use std::path::{Path, PathBuf};
use std::process::{Command, Output};
fn bin() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_supercode"))
}
fn entry() -> PathBuf {
let workspace = Path::new(env!("CARGO_MANIFEST_DIR"))
.ancestors()
.nth(2)
.expect("workspace root");
workspace.join("sdk/orchestrator/bin/orchestrator.mjs")
}
fn scratch(label: &str) -> PathBuf {
let root = std::env::temp_dir().join(format!(
"supercode-orc13-cli-{label}-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
std::fs::create_dir_all(&root).unwrap();
root
}
fn seed(root: &Path) -> PathBuf {
let home = root.join("orchestrator");
std::fs::create_dir_all(home.join("profiles/coder")).unwrap();
std::fs::write(
home.join("config.yaml"),
"worker:\n harness: hermes\nexpiry:\n idle_minutes: 30\n",
)
.unwrap();
std::fs::write(home.join("AGENTS.md"), "# Assistant\n").unwrap();
std::fs::write(home.join("CLAUDE.md"), "@AGENTS.md\n").unwrap();
std::fs::write(
home.join("profiles/coder/config.yaml"),
"worker:\n harness: hermes\n",
)
.unwrap();
home
}
fn run(home: &Path, args: &[&str]) -> Output {
Command::new(bin())
.env("SUPERCODE_ORCHESTRATOR_HOME", home)
.env("SUPERCODE_ORCHESTRATOR_ENTRY", entry())
.args(args)
.output()
.expect("supercode binary runs")
}
fn stdout_of(output: &Output) -> String {
assert!(
output.status.success(),
"command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
String::from_utf8_lossy(&output.stdout).into_owned()
}
fn json_of(output: &Output) -> serde_json::Value {
serde_json::from_str(&stdout_of(output)).expect("json output")
}
fn have_node() -> bool {
Command::new("node")
.arg("--version")
.output()
.is_ok_and(|output| output.status.success())
}
#[test]
fn jobs_create_writes_through_the_packages_own_writer_and_the_readers_agree() {
if !have_node() {
eprintln!("skipped: node is not on PATH");
return;
}
let root = scratch("jobs");
let home = seed(&root);
let created = json_of(&run(
&home,
&[
"jobs",
"create",
"--harness",
"orchestrator",
"--every",
"30m",
"--message",
"check the repo",
"--name",
"repo check",
"--deliver",
"local",
"--json",
],
));
let ran = created["ran"].as_str().unwrap();
assert!(ran.contains("jobs.create"), "{ran}");
assert!(ran.ends_with("[cold]"), "{ran}");
assert!(ran.contains("orchestrator.mjs"), "{ran}");
let id = created["id"].as_str().unwrap().to_string();
assert_eq!(created["job"]["harness"], "orchestrator");
assert_eq!(created["job"]["payload"]["text"], "check the repo");
assert_eq!(created["job"]["schedule"]["display"], "every 30 min");
assert_eq!(created["job"]["deliver"]["target"], "local");
assert_eq!(created["job"]["enabled"], true);
let listed = json_of(&run(
&home,
&["jobs", "list", "--harness", "orchestrator", "--json"],
));
let jobs = listed["jobs"].as_array().unwrap();
assert_eq!(jobs.len(), 1);
assert_eq!(jobs[0]["id"], id.as_str());
assert_eq!(
listed["sources"][0]["path"],
home.join("cron/jobs.json").to_string_lossy().as_ref()
);
assert_eq!(
json_of(&run(
&home,
&["jobs", "pause", "--harness", "orchestrator", &id, "--json"]
))["job"]["enabled"],
false
);
assert_eq!(
json_of(&run(
&home,
&["jobs", "resume", "--harness", "orchestrator", &id, "--json"]
))["job"]["enabled"],
true
);
let deleted = json_of(&run(
&home,
&["jobs", "delete", "--harness", "orchestrator", &id, "--json"],
));
assert_eq!(deleted["deleted"], true);
let after = json_of(&run(
&home,
&["jobs", "list", "--harness", "orchestrator", "--json"],
));
assert!(after["jobs"].as_array().unwrap().is_empty());
std::fs::remove_dir_all(&root).ok();
}
#[test]
fn a_verb_the_reducer_refuses_surfaces_its_reason_and_writes_nothing() {
if !have_node() {
eprintln!("skipped: node is not on PATH");
return;
}
let root = scratch("refuse");
let home = seed(&root);
let output = run(
&home,
&[
"jobs",
"delete",
"--harness",
"orchestrator",
"job_does_not_exist",
"--json",
],
);
assert!(!output.status.success(), "a refusal must not exit 0");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("jobs_delete: no job job_does_not_exist"),
"{stderr}"
);
assert!(
!home.join("cron/jobs.json").exists(),
"a refusal writes nothing"
);
std::fs::remove_dir_all(&root).ok();
}
#[test]
fn profiles_create_and_delete_go_through_the_package_and_the_trash() {
if !have_node() {
eprintln!("skipped: node is not on PATH");
return;
}
let root = scratch("profiles");
let home = seed(&root);
let created = json_of(&run(
&home,
&[
"profiles",
"create",
"--harness",
"orchestrator",
"ops",
"--json",
],
));
assert!(created["ran"].as_str().unwrap().contains("profiles.create"));
assert_eq!(created["profile"]["kind"], "orchestrator_profile");
assert_eq!(
created["profile"]["home"],
home.join("profiles/ops").to_string_lossy().as_ref()
);
assert!(home.join("profiles/ops/config.yaml").is_file());
let listed = json_of(&run(
&home,
&["profiles", "list", "--harness", "orchestrator", "--json"],
));
let names: Vec<&str> = listed["profiles"]
.as_array()
.unwrap()
.iter()
.map(|row| row["name"].as_str().unwrap())
.collect();
assert_eq!(names, vec!["default", "coder", "ops"]);
let deleted = json_of(&run(
&home,
&[
"--yes",
"profiles",
"delete",
"--harness",
"orchestrator",
"ops",
"--json",
],
));
assert_eq!(deleted["deleted"], true);
assert!(!home.join("profiles/ops").exists());
let trash: Vec<PathBuf> = std::fs::read_dir(home.join("profiles/.trash"))
.expect("the trash exists")
.flatten()
.map(|entry| entry.path())
.collect();
assert_eq!(trash.len(), 1, "{trash:?}");
assert!(trash[0].join("config.yaml").is_file());
let after = json_of(&run(
&home,
&["profiles", "list", "--harness", "orchestrator", "--json"],
));
let names: Vec<&str> = after["profiles"]
.as_array()
.unwrap()
.iter()
.map(|row| row["name"].as_str().unwrap())
.collect();
assert_eq!(names, vec!["default", "coder"]);
std::fs::remove_dir_all(&root).ok();
}
#[test]
fn sessions_reset_names_the_binding_by_its_surface_and_refuses_a_session_id() {
if !have_node() {
eprintln!("skipped: node is not on PATH");
return;
}
let root = scratch("sessions");
let home = seed(&root);
let output = run(
&home,
&[
"sessions",
"reset",
"--harness",
"orchestrator",
"--surface",
"loopback|group|coder-room||",
"--json",
],
);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("no live conversation on loopback|group|coder-room||"),
"{stderr}"
);
let output = run(
&home,
&[
"sessions",
"reset",
"--harness",
"orchestrator",
"--session",
"some-runtime",
"--json",
],
);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("--surface"), "{stderr}");
let output = run(
&home,
&[
"sessions",
"archive",
"x",
"--harness",
"orchestrator",
"--json",
],
);
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("a binding is never archived or deleted"),
"{stderr}"
);
std::fs::remove_dir_all(&root).ok();
}