mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 15:02:04 +00:00
The Coach snapshot read raw prisma.workout rows while GET /api/workouts runs pickCanonicalWorkoutRows, so a dual-source user (e.g. Apple Watch + Withings recording the same run) got the session double-counted in the Coach prompt and the get_workouts MCP tool. Route the snapshot's workout block through the same picker, keyed off the user's own sourcePriorityJson. HRV resolves SDNN only on every MCP/coach path, so an Oura/Polar/WHOOP-only account (RMSSD, not SDNN) saw a false empty HRV block even though the app's HRV sub-page already unions both flavours. The coach snapshot now queries both types; the MCP rich reads (compare_metric, get_metric_baseline, detect_changepoints) fall back to RMSSD when the user has zero SDNN rows, mirroring the app's primary-then-fallback rule. Also aligns surfaces.mcp as a real gate: a metric-status id the signal registry marks mcp:false (cardio recovery, wrist temperature, sleep score, ...) no longer resolves through the rich-read registry path, closing a contract gap between the two registries (no data was actually exposed before this, but a future mcp:false signal without this guard would have leaked silently). The remaining day-edge tz mismatch between the rollup-backed rich reads and the user-tz coach timelines is left documented rather than patched: the underlying rollup buckets are themselves written on UTC calendar boundaries, so shifting only the read-side window would trade one one-sided inconsistency for another without fixing the root cause.