use super::{noop_editor, with_fx};
use crate::cmd::{Outcome, workflow};
use crate::template::{GitRunner, RealGit};
use crate::workspace::{self, fixture, workflow_mark};
fn call(
ws: &std::path::Path,
agent: &str,
config: Option<&str>,
clear: bool,
) -> crate::cmd::Outcome {
let (r, out, _err) = with_fx("true", b"", &noop_editor, |fx| {
workflow::run(
workflow::Args {
workspace: ws.to_path_buf(),
agent: agent.to_string(),
config: config.map(str::to_string),
clear,
},
fx,
)
});
assert!(out.is_empty(), "the product is the Outcome, not a print");
r.unwrap()
}
fn run(ws: &std::path::Path, agent: &str, config: Option<&str>, clear: bool) {
assert!(
matches!(call(ws, agent, config, clear), Outcome::Quiet),
"a write is product-less (§3.4)",
);
}
fn read(ws: &std::path::Path, agent: &str) -> String {
match call(ws, agent, None, false) {
Outcome::Line(line) => line,
other => panic!("the read answers one line, got {other:?}"),
}
}
fn head(ws: &std::path::Path, lineage: &str) -> String {
RealGit::new()
.run_capture(
&workspace::repo_git(ws),
&["rev-parse", &workspace::config_ref(lineage)],
)
.unwrap()
.trim()
.to_string()
}
#[test]
fn a_switch_writes_the_standing_mark_at_the_named_lineages_head() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
fixture::amend_config(
&ws,
&[(
"workflow.yaml",
"events: {}\nretry:\n max_attempts: 2\n backoff: exponential\n",
)],
);
let want = head(&ws, "default");
run(&ws, "20260101-a1", Some("default"), false);
assert_eq!(
workflow_mark::read(&ws, "20260101-a1", &RealGit::new()),
Some(want),
"the mark is the verb's whole effect",
);
}
#[test]
fn an_unnamed_config_reads_and_writes_nothing() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
let line = read(&ws, "20260101-a1");
assert!(line.starts_with("20260101-a1 runs "), "{line}");
assert!(line.contains(&head(&ws, "default")[..12]), "{line}");
assert!(line.contains("(config/default)"), "{line}");
assert!(
line.contains("followed from its governing lineage"),
"{line}"
);
assert_eq!(
workflow_mark::read(&ws, "20260101-a1", &RealGit::new()),
None,
"a read writes no ref",
);
}
#[test]
fn the_read_names_the_mark_and_the_agent_holding_it() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
let pinned = head(&ws, "default");
fixture::amend_config(&ws, &[("workflow.yaml", "events: {}\n")]);
run(&ws, "20260101-a1", Some("default"), false);
let line = read(&ws, "20260101-a1");
assert!(line.contains(&head(&ws, "default")[..12]), "{line}");
assert!(line.contains("marked on [20260101-a1]"), "{line}");
assert!(!line.contains("ancestor"), "{line}");
assert_ne!(pinned, head(&ws, "default"), "the lineage really advanced");
}
#[test]
fn the_read_names_the_ancestor_whose_mark_a_child_inherits() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
fixture::spawn_agent(&ws, "20260101-a1-20260102-c1", "agents/20260101-a1");
run(&ws, "20260101-a1", Some("default"), false);
let line = read(&ws, "20260101-a1-20260102-c1");
assert!(line.contains("marked on ancestor [20260101-a1]"), "{line}");
}
#[test]
fn a_mark_on_a_commit_no_lineage_stands_on_renders_the_absence() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
let pinned = head(&ws, "default");
run(&ws, "20260101-a1", Some("default"), false);
fixture::amend_config(&ws, &[("workflow.yaml", "events: {}\n")]);
let line = read(&ws, "20260101-a1");
assert!(line.contains(&pinned[..12]), "{line}");
assert!(!line.contains("(config/"), "{line}");
}
#[test]
fn clear_deletes_the_mark_and_deletes_config_not_code() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
run(&ws, "20260101-a1", Some("default"), false);
run(&ws, "20260101-a1", None, true);
assert_eq!(
workflow_mark::read(&ws, "20260101-a1", &RealGit::new()),
None,
"cleared: the followed config's workflow governs again",
);
assert!(
read(&ws, "20260101-a1").contains("followed from its governing lineage"),
"and the read says so",
);
}
#[test]
fn the_read_says_so_when_diverged_lineages_hold_the_agent() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
let fork = head(&ws, "default");
RealGit::new()
.run(
&workspace::repo_git(&ws),
&["update-ref", "refs/heads/config/variant", &fork],
)
.unwrap();
fixture::amend_config(&ws, &[("souls/worker.md", "a newer soul\n")]);
let line = read(&ws, "20260101-a1");
assert!(line.contains(&fork[..12]), "{line}");
assert!(
line.contains("followed from its fork commit — 2 diverged config lineages"),
"{line}"
);
}