web: surface personal training findings — cadence, fueling

- NatesNotes.md restructured into the personal-findings doc (cadence 170
  target / 161 natural, 80 g carb/h, 3/2 breathing, gait cues, injury log)
- load_activities exposes avg_cadence_spm (summaryDTO.averageRunCadence,
  falling back to Takeout's avgDoubleCadence — full coverage, 342/342 runs)
- load_fit_records: FIT running cadence is single-leg rev/min; now returns
  true steps/min ((cadence + fractional_cadence) * 2)
- Dashboard: cadence trend chart (per-run avg, 28-day mean, 170/161 lines)
  + Cad column in recent activities
- Activity Detail: per-second cadence trace with %time >= 170
- Race Plan: fueling section (carb g/h x est. finish time per race)
- one-time migration: 18 epoch-ms-as-text timestamps -> ISO (P2 item;
  backup at data/backups/garmin-20260612-082025.db)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 08:35:01 -04:00
parent 87f73ad36b
commit 1b6ad40897
6 changed files with 215 additions and 45 deletions

View File

@@ -38,6 +38,14 @@ architecture and conventions. Delete this file when the list is done.
round-trip + sync button all run on garminconnect; verified headlessly via
streamlit AppTest (login restore, button click, full sync, no exceptions).
`openrun.ingest.auth` (garth) remains only for `--backend=garth`.
- **Personal findings surfaced in UI (2026-06-12)**: NatesNotes.md is the
findings doc (cadence 170/161, 80 g carb/h, 3/2 breathing, gait cues).
Dashboard gained a cadence trend chart + table column; Activity Detail a
per-second cadence trace (FIT cadence is single-leg — load_fit_records now
doubles it); Race Plan a fueling calculator. Targets 170/161 are constants
in the pages — move to openrun.toml when config grows a slot. Still unsurfaced:
walking/time-on-feet (Dashboard filters type='running'; off-watch walking
only exists in daily_steps).
- **New goal (user, 2026-06-12): shareable web UI** — let others run the
openrun web app against their own Garmin account. Known gaps: per-user
token store + DB (everything is cwd-relative single-user today), per-user
@@ -57,8 +65,11 @@ architecture and conventions. Delete this file when the list is done.
`openrun-sync`, fall back to `../garmin-pgc/` python-garminconnect backend if
garth hits Cloudflare 429), then populate `race_plan` through 2026-09-12
using `banister_forecast` + `calibrate_tl_per_km`; log off-watch work.
- **P2 — data quality**: fix the 18 mixed-format timestamps, utcnow warnings,
add `schema_version` + tiny migration runner before any public release.
- **P2 — data quality**: the 18 epoch-ms timestamps were migrated to ISO via
one-time UPDATE on 2026-06-12 (they were stored as TEXT like
"1658951176000.0"; backup at data/backups/garmin-20260612-082025.db).
Still to do: normalize on ingest so Takeout re-ingest can't reintroduce
them, utcnow warnings, `schema_version` + tiny migration runner.
- **P3 — merge sync fork**: fold `../garmin-pgc/` into openrun as
`openrun-sync --backend=garminconnect` instead of a sibling project.
- **P4 — roadmap items reordered for the ultra**: TrainingReadinessDTO +