CreatorTrack Fitness polish + wellness data-freshness fixes¶
URL: https://mkdocs.justinsforge.com/memory/handoffs/creatortrack-fitness-polish-2026-07-06/
Data freshness: root causes found and fixed (forge main, already live)¶
- Hevy frozen since 2026-07-03 (the 86h monitor alert).
forge_hevy_poll.pywas stubbed out in the Notion decommission, but it was the ONLY thing fetching workouts from the Hevy API;data/hevy/raw_hevy_workouts.jsonl,wellness.hevy_workouts, and the~/.forge-state/hevy_last_syncstamp all froze. Fix (commit3d23ab5on forge main):forge_wellness_pg_sync.pynow owns the fetch (refresh_hevy_raw()): full workout list + exercise-template catalog from api.hevyapp.com, atomic rewrite, refuses an empty API response, stampshevy_last_sync; age-gated to 6h so the 15-min timer hits the API ~4x/day. Verified end to end: 483 workouts + 485 templates fetched, PG synced, stamp current, chip shows green. Retiredforge_hevy_pollcron lines removed from crontab. Note: newest workout is genuinely 2026-06-29; Justin has not lifted since. - Eight Sleep gaps are device-side, not code.
facts_wellnesshas no rows for Jul 5 and only 6 for Jul 4, then resumes Jul 6; ha_poller runs every 15 min and is healthy. Pattern matches the pod dropping off wifi (known fix: 2.4GHz AP,reference_eight_sleep_pod_connectivity). App now shows gaps explicitly instead of silently showing an older night. - Garmin is healthy. Poller every 30 min 09:00-22:00 CT, facts current same-day. The app-side date math (America/Chicago in
lib/fitness/time.ts) is correct; "stale-looking" Garmin was the silent-fallback UI problem, now labeled. - Also fixed while here: the worktree DB was missing 4 migrations merged to main after the dev-base clone (
core.my_blocked_apps500); applied.
Fitness app UI (branch feat/fitness-polish, commit 12c6ad0)¶
- Today view = real day surface: shared
WeekStrip+DayHead(Habits/Meals pattern), any day in the 60-day window viewable; ring fill = Eight Sleep score, so pod-offline days show as empty rings right in the strip.DashboardDatanow shipsdailyper-day metric maps +today_iso. - Freshness chips in the app header on every view: Eight Sleep / Garmin / Hevy pipeline age, green/amber/red (warn at expected cadence, bad at 2x), tooltip with expectation.
- Explicit gap states: a day with no Eight Sleep/Garmin data says so (
.fit-daygap); today-with-no-data-yet falls back to the latest rich day WITH a visible "showing Jul 3" note (Eight Sleep card previously had NO stale indicator at all). - Polish: card hover elevation, readiness banner left-band + tint keyed to the call (push/maintain/pull back/rest), chip/gap styles. Chart primitives were already solid (tooltips, range nav, heatmap); left intact.
- Not done, deliberate: converting DetailModals to the shared SidePeek (URL-param plumbing on a node route; modals work; separate PR if wanted). 4 pre-existing eslint errors in
DetailModals.tsx/charts.tsx(react-hooks/refs, setState-in-effect) predate this branch.
Ops warning: dev-slot reaper reaped an ACTIVE agent slot¶
At 19:02 the reaper hit the >4-slot cap and tore down feat/fitness-polish (worktree + DB deleted) while this agent was mid-session; headless Playwright probes leave no persistent connection, so agent slots look idle. Recovered via re-bootstrap; this session now holds a keep-alive TCP socket to :3066 as a workaround. Consider teaching the reaper to treat slots with a recent git commit or recent file mtime as active.
Review¶
- Branch:
feat/fitness-polish(do not merge withoutrm -rf .next-devgotcha check; no route changes though) - Review: Today view day-nav (click days, prev week, Jul 5 = Eight Sleep gap state, Back to today), header chips on all 7 views, readiness banner tint. tsc clean.
- Forge main commits:
3d23ab5(hevy fetch),4d48d62(topic file). - Preview: http://100.97.43.104:3066
[Claude Code]