Skip to main content

Module checker

Module checker 

Source
Expand description

The contract every checker meets, and the machinery that makes it hold.

§What a checker is for

Law III: model output is a proposal, never ground truth. Something has to decide whether the proposal may commit, and that something must not itself be a model — otherwise the guarantee is circular and the whole engine is an elaborate way of asking a language model twice.

A Checker is that decider. It takes the proposal (WorkOrder) and what actually happened (Condensate), and returns a verdict. It is the only thing in BoundGraph whose answer can cause a state change.

§Why check is a provided method

An implementation writes judge and never touches the rest. check wraps it and does three things the implementation is not trusted to do for itself:

  1. Refuses a checker that holds too much authority, before it runs.
  2. Binds the verdict to what was checked, by putting the digests of the work order and the condensate into the evidence itself.
  3. Signs, or fails.

Every one of those is a property the system relies on across all checkers, and a guarantee spread across implementations is a guarantee that the sixth implementation breaks. This is the same reason Slicer::condense is a provided method in feature 07.

§A checker cannot call a reasoner

Not by convention, and not by code review. By its capability set.

Checker::grants declares what the checker needs, and check refuses to run one whose declaration is not within checker_ceiling. The ceiling omits net and secret, which are the only two ways to reach a model provider: no egress, no API key, no inference. It also omits time and rand, which is the same mechanism enforcing the determinism requirement, and fs:write, so a checker cannot alter the thing it is judging.

An undecidable comparison is a refusal, not a pass — Tri::Unknown is treated exactly as feature 02 treats it everywhere else.

§A checker has no failure channel except its verdict

judge returns a Judgement, not a Result. That is deliberate and it is the point of the three-valued Verdict: a checker whose compiler crashed, whose test run timed out, or whose input was not what it expected returns Verdict::Inconclusive, which never commits.

Had judge been fallible there would be two ways to say “no answer” — an Err and an Inconclusive — and somewhere a caller would handle the Err by logging it and carrying on. There is no such caller here because there is no such Err.

CheckError exists for the two things that are not a checker’s opinion: a checker that declared authority it may not hold, and a signature that could not be produced. Neither yields evidence, so neither commits.

§Determinism

A checker is a pure function of (work order, condensate). No clock, no randomness, no iteration over a hashed collection, no network. Replay (US-1006) re-runs a recorded check and compares the evidence byte for byte, and ed25519 signatures are themselves deterministic, so the whole pipeline from inputs to signature reproduces — which is what makes a cassette test (US-1008) able to assert that a verdict did not change.

Structs§

Constant
A checker that always returns the same verdict.
Judgement
What a checker decided, before it becomes signed Evidence.

Enums§

CheckError
The engine refused to produce evidence.

Traits§

Checker
Layer 5: turns a proposal and a result into a signed verdict.

Functions§

checker_ceiling
The widest authority any checker may hold.
ensure_model_free
Whether a grant set is narrow enough for a checker to hold.