use super::workflow_source::nearest_mark;
use super::{ConfigSource, resolve_worker};
use crate::prompt::inbox::Launcher;
use crate::prompt::{Deps, NanoIdGen, SystemClock};
use crate::template::{GitRunner, RealGit};
use crate::workspace::{self, fixture, workflow_mark};
use std::path::Path;
use std::sync::atomic::AtomicBool;
use tempfile::TempDir;
struct NoAdapter;
impl crate::prompt::AdapterRunner for NoAdapter {
fn run(
&self,
_b: &std::ffi::OsString,
_a: &[&str],
_s: &[u8],
_o: &mut dyn FnMut(&[u8]) -> std::io::Result<()>,
) -> std::io::Result<Vec<u8>> {
unreachable!("the adapter is never reached at resolution")
}
}
struct NoSleeper;
impl crate::prompt::Sleeper for NoSleeper {
fn sleep(&self, _d: std::time::Duration) {
unreachable!("the sleeper is never reached at resolution")
}
}
struct NoTools;
impl crate::prompt::tool::ToolExecutor for NoTools {
fn execute(
&self,
_c: crate::prompt::tool::ToolCall<'_>,
_s: &Path,
_st: &AtomicBool,
_b: Option<crate::config::ToolOutputBound>,
) -> Result<crate::prompt::tool::ToolOutcome, crate::prompt::ExecError> {
unreachable!("the tool executor is never reached at resolution")
}
}
struct NoLauncher;
impl Launcher for NoLauncher {
fn launch(&self, _ws: &Path, _agent: &str) -> std::io::Result<()> {
unreachable!("no driver is launched at resolution")
}
}
pub(super) struct Fx {
pub(super) git: RealGit,
clock: SystemClock,
id: NanoIdGen,
adapter: NoAdapter,
sleeper: NoSleeper,
tools: NoTools,
launcher: NoLauncher,
stop: AtomicBool,
cfg: TempDir,
}
impl Fx {
pub(super) fn new() -> Self {
let cfg = TempDir::new().unwrap();
std::fs::write(cfg.path().join("models.yaml"), "adapter: /bin/true\n").unwrap();
Self {
git: RealGit::new(),
clock: SystemClock,
id: NanoIdGen,
adapter: NoAdapter,
sleeper: NoSleeper,
tools: NoTools,
launcher: NoLauncher,
stop: AtomicBool::new(false),
cfg,
}
}
pub(super) fn deps(&self) -> Deps<'_> {
Deps {
adapter: &self.adapter,
sleeper: &self.sleeper,
git: &self.git,
clock: &self.clock,
id_gen: &self.id,
tool_executor: &self.tools,
config_root: self.cfg.path(),
data_root: self.cfg.path(),
adapter_target: None,
stop: &self.stop,
launcher: &self.launcher,
rng: crate::workspace::agent_name::mint::test_rng(),
}
}
}
pub(super) fn head(ws: &Path) -> String {
RealGit::new()
.run_capture(
&workspace::repo_git(ws),
&["rev-parse", &workspace::config_ref("default")],
)
.unwrap()
.trim()
.to_string()
}
pub(super) const SWITCHED_WORKFLOW: &str =
"events: {}\nretry:\n max_attempts: 7\n backoff: exponential\n";
#[test]
fn an_unmarked_agent_resolves_the_governing_workflow_the_basic_agentic_loop() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-r1");
let fx = Fx::new();
let cfg = resolve_worker(&ws, ConfigSource::Agent("20260101-r1"), &fx.deps()).unwrap();
assert_eq!(cfg.workflow.retry.max_attempts, 3);
assert!(cfg.workflow.compaction.is_some());
assert_eq!(cfg.workflow_commit, cfg.config_commit);
}
#[test]
fn a_marked_agent_pins_the_marked_workflow_while_every_other_fact_follows_the_tip() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-r1");
let fork = head(&ws);
fixture::amend_config(
&ws,
&[
("workflow.yaml", SWITCHED_WORKFLOW),
("souls/worker.md", "a switched soul\n"),
],
);
let fx = Fx::new();
workflow_mark::write(&ws, "20260101-r1", &fork, &fx.git).unwrap();
let cfg = resolve_worker(&ws, ConfigSource::Agent("20260101-r1"), &fx.deps()).unwrap();
assert_eq!(
cfg.workflow.retry.max_attempts, 3,
"the marked (fork) workflow stands against the moved tip",
);
assert!(
cfg.soul.contains("a switched soul"),
"every unmarked control fact follows the tip (operator ruling 2026-09-01)",
);
assert_eq!(cfg.workflow_commit, fork);
assert_eq!(cfg.config_commit, head(&ws));
assert_ne!(cfg.workflow_commit, cfg.config_commit);
}
#[test]
fn an_unmarked_agent_follows_the_tips_workflow_like_every_other_control_fact() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-r1");
fixture::amend_config(&ws, &[("workflow.yaml", SWITCHED_WORKFLOW)]);
let fx = Fx::new();
let cfg = resolve_worker(&ws, ConfigSource::Agent("20260101-r1"), &fx.deps()).unwrap();
assert_eq!(cfg.workflow.retry.max_attempts, 7);
}
#[test]
fn clearing_the_mark_returns_resolution_to_the_followed_workflow() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-r1");
let fork = head(&ws);
fixture::amend_config(&ws, &[("workflow.yaml", SWITCHED_WORKFLOW)]);
let fx = Fx::new();
workflow_mark::write(&ws, "20260101-r1", &fork, &fx.git).unwrap();
workflow_mark::clear(&ws, "20260101-r1", &fx.git).unwrap();
let cfg = resolve_worker(&ws, ConfigSource::Agent("20260101-r1"), &fx.deps()).unwrap();
assert_eq!(cfg.workflow.retry.max_attempts, 7, "the tip's workflow");
}
#[test]
fn a_child_resolves_the_nearest_ancestor_mark_so_marking_the_root_switches_the_tree() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-r1");
fixture::spawn_agent(&ws, "20260101-r1-20260102-c1", "agents/20260101-r1");
fixture::amend_config(&ws, &[("workflow.yaml", SWITCHED_WORKFLOW)]);
let fx = Fx::new();
workflow_mark::write(&ws, "20260101-r1", &head(&ws), &fx.git).unwrap();
let cfg = resolve_worker(
&ws,
ConfigSource::Agent("20260101-r1-20260102-c1"),
&fx.deps(),
)
.unwrap();
assert_eq!(cfg.workflow.retry.max_attempts, 7, "inherited by descent");
}
#[test]
fn a_childs_own_mark_overrides_its_ancestors() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-r1");
fixture::spawn_agent(&ws, "20260101-r1-20260102-c1", "agents/20260101-r1");
let governing = head(&ws);
fixture::amend_config(&ws, &[("workflow.yaml", SWITCHED_WORKFLOW)]);
let fx = Fx::new();
workflow_mark::write(&ws, "20260101-r1", &head(&ws), &fx.git).unwrap();
workflow_mark::write(&ws, "20260101-r1-20260102-c1", &governing, &fx.git).unwrap();
assert_eq!(
nearest_mark(&ws, "20260101-r1-20260102-c1", &fx.git),
Some(("20260101-r1-20260102-c1".to_string(), governing)),
"nearest wins, and it names its holder: the child's own mark, not the root's",
);
let cfg = resolve_worker(
&ws,
ConfigSource::Agent("20260101-r1-20260102-c1"),
&fx.deps(),
)
.unwrap();
assert_eq!(cfg.workflow.retry.max_attempts, 3);
}
#[test]
fn a_fresh_fork_has_no_descent_and_resolves_the_governing_workflow() {
let (_h, ws) = fixture::workspace();
let fx = Fx::new();
let spec = workspace::config_ref("default");
let cfg = resolve_worker(
&ws,
ConfigSource::Fork {
point: &spec,
role: crate::prompt::WORKER_ROLE,
},
&fx.deps(),
)
.unwrap();
assert_eq!(cfg.workflow.retry.max_attempts, 3);
}
#[test]
fn diverged_lineages_resolve_the_fork_commit_and_say_so_loudly() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-r1");
let fx = Fx::new();
fx.git
.run(
&workspace::repo_git(&ws),
&["update-ref", "refs/heads/config/variant", &head(&ws)],
)
.unwrap();
fixture::amend_config(&ws, &[("workflow.yaml", SWITCHED_WORKFLOW)]);
let cfg = resolve_worker(&ws, ConfigSource::Agent("20260101-r1"), &fx.deps()).unwrap();
assert_eq!(
cfg.workflow.retry.max_attempts, 3,
"held on the fork commit: the advanced default's workflow does not reach it",
);
}