|
| 1 | +# OpenProgression Versioning |
| 2 | + |
| 3 | +**Version:** 1.0.0 |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +OpenProgression is a standard, not just a codebase. Gym software, coaching platforms, and developer tools consume OP data and depend on its structure being stable. This document defines how the standard evolves without breaking existing consumers. |
| 8 | + |
| 9 | +The core principle: **additive changes are free, breaking changes require a major version bump and a migration path.** |
| 10 | + |
| 11 | +## Version Format |
| 12 | + |
| 13 | +OP follows [Semantic Versioning](https://semver.org/) applied to a data standard: |
| 14 | + |
| 15 | +``` |
| 16 | +MAJOR.MINOR.PATCH |
| 17 | +``` |
| 18 | + |
| 19 | +- **MAJOR** -- Breaking changes to existing schemas, level definitions, or category structure |
| 20 | +- **MINOR** -- Additive extensions (new data files, new optional fields, new movements) |
| 21 | +- **PATCH** -- Corrections (benchmark value adjustments, typo fixes, source citation updates) |
| 22 | + |
| 23 | +The version number applies to the standard as a whole. Individual data files carry a `"version"` field that tracks the standard version they conform to. |
| 24 | + |
| 25 | +## The Stability Contract |
| 26 | + |
| 27 | +These are the things consumers can depend on. Breaking any of these requires a major version bump. |
| 28 | + |
| 29 | +### Core guarantees (MAJOR version) |
| 30 | + |
| 31 | +| Guarantee | What it means | |
| 32 | +|-----------|---------------| |
| 33 | +| **7 levels** | The level IDs, names, numbers (1-7), and percentile ranges in `data/levels.json` do not change | |
| 34 | +| **8 categories** | The category IDs and names in `data/categories.json` do not change | |
| 35 | +| **Benchmark schema** | The shape of `data/benchmarks/*.json` does not change -- `standards`, `bwMultiplier`, `sources` fields remain stable | |
| 36 | +| **Level calculation** | The weakest-link principle and the method for determining an athlete's level do not change | |
| 37 | +| **Gender differentiation** | All benchmarks provide both `male` and `female` values | |
| 38 | +| **Source traceability** | Every benchmark value traces to a citable source in `data/sources.json` | |
| 39 | + |
| 40 | +An application that reads `data/levels.json`, `data/categories.json`, and `data/benchmarks/*.json` will continue to work across all minor and patch releases without code changes. |
| 41 | + |
| 42 | +### Extension guarantees (MINOR version) |
| 43 | + |
| 44 | +New data files, new optional fields, and new spec documents are additive. They never modify the schema of existing files. Consumers that don't use the new data are unaffected. |
| 45 | + |
| 46 | +Examples of minor changes: |
| 47 | +- Adding a new data file (e.g., `data/milestones.json`, `data/progressions.json`) |
| 48 | +- Adding a new benchmark movement to an existing category file |
| 49 | +- Adding optional fields to existing schemas (fields that weren't there before) |
| 50 | +- Adding new spec documents (e.g., `spec/progressions.md`) |
| 51 | +- Adding new source citations to `data/sources.json` |
| 52 | + |
| 53 | +### Correction guarantees (PATCH version) |
| 54 | + |
| 55 | +Benchmark values can be adjusted within a patch release when evidence shows a number is wrong. These are not treated as breaking changes because the standard's purpose is accuracy -- a benchmark that's provably off should be corrected. |
| 56 | + |
| 57 | +Examples of patch changes: |
| 58 | +- Adjusting a benchmark value based on new research or community review |
| 59 | +- Fixing a typo in a description or citation |
| 60 | +- Correcting a source URL |
| 61 | +- Updating `notes` fields |
| 62 | + |
| 63 | +## What Counts as Breaking |
| 64 | + |
| 65 | +Any change that would cause an existing consumer to produce incorrect results, crash, or need code changes: |
| 66 | + |
| 67 | +| Change | Why it breaks | |
| 68 | +|--------|--------------| |
| 69 | +| Removing or renaming a level | Apps display level names, store level IDs | |
| 70 | +| Changing the number of levels (adding Level 8, removing a level) | UI layouts, color mappings, percentile logic | |
| 71 | +| Removing or renaming a category | Benchmark lookups, category-based filtering | |
| 72 | +| Changing the number of categories | Radar charts, UI grids, overall level calculation | |
| 73 | +| Removing a field from the benchmark schema | Deserialization fails, null references | |
| 74 | +| Changing the `standards` key names (e.g., `beginner` to `level_1`) | Every lookup breaks | |
| 75 | +| Changing the weakest-link principle | Level calculation logic changes | |
| 76 | +| Changing units mid-category (kg to lb, seconds to minutes) | Every comparison breaks | |
| 77 | + |
| 78 | +## Extensions vs. Core |
| 79 | + |
| 80 | +The standard distinguishes between **core** data (the stability contract) and **extensions** (additive features). |
| 81 | + |
| 82 | +### Core data files |
| 83 | + |
| 84 | +These files are covered by the stability contract. Their schemas are frozen within a major version: |
| 85 | + |
| 86 | +``` |
| 87 | +data/levels.json |
| 88 | +data/categories.json |
| 89 | +data/benchmarks/*.json |
| 90 | +data/sources.json |
| 91 | +``` |
| 92 | + |
| 93 | +### Extension data files |
| 94 | + |
| 95 | +These files provide additional functionality. They are additive and optional -- an implementation that ignores them is still a complete OP implementation: |
| 96 | + |
| 97 | +``` |
| 98 | +data/metcons.json (added in 1.0.0) |
| 99 | +data/sessions.json (added in 1.0.0) |
| 100 | +data/milestones.json (proposed in 1.1.0) |
| 101 | +data/progressions.json (proposed in 1.1.0) |
| 102 | +``` |
| 103 | + |
| 104 | +Extensions follow the same versioning rules once introduced. After an extension ships in a minor release, its schema is stable within that major version. |
| 105 | + |
| 106 | +### How to tell if something is core or extension |
| 107 | + |
| 108 | +If removing it would break the "7 levels, 8 categories" level assessment system, it's core. Everything else is an extension. |
| 109 | + |
| 110 | +## Adding New Content |
| 111 | + |
| 112 | +### New movements within existing categories |
| 113 | + |
| 114 | +Adding a new benchmark movement (e.g., Wall Ball to Bodyweight) is a **minor** change. The category file gains a new entry, but existing entries are untouched. Consumers that iterate over all movements in a category will pick up the new one automatically. Consumers that look up specific movements by ID are unaffected. |
| 115 | + |
| 116 | +### New categories |
| 117 | + |
| 118 | +Adding a 9th category would be a **major** change. It changes the weakest-link calculation (overall level now depends on 9 categories instead of 8), breaks UI layouts built for 8 categories, and changes the "8 categories" part of the standard's identity. |
| 119 | + |
| 120 | +If a new domain needs to be tracked, consider whether it can be added as movements within an existing category before creating a new one. |
| 121 | + |
| 122 | +### New levels |
| 123 | + |
| 124 | +Adding an 8th level or splitting an existing level would be a **major** change. It changes percentile boundaries, color mappings, and the "7 levels" identity. |
| 125 | + |
| 126 | +Foundation Milestones (F1, F2, F3) are explicitly **not levels** -- they are an extension that provides sub-Beginner progress markers without modifying the level system. This is the correct pattern for adding granularity without breaking the core. |
| 127 | + |
| 128 | +### New data files |
| 129 | + |
| 130 | +Adding a new data file is always a **minor** change. The file is additive and consumers that don't read it are unaffected. |
| 131 | + |
| 132 | +## Version Number Propagation |
| 133 | + |
| 134 | +When a release is made, the version number updates in: |
| 135 | + |
| 136 | +1. **All data file `"version"` fields** -- every JSON file with a `"version"` key gets the new standard version |
| 137 | +2. **All spec document `**Version:**` headers** -- every `.md` file in `spec/` gets the new version |
| 138 | +3. **The website footer** (`v1.0.0` badge) |
| 139 | +4. **The README** (standard version badge) |
| 140 | + |
| 141 | +This keeps everything in sync and makes it easy to verify which version of the standard a file conforms to. |
| 142 | + |
| 143 | +## Deprecation Process |
| 144 | + |
| 145 | +If a field, movement, or data file needs to be removed in a future major version: |
| 146 | + |
| 147 | +1. **Announce** -- mark it as deprecated in the current minor release (add a `"deprecated": true` field or a note in the spec) |
| 148 | +2. **Document** -- explain what replaces it and why |
| 149 | +3. **Wait** -- deprecated items remain functional for at least one minor release cycle |
| 150 | +4. **Remove** -- the next major version can remove deprecated items |
| 151 | + |
| 152 | +This gives consumers time to migrate. |
| 153 | + |
| 154 | +## Release Checklist |
| 155 | + |
| 156 | +For any OP release: |
| 157 | + |
| 158 | +- [ ] Determine version bump type (major / minor / patch) |
| 159 | +- [ ] Update version numbers in all data files and spec documents |
| 160 | +- [ ] Update the changelog (if one exists) or the GitHub release notes |
| 161 | +- [ ] Run `node scripts/validate-data.mjs` -- all checks pass |
| 162 | +- [ ] Build the website -- `cd website && npm run build` succeeds |
| 163 | +- [ ] Tag the release in git: `git tag v1.x.x` |
| 164 | +- [ ] Update the website version badge |
| 165 | + |
| 166 | +## Version History |
| 167 | + |
| 168 | +| Version | Date | Type | Summary | |
| 169 | +|---------|------|------|---------| |
| 170 | +| 1.0.0 | 2025-02-17 | Initial | 7 levels, 8 categories, 25 benchmark movements, scaled programming, metcon library | |
0 commit comments