Release governance
In plain language
A change to the substrate reaches production through a process that a machine enforces at every step. All 34 packages share one version and publish together; a release is a signed-off tag on the main branch that re-runs every test before a single artifact is pushed; published artifacts are immutable; and consumers upgrade by choosing a version, never by receiving a silent change. The rules exist because one undocumented drift once cost a release cycle — and the response was to make the rules mechanical.
The mechanism
One release, many artifacts (ADR-0008). Every @magpie/* package shares
a single semantic version; internal dependencies are pinned to that exact
version. A consumer that installs any one package transitively gets every
other at the matching version — "there is no version-skew condition Magpie
can be in; there is only Magpie at version X."
The publish workflow is the only sanctioned path. Triggered by a tag
matching magpie-MAJOR.MINOR.PATCH (annotated, pointing at a commit on
main that already passed CI), the workflow asserts every package's version
equals the tag, re-runs lint, format, typecheck and test against the tagged
commit, builds, authenticates through short-lived federated credentials,
and publishes in topological dependency order with a skip-guard so a re-run
is idempotent. Published artifact sets are immutable; a tag is never moved
after a successful publish.
Mechanically enforced (ADR-0016). Nine INV-REL-* invariants cover tag
semantics, artifact immutability, cross-package version coherence, a closed
runtime-surface classification, and a trust-policy preflight. Public and
runtime surfaces are snapshot-governed, so an accidental API change fails
CI; a workspace-wide source-grep rejects table scans and non-transactional
writes; and the post-publish verifier installs the published artifacts and
runs a runtime round-trip probe against them.
Pre-1.0, on purpose. Below 1.0.0 the public API may change between
minor versions; patches are bug-fix only. Every breaking change still ships
with a migration note, event schemas still follow their own immutability
rule, and consumers pin exact versions and upgrade behind their own mirror
test suites. 1.0.0 will be declared by an explicit decision after
stability evidence, not by the calendar.
The composition layer mirrors the posture. mag-composition has its own
version line, its own publish verification and the same tooling, so a
substrate patch never forces a composition republish or vice versa.
Design notes
- Why lockstep (ADR-0008). The event-object-identity guarantee — a subscriber's event definition is the same object as the publisher's — holds only when both resolve to the same install. Independent versioning would silently degrade that to "structurally compatible".
- Why doctrine became mechanism (ADR-0016). The first publish of a release failed because an IAM trust policy matched the ADR rather than the workflow's actual tag pattern; the fix had been made by hand, off-repo, and the ADR not updated. "It is the canonical example of why doctrine has operational consequences." Every rule now has a check.
Sources
magpie/docs/adr/0008-magpie-publishing-model.md.magpie/docs/adr/0016-release-governance.md— INV-REL-01…09.magpie/.github/workflows/publish-magpie.yml,magpie/infra/scripts/verify-magpie-publish.ts.mag-composition/docs/adr/0001-stack-and-governance.md,0005-ci-and-publish-operationalization.md.