Skip to content

The notice verifier

src/credit/guardrails/verifier.py. Pure Python, no network, no model. It takes the notice and what the notice must say (the application, the derived reason codes, the decision being recorded) and returns one pass/fail per check plus a SHA-256 of the exact notice it checked.

# Check Fails when
V1 reasons_match_derivation The notice's reason codes differ from the derived ones, in set or order
V2 reason_count A decline has 0 or more than 4 reasons; an approval has any
V3 no_prohibited_basis A reason maps to an excluded attribute, or its text contains a prohibited-basis term (NFKC-normalised, whole words)
V4 specific_reasons A reason does not state the applicant's actual value, or contains a generic phrase ("internal standards", "score too low", …)
V5 decision_consistent The decision statement or field disagrees with the decision being recorded
V6 numbers_grounded The numbers in a reason differ from the numbers in its approved wording filled with the applicant's fields
V7 legal_frame_intact The frame's hash differs from the pinned, reviewed frame
V8 approved_wording A sentence is not exactly an approved variant, contains non-ASCII or control characters, or matches a promise pattern

Prohibited terms are checked in reason text only. The ECOA paragraph is required to name race, sex, age and the other bases, so it is verified by exact hash (V7) instead; a test pins that this is not a false positive.

Independence

The verifier does not import the renderer. It re-derives the approved sentence from the catalogue with its own substitution and pins the frame by hash. If a developer edits the template, the catalogue, or the code mapping, the verifier and the golden-notice test both fail until the change is reviewed.

Binding to the exact notice

The report carries notice_sha256. The workflow refuses to send a notice whose current hash differs from the verified one, so a stale or tampered notice cannot be sent (tested).

Mutation suite

evals/mutations.py injects one defect at a time into every genuine notice:

Mutator Defect Intended check
M1 reorder two reasons V1
M2 drop the top reason V1
M3 append a fifth, otherwise-approved reason V1, V2
M4 "because of your age" appended V3
M5 "You did not meet our internal standards." V4
M6 decision statement says approved V5
M7 reason code not in the catalogue V1
M8 a stated number changed V6
M9 ECOA statement removed V7
M10 "If you reapply with a co-signer we will approve" V8
M11 category label swapped for another value V4
M12 reason negated V8
M13 zero-width character inserted V8
M14 unapproved wording variant V8, V6

A mutant is killed only when every intended check fails. Mutators that cannot apply (M8 on a notice with no numeric reason) are counted as not applicable, never as kills, and every mutator must apply at least once. A mutator that returns an unchanged notice stops the run as a harness bug. The meta-mutation switches each check off in turn and requires the gate to fail. Results: generated results.

What it does not do

It does not check that the model is right, that a reason is causal, or that the template is legally adequate. Those are model-validation and legal-review questions.