# Handoff: right-size the exercise library by functional coverage Repo: `~/Documents/indie/Workouts`. Read `Exercise Library/SYSTEM.md` first (motion format, props, visual language), then one machine motion (`Leg Press/motion.json`) and one bodyweight motion (`Bird Dog/motion.json`) as templates, one `info.md` (`Leg Press/info.md`) plus its parser (`Workouts/ExerciseFigure/ExerciseInfo.swift` — it parses a fixed shape, not general Markdown), and `render.py` (`--sheet`, `--strict`, `--orbit`, `--export`, `--fixtures`). ## The question this session answers Not "how many exercises" but "which movement patterns can a user not log?" The picker (`ExercisePickerView`) lists exactly the bundled library names and there is no free-text fallback — the library is the app's **closed catalog**. A missing pattern is a hard wall, not a cosmetic gap. Build the coverage model, audit against it, then author the gap-fillers in priority order. ## The coverage model (starting point — refine it, don't rubber-stamp it) Two axes, and the target list is their **union**: 1. **Function — a movement-pattern × modality matrix.** Patterns: squat, hinge, lunge, horizontal push, vertical push, horizontal pull, vertical pull, elbow flexion, elbow extension, shoulder raise (lateral/rear), hip ab/adduction, calf, core anti-extension, core rotation, core lateral, core flexion, mobility/warm-up. Modalities: machine, free weight (barbell/dumbbell), bodyweight/floor. A cell needs an exercise only if real programs train that pattern that way. 2. **Equipment — a gym-floor census.** Walk a typical commercial gym (Planet Fitness / Golds tier): every common machine and free-weight station should have at least one library entry, because users log by station name, not by pattern — the matrix calls horizontal push "covered" by Chest Press, but Bench Press, Dumbbell Bench Press, and Pec Deck are distinct stations people expect to find in the picker. Inclusion test: "found in most gyms," not "exists somewhere." The test for "done": a typical gym-goer — machine circuit, free-weight lifter, or home/bodyweight — can build their whole program from the picker without a missing pattern *or* a missing station. Write both filled tables into SYSTEM.md (or a COVERAGE.md beside it) so future additions are judged the same way. ## What a rough audit already shows (verify, then prioritize) - **Hinge: zero coverage in any modality** — no Deadlift, Romanian Deadlift, Glute Bridge, or Hip Thrust. The single biggest hole; glutes are basically untrained by the current catalog. - **No lunge pattern** (Lunge / Split Squat). - **Bodyweight column missing its canon**: Squat, Push-Up, Pull-Up. - **Free-weight column completely empty** — zero barbell/dumbbell exercises. The `dumbbell` prop type exists in both renderers but has never been used by a motion; its first real use may shake out bugs. - **Shoulder raise**: no Lateral Raise (machine Shoulder Press only). - **Core flexion**: no plain Crunch (machine Abdominal only). - **Census gaps** — the current 14 machines are the standard selectorized circuit (good coverage there), but common stations are absent: bench press / incline bench (barbell + dumbbell), squat rack / Smith machine, pec deck (+ rear-delt fly), the cable station's staples (triceps pushdown, cable curl, cable crossover, face pull), assisted dip / pull-up, hack squat, back extension (roman chair), hip thrust, and the whole dumbbell rack (rows, shoulder press, flys, lateral raises, curls, RDLs, lunges, goblet squat). - Memory notes a desired "morning wake-up" mobility set (Cat-Cow exists; neck rolls, arm circles, etc.) — decide whether it's this session or the next phase. The pattern matrix alone lands around 40–46 total (currently 22); the union with the gym-floor census pushes it to roughly 50–60. The tables decide which ones and in what order: hinge first, then the bench/rack/dumbbell free-weight canon and bodyweight staples, then the remaining stations (cables, pec deck, assisted machines), then isolation/mobility. ## Authoring workflow, per exercise - New folder `/` with `motion.json` + `info.md`. The folder/`name` string is user-facing (picker + run screen) — match the existing naming register. - Pose keyframes in anatomical angles per SYSTEM.md; run `python3 render.py --strict ""` (ROM violations are data bugs; a few legacy warnings exist in old motions, add none), eyeball `preview.gif` AND `orbit.gif` — every exercise orbits in-app now, so check ±45°/90°/180°, not just the authored view. - Machines need props: scene slabs carry `z`/`depth` (see SYSTEM.md props section), `bar`/`pad`/`roller`/`cable` ride joints. Free weights are usually just a `bar` (with `plateR`) or `dumbbell` at the hands. - `info.md` must follow the parsed shape: `# Title`, summary paragraph, the `**Category:** / **Type:** / **Targets:** / **Prescription:**` bullets, then `## Setup / Execution / Cues / Common Mistakes / Progression`. **Machine exercises' `Type:` must start "Machine-based"** — that prefix is what shows the machine-settings UI (`ExerciseInfo.isMachineBased`). ## Invariants — do not break - **Data-only expansion.** New exercises need zero Swift changes; if you find yourself touching the schema or solver, stop and re-read SYSTEM.md — and any schema change must land in `render.py`/`kinematics.py` and the Swift port in lockstep, fixtures regenerated. - `WorkoutsTests/ExerciseMotionTests.swift` asserts `fixtures.exercises.count == 22` — bump it to the new count and regenerate with `python3 render.py --fixtures`. `allBundledMotionsBuildTimelines` covers new motions automatically. - Starter splits and their fixed-ULID seeds are frozen — adding library exercises must not touch `StarterSplits/` or `Workouts/Seed/`. - Every exercise ships both files: a motion with no `info.md` renders a blank reference page in Settings → Library. ## Verification workflow `python3 render.py --strict` (whole library) + `--sheet` and eyeball; `--orbit` for each new machine; `python3 render.py --export` then `python3 render.py --fixtures`; `xcodebuild test -scheme Workouts -destination 'platform=iOS Simulator,name=iPhone 17 Pro' -only-testing:WorkoutsTests` (48 green today; count assertion updated); `xcodebuild build -scheme "Workouts Watch App" -destination 'generic/platform=watchOS Simulator'`. If test results ever contradict the source, suspect a stale incremental build — nuke DerivedData and rerun. One end-user CHANGELOG.md sentence per the app-changelog skill (e.g. the library doubles with deadlifts, lunges, push-ups, dumbbells…), README key-features line if it names library scope. Commit in reviewable batches (the coverage model + audit first, then exercises by pattern group), push, delete this file in the final commit. ## Judgment calls you're empowered to make The final matrix rows and which cells count as "required"; where the census draws its "most gyms" line (kettlebells, T-bar row, pullover machine, and cardio equipment are likely out; Smith machine is borderline); whether the cable station gets one entry per exercise or per pattern; the exact exercise picks and their names; whether the mobility/"morning wake-up" set is in scope or explicitly deferred to the next phase; per-exercise camera yaw and prop minimalism (schematic silhouettes, never scale models).