use crate::harness::*;
#[test]
fn dashed_teammate_name_id_round_trips_as_target() {
let enc = "-Users-testuser-Projects-dashmate";
let sess = "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d";
let id = "aP1-engine-9cf2f06d6235ca64";
let h = Home::new();
h.write(
&format!("{enc}/{sess}.jsonl"),
concat!(
r#"{"type":"user","uuid":"u0","timestamp":"2026-06-07T05:00:00.000Z","message":{"role":"user","content":"go"}}"#, "\n",
r#"{"type":"assistant","uuid":"a0","timestamp":"2026-06-07T05:00:01.000Z","message":{"role":"assistant","content":[{"type":"tool_use","id":"call0","name":"Agent","input":{"name":"P1-engine","subagent_type":"executor","description":"do it"}}]}}"#, "\n",
),
);
h.write(
&format!("{enc}/{sess}/subagents/agent-{id}.jsonl"),
concat!(
r#"{"type":"user","isSidechain":true,"agentId":"aP1-engine-9cf2f06d6235ca64","timestamp":"2026-06-07T05:00:02.000Z","message":{"role":"user","content":"teammate: probe the dashy widget"}}"#, "\n",
r#"{"type":"assistant","timestamp":"2026-06-07T05:00:03.000Z","message":{"role":"assistant","content":[{"type":"text","text":"probed"}]}}"#, "\n",
),
);
h.write(
&format!("{enc}/{sess}/subagents/agent-{id}.meta.json"),
r#"{"agentType":"P1-engine","name":"P1-engine","taskKind":"in_process_teammate"}"#,
);
let l = h.run(&["list", &format!("@{id}")]);
assert!(l.success, "list @dashed-teammate-id: {}", l.stderr);
assert!(
l.stdout.contains("SUBAGENT") && l.stdout.contains(id),
"the subagent banner names the teammate id: {}",
l.stdout
);
let s = h.run(&["show", &format!("@{id}"), "--line", "1"]);
assert!(s.success, "show @dashed-teammate-id: {}", s.stderr);
assert!(
s.stdout.contains("teammate: probe the dashy widget"),
"show fetches from the teammate transcript: {}",
s.stdout
);
}
#[test]
fn at_agent_hex_subtree_includes_descendants_unless_no_subagents() {
let enc = "-Users-testuser-Projects-agtree";
let sess = "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d";
let parent = "aaaa1111bbbb2222c"; let child = "cccc3333dddd4444e"; let h = Home::new();
h.write(
&format!("{enc}/{sess}.jsonl"),
concat!(
r#"{"type":"user","uuid":"u0","timestamp":"2026-06-07T05:00:00.000Z","message":{"role":"user","content":"go"}}"#, "\n",
r#"{"type":"assistant","uuid":"a0","timestamp":"2026-06-07T05:00:01.000Z","message":{"role":"assistant","content":[{"type":"tool_use","id":"call_parent","name":"Agent","input":{"description":"parent"}}]}}"#, "\n",
),
);
h.write(
&format!("{enc}/{sess}/subagents/agent-{parent}.jsonl"),
concat!(
r#"{"type":"user","isSidechain":true,"agentId":"aaaa1111bbbb2222c","timestamp":"2026-06-07T05:00:02.000Z","message":{"role":"user","content":"PARENTWORK"}}"#, "\n",
r#"{"type":"assistant","timestamp":"2026-06-07T05:00:03.000Z","message":{"role":"assistant","content":[{"type":"tool_use","id":"call_child","name":"Agent","input":{"description":"child"}}]}}"#, "\n",
),
);
h.write(
&format!("{enc}/{sess}/subagents/agent-{parent}.meta.json"),
r#"{"agentType":"general-purpose","toolUseId":"call_parent"}"#,
);
h.write(
&format!("{enc}/{sess}/subagents/agent-{child}.jsonl"),
concat!(
r#"{"type":"user","isSidechain":true,"agentId":"cccc3333dddd4444e","timestamp":"2026-06-07T05:00:04.000Z","message":{"role":"user","content":"CHILDWORK"}}"#, "\n",
r#"{"type":"assistant","timestamp":"2026-06-07T05:00:05.000Z","message":{"role":"assistant","content":[{"type":"text","text":"ok"}]}}"#, "\n",
),
);
h.write(
&format!("{enc}/{sess}/subagents/agent-{child}.meta.json"),
r#"{"agentType":"Explore","toolUseId":"call_child"}"#,
);
let full = h.run(&["search", "WORK", &format!("@{parent}")]);
assert!(full.success, "stderr: {}", full.stderr);
assert!(
full.stdout.contains("PARENTWORK"),
"parent in scope: {}",
full.stdout
);
assert!(
full.stdout.contains("CHILDWORK"),
"descendant child in scope: {}",
full.stdout
);
let alone = h.run(&["search", "WORK", &format!("@{parent}"), "--no-subagents"]);
assert!(alone.success, "stderr: {}", alone.stderr);
assert!(
alone.stdout.contains("PARENTWORK"),
"parent still in scope: {}",
alone.stdout
);
assert!(
!alone.stdout.contains("CHILDWORK"),
"child EXCLUDED under --no-subagents: {}",
alone.stdout
);
}
#[test]
fn cross_surface_session_id_is_identical_for_a_subagent() {
let h = populated_home();
let files = h.run(&[
"files",
at(SESS).as_str(),
"--by",
"file",
"--format",
"json",
]);
let search = h.run(&["search", "", ENC, at(SESS).as_str(), "--format", "json"]);
let turns = h.run(&[
"verbatim",
at(SESS).as_str(),
"--subagents",
"--budget",
"8000",
"--format",
"json",
]);
for (name, out) in [("files", &files), ("search", &search), ("verbatim", &turns)] {
assert!(out.success, "{name} stderr: {}", out.stderr);
assert!(
!out.stdout.contains("\"agent-aaa111\"") && !out.stdout.contains("agent-aaa111"),
"{name} leaked an agent- prefixed session_id: {}",
out.stdout
);
}
assert!(
files.stdout.contains("aaa111") || turns.stdout.contains("aaa111"),
"no surface emitted the bare subagent id; files={} turns={}",
files.stdout,
turns.stdout
);
}
#[test]
fn at_agent_hex_scopes_to_the_subtree() {
let enc = "-Users-testuser-Projects-agentscope";
let sess = "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d";
let hex = "aaa111bbb222ccc33"; let h = Home::new();
h.write(
&format!("{enc}/{sess}.jsonl"),
concat!(
r#"{"type":"user","uuid":"u0","timestamp":"2026-06-07T05:00:00.000Z","message":{"role":"user","content":"go"}}"#, "\n",
r#"{"type":"assistant","uuid":"a0","timestamp":"2026-06-07T05:00:01.000Z","message":{"role":"assistant","content":[{"type":"tool_use","id":"call0","name":"Agent","input":{"description":"do it"}}]}}"#, "\n",
),
);
h.write(
&format!("{enc}/{sess}/subagents/agent-{hex}.jsonl"),
concat!(
r#"{"type":"user","isSidechain":true,"agentId":"aaa111bbb222ccc33","timestamp":"2026-06-07T05:00:02.000Z","message":{"role":"user","content":"sub: the WIDGET work"}}"#, "\n",
r#"{"type":"assistant","timestamp":"2026-06-07T05:00:03.000Z","message":{"role":"assistant","content":[{"type":"text","text":"sub done"}]}}"#, "\n",
),
);
let s = h.run(&["search", "WIDGET", &format!("@{hex}")]);
assert!(s.success, "stderr: {}", s.stderr);
assert!(
s.stdout.contains(hex),
"scoped to the subagent: {}",
s.stdout
);
assert!(
s.stdout.contains("subagent"),
"branded as a subagent: {}",
s.stdout
);
let miss = h.run(&["search", "x", "@deadbeefdeadbeef0"]);
assert!(!miss.success);
assert!(
miss.stderr.contains("no subagent") && miss.stderr.contains("agents"),
"guides to agents listing: {}",
miss.stderr
);
}
#[test]
fn agent_twelve_hex_fallback_ambiguity_fails_loud() {
let h = Home::new();
let enc = "-Users-dev-example-project";
let sess = "55667788-9900-4000-8000-00000000000a";
h.write(
&format!("{enc}/{sess}.jsonl"),
concat!(
r#"{"type":"user","timestamp":"2026-06-07T05:00:00.000Z","message":{"role":"user","content":"lead"}}"#, "\n",
),
);
let twin_a = "abcd1234abcd1234aaaa";
let twin_b = "abcd1234abcd1234bbbb";
for (agent, word) in [(twin_a, "TWINALPHA"), (twin_b, "TWINBETA")] {
h.write(
&format!("{enc}/{sess}/subagents/agent-{agent}.jsonl"),
&format!(
"{}\n",
format_args!(
r#"{{"type":"user","isSidechain":true,"agentId":"{agent}","timestamp":"2026-06-07T05:00:02.000Z","message":{{"role":"user","content":"seed {word}"}}}}"#
),
),
);
}
let ambi = h.run(&["search", "TWIN", &format!("@{}", &twin_a[..16])]);
assert!(!ambi.success, "ambiguous fallback must error");
assert!(
ambi.stderr.contains("AMBIGUOUS")
&& ambi.stderr.contains(twin_a)
&& ambi.stderr.contains(twin_b),
"the fallback names both candidates: {}",
ambi.stderr
);
}
#[test]
fn at_token_unrecognized_shapes_fail_loud_never_path_fallthrough() {
let h = populated_home();
for tok in ["@a", "@22", "@224"] {
let out = h.run(&["list", tok]);
assert!(!out.success, "{tok} must hard-error: {}", out.stdout);
assert!(
out.stderr.contains("too short") && out.stderr.contains("4-11"),
"{tok} names the prefix minimum: {}",
out.stderr
);
assert!(
!out.stderr.contains("no Claude Code project dir"),
"{tok} must not fall through to path resolution: {}",
out.stderr
);
}
for tok in ["@notanid", "@1234-ab", "@"] {
let out = h.run(&["list", tok]);
assert!(!out.success, "{tok} must hard-error: {}", out.stdout);
assert!(
out.stderr.contains("not a recognized @-target"),
"{tok} names the grammar: {}",
out.stderr
);
}
let enc = h.run(&["list", &format!("@{ENC}")]);
assert!(enc.success, "stderr: {}", enc.stderr);
assert!(
enc.stdout.contains(SESS),
"lists the fixture session: {}",
enc.stdout
);
}
#[test]
fn windows_drive_encoded_dir_targets_resolve() {
let h = Home::new();
let enc = "C--Users-dev-winproj";
let sess = "99aabbcc-ddee-4000-8000-00000000000e";
h.write(
&format!("{enc}/{sess}.jsonl"),
concat!(
r#"{"type":"user","timestamp":"2026-06-07T05:00:00.000Z","message":{"role":"user","content":"win work"}}"#, "\n",
),
);
let bare = h.run(&["list", enc]);
assert!(bare.success, "stderr: {}", bare.stderr);
assert!(
bare.stdout.contains(sess),
"bare drive-encoded token resolves: {}",
bare.stdout
);
let at_form = h.run(&["list", &format!("@{enc}")]);
assert!(at_form.success, "stderr: {}", at_form.stderr);
assert!(
at_form.stdout.contains(sess),
"@-prefixed drive-encoded token resolves: {}",
at_form.stdout
);
}
#[test]
fn target_jsonl_file_path_scopes_to_session() {
let h = populated_home();
let jsonl = h.projects().join(format!("{ENC}/{SESS}.jsonl"));
let out = h.run(&["search", "carry", jsonl.to_str().unwrap(), "--no-subagents"]);
assert!(out.success, "stderr: {}", out.stderr);
assert!(
out.stdout.contains(&format!("{}\u{b7}t", &SESS[..8])),
"scoped to the session: {}",
out.stdout
);
let bad = h.run(&["search", "carry", "/no/such/session.jsonl"]);
assert!(!bad.success);
assert!(
bad.stderr.contains("no session transcript at"),
"honest missing-file error: {}",
bad.stderr
);
}
#[test]
fn target_at_uuid_routes_to_session() {
let h = populated_home();
let out = h.run(&["agents", &format!("@{SESS}")]);
assert!(out.success, "stderr: {}", out.stderr);
assert!(
out.stdout.contains("builtin-task"),
"resolved the session: {}",
out.stdout
);
}
#[test]
fn target_at_main_resolves_env_session() {
let h = populated_home();
let out = h.run_with_env(&["agents", "@main"], &[("CLAUDE_CODE_SESSION_ID", SESS)]);
assert!(out.success, "stderr: {}", out.stderr);
assert!(
out.stdout.contains("builtin-task"),
"@main → env session: {}",
out.stdout
);
let no_env = h.run(&["agents", "@main"]);
assert!(!no_env.success);
assert!(
no_env.stderr.contains("CLAUDE_CODE_SESSION_ID is not set"),
"guidance when env absent: {}",
no_env.stderr
);
}
#[test]
fn target_at_encoded_dir_resolves() {
let h = populated_home();
let out = h.run(&["agents", &format!("@{ENC}")]);
assert!(out.success, "stderr: {}", out.stderr);
assert!(
out.stdout.contains("builtin-task"),
"@encoded resolved: {}",
out.stdout
);
}
#[test]
fn target_at_uuid_prefix_resolves_unique_and_errors_on_ambiguity() {
let h = Home::new();
let a = "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d";
let b = "0a1b2c3d-ffff-4a6b-8c7d-9e0f1a2b3c4d";
let c = "deadbeef-1111-2222-3333-444455556666";
for s in [a, b, c] {
h.write(
&format!("{ENC}/{s}.jsonl"),
&format!(
"{{\"type\":\"user\",\"sessionId\":\"{s}\",\"cwd\":\"/p\",\"timestamp\":\"2026-06-07T05:00:00.000Z\",\"message\":{{\"role\":\"user\",\"content\":\"hi\"}}}}\n"
),
);
}
let uniq = h.run(&["list", "@deadbeef"]);
assert!(uniq.success, "stderr: {}", uniq.stderr);
assert!(
uniq.stdout.contains(c),
"unique prefix resolved: {}",
uniq.stdout
);
assert!(
!uniq.stdout.contains(a),
"scoped to ONLY the matched session: {}",
uniq.stdout
);
let amb = h.run(&["list", "@0a1b2c3d"]);
assert!(!amb.success, "ambiguous prefix must error: {}", amb.stdout);
assert!(
amb.stderr.contains("AMBIGUOUS"),
"says ambiguous: {}",
amb.stderr
);
assert!(
amb.stderr.contains(a) && amb.stderr.contains(b),
"lists both candidates: {}",
amb.stderr
);
let none = h.run(&["list", "@99999999"]);
assert!(!none.success);
assert!(
none.stderr.contains("no session or agent id starts with"),
"{}",
none.stderr
);
}
#[test]
fn uuid_prefix_minimum_boundary_is_exactly_four() {
let h = Home::new();
h.write(
"-Users-testuser-Projects-pfx/abcd1234-4e5f-4a6b-8c7d-9e0f1a2b3c4d.jsonl",
"{\"type\":\"user\",\"uuid\":\"u0\",\"timestamp\":\"2026-06-07T05:00:00.000Z\",\"message\":{\"role\":\"user\",\"content\":\"go\"}}\n",
);
let ok = h.run(&["list", "@abcd"]);
assert!(
ok.success && ok.stdout.contains("abcd1234"),
"4-hex prefix resolves: {}\n{}",
ok.stderr,
ok.stdout
);
let short = h.run(&["list", "@abc"]);
assert!(
!short.success && short.stderr.contains("too short"),
"3-hex errors with guidance: {}",
short.stderr
);
}
#[test]
fn bare_id_shaped_tokens_get_the_at_hint() {
let h = Home::new();
let p = h.run(&["list", "abcd1234"]);
assert!(
!p.success && p.stderr.contains("did you mean '@abcd1234'"),
"prefix shape hint: {}",
p.stderr
);
let a = h.run(&["list", "aabbccdd11223344"]);
assert!(
!a.success && a.stderr.contains("did you mean '@aabbccdd11223344'"),
"agent-hex shape hint: {}",
a.stderr
);
}
#[test]
fn bare_basename_jsonl_target_resolves_from_its_own_dir() {
let h = Home::new();
let sess = "3f2e1d0c-9b8a-4756-a432-10fedcba9876";
let enc = "-Users-dev-example-project";
let top = h.write(
&format!("{enc}/{sess}.jsonl"),
concat!(
r#"{"type":"user","uuid":"u1","timestamp":"2026-06-07T05:00:00.000Z","message":{"role":"user","content":"drifting buoy"}}"#,
"\n",
r#"{"type":"assistant","uuid":"a1","parentUuid":"u1","timestamp":"2026-06-07T05:00:01.000Z","message":{"role":"assistant","content":[{"type":"text","text":"charted"}]}}"#,
"\n",
),
);
let sub = h.write(
&format!("{enc}/{sess}/subagents/agent-b7c6d5e4f3a29180.jsonl"),
concat!(
r#"{"type":"user","uuid":"su1","timestamp":"2026-06-07T05:00:02.000Z","message":{"role":"user","content":"probe the reef"}}"#,
"\n",
r#"{"type":"assistant","uuid":"sa1","parentUuid":"su1","timestamp":"2026-06-07T05:00:03.000Z","message":{"role":"assistant","content":[{"type":"text","text":"reef probed"}]}}"#,
"\n",
),
);
let abs = h.run(&["list", top.to_str().unwrap()]);
assert!(abs.success, "absolute: {}", abs.stderr);
let dir = top.parent().unwrap();
let dot = h.run_full(&["list", &format!("./{sess}.jsonl")], &[], Some(dir));
assert!(dot.success, "./relative: {}", dot.stderr);
let subdir = h.run_full(
&["list", &format!("{enc}/{sess}.jsonl")],
&[],
Some(dir.parent().unwrap()),
);
assert!(subdir.success, "subdir-relative: {}", subdir.stderr);
let bare = h.run_full(&["list", &format!("{sess}.jsonl")], &[], Some(dir));
assert!(bare.success, "bare basename: {}", bare.stderr);
for out in [&abs, &dot, &subdir, &bare] {
assert!(
out.stdout.contains(sess) && out.stdout.contains("drifting buoy"),
"same session row from every spelling:\n{}",
out.stdout
);
}
let sdir = sub.parent().unwrap();
let sbare = h.run_full(
&["list", "agent-b7c6d5e4f3a29180.jsonl", "--no-subagents"],
&[],
Some(sdir),
);
assert!(sbare.success, "bare subagent basename: {}", sbare.stderr);
assert!(
sbare.stdout.contains("SUBAGENT b7c6d5e4f3a29180")
&& sbare.stdout.contains("probe the reef"),
"classified as the subagent, bare id, own content:\n{}",
sbare.stdout
);
}