Invariants
The law is a table of claims with a lifecycle:
proposed → active → retired
An amendment is not a state: it is an edit to an active row, made through a
change (see Amend below). A fourth state, drift, records a real finding the
code has not caught up with: its legs report and never gate.
Three birth paths, one table
- Seeded —
seedinventories the boundaries and the agent drafts candidates from them (arevoke updatein a migration suggests “nobody writes balances”). Bornproposed: not law until a human validates. - Interviewed — the from-scratch path: the interview protocol draws the law out of the person’s head.
- Organic — the main path at steady state: a decision made inside a change is declared an invariant at close.
The agent proposes; the human enacts
The authority label demands it: “published” means someone with authority
answered for it, and an LLM cannot answer for it alone. New claims enter as
proposed rows, whose legs never block, and only a human flips a row to
active.
Validation of seeded output runs in batches ordered by blast radius:
accept / correct / discard, with whatever stays unvalidated remaining marked
proposed.
That rule is ungateable, and the law says so
verify cannot check who enacted a row, and the law declares it ungateable
with its reason rather than pretending. Two reasons, both properties of the
tool rather than gaps in it. multivac never fabricates git identity: it
runs as whoever runs it, so an agent working on your machine commits under your
name and nothing in the repository tells the two apart. And a git hook executes
with the caller’s permissions, so any gate installed at pre-commit is a gate the
same process can skip — a guardrail cannot live on the side of the thing it is
meant to stop.
Where it is enforced is the forge: the merge button, held by an account the
agent does not have. Nothing lands on main directly.
The half that is checked is not who but when. A row that reaches
active in the same commit that writes the code it anchors is a rule nobody
reviewed on its own — the claim and its evidence arrive together under one hand
— so verify refuses that commit and names the files to unstage. It decides
this from the index against HEAD, which means it can only answer while a
commit is being composed; outside one it prints that it could not answer instead
of passing quietly. It is not a security boundary: nothing here stops a person
with push rights who decides to skip it.
Amend
An invariant is never relaxed in code — it is changed in the law first.
A change lists the row under invariants.touches, updates the row (dated) in
that change, and the code follows in the same change. Declare the amended row as one of the
change’s claims and change close re-runs verify over it before it will
archive; listed only under touches, it is reported by verify on each commit
where the hooks are armed, and refused only in a blocking mode or under
--strict, rather than checked by close.
Retire
The row is not deleted — it is marked retired and keeps its ID. On a retired
row verify evaluates only the absent legs; every other mode stops being
evaluated, and an absent leg the row already carried keeps gating, because
verify cannot tell it from a tombstone. The tombstone is authored, not
derived: retiring writes NEW absent legs on that row for the dead
mechanism’s identifiers — the names someone would grep for, in every surface
where they could resurface:
| INV-19 | RETIRED — cart reservation holds stock. | specified | retired | 2026-08-13 | journal |
<!-- @anchor INV-19 api:src/**/*.ts /reserveStock/ absent -->
<!-- @anchor INV-19 *:AGENTS.md /(^|[^[:alnum:]_])stock[[:space:]]+reservation([^[:alnum:]_]|$)/i absent -->Existing legs are never flipped: inverting an enactment leg would demand the enactment itself disappear, which is wrong in the general case. Same primitive, new legs. In the same change, the dead mechanism’s remains leave the code and the doors — the new legs hold the change to it at close.
IDs
Stable, never renumbered, never reused. History — who, when, why — is git, not duplicated in metadata.