use super::{model_focused, world};
use crate::boundary::Action;
use crate::boundary::reply::Reply;
use crate::cli_outbound::Cli;
use crate::opslog::{self, DETACHED_EXIT};
use crate::start::Prepared;
use crate::test_support::{engine, spawn_guard};
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use tempfile::tempdir;
fn fake_lernie(dir: &Path) -> Cli {
let path = dir.join("lernie");
fs::write(&path, "#!/bin/sh\nexit 0\n").unwrap();
let mut perms = fs::metadata(&path).unwrap().permissions();
perms.set_mode(0o755);
fs::set_permissions(&path, perms).unwrap();
Cli::new(path)
}
fn prepared(w: &super::World) -> Prepared {
Prepared {
workspace: crate::naming::leaf(&w.ws_cobalt),
binding: Some(w.ws_cobalt.clone()),
goal: "prefill".into(),
origin: crate::opslog::Origin::Conversation,
}
}
#[test]
fn the_engines_dispatch_is_the_one_chokepoint_a_posted_act_reaches() {
let bin = tempdir().unwrap();
let w = world();
let (_c, m) = model_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let lernie = fake_lernie(bin.path());
let deps = m.boundary_deps(&lernie, &Cli::new("/no/bl"));
let action = Action::Scan {
workspace: crate::naming::leaf(&(w.ws_cobalt.clone())),
};
let Reply::Outcome(outcome) = engine::act(&m, &deps, "TS", &action).unwrap() else {
panic!("a verb answers an outcome");
};
assert!(outcome.ok());
let ops = opslog::tail(&w.roots.yog_state, 4);
assert_eq!(ops.last().map(|e| e.ts.clone()), Some("TS".to_owned()));
}
#[test]
fn the_retarget_exit_spawns_the_bound_lernie_verb() {
let bin = tempdir().unwrap();
let w = world();
let (_c, m) = model_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let lernie = fake_lernie(bin.path());
let deps = m.boundary_deps(&lernie, &Cli::new("/no/bl"));
let action = Action::Retarget {
workspace: crate::naming::leaf(&(w.ws_cobalt.clone())),
agent: "c-1".into(),
};
let Reply::Outcome(outcome) = engine::act(&m, &deps, "TR", &action).unwrap() else {
panic!("a verb answers an outcome");
};
assert!(outcome.ok());
let ops = opslog::tail(&w.roots.yog_state, 4);
let last = ops.last().expect("the verb is on the trail");
assert_eq!(
last.argv[1..],
[
"retarget".to_owned(),
w.ws_cobalt.display().to_string(),
"c-1".to_owned()
]
);
assert_eq!(last.cwd, w.ws_cobalt.display().to_string());
}
#[test]
fn the_prompt_door_launches_detached_and_mints_off_the_seat_s_own_seed() {
let bin = tempdir().unwrap();
let w = world();
let (_c, m) = model_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let lernie = fake_lernie(bin.path());
let deps = m.boundary_deps(&lernie, &Cli::new("/no/bl"));
let action = Action::Prompt {
prepared: prepared(&w),
goal: "go".into(),
seed: Some(7),
};
let Reply::Started { conversation } = engine::act(&m, &deps, "T1", &action).unwrap() else {
panic!("the prompt door answers the minted name");
};
assert!(
!conversation.is_empty(),
"the minted conversation name rides back"
);
let ops = opslog::tail(&w.roots.yog_state, 4);
assert_eq!(
ops.last().map(|e| e.exit),
Some(DETACHED_EXIT),
"the handoff's §4.2 sentinel row"
);
let dead = m.boundary_deps(&Cli::new("/no/such/lernie"), &Cli::new("/no/bl"));
let err = engine::act(&m, &dead, "T2", &action).unwrap_err();
assert!(!err.is_empty());
}
#[test]
fn a_seedless_prompt_mints_off_the_stamp() {
let bin = tempdir().unwrap();
let w = world();
let (_c, m) = model_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let lernie = fake_lernie(bin.path());
let deps = m.boundary_deps(&lernie, &Cli::new("/no/bl"));
let action = Action::Prompt {
prepared: prepared(&w),
goal: "go".into(),
seed: None,
};
let Reply::Started { conversation } = engine::act(&m, &deps, "T9", &action).unwrap() else {
panic!("the prompt door answers the minted name");
};
assert!(!conversation.is_empty(), "a name was minted regardless");
}
#[test]
fn the_spend_ceiling_refuses_the_fire_and_says_so_on_the_trail() {
let bin = tempdir().unwrap();
let w = world();
fs::create_dir_all(&w.roots.yog_state).unwrap();
fs::write(
w.roots.ui_json(),
r#"{"v":1,"prices":{"opus":{"input":1}},"ceiling":0}"#,
)
.unwrap();
let (_c, m) = model_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let lernie = fake_lernie(bin.path());
let deps = m.boundary_deps(&lernie, &Cli::new("/no/bl"));
let action = Action::Prompt {
prepared: prepared(&w),
goal: "go".into(),
seed: Some(7),
};
let err = engine::act(&m, &deps, "T3", &action).unwrap_err();
assert!(err.contains("spend ceiling reached"), "{err}");
let ops = opslog::tail(&w.roots.yog_state, 4);
let last = ops.last().expect("the refusal is on the trail");
assert_eq!(last.ts, "T3");
assert_eq!(last.argv.first().map(String::as_str), Some("yog-step"));
assert!(
last.argv.iter().any(|a| a == "ceiling"),
"the row names the gate: {:?}",
last.argv
);
assert!(
!last.argv.iter().any(|a| a == "prompt"),
"nothing was spawned: {:?}",
last.argv
);
}
#[test]
fn an_attempt_dispatches_the_ordinary_fork_and_logs_its_whole_argv() {
let bin = tempdir().unwrap();
let w = world();
let (_c, m) = model_focused(&w, &w.ws_cobalt);
let _g = spawn_guard();
let lernie = fake_lernie(bin.path());
let deps = m.boundary_deps(&lernie, &Cli::new("/no/bl"));
let action = Action::Fork {
workspace: crate::naming::leaf(&(w.ws_cobalt.clone())),
parent: "c-1".into(),
attempt: crate::fork::Attempt {
from: "aaaa1111".into(),
role: "worker".into(),
skills: vec!["bash".into()],
},
goal: "try it the other way".into(),
};
let Reply::Outcome(outcome) = engine::act(&m, &deps, "TS", &action).unwrap() else {
panic!("a verb answers an outcome");
};
assert!(outcome.ok());
let argv = opslog::tail(&w.roots.yog_state, 4)
.last()
.map(|e| e.argv.clone())
.unwrap_or_default();
assert!(argv.contains(&"dispatch".to_owned()), "{argv:?}");
assert!(argv.contains(&"worker".to_owned()), "{argv:?}");
assert!(argv.contains(&"c-1".to_owned()), "{argv:?}");
assert!(argv.contains(&"--from".to_owned()), "{argv:?}");
assert!(argv.contains(&"aaaa1111".to_owned()), "{argv:?}");
assert!(
argv.contains(&"try it the other way".to_owned()),
"{argv:?}"
);
let pin = argv.iter().find(|a| a.starts_with("skills/bash/SKILL.md="));
let pin = pin.expect("the skill rides as a pin");
assert!(pin.contains("world/lernie/skills/bash/SKILL.md"), "{pin}");
}