Skip to content

A doctrine's class is what decides whether a violation stops the command, not a label beside it

There are two classes. blocking means a violation ends the command with a non-zero exit; advisory means the violation is reported and the command still succeeds. The class is read at dispatch time and is what routes the finding, so it is a mechanism rather than a label.

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: not run 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

The test changes checkpoint freshness from advisory to blocking in a copy of the vendored rule file and asserts that check's exit code moves from 0 to 10. There are two classes and no override.

What it means

There are two classes. blocking means a violation ends the command with a non-zero exit; advisory means the violation is reported and the command still succeeds. The class is read at dispatch time and is what routes the finding, so it is a mechanism rather than a label.

How it works

A validator never calls mj_fail directly. It calls mj_doctrine_fail, which reads MJ_DOCTRINE_CLASS — set by the dispatcher from the registry — and emits FAIL for a blocking doctrine and WARN for an advisory one. Only FAIL and DRIFT increment the counter the command turns into its exit code. An unknown class is neither: it is a configuration error, reported as such, and it fails closed rather than defaulting to advisory.

watch is the one command that overrides this, and deliberately. It never blocks work — it reports what has moved and exits 11 to say it found something — so under watch every deviation is drift, advisory ones included.

How to see it

majordomus check                       # WARN checkpoint  … 40m ago, interval 15m   → exit 0
# change class: advisory to class: blocking for majordomus.checkpoint-freshness
majordomus check                       # FAIL checkpoint  … 40m ago, interval 15m   → exit 10

test/cases/17_doctrine_enforcement.sh performs exactly that edit in a throwaway copy of the tool and asserts the exit code moves.

What it does not cover

The class says what a violation costs, not how serious the underlying problem is. There is no severity ladder, and adding one would mean adding a level that neither blocks nor is worth reporting.

Why it exists

Enforcement systems drift toward a middle setting where a rule is nominally enforced and nothing ever fails. Two classes make that impossible to express: a rule either stops the work or it does not, and the registry says which in one word that the code reads.

Detail rendered from docs/claims/doctrine-class-decides.md.

From the statement to the proof

  1. 1 · the public statement

    A doctrine's class is what decides whether a violation stops the command, not a label beside it

    Made on Doctrine, Policy.

  2. 2 · the canonical claim

    doctrine-class-decidesdeclared status: guaranteed in docs/CLAIMS.yaml

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

  3. 3 · the implementation

    lib/doctrine.sh · majordomus doctrine

  4. 4 · the test and the scenarios

    Test: test/cases/17_doctrine_enforcement.sh

    Executed in Prove a rule is actually enforced, not merely written down, Gate CI on the tool itself, with an exit code that is a contract.

  5. 5 · the recorded runs

    recorded evidence: not run 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 17_doctrine_enforcement

Where this claim is used

Related claims same implementation

The moments this answers

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