Files
openrun/NEXT_SESSION.md
noisedestroyers 1b6ad40897 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>
2026-06-12 08:35:01 -04:00

5.2 KiB
Raw Blame History

Session handoff — 2026-06-12

Working plan agreed with the user: step through P0→P4 below, in order. Read this file instead of re-exploring the repo; README.md + ROADMAP.md cover architecture and conventions. Delete this file when the list is done.

State (verified 2026-06-12, P0 session)

  • All 111 tests pass (uv run pytest).
  • P0 DONE (commit 6df25bcd, NOT yet pushed — push denied to agent, run git push origin main): .gitignore fixed and Takeout dump (23,673 files, personal health data) untracked; note it is still in remote history from earlier pushes — rewrite history if that ever matters. CI added at .gitea/workflows/test.yml (remote g.o00.io is Gitea — Actions must be enabled repo-side with a registered runner). gitlab remote URL typo (ttps://) fixed. scripts/backup_db.sh snapshots the DB, keeps 14.
  • DB: garmin/data/garmin.db is canonical — 378 activities (→ 2026-05-10), 349 FITs linked, wellness through 2026-05-17.
  • The stray ../data/garmin.db (vault root) was a Takeout-ZIP ingest run from the wrong cwd on 2026-06-08 (7 extra activities May 17Jun 2, epoch-ms timestamps, no FITs). Copied to data/backups/vault-root-takeout-ingest-2026-06-08.db; the original at ../data/ is redundant once live sync runs — user should delete it.
  • SYNC DONE (2026-06-12) via new garminconnect backend. garth's SSO login is Cloudflare-429-blocked AND garth is deprecated (matin/garth#222), so src/openrun/ingest/garminconnect_backend.py now authenticates with python-garminconnect 0.3.5 DI tokens (.secrets/garmin_tokens.json) and shims garth's client surface; openrun-sync --backend=auto prefers it. This is P3-lite, pulled forward. Login (once/year-ish): uv run python -m openrun.ingest.garminconnect_backend. Gotchas learned: usersummary endpoint needs UUID displayName, not userName (403 otherwise); a parseable-but-dead tokenstore blocks the password fallback in gc.login (main() parks it as .bak first).
  • DB after sync: 385 activities (→ 2026-06-02), all ISO timestamps on new rows, 356 FITs linked, 364 TIZ rows, wellness through 2026-06-12. The 18 legacy epoch-ms rows remain (P2).
  • Web Sync page ported to the gc backend (same session): login + MFA 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 openrun.toml (zones/races — openrun-init helps), and deploy story (streamlit run is single-process; secrets must stay server-side).
  • race_plan table is EMPTY and manual_activities empty, but openrun.toml has races: 30K 2026-06-13, 50K 2026-07-25, 50 MILE 2026-09-12.
  • Known bugs: 18 activities have epoch-ms floats in start_time_local (should be ISO strings) — normalize on ingest + one-time migration; datetime.utcnow() deprecation warnings in src/openrun/ingest/garmin_api.py.

Plan

  • P0 — protect the work: .gitignore, private remote, CI running pytest, pick canonical DB + backup story. (commit done)
  • P1 — use it for the ultra build: live sync (openrun-auth + 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: 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 + RunRacePredictions ingest (ROADMAP 1.2), route map (3.2). Defer DBSCAN, multi-athlete, distribution until after September.

Gaps identified (not yet scheduled)

  • Subjective data: RPE/soreness/injury notes (user hand-writes these in ../RunningLogs.md; March right-leg injury) — tie into DB, plot vs ACWR/TSB.
  • Ultra metrics: weekly vert, time-on-feet, back-to-back long-run detection, grade-adjusted pace (elevation_gain already in schema, unused).
  • Sync automation (launchd/cron weekly openrun-sync).