use super::*;
use crate::transcript::{Entry, EntryKind, Usage};
fn model(name: &str, blocks: Vec<Block>) -> Entry {
Entry {
name: name.to_owned(),
raw: Vec::new(),
kind: EntryKind::Model {
model_id: "m".to_owned(),
blocks,
usage: Usage::new(),
},
}
}
#[test]
fn every_entry_kind_folds_to_its_quotation() {
let transcript = Transcript {
entries: vec![
Entry {
name: "001-you.md".to_owned(),
raw: Vec::new(),
kind: EntryKind::Delivered {
sender: "you".to_owned(),
epitaph: None,
body: "ship it".to_owned(),
},
},
model(
"002-m.json",
vec![
Block::Text("on it".to_owned()),
Block::Thinking("hmm".to_owned()),
Block::ToolUse {
id: "t1".to_owned(),
name: "bash".to_owned(),
input_summary: "ls".to_owned(),
},
],
),
Entry {
name: "003-tool.json".to_owned(),
raw: Vec::new(),
kind: EntryKind::ToolResult {
tool_use_id: "t1".to_owned(),
content: "boom".to_owned(),
is_error: true,
},
},
Entry {
name: "«live»".to_owned(),
raw: Vec::new(),
kind: EntryKind::Streaming {
thinking: String::new(),
text: "partial".to_owned(),
},
},
Entry {
name: "junk".to_owned(),
raw: Vec::new(),
kind: EntryKind::Raw,
},
],
};
let all = fold(&transcript, None);
assert!(all.contains("[message from you]\nship it"));
assert!(all.contains("on it") && all.contains("(thinking) hmm"));
assert!(all.contains("(tool bash) ls"));
assert!(all.contains("[tool result (error)]\nboom"));
assert!(!all.contains("partial"), "no streaming text in a v1 window");
}
#[test]
fn a_delta_keeps_only_the_named_entries() {
let transcript = Transcript {
entries: vec![
model("001-m.json", vec![Block::Text("old".to_owned())]),
model("002-m.json", vec![Block::Text("new".to_owned())]),
],
};
let only = vec!["002-m.json".to_owned()];
let window = fold(&transcript, Some(&only));
assert!(window.contains("new") && !window.contains("old"));
}
#[test]
fn a_result_without_an_error_says_so_plainly() {
let transcript = Transcript {
entries: vec![Entry {
name: "001-tool.json".to_owned(),
raw: Vec::new(),
kind: EntryKind::ToolResult {
tool_use_id: "t1".to_owned(),
content: "ok".to_owned(),
is_error: false,
},
}],
};
assert!(fold(&transcript, None).contains("[tool result]\nok"));
}
#[test]
fn an_oversized_window_keeps_its_tail_and_says_it_elided() {
let long = "x".repeat(WINDOW_MAX + 100);
let folded = tail(&long);
assert!(folded.starts_with("[earlier work elided]"));
assert_eq!(
folded.chars().count(),
WINDOW_MAX + "[earlier work elided]\n".len()
);
assert_eq!(tail("short"), "short", "a window under the budget is whole");
}
#[test]
fn a_missing_agent_yields_empty_evidence_and_no_error() {
let dir = tempfile::tempdir().expect("tempdir");
assert_eq!(
gather(dir.path(), "nobody", None, "deadbeef"),
Evidence::default()
);
}
#[test]
fn an_unanswerable_diff_falls_back_to_the_whole_transcript() {
let dir = tempfile::tempdir().expect("tempdir");
assert_eq!(delta(dir.path(), Some("aaa"), "bbb"), None);
assert_eq!(delta(dir.path(), None, "bbb"), None);
}
#[test]
fn the_delta_is_derived_from_the_last_checked_sha() {
let fx = crate::git_tree::tests::fixture::Fixture::new();
let id = "20260803T120000Z-a001";
fx.build_agent(id, "close bl-1");
let wt = fx.path.join("agents").join(id);
let messages = wt.join("messages");
std::fs::create_dir_all(&messages).expect("messages");
let write = |n: &str, text: &str| {
std::fs::write(
messages.join(n),
serde_json::json!([{ "type": "text", "text": text }]).to_string(),
)
.expect("message");
};
write("001-m.json", "the first turn");
commit(&wt, "first");
let first = head(&wt);
write("002-m.json", "the second turn");
commit(&wt, "second");
let second = head(&wt);
let all = gather(&fx.path, id, None, &second);
assert_eq!(all.goal.trim(), "close bl-1", "the goal, verbatim");
assert!(all.window.contains("the first turn") && all.window.contains("the second turn"));
let since = gather(&fx.path, id, Some(&first), &second);
assert!(
!since.window.contains("the first turn") && since.window.contains("the second turn"),
"only what the branch gained: {:?}",
since.window
);
}
fn commit(wt: &std::path::Path, message: &str) {
for args in [vec!["add", "-A"], vec!["commit", "-q", "-m", message]] {
let out = crate::git_env::git()
.arg("-C")
.arg(wt)
.args(&args)
.output()
.expect("git");
assert!(out.status.success(), "git {args:?}: {out:?}");
}
}
fn head(wt: &std::path::Path) -> String {
let out = crate::git_env::git()
.arg("-C")
.arg(wt)
.args(["rev-parse", "HEAD"])
.output()
.expect("git");
String::from_utf8_lossy(&out.stdout).trim().to_owned()
}