The pipeline is a verifier, not a runner
A CI pipeline that builds an artefact, tags it, and then tests it has already made the mistake. By the time the tests run, the name exists — and a name is a promise other things resolve. The pattern this estate arrived at inverts that order, and the inversion is the whole of the idea.
Build once, verify before naming. Nothing gets a name until it has passed as an anonymous digest.
The shape
| Step | What happens | Why in that order |
|---|---|---|
| 1. Native per-arch builds | Each architecture builds on its own runner rather than under emulation. | Emulated builds are slow enough that people stop running them, and different enough that they hide platform bugs until release. |
| 2. Push by digest only | The built image goes to the registry addressed by its content hash. No tag is applied. | A digest is a fact about bytes. A tag is a claim about fitness, and it is far too early to make one. |
| 3. Integration-test the pre-tag image | The tests pull the digest and exercise the real artefact, not a rebuild of it. | Testing a rebuild tests the build. Testing the digest tests the thing that will ship. |
| 4. Assemble the manifest, then tag | Only now are the per-arch digests combined and given a name. | The name is applied to something that has already passed. Naming is the last step because naming is the promise. |
The same shape, one level up
Machine images follow the identical discipline, and this is where it becomes obvious that the pattern is a principle rather than a container-registry trick. The image is baked; then a new instance is relaunched from the baked image and re-verified from the outside; and only then is it tagged healthy.
The artefact proves itself twice: once as built, once as booted.
A build that succeeds proves the build succeeded. It does not prove that what was built starts. Those are different claims, and treating them as one is how an unbootable image gets promoted with a green pipeline behind it.
Auto-increment versioning: one source, many consumers
Versions come from a single file at the repository root, incremented by branch policy — the development branch bumps a minor, the main branch bumps a major — read at runtime by the application and used as the image tag by the pipeline. One fact, written once, consumed everywhere.
This site runs the same pattern, which is the nearest thing to a live demonstration a hub page can offer: admin/build/version.txt owns the version, chrome.py stamps it across every page and both text twins, and the pre-release gate refuses to tag if any page disagrees with the file or if the release commit's subject disagrees with either. See how this site is built.
Counter-evidence
Two lapses, both in the pipeline that teaches the pattern. Published as found as of 24 August 2026, measured in the sg-compute pack:
- A workflow invokes a binary that is defined nowhere, sixteen times. The workflow is dead: it cannot have run successfully, and nobody noticed, which means nobody was reading the result. A pipeline is only a verifier if somebody is verifying the verifier.
- The one-source-of-truth rule has a second version file, read by nothing. It is the exact drift the rule exists to prevent, sitting inside the estate that wrote the rule.
The second one is worth more than the first. A dead workflow is a maintenance failure. A second version file is a structural failure of the very pattern the section above recommends, and it teaches the real rule: single-source-of-truth is not achieved by declaring a source, it is achieved by deleting the others. Until the second file is gone, the estate has two sources and a convention, which is what everybody else has.
The consistency requirement that follows from this is stated on the topic map; the conventions that would enforce it belong to coding.sgit.ai.