illumitech-forge-cli 1.1.1

Evidence-backed agent execution CLI
Documentation
//! Product integration regressions. Disposable command gates are not native acceptance.
use forge_domain::digest;
use serde_json::{Value, json};
use std::{fs, path::Path, process::Command};

fn call(state: &Path, args: &[&str], ok: bool) -> Value {
    let out = Command::new(env!("CARGO_BIN_EXE_illumitech-forge"))
        .args(["--json", "--state-dir"])
        .arg(state)
        .args(args)
        .output()
        .unwrap();
    assert_eq!(
        out.status.success(),
        ok,
        "args={args:?} stdout={} stderr={}",
        String::from_utf8_lossy(&out.stdout),
        String::from_utf8_lossy(&out.stderr)
    );
    let value: Value = serde_json::from_slice(&out.stdout).unwrap();
    assert_eq!(value["schema_version"], 1);
    assert_eq!(value["tool_version"], env!("CARGO_PKG_VERSION"));
    value
}
#[test]
fn v1_end_to_end_with_external_gates() {
    let t = tempfile::tempdir().unwrap();
    let base = t.path().canonicalize().unwrap();
    let root = base.join("project");
    let state = base.join("state");
    fs::create_dir(&root).unwrap();
    assert!(
        Command::new("git")
            .args(["init", "-q"])
            .arg(&root)
            .status()
            .unwrap()
            .success()
    );
    fs::write(root.join("preserved.txt"), "keep").unwrap();
    assert!(
        Command::new("git")
            .current_dir(&root)
            .args([
                "-c",
                "user.name=Fixture",
                "-c",
                "user.email=fixture@example.invalid",
                "commit",
                "--allow-empty",
                "-qm",
                "disposable fixture"
            ])
            .status()
            .unwrap()
            .success()
    );
    let ops = base.join("operations");
    call(
        &state,
        &[
            "feature",
            "new",
            "--root",
            root.to_str().unwrap(),
            "--id",
            "001-demand",
            "--title",
            "Synthetic demand",
            "--ops-root",
            ops.to_str().unwrap(),
            "--apply",
        ],
        true,
    );
    assert!(
        !state.exists(),
        "guided creation must not open execution state"
    );
    let gate = base.join("independent_gate.py");
    fs::write(&gate, "from pathlib import Path\nimport sys\nroot=Path(sys.argv[1])\nassert (root/'result.txt').read_text() == '42'\nassert (root/'preserved.txt').read_text() == 'keep'\n").unwrap();
    let manifest = base.join("release.json");
    let body = json!({"schema_version":1,"release_id":"v1-integration","repos":{"app":{"path":root,"specs":["001-demand"]}},"context":{"profile":"bounded","budget_tokens":8192},"budget":{"actions":"off"},"tasks":[{"id":"work","repo":"app","description":"Write exactly 42 while preserving existing content.","executor":{"kind":"command","argv":["python3","-c","from pathlib import Path; Path('result.txt').write_text('42')"]},"acceptance":[{"kind":"gate","id":"independent"}]}],"gates":[{"id":"independent","argv":["python3",gate,"{repo}"],"inputs":{gate.to_str().unwrap():digest(&fs::read(&gate).unwrap())}}]});
    fs::write(&manifest, serde_json::to_vec(&body).unwrap()).unwrap();
    let m = manifest.to_str().unwrap();
    for args in [
        vec!["release", "inspect", m],
        vec!["release", "run", m, "--dry-run"],
        vec![
            "context",
            "plan",
            m,
            "--task",
            "work",
            "--budget-tokens",
            "8192",
        ],
        vec!["review", "plan", m],
    ] {
        call(&state, &args, true);
        assert!(
            !state.exists(),
            "previews must not create operational state"
        );
    }
    let execution = call(&state, &["release", "run", m], true);
    assert_eq!(execution["run"]["status"], "passed");
    let report = call(&state, &["report", m], true);
    assert_eq!(report["run"]["status"], "passed");
    let snapshot = base.join("snapshot");
    call(
        &state,
        &["state", "snapshot", "--output", snapshot.to_str().unwrap()],
        true,
    );
    let restored = base.join("restored");
    call(
        &state,
        &[
            "state",
            "restore",
            "--snapshot",
            snapshot.to_str().unwrap(),
            "--target-state-dir",
            restored.to_str().unwrap(),
            "--apply",
        ],
        true,
    );
    assert_eq!(call(&restored, &["report", m], true)["run"], report["run"]);
    // The immutable evaluator pin is still authoritative after a successful restore.
    fs::write(&gate, "raise SystemExit('changed evaluator')\n").unwrap();
    let blocked = call(&restored, &["release", "run", m], false);
    assert_eq!(blocked["status"], "blocked");
    assert_eq!(blocked["error_code"], "operation_blocked");
    assert_eq!(
        fs::read_to_string(root.join("preserved.txt")).unwrap(),
        "keep"
    );
}

#[test]
fn v1_distribution_inventory_and_support_matrix() {
    let t = tempfile::tempdir().unwrap();
    let state = t.path().join("absent");
    let contract = call(&state, &["contracts"], true);
    assert!(!state.exists());
    assert_eq!(contract["contracts"]["manifest"], 1);
    assert_eq!(contract["contracts"]["state_sqlite"], 1);
    assert!(
        contract["platforms"]["windows"]
            .as_str()
            .unwrap()
            .contains("experimental")
    );
    assert!(
        contract["platforms"]["linux"]
            .as_str()
            .unwrap()
            .contains("blocked")
    );
    assert!(
        contract["candidate"]
            .as_str()
            .unwrap()
            .contains("not a publication")
    );
    assert!(
        contract["publication"]
            .as_str()
            .unwrap()
            .contains("separate explicit authorization")
    );
}