Skip to content

feat(trends): CTL/ATL/TSB training-load card (iOS/macOS + Android) - #1425

Merged
ryanbr merged 1 commit into
mainfrom
feat-training-load-chart
Aug 18, 2026
Merged

ryanbr merged 1 commit into
mainfrom
feat-training-load-chart

Conversation

@ryanbr

@ryanbr ryanbr commented Aug 18, 2026

Copy link
Copy Markdown
Owner

What

The first UI surface for the training-load model (TrainingLoadEngine, #1423) — a card on the Trends screen, all three platforms. Overlays CTL (chronic, 42-day fitness) and ATL (acute, 7-day fatigue) on one shared y-scale, so the vertical gap between the lines reads as the TSB / form (CTL − ATL). Form is the headline number; a footer shows CTL / ATL / Form / Days.

  • Descriptive only — CTL/ATL/TSB never feed the Charge/Readiness score. Load is daily Effort/strain (DailyMetric.strain), not TRIMP.
  • Full history, not the range window — chronic load is a 42-day horizon. Honest empty state names how many consecutive Effort days are still needed; a building subtitle shows "N of 42" while the baseline calibrates.
  • Calls TrainingLoadEngine.evaluate directly (not the paired evaluateWithTrainingLoad), so it never runs the unused Readiness synthesis.
  • Apple: isolated card file (Strand/Screens/TrainingLoadCard.swift) to keep its type-check cost out of TrendsView; reuses ChartCard/ChartFooter. Android: shared-scale two-line Canvas in TrainingLoadCard.kt. Design tokens only.

Localization

New copy localized de/es/fr/pt-PT on both platforms (Localizable.xcstrings + strings.xml × locales). CTL/ATL/TSB added to the i18n audit's UNIVERSAL acronym set (identical in every language, like HRV/SpO2). Tools/i18n_audit.py → 0 translation gaps, no new hardcoded literals.

Validation

@ryanbr
ryanbr force-pushed the feat-training-load-chart branch from 1cd61b0 to fdda465 Compare August 18, 2026 01:43
Surfaces the long-horizon training-load model (TrainingLoadEngine) as a card on
the Trends screen, all three platforms. Overlays chronic load (CTL, 42-day
fitness) and acute load (ATL, 7-day fatigue) on one shared y-scale so the gap
between the lines reads as the TSB / form (CTL - ATL); form is the headline
number + a footer stat, with CTL/ATL/Days/Form stats below.

- Descriptive only: CTL/ATL/TSB never feed the Charge/Readiness score. Load is
  daily Effort/strain (DailyMetric.strain), not TRIMP.
- Models the FULL history, not the range window (chronic load is a 42-day
  horizon). Honest empty state names how many consecutive Effort days are still
  needed; a "building" subtitle shows N of 42 while the baseline calibrates.
- Calls TrainingLoadEngine.evaluate directly, not the paired
  evaluateWithTrainingLoad, so it never runs the unused Readiness synthesis.
- Apple: isolated card file to keep its type-check cost out of TrendsView.
  Android: shared-scale two-line Canvas.
- Localized de/es/fr/pt-PT on both platforms (xcstrings + strings.xml);
  CTL/ATL/TSB added to the i18n audit UNIVERSAL acronym set (like HRV).
@ryanbr
ryanbr force-pushed the feat-training-load-chart branch from fdda465 to f2c7290 Compare August 18, 2026 01:48
@ryanbr
ryanbr merged commit b9f774f into main Aug 18, 2026
8 checks passed
@ryanbr
ryanbr deleted the feat-training-load-chart branch August 18, 2026 02:01
ryanbr added a commit that referenced this pull request Aug 18, 2026
Build numbers only. MARKETING_VERSION / versionName stay 10.1.1 — the staging
line is one above the latest release (v10.1.0) and holds there until 10.1.1
actually ships.

versionCode 341 -> 342 and CURRENT_PROJECT_VERSION 223 -> 224, both +1 past the
previous staging build so a sideloaded update installs in place rather than
being refused as a downgrade.

Picks up since the last testing build (f2271cd): backup build provenance
(#1422), the CTL/ATL/TSB training-load engine (#1423) and its Trends card
(#1425), sleep-vs-wake HR contrast (#1424), the v20 optical decoder + CRC gate
(#895), the Sleep UI split (#1426), the WHOOP4 clock-correlation fix (#1427),
the settings waist-row layout + copy fix (#1428), hourly Apple step import
(#1429), Low refresh (#1430), and Power saving moving into More with a 35%
ceiling (#1431).
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