Coach answers you can check
INCREMNT is a strength-training app that turns logged workouts into a plan you can follow and understand. This week’s work tightened the line between what Coach can prove, what it recommends, and what it is allowed to change.
- The Coach build verifies final prose against the evidence it actually selected, not every read it happened to perform.
- Explicit requests such as “3 sets of 8 at 60 kg” survive as typed plan changes through review and apply.
- A bounded production gate covers answer integrity, missing-data paths, and exact-number plan changes before release.
- The Coach opening offers more relevant follow-ups and a quiet, single-line thinking state.
Product: trust is a behaviour, not a tone
The useful question for a training coach isn’t whether an answer sounds confident. It’s whether the athlete can tell what the answer is based on, and whether a suggested change means exactly what they asked for.
That boundary is now explicit in Coach. A turn carries a selected evidence bundle into finalisation. If the answer cites a session, a date, a chart, or a next-workout prescription, the verifier checks that claim against the selected bundle. A true value from an unselected read can still be rejected. That is an important distinction: “we had the data somewhere” isn’t the same as “this answer was grounded in the data used to make it.”
The same rule applies to recommendations. If the current plan says Bench Press is 2×11 at 22.5 kg and 2×11 at 25 kg, Coach can’t quietly substitute a historical load just because it appeared in the conversation. Historical numbers can remain useful context, but they can’t masquerade as the next prescription. The answer either follows the current plan or carries a typed, reviewable change for the athlete to approve.
That makes the product feel more like a careful training partner and less like a chat box with a memory. It also gives the athlete a clear boundary around agency: advice can be explained, and changes can be inspected, but nothing is silently applied.
The iOS build understands an explicit set_prescription / exact edit with optional sets, reps, weight, and units. Invalid values are rejected rather than rounded into something plausible. The review screen shows the before-and-after for each occurrence of an exercise, keeps warm-ups intact, and checks that the program being applied is still the one that was reviewed. Qualitative changes still go through the progression engine; an exact request stays exact.
The opening experience follows the same principle in a lighter way. Starter questions are built from the athlete’s actual recent sessions, active plan, and weekly check-in context. Follow-ups are optional continuations based on what Coach established, not a second answer or a prompt to invent a problem. While Coach works, the transcript now shows one calm status line such as “Looking at your recent training” instead of exposing a busy work timeline. The underlying activity remains available for diagnostics; the conversation only shows what helps the athlete wait.
Building INCREMNT: carry the proof, then type the change
The hard part was not adding another assertion to a test. It was preserving meaning across a multi-step system: route the question, read several sources, let the model draft an answer, verify the draft, serialize a result, and finally let an iOS client review or apply it.
The fix was to make the selected evidence a first-class handoff. The agent foundation keeps the original read results available during the turn, but final verification receives only the bounded evidence IDs and facts selected for delivery. That prevents a later verifier from “finding” support in a read the final answer never used. The stored result keeps bounded display evidence and a delivery receipt rather than a dump of the whole conversation.
The verifier now checks several failure modes at that boundary:
- weighted claims must match selected rows;
- dates in the answer must belong to the selected evidence or the requested scope;
- next-session prescriptions must match the authoritative current plan;
- a conflicting number is only allowed when the same exercise has a typed plan change attached.
Those checks are deliberately blocking. A repair can retry a contradictory finish, but repeated contradictions end in a truthful limited or validation-failed delivery with no proposal attached. That is safer than emitting a polished answer whose evidence and action disagree.
On the client, explicit values use a small Codable contract instead of hiding numbers inside free text. RequestedPlanPrescription validates bounds and units. PlanChangesetResolver uses one transformation for both the review screen and the eventual apply path, so the athlete doesn’t approve one result and receive another. It handles partial requests too: “make it five sets” changes the count while preserving unspecified load and reps. Warm-ups stay separate from working sets. The change history and stale-review guard remain in place.
This is a useful design constraint for any system that turns language into state: preserve the request as structured data until the last responsible moment, and make the preview and mutation share the same pure transform. It costs more than parsing a sentence at the edge, but it removes an entire class of “looked right, applied differently” bugs.
We also added a production release gate instead of relying on a happy-path replay. The stored manifest contains ten sanitised golden cases covering the six answer-integrity contracts, missing data, canonical plan changes, and awkward exact-number requests. A malformed finish is probed explicitly and must end in a validation-failed fallback. Live mode runs three independently tagged samples through the rollout candidate, while the report is bounded to route, disposition, structured block types, repair counts, timing, and trace identifiers. It does not write prompts, answers, or conversations into the artifact.
The tests are the proof trail. Node fixtures reject a value that exists in the snapshot but not in selected evidence, reject a historical load that conflicts with the current next-session plan, accept the exact plan, and verify that exhausted validation stays distinct from missing data. iOS tests cover exact prescriptions, unit conversion, warm-up preservation, partial values, repeated exercise occurrences, stale reviews, and conflicting edits. The work is designed to be run through Xcode and the bounded gate before a release decision, not inferred from a green-looking screen.
There’s a product lesson in that plumbing. Trust is not a voice setting. It comes from making the evidence boundary visible in the architecture, then refusing to cross it when the data doesn’t support the sentence or the requested action.