# Release Specification
- [Purpose](#purpose)
- [Requirements](#requirements)
- [`release:versions-are-semantic-and-aligned` — Versions are semantic and aligned](#releaseversions-are-semantic-and-aligned--versions-are-semantic-and-aligned)
- [`release:a-tag-derives-from-the-version-file` — A tag derives from the version file](#releasea-tag-derives-from-the-version-file--a-tag-derives-from-the-version-file)
- [`release:a-released-version-is-not-re-authored` — A released version is not re-authored](#releasea-released-version-is-not-re-authored--a-released-version-is-not-re-authored)
- [`release:license-declares-both-halves` — The license declares both halves](#releaselicense-declares-both-halves--the-license-declares-both-halves)
- [`release:the-delivered-gate-set-is-declared-once` — The delivered gate set is declared once](#releasethe-delivered-gate-set-is-declared-once--the-delivered-gate-set-is-declared-once)
- [`release:a-canon-gate-is-not-delivered` — A canon gate is not delivered](#releasea-canon-gate-is-not-delivered--a-canon-gate-is-not-delivered)
## Purpose
Rules governing how this repository cuts a release: which artifact states the version, how a tag derives from it, what a release carries, and how the licence splits. No instance adopts this spec. Every rule here is verified by a cargo test that never ships, so an instance holding these rules would hold rules it cannot run.
## Requirements
### `release:versions-are-semantic-and-aligned` — Versions are semantic and aligned
`Cargo.toml` states the release identity as one semantic version, and every other artifact naming a version MUST carry that value.
#### Scenario: A second artifact names a different version
- GIVEN `Cargo.toml` reads 0.3.0 and the instance manifest reads 0.2.0
- WHEN the canon test suite runs
- THEN it fails and names `Cargo.toml` as the value to correct toward, not the disagreement
Verify: `pre-commit run cargo-test --all-files`
### `release:a-tag-derives-from-the-version-file` — A tag derives from the version file
A release tag MUST be `v<version>` for the version `Cargo.toml` states at the commit it names, and MUST be produced by the release automation rather than authored by hand.
#### Scenario: A maintainer tags by hand
- GIVEN a working tree whose `Cargo.toml` reads 0.3.0
- WHEN a tag named `v0.4.0` is pushed
- THEN the tag ruleset rejects it, because the tag resolves consumers to a version the tree does not hold
Verify: reviewer confirms every `v*` tag was created by the merged release pull request
### `release:a-released-version-is-not-re-authored` — A released version is not re-authored
If a version is published, then further changes MUST ship as a new version; a published version is never re-authored.
#### Scenario: A fix lands after a version is published
- GIVEN a consumer pinned to `rev: v0.3.0` or the published crate
- WHEN a defect in 0.3.0 needs correcting
- THEN the fix merges forward and the automation proposes 0.3.1, because the registry refuses a second 0.3.0 and a moved tag serves two payloads under one name
Verify: reviewer confirms corrections are cut forward as a new version, never by retagging
### `release:license-declares-both-halves` — The license declares both halves
The release MUST carry a named license file for the method and one for the distribution, the root `LICENSE` MUST name both, and the crate metadata MUST carry the combined SPDX expression.
#### Scenario: A project installs the binary without the method
- GIVEN a target that installs the hooks and the verifier
- WHEN a reader opens `LICENSE` or the crate metadata to learn the terms
- THEN one identifier covers what was installed and the other stays with what was left behind
Verify: `pre-commit run cargo-test --all-files`
### `release:the-delivered-gate-set-is-declared-once` — The delivered gate set is declared once
Every gate the release delivers MUST be declared in the one registry that the projection into an instance and the manifest published to a consumer are both rendered from.
#### Scenario: A gate reaches the payload but no wiring
- GIVEN a gate compiled into the binary and named by no pre-commit entry
- WHEN the instance runs its hooks
- THEN the gate exists and never runs, so both deliveries are rendered from the registry and held equal to it
Verify: `pre-commit run cargo-test --all-files`
### `release:a-canon-gate-is-not-delivered` — A canon gate is not delivered
A check of an invariant only this repository has MUST stay a canon-side test, and MUST reach neither the projection nor the published manifest.
#### Scenario: An instance receives the release checks
- GIVEN a check holding the crate version against the instance manifest of the canon
- WHEN it is delivered to a knowledge base that cuts no release
- THEN the instance is gated on a process it does not run, so the boundary is asserted rather than assumed
Verify: `pre-commit run cargo-test --all-files`