use crate::prompt::inbox::{inbox_dir, try_acquire};
use crate::test_support::lernie_binary;
use crate::workspace::fixture;
use std::path::Path;
use std::process::Command;
fn message(ws: &Path, agent: &str, content: &str) -> (bool, String) {
let out = Command::new(lernie_binary())
.arg("message")
.arg(ws)
.arg(agent)
.arg(content)
.output()
.expect("spawn lernie message");
(
out.status.success(),
String::from_utf8_lossy(&out.stderr).into_owned(),
)
}
#[test]
fn an_escaping_agent_id_is_declined_and_writes_nothing_outside_the_workspace() {
let (holder, ws) = fixture::workspace();
let (ok, stderr) = message(&ws, "../../victim/pwned", "hello");
assert!(!ok, "an escaping id must exit non-zero");
assert!(stderr.contains("lernie message: agent id"), "{stderr}");
assert!(
!holder.path().join("victim").exists(),
"nothing is written outside the workspace"
);
}
#[test]
fn a_recipient_with_no_branch_is_declined_rather_than_silently_deposited() {
let (_h, ws) = fixture::workspace();
let (ok, stderr) = message(&ws, "20260101-a1", "hello");
assert!(!ok, "an unknown recipient must exit non-zero");
assert!(stderr.contains("existing agent"), "{stderr}");
assert!(
!inbox_dir(&ws, "20260101-a1").exists(),
"the decline creates no inbox directory"
);
}
#[test]
fn an_existing_recipient_still_receives_its_deposit() {
let (_h, ws) = fixture::workspace();
fixture::spawn_root(&ws, "20260101-a1");
let _held = try_acquire(&inbox_dir(&ws, "20260101-a1"))
.unwrap()
.expect("free lease");
let (ok, stderr) = message(&ws, "20260101-a1", "hello");
assert!(ok, "{stderr}");
let deposits = std::fs::read_dir(inbox_dir(&ws, "20260101-a1"))
.unwrap()
.flatten()
.filter(|e| e.file_name().to_string_lossy().ends_with(".md"))
.count();
assert_eq!(deposits, 1, "exactly one deposit landed");
}