- 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>
86 lines
5.2 KiB
Markdown
86 lines
5.2 KiB
Markdown
# 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 17–Jun 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`).
|