ADR-0116 — Shipped-spec invariant + status/spec coherence check
- Sections
- 4
- Format
- Markdown
- Order
- 152 / 156
Context
ADR-0108 made the spec an Active living container with a small status set
(draft → ready → active → superseded); ADR-0110 made each
## Execution change-cycle entry the durable, structured residue of a closed change (Scope, the
AC→evidence Coverage digest, the SHA/hash Pins). Together they assume a spec's recorded lifecycle and
its board placement stay coherent. Nothing checks that they do.
The Phase 3 family sweep (workflow wf9rvvwys) found the drift this leaves open. SPEC-suspec-agents
was marked shipped on the workspace board, yet:
- its own frontmatter status still said
ready(board and spec disagreed about whether the work was done); - it carried no
## Executionsection at all — the AC→evidence digest ADR-0110 calls for a closed spec was simply absent, so the requirement→evidence linkage for a "shipped" feature did not exist; - one of its acceptance criteria still named a retired artifact, an AC that could never have closed against the work that actually shipped.
A spec the board calls shipped, with no Execution record, a disagreeing status, and an AC pointing at a thing that no longer exists, is the exact silent-staleness failure ADR-0108 set out to catch — and it slipped because the lifecycle is held by discipline alone, with no coherence gate. This was one of the recurring classes the sweep traced to a missing automated gate: humans caught it, no check did.
Decision
Propose an invariant — a spec marked shipped on the board MUST be coherent with its own record —
and propose extending the existing suspec check to verify it. A spec is shipped-coherent iff:
-
Status agrees. When the board places a spec in a terminal/shipped column, the spec's own frontmatter status is the agreeing terminal value (
activefor an amended-and-shipped living spec, orsupersededwith asuperseded_by:pointer) — never stilldraft/ready. The two records of "is this done?" must not contradict each other. -
Execution is present. A shipped spec carries at least one
## Executionchange-cycle entry (ADR-0110): the durable Scope + AC→evidence Coverage digest for the change that shipped. A spec the board calls done with no Execution record is incoherent — the requirement→evidence linkage for a shipped feature is exactly the residue ADR-0110 keeps.
Spec-side shipped; board-signal half deferred. suspec check (the toolable subset,
ADR-0063) now carries the spec-status↔## Execution
coherence (SPEC-method-gates): it flags an active spec with no ## Execution, and a non-active
(draft/ready/done) spec that carries one. The other half — failing when the board marks a spec shipped
but the spec disagrees — is NOT built: the board's State column is freeform prose, not a low-FP signal to
parse, so that half stays the deferred toolable follow-up.
The check is 0-FP by construction on the board signal: it fires only on a spec the board itself
declares shipped, so a draft/ready/in-flight spec is never touched, and a legacy or 1:1-simple spec
that the board has not marked shipped is never forced into the structured form. (The AC-names-a-retired-
artifact symptom is left to the ADR-0108 reference-snapshot staleness mechanism and to review — it is
not part of this coherence check.)
_Level: toolable — the spec-status↔Execution checks shipped (suspec check: active-spec-no-execution
nonactive-spec-with-execution, suspec-cli). The board-signal half stays proposed (the freeform board is not a low-FP parse target); it remains a discipline-and-review obligation until/unless built._
Consequences
- The shipped/ready contradiction the sweep found becomes detectable instead of relying on a human reading both the board and the frontmatter. The board and the spec stop being two records that can silently disagree about whether a feature is done.
- A shipped spec is forced to carry its ADR-0110 evidence digest — the gate makes the durable AC→evidence residue a precondition of "shipped," not an optional courtesy that a fast close can skip.
- Cost: another
suspec checkcore check to specify and (later) build and maintain; until it ships this is one more discipline-and-review obligation, which is precisely the failure mode the sweep showed discipline alone does not hold. The honest cost is the gap between thisproposedrecord and a shipped checker — this ADR closes nothing on its own. - Coupling to the board reader. The check needs to read the board's shipped signal as well as the spec; it inherits whatever the board representation is. If a spec is shipped without ever touching the board, the gate has no signal to fire on — it covers board-recorded shipped specs, not every closed one.
Affected obligations / constraints
- Refines: ADR-0108 (adds a coherence gate to the living-spec lifecycle
it defines) and ADR-0110 (makes a present
## Executiondigest a precondition of a board-shipped spec). Grounded by: the Phase 3 family sweep (wf9rvvwys,SPEC-suspec-agents). - Does NOT change: the spec status set, the
## Executionformat, the verdict model, or the checks contract — nochecks.yamlrule is added here (the checker is proposed, not shipped; ADR-0063). ADRs 0108/0110 are refined by reference, never edited (Nygard immutability).
Starter kit: Set up a workspace