use argonauts_core::events::run::{CheckedInstruction, InstructionOutcome};
use argonauts_core::names::RoleName;
use argonauts_core::settings::crew::{CrewSettings, Orchestrator};
use argonauts_core::settings::roles::RoleSettings;
use super::*;
fn followed(kind: InstructionKind, says: &str) -> CheckedInstruction {
CheckedInstruction {
says: says.to_owned(),
kind,
outcome: InstructionOutcome::Followed {
said: String::new(),
note: None,
},
}
}
fn applied(instructions: Vec<CheckedInstruction>, settings: &[(&str, &str)]) -> Applied {
Applied {
instructions,
settings: settings
.iter()
.map(|(key, value)| ((*key).to_owned(), (*value).to_owned()))
.collect(),
..Applied::default()
}
}
fn fable() -> Settings {
Settings {
crew: CrewSettings {
main: "claude-code/fable-5-1".parse().unwrap(),
..CrewSettings::default()
},
..Settings::default()
}
}
fn opus_workers_and_an_astra_reviewer() -> Applied {
applied(
vec![
followed(
InstructionKind::Others,
"all the other agents need to be opus",
),
followed(InstructionKind::Review, "the reviewer will be astra"),
],
&[
("crew.worker", "[\"claude-code/opus-5-5\"]"),
("crew.judge", "[\"claude-code/opus-5-5\"]"),
("roles.reviewer.models", "[\"astra\"]"),
("review.per_task", "1"),
],
)
}
#[test]
fn the_words_show_against_where_the_rest_came_from() {
let lines = understood(&fable(), &opus_workers_and_an_astra_reviewer(), None)
.expect("the words changed the crew");
let from: Vec<(&str, &str)> = lines
.iter()
.map(|line| (line.role.plural(), line.from.as_str()))
.collect();
assert_eq!(
from,
[
("orchestrator", "your main session"),
("workers", "as you asked"),
("reviewers", "as you asked"),
("judge", "as you asked: \"all the other agents\""),
]
);
assert_eq!(lines[1].who, lines[3].who, "the judge is Opus too");
let shown = text(&lines);
assert!(
shown.starts_with("Crew for this request\norchestrator "),
"{shown}"
);
}
#[test]
fn a_role_that_follows_says_so() {
let mut settings = fable();
settings.crew = CrewSettings {
main: settings.crew.main.clone(),
orchestrator: Orchestrator::Main,
worker: Vec::new(),
reviewer: vec!["antigravity-cli".parse().unwrap()],
judge: Vec::new(),
worker_workflows: false,
merger: Vec::new(),
orchestrator_context: Default::default(),
};
let words = applied(
vec![followed(InstructionKind::Review, "astra reviews")],
&[("roles.reviewer.models", "[\"astra\"]")],
);
let lines = understood(&settings, &words, None).unwrap();
assert_eq!(lines[3].who, lines[2].who, "the judge is Astra too");
assert_eq!(lines[2].from, "as you asked");
assert_eq!(lines[3].from, "follows the reviewers");
assert_eq!(lines[1].from, "follows the orchestrator");
assert!(lines[3].asked.is_none(), "a role that follows isn't kept");
}
#[test]
fn only_your_words_show_a_crew() {
assert!(understood(&fable(), &Applied::default(), None).is_none());
let bell = applied(
vec![followed(InstructionKind::ForTheMainAgent, "keep it short")],
&[("ui.bell", "false")],
);
assert!(understood(&fable(), &bell, None).is_none());
let not_words = applied(Vec::new(), &[("crew.worker", "[\"codex\"]")]);
assert!(understood(&fable(), ¬_words, None).is_none());
let not_followed = applied(
vec![CheckedInstruction {
outcome: InstructionOutcome::NotFollowed {
why: "no agent here is called zed".to_owned(),
},
..followed(InstructionKind::Review, "zed reviews")
}],
&[],
);
assert!(understood(&fable(), ¬_followed, None).is_none());
}
#[test]
fn keeping_the_crew_writes_the_roles_your_words_set() {
let settings = fable();
let lines = understood(&settings, &opus_workers_and_an_astra_reviewer(), None).unwrap();
assert_eq!(
to_keep(&settings, &lines),
[
(
"crew.worker".to_owned(),
"[\"claude-code/opus-5-5\"]".to_owned()
),
("crew.reviewer".to_owned(), "[\"astra\"]".to_owned()),
(
"crew.judge".to_owned(),
"[\"claude-code/opus-5-5\"]".to_owned()
),
]
);
let mut own_reviewers = fable();
own_reviewers.roles.insert(
RoleName::Reviewer,
RoleSettings {
models: vec!["codex".parse().unwrap()],
..RoleSettings::default()
},
);
let lines = understood(&own_reviewers, &opus_workers_and_an_astra_reviewer(), None).unwrap();
let kept = to_keep(&own_reviewers, &lines);
assert!(
kept.contains(&("roles.reviewer.models".to_owned(), "[\"astra\"]".to_owned())),
"{kept:?}"
);
}
#[test]
fn a_crew_from_captain_shows_the_models_the_run_has() {
let mut settings = Settings {
crew: CrewSettings {
main: "claude-code/claude-haiku-5-5".parse().unwrap(),
..CrewSettings::default()
},
..Settings::default()
};
settings.crew.worker = ["claude-code", "antigravity-cli", "codex"]
.map(|worker| worker.parse().unwrap())
.to_vec();
let words = applied(
vec![followed(
InstructionKind::Review,
"with Codex as the reviewer",
)],
&[
("roles.reviewer.models", "[\"codex\"]"),
(
"roles.worker.models",
"[\"claude-code\", \"antigravity-cli\"]",
),
],
);
let run: Vec<String> = [
"workflow=\"orchestrator\"",
"crew.orchestrator=\"main\"",
"roles.reviewer.models=[\"codex\"]",
"roles.worker.models=[\"claude-code\", \"antigravity-cli\"]",
"roles.worker.models=[\"claude-code/claude-haiku-5-5\"]",
]
.map(str::to_owned)
.to_vec();
let lines = understood(&settings, &words, Some(&run)).expect("the reviewer is your words");
let shown: Vec<(&str, &str)> = lines
.iter()
.map(|line| (line.role.plural(), line.from.as_str()))
.collect();
assert_eq!(
shown,
[
("orchestrator", "your main session"),
("workers", "your main session"),
("reviewers", "as you asked"),
("judge", "your settings"),
]
);
assert_eq!(lines[0].who, lines[1].who, "the main session builds too");
assert!(!lines[1].who.contains("Antigravity"), "{}", lines[1].who);
assert_eq!(
to_keep(&settings, &lines),
[("crew.reviewer".to_owned(), "[\"codex\"]".to_owned())]
);
let words_only = understood(&settings, &words, None).unwrap();
assert_eq!(words_only[1].from, "as you asked");
}
#[test]
fn the_phrase_is_the_words_that_reach_every_other_role() {
assert_eq!(
phrase("all the other agents need to be opus"),
"all the other agents"
);
assert_eq!(phrase("every other agent, on opus"), "every other agent");
assert_eq!(phrase("the others on opus"), "the others");
assert_eq!(phrase("everyone else on opus"), "everyone else on opus");
}