Ship the 47-exercise library in-app: export, fixtures, tests, docs

render.py --export bundles the 25 new motion rigs and info pages;
figure-fixtures.json regenerated for all 47 (the Swift solver reproduces
every new motion, including negative-y pins and the new prop uses). The
fixture count assertion moves to 47, and the no-bundled-motion test now
uses Treadmill - a permanent COVERAGE.md exclusion - since Bench Press
exists. 48 tests green; watch target builds. Coverage handoff complete -
TODO-coverage.md retired.

Claude-Session: https://claude.ai/code/session_01HJDQQDA9QdP8zByg43H5v3
This commit is contained in:
2026-07-07 12:18:07 -04:00
parent b545ad05c9
commit 7c241ec44c
56 changed files with 1858 additions and 141 deletions
+2
View File
@@ -1,5 +1,7 @@
**July 2026**
The exercise library more than doubles — deadlifts, squats, lunges, bench presses, dumbbell work, pull-ups, and the cable stations — each with its own animated form guide.
Machine form guides now slowly circle around the figure too — seats, cables, and pads turn with the body, showing every exercise from all sides.
Form guides are now viewed from a slight elevation, with an exercise mat under the figure that turns with the camera.
-132
View File
@@ -1,132 +0,0 @@
# 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 4046 total (currently 22); the union
with the gym-floor census pushes it to roughly 5060. 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 `<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"; 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).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

After

Width:  |  Height:  |  Size: 622 KiB

+8 -5
View File
@@ -12,11 +12,14 @@ your own iCloud Drive.
machine routines, plus an equipment-free **Bodyweight Core** circuit with its
own warm-up) appear automatically on first launch; editing one makes it your
own copy, and deleted starters can be restored from Settings.
- **Exercise library** — a bundled library of exercises to populate your splits,
authored in `Exercise Library/` with per-exercise setup, cues, mistakes,
progressions, and an anatomically-rigged 3D stick-figure visual system — covering the
bodyweight core moves plus the full Planet Fitnessstyle machine circuit
(presses, rows, pulldowns, curls, leg and hip machines).
- **Exercise library** — a bundled library of 47 exercises to populate your
splits, authored in `Exercise Library/` with per-exercise setup, cues,
mistakes, progressions, and an anatomically-rigged 3D stick-figure visual
system — covering every common movement pattern and gym station (see the
library's `COVERAGE.md`): the full machine circuit, the barbell and dumbbell
free-weight canon (deadlifts, squats, benches, rows, curls, raises), the
cable staples, and the bodyweight staples (push-ups, pull-ups, dips,
lunges, and the floor core set).
- **Run a workout** — start a session from a split, then tap an exercise to run it
as a paged flow: a **Ready?** lead-in, count-up work phases, count-down rests, and
a **Finish** page — mirroring the Apple Watch. Swipe a row to mark it complete, or
@@ -0,0 +1,39 @@
# Back Extension
The roman-chair hinge — hips anchored on the pad, fold forward, then raise
the trunk back in line with the legs.
- **Category:** Main circuit
- **Type:** Machine-based back extension (hip hinge)
- **Targets:** Spinal erectors, glutes, hamstrings
- **Prescription:** 3 × 1015
## Setup
Set the pad so its top edge sits at the crease of your hips — you must be
able to fold freely over it. Hook your heels under the ankle rollers,
cross your arms over your chest.
## Execution
1. Fold forward over the pad with a controlled, mostly-flat back.
2. Lower until the hamstrings stop you, without going slack.
3. Squeeze glutes and back to raise the trunk until it lines up with the
legs — no higher.
## Cues
- Movement comes from the hips with the back held long.
- Rise to a straight body line, not into an arch.
- Slow down; momentum does nothing here.
## Common Mistakes
- Pad set too high, blocking the hinge.
- Hyperextending past the body line at the top.
- Swinging up with momentum.
## Progression
Slow the lowering phase, add a pause at the top, then hold a plate to the
chest for load.
@@ -0,0 +1,37 @@
{
"name": "Back Extension",
"primary": 2,
"working": ["spine"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[102, 124], [154, 106]], "w": 9, "depth": 8},
{"kind": "line", "pts": [[130, 122], [130, 150]], "w": 5},
{"kind": "line", "pts": [[58, 142], [88, 142]], "w": 5, "depth": 6}
]},
{"type": "roller", "at": ["foot_r", "foot_l"], "r": 4.5, "side": 1, "back": 4}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [150, 102], "pitch": 112},
"spine": [0, 12],
"neck": 10, "head": -30,
"shoulder_r": 30, "elbow_r": 140,
"shoulder_l": 30, "elbow_l": 140,
"hip_r": 48, "knee_r": 12, "ankle_r": 12,
"hip_l": 48, "knee_l": 12, "ankle_l": 12,
"pins": {"foot_r": [72, 136], "foot_l": [76, 138]}
},
{
"hold": 0.6, "tween": 1.1,
"root": {"pos": [150, 102], "pitch": 65},
"spine": [0, -6],
"neck": 5, "head": -55,
"shoulder_r": 30, "elbow_r": 140,
"shoulder_l": 30, "elbow_l": 140,
"hip_r": 2, "knee_r": 12, "ankle_r": 12,
"hip_l": 2, "knee_l": 12, "ankle_l": 12,
"pins": {"foot_r": [72, 136], "foot_l": [76, 138]}
}
]
}
@@ -0,0 +1,39 @@
# Barbell Squat
The barbell back squat — bar across the upper back, sit down between the
heels, stand back up.
- **Category:** Main circuit
- **Type:** Free-weight compound squat
- **Targets:** Quadriceps, glutes, adductors, trunk
- **Prescription:** 4 × 68
## Setup
Set the bar on your upper traps (not the neck), hands just outside the
shoulders, and step back from the rack. Feet shoulder-width, toes slightly
out, brace before every rep.
## Execution
1. Sit down and back — hips and knees bend together, chest stays up.
2. Descend until the thighs reach at least parallel, knees tracking over
the toes.
3. Drive the floor apart and stand back up to full lockout.
## Cues
- Big breath and brace at the top; exhale at the finish.
- The bar stays over mid-foot — watch the sideways bar path, not the mirror.
- Elbows down under the bar, not flared behind it.
## Common Mistakes
- Knees caving inward out of the bottom.
- Heels lifting — weight drifting onto the toes.
- Chest collapsing forward into a good-morning.
## Progression
Master the Bodyweight Squat and Goblet Squat first; add weight in small
jumps only while depth and knee tracking hold.
@@ -0,0 +1,35 @@
{
"name": "Barbell Squat",
"primary": 2,
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 14}
],
"frames": [
{
"hold": 0.4, "tween": 1.1,
"root": {"pos": [160, 64], "pitch": 6},
"spine": [0, 0],
"neck": 2, "head": -6,
"shoulder_r": 28, "elbow_r": 140,
"shoulder_l": 28, "elbow_l": 140,
"hip_r": 5, "knee_r": 4, "ankle_r": 0,
"hip_l": 5, "knee_l": 4, "ankle_l": 0,
"pins": {"foot_r": [160, 148], "foot_l": [164, 150],
"hand_r": [166, -16], "hand_l": [170, -14]}
},
{
"hold": 0.4, "tween": 1.1,
"root": {"pos": [117, 108], "pitch": 35},
"spine": [0, -4],
"neck": 5, "head": -28,
"shoulder_r": 55, "elbow_r": 140,
"shoulder_l": 55, "elbow_l": 140,
"hip_r": 100, "knee_r": 118, "ankle_r": 22,
"hip_l": 100, "knee_l": 118, "ankle_l": 22,
"pins": {"foot_r": [160, 148], "foot_l": [164, 150],
"hand_r": [163, 30], "hand_l": [167, 32]}
}
]
}
@@ -0,0 +1,40 @@
# Bench Press
The barbell press — lying on the flat bench, lower the bar to the chest
and press it back to straight arms.
- **Category:** Main circuit
- **Type:** Free-weight horizontal press
- **Targets:** Chest, front delts, triceps
- **Prescription:** 4 × 68
## Setup
Lie with eyes under the bar, feet flat on the floor, shoulder blades
pinched back and down. Grip a little wider than shoulder-width and
unrack to straight arms over the shoulders.
## Execution
1. Lower the bar under control to the mid-chest, elbows about 45° from
the body.
2. Touch lightly — no bounce.
3. Press back up and slightly toward the face to lockout over the
shoulders.
## Cues
- Shoulder blades stay pinched against the bench the whole set.
- Wrists stacked over elbows; bar sits low in the palm.
- Feet drive quietly into the floor.
## Common Mistakes
- Bouncing the bar off the chest.
- Elbows flared straight out at 90°.
- Hips lifting off the bench.
## Progression
Add small plates while every rep touches and locks out; a spotter or
safety pins once the loads get honest.
@@ -0,0 +1,39 @@
{
"name": "Bench Press",
"primary": 1,
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[58, 124], [162, 124]], "w": 9, "depth": 8},
{"kind": "line", "pts": [[78, 129], [78, 150]], "w": 4},
{"kind": "line", "pts": [[144, 129], [144, 150]], "w": 4}
]},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 12}
],
"frames": [
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [150, 116], "pitch": -90},
"spine": [0, 0],
"neck": 8, "head": 0,
"shoulder_r": 15, "elbow_r": 100,
"shoulder_l": 15, "elbow_l": 100,
"hip_r": 78, "knee_r": 82, "ankle_r": 5,
"hip_l": 78, "knee_l": 82, "ankle_l": 5,
"pins": {"foot_r": [196, 148], "foot_l": [200, 150],
"hand_r": [93, 100], "hand_l": [97, 102]}
},
{
"hold": 0.4, "tween": 1.2,
"root": {"pos": [150, 116], "pitch": -90},
"spine": [0, 0],
"neck": 8, "head": 0,
"shoulder_r": 90, "elbow_r": 5,
"shoulder_l": 90, "elbow_l": 5,
"hip_r": 78, "knee_r": 82, "ankle_r": 5,
"hip_l": 78, "knee_l": 82, "ankle_l": 5,
"pins": {"foot_r": [196, 148], "foot_l": [200, 150],
"hand_r": [67, 57], "hand_l": [71, 59]}
}
]
}
@@ -0,0 +1,37 @@
# Bodyweight Squat
The unloaded squat — arms reach forward as a counterbalance while the hips
sit down between the heels. The pattern every loaded squat is built on.
- **Category:** Warm-up and main circuit
- **Type:** Bodyweight squat
- **Targets:** Quadriceps, glutes, mobility
- **Prescription:** 3 × 1520, or 10 slow reps as a warm-up
## Setup
Stand with feet shoulder-width, toes slightly turned out, arms relaxed at
your sides.
## Execution
1. Reach the arms forward as the hips sit down and back.
2. Descend as deep as comfortable — thighs at least parallel — heels flat.
3. Stand back up tall and let the arms drop.
## Cues
- Knees track over the toes the whole way down and up.
- Chest up; the arms reaching forward keep you from tipping.
- Slow down — a three-second descent teaches control.
## Common Mistakes
- Heels lifting at the bottom.
- Knees diving inward.
- Shallow, quick bouncing instead of full, controlled reps.
## Progression
Slow the tempo, pause at the bottom, then load the pattern with the
Goblet Squat.
@@ -0,0 +1,30 @@
{
"name": "Bodyweight Squat",
"primary": 2,
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l"],
"frames": [
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [160, 64], "pitch": 4},
"spine": [0, 0],
"neck": 2, "head": -6,
"shoulder_r": 6, "elbow_r": 5,
"shoulder_l": 6, "elbow_l": 5,
"hip_r": 4, "knee_r": 3, "ankle_r": 0,
"hip_l": 4, "knee_l": 3, "ankle_l": 0,
"pins": {"foot_r": [160, 148], "foot_l": [164, 150]}
},
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [146, 106], "pitch": 30},
"spine": [0, -4],
"neck": 5, "head": -24,
"shoulder_r": 118, "elbow_r": 8,
"shoulder_l": 118, "elbow_l": 8,
"hip_r": 98, "knee_r": 118, "ankle_r": 22,
"hip_l": 98, "knee_l": 118, "ankle_l": 22,
"pins": {"foot_r": [160, 148], "foot_l": [164, 150]}
}
]
}
@@ -0,0 +1,38 @@
# Crunch
The floor ab curl — peel the shoulder blades off the mat, squeeze, and
lower. Short range, all abs.
- **Category:** Main circuit
- **Type:** Spinal flexion (upper)
- **Targets:** Rectus abdominis
- **Prescription:** 3 × 1520, slow
## Setup
Lie on your back, knees bent, feet flat. Fingertips lightly behind the
ears, elbows wide.
## Execution
1. Exhale and curl the ribs toward the pelvis until the shoulder blades
leave the floor.
2. Squeeze the abs hard at the top for a beat.
3. Lower the shoulders back down without letting the head rest.
## Cues
- It's a curl, not a sit-up — the lower back stays on the mat.
- Chin off the chest; the hands never pull the head.
- Exhale on the way up to deepen the contraction.
## Common Mistakes
- Yanking the neck with the hands.
- Sitting all the way up with the hip flexors.
- Racing through reps with momentum.
## Progression
Slow the tempo and add a pause at the top; hold a small plate on the
chest, or move to the Abdominal machine for stack-loaded flexion.
@@ -0,0 +1,29 @@
{
"name": "Crunch",
"primary": 2,
"working": ["spine"],
"frames": [
{
"hold": 0.4, "tween": 0.8,
"root": {"pos": [166, 146], "pitch": -90},
"spine": [0, 0],
"neck": 12, "head": 0,
"shoulder_r": 155, "elbow_r": 140,
"shoulder_l": 155, "elbow_l": 140,
"hip_r": 75, "knee_r": 85, "ankle_r": 5,
"hip_l": 75, "knee_l": 85, "ankle_l": 5,
"pins": {"foot_r": [205, 148], "foot_l": [209, 150]}
},
{
"hold": 0.6, "tween": 1.0,
"root": {"pos": [166, 144], "pitch": -90},
"spine": [14, 34],
"neck": 30, "head": 0,
"shoulder_r": 150, "elbow_r": 140,
"shoulder_l": 150, "elbow_l": 140,
"hip_r": 75, "knee_r": 85, "ankle_r": 5,
"hip_l": 75, "knee_l": 85, "ankle_l": 5,
"pins": {"foot_r": [205, 148], "foot_l": [209, 150]}
}
]
}
@@ -0,0 +1,40 @@
# Deadlift
The barbell hip hinge — brace hard, then stand up with the bar by driving
the hips through.
- **Category:** Main circuit
- **Type:** Free-weight compound hinge
- **Targets:** Glutes, hamstrings, spinal erectors, grip
- **Prescription:** 4 × 68
## Setup
Stand with the bar over mid-foot, feet hip-width. Hinge down with a flat
back and grip the bar just outside your legs. Shoulders slightly ahead of
the bar, hips higher than knees, chest up.
## Execution
1. Take the slack out of the bar, brace your trunk, then push the floor
away — hips and shoulders rise together.
2. Once the bar passes the knees, drive the hips forward to stand tall.
3. Lower under control by hinging at the hips first, then bending the
knees once the bar clears them.
## Cues
- Flat back from setup to lockout — the spine never rounds or overarches.
- Keep the bar dragging close to the legs the whole way.
- Finish with glutes, not by leaning back.
## Common Mistakes
- Squatting the weight up — hips too low, knees pushed forward.
- Rounding the lower back off the floor.
- Jerking the bar off the ground instead of pushing through the legs.
## Progression
Add weight in small jumps while all reps stay flat-backed; start from
blocks or a rack if floor mobility isn't there yet.
@@ -0,0 +1,35 @@
{
"name": "Deadlift",
"primary": 1,
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l", "spine"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 16}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [92, 90], "pitch": 78},
"spine": [0, -6],
"neck": 5, "head": -70,
"shoulder_r": 75, "elbow_r": 5,
"shoulder_l": 75, "elbow_l": 5,
"hip_r": 115, "knee_r": 30, "ankle_r": 15,
"hip_l": 115, "knee_l": 30, "ankle_l": 15,
"pins": {"foot_r": [150, 147], "foot_l": [154, 149],
"hand_r": [156, 130], "hand_l": [160, 132]}
},
{
"hold": 0.4, "tween": 1.2,
"root": {"pos": [150, 64], "pitch": 10},
"spine": [0, 0],
"neck": 2, "head": -8,
"shoulder_r": 10, "elbow_r": 3,
"shoulder_l": 10, "elbow_l": 3,
"hip_r": 8, "knee_r": 5, "ankle_r": 0,
"hip_l": 8, "knee_l": 5, "ankle_l": 0,
"pins": {"foot_r": [150, 147], "foot_l": [154, 149],
"hand_r": [161, 38], "hand_l": [165, 40]}
}
]
}
@@ -0,0 +1,37 @@
# Dip
The bodyweight press on parallel bars — lower until the shoulders reach
elbow depth, then press back to straight arms.
- **Category:** Main circuit
- **Type:** Bodyweight elbow extension (chest/triceps press)
- **Targets:** Triceps, chest, front delts
- **Prescription:** 3 × 612
## Setup
Support yourself on the parallel bars with straight arms, shoulders
pressed down, slight forward lean, knees bent behind.
## Execution
1. Bend the elbows and lower until the upper arms reach parallel.
2. Keep the elbows tracking back, body leaning slightly forward.
3. Press back up to full lockout without the shoulders shrugging.
## Cues
- Shoulders stay down away from the ears at every depth.
- More forward lean hits chest; upright hits triceps.
- Depth to parallel — a shaky bottom inch isn't worth the shoulder.
## Common Mistakes
- Sinking the shoulders into the ears at the bottom.
- Flaring the elbows straight out.
- Bouncing out of the deep position.
## Progression
Use the assisted dip machine or bands until full-range reps are smooth;
then add reps, then hang weight from a belt.
@@ -0,0 +1,36 @@
{
"name": "Dip",
"primary": 2,
"camera": {"zoom": 0.78},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[176, 66], [176, 150]], "w": 5},
{"kind": "circle", "c": [176, 61], "r": 3.5, "fill": true, "color": "prop"}
]}
],
"frames": [
{
"hold": 0.4, "tween": 1.1,
"root": {"pos": [160, 86], "pitch": 8},
"spine": [0, 0],
"neck": 5, "head": -10,
"shoulder_r": 2, "elbow_r": 8,
"shoulder_l": 2, "elbow_l": 8,
"hip_r": 45, "knee_r": 130, "ankle_r": -20,
"hip_l": 45, "knee_l": 130, "ankle_l": -20,
"pins": {"hand_r": [174, 60], "hand_l": [178, 62]}
},
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [160, 116], "pitch": 18},
"spine": [0, 4],
"neck": 8, "head": -15,
"shoulder_r": -30, "elbow_r": 110,
"shoulder_l": -30, "elbow_l": 110,
"hip_r": 78, "knee_r": 148, "ankle_r": -20,
"hip_l": 78, "knee_l": 148, "ankle_l": -20,
"pins": {"hand_r": [174, 60], "hand_l": [178, 62]}
}
]
}
@@ -0,0 +1,38 @@
# Dumbbell Bench Press
The dumbbell press on the flat bench — a deeper, freer pressing arc than
the bar, one weight in each hand.
- **Category:** Main circuit
- **Type:** Free-weight horizontal press (dumbbells)
- **Targets:** Chest, front delts, triceps
- **Prescription:** 3 × 812
## Setup
Sit with the dumbbells on your thighs, then lie back and kick them up to
straight arms over the shoulders. Feet flat, shoulder blades pinched.
## Execution
1. Lower both dumbbells to the outside of the chest, elbows about 45°
from the body.
2. Reach a comfortable stretch — deeper than a bar allows.
3. Press back up and slightly together to lockout.
## Cues
- The dumbbells travel in a shallow A-shape, not straight lines.
- Keep the wrists neutral and stacked over the elbows.
- Lower slowly; the stretch is where dumbbells earn their keep.
## Common Mistakes
- Clanging the weights together at the top.
- Uneven pressing — one side racing ahead.
- Dropping the dumbbells from lockout instead of walking them down.
## Progression
Add weight while both sides press evenly; pause reps in the stretch
position.
@@ -0,0 +1,40 @@
{
"name": "Dumbbell Bench Press",
"primary": 1,
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[58, 124], [162, 124]], "w": 9, "depth": 8},
{"kind": "line", "pts": [[78, 129], [78, 150]], "w": 4},
{"kind": "line", "pts": [[144, 129], [144, 150]], "w": 4}
]},
{"type": "dumbbell", "at": "hand_r"},
{"type": "dumbbell", "at": "hand_l"}
],
"frames": [
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [150, 116], "pitch": -90},
"spine": [0, 0],
"neck": 8, "head": 0,
"shoulder_r": 12, "elbow_r": 105,
"shoulder_l": 12, "elbow_l": 105,
"hip_r": 78, "knee_r": 82, "ankle_r": 5,
"hip_l": 78, "knee_l": 82, "ankle_l": 5,
"pins": {"foot_r": [196, 148], "foot_l": [200, 150],
"hand_r": [90, 104], "hand_l": [98, 106]}
},
{
"hold": 0.4, "tween": 1.2,
"root": {"pos": [150, 116], "pitch": -90},
"spine": [0, 0],
"neck": 8, "head": 0,
"shoulder_r": 90, "elbow_r": 5,
"shoulder_l": 90, "elbow_l": 5,
"hip_r": 78, "knee_r": 82, "ankle_r": 5,
"hip_l": 78, "knee_l": 82, "ankle_l": 5,
"pins": {"foot_r": [196, 148], "foot_l": [200, 150],
"hand_r": [66, 57], "hand_l": [72, 59]}
}
]
}
@@ -0,0 +1,37 @@
# Dumbbell Curl
The free-weight biceps curl — elbows pinned to the sides, curl both
dumbbells from a full hang to the shoulders.
- **Category:** Main circuit
- **Type:** Free-weight elbow flexion (dumbbells)
- **Targets:** Biceps, forearms
- **Prescription:** 3 × 1012
## Setup
Stand tall with a dumbbell in each hand at your sides, palms forward (or
turning as you curl), elbows lightly touching the ribs.
## Execution
1. Curl both weights up in an arc until the forearms reach the biceps.
2. Keep the elbows fixed in place at your sides.
3. Lower all the way to straight arms — the stretch counts.
## Cues
- Elbows are hinges, not swings — they never travel forward or back.
- Wrists stay neutral; no flicking at the top.
- Stand tall; the trunk does not rock.
## Common Mistakes
- Swinging the hips to start the rep.
- Half reps that skip the bottom stretch.
- Elbows drifting forward, turning it into a front raise.
## Progression
Add weight only while the torso stays statue-still; alternate arms or
curl seated to remove all momentum.
@@ -0,0 +1,34 @@
{
"name": "Dumbbell Curl",
"primary": 2,
"camera": {"zoom": 0.7},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "dumbbell", "at": "hand_r"},
{"type": "dumbbell", "at": "hand_l"}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [160, 64], "pitch": 3},
"spine": [0, 0],
"neck": 2, "head": -4,
"shoulder_r": 3, "elbow_r": 10,
"shoulder_l": 3, "elbow_l": 10,
"hip_r": 3, "knee_r": 2, "ankle_r": 0,
"hip_l": 3, "knee_l": 2, "ankle_l": 0,
"pins": {"foot_r": [158, 148], "foot_l": [162, 150]}
},
{
"hold": 0.4, "tween": 1.2,
"root": {"pos": [160, 64], "pitch": 3},
"spine": [0, 0],
"neck": 2, "head": -4,
"shoulder_r": 6, "elbow_r": 128,
"shoulder_l": 6, "elbow_l": 128,
"hip_r": 3, "knee_r": 2, "ankle_r": 0,
"hip_l": 3, "knee_l": 2, "ankle_l": 0,
"pins": {"foot_r": [158, 148], "foot_l": [162, 150]}
}
]
}
@@ -0,0 +1,38 @@
# Dumbbell Fly
The chest isolation — arms sweep from wide open to over the chest in a
hugging arc, elbows softly fixed.
- **Category:** Main circuit
- **Type:** Free-weight chest fly (dumbbells)
- **Targets:** Chest, front delts
- **Prescription:** 3 × 1015, light and controlled
## Setup
Lie on the flat bench with light dumbbells pressed over the chest, palms
facing each other, a slight fixed bend in the elbows.
## Execution
1. Open the arms in a wide arc until you feel a full chest stretch —
hands about level with the chest, never below the shoulders' comfort.
2. Keep the elbow angle unchanged the entire way.
3. Sweep back up as if hugging a barrel, squeezing the chest together.
## Cues
- It's an arc, not a press — the elbows never bend and extend.
- Go light; the stretch does the work, not the load.
- Stop the descent the moment the chest stretch peaks.
## Common Mistakes
- Bending the elbows on the way down and pressing back up.
- Dropping too deep and straining the shoulders.
- Using bench-press weights.
## Progression
Slow the lowering phase and pause in the stretch; the Pec Deck offers
the same motion with the path guided.
@@ -0,0 +1,39 @@
{
"name": "Dumbbell Fly",
"primary": 2,
"camera": {"yaw": 90},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[148, 124], [172, 124]], "w": 8, "depth": 40},
{"kind": "line", "pts": [[154, 129], [154, 150]], "w": 4},
{"kind": "line", "pts": [[166, 129], [166, 150]], "w": 4}
]},
{"type": "dumbbell", "at": "hand_r"},
{"type": "dumbbell", "at": "hand_l"}
],
"frames": [
{
"hold": 0.5, "tween": 1.0,
"root": {"pos": [160, 116], "pitch": -90},
"spine": [0, 0],
"neck": 8, "head": 0,
"shoulder_r": 88, "elbow_r": 12,
"shoulder_l": 88, "elbow_l": 12,
"hip_r": {"flexion": 78, "abduction": 10}, "knee_r": 82, "ankle_r": 5,
"hip_l": {"flexion": 78, "abduction": 10}, "knee_l": 82, "ankle_l": 5,
"pins": {"foot_r": [142, 148], "foot_l": [178, 150]}
},
{
"hold": 0.5, "tween": 1.3,
"root": {"pos": [160, 116], "pitch": -90},
"spine": [0, 0],
"neck": 8, "head": 0,
"shoulder_r": {"flexion": 16, "abduction": 84}, "elbow_r": 22,
"shoulder_l": {"flexion": 16, "abduction": 84}, "elbow_l": 22,
"hip_r": {"flexion": 78, "abduction": 10}, "knee_r": 82, "ankle_r": 5,
"hip_l": {"flexion": 78, "abduction": 10}, "knee_l": 82, "ankle_l": 5,
"pins": {"foot_r": [142, 148], "foot_l": [178, 150]}
}
]
}
@@ -0,0 +1,39 @@
# Dumbbell Row
The one-arm row — knee and hand braced on the bench, pull the dumbbell
from a dead hang to the ribs.
- **Category:** Main circuit
- **Type:** Free-weight horizontal pull (dumbbell)
- **Targets:** Lats, mid-back, biceps
- **Prescription:** 3 × 812 per side
## Setup
Put the same-side knee and hand on a bench, the other foot planted on
the floor. Back flat and parallel to the ground, dumbbell hanging
straight down from the shoulder.
## Execution
1. Pull the dumbbell up and back toward the hip until the elbow passes
the ribs.
2. Squeeze the shoulder blade at the top.
3. Lower to a full hang and stretch. Finish the set, then switch sides.
## Cues
- The elbow leads; the hand just holds on.
- Shoulders stay square to the floor — no twisting to hoist the weight.
- Long neck, eyes down; the back stays flat.
## Common Mistakes
- Rotating the torso open at the top of each rep.
- Pulling with the biceps instead of driving the elbow back.
- Cutting the stretch short at the bottom.
## Progression
Heavier dumbbells while the torso stays quiet; pause each rep at the top
for a stricter mid-back stimulus.
@@ -0,0 +1,39 @@
{
"name": "Dumbbell Row",
"primary": 2,
"working": ["arm_r"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[100, 124], [215, 124]], "w": 9, "depth": 8},
{"kind": "line", "pts": [[118, 129], [118, 150]], "w": 4},
{"kind": "line", "pts": [[196, 129], [196, 150]], "w": 4}
]},
{"type": "dumbbell", "at": "hand_r"}
],
"frames": [
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [168, 82], "yaw": 180, "pitch": 80},
"spine": [0, 0],
"neck": 10, "head": -50,
"shoulder_r": 75, "elbow_r": 8,
"shoulder_l": 72, "elbow_l": 5,
"hip_r": 25, "knee_r": 25, "ankle_r": 10,
"hip_l": 80, "knee_l": 95, "ankle_l": -50,
"pins": {"foot_r": [196, 148], "foot_l": [202, 122],
"hand_l": [66, 120], "hand_r": [92, 125]}
},
{
"hold": 0.5, "tween": 1.1,
"root": {"pos": [168, 82], "yaw": 180, "pitch": 80},
"spine": [0, 0],
"neck": 10, "head": -50,
"shoulder_r": 40, "elbow_r": 115,
"shoulder_l": 72, "elbow_l": 5,
"hip_r": 25, "knee_r": 25, "ankle_r": 10,
"hip_l": 80, "knee_l": 95, "ankle_l": -50,
"pins": {"foot_r": [196, 148], "foot_l": [202, 122],
"hand_l": [66, 120], "hand_r": [100, 86]}
}
]
}
@@ -0,0 +1,37 @@
# Dumbbell Shoulder Press
The overhead press with dumbbells — seated against an upright bench,
press from the shoulders to lockout overhead.
- **Category:** Main circuit
- **Type:** Free-weight vertical press (dumbbells)
- **Targets:** Shoulders, triceps, upper chest
- **Prescription:** 3 × 812
## Setup
Set the bench back upright. Sit with the dumbbells at shoulder height,
palms forward, forearms vertical, feet planted.
## Execution
1. Press both dumbbells straight up until the arms lock out overhead.
2. Keep the weights over the shoulders — not drifting forward.
3. Lower under control back to shoulder height.
## Cues
- Forearms vertical from every angle, wrists stacked over elbows.
- Ribs down; the back stays on the pad, not arching off it.
- The head moves slightly through at the top — bar path stays vertical.
## Common Mistakes
- Overarching the lower back to press bigger weights.
- Stopping short of lockout.
- Letting the dumbbells drift out sideways on the way up.
## Progression
Add weight while the back stays quiet on the pad; standing presses
recruit more trunk once the seated pattern is strong.
@@ -0,0 +1,41 @@
{
"name": "Dumbbell Shoulder Press",
"primary": 2,
"camera": {"zoom": 0.82},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[117, 128], [113, 58]], "w": 8, "depth": 8},
{"kind": "line", "pts": [[114, 134], [150, 134]], "w": 8, "depth": 8},
{"kind": "line", "pts": [[132, 136], [132, 150]], "w": 5}
]},
{"type": "dumbbell", "at": "hand_r"},
{"type": "dumbbell", "at": "hand_l"}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [130, 124], "pitch": 2},
"spine": [0, 2],
"neck": 4, "head": -6,
"shoulder_r": 35, "elbow_r": 145,
"shoulder_l": 35, "elbow_l": 145,
"hip_r": 84, "knee_r": 64,
"hip_l": 84, "knee_l": 64,
"pins": {"foot_r": [176, 150], "foot_l": [180, 151],
"hand_r": [146, 30], "hand_l": [150, 32]}
},
{
"hold": 0.4, "tween": 1.2,
"root": {"pos": [130, 124], "pitch": 2},
"spine": [0, 2],
"neck": 4, "head": -6,
"shoulder_r": 168, "elbow_r": 8,
"shoulder_l": 168, "elbow_l": 8,
"hip_r": 84, "knee_r": 64,
"hip_l": 84, "knee_l": 64,
"pins": {"foot_r": [176, 150], "foot_l": [180, 151],
"hand_r": [138, -19], "hand_l": [142, -17]}
}
]
}
@@ -0,0 +1,39 @@
# Face Pull
The cable pull to the face — elbows high and wide, rope to the bridge of
the nose. Small weight, big shoulders-health payoff.
- **Category:** Main circuit
- **Type:** Machine-based cable pull (rear delts)
- **Targets:** Rear delts, mid-back, rotator cuff
- **Prescription:** 3 × 1215, light
## Setup
Set a rope attachment at face height (or slightly above). Grip with
thumbs toward you, step back until the arms are straight, and stand
tall with a slight stagger if needed.
## Execution
1. Pull the rope straight toward the bridge of your nose.
2. Elbows travel high and wide; at the end the knuckles point back
beside the ears.
3. Pause, then let the arms straighten slowly forward.
## Cues
- Elbows lead and stay at shoulder height the whole pull.
- Pull the rope apart as it reaches the face.
- Ribs down; the trunk doesn't lean back to finish the rep.
## Common Mistakes
- Turning it into a row with elbows dropping to the ribs.
- Too much weight — the shoulders shrug and the trunk sways.
- Anchor set too low, dragging the pull toward the chest.
## Progression
Add reps and pause length before weight; the Rear Delt Fly machine
covers the same muscles with chest support.
@@ -0,0 +1,38 @@
{
"name": "Face Pull",
"primary": 2,
"camera": {"zoom": 0.7},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "circle", "c": [242, -30], "r": 4, "fill": true, "color": "prop"}
]},
{"type": "cable", "from": [242, -30], "to": ["hand_r", "hand_l"], "w": 3}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [150, 66], "pitch": 5},
"spine": [0, 2],
"neck": 4, "head": -6,
"shoulder_r": 95, "elbow_r": 10,
"shoulder_l": 95, "elbow_l": 10,
"hip_r": 6, "knee_r": 8, "ankle_r": 0,
"hip_l": 6, "knee_l": 8, "ankle_l": 0,
"pins": {"foot_r": [146, 148], "foot_l": [150, 150],
"hand_r": [214, -24], "hand_l": [218, -22]}
},
{
"hold": 0.5, "tween": 1.1,
"root": {"pos": [150, 66], "pitch": 5},
"spine": [0, 2],
"neck": 4, "head": -6,
"shoulder_r": {"flexion": 95, "abduction": 15}, "elbow_r": 140,
"shoulder_l": {"flexion": 95, "abduction": 15}, "elbow_l": 140,
"hip_r": 6, "knee_r": 8, "ankle_r": 0,
"hip_l": 6, "knee_l": 8, "ankle_l": 0,
"pins": {"foot_r": [146, 148], "foot_l": [150, 150],
"hand_r": [170, -26], "hand_l": [174, -24]}
}
]
}
@@ -0,0 +1,39 @@
# Glute Bridge
The floor hip hinge — drive through the heels and lift the hips until the
body is a straight line from shoulders to knees.
- **Category:** Warm-up and main circuit
- **Type:** Hip extension (floor)
- **Targets:** Glutes, hamstrings
- **Prescription:** 3 × 1215, squeeze at the top
## Setup
Lie on your back, knees bent, feet flat on the floor about hip-width and
close enough that your fingertips can graze your heels. Arms rest at your
sides.
## Execution
1. Press through the heels and squeeze the glutes to lift the hips.
2. Stop when shoulders, hips and knees form a straight line — no arching
past it.
3. Hold the squeeze for a beat, then lower with control.
## Cues
- The glutes lift the hips; the lower back just comes along.
- Ribs stay down — finish with the glutes, not by overarching.
- Knees track over the feet, never falling inward or out.
## Common Mistakes
- Pushing through the toes instead of the heels.
- Overarching the lower back at the top.
- Bouncing reps off the floor.
## Progression
Pause holds at the top, then single-leg bridges; graduate to the barbell
Hip Thrust for load.
@@ -0,0 +1,29 @@
{
"name": "Glute Bridge",
"primary": 2,
"working": ["leg_r", "leg_l"],
"frames": [
{
"hold": 0.4, "tween": 0.8,
"root": {"pos": [168, 144], "pitch": -90},
"spine": [0, 0],
"neck": 20, "head": -6,
"shoulder_r": -4, "elbow_r": 0,
"shoulder_l": -4, "elbow_l": 0,
"hip_r": 72, "knee_r": 82, "ankle_r": 5,
"hip_l": 72, "knee_l": 82, "ankle_l": 5,
"pins": {"foot_r": [205, 148], "foot_l": [209, 150]}
},
{
"hold": 0.9, "tween": 1.0,
"root": {"pos": [172, 116], "pitch": -110},
"spine": [0, -4],
"neck": 48, "head": -6,
"shoulder_r": -14, "elbow_r": 0,
"shoulder_l": -14, "elbow_l": 0,
"hip_r": 16, "knee_r": 92, "ankle_r": 5,
"hip_l": 16, "knee_l": 92, "ankle_l": 5,
"pins": {"foot_r": [205, 148], "foot_l": [209, 150]}
}
]
}
@@ -0,0 +1,37 @@
# Goblet Squat
The dumbbell squat — hold one dumbbell vertically at the chest and squat
between the heels. The friendliest way to load a squat.
- **Category:** Main circuit
- **Type:** Free-weight squat (dumbbell)
- **Targets:** Quadriceps, glutes, trunk
- **Prescription:** 3 × 1012
## Setup
Hold a dumbbell vertically against your chest, both palms cupping the top
end, elbows pointing down. Feet shoulder-width, toes slightly out.
## Execution
1. Squat down between the heels, keeping the dumbbell glued to the chest.
2. Reach full depth — elbows travel inside the knees.
3. Stand back up tall without letting the weight tip you forward.
## Cues
- The counterweight in front lets the torso stay very upright — use it.
- Elbows brush the inside of the knees at the bottom.
- Whole foot planted; drive through the heels.
## Common Mistakes
- Letting the dumbbell drift away from the chest.
- Cutting depth short.
- Collapsing the upper back as the weight gets heavy.
## Progression
Heavier dumbbells until they're awkward to hold — then move to the
Barbell Squat.
@@ -0,0 +1,35 @@
{
"name": "Goblet Squat",
"primary": 2,
"camera": {"zoom": 0.72},
"working": ["leg_r", "leg_l"],
"props": [
{"type": "dumbbell", "at": ["hand_r", "hand_l"], "angle": 90, "halfLen": 8, "plateR": 5}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [160, 66], "pitch": 5},
"spine": [0, 0],
"neck": 2, "head": -6,
"shoulder_r": 38, "elbow_r": 125,
"shoulder_l": 38, "elbow_l": 125,
"hip_r": 5, "knee_r": 4, "ankle_r": 0,
"hip_l": 5, "knee_l": 4, "ankle_l": 0,
"pins": {"foot_r": [162, 148], "foot_l": [166, 150],
"hand_r": [176, -2], "hand_l": [180, 0]}
},
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [150, 104], "pitch": 22},
"spine": [0, -4],
"neck": 4, "head": -18,
"shoulder_r": 46, "elbow_r": 120,
"shoulder_l": 46, "elbow_l": 120,
"hip_r": 96, "knee_r": 116, "ankle_r": 20,
"hip_l": 96, "knee_l": 116, "ankle_l": 20,
"pins": {"foot_r": [162, 148], "foot_l": [166, 150],
"hand_r": [190, 40], "hand_l": [194, 42]}
}
]
}
@@ -0,0 +1,38 @@
# Hip Thrust
The loaded glute bridge — shoulders on a bench, barbell across the hips,
drive the hips up to a straight line.
- **Category:** Main circuit
- **Type:** Free-weight hip extension
- **Targets:** Glutes, hamstrings
- **Prescription:** 4 × 810
## Setup
Sit on the floor with your upper back against a bench, the bar (padded)
across your hips, hands steadying it. Feet flat, hip-width, heels under
the knees.
## Execution
1. Brace, tuck the chin, and drive through the heels to lift the hips.
2. Stop when shoulders, hips and knees are level — a flat tabletop.
3. Squeeze the glutes at the top, then lower the hips under control.
## Cues
- Chin tucked, ribs down — the body hinges around the bench edge.
- Full lockout comes from the glutes, not from arching the back.
- Shins vertical at the top; adjust foot distance until they are.
## Common Mistakes
- Overarching the lower back instead of finishing with the glutes.
- Feet too far forward, turning it into a hamstring exercise.
- Cutting the range short at the top.
## Progression
Start with the bar alone to groove the pattern, then add plates; pause
reps at the top for extra glute work.
@@ -0,0 +1,38 @@
{
"name": "Hip Thrust",
"primary": 2,
"working": ["leg_r", "leg_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[50, 122], [88, 122]], "w": 9, "depth": 8},
{"kind": "line", "pts": [[68, 127], [68, 150]], "w": 5}
]},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 13}
],
"frames": [
{
"hold": 0.4, "tween": 0.8,
"root": {"pos": [150, 136], "pitch": -75},
"spine": [0, 6],
"neck": 42, "head": -4,
"shoulder_r": 4, "elbow_r": 8,
"shoulder_l": 4, "elbow_l": 8,
"hip_r": 78, "knee_r": 88, "ankle_r": 5,
"hip_l": 78, "knee_l": 88, "ankle_l": 5,
"pins": {"foot_r": [203, 147], "foot_l": [207, 149],
"hand_r": [124, 127], "hand_l": [128, 129]}
},
{
"hold": 0.9, "tween": 1.0,
"root": {"pos": [152, 114], "pitch": -89},
"spine": [0, 2],
"neck": 48, "head": -4,
"shoulder_r": 4, "elbow_r": 8,
"shoulder_l": 4, "elbow_l": 8,
"hip_r": 24, "knee_r": 92, "ankle_r": 5,
"hip_l": 24, "knee_l": 92, "ankle_l": 5,
"pins": {"foot_r": [203, 147], "foot_l": [207, 149],
"hand_r": [126, 111], "hand_l": [130, 113]}
}
]
}
@@ -0,0 +1,37 @@
# Incline Bench Press
The barbell press on the tilted bench — same press, aimed at the upper
chest.
- **Category:** Main circuit
- **Type:** Free-weight incline press
- **Targets:** Upper chest, front delts, triceps
- **Prescription:** 3 × 810
## Setup
Set the bench to a moderate incline (around 3045°). Lie back with the
bar over the eyes, shoulder blades set, feet planted.
## Execution
1. Lower the bar to the upper chest, just below the collarbones.
2. Touch lightly, keeping the forearms vertical.
3. Press straight up to lockout above the shoulders.
## Cues
- The steeper the bench, the more shoulder and less chest.
- Ribcage up, but hips stay on the pad.
- Bar path is a straight vertical line on the incline.
## Common Mistakes
- Sliding the bar path out over the belly.
- Overarching to turn it back into a flat press.
- Grip too wide for the shorter incline stroke.
## Progression
Work up in weight after the flat Bench Press, not before it; dumbbells
on the same bench trade load for range.
@@ -0,0 +1,40 @@
{
"name": "Incline Bench Press",
"primary": 1,
"camera": {"zoom": 0.85},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[142, 127], [86, 60]], "w": 9, "depth": 8},
{"kind": "line", "pts": [[140, 130], [166, 127]], "w": 8, "depth": 8},
{"kind": "line", "pts": [[152, 133], [152, 150]], "w": 5}
]},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 12}
],
"frames": [
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [148, 122], "pitch": -38},
"spine": [0, 0],
"neck": 18, "head": -4,
"shoulder_r": 30, "elbow_r": 115,
"shoulder_l": 30, "elbow_l": 115,
"hip_r": 85, "knee_r": 75, "ankle_r": 5,
"hip_l": 85, "knee_l": 75, "ankle_l": 5,
"pins": {"foot_r": [198, 148], "foot_l": [202, 150],
"hand_r": [106, 38], "hand_l": [110, 40]}
},
{
"hold": 0.4, "tween": 1.2,
"root": {"pos": [148, 122], "pitch": -38},
"spine": [0, 0],
"neck": 18, "head": -4,
"shoulder_r": 118, "elbow_r": 5,
"shoulder_l": 118, "elbow_l": 5,
"hip_r": 85, "knee_r": 75, "ankle_r": 5,
"hip_l": 85, "knee_l": 75, "ankle_l": 5,
"pins": {"foot_r": [198, 148], "foot_l": [202, 150],
"hand_r": [98, -3], "hand_l": [102, -1]}
}
]
}
@@ -0,0 +1,37 @@
# Lateral Raise
The side-delt isolation — raise light dumbbells out to the sides until
the arms are level with the shoulders.
- **Category:** Main circuit
- **Type:** Free-weight lateral raise (dumbbells)
- **Targets:** Side delts
- **Prescription:** 3 × 1215, light
## Setup
Stand tall with light dumbbells at your sides, a slight fixed bend in
the elbows, shoulders relaxed down.
## Execution
1. Raise both arms out to the sides, leading with the elbows.
2. Stop at shoulder height — arms level, pinkies no higher than thumbs.
3. Lower slowly back to the sides.
## Cues
- Pour-the-jug: elbows stay just above the hands.
- Shoulders stay down away from the ears — no shrugging.
- The weights float up; the trunk never sways.
## Common Mistakes
- Going too heavy and swinging the weights up.
- Shrugging the traps into the raise.
- Raising past shoulder height.
## Progression
More reps before more weight; slow negatives and pauses at the top beat
bigger dumbbells here.
@@ -0,0 +1,32 @@
{
"name": "Lateral Raise",
"primary": 2,
"camera": {"yaw": 90, "zoom": 0.7},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "dumbbell", "at": "hand_r"},
{"type": "dumbbell", "at": "hand_l"}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [160, 64]},
"spine": [0, 0],
"neck": 0, "head": 0,
"shoulder_r": {"flexion": 4, "abduction": 8}, "elbow_r": 10,
"shoulder_l": {"flexion": 4, "abduction": 8}, "elbow_l": 10,
"hip_r": {"flexion": 0, "abduction": 6}, "knee_r": 0,
"hip_l": {"flexion": 0, "abduction": 6}, "knee_l": 0
},
{
"hold": 0.5, "tween": 1.3,
"root": {"pos": [160, 64]},
"spine": [0, 0],
"neck": 0, "head": 0,
"shoulder_r": {"flexion": 4, "abduction": 88}, "elbow_r": 12,
"shoulder_l": {"flexion": 4, "abduction": 88}, "elbow_l": 12,
"hip_r": {"flexion": 0, "abduction": 6}, "knee_r": 0,
"hip_l": {"flexion": 0, "abduction": 6}, "knee_l": 0
}
]
}
@@ -0,0 +1,38 @@
# Lunge
The split-stance squat — drop the back knee toward the floor, then drive
back up through the front heel. Bodyweight first, dumbbells in hand later.
- **Category:** Main circuit
- **Type:** Split-stance squat (bodyweight or dumbbells)
- **Targets:** Quadriceps, glutes, balance
- **Prescription:** 3 × 810 per side
## Setup
Take a long step so both knees can bend to 90° — front shin vertical,
back heel up. Hips square to the front, hands at your sides or on hips.
## Execution
1. Lower straight down until the back knee hovers just above the floor.
2. The front knee stays over the mid-foot, torso upright.
3. Drive through the front heel to come back up. Finish the set, then
switch sides.
## Cues
- Down like an elevator, not forward like a slide.
- Front heel carries the work; the back leg balances.
- Squeeze the front glute to stand up.
## Common Mistakes
- Stance too short — the front knee shoots past the toes.
- Torso pitching forward on the way up.
- Pushing off the back foot instead of the front heel.
## Progression
Hold a dumbbell in each hand; step backward into each rep (reverse lunge)
or elevate the back foot for a split squat.
@@ -0,0 +1,30 @@
{
"name": "Lunge",
"primary": 2,
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l"],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [160, 68], "pitch": 6},
"spine": [0, 0],
"neck": 2, "head": -6,
"shoulder_r": 5, "elbow_r": 8,
"shoulder_l": 5, "elbow_l": 8,
"hip_r": 25, "knee_r": 10, "ankle_r": 5,
"hip_l": -25, "knee_l": 10, "ankle_l": -12,
"pins": {"foot_r": [196, 148], "foot_l": [124, 147]}
},
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [160, 106], "pitch": 8},
"spine": [0, 0],
"neck": 2, "head": -6,
"shoulder_r": 5, "elbow_r": 8,
"shoulder_l": 5, "elbow_l": 8,
"hip_r": 80, "knee_r": 95, "ankle_r": 15,
"hip_l": -12, "knee_l": 100, "ankle_l": -42,
"pins": {"foot_r": [196, 148], "foot_l": [124, 147]}
}
]
}
@@ -0,0 +1,40 @@
# Pec Deck
The machine chest fly — arms sweep together in front of the chest along
the machine's fixed arc.
- **Category:** Main circuit
- **Type:** Machine-based chest fly
- **Targets:** Chest, front delts
- **Prescription:** 4 × 10
## Setup
Adjust the seat so the handles sit at chest height with your upper arms
level. Back flat on the pad, feet planted, a soft bend fixed in the
elbows.
## Execution
1. Sweep both arms together in a wide arc until the handles meet in
front of the chest.
2. Squeeze the chest hard for a beat at the middle.
3. Open back up with control until you feel a full chest stretch.
## Cues
- Elbow angle never changes — the chest swings the arms.
- Shoulders stay back against the pad; they don't roll forward at the
squeeze.
- Slow the return; the stretch half of the rep counts.
## Common Mistakes
- Setting the seat so low the handles sit at the shoulders.
- Shoulders rounding forward to chase extra range.
- Letting the stack yank the arms open.
## Progression
Add a plate once every rep meets in the middle with a one-second
squeeze; the Dumbbell Fly trades the guided path for free control.
@@ -0,0 +1,37 @@
{
"name": "Pec Deck",
"primary": 2,
"camera": {"yaw": 90},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[160, 64], [160, 120]], "w": 16, "z": -14, "depth": 6},
{"kind": "line", "pts": [[135, 131], [185, 131]], "w": 10, "depth": 12},
{"kind": "line", "pts": [[160, 136], [160, 150]], "w": 6}
]},
{"type": "pad", "at": "hand_r", "angle": 90, "halfLen": 9, "w": 5},
{"type": "pad", "at": "hand_l", "angle": 90, "halfLen": 9, "w": 5}
],
"frames": [
{
"hold": 0.5, "tween": 1.1,
"root": {"pos": [160, 116]},
"spine": [0, 0],
"neck": 0,
"shoulder_r": {"flexion": 18, "abduction": 82}, "elbow_r": 25,
"shoulder_l": {"flexion": 18, "abduction": 82}, "elbow_l": 25,
"hip_r": 78, "knee_r": 62,
"hip_l": 78, "knee_l": 62
},
{
"hold": 0.5, "tween": 1.2,
"root": {"pos": [160, 116]},
"spine": [0, 0],
"neck": 0,
"shoulder_r": {"flexion": 86, "abduction": 6}, "elbow_r": 25,
"shoulder_l": {"flexion": 86, "abduction": 6}, "elbow_l": 25,
"hip_r": 78, "knee_r": 62,
"hip_l": 78, "knee_l": 62
}
]
}
@@ -0,0 +1,37 @@
# Pull-Up
The vertical pull — from a dead hang, pull the chin over the bar and
lower all the way back down.
- **Category:** Main circuit
- **Type:** Bodyweight vertical pull
- **Targets:** Lats, biceps, mid-back, grip
- **Prescription:** 3 × as many strict reps as possible
## Setup
Grip the bar just outside shoulder-width, palms away. Hang with straight
arms, shoulders active (pulled slightly down), knees bent or legs long.
## Execution
1. Drive the elbows down toward the ribs to pull the body up.
2. Chin clears the bar — chest toward it, not chin poking over.
3. Lower with control to a full dead hang every rep.
## Cues
- Start every rep from straight arms; half hangs don't count.
- Think "elbows to pockets", not "chin to bar".
- Quiet body — no swinging or kicking.
## Common Mistakes
- Kipping and swinging for extra reps.
- Stopping the descent halfway.
- Shrugging the shoulders to the ears at the top.
## Progression
Use the assisted pull-up machine or a band until 5 strict reps come
easily; then add reps, then hang weight from a belt.
@@ -0,0 +1,33 @@
{
"name": "Pull-Up",
"primary": 2,
"camera": {"zoom": 0.7},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 24}
],
"frames": [
{
"hold": 0.5, "tween": 1.0,
"root": {"pos": [156, 99]},
"spine": [0, 0],
"neck": 2, "head": -6,
"shoulder_r": 182, "elbow_r": 5,
"shoulder_l": 182, "elbow_l": 5,
"hip_r": 35, "knee_r": 120, "ankle_r": -30,
"hip_l": 35, "knee_l": 120, "ankle_l": -30,
"pins": {"hand_r": [154, -46], "hand_l": [158, -44]}
},
{
"hold": 0.4, "tween": 1.3,
"root": {"pos": [156, 67]},
"spine": [0, 0],
"neck": 4, "head": -10,
"shoulder_r": 150, "elbow_r": 125,
"shoulder_l": 150, "elbow_l": 125,
"hip_r": 35, "knee_r": 120, "ankle_r": -30,
"hip_l": 35, "knee_l": 120, "ankle_l": -30,
"pins": {"hand_r": [154, -46], "hand_l": [158, -44]}
}
]
}
@@ -0,0 +1,38 @@
# Push-Up
The bodyweight press — a moving plank: lower the chest to the floor and
press back up without the hips sagging.
- **Category:** Warm-up and main circuit
- **Type:** Bodyweight horizontal press
- **Targets:** Chest, front delts, triceps, trunk
- **Prescription:** 3 × 815
## Setup
Hands under the shoulders, legs long, toes tucked. Squeeze the glutes
and brace so the body is one straight line from head to heels.
## Execution
1. Bend the elbows about 45° from the body and lower the chest toward
the floor.
2. Stop a fist's height off the ground, body still one line.
3. Press the floor away to straight arms.
## Cues
- The plank never breaks — hips neither sag nor pike.
- Screw the hands into the floor to keep the elbows tracking.
- Chest leads the descent, not the chin or the hips.
## Common Mistakes
- Hips sagging into a banana shape.
- Flaring the elbows to 90°.
- Craning the neck at the floor.
## Progression
Start from an incline (hands on a bench) if reps stall; graduate to feet
elevated, then slow negatives.
@@ -0,0 +1,31 @@
{
"name": "Push-Up",
"primary": 1,
"working": ["arm_r", "arm_l"],
"frames": [
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [180, 115], "yaw": 180, "pitch": 73},
"spine": [0, 0],
"neck": 0, "head": -60,
"shoulder_r": 90, "elbow_r": 8,
"shoulder_l": 90, "elbow_l": 8,
"hip_r": 5, "knee_r": 3, "ankle_r": 25,
"hip_l": 5, "knee_l": 3, "ankle_l": 25,
"pins": {"hand_r": [97, 148], "hand_l": [101, 150],
"foot_r": [256, 143], "foot_l": [260, 145]}
},
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [180, 132], "yaw": 180, "pitch": 85},
"spine": [0, 0],
"neck": 0, "head": -55,
"shoulder_r": 60, "elbow_r": 110,
"shoulder_l": 60, "elbow_l": 110,
"hip_r": 5, "knee_r": 3, "ankle_r": 25,
"hip_l": 5, "knee_l": 3, "ankle_l": 25,
"pins": {"hand_r": [97, 148], "hand_l": [101, 150],
"foot_r": [256, 143], "foot_l": [260, 145]}
}
]
}
@@ -0,0 +1,38 @@
# Rear Delt Fly
The reverse pec deck — facing the pad, arms sweep from the front out
wide and back, hitting what pressing never touches.
- **Category:** Main circuit
- **Type:** Machine-based reverse fly
- **Targets:** Rear delts, mid-back
- **Prescription:** 3 × 1215, light
## Setup
Set the handles to the rear-fly position and sit facing the pad, chest
supported, handles together in front at shoulder height, arms long with
soft elbows.
## Execution
1. Sweep both arms out and back as far as the shoulder blades allow.
2. Pause with the arms wide, squeezing between the shoulder blades.
3. Return forward under control without the stack touching down.
## Cues
- Lead with the knuckles, arms long — it's a sweep, not a row.
- Chest glued to the pad; no leaning back for leverage.
- Light weight, full arc — momentum defeats the rear delts instantly.
## Common Mistakes
- Bending the elbows into a rowing motion.
- Loading too heavy and shortening the arc.
- Shrugging the traps into the sweep.
## Progression
More reps and a longer pause out wide before more weight; the Face Pull
covers the same territory from the cable stack.
@@ -0,0 +1,37 @@
{
"name": "Rear Delt Fly",
"primary": 2,
"camera": {"yaw": 270},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "line", "pts": [[160, 64], [160, 120]], "w": 16, "z": -14, "depth": 6},
{"kind": "line", "pts": [[135, 131], [185, 131]], "w": 10, "depth": 12},
{"kind": "line", "pts": [[160, 136], [160, 150]], "w": 6}
]},
{"type": "pad", "at": "hand_r", "angle": 90, "halfLen": 9, "w": 5},
{"type": "pad", "at": "hand_l", "angle": 90, "halfLen": 9, "w": 5}
],
"frames": [
{
"hold": 0.5, "tween": 1.1,
"root": {"pos": [160, 116]},
"spine": [0, 0],
"neck": 0,
"shoulder_r": {"flexion": 85, "abduction": 6}, "elbow_r": 15,
"shoulder_l": {"flexion": 85, "abduction": 6}, "elbow_l": 15,
"hip_r": 78, "knee_r": 62,
"hip_l": 78, "knee_l": 62
},
{
"hold": 0.5, "tween": 1.2,
"root": {"pos": [160, 116]},
"spine": [0, 0],
"neck": 0,
"shoulder_r": {"flexion": 12, "abduction": 84}, "elbow_r": 15,
"shoulder_l": {"flexion": 12, "abduction": 84}, "elbow_l": 15,
"hip_r": 78, "knee_r": 62,
"hip_l": 78, "knee_l": 62
}
]
}
@@ -0,0 +1,39 @@
# Romanian Deadlift
The stretch-focused hip hinge — push the hips back with soft knees until
the hamstrings stop you, then stand back up. Barbell or dumbbells.
- **Category:** Main circuit
- **Type:** Free-weight hinge (barbell or dumbbells)
- **Targets:** Hamstrings, glutes, spinal erectors
- **Prescription:** 3 × 810
## Setup
Stand tall holding the bar (or dumbbells) at the hips, feet hip-width,
knees unlocked. Set your shoulders back and brace.
## Execution
1. Push the hips straight back and let the weight slide down the thighs,
back flat, knees only slightly bent.
2. Stop when the hamstrings are fully stretched — usually just below the
knees — without the back rounding.
3. Drive the hips forward to stand tall again.
## Cues
- The hips travel backward, not down — this is not a squat.
- Weight stays close to the legs the whole rep.
- Feel the hamstrings load on the way down; that stretch is the exercise.
## Common Mistakes
- Bending the knees more as the weight lowers, turning it into a deadlift.
- Rounding the back to reach the floor — depth comes from the hips.
- Rushing the lowering phase.
## Progression
Add weight once the full stretch is reached with a flat back every rep;
single-leg RDLs for balance and asymmetry work.
@@ -0,0 +1,35 @@
{
"name": "Romanian Deadlift",
"primary": 1,
"camera": {"zoom": 0.7},
"working": ["leg_r", "leg_l", "spine"],
"props": [
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 26, "plateR": 13}
],
"frames": [
{
"hold": 0.4, "tween": 0.9,
"root": {"pos": [90, 92], "pitch": 68},
"spine": [0, -6],
"neck": 5, "head": -62,
"shoulder_r": 66, "elbow_r": 4,
"shoulder_l": 66, "elbow_l": 4,
"hip_r": 112, "knee_r": 12, "ankle_r": 12,
"hip_l": 112, "knee_l": 12, "ankle_l": 12,
"pins": {"foot_r": [158, 147], "foot_l": [162, 149],
"hand_r": [167, 120], "hand_l": [171, 122]}
},
{
"hold": 0.4, "tween": 1.4,
"root": {"pos": [158, 64], "pitch": 10},
"spine": [0, 0],
"neck": 2, "head": -8,
"shoulder_r": 10, "elbow_r": 3,
"shoulder_l": 10, "elbow_l": 3,
"hip_r": 8, "knee_r": 8, "ankle_r": 0,
"hip_l": 8, "knee_l": 8, "ankle_l": 0,
"pins": {"foot_r": [158, 147], "foot_l": [162, 149],
"hand_r": [169, 38], "hand_l": [173, 40]}
}
]
}
@@ -0,0 +1,39 @@
# Triceps Pushdown
The cable triceps staple — elbows pinned to the sides, push the bar from
chest height down to straight arms.
- **Category:** Main circuit
- **Type:** Machine-based cable elbow extension
- **Targets:** Triceps
- **Prescription:** 3 × 1012
## Setup
Stand at the high pulley with a bar or rope attachment, feet under the
hips, slight forward lean. Grip with the elbows bent past 90° and tucked
to the ribs.
## Execution
1. Push the handle down until the arms are completely straight.
2. Squeeze the triceps at the bottom for a beat.
3. Let the forearms ride back up until they pass 90°, elbows never
leaving the sides.
## Cues
- Elbows are bolted to the ribs — only the forearms move.
- Stand tall-ish; don't lean your bodyweight onto the bar.
- Full lockout every rep; the last few degrees are the exercise.
## Common Mistakes
- Elbows drifting forward and up on the way down.
- Shoulders and back pressing the weight instead of the triceps.
- Cutting the top of the rep short.
## Progression
Add a plate when every rep locks out with quiet elbows; a rope
attachment adds a harder finish at the bottom.
@@ -0,0 +1,39 @@
{
"name": "Triceps Pushdown",
"primary": 2,
"camera": {"zoom": 0.7},
"working": ["arm_r", "arm_l"],
"props": [
{"type": "scene", "shapes": [
{"kind": "circle", "c": [186, -58], "r": 4, "fill": true, "color": "prop"}
]},
{"type": "cable", "from": [186, -58], "to": ["hand_r", "hand_l"], "w": 3},
{"type": "bar", "at": ["hand_r", "hand_l"], "halfLen": 10}
],
"frames": [
{
"hold": 0.4, "tween": 1.0,
"root": {"pos": [150, 66], "pitch": 8},
"spine": [0, 2],
"neck": 6, "head": -8,
"shoulder_r": 15, "elbow_r": 130,
"shoulder_l": 15, "elbow_l": 130,
"hip_r": 6, "knee_r": 5, "ankle_r": 0,
"hip_l": 6, "knee_l": 5, "ankle_l": 0,
"pins": {"foot_r": [146, 148], "foot_l": [150, 150],
"hand_r": [172, -10], "hand_l": [176, -8]}
},
{
"hold": 0.4, "tween": 1.1,
"root": {"pos": [150, 66], "pitch": 8},
"spine": [0, 2],
"neck": 6, "head": -8,
"shoulder_r": 8, "elbow_r": 10,
"shoulder_l": 8, "elbow_l": 10,
"hip_r": 6, "knee_r": 5, "ankle_r": 0,
"hip_l": 6, "knee_l": 5, "ankle_l": 0,
"pins": {"foot_r": [146, 148], "foot_l": [150, 150],
"hand_r": [168, 40], "hand_l": [172, 42]}
}
]
}
+4 -3
View File
@@ -21,8 +21,9 @@ struct ExerciseMotionTests {
}
@Test func exerciseWithoutBundledMotionLoadsNothing() {
#expect(ExerciseMotionLibrary.resources(for: "Bench Press") == nil)
#expect(FigureAnimation(exerciseName: "Bench Press") == nil)
// Cardio equipment is a permanent library exclusion (see COVERAGE.md).
#expect(ExerciseMotionLibrary.resources(for: "Treadmill") == nil)
#expect(FigureAnimation(exerciseName: "Treadmill") == nil)
}
/// Resolving Bird Dog's first key frame must reproduce the reference IK: both
@@ -130,7 +131,7 @@ struct ExerciseMotionTests {
bundle.url(forResource: "figure-fixtures", withExtension: "json"),
"figure-fixtures.json must be bundled as a WorkoutsTests resource (see project.yml)")
let fixtures = try JSONDecoder().decode(FigureFixtures.self, from: Data(contentsOf: url))
#expect(fixtures.exercises.count == 22)
#expect(fixtures.exercises.count == 47)
for exercise in fixtures.exercises {
let resources = try #require(ExerciseMotionLibrary.resources(for: exercise.name),
File diff suppressed because one or more lines are too long