← back to the timeline
Jun 9 2026

two things got done: When you change your goal, your targets quietly catch up. Tap any of these to read the whole thing.

When you change your goal, your targets quietly catch up

A while back I gave each athlete two strength numbers per movement: a floor (the level we keep them at) and a stretch (the next milestone t…

Done
the problem

A while back I gave each athlete two strength numbers per movement: a floor (the level we keep them at) and a stretch (the next milestone to aim for). The plan always said: if the athlete later changes their goal, re-work the stretch number to match, but leave the floor alone. That part was never built. There was even an empty slot in the data for "when did they last change their goal," and nothing ever filled it in.

what I changed

Now, when an athlete edits their goal (the wording or the body parts they want to focus on), the app quietly re-works each stretch number and records the moment they changed their goal. Two rules keep it safe: the floor never moves, and the stretch can only go up, if the athlete had already nudged a target higher, we never pull it back down.

One honest thing I found while planning: the way we calculate a stretch only looks at how strong you are and which way your strength is trending, it doesn't read your goal words at all. So changing your goal mostly just refreshes the date and only nudges a number if your trend has moved. That turns out to be exactly what the original plan meant by doing it "silently." I built that honest, quiet version, and filed a separate note (#305) for the bigger question, should changing your goal actually move the numbers more?, because that needs real data before it's worth guessing at.

how I tested it

I wrote the tests first. 15 small tests for the core logic (all pass on my machine), plus 6 database tests that the build server runs. I also checked that all the old goal-saving tests still pass, so nothing that already worked got broken.

Done. Built in pull request 306 (issue 304), spun off 305 for the bigger "make it actually move the numbers" question. No app change and no database change were needed, it's all on the server.

Gave the athlete real strength targets to review and reach for

The app was always meant to show you concrete strength targets per movement once it knew you well enough, a "floor" (what you can reliably…

Done
the problem

The app was always meant to show you concrete strength targets per movement once it knew you well enough, a "floor" (what you can reliably do) and a "stretch" (what you're reaching for). But that whole layer was never built: the targets were always empty, and the screen that would show them didn't exist. Last entry I switched on the "how sure am I" ratings; this builds the thing those ratings unlock, once your main lifts are "known," the app can finally put real numbers in front of you.

what I changed
  • The numbers (server). When at least 4 of your 6 big movements are "known," the app works out, for each: a floor = a rounded-down typical of your recent best lifts (so it never overstates what you've shown), and a stretch = a bit above that, scaled to how you're trending (more if you're climbing, less if you're stalling). It also tracks whether you're behind / on track / ahead / there. Late-blooming lifts get targets too, the moment they qualify.
  • The screen (app). A one-time "your targets are ready" banner → a review screen showing each lift's floor, stretch, and progress.
  • Editing (app + server). You can nudge a stretch target up (never down, and you can't touch the floor, it reflects what you've actually lifted). The server enforces that upward-only rule so a bad app version can't cheat it. Once you've reviewed, the banner stays gone for good.
  • A nice catch from the design pass: two "capability" fields the old formulas wanted to use turned out to be dead (always zero), so everything was re-grounded on the live lift history instead, caught before it shipped a screen full of zeros.
how I tested it

Five small pieces, each shipped on its own. Server logic has unit + end-to-end tests (drove real sessions until the targets appeared); the app code was compiled and its logic unit- tested locally. Every server piece passed the reliable server test before merging.

How it was decided. Same rigorous design interview as last time, every question got three independent takes (mine, a fresh reviewer, and one that remembered the whole conversation), best answer taken. Written up in a new decision record (ADR-0021).

Done. All five pieces merged (294–298 via PRs 299–302 + this docs PR); umbrella 269 closed. Note: the app screens are compiled and logic-tested but I couldn't eyeball them rendered, so a quick visual once-over on a device is worth doing.