use super::{World, fake_fail};
use crate::binding::workspace_path;
use crate::cli_outbound::Cli;
use crate::opslog::{Origin, SYNTHETIC_EXIT, YOG_STEP};
use crate::start::{Deps, StartError, execute_ensure_workspace};
use crate::world::{Layout, layout_under};
const MANIFEST: &str = "roles:\n worker:\n pinned:\n - goal.md\n\
order: []\n budget_tokens: 150000\n overflow: drop\n";
fn layout(w: &World) -> Layout {
layout_under(w.yog.path())
}
fn deps(w: &World, litany: &Cli) -> Deps {
Deps {
bl: Cli::new("/no/bl"),
litany: litany.clone(),
state_root: w.state.path().to_path_buf(),
yog_binary: std::path::PathBuf::from("/no/yog"),
}
}
#[test]
fn ensure_aborts_when_the_capability_control_cannot_be_authored() {
let w = World::new();
let ws = workspace_path(w.yog.path(), "cobalt-gecko");
crate::test_support::workspace::seed_workspace_workflow(&ws, "events: {}\n");
let litany = Cli::new(fake_fail(w.bin.path(), "litany", "no config for you"));
let err = execute_ensure_workspace(
&deps(&w, &litany),
"TS",
&ws,
"default",
&layout(&w),
Origin::Balls,
)
.unwrap_err();
assert!(matches!(err, StartError::Control(_)), "{err}");
let ops = w.ops();
assert_eq!(
ops.last().unwrap().argv,
[YOG_STEP, "control"],
"the abort leaves its own step-failure row (Z5)"
);
assert_eq!(ops.last().unwrap().exit, SYNTHETIC_EXIT);
}
#[test]
fn ensure_leaves_an_already_controlled_workspace_alone() {
let w = World::new();
let ws = workspace_path(w.yog.path(), "cobalt-gecko");
let shim = crate::world::tools::control_path(&layout(&w).tools);
let authored = crate::control::author::authored("events: {}\n", &shim);
crate::test_support::workspace::seed_workspace_workflow(&ws, &authored);
let litany = Cli::new("/definitely/not/a/real/litany");
assert!(
!execute_ensure_workspace(
&deps(&w, &litany),
"TS",
&ws,
"default",
&layout(&w),
Origin::Balls
)
.unwrap()
);
assert!(w.ops().is_empty(), "converged: nothing ran, nothing logged");
}
#[test]
fn ensure_converges_the_control_and_the_instruction_glob_in_one_drive() {
let w = World::new();
let ws = workspace_path(w.yog.path(), "cobalt-gecko");
crate::test_support::workspace::seed_workspace_config(
&ws,
&[
("workflow.yaml", "events: {}\n"),
("manifest.yaml", MANIFEST),
],
);
let record = w.bin.path().join("staged");
let litany = Cli::new(super::write_exec(
w.bin.path(),
"litany",
&format!(
"#!/bin/sh\nprintf '%s\\n' \"$YOG_EDIT_SRC\" > '{}'\nexit 0\n",
record.display()
),
));
execute_ensure_workspace(
&deps(&w, &litany),
"TS",
&ws,
"default",
&layout(&w),
Origin::Balls,
)
.unwrap();
assert_eq!(w.ops().len(), 1, "one drive, one row: {:?}", w.verbs());
let staged = std::path::PathBuf::from(std::fs::read_to_string(&record).unwrap().trim());
let workflow = std::fs::read_to_string(staged.join("workflow.yaml")).unwrap();
assert!(workflow.contains("tool_control:"), "{workflow}");
let manifest = std::fs::read_to_string(staged.join("manifest.yaml")).unwrap();
assert!(manifest.contains("- instructions/**"), "{manifest}");
assert!(manifest.contains("budget_tokens: 150000"), "{manifest}");
}
#[test]
fn ensure_leaves_an_already_converged_workspace_alone() {
let w = World::new();
let ws = workspace_path(w.yog.path(), "cobalt-gecko");
let shim = crate::world::tools::control_path(&layout(&w).tools);
crate::test_support::workspace::seed_workspace_config(
&ws,
&[
(
"workflow.yaml",
&crate::control::author::authored("events: {}\n", &shim),
),
(
"manifest.yaml",
&crate::start::instructions::manifest::authored(MANIFEST),
),
],
);
let litany = Cli::new("/definitely/not/a/real/litany");
assert!(
!execute_ensure_workspace(
&deps(&w, &litany),
"TS",
&ws,
"default",
&layout(&w),
Origin::Balls
)
.unwrap()
);
assert!(w.ops().is_empty(), "converged: nothing ran, nothing logged");
}