Files
workouts/Exercise Library/TODO-coverage.md
T

5.9 KiB
Raw Blame History

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)

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 — the test for "done" is that a typical gym-goer (machine circuit, free-weight lifter, or home/bodyweight) can build their whole program from the picker. Write the filled matrix 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).
  • 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.

Filling these modestly lands around 4046 total (currently 22) — "double the library" is the outcome, but the matrix decides which ones and in what order: hinge first, then lunge + bodyweight canon, then free weights, then isolation/mobility.

Authoring workflow, per exercise

  • New folder <Name>/ 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 "<Name>" (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"; the exact exercise picks per gap 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).