# Phase 2 Probe Testing Install dependencies: ```sh uv sync ``` Optional environment setup: ```sh 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: ```text /workout-service/fbt-adaptive/ ``` 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`: ```text 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 ```sh 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 ```sh 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: ```sh 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: ```sh 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: ```sh uv run python scripts/probe_garmin.py workout --dump-json ``` This writes `debug/workout_.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 ```sh 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: ```sh 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/` returned step arrays. `/workout-service/workout/uuid/` returned an empty list, and other candidate detail endpoints returned errors. ## Offline Dump Analysis Analyze a saved dump without logging in to Garmin: ```sh 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: ```text No dated workout-like object was found. ``` ## Dummy Upload And Schedule Test Dry run: ```sh 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: ```sh 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: ```sh 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: ```sh uv run python scripts/clone_today_workout.py --date today --schedule ``` The clone is named: ```text GCClone YYYY-MM-DD ``` 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: ```sh uv run python scripts/probe_garmin.py generated --prefix GCClone ``` List generated scheduled calendar entries for the month containing `--date`: ```sh 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: ```sh uv run python scripts/probe_garmin.py generated-calendar --date today --prefix GCClone --unschedule-id --confirm ``` Delete a generated workout template only if you are sure the ID is from the generated-prefix list: ```sh uv run python scripts/probe_garmin.py generated --prefix GCClone --delete-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.