mod common;
use common::*;
use std::process::Command;
fn inject_scope_cmd(ws: &TempWorkspace, envs: &[(&str, &str)]) -> Command {
let mut cmd = Command::new(ccsm_binary());
cmd.current_dir(ws.path())
.env_remove("CCSM_SESSION")
.env_remove("CCSM_WORKTREE")
.env_remove("CCSM_WORKSPACE")
.env("HOME", ws.home());
for (k, v) in envs {
cmd.env(k, v);
}
cmd
}
fn run_inject_scope(ws: &TempWorkspace, envs: &[(&str, &str)]) -> (String, String, bool) {
let mut cmd = inject_scope_cmd(ws, envs);
cmd.arg("inject-scope");
let out = cmd.output().expect("inject-scope execution failed");
(
String::from_utf8_lossy(&out.stdout).to_string(),
String::from_utf8_lossy(&out.stderr).to_string(),
out.status.success(),
)
}
fn run_inject_scope_with_name(ws: &TempWorkspace, name: &str, envs: &[(&str, &str)]) -> (String, String, bool) {
let mut cmd = inject_scope_cmd(ws, envs);
cmd.args(["inject-scope", name]);
let out = cmd.output().expect("inject-scope execution failed");
(
String::from_utf8_lossy(&out.stdout).to_string(),
String::from_utf8_lossy(&out.stderr).to_string(),
out.status.success(),
)
}
fn setup_session(ws: &TempWorkspace) {
ws.run_ok(&["new", "test-session", "-g", "test goal", "-b", "main"]);
ws.run_ok(&["start", "test-session"]);
}
#[test]
fn inject_scope_basic_output() {
ensure_built();
let ws = TempWorkspace::new();
setup_session(&ws);
let (stdout, stderr, success) = run_inject_scope(&ws, &[("CCSM_SESSION", "test-session")]);
assert!(success, "inject-scope should succeed: {stderr}");
assert!(stdout.contains("ACTIVE SESSION: test-session"), "stdout: {stdout}");
assert!(stdout.contains("GOAL: test goal"), "stdout: {stdout}");
assert!(stdout.contains("<system-reminder>"), "stdout: {stdout}");
assert!(stdout.contains("</system-reminder>"), "stdout: {stdout}");
}
#[test]
fn inject_scope_no_session() {
ensure_built();
let ws = TempWorkspace::new();
setup_session(&ws);
let (stdout, _stderr, success) = run_inject_scope(&ws, &[]);
assert!(success, "inject-scope should return Ok even without session");
assert!(stdout.is_empty() || !stdout.contains("ACTIVE SESSION"),
"no session output should appear:\n{stdout}");
}
#[test]
fn inject_scope_name_flag() {
ensure_built();
let ws = TempWorkspace::new();
setup_session(&ws);
let (stdout, stderr, success) = run_inject_scope_with_name(&ws, "test-session", &[]);
assert!(success, "inject-scope --name should succeed: {stderr}");
assert!(stdout.contains("ACTIVE SESSION: test-session"), "stdout: {stdout}");
}
#[test]
fn inject_scope_worktree_env_var() {
ensure_built();
let ws = TempWorkspace::new();
setup_session(&ws);
let wt_path = ws.path().join(".claude").join("worktrees").join("test-session");
let (stdout, _stderr, success) = run_inject_scope(&ws, &[
("CCSM_SESSION", "test-session"),
("CCSM_WORKTREE", &wt_path.to_string_lossy()),
]);
assert!(success);
assert!(stdout.contains("WORKTREE BOUNDARY"), "WORKTREE BOUNDARY section should be present:\n{stdout}");
assert!(stdout.contains(&*wt_path.to_string_lossy()),
"WORKTREE path should match CCSM_WORKTREE env var:\n{stdout}");
assert!(stdout.contains("DON'T:"), "DON'T section should be present:\n{stdout}");
assert!(stdout.contains("DO:"), "DO section should be present:\n{stdout}");
assert!(stdout.contains("ASK FIRST"), "ask-constraint should be present:\n{stdout}");
}
#[test]
fn inject_scope_worktree_env_var_overrides_derived() {
ensure_built();
let ws = TempWorkspace::new();
setup_session(&ws);
let override_path = "/tmp/custom-worktree-path";
let (stdout, _stderr, success) = run_inject_scope(&ws, &[
("CCSM_SESSION", "test-session"),
("CCSM_WORKTREE", override_path),
]);
assert!(success);
assert!(stdout.contains(override_path),
"WORKTREE path should be the CCSM_WORKTREE value, not derived:\n{stdout}");
}
#[test]
fn inject_scope_worktree_line_omitted_when_no_worktree() {
ensure_built();
let ws = TempWorkspace::new();
ws.run_ok(&["new", "no-wt-session", "-g", "no worktree"]);
ws.run_ok(&["start", "no-wt-session"]);
let (stdout, _stderr, success) = run_inject_scope(&ws, &[("CCSM_SESSION", "no-wt-session")]);
assert!(success);
assert!(!stdout.contains("WORKTREE BOUNDARY"),
"WORKTREE BOUNDARY section should be absent when no worktree exists:\n{stdout}");
}
#[test]
fn inject_scope_branch_check() {
ensure_built();
let ws = TempWorkspace::new();
setup_session(&ws);
let (stdout, _stderr, success) = run_inject_scope(&ws, &[("CCSM_SESSION", "test-session")]);
assert!(success);
assert!(stdout.contains("ACTIVE SESSION"), "stdout: {stdout}");
}