use super::*;
use tempfile::TempDir;
const PARENT: &str = "20260101-a1";
const SPECCER: &str = "20260101-a1-20260102-s1";
const BUILDER: &str = "20260101-a1-20260102-b2";
const CHILD_OF_BUILDER: &str = "20260101-a1-20260102-b2-20260103-w9";
fn owed(worktree: &std::path::Path, agent_id: &str) -> Result<bool, crate::prompt::Error> {
owes_a_reply(&read_entries(worktree)?, agent_id)
}
fn transcript(entries: &[(&str, &str)]) -> TempDir {
let wt = TempDir::new().unwrap();
std::fs::create_dir_all(wt.path().join("messages")).unwrap();
for (name, body) in entries {
std::fs::write(wt.path().join("messages").join(name), body).unwrap();
}
wt
}
fn prompt(from: &str) -> String {
format!("---\nfrom: {from}\ndeposited_at: t\n---\ndo it\n")
}
fn result(from: &str) -> String {
format!(
"---\nfrom: {from}\ndeposited_at: t\nepitaph: final-response\nterminal_ref: sha\n---\nok\n"
)
}
const TERMINAL: &str = r#"[{"type":"text","text":"Task complete."}]"#;
const TOOL_CALL: &str = r#"[{"type":"tool_use","id":"t1","name":"bash","input":{}}]"#;
#[test]
fn a_branch_that_has_never_answered_owes_its_first_reply() {
let wt = transcript(&[("001-20260101-a1.md", &prompt(PARENT))]);
assert!(owed(wt.path(), BUILDER).unwrap());
let bare = TempDir::new().unwrap();
assert!(owed(bare.path(), BUILDER).unwrap());
}
#[test]
fn a_prompt_delivered_since_the_last_answer_is_owed_one() {
let wt = transcript(&[
("001-20260101-a1.md", &prompt(PARENT)),
("002-claude-sonnet-5.json", TERMINAL),
("003-20260101-a1-20260102-s1.md", &prompt(SPECCER)),
("004-claude-sonnet-5.json", TERMINAL),
]);
assert!(owed(wt.path(), BUILDER).unwrap());
}
#[test]
fn a_foreign_reply_asks_nothing_so_the_exchange_terminates() {
let wt = transcript(&[
("001-20260101-a1-20260102-s1.md", &prompt(SPECCER)),
("002-claude-sonnet-5.json", TERMINAL),
("003-20260101-a1-20260102-s1.md", &result(SPECCER)),
("004-claude-sonnet-5.json", TERMINAL),
]);
assert!(!owed(wt.path(), BUILDER).unwrap());
}
#[test]
fn an_own_childs_return_keeps_the_answer_owed() {
let wt = transcript(&[
("001-20260101-a1.md", &prompt(PARENT)),
("002-claude-sonnet-5.json", TERMINAL),
(
"003-20260101-a1-20260102-b2-20260103-w9.md",
&result(CHILD_OF_BUILDER),
),
("004-claude-sonnet-5.json", TERMINAL),
]);
assert!(owed(wt.path(), BUILDER).unwrap());
}
#[test]
fn a_self_note_asks_nothing() {
let wt = transcript(&[
("001-20260101-a1.md", &prompt(PARENT)),
("002-claude-sonnet-5.json", TERMINAL),
("003-20260101-a1-20260102-b2.md", &prompt(BUILDER)),
("004-claude-sonnet-5.json", TERMINAL),
]);
assert!(!owed(wt.path(), BUILDER).unwrap());
}
#[test]
fn the_window_opens_at_the_previous_terminal_and_skips_tool_steps() {
let wt = transcript(&[
("001-20260101-a1.md", &prompt(PARENT)),
("002-claude-sonnet-5.json", TERMINAL),
("003-20260101-a1-20260102-s1.md", &prompt(SPECCER)),
("004-claude-sonnet-5.json", TOOL_CALL),
("005-tool.json", "[]"),
("006-claude-sonnet-5.json", TERMINAL),
]);
assert!(owed(wt.path(), BUILDER).unwrap());
}
#[test]
fn a_prompt_before_the_previous_answer_is_outside_the_window() {
let wt = transcript(&[
("001-20260101-a1.md", &prompt(PARENT)),
("002-claude-sonnet-5.json", TERMINAL),
("003-claude-sonnet-5.json", TERMINAL),
]);
assert!(!owed(wt.path(), BUILDER).unwrap());
}
#[test]
fn an_unparseable_name_is_not_an_entry() {
let wt = transcript(&[
("noseq.md", "x"),
("abc-user.md", "x"),
("001-.md", "x"),
("002-claude-sonnet-5.txt", TERMINAL),
]);
assert!(owed(wt.path(), BUILDER).unwrap());
}
#[test]
fn an_unreadable_entry_surfaces_rather_than_answering_nobody() {
let wt = transcript(&[("001-20260101-a1.md", &prompt(PARENT))]);
std::fs::create_dir(wt.path().join("messages/002-claude-sonnet-5.json")).unwrap();
assert!(owed(wt.path(), BUILDER).is_err());
let wt2 = transcript(&[
("002-claude-sonnet-5.json", TERMINAL),
("003-claude-sonnet-5.json", TERMINAL),
]);
std::fs::create_dir(wt2.path().join("messages/004-20260101-a1.md")).unwrap();
assert!(owed(wt2.path(), BUILDER).is_err());
}
#[test]
fn a_messages_path_that_is_not_a_directory_surfaces() {
let wt = TempDir::new().unwrap();
std::fs::write(wt.path().join("messages"), "not a directory").unwrap();
assert!(owed(wt.path(), BUILDER).is_err());
}