type: adr id: adr-0080 status: accepted created: 2026-06-16 updated: 2026-06-16
ADR-0080 — Requirement ids are spec-scoped, not workspace-global
Context
C002 (duplicate-id, hard error) had two clauses: no two files claim the same frontmatter id:,
and no requirement id is reused across specs — the second clause was meant to make a bare
AC-001 an unambiguous workspace-wide reference. ADR-0078 narrowed that second clause to exempt
draft specs but explicitly deferred the deeper question: "does not resolve the deeper, separate
question of whether requirement ids should be globally unique or spec-scoped … left to a future
decision if revisited."
Dogfooding the reference CLI surfaced the answer. corpus check over the corpus-works workspace is red
with ~29 cross-spec C002 findings, because every spec naturally numbers its requirements from
AC-001 and the kit's corpus new spec scaffold mints AC-001 for each new spec — so any two
non-draft specs collide through no author fault, and the gate (the product's wedge) reds against its
own dogfood workspace.
The decisive facts: the "globally-unique bare AC" goal has zero live consumers — every real
reference in the workspace (review coverage rows, C012 reconciliation, task scope) is already scoped
to a single named source spec; the only workspace strings of the form SPEC-x#AC-NNN are template
placeholders. And the format reference already says ids are "unique within a file" and already
defines SPEC-x#AC-NNN as the cross-file reference form — so C002's cross-spec clause was the
contradiction, not the spec-scoped model. C001 (unique-ids) independently enforces within-file
uniqueness, so nothing is lost by scoping.
Decision
Requirement ids are spec-scoped. A bare AC-NNN is unique only within its own spec (enforced by
C001); it may recur freely in another spec. A reference that crosses a spec boundary must qualify
as SPEC-x#AC-NNN. C002 retains only its frontmatter-id: uniqueness clause (a duplicate
SPEC-x is ambiguous regardless of lifecycle, so that clause is unchanged and not draft-exempt).
This closes the question ADR-0078 left open and subsumes ADR-0078's draft carve-out for requirement
ids — with requirement ids no longer cross-checked at all, the draft exemption for them is moot
(C002's surviving frontmatter-id: clause never had a draft exemption). ADR-0078's reasoning about
draft ids being work-in-progress still informs the sibling lifecycle gates (C007, and C012's
non-draft source-spec guard, ADR-0079).
C002's id, name (duplicate-id), and severity (hard error) are unchanged — the machine row in
checks.yaml is the same, so the contract version and the corpus-cli drift guard are unaffected; only
the prose semantics in reference/checks.md and reference/structured-requirements.md change, plus
the deletion of the cross-spec requirement-id pass in the reference implementation
(corpus-cli .../checkWorkspace.ts).
Consequences
corpus checkgreens against the corpus-works dogfood workspace; the cross-spec C002 findings clear, and every spec (and thecorpus new specscaffold) can number fromAC-001without coordination.- A bare
AC-001quoted without its spec is now ambiguous by design — readers and tools carry the source-spec binding, which tasks, reviews, and C012 already require. Cross-spec references useSPEC-x#AC-NNN. - The reference impl drops the
requirementIdToPathsaccumulation/emit incheckWorkspace.ts; the frontmatter-id:collision check stays. corpus-cli'scheckWorkspacetests assert the new behavior (a reusedAC-001across specs is not a C002 finding; a duplicate frontmatter id still is). - This does not weaken in-file id integrity (C001 holds) and does not touch C012 — which keys a review's coverage rows against its single named source spec, exactly the spec-scoped model.
Ready to run the loop on your own repo? Get started — copy the kit and write your first spec.