agentic-workspace-cli 1.3.2

Native command-line adapter for Agentic Workspace
use serde_json::Value;
use std::{
    fs,
    path::PathBuf,
    process::Command,
    sync::atomic::{AtomicU64, Ordering},
    time::{SystemTime, UNIX_EPOCH},
};

static NEXT_TARGET: AtomicU64 = AtomicU64::new(0);

struct Target(PathBuf);
impl Target {
    fn empty() -> Self {
        let path = std::env::temp_dir().join(format!(
            "aw-native-cli-{}-{}-{}",
            std::process::id(),
            SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_nanos(),
            NEXT_TARGET.fetch_add(1, Ordering::Relaxed)
        ));
        fs::create_dir(&path).unwrap();
        Self(path)
    }
}
impl Drop for Target {
    fn drop(&mut self) {
        fs::remove_dir_all(&self.0).unwrap();
    }
}

#[test]
fn empty_target_is_direct_without_python_or_node() {
    let target = Target::empty();
    let result = Command::new(env!("CARGO_BIN_EXE_agentic-workspace"))
        .args(["start", "--target"])
        .arg(&target.0)
        .args(["--task", "Inspect this empty workspace", "--format", "json"])
        .env_clear()
        .env("PATH", "")
        .output()
        .unwrap();
    assert!(
        result.status.success(),
        "{}",
        String::from_utf8_lossy(&result.stderr)
    );
    let decision: Value = serde_json::from_slice(&result.stdout).unwrap();
    assert_eq!(decision["decision_packet"]["status"], "direct");
    assert!(decision.get("capability_contract").is_none());
    assert!(decision.get("planning").is_none());
    assert_eq!(fs::read_dir(&target.0).unwrap().count(), 0);
}

#[test]
fn actual_registry_selection_is_current_then_stale_without_language_runtimes() {
    let target = Target::empty();
    let registry = target.0.join("tools/skills/REGISTRY.json");
    fs::create_dir_all(registry.parent().unwrap()).unwrap();
    let text = include_str!("../_inputs/tools/skills/REGISTRY.json");
    fs::write(&registry, text).unwrap();
    let start = |input: Option<&PathBuf>| {
        let mut command = Command::new(env!("CARGO_BIN_EXE_agentic-workspace"));
        command
            .args(["start", "--target"])
            .arg(&target.0)
            .args(["--task", "Inspect the repository boundaries"])
            .args(["--projection", "full"])
            .env_clear()
            .env("PATH", "");
        if let Some(input) = input {
            command.arg("--input").arg(input);
        }
        let result = command.output().unwrap();
        assert!(
            result.status.success(),
            "{}",
            String::from_utf8_lossy(&result.stderr)
        );
        serde_json::from_slice::<Value>(&result.stdout).unwrap()
    };
    let discovered = start(None);
    assert_eq!(discovered["decision_packet"]["status"], "direct");
    let mut request = discovered["semantic_routes"]["requests"][1].clone();
    request["arguments"] =
        serde_json::json!({"posture":"selected","routes":["workspace/ownership/audit"]});
    let input = target.0.join("request.json");
    fs::write(&input, serde_json::to_vec(&request).unwrap()).unwrap();
    let current = start(Some(&input));
    assert_eq!(current["semantic_routes"]["status"], "current");
    assert_eq!(
        current["decision_packet"]["semantic_task_routes"]["status"],
        "current"
    );
    assert_eq!(
        current["decision_packet"]["semantic_task_routes"]["authority_effect"],
        "applicability-only"
    );
    fs::write(&registry, format!("{text}\n")).unwrap();
    let stale = start(Some(&input));
    assert_eq!(stale["semantic_routes"]["status"], "stale");
    assert_eq!(
        stale["decision_packet"]["semantic_task_routes"]["status"],
        "stale"
    );
    assert!(!target.0.join(".agentic-workspace").exists());
}

#[test]
fn transport_rejects_private_flags_without_any_runtime() {
    let result = Command::new(env!("CARGO_BIN_EXE_agentic-workspace"))
        .args(["start", "--admitted-revision", "caller-owned"])
        .env_clear()
        .env("PATH", "")
        .output()
        .unwrap();
    assert_eq!(result.status.code(), Some(2));
    assert!(result.stdout.is_empty());
    let error: Value = serde_json::from_slice(&result.stderr).unwrap();
    assert_eq!(error["error"]["code"], "invalid-cli-input");
}