Skip to main content

spec_driven_docs/commands/
gate.rs

1//! `gate` subcommand: runtime-shape.
2//!
3//! Runs one delivered gate against the invoking repository, printing every
4//! violation to stdout, or lists the registry. Gate semantics live in
5//! `gates`; this handler only dispatches and reports.
6
7use crate::cli::gate::GateArgs;
8use crate::context::AppContext;
9use crate::error::AppError;
10use crate::gates::{GateCtx, spec};
11use crate::output;
12
13/// Run or list gates.
14///
15/// # Errors
16///
17/// [`AppError::Violations`] when the gate found any; I/O errors when it
18/// could not run.
19pub fn run(_ctx: &AppContext, args: GateArgs) -> Result<(), AppError> {
20    let GateArgs { id, files, list } = args;
21    if list {
22        for gate in crate::gates::GATES {
23            output::line(format!("{}: {}", gate.id, gate.name));
24        }
25        return Ok(());
26    }
27    let Some(id) = id else {
28        return Err(AppError::Usage(
29            "a gate id or --list is required".to_string(),
30        ));
31    };
32    let gate_ctx = GateCtx::new(".");
33    let violations = (spec(id).run)(&gate_ctx, &files)?;
34    if violations.is_empty() {
35        return Ok(());
36    }
37    for violation in &violations {
38        output::line(violation);
39    }
40    Err(AppError::Violations {
41        count: violations.len(),
42    })
43}