← All changes
Runner & rest timer
- The rest timer is now anchored to the wall clock. Backgrounding the app mid-rest used to freeze the in-app countdown (the lock-screen Live Activity was always correct). The countdown now recomputes from an absolute end date on every tick and resyncs the moment the app returns to the foreground. A gong that expired while you were away only plays if it just happened — a late gong is worse than none.
- RPE, optionally. After logging a set, the rest card offers a quiet
6–10 chip row for the set you just did. Tap to rate, tap again to
clear, ignore it entirely — nothing blocks. Ratings show as
@8in the summary and ride along in the Strava description. - Add an exercise mid-session. A ghost row in the runner appends any exercise from your library to the running session — seeded with last time’s weights — without touching the template on disk.
- Skip an exercise, explicitly. A muted “Skip exercise” chip marks the difference between “chose not to today” and “never got there”. The summary shows SKIPPED instead of 0/3; Strava omits it.
Editor & library
- Reorder everything. Drag exercises within a block; move blocks and sets up/down. No more JSON round-trips to change an order.
- New workout from scratch. The + menu now creates a blank template straight into the editor — v1 on save, written to iCloud like any import.
- Quick-start. “Start session” on a workout card’s context menu and “Start again” on any history row skip the detail screen entirely.
History & data
- Export your history. Settings → Data exports every finished session as JSON (full per-set log) or CSV (one row per set: reps, weight in kg, RPE, pain, skipped). The same ownership the workout templates always had, now for the training log.
- Sets per muscle group. A second card in History stacks weekly completed sets per muscle group over 4/8/12 weeks. No targets, no deltas — just the bars.
- Estimated 1RM. The exercise progression screen adds a quiet dashed Epley trend (mass-weighted rep sets, 1–12 reps only). Informational only; no PR celebration anywhere.
Watch (protocol v6)
- Personalized heart-rate zones. Max heart rate is now a setting (Settings → Watch) and rides to the watch in the start payload. Zone colors were previously hardcoded against 185.
- An honest rest ring. The watch now receives the planned rest total and fills its ring proportionally instead of guessing.
- Both fields are optional on the wire — older watch builds simply fall back to the previous behavior.
Under the hood
- 49 new unit tests (231 → 280): wall-clock rest recovery, back-compat
decodes for
rpeandskipped, watch protocol v6 round-trips against raw v5 fixtures, watch-message routing without a live WCSession, and Strava token parsing without network or Keychain. - TestFlight uploads are self-healing again: the lane now maintains a classic distribution certificate and explicit provisioning profiles via the App Store Connect API key, with no dependency on Xcode’s (silently expiring) account session.