api.newsroom.sgit.ai v0.2.14

Home / How-to / Make a release

How-to, for maintainers

Make a release

A release is a directory that is never changed after it is on dev, the default branch. The tree is always exactly the release the version file names, or the check fails.

The rules, while the files are frozen

Until phase 4 of the brief is finished (the refactoring with every test passing, and the adversarial exercise), the served files change only as a new release, each change with a test that fails without it and a reason in the pull request. A fix to a finding is a deliberate change to the test that pinned it. A new reader feature is built here, as a new versioned file, never in the newsroom's tree.

1. Change, and test

Edit under the served paths (assets/, for/, wire/, passkey/); if the file is one of the meter's, it is a new component version at a new path, never an edit of v1.4.0. Run the tests in the three engines against the newsroom checkout (running the tests).

2. Version and cut

tools/version.json holds two numbers and a date, all from the file, never the clock:

$EDITOR tools/version.json          # {"version": "v0.2.3", "release": "v0.2.3", "date": "2026-10-20"} for a change to a served file;
                                    # {"version": "v0.2.3", "release": "v0.2.0", ...} for a change to the site, the tests or the tools
python3 tools/release.py cut        # (served files changed) releases/v0.2.3/<every served file> and manifest.json
python3 tools/release.py check      # every release matches its manifest; the tree is the release; the two numbers obey their rule
python3 site/build.py               # the site: the version in the bar, the release on /releases/
python3 site/check.py               # the site's gate: references, canonical, chrome, sitemap, llms, no key shapes

Add the version's line to site/data/versions.json (newest first); the build refuses a version without one, and /versions/ shows them all. A new page needs its link-preview card: python3 site/og.py draws one into site/og/ for every page that has none (commit it; the gate fails a page without one).

cut refuses to write over an existing release directory, refuses a release that is not the repository's version, and refuses a file that differs from the newsroom's bytes unless CHANGED_FROM_NEWSROOM records why. Write a release's note at site/releases/v0.2.3.md.

3. The pull request

CI runs the syntax check, the manifest check, the build twice, the site check and the tests in three engines. A pull request needs one person and one agent reviewer; the agent's review is a required check. The description says what changed, which test fails without it, and why now.

4. Merge, deploy, tag, check

A push to dev (the default branch, and the release branch) runs deploy-pages.yml: the checks again, a tag of the version, the Pages deploy of www/ and releases/, and then tools/live_check.py, which asks the live host for every file of the release and compares the hashes, retrying while Pages propagates. The release is live when that job is green, not before.

5. The consumers

Tell the newsroom (and sgit.ai, once it pins): taking a release. The newsroom's release note names the API release it moved to.

What never happens

A file under releases/ is never edited. A tag is never moved. A release is never cut from a tree that differs from it. A served file is never loaded unversioned.