Skip to content

Every rule names what proves it, and every path it names is in the tree

A rule of this repository declares a class. blocking means a gate refuses work that

declared statusdeclared status: guaranteed Declared deterministic and blocking, implemented, and naming the behavioural test that is to prove it. Whether a recorded run supports it is the evidence verdict, shown beside it.

recorded evidencerecorded evidence: stale Declared guaranteed, and not supported by a recorded run: the test is named, and no passing run of the current inputs is recorded. how evidence is recorded

A rule could name a behavioural case in English prose, and nothing noticed when that case was renamed or deleted; the rule went on reading as enforced. The gate holds both halves of the relation. A named path that is not in the tree is `dangling` and is never ratcheted, because a proof that does not exist is worse than no proof. A rule of either class naming neither a validator nor a test nor a reason is `unproven`, which is the half no other check in this repository knows to look for; advisory is not an exemption, and the one exemption is a vendored rule tagged `principle`, which the package pins by hash and which the gate counts on every run. `majordomus rules` reports the same `unproven` state for every class but calls it a finding only for a blocking rule; the gate is what refuses it for an advisory one.

What it means

A rule of this repository declares a class. blocking means a gate refuses work that violates it — that is a claim about the world, and it is either true or it is not. Before this guarantee, nothing decided which. A rule could say, in a # Verification section written for a human reader, that test/cases/28_no_hardcoded_values.sh proved it, and nothing noticed when that case was renamed. The rule went on reading as enforced on every surface that asked, because every surface asked the same question: does the rule carry an x-majordomus block? A green badge for the presence of a YAML key.

The guarantee is the relation, held in both directions. What the rule names is in the front matter, where a program reads it, and what it names is in the tree.

How it works

scripts/ci/rule-proof-check reads every rule object under the rules section — the denominator comes from the tree, so a rule added tomorrow is measured tomorrow — and reports two findings, which fail differently on purpose:

dangling — the block names a path that is not in the tree. Never ratcheted, at any class. A proof that does not exist is worse than no proof, because the rule reads as proven, and recording it in the baseline does not silence it: the baseline is about rules with no proof, not about rules whose proof is a lie.

unproven — a rule of either class names neither a validator, nor a test, nor a reason why nothing executable can express it. Advisory is not an exemption: an advisory rule that named nothing could stay documented-only forever. The one exemption is a vendored rule tagged principle, which the package pins by hash, and the gate prints how many it exempts. This is the half nothing else in the repository can express. scripts/ci/reference-check already refuses a path named in any authored document that is not in the tree, and a rule's front matter is prose to it, so it catches the dangling half today — measured, not assumed. What no other check knows is that a rule is supposed to name anything at all. majordomus rules reports the same unproven state for every class but calls it a finding only for a blocking rule; this gate is what refuses it for an advisory one.

How to see it

scripts/ci/rule-proof-check            report, and fail on new debt
scripts/ci/rule-proof-check --strict   fail on any finding, baseline ignored

The rule-proof gate in .ai/repo/ci/gates.yaml runs the first on every change that touches a rule. The baseline is empty: every rule in this repository, less the exempt vendored principles, names executable proof or declares why a reader is the proof.

What it does not cover

That the proof is any good. The gate decides that a rule names something and that what it names is in the tree. Whether the case it names actually exercises the behaviour the rule describes is not decidable here, and a case that asserted true would satisfy it. That judgement is review's, and it is the reason naming a proof is a floor rather than a ceiling.

Nor does it run anything. A named case that has never been executed still satisfies this claim; whether a run happened, passed, and is younger than what it is about is a different question, answered by the proof graph and by EVIDENCE.md.

Why it exists

Because a rule that reads as enforced and is not is worse than a rule everyone knows is unenforced. The first is trusted. On 2026-09-11 the repository held ten blocking rules whose only verification was the word "Review.", and six more whose proof existed but was named in prose no program reads — so a case could be renamed and the rule would go on displaying a green badge on every surface that asked.

What proves it

test/cases/125_rule_proof.sh, by mutation. The tree is green; one fact changes — a case is deleted while the rule still names it, a blocking or an advisory rule is added naming nothing, a declaration is written with no reason — the gate goes red naming that fact; the change is undone; the tree is green again. A mutation nothing survives is a guarantee nothing gives.

Detail rendered from docs/claims/rule-proof-is-named-and-resolves.md.

From the statement to the proof

  1. 1 · the public statement

    Every rule names what proves it, and every path it names is in the tree

    Made on Doctrine.

  2. 2 · the canonical claim

    rule-proof-is-named-and-resolvesdeclared status: guaranteed in docs/CLAIMS.yaml

    Defined in read it on this site · docs/DOCTRINE.md

  3. 3 · the implementation

    scripts/ci/rule-proof-check

  4. 4 · the test and the scenarios

    Test: test/cases/125_rule_proof.sh

  5. 5 · the recorded runs

    recorded evidence: stale how evidence is recorded

Verify it yourself

The test runs in a disposable temporary repository and asserts the behaviour, not a string in the source.

from a clone of the repository
bash test/run.sh 125_rule_proof

Related claims same implementation

Searches the titles and descriptions of every page this site publishes.