|
| 1 | +# WOD Generation Playbook |
| 2 | + |
| 3 | +This document is the single source of truth for generating metcons and programming sessions. Read this before generating any WODs. For detailed schema and scaling rules, see `spec/programming.md`. |
| 4 | + |
| 5 | +## Quick Start Checklist |
| 6 | + |
| 7 | +When asked to generate WODs or programming: |
| 8 | + |
| 9 | +1. **Check existing state** (see Step 1 below) |
| 10 | +2. **Confirm scope with user** (overwrite, fill gaps, or new months) |
| 11 | +3. **Design metcons first** (the building blocks) |
| 12 | +4. **Write sessions per week** (the schedule that uses metcons) |
| 13 | +5. **Validate everything** |
| 14 | +6. **Commit, PR, merge to main/test/prod** |
| 15 | + |
| 16 | +## File Locations |
| 17 | + |
| 18 | +| File | Purpose | |
| 19 | +|------|---------| |
| 20 | +| `data/metcons.json` | All metcon definitions (the WOD library) | |
| 21 | +| `data/sessions.json` | Daily programming sessions referencing metcons by code | |
| 22 | +| `spec/programming.md` | Full schema, scaling rules, session structure | |
| 23 | +| `scripts/audit-metcons.mjs` | Automated scaling integrity validation | |
| 24 | +| `scripts/validate-data.mjs` | General data validation (levels, benchmarks, etc.) | |
| 25 | +| `website/app/programming/page.tsx` | Renderer (reads from public/data/) | |
| 26 | + |
| 27 | +## Step 1: Check Existing State |
| 28 | + |
| 29 | +Always run this before generating anything: |
| 30 | + |
| 31 | +```bash |
| 32 | +node -e " |
| 33 | +const m = require('./data/metcons.json'); |
| 34 | +const s = require('./data/sessions.json'); |
| 35 | +console.log('Metcons:', m.metcons.length, '(codes:', m.metcons[0]?.code, 'to', m.metcons[m.metcons.length-1]?.code + ')'); |
| 36 | +console.log('Sessions:', s.sessions.length); |
| 37 | +const dates = s.sessions.map(x => x.date).sort(); |
| 38 | +console.log('Date range:', dates[0], 'to', dates[dates.length-1]); |
| 39 | +const months = [...new Set(dates.map(d => d.slice(0,7)))]; |
| 40 | +console.log('Months covered:', months.join(', ')); |
| 41 | +" |
| 42 | +``` |
| 43 | + |
| 44 | +Report findings to the user before proceeding. Ask whether to: |
| 45 | +- **Overwrite** existing months (replace sessions, keep or replace metcons) |
| 46 | +- **Fill gaps** (add sessions for missing days in existing months) |
| 47 | +- **Extend** (add new months only, keeping everything existing) |
| 48 | + |
| 49 | +## Step 2: Design Metcons |
| 50 | + |
| 51 | +Metcons are the building blocks. Create them before sessions. |
| 52 | + |
| 53 | +### How Many |
| 54 | + |
| 55 | +A typical month needs ~22 sessions (5 days/week x 4.5 weeks). Not every session needs a unique metcon. Plan for: |
| 56 | +- ~10-12 new metcons per month |
| 57 | +- Reuse 6-8 existing metcons as retests for progress tracking |
| 58 | +- Target 20 total metcons per month of programming |
| 59 | + |
| 60 | +### Naming Convention |
| 61 | + |
| 62 | +Format: `OP-XXX "Descriptive Noun"` |
| 63 | + |
| 64 | +**Descriptive words** (first word signals the workout character): |
| 65 | +- Quick = short sprint, sub-5 min |
| 66 | +- Long = 20+ min grind |
| 67 | +- Heavy = barbell-forward |
| 68 | +- Light = low/no weight, high rep speed |
| 69 | +- Spicy = high intensity |
| 70 | +- Dark = gymnastics-heavy |
| 71 | +- Thick = grinding, high volume |
| 72 | +- Sharp = interval-based |
| 73 | +- Sweet = balanced, approachable |
| 74 | +- Loud = big movements, explosive |
| 75 | + |
| 76 | +**Noun** = concrete, visual, 1-2 syllables. No repeats across the library. |
| 77 | + |
| 78 | +### Load Calibration |
| 79 | + |
| 80 | +All Rx loads are derived from benchmark 1RM data. The percentage depends on rep volume: |
| 81 | + |
| 82 | +| Rep Volume | % of 1RM | Example | |
| 83 | +|-----------|---------|---------| |
| 84 | +| Low (3-5 reps, EMOM) | 50-55% | Squat Clean 4r EMOM @ 80/55 | |
| 85 | +| Moderate (8-12 reps) | 40-50% | HPC 10r @ 70/50 | |
| 86 | +| High (15+ reps or 21-15-9) | 35-44% | Thruster 15r @ 55/40, DL 21-15-9 @ 100/70 | |
| 87 | +| Long AMRAP (6-10 reps, 20+ min) | 44-50% | PS 6r AMRAP @ 55/40 | |
| 88 | + |
| 89 | +**Reference 1RM benchmarks (Rx level):** |
| 90 | + |
| 91 | +| Movement | Male 1RM | Female 1RM | |
| 92 | +|----------|---------|-----------| |
| 93 | +| Back Squat | 180 | 120 | |
| 94 | +| Front Squat | 153 | 102 | |
| 95 | +| Deadlift | 240 | 170 | |
| 96 | +| Strict Press | 95 | 57 | |
| 97 | +| Power Clean | 135 | 95 | |
| 98 | +| Snatch | 125 | 80 | |
| 99 | +| Clean and Jerk | 150 | 105 | |
| 100 | + |
| 101 | +### Equipment Rules |
| 102 | + |
| 103 | +- **Barbell**: All loads in multiples of 5 kg. Never use imperial-converted numbers (43, 61, etc.) |
| 104 | +- **Kettlebell**: Standard sizes only: 6, 8, 12, 16, 20, 24, 28, 32 kg. Rx male 32, female 24. All KB swings are Russian (to eye level). Never American. |
| 105 | +- **Wall Ball**: Standard sizes only: 3, 4, 6, 9 kg. Rx male 9, female 6. |
| 106 | +- **Box**: Heights: 30, 40, 50, 60 cm. Rx male 60, female 50. |
| 107 | + |
| 108 | +### Scaling Rules |
| 109 | + |
| 110 | +Every scaled movement MUST have all 6 non-Rx levels. Use `{}` for "same as Rx". |
| 111 | + |
| 112 | +**Scaling chains** (hardest to easiest): |
| 113 | +- Pulling: Bar Muscle-up > C2B > Pull-up > Jumping Pull-up > Ring Row |
| 114 | +- Core: TTB > Hanging Knee Raise > Sit-up |
| 115 | +- Squatting: Pistol > Pistol to Box > Air Squat |
| 116 | +- Rope: Double-Under > Single-Under |
| 117 | +- Box: Box Jump > Box Step-up |
| 118 | +- Burpee: Bar-facing Burpee > Burpee to Target > Burpee > Bodybuilder |
| 119 | +- Lunge: Jumping Lunge > Walking Lunge |
| 120 | +- Press: HSPU > Pike Push-up > Push-up > Knee Push-up |
| 121 | +- Olympic: Squat Clean > Power Clean; Power Snatch > Power Clean; C&J > PC & Push Press |
| 122 | + |
| 123 | +**Integrity rules:** |
| 124 | +1. No placeholders ("-", "N/A", empty strings) |
| 125 | +2. Monotonic difficulty (movement subs only get easier going down) |
| 126 | +3. Monotonic load (same movement, load only decreases going down) |
| 127 | +4. Monotonic reps (same movement, reps only decrease going down) |
| 128 | +5. Reps MAY increase when subbing to an easier movement (to preserve stimulus) |
| 129 | + |
| 130 | +### Writing Metcons Incrementally |
| 131 | + |
| 132 | +To avoid output token limits, add metcons in batches of 2-3 using the Edit tool. Insert before the closing `]}` of metcons.json. |
| 133 | + |
| 134 | +**Do NOT rewrite the entire file with Write.** Use Edit to append. |
| 135 | + |
| 136 | +## Step 3: Design Sessions |
| 137 | + |
| 138 | +### Weekly Template |
| 139 | + |
| 140 | +| Day | Focus | Strength | Metcon Style | |
| 141 | +|-----|-------|----------|-------------| |
| 142 | +| Monday | Heavy lower body | Back Squat / Front Squat + accessory pull | Sprint or interval (TC 8-16) | |
| 143 | +| Tuesday | Engine / capacity | Skill work (HS, DU) 10 min | Long AMRAP or moderate effort (TC 20-30) | |
| 144 | +| Wednesday | Press / upper body | Strict Press / Push Press + Rows | Moderate metcon (TC 16-18) | |
| 145 | +| Friday | Pull / posterior chain | Deadlift (build heavy) | Grind (TC 18-22) | |
| 146 | +| Saturday | Olympic lifting | Power Clean / Snatch E90S skill | Weekend grinder (TC 20-25) | |
| 147 | + |
| 148 | +### Time Budget |
| 149 | + |
| 150 | +``` |
| 151 | +estimatedMinutes = warmup + strength + metcon.timeCap + accessory |
| 152 | +``` |
| 153 | + |
| 154 | +| Part | Max | Typical | |
| 155 | +|------|-----|---------| |
| 156 | +| Warmup | 10 min | 8-10 | |
| 157 | +| Strength | 20 min | 10-18 | |
| 158 | +| Metcon | 40 min | 8-30 | |
| 159 | +| Accessory | 15 min | 5-12 | |
| 160 | +| **Session total** | | **45-58 min** | |
| 161 | + |
| 162 | +**Constraints:** |
| 163 | +- If metcon TC > 25 min, strength must be short (skill work) or null |
| 164 | +- If metcon TC = 40 min, strength must be null |
| 165 | +- estimatedMinutes MUST exactly equal the sum of parts |
| 166 | + |
| 167 | +### Retest Strategy |
| 168 | + |
| 169 | +In a 4-week cycle: |
| 170 | +- Weeks 1-2: Introduce new metcons |
| 171 | +- Weeks 3-4: Retest key metcons from weeks 1-2 (and from previous months) for progress tracking |
| 172 | +- Aim for 6-8 retests per month |
| 173 | + |
| 174 | +### Writing Sessions Incrementally |
| 175 | + |
| 176 | +Sessions can be written per week. Write the full sessions.json using the Write tool (replacing previous content), or build it up incrementally with Edit. |
| 177 | + |
| 178 | +## Step 4: Validate |
| 179 | + |
| 180 | +Run all three validations: |
| 181 | + |
| 182 | +```bash |
| 183 | +# 1. Metcon scaling integrity (loads, levels, chains) |
| 184 | +node scripts/audit-metcons.mjs |
| 185 | + |
| 186 | +# 2. General data validation (levels, benchmarks, sources) |
| 187 | +node scripts/validate-data.mjs |
| 188 | + |
| 189 | +# 3. Session time budget verification |
| 190 | +node -e " |
| 191 | +const m = require('./data/metcons.json'); |
| 192 | +const s = require('./data/sessions.json'); |
| 193 | +for (const sess of s.sessions) { |
| 194 | + const w = sess.warmup?.durationMinutes || 0; |
| 195 | + const st = sess.strength?.durationMinutes || 0; |
| 196 | + const mc = m.metcons.find(x => x.code === sess.metcon); |
| 197 | + const tc = mc ? mc.timeCap : 0; |
| 198 | + const a = sess.accessory?.durationMinutes || 0; |
| 199 | + const sum = w + st + tc + a; |
| 200 | + const ok = sum === sess.estimatedMinutes ? 'ok' : 'MISMATCH ' + sum; |
| 201 | + console.log(sess.date, sess.metcon, 'est:' + sess.estimatedMinutes, ok); |
| 202 | +} |
| 203 | +" |
| 204 | +``` |
| 205 | + |
| 206 | +Then copy data to public: |
| 207 | + |
| 208 | +```bash |
| 209 | +cd website && node scripts/copy-data.mjs |
| 210 | +``` |
| 211 | + |
| 212 | +## Step 5: Ship |
| 213 | + |
| 214 | +```bash |
| 215 | +# Create branch and commit |
| 216 | +git checkout -b feature/MONTH-programming |
| 217 | +git add data/metcons.json data/sessions.json website/public/data/metcons.json website/public/data/sessions.json website/public/data/openprogression.json |
| 218 | +git commit -m "Add MONTH programming: N new metcons + N sessions" |
| 219 | + |
| 220 | +# Push, PR, merge |
| 221 | +git push -u origin feature/MONTH-programming |
| 222 | +gh pr create --title "Add MONTH programming" --body "..." |
| 223 | +gh pr merge N --merge |
| 224 | + |
| 225 | +# Sync all branches |
| 226 | +git checkout main && git pull |
| 227 | +git checkout test && git merge main --ff-only && git push |
| 228 | +git checkout prod && git merge main --ff-only && git push |
| 229 | +git checkout main |
| 230 | + |
| 231 | +# Release |
| 232 | +gh release create vX.Y.Z --title "vX.Y.Z - MONTH Programming" --notes "..." |
| 233 | +``` |
| 234 | + |
| 235 | +## Things to Never Do |
| 236 | + |
| 237 | +- Never use em dashes anywhere |
| 238 | +- Never use imperial units or imperial-converted loads (43, 61, 48, etc.) |
| 239 | +- Never use "American Kettlebell Swing" |
| 240 | +- Never use "Kipping Pull-up" as a scaling sub (Pull-up includes kipping) |
| 241 | +- Never use "Good mornings with bar" (complex exercise, unsuited below Advanced) |
| 242 | +- Never skip levels in scaling (all 6 must be present if scaling exists) |
| 243 | +- Never use "Up-Down" (use "Bodybuilder" instead) |
| 244 | +- Never create sessions where estimatedMinutes does not equal the sum of parts |
0 commit comments