Files
2026-06-16 15:14:37 +02:00

8.4 KiB

Phase 2 Probe Testing

Install dependencies:

uv sync

Optional environment setup:

cp .env.example .env

Fill GARMIN_EMAIL and GARMIN_PASSWORD in .env, or leave them blank and the scripts will prompt. Tokens are stored in .garmin-tokens by default.

Garmin Coach cycling detail currently comes from this Connect API endpoint:

/workout-service/fbt-adaptive/<workoutUuid>

The browser network analyzer shows the same route under /gc-api/..., but the CLI should use the Connect API route with normal python-garminconnect tokens. If you are debugging the browser-only /gc-api route specifically, you can copy the Cookie request header into .env:

GARMIN_GC_API_COOKIE=JWT_WEB=...; ...

Treat that cookie like a password. Do not commit .env, screenshots containing the cookie, or debug logs with request headers.

Local Checkout Validation

uv run python scripts/local_check.py

Expected:

  • PASS: ruff check .
  • PASS: ty check
  • PASS: pytest
  • PASS: ... scripts/probe_garmin.py dummy --date tomorrow --dry-run
  • debug/local_checks.json is written.

This command does not log in to Garmin or upload anything.

Login

uv run python scripts/probe_garmin.py login

Expected:

  • If cached tokens work, it prints account/device summary.
  • If credentials are needed, it prompts for email/password.
  • If MFA is required, it prompts for the MFA code.
  • It must not print the Garmin password or MFA code.

Discovery

Preferred one-pass read-only report:

uv run python scripts/probe_garmin.py report --dump-json

This writes debug/probe_report.json. It logs in once and collects account summary, training plans, workout type metadata, normal workouts, today/tomorrow calendar entries, and today/tomorrow Coach/adaptive match summaries. It continues through partial API failures and records errors in the report.

Individual discovery commands:

uv run python scripts/probe_garmin.py plans
uv run python scripts/probe_garmin.py types
uv run python scripts/probe_garmin.py calendar --date today --dump-json
uv run python scripts/probe_garmin.py calendar --date tomorrow --dump-json
uv run python scripts/probe_garmin.py workouts --limit 25 --dump-json
uv run python scripts/probe_garmin.py generated --prefix GCClone
uv run python scripts/probe_garmin.py generated-calendar --date today --prefix GCClone

Check:

  • Training plans are listed.
  • Any plan marked FBT_ADAPTIVE, Coach, or adaptive is shown as a candidate.
  • Workout type metadata is written to debug/workout_types.json.
  • Calendar JSON dumps are written under debug/.
  • Normal workouts are visible.
  • Generated probe/clone workout templates are listed separately by prefix, if any exist.
  • Generated scheduled calendar entries are listed separately by prefix for the inspected month, if any exist.

If you have a normal cycling workout that already syncs to the Edge 1030, inspect it:

uv run python scripts/probe_garmin.py workout <workout-id> --dump-json

This writes debug/workout_<workout-id>.json, which is useful as a known-good schema reference.

debug/ is gitignored because dumps can contain private Garmin account data even after redaction.

Coach Workout Inspection

uv run python scripts/probe_garmin.py coach --date today --dump-json
uv run python scripts/probe_garmin.py coach --date tomorrow --dump-json

Useful output:

  • Workout-like objects with workoutSegments/workoutSteps: N
  • A readable step summary with warmup/interval/recovery/cooldown/repeat steps.
  • debug/coach_workout_YYYY-MM-DD.json when a matched workout is found.
  • debug/coach_workout_today.json when today's matched workout is found.
  • The probe should fetch the full fbt-adaptive detail from workoutUuid.

Blocking output:

  • No parseable workoutSegments/workoutSteps found for this date.

If blocked, report the command output and keep the redacted JSON in debug/ for inspection.

If coach finds dated Coach task summaries but no step arrays, run the read-only endpoint sweep:

uv run python scripts/probe_garmin.py coach-endpoints --date today --dump-json

