Rollup rows were grouped by (type, day) only, so two sources reporting
the same standard vital for one day (e.g. WHOOP + Apple Watch resting
heart rate) were AVG-blended into a single row instead of resolving to
the source-priority ladder's canonical reading.
Re-grain the rollup table to (type, day, source): the writer now groups
by source and delete-then-inserts each affected partition (so a source
that stops reporting a bucket cannot strand a stale row), and the read
path will collapse overlapping sources to the canonical reading in a
follow-up commit. Cumulative metrics (steps, energy) keep summing per
source. Migration 0115 purges the legacy source-blind aggregates; the
boot backfill + read-time self-heal re-mint per-source rows.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>