When training feedback survives the handoff
INCREMNT is an iOS strength-training app that helps athletes follow a plan and decide what to lift next. This week’s central work made training feedback durable across two important handoffs: a completed week can become a saved report that Coach can reopen, and effort recorded on Apple Watch is persisted before the phone clears the workout state.
- Added saved weekly reports with sessions, completed sets, volume, personal records, stalled exercises, and a takeaway for a finished Monday–Sunday window.
- Let athletes reopen older reports from Body, carry the selected report into Coach, and ask follow-up questions without replacing the saved facts with rolling context.
- Added an Apple Watch effort rating before workout completion, including a skip path, and persisted the score before clearing the pending Watch finish request.
- Added deterministic Maestro and focused unit coverage for historical report navigation, sparse weeks, rated and skipped Watch finishes, and phone recovery.
Product: feedback should still be there when you come back
INCREMNT is a training app for the decision after the workout as much as the workout itself. You log the work, see what changed, and use that evidence to decide what deserves attention next. That chain breaks if the useful part disappears when a screen closes or a week rolls over.
The new weekly review starts with a simple promise: a finished week gets a durable snapshot. The service waits until the athlete’s local Sunday is complete, then stores facts for that Monday–Sunday window: session count, completed sets, planned sets in logged workouts, total volume, estimated bests, stalled exercises, and a takeaway. The report is account- and week-owned, so it can be found again rather than regenerated from whatever the latest activity happens to be.
That changes the Body experience from “there is a current card” to “there is a history of decisions.” The dashboard can show a saved review, the detail sheet can switch between periods, and a sparse week can say that it contains zero workouts without pretending there is a meaningful highlight. The language is intentionally plain because the report is meant to help an athlete choose what to do next, not perform analysis at them.
The handoff to Coach is the important part. From a saved report, Ask Coach about this week carries the selected period and its stored evidence into the conversation. Returning through Coach history can reopen the same report, and going back to Body can select an older one without losing the reference. Coach can explain the snapshot, but it cannot silently replace the saved facts with a fresh, broader activity query.
That boundary is useful for an athlete who wants continuity. A review read on Tuesday should still mean the same thing on Friday. It also gives the product a more honest answer to “why did you tell me this?” The answer can point to the week that produced the report, the numbers behind it, and the exercises that need attention.
The other side of the same problem appeared at the end of a workout. Apple Watch now asks for an effort score from 1 to 10 before finishing, with a clear Skip Rating option. A selected score is shown in the phone summary as effort, while skipping leaves that field absent. The choice is small, but it gives the athlete a way to record how the session felt while that memory is still fresh.
Building INCREMNT: make the boundary explicit, then test the crossing
The weekly report is not an AI paragraph stored in a database. The scheduled job builds a factual report from the account snapshot, freezes the source window and digest, and uses a write-if-missing path so later Coach prose cannot overwrite the facts. The date logic is local to the athlete’s timezone, including the awkward daylight-saving boundary where a seven-day week is not a fixed number of elapsed hours. A test covers that Monday–Sunday calculation and another proves that Sunday’s report waits until the local day has ended.
The client then has to carry more than a string. The report model has a versioned window, metrics, evidence and takeaway. Weekly review history keeps the report and its conversation reference together. The selected report is resolved from account-owned storage, then passed through both Coach generation paths; a generic “review my week” prompt is not enough because one path constructs its own messages. The saved report is the authority, not structured data supplied by the client.
The UI regression sequence is deliberately long: Body report, Coach, History, Body, an older report, then Coach again. It catches a subtle event-ordering bug where an already-mounted Coach view could clear a pending navigation event before the tab switch consumed it. The Maestro flow proves the route and display with seeded data; the service tests prove account-owned resolution and the completed-week cutoff. Neither is a claim about production model quality or a deployed cron run.
The Watch finish had a different race but the same shape. The Watch sends the effort score with the finish request. The phone matches that request to the current workout start time, merges the score into the first durable session summary, and only then clears the draft and pending request. If the request belongs to another workout, the score is ignored. Existing summary metadata—date, ID, calories, and heart-rate fields—stays intact.
That ordering matters because clearing the draft also removes the evidence needed to recover the score. The earlier implementation could show a completion state before the phone had safely persisted the value. The fix makes persistence the first write and presentation a consequence of it. Rated and skipped fixtures cover both branches, including a relaunch that finds one saved session. Focused tests also check invalid scores and a mismatched workout start.
There is a broader engineering rule underneath both features: state that crosses a boundary needs an owner, a stable identity, and a write order. The weekly report owns a specific account and week. The Watch effort owns a specific workout lifecycle. Once those identities are explicit, retries and handoffs become testable instead of hopeful.
Also moved forward
- Watch set cascading now waits for phone confirmation and stays visible during rest, while lifecycle reconciliation guards against stale startup clears. The changes include focused behaviour tests and a Sentry path for diagnosing recoverable mirror failures.
- Workout titles now show the last completed date, giving the next-session decision a little more history without opening a separate screen.
- Coach can be opened for guests, and Watch connection adoption now has a bounded analytics event. These are implementation steps, not claims about a released growth result.
What’s next
I’m keeping the next step narrow: exercise the saved-review and Watch-finish paths against the built app and the remaining release checks, then watch for the edge cases that only appear when a phone, Watch, and historical report disagree about what is current. The goal is simple—make the next training decision use the same evidence the last one produced.