Add Foundation Milestones and Movement Progressions for pre-Beginner …#1
Conversation
OneMuppet
left a comment
There was a problem hiding this comment.
PR Review: Foundation Milestones & Movement Progressions
Thanks for putting this together. The research is thorough, the spec is well-written, and this addresses a real gap in the standard. People at the bottom of Beginner (never trained, returning from injury) currently get zero feedback for months -- this fixes that.
Below is a full review with specific issues and solutions. Addressing these will get the PR to merge.
1. Backwards Compatibility (the big-picture concern)
OpenProgression is a standard, not just a codebase. Apps, gym software, and coaching platforms are already consuming our data. Every change needs to be non-breaking by default. This PR is already designed to be additive (new files, no changes to existing schemas), which is the right approach. But there are a few things to tighten up:
The "7 levels, 8 categories" contract
Our tagline, README, website, and marketing all say "7 levels, 8 categories." Foundation Milestones introduce what looks like 3 new levels (F1, F2, F3) below Beginner. Even though the spec correctly states "milestones are NOT levels," consumers and users will inevitably ask: "Is this 10 levels now?"
Solution: The spec and README text should be very explicit that:
- The 7-level system is unchanged. F1/F2/F3 are not levels.
data/levels.jsonis unchanged. No new level IDs, no new percentile ranges.- Milestones live in a completely separate data file (
milestones.json) with a different schema. - Apps that don't implement milestones continue to work with zero changes.
Suggested wording for the README section:
Foundation Milestones are not levels -- they do not change the 7-level system. They are optional pre-level progress markers in a separate data file (
data/milestones.json). Existing implementations that only readdata/levels.jsonanddata/benchmarks/*.jsonare unaffected.
Versioning strategy for the standard
This PR is a good moment to establish how OP handles additive extensions. We should document (maybe in CONTRIBUTING.md or a new spec/versioning.md) something like:
- Patch (1.0.x): Bug fixes, typo corrections, source citation updates
- Minor (1.x.0): Additive extensions (new data files, new optional fields). Existing consumers unaffected.
- Major (x.0.0): Breaking changes to existing schemas, level definitions, or benchmark values
This PR would be a minor version bump (1.0.0 -> 1.1.0) since it adds new files but doesn't modify existing ones. The version fields in milestones.json and progressions.json are currently "1.0.0" -- consider whether these should match the standard's version or have their own versioning. I'd suggest they track the standard version (so "1.1.0" when this ships).
Action: Add a note in the PR about which version this targets. We can handle the versioning spec separately, but the PR should at minimum bump version fields appropriately.
2. README Merge Conflict (will break merge)
The PR's README changes are based on an older version of main. Since the PR was opened, we've added deep links to section headers, reformatted the roadmap with checkboxes, and added links throughout.
What will conflict
The roadmap section has diverged significantly:
PR expects:
## Roadmap
+- **Movement progressions & foundation milestones** -- ...
- **Age-adjusted benchmarks** -- Current standards target ~18-40...Main currently has:
## Roadmap
- [x] **[Level Calculator](https://openprogression.org/calculator)** -- ...
- [x] **[Scaled Programming](https://openprogression.org/programming)** -- ...
- [ ] **Age-adjusted benchmarks** -- Current standards target ~18-40...The repository structure tree has also changed slightly.
Solution
Rebase the branch onto current main:
git fetch origin
git rebase origin/mainThen resolve the README conflicts:
- Keep the current main's deep-linked headers and checkbox roadmap format
- Add the Foundation Milestones section and progression files to the existing structure
- The new roadmap item should follow the checkbox pattern:
- [ ] **Movement progressions & foundation milestones** -- ...
Actually -- since this PR adds milestones and progressions, the roadmap item should be - [x] (checked) once merged.
3. Em Dashes -- Replace Throughout
We don't use em dashes (—) in this project. Use -- or rephrase instead.
Affected files:
- README.md: F1 description ("no gym needed"), milestone explanation, roadmap item
- data/milestones.json: the
descriptionfield at the top level - spec/levels.md: multiple lines in the Foundation Milestones section
- spec/progressions.md: throughout (many instances)
Solution
Run a find-and-replace across the PR's changed files:
# Replace all em dashes with --
sed -i '' 's/—/--/g' README.md spec/levels.md spec/progressions.md data/milestones.jsonVerify the replacements read naturally. Some may benefit from rephrasing instead of a straight swap.
4. Equipment Tag Inconsistency
Two dumbbell exercises are tagged "equipment": "kettlebell":
db_press(Dumbbell Shoulder Press) inprogressions.json, strict_press chain step 5db_bench_press(Dumbbell Bench Press) inprogressions.json, bench_press chain step 5
The spec's equipment tag table defines kettlebell as "Kettlebell or dumbbell," but for a machine-readable standard, having "equipment": "kettlebell" on a movement named "Dumbbell Bench Press" will confuse API consumers and break any filtering logic that takes the tags literally.
Solution (pick one)
Option A (recommended): Add a "dumbbell" equipment tag alongside "kettlebell":
| kettlebell | Kettlebell | Maybe |
| dumbbell | Dumbbell | Maybe |
Then tag the two dumbbell exercises with "equipment": "dumbbell".
Option B: Rename the tag to "free_weight" to cover both kettlebells and dumbbells. Less precise but avoids the proliferation of similar tags.
Option C: Keep as-is but rename the tag definition in the spec from "Kettlebell" to "Kettlebell / Dumbbell" and add a note. Least disruptive but still semantically confusing in the data.
5. Category Mapping: Farmer's Carry as "Gymnastics"
In milestones.json, the Farmer's Carry is categorized under "gymnastics". In the existing OP standard, gymnastics = pull-ups, HSPU, muscle-ups, toes-to-bar. Farmer's carry is a loaded carry / grip exercise.
I understand the reasoning -- it's in the pull-up progression chain (gymnastics target) and serves as an equipment-free grip strength proxy. But a consumer filtering milestones by category would see "gymnastics: carry heavy bags for 30 seconds" and be confused.
Solution
Either:
- Move it to
"bodyweight"-- it's a body-in-space loaded movement, closer to bodyweight than gymnastics - Add an explicit note in the milestone data or spec explaining why it's mapped to gymnastics (grip strength prerequisite for pull-up chain)
- Use a
"progressionCategory"field separate from"category"to distinguish "which OP category this feeds into" from "what type of exercise this is"
The simplest fix is moving it to "bodyweight" and adding a comment in the spec about the relationship to the pull-up chain.
6. Missing Categories in Milestones -- Needs Explicit Documentation
Foundation milestones cover 5-6 of the 8 categories (Squatting, Pressing, Pulling, Bodyweight, Monostructural, and arguably Gymnastics via grip). Olympic Lifting and Endurance are absent entirely.
This is almost certainly intentional (you can't clean without a barbell; metcon benchmarks like Fran require multiple prerequisite skills). But the spec doesn't say this, which means every reader will wonder "is this incomplete?"
Solution
Add a short section to spec/progressions.md under the milestone definitions:
Categories not covered by Foundation Milestones
Olympic Lifting and Endurance are intentionally excluded. Olympic lifts require barbell proficiency (which starts developing at F3 / post-F3). Endurance benchmarks (Fran, Grace, Murph) are multi-skill metcons that require competency in several movement patterns first. Athletes at the Foundation level should focus on building the movement patterns that these categories eventually require.
This turns a "gap" into a documented design decision.
7. The "either" Criteria Type -- New Schema Pattern
F3's "Dead Hang OR Farmer's Carry" requirement introduces a new criteria type ("type": "either") that doesn't exist anywhere else in the OP data model:
"criteria": {
"type": "either",
"options": [
{ "movement": "dead_hang_30s", "type": "time", "target": 30, "unit": "seconds" },
{ "movement": "farmers_carry_60s", "type": "time", "target": 60, "unit": "seconds" }
]
}This is a nice pattern for accessibility (home vs. gym), but it's a schema extension that consumers need to handle. Any app parsing milestone requirements will encounter a criteria type it hasn't seen before.
Solution
- Document the
"either"type in the spec's data format section -- what it means, how to evaluate it (pass if ANY option passes), and the schema shape - Add validation for the
"either"type invalidate-data.mjs-- currently the validator checkstypeof req.criteria === "object"but doesn't validate the"either"shape specifically - Consider whether this pattern might appear in future benchmark data too, and design the schema accordingly
8. Missing Source Citation
The spec text references Murphy et al. (2023) regarding Couch to 5K dropout rates ("73% non-completion rate with 19% injury incidence") in spec/progressions.md, but this source is not in data/sources.json.
Solution
Add the Murphy reference to sources.json:
{
"id": "murphy_2023",
"citation": "Murphy, M.H., et al. (2023). [full citation for the C25K dropout study]",
"type": "peer_reviewed",
"notes": "Couch to 5K completion and injury rates"
}Or if this was a secondary reference not critical to OP's data, remove the specific stats from the spec text.
9. Duplicated Progression Steps
Steps 1-4 (wall push-up -> incline push-up -> knee push-up -> full push-up) are fully duplicated across three chains: push_up, strict_press, and bench_press. The sharedSteps and sharedUpTo fields document the relationship, which is good.
This isn't a blocker, but be aware that any future update to (say) the wall push-up criteria would need to be applied to 3 places. The duplication is fine for v1 simplicity -- just flag it for future consideration.
No action needed now, but a future improvement could normalize this by having shared chains reference step data from a single source.
Summary: What's needed to merge
| # | Issue | Severity | Action |
|---|---|---|---|
| 1 | Backwards compatibility language | Medium | Strengthen "not levels" messaging, add versioning note |
| 2 | README merge conflict | Blocker | Rebase onto current main, resolve conflicts |
| 3 | Em dashes | Medium | Find-and-replace — with -- across all PR files |
| 4 | Equipment tags | Low | Add "dumbbell" tag or rename to "free_weight" |
| 5 | Farmer's carry category | Low | Move to "bodyweight" or document the gymnastics mapping |
| 6 | Missing category documentation | Low | Add explicit note about Olympic Lifting / Endurance exclusion |
| 7 | "either" criteria type |
Medium | Document in spec, add validation |
| 8 | Missing Murphy source | Low | Add to sources.json or remove stats |
| 9 | Duplicated steps | Info | No action needed now |
Items 2 and 3 are the hard requirements. The rest are recommendations that would strengthen the PR but aren't merge blockers.
Great work on this -- the research depth and spec quality are exactly what the standard needs. Looking forward to the next revision.
|
One more thing -- we just added Worth reading before the next revision, especially:
File: |
…athletes Extend the standard downward to serve untrained and deconditioned populations. Adds three milestones (F1 Foundation, F2 Moving, F3 Ready) as optional pre-level markers, and formalized movement regression chains for each benchmark movement. New files: spec/progressions.md, data/progressions.json, data/milestones.json Updated: README, levels spec, sources, and validation script.
…ibility Replace dead hang with farmer's carry in F1 (no pull-up bar needed), add box squat step, McGill Big 3 core exercises, band rows for home pulling, walk 10min as running entry point, and 4 new research sources.
- Replace em dashes with -- across spec and data files - Fix equipment tags: kettlebell -> free_weight for dumbbell exercises - Fix Farmer's Carry category: gymnastics -> monostructural - Remove Murphy et al. citation, soften C25K dropout claims - Document "either" criteria type in spec and validate in script - Strengthen "not levels" messaging with explicit compatibility note - Add rationale for excluding Olympic Lifting and Endurance from milestones
77f8332 to
e12a884
Compare
Per spec/versioning.md, milestones.json and progressions.json are extensions introduced in 1.1.0. Update version fields and validator to reflect this.
|
Addressed all review feedback in e12a884 + bumped extension versions in
Version bump -- Noticed the new spec/versioning.md on main, which lists Validator passes all 1232 checks. |
Follow-up Review (after commits b4bb428, e12a884, a4efcaf)Great work addressing the feedback. Almost everything from the first review is resolved. Here's the status and one remaining issue. Resolved
Remaining: Spec vs Data Category Mismatch for Farmer's CarryThe data in F1 -- spec says one thing, data says another:
{
"movement": "farmers_carry_30s",
"category": "monostructural",
...
}F3 -- same mismatch:
{
"movement": "dead_hang_or_carry",
"category": "monostructural",
...
}Which category should it be?Beyond just syncing spec and data, there's a design question here. With farmer's carry as F1:
F3:
The milestones are supposed to follow the weakest-link principle and test across multiple categories. Having 2 monostructural items and 0 gymnastics in both F1 and F3 weakens that cross-category coverage. Recommended fixOption A (recommended): Revert to The original Changes needed:
Option B: Move to Farmer's carry as bodyweight is defensible (loaded carry, body moving through space). This keeps gymnastics empty but at least doesn't double up on monostructural. Dead hang is a stretch for bodyweight though. Changes needed:
Option C: Keep as Least recommended. Fixes the mismatch but weakens cross-category coverage. Changes needed:
Whichever option you pick, the rule is: spec and data must say the same thing. The validator checks categories against Once this is resolved, the PR is ready to merge. |
Farmer's carry and dead hang feed the pull-up progression chain (gymnastics). Keeping them as gymnastics preserves cross-category coverage in milestones and matches the spec tables.
OneMuppet
left a comment
There was a problem hiding this comment.
All review items resolved. Spec and data are in sync, category coverage is solid, versioning is correct at 1.1.0, and the extension is cleanly additive with no impact on core data files.
Good to merge.
Closes #1
https://github.com/SnowOak-Ventures/crossfit-maskineriet-marketing/issues/1