From the build log of an AI coach that learns what you can lift and tells you exactly what to do next.
four things got done: The app now remembers when a set hurt (groundwork). Tap any of these to read the whole thing.
During a workout you can tap "something hurt" or "my form broke down" after a set. Until now the coach only used that in the moment, it was forgotten the instant the workout ended. So it could never notice "you've flagged your shoulder on bench three weeks running." Genuinely useful information was being thrown away.
Gave those flags a permanent home in the database and started saving them against every set you log. This is deliberately just the plumbing: the flags are now kept safely, but the coach doesn't yet read your history of them or change its advice because of it. That next step is held back on purpose, deciding how the coach should react to a run of pain flags is a careful, safety-related call I want to make properly rather than by default. I also taught the server to check the flags so only real ones ("pain", "form broke down") can be stored.
Ran the server test suite, 38 checks pass, including five new ones for good flags, no flags, and bad flags being turned away, and built the whole app clean (no errors). It's backwards-safe: every set saved before today simply counts as "no flags".
One of our automated checks would sometimes fail for no real reason, a coin-flip, not a genuine bug. It was the test that makes sure the app handles "you're offline" gracefully. Behind the scenes, when the internet is down the app quietly retries a few times (waiting 1, then 2, then 4 seconds) before giving up, all inside an 8-second budget. The test insisted on one exact outcome ("gave up with an error message"), but a tiny bit of random timing meant the app would sometimes hit the 8-second budget first and report "timed out" instead. Both are perfectly fine ways to say "you're offline", but the over-strict test treated the second one as a failure, so it flaked, especially on the busy build server. That red check kept showing up on unrelated changes.
Loosened the test to check what actually matters: when the network fails, the app never pretends it worked, and it always shows a real message, accepting either "error" or "timed out" as a valid offline outcome. I changed nothing about how the app behaves; only the test got more honest. (I left a note that the deeper question, whether "no internet" should be retried at all, is a separate decision for another day.)
Built and ran the test three times in a row, passed every time, zero failures.
Two unrelated loose ends from a backlog pass. First, behind the scenes the coach keeps a little list of the dates you trained each movement, and that list quietly grew forever, one date added every workout, slowly bloating your saved profile. Second, when you add a set by hand to a finished workout, the app always filed it as a "backoff" set with no way to say otherwise, even though that label changes how the coach reads the set.
Most of the app already wears the new "Brutalist" look, pure black, bold condensed type, one lime highlight for the main action. But a handful of smaller screens never got the makeover and still showed the old dark-navy-and-blue style, so they stuck out. None of them are screens you see every day, which is why they were left for last: the "no program yet" and "all done" messages on the Workout tab, the workout error screen, the little amber "workout paused" banner, the equipment list you reach from Settings, and the "this build needs setup" notice.
Restyled all of them to the shared look and pulled out the leftover blue. The Workout tab's empty and finished screens, the error screen, and the paused banner now use the same black background, bold type, and lime/amber accents as everything else. The equipment screen (where you add or tweak your gym gear) got the same treatment. The tab bar along the bottom also picked up a black, no-more-blue style. Nothing about how any of these screens work changed, only how they look.
Built the whole app cleanly for each change and once more all together at the end, every build passed. Two notes for me: a couple of system pop-ups (the "session mismatch" and confirm dialogs) can't be repainted, iOS draws those itself, so they're left as-is; and the bottom tab bar's exact selected colour is a judgement call I made (white on black) that's worth an eyeball on a real phone.