CODEX // oaoisme wiki

§ Forge — hypertrophy tracker

Smart coaching

updated 2026-06-08

Forge logs, progresses, and shows fatigue/volume — smart coaching turns that data into advice. The design principle is ambient and non-prescriptive: advice appears inline as small chips/banners, and nothing auto-changes your program — you always choose.

The module

coach.js is a pure module (mirrors engine.js): no DB, no clock reads (the caller passes now/pre-shaped data), so it's unit-tested in isolation (coach.test.js). It consumes the engine's existing outputs — computeFatigue, weeklyVolume, epley1RM — plus the live program and session history, and returns plain advice objects the server renders.

Thresholds are named constants: hypertrophy band 10–20 effective sets/week, frequency target 2×, fatigue-warn at tier ≥3 (~≥70%), plateau window 3 sessions.

The four modules

1. Recovery warnings (Today)

For the day's program, any target muscle still fatigued (tier ≥3) is flagged with its % and days-since-trained — "Quads 96% (0d)". A banner lists them; each affected exercise card gets an amber warn chip. You're told it's still cooked; whether you train it is up to you. Uses the same fatigue decay the heatmap uses.

2. Volume & balance audit (Body)

Runs an automatic version of a hand audit over the live program design: per-muscle effective sets/cycle (Σ contribution × sets) and frequency, compared to the band. Flags under (below MEV), over (above MRV), or low_freq (<2×), each with a concrete fix ("add ~4 sets", "split across 2 days"), plus an "N/16 in range" summary. Equipment-capped groups (forearms, lower back — no direct tool with a bar + dumbbells) are tagged capped and not nagged.

3. Plateau detection (Exercise / Progress)

For a lift with ≥4 sessions of history, it walks the estimated-1RM series (best working set per session) and flags a stall when no new best appears across the last 3 trained sessions, suggesting a rep-range reset or back-off. It is the thing that won't let you tell yourself the quiet lie of "still progressing" on a plateau.

4. Deload signal (Body / Progress)

A composite, ambient flag. Fires on ≥2 stalled main lifts, ≥3 fully-fatigued (molten) muscles, ≥2 muscles over MRV, or a ≥5-week training block with any stall/fatigue. Shows "deload worth considering" with the reasons — never forces a deload week (no mesocycle state is stored in v1).

Where it's wired

server.js calls coach per route and reuses existing db reads (setsForFatigue, getProgram, exerciseHistory, recentSessions); the only additions are two server helpers — keyLiftStalls() and activeWeeks() (a block-length proxy: distinct training weeks in the trailing 8). No schema change. Advice renders in amber --warn (heat-red at high severity) as hairline chips/banners — see the design system.

Tested

coach.test.js covers each module's logic (recovery thresholds + sorting, audit flags/fixes, plateau detection, deload composite). The live e2e.mjs gained a Smart Coaching pass that seeds stall + fatigue scenarios via the API and asserts every surface shows the right advice — recovery banner + chip on Today, audit card + deload on Body, stalled list on Progress, plateau flag on a lift — on desktop + mobile, zero console errors. Whole suite: 77 checks green.

Not in v1 (deliberately)

No persisted mesocycle state, no one-tap auto-apply, no user-configurable thresholds, no dismiss/snooze. The next planned work (separate builds) is bulletproof in-gym UX (offline logging), growth tracking (bodyweight / measurements / photos), and a Telegram nudge integration.