Step 4 — the attorney gate is a graph invariant
Every workflow must pass through staff_review before anything is signed or filed — not as a policy memo, but as a
property checked over the state-machine graph itself with a breadth-first search from BEGIN.
From workflows/src/guardrail.rs:
pub fn staff_review_precedes_signature(spec: &WorkflowSpec) -> Result<(), GateViolation> {
let begin = StateName::begin();
if let Some(signature) = reaches_target_without_review(spec, &begin, is_signature_state) {
return Err(GateViolation {
fill_state: begin.as_str().to_string(),
submission_state: signature,
});
}
Ok(())
}