Actionable Balance

The Athlete Profile on the Stats tab knows a lot about you. It knows your push is Advanced, your pull is Intermediate, your squat is Newcomer. It shows you a tier per family. And then it stops there.

v1.34 makes it act. When your training is out of balance — really out of balance — a card on the Stats tab tells you which family is lagging, why it matters, and points at the specific add-on that would fix it.

The gap the profile was leaving open

v1.12 shipped the Athlete Profile. Six-tier ranks per family and skill, archetype title, hero image. A calisthenics identity view derived live from your rung state.

But identity views don't train anything. A Puller with Newcomer squats can look at that card every week and never do a squat. The tier read was passive.

v1.33 shipped Add-ons — 14 complementary sessions targeting specific families (Bulletproof Shoulders for push, Posterior Chain for hinge, Core Foundations for core). Real work, right-sized to purpose.

The connection between "here's the imbalance" and "here's the fix for it" was still on the user. v1.34 closes that loop.

How Balance Advice works

Every time the Stats tab loads, the backend computes a tier for each of your five universal families (push / pull / squat / hinge / core) from your live rung state. It sorts them, finds the tier gap between weakest and strongest, and decides whether to say anything.

Silent when the gap is 0–1 tiers. Everyone has variance across families — that's normal. No card.

Silent when the gap is 2 tiers. Reserved for a softer future surface — we don't want to be noisy about every minor asymmetry.

Actionable when the gap is 3 or more tiers. That's Advanced-vs-Newcomer territory. Something meaningful is behind the rest of your training. Time to intervene.

When Balance Advice fires, the Stats card shows:

  • Which family is lagging — named directly. "Your push is Newcomer, your pull is Advanced."
  • Why we're saying it — a coach-voice opening tuned per family. Push gets "your pressing is lagging behind the rest of your training." Core gets "your core is the bottleneck — everything above and below is stronger." Five distinct openings, one per family.
  • What to do — a specific add-on, matched to family and current tier level. Beginner-tier user with a Newcomer weakness gets the Beginner add-on. Novice weakness gets the Advanced variant.
  • How much — "For 3 weeks, run Bulletproof Shoulders (Beginner) 2 times a week." Explicit dose, not a vague suggestion.

Two ways to act on it:

  • Start it now — tap the recommendation and you're at StartProgram, one tap from beginning.
  • Add it to this week — tap the secondary button and the session gets injected into your plan on the nearest available weekday (at least two days out, weekends skipped). A toast confirms which day. Foundations plans and paused plans hide this button — Foundations is progression-driven so there's no day slot to inject into, and paused plans stay paused.

Why the specific choices

Tier gap of 3. We tested threshold 2 in our head and it fires too often — real athletes have gaps of 2 between push and squat all the time and don't need to be told about it. Gap of 3 (Advanced vs Novice, or Elite vs Beginner) is where a coach actually starts noticing.

Beginner tier is the default add-on. If your push is Newcomer, we're not sending you into Bulletproof Shoulders Advanced with band-assisted work. Novice-tier and above get the Advanced variant — it's where the band tier makes sense.

Pull uses Core Foundations, hinge uses Posterior Chain. We don't have a pull-specific add-on yet. Core Foundations trains lots of pull-supportive scapular and anti-flexion work, so it's a defensible proxy for now. Hinge → Posterior Chain is exact — that's what Posterior Chain trains.

Reasoning is server-authored. We can tune the copy per-family without shipping an iOS update. If a specific opening lands wrong we edit the string, deploy, done.

Under the hood

  • 15 backend unit tests for the imbalance detector plus 15 for the plan-injection endpoint — covering all five families, missing-rung cases, tier-aware program selection, day-picker edge cases (weekend skip, occupied slots, ≥2-day buffer), and rejection paths (Foundations plan, paused plan).
  • iOS decoder tests locking the JSON contract with the backend — if the response shape drifts, tests fail before users see it.
  • Three analytics events: balance_advice_shown (fires once per Stats view when a card renders), balance_advice_tapped (recommendation button), and balance_advice_injected (add-to-week success, sliced by family, weekday, and how many days ahead the session landed).
  • Failure paths are quiet: fetch failures hide the card, injection failures toast the user and log to Sentry rather than blocking the tab.

What's next

Balance Advice v1.34 is read + tap + add-to-week. One follow-up is already shaped:

Level 3 (v1.35+, planned). When a major imbalance persists for multiple weeks, the app proactively proposes a plan modification: "We noticed your posterior chain lagging. Would you like Posterior Chain added to your plan for 3 weeks?" One tap to accept, revocable.

For now: see the card, act on it, do the session. That's the loop.

Available in v1.34.0 on TestFlight now. Rolling out to the App Store this week.