use super::tests::{NoopLauncher, scaffolded_repo_with_parent, sub_count};
use super::*;
use crate::template::{GitRunner, RealGit};
use crate::workspace::fixture;
const STRICT_SOUL: &str = "You are the strict worker.";
fn author_strict(ws: &Path) {
crate::template::authoring::author(
ws,
&ws.join(".no-pools"),
"strict",
crate::template::authoring::Origin::Fork { source: "default" },
|dir| std::fs::write(dir.join("souls/worker.md"), STRICT_SOUL),
&RealGit::new(),
)
.unwrap();
}
fn child_of(repo: &Path, parent: &str) -> String {
std::fs::read_dir(repo.join(crate::workspace::AGENTS_DIR))
.unwrap()
.flatten()
.map(|e| e.file_name().to_string_lossy().to_string())
.find(|n| n.starts_with(&format!("{parent}-")))
.expect("the forked child")
}
#[test]
fn a_child_forked_across_lineages_is_governed_by_the_config_it_forked_off() {
let (_holder, repo) = scaffolded_repo_with_parent("20260101-p1");
author_strict(&repo);
fixture::spawn_agent(&repo, "20260101-r2", "config/strict");
run_with(
"worker",
&repo,
"20260101-p1",
Some("continue that work"),
Some("agents/20260101-r2"),
None,
crate::prompt::PinnedDocs::none(),
&NoopLauncher,
)
.unwrap();
let child = child_of(&repo, "20260101-p1");
let git = RealGit::new();
let soul =
std::fs::read_to_string(crate::workspace::agent_worktree(&repo, &child).join("soul.md"))
.unwrap();
assert_eq!(soul, STRICT_SOUL);
let at_dispatch = crate::workspace::governing_config(&repo, "config/strict", &git).unwrap();
let at_advance =
crate::workspace::governing_config(&repo, &crate::workspace::agent_ref(&child), &git)
.unwrap();
assert_eq!(at_advance, at_dispatch);
assert_ne!(
at_advance,
crate::workspace::governing_config(
&repo,
&crate::workspace::agent_ref("20260101-p1"),
&git
)
.unwrap(),
"the fork point's config must differ from the parent's, or this proves nothing"
);
}
#[test]
fn role_validity_is_asked_of_the_config_that_will_govern_the_child() {
let (_holder, repo) = scaffolded_repo_with_parent("20260101-p1");
author_strict(&repo);
crate::template::authoring::author(
&repo,
&repo.join(".no-pools"),
"strict",
crate::template::authoring::Origin::Advance,
|dir| {
std::fs::write(
dir.join("providers.yaml"),
"roles:\n worker:\n provider: anthropic\n model: sonnet\n",
)
},
&RealGit::new(),
)
.unwrap();
fixture::spawn_agent(&repo, "20260101-r2", "config/strict");
let err = run_with(
ROLE_COMPACTOR,
&repo,
"20260101-p1",
None,
Some("agents/20260101-r2"),
None,
crate::prompt::PinnedDocs::none(),
&NoopLauncher,
)
.unwrap_err();
let msg = err.to_string();
assert!(matches!(err, DispatchCliError::InvalidRole(_)), "{msg}");
assert!(msg.contains("defined roles: worker"), "{msg}");
assert_eq!(
sub_count(&repo, "20260101-p1"),
0,
"declined before the fork"
);
}
#[test]
fn a_named_fork_point_forks_the_child_off_it_not_the_parents_tip() {
let (_holder, repo) = scaffolded_repo_with_parent("20260101-p1");
let git = crate::template::RealGit::new();
let parent_wt = crate::workspace::agent_worktree(&repo, "20260101-p1");
let earlier = git
.run_capture(&parent_wt, &["rev-parse", "HEAD"])
.unwrap()
.trim()
.to_string();
std::fs::write(parent_wt.join("tip-only.md"), "later").unwrap();
git.run(&parent_wt, &["add", "tip-only.md"]).unwrap();
git.run(&parent_wt, &["commit", "-m", "later work"])
.unwrap();
run_with(
"worker",
&repo,
"20260101-p1",
Some("continue from there"),
Some(&earlier),
None,
crate::prompt::PinnedDocs::none(),
&NoopLauncher,
)
.unwrap();
let child = std::fs::read_dir(repo.join(crate::workspace::AGENTS_DIR))
.unwrap()
.flatten()
.map(|e| e.file_name().to_string_lossy().to_string())
.find(|n| n.starts_with("20260101-p1-"))
.expect("the forked child");
let child_ref = crate::workspace::agent_ref(&child);
let bare = crate::workspace::repo_git(&repo);
assert!(
git.run(
&bare,
&["merge-base", "--is-ancestor", &earlier, &child_ref]
)
.is_ok(),
"the named ref must be an ancestor of the child"
);
assert!(
!repo
.join(crate::workspace::AGENTS_DIR)
.join(&child)
.join("tip-only.md")
.exists(),
"the child forked off the earlier commit, not the parent's tip"
);
}
#[test]
fn an_absent_fork_point_is_declined_before_the_fork() {
let (_holder, repo) = scaffolded_repo_with_parent("20260101-p1");
let err = run_with(
"worker",
&repo,
"20260101-p1",
Some("g"),
Some("agents/nope"),
None,
crate::prompt::PinnedDocs::none(),
&NoopLauncher,
)
.unwrap_err();
let msg = err.to_string();
assert!(
matches!(err, DispatchCliError::UnknownForkPoint(_)),
"{msg}"
);
assert!(msg.contains("no ref or commit \"agents/nope\""), "{msg}");
assert!(msg.contains("a child forks off the ref you name"), "{msg}");
assert_eq!(sub_count(&repo, "20260101-p1"), 0, "no branch, no debris");
}