diff --git a/crates/mind-body/tests/self_run.rs b/crates/mind-body/tests/self_run.rs
index ddfc2f1..98f014f 100644
--- a/crates/mind-body/tests/self_run.rs
+++ b/crates/mind-body/tests/self_run.rs
@@ -46,6 +46,44 @@ fn the_run_cap_must_be_a_positive_number_of_seconds_and_the_runtime_directory_mu
assert!(!message.contains("MIND_SELF_RUN_CAP_S") && message.contains("RUNTIME_DIRECTORY is not set"), "{message}");
}
+/// The hook `claude` runs in the session: `mind-self-run inject --spool
` reads the hook's
+/// JSON on stdin and prints what the spool holds as context, exit 0; with `--pre-compact` it
+/// blocks the compaction with exit 2; without a spool it is a usage error.
+#[test]
+fn inject_prints_the_spooled_briefs_as_hook_context_and_blocks_a_compaction() {
+ use std::io::Write;
+ use std::process::Stdio;
+ let spool = std::env::temp_dir().join(format!("mind-self-run-inject-{}", std::process::id()));
+ std::fs::create_dir_all(&spool).unwrap();
+ std::fs::write(
+ spool.join("00000000000000000007-b7.json"),
+ r#"{"id":"eureka-body:follow_up:b7","campaign":"eureka-body","repo":"GameCult/Huginn","item":"Wire the thing.","ordinal":7}"#,
+ )
+ .unwrap();
+ let inject = |extra: &[&str], input: &str| {
+ let mut child = Command::new(env!("CARGO_BIN_EXE_mind-self-run"))
+ .args(["inject", "--spool", spool.to_str().unwrap()])
+ .args(extra)
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .spawn()
+ .unwrap();
+ child.stdin.take().unwrap().write_all(input.as_bytes()).unwrap();
+ child.wait_with_output().unwrap()
+ };
+ let blocked = inject(&["--pre-compact"], "{}");
+ assert_eq!((blocked.status.code(), blocked.stdout.is_empty()), (Some(2), true));
+ let printed = inject(&[], r#"{"hook_event_name":"PostToolBatch"}"#);
+ assert_eq!(printed.status.code(), Some(0));
+ let text = String::from_utf8_lossy(&printed.stdout);
+ assert!(text.contains("hookSpecificOutput") && text.contains("eureka-body:follow_up:b7") && text.contains("Wire the thing."), "{text}");
+ assert!(inject(&[], "{}").stdout.is_empty(), "claimed once");
+ let bare = Command::new(env!("CARGO_BIN_EXE_mind-self-run")).arg("inject").stdin(Stdio::null()).output().unwrap();
+ assert_eq!(bare.status.code(), Some(2));
+ std::fs::remove_dir_all(&spool).unwrap();
+}
+
#[test]
fn without_an_instance_or_with_a_stray_argument_it_exits_2_with_the_usage_and_echoes_nothing() {
let canary = "canary-argument-3f9a";
@@ -321,7 +359,7 @@ mod lane {
let body = format!(
"read -r -u \"$CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR\" cred
echo journal-line >&2
-echo '{first}'\necho '{second}'\nread -t 5 start\nread -t 5 flush\necho \"$start\" >> {record}\necho \"$flush\" >> {record}\necho \"$SELF_RUN_ENV_CANARY\" >> {record}\necho \"$cred\" >> {record}\necho '{{\"type\":\"result\"}}'\nwhile read more; do :; done\nexit 0",
+echo '{first}'\necho '{second}'\nread -t 5 start\nread -t 5 flush\necho \"$start\" >> {record}\necho \"$flush\" >> {record}\necho \"$SELF_RUN_ENV_CANARY\" >> {record}\necho \"$cred\" >> {record}\necho '{{\"type\":\"result\"}}'\necho '{{\"type\":\"result\"}}'\nwhile read more; do :; done\nexit 0",
first = request("msg_1", 100),
second = request("msg_2", 299_999),
record = bin.path().join("record").display(),
@@ -333,7 +371,8 @@ echo '{first}'\necho '{second}'\nread -t 5 start\nread -t 5 flush\necho \"$start
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
assert_eq!(output.status.code(), Some(0), "{stdout}\n{}", String::from_utf8_lossy(&output.stderr));
- assert_eq!(stdout, "request 1 prefix 101\nrequest 2 prefix 300000\nended: flush-requested code 0 requests 2 prefix 300000\n");
+ let printed: String = stdout.lines().filter(|line| !line.starts_with("decision ") && !line.starts_with("result")).map(|line| format!("{line}\n")).collect();
+ assert_eq!(printed, "request 1 prefix 101\nrequest 2 prefix 300000\nended: flush-requested code 0 requests 2 prefix 300000\n");
assert!(!all_output(&output).contains(ENV_CANARY), "the unit environment is not echoed");
assert!(String::from_utf8_lossy(&output.stderr).contains("journal-line"), "the child's stderr is the unit's journal");