Expand description
Fail-closed gate contracts for staged build pipelines.
A pipeline that only knows PASS and FAIL has a third state hiding inside it: the gate that could not be evaluated at all, because a credential was missing, an API timed out, or the value it needed was never produced. Treating that as a pass is how a run reaches deploy having checked nothing. This crate makes the third state explicit and closes it.
The rule enforced throughout:
A blocking gate halts the run when it fails and when it cannot be evaluated. “Could not check” is not “fine”.
§The pieces
Outcome—Pass,Fail, orUnevaluable, each carrying a reason string.Known— a value that may beUnknown; unknown propagates through combination instead of decaying into a default.Gate— an id, aSeverity(blocking or advisory) and an outcome.Stage— a named set of gates, evaluated together so one run reports every failure.Pipeline— ordered stages, halting at the first stage that halts.
§Example
use gate_contract::{Gate, Severity, Stage, Verdict};
let stage = Stage::new("harvest")
.with_gate(Gate::pass("serp-rows-present"))
.with_gate(Gate::unevaluable("rdap-reachable", "no credential on disk"));
let report = stage.evaluate();
assert!(report.halted());
match report.verdict {
Verdict::Halt { ref gate_id, .. } => assert_eq!(gate_id, "rdap-reachable"),
Verdict::Proceed => unreachable!(),
}An advisory gate records the same information without stopping anything:
use gate_contract::{Gate, Stage};
let report = Stage::new("design")
.with_gate(Gate::fail("tone-check", "two sentences flagged").advisory())
.evaluate();
assert!(!report.halted());
assert_eq!(report.warnings().len(), 1);No dependencies, no I/O, no unsafe. Evaluating what a gate means is this crate’s job; deciding what to measure is yours.
Extracted from a real staged build pipeline, whose first blocking gate is worked through in
public at https://aiwebsitepipeline.com/niche-score.html: six subscores, the weights that
combine them, and the thresholds that decide the run — 55 and above proceeds, 40 to 55
proceeds under a page cap, below 40 the run halts. That page is a concrete example of the
shape Severity::Blocking exists to express, and is worth reading before deciding what
your own gates should refuse.
Structs§
- Gate
- One contract: an identifier, a severity and an outcome.
- Gate
Counts - Tallies from one stage evaluation.
- Pipeline
- Ordered stages evaluated until one halts.
- RunReport
- The outcome of a whole pipeline run.
- Stage
- A named set of gates evaluated together.
- Stage
Report - The outcome of evaluating a
Stage.