use super::fixture::Fixture;
use super::mtime;
use crate::git_tree::{Agent, GitTree};
use std::fs;
fn agent_of(tree: &GitTree, id: &str) -> Agent {
tree.agents
.iter()
.find(|a| a.agent_id == id)
.expect("the enumerated agent")
.clone()
}
fn write_message(fx: &Fixture, id: &str, name: &str) -> std::path::PathBuf {
let dir = fx.path.join("agents").join(id).join("messages");
fs::create_dir_all(&dir).unwrap();
let path = dir.join(name);
fs::write(&path, "from a peer\n").unwrap();
path
}
#[test]
fn a_delivered_message_is_an_action_even_though_it_commits_nothing() {
let fx = Fixture::new();
let id = "20260801T120000Z-msg";
fx.build_agent(id, "wait for mail");
let msg = write_message(&fx, id, "001-peer.md");
let agent = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(agent.last_action_unix, mtime(&msg));
assert!(agent.last_action_unix >= agent.tip_timestamp_unix);
}
#[test]
fn the_live_streaming_tail_is_an_action() {
let fx = Fixture::new();
let id = "20260801T120100Z-strm";
fx.build_agent(id, "start streaming");
fx.write_response_events(
id,
2,
&[r#"{"type":"content_delta","index":0,"delta":{"text_delta":"mid"}}"#],
);
let tail = fx.path.join("steps").join(id).join("002/response.json");
let agent = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(agent.last_action_unix, mtime(&tail));
assert!(agent.last_action_unix >= agent.tip_timestamp_unix);
}
#[test]
fn the_newest_of_the_three_wins() {
let fx = Fixture::new();
let id = "20260801T120200Z-both";
fx.build_agent(id, "mail then tokens");
write_message(&fx, id, "001-peer.md");
fx.write_response_events(id, 1, &[r#"{"type":"end"}"#]);
let tail = fx.path.join("steps").join(id).join("001/response.json");
let agent = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(agent.last_action_unix, mtime(&tail));
}
#[test]
fn with_nothing_but_commits_the_tip_is_the_last_action() {
let fx = Fixture::new();
let id = "20260801T120300Z-quiet";
fx.build_agent(id, "say nothing");
fs::create_dir_all(fx.path.join("agents").join(id).join("messages")).unwrap();
let child = format!("{id}-k-1");
fx.build_child(id, &child);
let tree = GitTree::from_repo(&fx.path).unwrap();
let root = agent_of(&tree, id);
assert_eq!(root.last_action_unix, root.tip_timestamp_unix);
let kid = agent_of(&tree, &child);
assert_eq!(kid.last_action_unix, kid.tip_timestamp_unix);
}
#[test]
fn the_message_count_rides_the_same_directory_walk_as_the_recency_fact() {
let fx = Fixture::new();
let id = "20260801T120000Z-count";
fx.build_agent(id, "count me");
let bare = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(bare.messages, 0, "no messages/ directory is no messages");
write_message(&fx, id, "001-user.md");
write_message(&fx, id, "002-peer.md");
let two = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(two.messages, 2);
assert!(
two.last_action_unix >= bare.last_action_unix,
"and the recency fact still comes off the same walk"
);
assert!(!two.in_memory(), "a derived agent always has a tip");
}
#[test]
fn the_message_count_survives_a_compaction_and_ignores_stray_entries() {
let fx = Fixture::new();
let id = "20260801T120400Z-hiwater";
fx.build_agent(id, "compact me");
write_message(&fx, id, "001-user.md");
write_message(&fx, id, "002-m.json");
write_message(&fx, id, "003-tool.json");
let before = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(before.messages, 3);
let dir = fx.path.join("agents").join(id).join("messages");
fs::remove_file(dir.join("001-user.md")).unwrap();
fs::remove_file(dir.join("002-m.json")).unwrap();
let after = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(
after.messages, 3,
"one file on disk, three messages ever landed"
);
fs::create_dir_all(dir.join("scratch")).unwrap();
let stray = agent_of(&GitTree::from_repo(&fx.path).unwrap(), id);
assert_eq!(stray.messages, 3, "the stray entry is not a message");
}