Current section
Files
Jump to
Current section
Files
priv/toolchain/canon/registers.md
# External Registers
A **register** is a machine-authoritative system outside the repository
that holds structured claims about it — a compliance register, an API
catalogue, an SLO inventory, a design-token system. Inside the
repository, code is the source of truth and artifacts carry the *why*
([`principles.md` §1](principles.md#1-the-directive)); a register
extends the same relation across the repository boundary: **the
register is the source of truth for the structured claim; artifacts
here carry its why, in the same three forms.** No new artifact type
exists for register participation.
## 1. The split rule
When a claim is structured and machine-reconciled — an inventory row,
a classification tier, a threshold, an owner, a due date, a status —
it lives in the register, not in prose. When a claim is reasoning —
why the rule exists, why the alternative was rejected, why the
exemption is justified — it lives here, in the three permitted forms.
The failure modes are symmetric. A structured value hand-maintained in
prose is an uncoupled present-tense assertion
([`principles.md` §1](principles.md#1-the-directive)): the register
moves and the prose silently lies. Reasoning stuffed into register
fields is unreviewable: no PR, no CODEOWNERS, no premise structure.
Each side holds what it can defend.
## 2. Claim modes
Register claims arrive in three modes. Each maps onto an existing
form — the mode decides the destination, exactly as the trigger column
in `AGENTS.md` does for change-time decisions:
| Mode | The claim | Repository artifact |
|---|---|---|
| **Normative** — what ought to hold | an obligation, a requirement, a rule the register checks against | A **goal** when externally sourced (regulator, customer, contract — with the verbatim quote, per [`conventions.md` §2](conventions.md#2-goals-docsgoals)); an **ADR** when it is a cross-cutting rule ([`conventions.md` §1](conventions.md#1-adrs-docsadr)) |
| **Descriptive** — what currently is | an inventory fact, a configuration, a measured state | Usually **none** — the register and the code *are* the truth. A **domain document** only when a business fact shapes the claim and is not recoverable from either ([`conventions.md` §3](conventions.md#3-domain-documents-docsdomain)) |
| **Proposed** — what is intended to change, or accepted as-is | a gap with an owner and a due date, or a waived finding | An **ADR with `Status: Proposed`** when the intent is a rule the codebase will adopt — the on-the-record *why* of the pending change. The register tracks the schedule (owner, due, disposition); the artifact never carries dates or owners |
| **Judgmental-structured** — a decided value in machine shape | a classification, a purpose, a facet, a subject declaration — structured like an inventory row, decided like a premise | A **claim file** (`docs/registers/`, see `claim-files.md`): structured so the witnessing procedure reconciles it, in the repo so a PR ratifies it. The register's own argument shows why it cannot hold these ("reasoning stuffed into register fields is unreviewable"); prose cannot either (the register moves and prose lies). The claim file is the third form both sides were missing |
## 3. The join
A register row references its rationale by repository-relative path
and optional Markdown anchor — the same cross-reference form as
everything else ([`conventions.md` §8](conventions.md#8-naming-and-cross-referencing)):
```
rationale_ref: docs/adr/data-erasure-on-request.md
```
An artifact referenced by a register MAY carry the reverse pointer as
a trailer line after its body, telling a reader the artifact is
load-bearing for an external system:
```
Register: <system>, <row-id>
```
## 4. The contract
Because the join is a pointer between two machine-readable sides,
its health is computable. Three reconciliations; each finding is real
work, not noise:
- **Dangling pointer** — a register row whose `rationale_ref` resolves
to nothing. Caused by a rename or deletion here. Renaming or
deleting a register-targeted artifact entails updating the register
row, exactly as with inbound repository references; the
reconciliation catches the miss when forgotten.
- **Orphan artifact** — an artifact carrying a `Register:` trailer
with no register row pointing back. Either the row was retired
(remove the trailer) or the registration was never made (a
missing-declaration finding on the register side).
- **Stale rationale** — the artifact's last material change predates a
material change to what it justifies: the code its `Application:` or
`Codified-by:` cites, or the register value it explains. Currency,
computed per artifact rather than per repository.
## 5. Boundaries
- When a register's reconciliation finds a gap, it **proposes** — a
finding, a draft, a PR; a human authors the artifact. The register
never writes this repository's prose. (Agent-assisted scaffolding —
surveying the code, fact-checking the derivable facts, and writing
stubs with the gaps marked for a human to fill — is what the
`/dds-sync` skill does; `/dds-check` then verdicts the
structure. Neither invents the content; the human authors and ratifies
at PR review.)
- When an artifact needs a register value, it **points**; quoting the
value couples the artifact to a store it cannot co-maintain.
- A register row is not a source
([`principles.md` §5](principles.md#5-sources-authority-and-the-requirement-as-premise)).
A goal still quotes the external authority verbatim; the register
tracks discharge status, not authority. A register row citing a goal
does not relieve the goal of its `Source:` line.
## 6. Authority
The register's owning team defines its rows, schema, and
reconciliation cadence. Artifact authority is unchanged — per-layer
CODEOWNERS govern modification, and registering an artifact transfers
nothing. The two sides meet only at the pointer.