illumitech-forge-cli 1.6.0

Evidence-backed agent execution CLI
Documentation
//! Protocol fixtures exercise real workflow/evaluator execution, not a live LLM account.
#![cfg(unix)]
use serde_json::{Value, json};
use std::{fs, os::unix::fs::PermissionsExt, path::PathBuf, process::Command};

struct Fixture {
    _temp: tempfile::TempDir,
    base: PathBuf,
    repo: PathBuf,
    ops: PathBuf,
    input: PathBuf,
    bin: PathBuf,
}
impl Fixture {
    fn new() -> Self {
        let temp = tempfile::tempdir().unwrap();
        let base = temp.path().canonicalize().unwrap();
        let repo = base.join("project with spaces");
        fs::create_dir(&repo).unwrap();
        for args in [
            vec!["init", "-q"],
            vec![
                "-c",
                "user.name=Fixture",
                "-c",
                "user.email=fixture@example.invalid",
                "-c",
                "commit.gpgSign=false",
                "-c",
                "core.hooksPath=/dev/null",
                "commit",
                "--allow-empty",
                "-qm",
                "fixture",
            ],
        ] {
            assert!(
                Command::new("git")
                    .arg("-C")
                    .arg(&repo)
                    .args(args)
                    .status()
                    .unwrap()
                    .success()
            );
        }
        fs::write(repo.join("preserved.txt"), "preserve").unwrap();
        let bin = base.join("bin");
        fs::create_dir(&bin).unwrap();
        fs::write(bin.join("codex"), r#"#!/usr/bin/env python3
import json,os
from pathlib import Path
counter=Path(os.environ['CALL_COUNTER'])
calls=counter.read_text().count('call') if counter.exists() else 0
counter.write_text(('call\n')*(calls+1))
if not counter.with_name('prose-only').exists():
    Path('first.txt' if calls==0 else 'second.txt').write_text('verified')
print(json.dumps({'type':'thread.started','thread_id':'fixture'}))
print(json.dumps({'type':'turn.completed','usage':{'input_tokens':100,'cached_input_tokens':0,'output_tokens':10}}))
"#).unwrap();
        fs::set_permissions(bin.join("codex"), fs::Permissions::from_mode(0o700)).unwrap();
        let ops = base.join("ops");
        let input = base.join("request.json");
        let checks:Vec<_>=[("AC1","first","first.txt"),("AC2","second","second.txt")].into_iter().map(|(id,task,file)|json!({"id":id,"argv":["python3","{checks}/verify.py","{repo}",file],"task_ids":[task],"timeout_seconds":10})).collect();
        let tasks:Vec<_>=[("first",Vec::<&str>::new(),0),("second",vec!["first"],1)].into_iter().map(|(id,deps,index)|json!({"id":id,"title":format!("Deliver {id} behavior"),"dependencies":deps,"acceptance":[{"id":checks[index]["id"],"description":"Expected output exists and unrelated work is preserved","command":checks[index]["argv"]}]})).collect();
        let request = json!({"schema_version":1,"id":"001-feature","title":"Incremental feature","request":"Deliver first.txt then second.txt with verified content; preserve preserved.txt","recipe":"feature","checks":checks,"files":{"verify.py":"import pathlib,sys\np=pathlib.Path(sys.argv[1]); f=p/sys.argv[2]\nsys.exit(0 if f.is_file() and f.read_text()=='verified' and (p/'preserved.txt').read_text()=='preserve' else 1)\n"},"proposal":{"schema_version":1,"id":"001-feature","title":"Incremental feature","summary":"Two independently validated dependent tasks","tasks":tasks}});
        fs::write(&input, serde_json::to_vec(&request).unwrap()).unwrap();
        Self {
            _temp: temp,
            base,
            repo,
            ops,
            input,
            bin,
        }
    }
    fn call(&self, verb: &str, extra: &[&str]) -> (bool, Value) {
        let output = Command::new(env!("CARGO_BIN_EXE_forge"))
            .args(["--json", "modules", "feature", verb])
            .arg(if verb == "prepare" {
                self.input.as_os_str()
            } else {
                std::ffi::OsStr::new("001-feature")
            })
            .arg("--root")
            .arg(&self.repo)
            .arg("--ops-root")
            .arg(&self.ops)
            .args(extra)
            .current_dir(&self.base)
            .env(
                "PATH",
                format!("{}:{}", self.bin.display(), std::env::var("PATH").unwrap()),
            )
            .env("CALL_COUNTER", self.base.join("calls"))
            .output()
            .unwrap();
        let value = serde_json::from_slice(&output.stdout).unwrap_or_else(|_| {
            panic!(
                "{} {}",
                String::from_utf8_lossy(&output.stdout),
                String::from_utf8_lossy(&output.stderr)
            )
        });
        (output.status.success(), value)
    }
    fn calls(&self) -> usize {
        fs::read_to_string(self.base.join("calls"))
            .unwrap_or_default()
            .lines()
            .count()
    }
    fn edit(&self, f: impl FnOnce(&mut Value)) {
        let mut value = serde_json::from_slice(&fs::read(&self.input).unwrap()).unwrap();
        f(&mut value);
        fs::write(&self.input, serde_json::to_vec(&value).unwrap()).unwrap();
    }
    fn prepare(&self) -> Value {
        let (ok, v) = self.call("prepare", &["--apply"]);
        assert!(ok, "{v}");
        v
    }
}
#[test]
fn feature_preview_and_admission_never_execute_or_guess_checks() {
    let f = Fixture::new();
    let (ok, v) = f.call("prepare", &[]);
    assert!(ok, "{v}");
    assert_eq!(v["status"], "preview");
    assert!(!f.ops.exists());
    assert!(!f.repo.join("specs").exists());
    f.edit(|r| r["checks"][0]["argv"] = json!(["true"]));
    assert!(!f.call("prepare", &["--apply"]).0);
    assert!(!f.ops.exists());
    assert_eq!(f.calls(), 0);
}
#[test]
fn feature_executes_dependency_order_and_checkpoints_without_replay() {
    let f = Fixture::new();
    let p = f.prepare();
    let digest = p["scope_digest"].as_str().unwrap();
    assert!(!f.call("start", &["--approve-scope", &"0".repeat(64)]).0);
    assert_eq!(f.calls(), 0);
    let (ok, v) = f.call("start", &["--approve-scope", digest]);
    assert!(ok, "{v}");
    assert_eq!(f.calls(), 2);
    let (ok, v) = f.call("checkpoint", &[]);
    assert!(ok, "{v}");
    assert_eq!(v["effective_status"], "passed");
    assert_eq!(v["checkpoint"]["authority"], "none");
    assert_eq!(v["checkpoint"]["automatic_compaction"], false);
    assert!(
        v["tasks"]
            .as_array()
            .unwrap()
            .iter()
            .all(|t| t["status"] == "passed")
    );
    assert_eq!(
        v["checkpoint"]["proposal"]["tasks"][1]["dependencies"],
        json!(["first"])
    );
    assert!(!f.call("start", &["--approve-scope", digest]).0);
    let (ok, v) = f.call("resume", &[]);
    assert!(ok, "{v}");
    assert_eq!(f.calls(), 2, "{v}");
    assert_eq!(
        fs::read_to_string(f.repo.join("preserved.txt")).unwrap(),
        "preserve"
    );
}
#[test]
fn prose_does_not_pass_first_gate_or_schedule_dependent_feature_task() {
    let f = Fixture::new();
    fs::write(f.base.join("prose-only"), "").unwrap();
    let p = f.prepare();
    let (ok, v) = f.call(
        "start",
        &["--approve-scope", p["scope_digest"].as_str().unwrap()],
    );
    assert!(!ok, "{v}");
    assert_eq!(f.calls(), 1);
    let (_, v) = f.call("checkpoint", &[]);
    assert_ne!(v["effective_status"], "passed");
    assert_eq!(v["checkpoint"]["authority"], "none");
    assert!(!f.repo.join("second.txt").exists());
}
#[test]
fn changed_source_and_cross_recipe_are_blocked_before_native_execution() {
    let f = Fixture::new();
    f.edit(|r| r["recipe"] = json!("pr"));
    assert!(!f.call("prepare", &["--apply"]).0);
    assert!(!f.ops.exists());
    f.edit(|r| r["recipe"] = json!("feature"));
    let p = f.prepare();
    fs::write(f.repo.join("new-unreviewed.txt"), "changed").unwrap();
    assert!(
        !f.call(
            "start",
            &["--approve-scope", p["scope_digest"].as_str().unwrap()]
        )
        .0
    );
    assert_eq!(f.calls(), 0);
}
#[test]
fn feature_scope_does_not_grant_declared_human_acceptance() {
    let f = Fixture::new();
    f.edit(|r| r["human_gates"] = json!(["owner-review"]));
    let p = f.prepare();
    let (ok, v) = f.call(
        "start",
        &["--approve-scope", p["scope_digest"].as_str().unwrap()],
    );
    assert!(!ok, "{v}");
    assert_eq!(f.calls(), 2);
    let (_, v) = f.call("status", &[]);
    assert_eq!(v["effective_status"], "awaiting_approval");
    assert_eq!(v["authorization"]["acceptance_granted"], false);
}