Developers
The type contract
The invariant is not a convention, it is a type. Every module compiles against a shape where a green cannot exist without a span.
Two verdicts, a cite, a reason
A result is proven with a cited span or a gap with a reason. There is no field for an approval that skips the chart.
export type Verdict = "proven" | "gap";
export interface CriterionResult {
criterion: Criterion;
verdict: Verdict;
passes: EvidencePass[];
// Present if and only if proven: the cited span.
cite?: ChartSpan;
// Present if and only if gap: what is missing and the one line that fixes it.
gapReason?: string;
rationale: string;
}What the shape guarantees
No third verdict
Verdict is proven or gap. Nothing else type-checks.
A cite rides every green
The cited span travels on the result, so a reviewer can follow it.
A reason rides every gap
A gap carries what is missing, so the output is a to-do, not a dead end.