0251 — A release does not wait for its consumers
Status: Accepted Date: 2026-10-06
Practice. Invariant P. Supersedes ADR 0250.
Context
ADR 0250 made release:train refuse a breaking or process-contract release until the tests of
the owner’s own consuming projects had passed on the packed candidate. The gate needed a list of
those projects, their checkouts and their test commands, kept in a profile on one machine, because
a public repository does not name private projects (ADR 0164).
A gate that names consumers is only as strong as what its record binds. The record was keyed by the framework tree and the toolchain; it did not bind the profile, the consumers’ commits, their test commands or the tarball, so a changed profile still satisfied it. Binding all of that makes the record honest, and it also makes the framework’s release depend on the state of private projects on one machine. That is the wrong direction of dependency: a library is released on evidence it owns, and a project that uses it owns the proof that an upgrade works for it.
Decision
The framework releases on its own evidence, and a consumer proves an upgrade on its own side.
release:trainchecks release metadata, the tagged head and the green exact-SHA CI run. It has no consumer check, no consumer profile and no waiver field.- The repository contains no tool that runs a consumer’s tests.
- The framework’s own consumer is the packed consumer lane, a fixture inside this repository that
installs the packed tarball and exercises the public surface,
stitchkit/processincluded. - A project that depends on
stitchkitpins a version and tries a new one in its own CI before it moves the pin. A behaviour change reaches it as a documented entry in the changelog (### ⚠️ Breaking changesand the upgrade plan), which is the framework’s side of the contract.
Consequences
- A release that breaks a project is found by that project when it upgrades, not before the tag. The fix is a patch release; pinned versions limit the exposure to the project that chose to move.
- A behaviour a consumer relies on and no framework lane covers is a missing lane here. It becomes a fixture in the packed consumer lane, in public terms and without naming the project.
- No machine configuration is needed to release.
Verification
scripts/release-tagging.test.ts: the tag step runs after the CI proof and before any tag or push,
and takes no consumer input.