use super::*;
use crate::template::RealGit;
use tempfile::TempDir;
fn init(wt: &Path) {
let g = RealGit::new();
g.run(wt, &["init", "-b", "agents/p1"]).unwrap();
g.run(wt, &["config", "user.email", "t@t"]).unwrap();
g.run(wt, &["config", "core.hooksPath", "/dev/null"])
.unwrap();
g.run(wt, &["config", "user.name", "t"]).unwrap();
}
fn commit(wt: &Path, subject: &str, rel: &str, content: &str) -> String {
let g = RealGit::new();
let f = wt.join(rel);
std::fs::create_dir_all(f.parent().unwrap()).unwrap();
std::fs::write(&f, content).unwrap();
g.run(wt, &["add", "-A"]).unwrap();
g.run(wt, &["commit", "-m", subject]).unwrap();
g.run_capture(wt, &["rev-parse", "HEAD"])
.unwrap()
.trim()
.to_string()
}
fn entry(wt: &Path, seq: u32, prompt: u64) -> String {
commit(
wt,
&format!("transcript {seq:03}: m [p1]"),
&format!("messages/{seq:03}-m.json"),
&format!(r#"{{"content":[],"usage":{{"input_tokens":{prompt}}}}}"#),
)
}
fn branch(wt: &Path, prompts: &[u64]) -> Vec<String> {
init(wt);
commit(wt, "step 001: dispatch [p1]", "goal.md", "g");
prompts
.iter()
.enumerate()
.map(|(i, p)| {
let seq = u32::try_from(i).unwrap() + 1;
entry(wt, seq, *p)
})
.collect()
}
#[test]
fn the_point_is_the_oldest_commit_the_budget_still_reaches() {
let dir = TempDir::new().unwrap();
let wt = dir.path();
let shas = branch(wt, &[100, 300, 600, 1000]);
let p = point(wt, "p1", 500, &RealGit::new()).unwrap();
assert_eq!(p.as_deref(), Some(shas[2].as_str()));
let p = point(wt, "p1", 399, &RealGit::new()).unwrap();
assert_eq!(p.as_deref(), Some(shas[3].as_str()));
}
#[test]
fn a_branch_that_fits_the_budget_has_nothing_to_compact() {
let dir = TempDir::new().unwrap();
let wt = dir.path();
branch(wt, &[100, 400, 1000]);
assert_eq!(point(wt, "p1", 900, &RealGit::new()).unwrap(), None);
let empty = TempDir::new().unwrap();
init(empty.path());
commit(empty.path(), "step 001: dispatch [p1]", "goal.md", "g");
assert_eq!(point(empty.path(), "p1", 1, &RealGit::new()).unwrap(), None);
}
#[test]
fn the_walk_measures_from_the_checkpoint_origin_not_inherited_history() {
let dir = TempDir::new().unwrap();
let wt = dir.path();
branch(wt, &[100, 200]);
commit(wt, "compaction base [p1-c1]", "summary/001.md", "s");
let after = [entry(wt, 3, 900), entry(wt, 4, 1200)];
assert_eq!(point(wt, "p1", 400, &RealGit::new()).unwrap(), None);
let p = point(wt, "p1", 200, &RealGit::new()).unwrap();
assert_eq!(p.as_deref(), Some(after[1].as_str()));
}
#[test]
fn only_model_entries_are_candidates() {
let dir = TempDir::new().unwrap();
let wt = dir.path();
init(wt);
commit(wt, "step 001: dispatch [p1]", "goal.md", "g");
entry(wt, 1, 100);
let mid = entry(wt, 2, 600);
commit(
wt,
"transcript 003: tool [p1]",
"messages/003-tool.json",
r#"{"content":[],"usage":{"input_tokens":650}}"#,
);
commit(wt, "transcript 004: u [p1]", "messages/004-u.md", "hi");
commit(
wt,
"transcript 005: m [p1]",
"messages/005-m.json",
r#"[{"type":"text","text":"no usage"}]"#,
);
entry(wt, 6, 1000);
let p = point(wt, "p1", 500, &RealGit::new()).unwrap();
assert_eq!(p.as_deref(), Some(mid.as_str()));
}
#[test]
fn a_branch_with_no_founding_commit_walks_its_whole_history() {
let dir = TempDir::new().unwrap();
let wt = dir.path();
init(wt);
commit(wt, "root", "a.txt", "1");
entry(wt, 1, 100);
let mid = entry(wt, 2, 600);
entry(wt, 3, 1000);
let p = point(wt, "p1", 500, &RealGit::new()).unwrap();
assert_eq!(p.as_deref(), Some(mid.as_str()));
}
struct FailAt(std::cell::Cell<usize>, usize);
impl GitRunner for FailAt {
fn run(&self, _d: &Path, _a: &[&str]) -> std::io::Result<()> {
unreachable!("the tail only captures")
}
fn run_capture(&self, d: &Path, args: &[&str]) -> std::io::Result<String> {
let n = self.0.get();
self.0.set(n + 1);
if n == self.1 {
return Err(std::io::Error::other("boom"));
}
RealGit::new().run_capture(d, args)
}
}
#[test]
fn each_git_step_surfaces_under_its_own_op_tag() {
let dir = TempDir::new().unwrap();
let wt = dir.path();
branch(wt, &[100, 1000]);
for (nth, op) in [(1, "token tail log"), (2, "token tail entry read")] {
let err = point(wt, "p1", 1, &FailAt(std::cell::Cell::new(0), nth)).unwrap_err();
assert!(
matches!(&err, Error::Git { op: o, .. } if *o == op),
"{err:?}"
);
}
}