Expected:

  • It prints the plan ID, workout name, workoutUuid, and calendar item ID.
  • It tries candidate private endpoints and continues through 404/errors.
  • It writes debug/coach_endpoint_probe_YYYY-MM-DD.json.

Useful output:

  • At least one candidate endpoint returned workout-like step data.

Blocking output:

  • No candidate endpoint returned workoutSegments/workoutSteps.

For the June 16, 2026 account probe, /workout-service/fbt-adaptive/<workoutUuid> returned step arrays. /workout-service/workout/uuid/<workoutUuid> returned an empty list, and other candidate detail endpoints returned errors.

Offline Dump Analysis

Analyze a saved dump without logging in to Garmin:

uv run python scripts/analyze_dump.py debug/coach_workout_today.json --date today --clone-dry-run --dump-json

Expected, if the dump contains a dated workout:

  • Date-containing object count is shown.
  • Workout-like object count is shown.
  • A matched workout summary is printed.
  • Local clone payload passed validation. is printed if conversion is structurally safe.

If the dump does not contain a dated workout-like object, the command exits non-zero and prints:

No dated workout-like object was found.

Dummy Upload And Schedule Test

Dry run:

uv run python scripts/probe_garmin.py dummy --date tomorrow --dry-run

Expected:

  • Dummy workout payload passed local validation.
  • The generated JSON is printed.
  • Nothing is uploaded.

Upload and schedule:

uv run python scripts/probe_garmin.py dummy --date tomorrow --schedule

After upload/schedule succeeds:

  1. Sync the Edge 1030 with Garmin Connect / Garmin Express.
  2. Check Training > Workouts.
  3. Check Training > Training Plan > calendar icon > tomorrow's date.
  4. Start normal route/course navigation, then start the dummy workout.
  5. Confirm whether workout prompts and navigation can run together.

Report:

  • Did the dummy workout appear in Garmin Connect?
  • Did it appear on the Edge 1030?
  • Did it appear in the calendar/date view?
  • Could it start while navigation was active?

Clone Test

Dry run:

uv run python scripts/clone_today_workout.py --date today --dry-run --dump-json

Expected:

  • Converted clone payload passed local validation.
  • The converted JSON is printed.
  • Nothing is uploaded.

Upload and schedule only if the dry run shows plausible steps:

uv run python scripts/clone_today_workout.py --date today --schedule

The clone is named:

GCClone YYYY-MM-DD <original workout name>

Repeated runs skip an existing clone for the same date unless --force is passed.

Report:

  • Did the cloned workout appear in Garmin Connect?
  • Did it appear on the Edge 1030 under workouts/calendar?
  • Can it be started on the Edge?
  • Can it run together with normal Edge navigation?
  • After completion, did Garmin Coach mark the original Coach workout complete?

Generated Workout Cleanup

List generated workout templates:

uv run python scripts/probe_garmin.py generated --prefix GCClone

List generated scheduled calendar entries for the month containing --date:

uv run python scripts/probe_garmin.py generated-calendar --date today --prefix GCClone

Unschedule a generated calendar entry only if you are sure the scheduled ID is from the generated-prefix calendar list:

uv run python scripts/probe_garmin.py generated-calendar --date today --prefix GCClone --unschedule-id <scheduled-id> --confirm

Delete a generated workout template only if you are sure the ID is from the generated-prefix list:

uv run python scripts/probe_garmin.py generated --prefix GCClone --delete-id <workout-id> --confirm

Expected:

  • Without --delete-id or --unschedule-id, these commands are read-only.
  • With --delete-id or --unschedule-id, the command refuses to run unless --confirm is also passed.
  • The commands refuse IDs that are not in the generated-prefix list.

Unknown:

  • Whether deleting the workout template also removes any scheduled calendar entry. Prefer unscheduling first, then check Garmin Connect calendar afterward and report what happened.

Current Acceptance Gate

Phase 3 should not start until the dummy scheduled workout works on the Edge 1030 and the Coach inspection either exposes parseable steps or we explicitly choose a fallback architecture.