use std::io::{Read, Write};
use std::net::TcpListener;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio};
use std::time::Duration;
use supercode::reduce::{project, ReductionLog, ReductionPolicy};
use supercode::session::{Session, SessionFormat};
use supercode::tokens::estimate_view_tokens;
fn bin() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_supercode"))
}
fn fresh_home(tag: &str) -> PathBuf {
let nanos = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos();
let dir = std::env::temp_dir().join(format!(
"supercode-c4c7-{tag}-{}-{nanos}",
std::process::id()
));
std::fs::create_dir_all(&dir).unwrap();
dir
}
fn run(home: &Path, extra: &[&str]) -> Output {
run_with_stdin(home, extra, "")
}
fn run_with_stdin(home: &Path, extra: &[&str], stdin: &str) -> Output {
let mut args = vec!["--api-key", "x", "--base-url", "http://127.0.0.1:1"];
args.extend_from_slice(extra);
let mut child = Command::new(bin())
.env("SUPERCODE_HOME", home)
.env_remove("OPENROUTER_API_KEY")
.env_remove("OPENAI_API_KEY")
.env_remove("ANTHROPIC_API_KEY")
.args(&args)
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.expect("failed to spawn the supercode binary");
child
.stdin
.as_mut()
.unwrap()
.write_all(stdin.as_bytes())
.unwrap();
child.wait_with_output().expect("child process failed")
}
fn spawn_capturing_sse_stub(
reply: &'static str,
) -> (std::net::SocketAddr, std::thread::JoinHandle<String>) {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind stub listener");
let addr = listener.local_addr().unwrap();
let handle = std::thread::spawn(move || {
let (mut sock, _) = listener.accept().expect("accept one connection");
sock.set_read_timeout(Some(Duration::from_millis(500)))
.expect("set read timeout");
let mut request = Vec::new();
let mut buf = [0u8; 65_536];
loop {
match sock.read(&mut buf) {
Ok(0) => break,
Ok(n) => request.extend_from_slice(&buf[..n]),
Err(e)
if e.kind() == std::io::ErrorKind::WouldBlock
|| e.kind() == std::io::ErrorKind::TimedOut =>
{
break
}
Err(e) => panic!("stub read failed: {e}"),
}
}
let sse = format!(
"data: {{\"choices\":[{{\"delta\":{{\"content\":\"{reply}\"}}}}]}}\n\ndata: [DONE]\n\n"
);
let response = format!(
"HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{sse}",
sse.len()
);
sock.write_all(response.as_bytes()).unwrap();
String::from_utf8(request).expect("request must be UTF-8")
});
(addr, handle)
}
fn run_at(home: &Path, base_url: &str, extra: &[&str]) -> Output {
let mut args = vec!["--api-key", "x", "--base-url", base_url];
args.extend_from_slice(extra);
Command::new(bin())
.env("SUPERCODE_HOME", home)
.env_remove("OPENROUTER_API_KEY")
.env_remove("OPENAI_API_KEY")
.env_remove("ANTHROPIC_API_KEY")
.args(args)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.expect("failed to spawn the supercode binary")
}
fn stdout(out: &Output) -> String {
String::from_utf8_lossy(&out.stdout).into_owned()
}
fn stderr(out: &Output) -> String {
String::from_utf8_lossy(&out.stderr).into_owned()
}
fn write_big_fixture(dir: &Path) -> PathBuf {
let sid = "22222222-3333-4444-5555-666666666666";
let mut lines: Vec<String> = Vec::new();
lines.push(
serde_json::json!({
"type": "user",
"message": {"role": "user", "content": "please investigate the failing test"},
"uuid": "u0", "parentUuid": null,
"timestamp": "2026-06-07T18:38:00.000Z", "sessionId": sid,
"cwd": "/tmp/proj", "userType": "external",
})
.to_string(),
);
let big = "x".repeat(20_000);
for i in 0..4 {
let tool_id = format!("toolu_{i:02}");
lines.push(
serde_json::json!({
"type": "assistant",
"message": {"role": "assistant", "content": [
{"type": "tool_use", "id": tool_id, "name": "bash", "input": {"command": "cargo test"}}
]},
"uuid": format!("a{i}"),
"parentUuid": if i == 0 { "u0".to_string() } else { format!("t{}", i - 1) },
"timestamp": "2026-06-07T18:38:01.000Z", "sessionId": sid,
})
.to_string(),
);
let content = if i == 0 {
big.clone()
} else {
"ok".to_string()
};
lines.push(
serde_json::json!({
"type": "user",
"message": {"role": "user", "content": [
{"tool_use_id": tool_id, "type": "tool_result", "content": [{"type": "text", "text": content}]}
]},
"uuid": format!("t{i}"), "parentUuid": format!("a{i}"),
"timestamp": "2026-06-07T18:38:02.000Z", "sessionId": sid,
"toolUseResult": {"status": "completed"},
})
.to_string(),
);
}
let path = dir.join("big_claude_session.jsonl");
std::fs::write(&path, lines.join("\n") + "\n").unwrap();
path
}
fn write_pass_order_fixture(dir: &Path) -> PathBuf {
let sid = "33333333-4444-5555-6666-777777777777";
let mut lines = vec![serde_json::json!({
"type": "user", "sessionId": sid, "cwd": dir,
"uuid": "root", "parentUuid": null,
"timestamp": "2026-07-16T00:00:00.000Z",
"message": {"role": "user", "content": "attribute the completed continuation"}
})
.to_string()];
for i in 0..12 {
let tool_id = format!("toolu_order_{i:02}");
lines.push(
serde_json::json!({
"type": "assistant", "sessionId": sid,
"uuid": format!("a{i}"), "parentUuid": if i == 0 { "root".to_string() } else { format!("t{}", i - 1) },
"timestamp": "2026-07-16T00:00:01.000Z",
"message": {"role": "assistant", "content": [
{"type": "text", "text": format!("analysis-{i}-{}", "y".repeat(20_000))},
{"type": "tool_use", "id": tool_id, "name": "bash",
"input": {"command": "cargo test"}}
]}
})
.to_string(),
);
lines.push(
serde_json::json!({
"type": "user", "sessionId": sid,
"uuid": format!("t{i}"), "parentUuid": format!("a{i}"),
"timestamp": "2026-07-16T00:00:02.000Z",
"message": {"role": "user", "content": [{
"type": "tool_result", "tool_use_id": tool_id,
"content": [{"type": "text", "text": format!("result-{i}-{}", "x".repeat(20_000))}]
}]},
"toolUseResult": {"status": "completed"}
})
.to_string(),
);
}
let path = dir.join("pass_order_claude_session.jsonl");
std::fs::write(&path, lines.join("\n") + "\n").unwrap();
path
}
fn expected_id(fixture_path: &Path) -> String {
let session = Session::load(fixture_path).unwrap();
let (_, log) = project(
&session,
&ReductionPolicy::default(),
&ReductionLog::default(),
);
assert_eq!(
log.reductions.len(),
1,
"fixture must yield exactly one reduction"
);
log.reductions[0].id.clone()
}
fn mint_reduced_session(home: &Path, fixture: &Path) -> String {
let out = run(home, &["resume", fixture.to_str().unwrap(), "--reduced"]);
let err = stderr(&out);
let line = err
.lines()
.find(|l| l.contains("full copy:"))
.unwrap_or_else(|| panic!("no `full copy:` line in:\n{err}"));
let sidecar_path = line.split("full copy:").nth(1).unwrap().trim();
Path::new(sidecar_path)
.file_name()
.unwrap()
.to_str()
.unwrap()
.strip_suffix(".sidecar.jsonl")
.unwrap()
.to_string()
}
fn sessions_dir(home: &Path) -> PathBuf {
home.join("sessions")
}
#[test]
fn show_reductions_lists_exactly_the_sidecar_ids_and_json_count_matches() {
let home = fresh_home("show-basic");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
let log_path = sessions_dir(&home).join(format!("{name}.reduction.json"));
let log_json: serde_json::Value =
serde_json::from_str(&std::fs::read_to_string(&log_path).unwrap()).unwrap();
let expected_ids: Vec<String> = log_json["reductions"]
.as_array()
.unwrap()
.iter()
.map(|r| r["id"].as_str().unwrap().to_string())
.collect();
assert_eq!(expected_ids.len(), 1);
let out = run(&home, &["sessions", "show-reductions", &name]);
assert!(
out.status.success(),
"show-reductions must exit 0: {}",
stderr(&out)
);
let table = stdout(&out);
for id in &expected_ids {
assert!(table.contains(id), "table must list id {id}:\n{table}");
}
assert_eq!(table.matches(" B ").count(), expected_ids.len());
let json_out = run(&home, &["sessions", "show-reductions", &name, "--json"]);
assert!(json_out.status.success());
let log: serde_json::Value = serde_json::from_str(&stdout(&json_out)).unwrap();
assert_eq!(
log["reductions"].as_array().unwrap().len(),
expected_ids.len()
);
let banner_err = {
let home2 = fresh_home("show-basic-banner");
let out2 = run(&home2, &["resume", fixture.to_str().unwrap(), "--reduced"]);
let e = stderr(&out2);
std::fs::remove_dir_all(&home2).ok();
e
};
let stub_count_line = banner_err
.lines()
.find(|l| l.contains("stubs"))
.expect("banner must have a stub-count line");
assert!(
stub_count_line.contains(&format!("{} stubs", expected_ids.len())),
"banner stub count must match: {stub_count_line}"
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn show_reductions_on_non_reduced_session_prints_notice_and_exits_zero() {
let home = fresh_home("show-nonreduced");
let dir = sessions_dir(&home);
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(dir.join("plain-sess.jsonl"), "{}\n").unwrap();
std::fs::write(
dir.join("plain-sess.meta.json"),
serde_json::json!({"name": "plain-sess", "title": "t"}).to_string(),
)
.unwrap();
let out = run(&home, &["sessions", "show-reductions", "plain-sess"]);
assert!(out.status.success(), "must exit 0: {}", stderr(&out));
assert!(
stdout(&out).contains("not a reduced session — nothing to show"),
"got: {}",
stdout(&out)
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn corrupt_sidecar_record_fails_show_reductions_and_convert_writes_no_file() {
let home = fresh_home("corrupt");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
let id = expected_id(&fixture);
let sidecar_path = sessions_dir(&home).join(format!("{name}.sidecar.jsonl"));
let sidecar = std::fs::read_to_string(&sidecar_path).unwrap();
assert!(
sidecar.contains("xxxxx"),
"fixture content must be present verbatim"
);
let tampered = sidecar.replacen("xxxxx", "yyyyy", 1);
std::fs::write(&sidecar_path, tampered).unwrap();
let show = run(&home, &["sessions", "show-reductions", &name]);
assert!(
!show.status.success(),
"must exit non-zero on a corrupt record"
);
assert!(
stderr(&show).contains(&id),
"error must name the offending id {id}: {}",
stderr(&show)
);
let out_path = home.join("out.jsonl");
let conv = run(
&home,
&[
"convert",
&name,
"--to",
"codex",
"-o",
out_path.to_str().unwrap(),
],
);
assert!(
!conv.status.success(),
"convert must exit non-zero on a corrupt record"
);
assert!(
stderr(&conv).contains(&id),
"convert error must name the offending id {id}: {}",
stderr(&conv)
);
assert!(
!out_path.exists(),
"convert must write no output file on failure"
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn missing_log_with_persisted_stubs_fails_every_reduced_store_surface() {
let home = fresh_home("missing-log-with-stubs");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
let dir = sessions_dir(&home);
let persisted = run_with_stdin(&home, &["chat", "--last"], "/reduce\n");
assert!(persisted.status.success(), "{}", stderr(&persisted));
let view = std::fs::read_to_string(dir.join(format!("{name}.jsonl"))).unwrap();
assert!(view.contains("sc-reduced"), "fixture must persist a stub");
std::fs::remove_file(dir.join(format!("{name}.reduction.json"))).unwrap();
let out_path = home.join("must-not-exist.jsonl");
let commands: Vec<Vec<&str>> = vec![
vec!["inspect", &name, "--json"],
vec!["sessions", "show-reductions", &name],
vec!["chat", "--last"],
vec![
"convert",
&name,
"--to",
"codex",
"--out",
out_path.to_str().unwrap(),
],
];
for args in commands {
let out = run(&home, &args);
assert!(
!out.status.success(),
"{args:?} silently accepted corruption"
);
let err = stderr(&out);
assert!(err.contains("reduction log is missing"), "{args:?}: {err}");
assert!(err.contains(&name), "{args:?}: {err}");
}
assert!(
!out_path.exists(),
"convert must write nothing for an uninterpretable reduced family"
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn missing_empty_log_is_valid_when_the_working_view_has_no_stubs() {
let home = fresh_home("missing-empty-log");
let fixture = home.join("tiny.jsonl");
std::fs::write(
&fixture,
serde_json::json!({
"type": "user",
"message": {"role": "user", "content": "tiny session"},
"uuid": "u-tiny",
"sessionId": "11111111-2222-4333-8444-555555555555",
"timestamp": "2026-07-12T00:00:00.000Z",
"cwd": "/tmp/tiny"
})
.to_string()
+ "\n",
)
.unwrap();
let name = mint_reduced_session(&home, &fixture);
let dir = sessions_dir(&home);
let persisted = run_with_stdin(&home, &["chat", "--last"], "/reduce\n");
assert!(persisted.status.success(), "{}", stderr(&persisted));
let view = std::fs::read_to_string(dir.join(format!("{name}.jsonl"))).unwrap();
assert!(!view.contains("sc-reduced"));
let log: ReductionLog = serde_json::from_str(
&std::fs::read_to_string(dir.join(format!("{name}.reduction.json"))).unwrap(),
)
.unwrap();
assert!(log.reductions.is_empty());
std::fs::remove_file(dir.join(format!("{name}.reduction.json"))).unwrap();
let inspected = run(&home, &["inspect", &name, "--json"]);
assert!(inspected.status.success(), "{}", stderr(&inspected));
let json: serde_json::Value = serde_json::from_slice(&inspected.stdout).unwrap();
assert_eq!(json["session"]["reduced"]["stub_count"], 0);
let exported = home.join("tiny.codex.jsonl");
let converted = run(
&home,
&[
"convert",
&name,
"--to",
"codex",
"--out",
exported.to_str().unwrap(),
],
);
assert!(converted.status.success(), "{}", stderr(&converted));
assert!(exported.exists());
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn convert_reduced_session_reads_sidecar_zero_leaks_and_fidelity_line() {
let home = fresh_home("convert-ok");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
let out_path = home.join("as-codex.jsonl");
let conv = run(
&home,
&[
"convert",
&name,
"--to",
"codex",
"-o",
out_path.to_str().unwrap(),
],
);
assert!(
conv.status.success(),
"convert must succeed: {}",
stderr(&conv)
);
let written = std::fs::read_to_string(&out_path).unwrap();
assert_eq!(
written.matches("sc-reduced").count(),
0,
"export must contain zero 'sc-reduced' occurrences"
);
let err = stderr(&conv);
assert!(
err.contains("fidelity: full"),
"missing fidelity line: {err}"
);
assert!(
err.contains("stubs rehydrated"),
"missing stub count: {err}"
);
assert!(
err.contains("resume on your subscription"),
"missing resume hint: {err}"
);
assert!(
err.contains("codex exec resume"),
"hint must name the target tool: {err}"
);
let claude_path = home.join("as-claude.jsonl");
let diagonal = run(
&home,
&[
"convert",
&name,
"--to",
"claude-code",
"-o",
claude_path.to_str().unwrap(),
],
);
assert!(diagonal.status.success(), "{}", stderr(&diagonal));
assert_eq!(
std::fs::read(&claude_path).unwrap(),
std::fs::read(&fixture).unwrap(),
"same-format reduced export must replay the original bytes"
);
assert!(
stderr(&diagonal).contains("byte-identical (verbatim)"),
"same-format reduced export must report its observed byte identity: {}",
stderr(&diagonal)
);
let sidecar_path = sessions_dir(&home).join(format!("{name}.sidecar.jsonl"));
let sidecar_str = std::fs::read_to_string(&sidecar_path).unwrap();
let sidecar = Session::from_sidecar_str(&sidecar_str).unwrap();
let expected = sidecar
.to_jsonl_spliced(SessionFormat::Codex, None)
.unwrap();
assert_eq!(
written, expected,
"convert output must match an independent sidecar re-export"
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn inspect_reduced_session_shows_reduced_rows_and_tag() {
let home = fresh_home("inspect-reduced");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
assert!(
!sessions_dir(&home).join(format!("{name}.jsonl")).exists(),
"EOF-only reduced resume must exercise the entry-only projection fallback"
);
let out = run(&home, &["inspect", &name]);
assert!(
out.status.success(),
"inspect must succeed: {}",
stderr(&out)
);
let text = stdout(&out);
assert!(text.contains("reduced"), "missing `reduced` row:\n{text}");
assert!(text.contains("stubs"), "missing stub count:\n{text}");
assert!(text.contains("sidecar"), "missing `sidecar` row:\n{text}");
assert!(
text.contains("⊟ reduced"),
"missing the reduced row tag:\n{text}"
);
let json_out = run(&home, &["inspect", &name, "--json"]);
assert!(json_out.status.success(), "{}", stderr(&json_out));
let json: serde_json::Value = serde_json::from_str(&stdout(&json_out)).unwrap();
let attribution = &json["session"]["reduced"]["attribution"];
let passes = attribution["passes"].as_array().unwrap();
assert_eq!(passes.len(), 9, "every enabled pass must be reported");
assert!(
passes
.iter()
.any(|row| row["applied_count"].as_u64().unwrap() > 0),
"fixture must have an attributed applied pass"
);
assert_eq!(attribution["aggregate_bytes_is_marginal_sum"], true);
assert_eq!(attribution["aggregate_is_marginal_sum"], true);
assert_eq!(
passes
.iter()
.map(|row| row["marginal_saved_bytes"].as_u64().unwrap())
.sum::<u64>(),
attribution["aggregate_saved_bytes"].as_u64().unwrap(),
"aggregate byte savings must be the marginal sum"
);
assert_eq!(
passes
.iter()
.map(|row| row["marginal_saved_tokens"].as_u64().unwrap())
.sum::<u64>(),
attribution["aggregate_saved_tokens"].as_u64().unwrap(),
"aggregate savings must be the marginal sum, never standalone claims added twice"
);
let sidecar = Session::from_sidecar_str(
&std::fs::read_to_string(sessions_dir(&home).join(format!("{name}.sidecar.jsonl")))
.unwrap(),
)
.unwrap();
let log: ReductionLog = serde_json::from_str(
&std::fs::read_to_string(sessions_dir(&home).join(format!("{name}.reduction.json")))
.unwrap(),
)
.unwrap();
let expected_view_messages = project(&sidecar, &ReductionPolicy::default(), &log).0.len() + 1;
let continued = run(&home, &["chat", "--last"]);
assert!(continued.status.success(), "{}", stderr(&continued));
assert!(
stderr(&continued).contains(&format!(
"Continuing reduced session ({expected_view_messages}-message view; {} full messages).",
sidecar.messages.len()
)),
"entry-only continuation count must include the model system message: {}",
stderr(&continued)
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn completed_reduced_turn_refreshes_durable_pass_order_attribution() {
let home = fresh_home("attribution-refresh");
let fixture = write_pass_order_fixture(&home);
let (addr, provider) = spawn_capturing_sse_stub("DONE");
let out = run_at(
&home,
&format!("http://{addr}"),
&[
"--quiet",
"--model",
"z-ai/glm-5.2",
"--reduced",
"--no-project-context",
"resume",
fixture.to_str().unwrap(),
"Reply exactly DONE.",
"--paused",
],
);
assert!(out.status.success(), "{}", stderr(&out));
let _ = provider.join().unwrap();
let listed = run(&home, &["sessions", "list", "--json"]);
assert!(listed.status.success(), "{}", stderr(&listed));
let sessions: serde_json::Value = serde_json::from_str(&stdout(&listed)).unwrap();
let name = sessions[0]["name"].as_str().unwrap();
let log: ReductionLog = serde_json::from_str(
&std::fs::read_to_string(sessions_dir(&home).join(format!("{name}.reduction.json")))
.unwrap(),
)
.unwrap();
let sidecar = Session::from_sidecar_str(
&std::fs::read_to_string(sessions_dir(&home).join(format!("{name}.sidecar.jsonl")))
.unwrap(),
)
.unwrap();
let attribution = log
.attribution
.expect("completed turn must persist attribution");
assert_eq!(
attribution.full_tokens,
estimate_view_tokens(&sidecar.messages),
"persisted attribution must be refreshed against the post-turn sidecar"
);
assert!(
attribution
.passes
.iter()
.map(|row| row.suppressed_by_later_pass_count)
.sum::<usize>()
> 0,
"A10 must durably name the earlier claims it subsumed"
);
assert_eq!(
attribution
.passes
.iter()
.map(|row| row.marginal_saved_tokens)
.sum::<u64>(),
attribution.aggregate_saved_tokens
);
std::fs::remove_dir_all(home).ok();
}
#[test]
fn no_reduced_saved_continuation_uses_full_history_and_keeps_sidecar_current() {
let home = fresh_home("no-reduced-saved");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
let sidecar_path = sessions_dir(&home).join(format!("{name}.sidecar.jsonl"));
let before = Session::from_sidecar_str(&std::fs::read_to_string(&sidecar_path).unwrap())
.unwrap()
.messages
.len();
const USER_MARKER: &str = "NO_REDUCED_SAVED_USER_MARKER";
const ASSISTANT_MARKER: &str = "NO_REDUCED_SAVED_ASSISTANT_MARKER";
let (addr, server) = spawn_capturing_sse_stub(ASSISTANT_MARKER);
let out = run_at(
&home,
&format!("http://{addr}"),
&["--no-reduced", "--last", "run", USER_MARKER],
);
assert!(out.status.success(), "{}", stderr(&out));
assert!(
stderr(&out).contains(&format!("Continuing session ({} messages).", before + 1)),
"the unreduced continuation must load full sidecar history: {}",
stderr(&out)
);
assert!(
!stderr(&out).contains("Continuing reduced session"),
"--no-reduced must suppress reduced-mode startup: {}",
stderr(&out)
);
let request = server.join().unwrap();
assert!(request.contains(USER_MARKER), "request lost the new prompt");
assert!(
request.contains(&"x".repeat(20_000)),
"unreduced request must contain the original oversized result"
);
assert!(
!request.contains("sc-reduced"),
"unreduced request must not contain unresolved reduction stubs"
);
let sidecar_text = std::fs::read_to_string(&sidecar_path).unwrap();
let sidecar = Session::from_sidecar_str(&sidecar_text).unwrap();
assert_eq!(sidecar.messages.len(), before + 2);
assert!(sidecar_text.contains(USER_MARKER));
assert!(sidecar_text.contains(ASSISTANT_MARKER));
let exported = home.join("continued.claude.jsonl");
let conv = run(
&home,
&[
"convert",
&name,
"--to",
"claude-code",
"--out",
exported.to_str().unwrap(),
],
);
assert!(conv.status.success(), "{}", stderr(&conv));
let export_text = std::fs::read_to_string(exported).unwrap();
assert!(export_text.contains(USER_MARKER));
assert!(export_text.contains(ASSISTANT_MARKER));
let meta: serde_json::Value = serde_json::from_str(
&std::fs::read_to_string(sessions_dir(&home).join(format!("{name}.meta.json"))).unwrap(),
)
.unwrap();
assert_eq!(meta["reduced"], true, "the sidecar family still exists");
assert_eq!(meta["stub_count"], 0, "the current full view has no stubs");
let log: serde_json::Value = serde_json::from_str(
&std::fs::read_to_string(sessions_dir(&home).join(format!("{name}.reduction.json")))
.unwrap(),
)
.unwrap();
assert_eq!(log["reductions"].as_array().unwrap().len(), 0);
assert_eq!(
log["expanded"].as_array().unwrap().len(),
1,
"--no-reduced must durably represent the full view as expand-all"
);
let inspected = run(&home, &["inspect", &name, "--json"]);
assert!(inspected.status.success(), "{}", stderr(&inspected));
let inspected: serde_json::Value = serde_json::from_slice(&inspected.stdout).unwrap();
assert_eq!(inspected["session"]["reduced"]["stub_count"], 0);
assert!(
!inspected.to_string().contains("sc-reduced"),
"inspect must agree that the saved full view has no active stubs"
);
let reopened = run(&home, &["chat", "--last"]);
assert!(reopened.status.success(), "{}", stderr(&reopened));
assert!(
stderr(&reopened).contains(&format!(
"Continuing reduced session ({}-message view; {} full messages).",
before + 3,
before + 2
)),
"ordinary reopen must report the full expanded view it actually loads: {}",
stderr(&reopened)
);
let reopened_log: serde_json::Value = serde_json::from_str(
&std::fs::read_to_string(sessions_dir(&home).join(format!("{name}.reduction.json")))
.unwrap(),
)
.unwrap();
assert_eq!(reopened_log["reductions"].as_array().unwrap().len(), 0);
assert_eq!(reopened_log["expanded"].as_array().unwrap().len(), 1);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn inspect_reduced_session_rejects_malformed_persisted_working_view() {
let home = fresh_home("inspect-malformed-view");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
std::fs::write(
sessions_dir(&home).join(format!("{name}.jsonl")),
"this is not a ChatMessage\n",
)
.unwrap();
let out = run(&home, &["inspect", &name, "--json"]);
assert!(!out.status.success(), "malformed persisted view must fail");
assert!(
stderr(&out).contains("parsing stored working view"),
"failure must name the broken working view: {}",
stderr(&out)
);
assert!(
stdout(&out).is_empty(),
"inspect must not print a projection after rejecting the persisted view"
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn inspect_reduced_session_rejects_unreadable_present_working_view() {
let home = fresh_home("inspect-unreadable-view");
let fixture = write_big_fixture(&home);
let name = mint_reduced_session(&home, &fixture);
let transcript = sessions_dir(&home).join(format!("{name}.jsonl"));
std::fs::create_dir(&transcript).unwrap();
let out = run(&home, &["inspect", &name, "--json"]);
assert!(
!out.status.success(),
"present but unreadable working view must fail"
);
assert!(
stderr(&out).contains("reading stored working view"),
"failure must name the unreadable working view: {}",
stderr(&out)
);
assert!(
stdout(&out).is_empty(),
"inspect must not print a projection after a working-view read error"
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn inspect_and_convert_on_non_reduced_input_are_unaffected() {
let home = fresh_home("regression");
let fixture = write_big_fixture(&home);
let insp = run(&home, &["inspect", fixture.to_str().unwrap()]);
assert!(insp.status.success());
let insp_text = stdout(&insp);
assert!(
!insp_text.contains("⊟ reduced"),
"non-reduced inspect must carry no reduced tag"
);
assert!(
!insp_text.to_lowercase().contains("reduced yes")
&& !insp_text.contains("reduced yes"),
"non-reduced inspect must carry no `reduced` row:\n{insp_text}"
);
let out_path = home.join("plain-convert.jsonl");
let conv = run(
&home,
&[
"convert",
fixture.to_str().unwrap(),
"--to",
"codex",
"-o",
out_path.to_str().unwrap(),
],
);
assert!(conv.status.success());
assert!(
!stderr(&conv).contains("fidelity:"),
"non-reduced convert must not print a fidelity line: {}",
stderr(&conv)
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn expand_then_reduce_restores_the_same_id_via_repl() {
let home = fresh_home("expand-reduce");
let fixture = write_big_fixture(&home);
let id = expected_id(&fixture);
let stdin = format!("/expand {id}\n/reduce\n");
let out = run_with_stdin(
&home,
&["resume", fixture.to_str().unwrap(), "--reduced"],
&stdin,
);
let err = stderr(&out);
let expand_line = err
.lines()
.find(|l| l.contains("expanded") && l.contains(&id))
.unwrap_or_else(|| panic!("no `⤢ expanded {id}` line in:\n{err}"));
assert!(
expand_line.contains('+'),
"expand line must show a byte delta: {expand_line}"
);
assert!(
expand_line.contains("~+"),
"expand line must show a token delta: {expand_line}"
);
assert!(
expand_line.contains("view now"),
"expand line must show the new view size: {expand_line}"
);
let reduce_line = err
.lines()
.find(|l| l.contains("re-reduced"))
.unwrap_or_else(|| panic!("no `⤵ re-reduced` line in:\n{err}"));
assert!(
reduce_line.contains("stubs"),
"reduce line must show a stub count: {reduce_line}"
);
let sidecar_line = err
.lines()
.find(|l| l.contains("full copy:"))
.expect("banner must name the sidecar");
let sidecar_path = sidecar_line.split("full copy:").nth(1).unwrap().trim();
let name = Path::new(sidecar_path)
.file_name()
.unwrap()
.to_str()
.unwrap()
.strip_suffix(".sidecar.jsonl")
.unwrap();
let jsonl_path = sessions_dir(&home).join(format!("{name}.jsonl"));
let jsonl = std::fs::read_to_string(&jsonl_path).unwrap();
assert!(
jsonl.contains(&format!("sc-reduced superseded {id}")),
"persisted view must contain the restored stub for {id}:\n{jsonl}"
);
let log_path = sessions_dir(&home).join(format!("{name}.reduction.json"));
let log: serde_json::Value =
serde_json::from_str(&std::fs::read_to_string(&log_path).unwrap()).unwrap();
let ids: Vec<&str> = log["reductions"]
.as_array()
.unwrap()
.iter()
.map(|r| r["id"].as_str().unwrap())
.collect();
assert_eq!(
ids,
vec![id.as_str()],
"the final log must contain the SAME id after expand+reduce"
);
std::fs::remove_dir_all(&home).ok();
}
#[test]
fn expand_bogus_id_errors_with_hint_and_changes_nothing() {
let home = fresh_home("expand-bogus");
let fixture = write_big_fixture(&home);
let out = run_with_stdin(
&home,
&["resume", fixture.to_str().unwrap(), "--reduced"],
"/expand bogus-id\n",
);
let err = stderr(&out);
assert!(err.contains("no reduction with id"), "missing error: {err}");
assert!(
err.contains("bogus-id"),
"error must name the bogus id: {err}"
);
assert!(
err.contains("valid ids"),
"error must hint at valid ids: {err}"
);
let sidecar_line = err
.lines()
.find(|l| l.contains("full copy:"))
.expect("banner must name the sidecar");
let sidecar_path = sidecar_line.split("full copy:").nth(1).unwrap().trim();
let name = Path::new(sidecar_path)
.file_name()
.unwrap()
.to_str()
.unwrap()
.strip_suffix(".sidecar.jsonl")
.unwrap();
let jsonl_path = sessions_dir(&home).join(format!("{name}.jsonl"));
assert!(
!jsonl_path.exists(),
"a bogus /expand must not create/modify the persisted view"
);
std::fs::remove_dir_all(&home).ok();
}