Versioning

Every release is a folder at a path that names it, never changed once published, with a manifest of hashes. How it works and how a release is made.

The rule

This is the brief's own rule: "every version is immutable. I think that's important" (the brief).

How it is enforced

tools/release.py in the repository does each step, and CI runs check on every commit:

CommandDoes
python3 tools/release.py bump patch (or minor)moves tools/version.json and the VERSION string in each file of src/ to the next release
python3 tools/release.py cutcopies src/ into the release's folder and writes its manifest; refuses a folder that already exists
python3 tools/release.py checkrecomputes every hash of every release; fails if any published byte moved, or if src/ differs from the current release without a bump
python3 tools/release.py major --from vX.Y.Zresets src/ to that release's bytes as the next major
python3 tools/release.py site --out DIRassembles what GitHub Pages serves: this site, every release folder, releases.json

After a deploy, tools/live_check.py asks the live host for every file of every release and compares it with the manifest.

Two numbers

tools/version.json holds version, the repository's version, which goes up on every push (a documentation fix too), and release, the newest cut of the kit, which consumers pin. The version history is the first; the releases are the second.

For a consuming site

Pin one release in one place (storyboards.sgit.ai keeps it in admin/build/api.json, copied from the manifest), load every file from that exact path with its integrity string, and have the gate check both. Moving to a new release is a one-line change and a rebuild.