akicita 0.1.1

Bounded autonomy for self-acting systems: an autonomy ladder (off/suggest/safe-apply/full), protected surfaces that never auto-apply, blast-radius caps, rate limits, and dedupe — named for the Lakota camp marshals who kept warriors inside the bounds
Documentation
use akicita::{Akicita, Config, Decision, Level, Proposal};

fn main() {
    let dir = std::env::temp_dir().join(format!("akicita-example-{}", std::process::id()));
    std::fs::create_dir_all(&dir).unwrap();
    let level_path = dir.join("autopilot_level");
    std::fs::write(&level_path, "safe-apply").unwrap();

    let mut config = Config::default();
    config
        .protected_basenames
        .insert("PolicyEngine.rs".to_string());
    config.journal_path = Some(dir.join("marshal_journal.ndjson"));

    let marshal = Akicita::new(Level::SafeApply, config, Some(level_path));

    let proposals = [
        Proposal::patch(
            "src/feature.rs",
            "// stub",
            "fn work() { done(); }",
            "implement the stub",
        ),
        Proposal::patch(
            "src/PolicyEngine.rs",
            "deny()",
            "allow()",
            "weaken the policy gate",
        ),
        Proposal::patch(
            "src/feature.rs",
            "// stub",
            "fn work() { done(); }",
            "implement the stub",
        ),
    ];

    for p in &proposals {
        match marshal.check(p) {
            Decision::Permit => println!("PERMIT   {} — {}", p.surface, p.intent),
            Decision::Hold { reason } => println!("HOLD     {} — {}", p.surface, reason),
            Decision::Deny { reason } => println!("DENY     {} — {}", p.surface, reason),
        }
    }

    let journal = std::fs::read_to_string(dir.join("marshal_journal.ndjson")).unwrap();
    println!("\njournal ({} lines):", journal.lines().count());
    println!("{journal}");

    std::fs::remove_dir_all(&dir).ok();
}