Skip to content

Healthspan v2 (3/3): rebuilt Healthspan tab - #14

Merged
ayiskakov merged 3 commits into
feat/healthspan-pipeline-v2from
feat/healthspan-tab-v2
Sep 23, 2026
Merged

ayiskakov merged 3 commits into
feat/healthspan-pipeline-v2from
feat/healthspan-tab-v2

Conversation

@ayiskakov

Copy link
Copy Markdown
Owner

PR 3 of 3 for Healthspan v2. Stacked on #13 (which is stacked on #12).

What changes

HealthspanView is rebuilt on the v2 rows. It works on macOS and iOS (the view is shared).

  1. Hero. The six-month Body Age (one decimal) against calendar age, with the ± band and "N yrs younger/older". Until Body Age unlocks, it shows an x of 21 scored days in the last 31 countdown instead, counted on the same gate the pipeline applies.
  2. Pace dial. −1…3× in four bands: reversing, slowing, steady and accelerating. It also shows the ± margin and the projected Body Age in six months. The dial says "Holding steady" whenever the margin covers 1×.
  3. Biggest lever. "Reaching your target for X would take about N years off your Body Age." N is that driver's persisted share, which is exactly what reaching the target removes.
  4. Drivers. Each row shows the value, the target (7–9 h for sleep), a signed years chip and a 30-day vs 6-month arrow. Tapping a row opens the driver's hazard-ratio curve, drawn from the engine functions with the user's value marked, plus its source.
  5. Trends. Six-month charts of Body Age and pace (StrandDesign TrendChart).
  6. Context. HRV against the age norm, labelled as not scored.
  7. Method sheet. The referent, 10 · ln(HR), the overlap rules, the windows, the limits, and the references.

Every readout comes from one HealthspanSnapshot of the persisted rows for the newest day, loaded once per refresh. The chips, lever, dial and chart's last point therefore cannot disagree with the headline. The Health hub's Vitality card overline changes from "Weekly" to "6 months", and the zone drivers are renamed "Zones 1–3 cardio" and "Zones 4–5 cardio".

The Resilience section (sibling plan) is not part of this PR.

Verification

  • HealthspanReadoutTests covers:
    • pace bands, including the margin-covers-1× steady case
    • the arrow's per-driver "better" direction and its dead-band
    • the lever floor
    • signed years formatting and the 7–9 h target
  • Design tokens only: StrandPalette, StrandFont, NoopMetrics and StrandDesign components.
  • All new copy is in Localizable.xcstrings in all nine shipped locales (de, es, fr, pt-PT, it, pl, ru, zh-Hans, zh-Hant). Format specifiers were checked against each key. Citations and references use Text(verbatim:), since they are bibliographic.
  • i18n_audit --ci main and doc_comment_lint are clean.
  • xcodebuild succeeds for Strand (macOS) and NOOPiOS. NOOPiOS was built without the embedded watch app, because the watchOS runtime is not installed locally.
  • Not yet checked visually: I have not launched the app to look at the screen.

- Hero: six-month Body Age vs calendar age with its ± band, and a
  21-of-31-scored-days countdown until it unlocks.
- Pace dial: −1…3× in four bands (reversing / slowing / steady /
  accelerating), the margin, and the projected Body Age in six months;
  "holding steady" whenever the margin covers 1×.
- Biggest lever: the years reaching that driver's target would take off.
- Drivers: value, target, a signed years chip and a 30-day-vs-6-month arrow;
  tapping opens the driver's hazard-ratio curve and its source.
- Six-month Body Age and pace trend charts, HRV as unscored context, and a
  method-and-references sheet.
- Every readout comes from one snapshot of the persisted rows for the newest
  day, so the chips, lever, dial and chart cannot disagree with the headline.
@ayiskakov
ayiskakov merged commit 4e59bb3 into feat/healthspan-pipeline-v2 Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant