use std::fs;
use std::path::{Path, PathBuf};
use serde_json::{json, Value};
use supercode::claude_peer::{ClaudePeerEndpoint, CLAUDE_PEER_ENDPOINT_PREFIX};
use supercode::harness_service::HarnessSessionService;
fn temp_root(label: &str) -> PathBuf {
let path = std::env::temp_dir().join(format!(
"supercode-peer-service-{label}-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
fs::create_dir_all(&path).unwrap();
path
}
fn dead_pid() -> u32 {
let mut child = std::process::Command::new("/usr/bin/true")
.spawn()
.or_else(|_| std::process::Command::new("true").spawn())
.unwrap();
let pid = child.id();
child.wait().unwrap();
pid
}
fn write_session(root: &Path, session_id: &str, pid: u32, name: &str, status: Option<&str>) {
let projects = root.join("projects/-tmp-project");
let sessions = root.join("sessions");
fs::create_dir_all(&projects).unwrap();
fs::create_dir_all(&sessions).unwrap();
fs::write(
projects.join(format!("{session_id}.jsonl")),
format!(
"{{\"type\":\"user\",\"sessionId\":\"{session_id}\",\"cwd\":\"/tmp/project\",\
\"message\":{{\"role\":\"user\",\"content\":\"hi\"}}}}\n"
),
)
.unwrap();
let status = status
.map(|status| format!(",\"status\":\"{status}\",\"updatedAt\":1786907689006"))
.unwrap_or_default();
fs::write(
sessions.join(format!("{pid}.json")),
format!(
"{{\"pid\":{pid},\"sessionId\":\"{session_id}\",\"cwd\":\"/tmp/project\",\
\"version\":\"2.1.224\",\"peerProtocol\":1,\"kind\":\"interactive\",\
\"entrypoint\":\"cli\",\"messagingSocketPath\":\"/tmp/cc-socks/{pid}.sock\",\
\"name\":\"{name}\",\"nameSource\":\"derived\"{status}}}"
),
)
.unwrap();
}
fn discover(root: &Path) -> Vec<Value> {
let mut service = HarnessSessionService::new();
let response = futures::executor::block_on(service.handle_async(json!({
"jsonrpc": "2.0",
"id": 1,
"method": "harness.v1.sessions.discover",
"params": {
"harnesses": ["claude-code"],
"homes": {"claude_code": root.join("projects")},
},
})));
response["result"]["sessions"].as_array().unwrap().clone()
}
#[test]
fn discovery_marks_a_running_claude_session_live_and_leaves_a_crashed_one_persisted() {
let root = temp_root("discover");
write_session(
&root,
"live-one",
std::process::id(),
"peer-live",
Some("busy"),
);
write_session(&root, "stale-one", dead_pid(), "peer-stale", Some("idle"));
let sessions = discover(&root);
assert_eq!(sessions.len(), 2, "{sessions:#?}");
let live = sessions
.iter()
.find(|session| session["locator"]["session_id"] == "live-one")
.unwrap();
let stale = sessions
.iter()
.find(|session| session["locator"]["session_id"] == "stale-one")
.unwrap();
assert_eq!(stale.get("live_endpoint"), None);
assert_eq!(stale.get("live_status"), None);
assert_eq!(live["live_status"], "busy");
let endpoint = live["live_endpoint"].as_str().unwrap();
assert!(endpoint.starts_with(CLAUDE_PEER_ENDPOINT_PREFIX));
let parsed = ClaudePeerEndpoint::parse(endpoint).unwrap();
assert_eq!(parsed.pid(), std::process::id());
assert_eq!(parsed.name(), "peer-live");
assert_eq!(
parsed.socket_path(),
PathBuf::from(format!("/tmp/cc-socks/{}.sock", std::process::id()))
);
fs::remove_dir_all(root).ok();
}
#[test]
fn a_live_session_that_never_published_a_status_carries_an_endpoint_without_one() {
let root = temp_root("no-status");
write_session(&root, "live-two", std::process::id(), "peer-quiet", None);
let sessions = discover(&root);
assert_eq!(sessions.len(), 1);
assert!(sessions[0]["live_endpoint"].is_string());
assert_eq!(sessions[0].get("live_status"), None);
fs::remove_dir_all(root).ok();
}
#[test]
fn messaging_a_harness_without_a_live_registry_refuses_by_name() {
let mut service = HarnessSessionService::new();
let response = futures::executor::block_on(service.handle_async(json!({
"jsonrpc": "2.0",
"id": 1,
"method": "harness.v1.sessions.message",
"params": {
"locator": {
"harness": "codex",
"session_id": "cx-1",
"storage": {"kind": "file", "path": "/tmp/rollout.jsonl"},
},
"text": "hello",
},
})));
let result = &response["result"];
assert_eq!(result["delivered_to_bus"], false);
assert_eq!(result["refusal"]["reason"], "harness_unsupported");
assert!(result["refusal"]["message"]
.as_str()
.unwrap()
.contains("codex"));
}
#[test]
fn messaging_a_persisted_only_claude_session_refuses_without_spawning_a_courier() {
let root = temp_root("not-live");
write_session(&root, "stale-two", dead_pid(), "peer-stale", Some("idle"));
let mut service = HarnessSessionService::new();
let response = futures::executor::block_on(service.handle_async(json!({
"jsonrpc": "2.0",
"id": 1,
"method": "harness.v1.sessions.message",
"params": {
"locator": {
"harness": "claude-code",
"session_id": "stale-two",
"storage": {"kind": "file", "path": root.join("projects/-tmp-project/stale-two.jsonl")},
},
"text": "hello",
"homes": {"claude_code": root.join("projects")},
},
})));
let result = &response["result"];
assert_eq!(result["delivered_to_bus"], false);
assert_eq!(result["refusal"]["reason"], "not_live");
fs::remove_dir_all(root).ok();
}
#[test]
fn the_service_advertises_the_message_method() {
let mut service = HarnessSessionService::new();
let response = futures::executor::block_on(service.handle_async(json!({
"jsonrpc": "2.0",
"id": 1,
"method": "harness.v1.capabilities",
"params": {},
})));
assert!(response["result"]["methods"]
.as_array()
.unwrap()
.iter()
.any(|method| method == "harness.v1.sessions.message"));
}