Skip to main content

agent_trace/commands/
violations.rs

1use crate::observability::CliOutput;
2use crate::store::Store;
3use crate::types::Action;
4use anyhow::Result;
5use std::path::Path;
6
7pub fn run(store_root: &Path, limit: Option<usize>, output: &dyn CliOutput) -> Result<()> {
8    let store = Store::open(store_root)?;
9    // Load ALL log entries — violations must never be silently truncated.
10    let all = store.git.log(usize::MAX)?;
11    let violations: Vec<_> = all
12        .into_iter()
13        .filter(|e| matches!(e.action, Action::Violation))
14        .take(limit.unwrap_or(50))
15        .collect();
16
17    if violations.is_empty() {
18        output.line("No violations recorded.")?;
19        return Ok(());
20    }
21
22    output.line(&format!("{} violation(s):", violations.len()))?;
23    for v in &violations {
24        let time = v.timestamp.format("%Y-%m-%d %H:%M:%S");
25        let files_str = v
26            .files
27            .iter()
28            .map(|(p, _, _)| p.display().to_string())
29            .collect::<Vec<_>>()
30            .join(", ");
31        output.line(&format!(
32            "  {} {} {} — {}",
33            time, v.actor, files_str, v.summary
34        ))?;
35    }
36    Ok(())
37}