#![allow(clippy::pedantic, clippy::nursery, missing_docs)]
use std::sync::atomic::{AtomicU64, Ordering};
use polyc_agent::ToolExecutor;
use polyc_agent::delegate::{ShareInCeiling, ShareInError, WorkerScope};
use polyc_tools::ToolRegistry;
fn tmp_root(prefix: &str) -> std::path::PathBuf {
static SEQ: AtomicU64 = AtomicU64::new(0);
let mut p = std::env::temp_dir();
let n = SEQ.fetch_add(1, Ordering::Relaxed);
p.push(format!("pc-{prefix}-{}-{n}", std::process::id()));
std::fs::create_dir_all(&p).expect("temp root is creatable");
p
}
fn registry_at(root: &std::path::Path) -> ToolRegistry {
ToolRegistry::rooted_at(root.to_path_buf(), None)
}
fn src_ceiling() -> ShareInCeiling {
ShareInCeiling {
allow: vec!["src/**".to_owned()],
max_files: 8,
max_bytes: 4096,
}
}
async fn write_file(tools: &dyn ToolExecutor, path: &str, content: &str) -> String {
let args = serde_json::json!({ "path": path, "content": content }).to_string();
tools.execute("file_write", &args).await
}
async fn read_file(tools: &dyn ToolExecutor, path: &str) -> String {
let args = serde_json::json!({ "path": path }).to_string();
tools.execute("file_read", &args).await
}
fn worker(
parent: &ToolRegistry,
id: &str,
share_in: &[String],
ceiling: &ShareInCeiling,
) -> Result<(std::sync::Arc<dyn ToolExecutor>, Vec<String>), ShareInError> {
let scope = WorkerScope {
worker_id: id,
share_in,
ceiling,
};
parent
.for_worker(&scope)
.expect("a registry owns a workspace, so it must re-root")
.map(|handoff| (handoff.tools, handoff.seeded))
}
fn refusal(
result: Result<(std::sync::Arc<dyn ToolExecutor>, Vec<String>), ShareInError>,
) -> ShareInError {
match result {
Ok((_, seeded)) => {
panic!("expected the delegation to be refused, but it seeded {seeded:?}")
}
Err(err) => err,
}
}
#[tokio::test]
async fn a_worker_reads_a_parent_file_the_call_named() {
let root = tmp_root("share-in-reads");
let parent = registry_at(&root);
write_file(&parent, "src/parser.rs", "fn parse() -> u8 { 42 }").await;
let (worker, seeded) = worker(
&parent,
"call-a",
&["src/parser.rs".to_owned()],
&src_ceiling(),
)
.expect("a file inside the ceiling seeds");
assert_eq!(seeded, vec!["src/parser.rs".to_owned()]);
let out = read_file(worker.as_ref(), "src/parser.rs").await;
assert!(
out.contains("fn parse"),
"a seeded worker must see the parent's file: {out}"
);
std::fs::remove_dir_all(&root).ok();
}
#[tokio::test]
async fn an_unnamed_parent_file_stays_unreachable() {
let root = tmp_root("share-in-unnamed");
let parent = registry_at(&root);
write_file(&parent, "src/parser.rs", "fn parse() {}").await;
write_file(&parent, "src/secrets.rs", "const TOKEN: &str = \"s3cret\";").await;
let (worker, _) = worker(
&parent,
"call-a",
&["src/parser.rs".to_owned()],
&src_ceiling(),
)
.expect("a file inside the ceiling seeds");
let out = read_file(worker.as_ref(), "src/secrets.rs").await;
assert!(
!out.contains("s3cret"),
"seeding one file must not expose the rest of the workspace: {out}"
);
std::fs::remove_dir_all(&root).ok();
}
#[tokio::test]
async fn a_workers_edit_to_a_seeded_file_never_reaches_the_parent() {
let root = tmp_root("share-in-copy");
let parent = registry_at(&root);
write_file(&parent, "src/parser.rs", "original").await;
let (worker, _) = worker(
&parent,
"call-a",
&["src/parser.rs".to_owned()],
&src_ceiling(),
)
.expect("a file inside the ceiling seeds");
write_file(worker.as_ref(), "src/parser.rs", "rewritten by the worker").await;
let parent_bytes =
std::fs::read_to_string(root.join("src/parser.rs")).expect("parent's file survives");
assert_eq!(
parent_bytes, "original",
"the worker wrote through its copy into the parent's file"
);
std::fs::remove_dir_all(&root).ok();
}
#[tokio::test]
async fn two_seeded_workers_still_cannot_clobber_each_other() {
let root = tmp_root("share-in-concurrent");
let parent = registry_at(&root);
write_file(&parent, "src/parser.rs", "original").await;
let requested = vec!["src/parser.rs".to_owned()];
let (a, _) = worker(&parent, "call-a", &requested, &src_ceiling()).expect("seeds");
let (b, _) = worker(&parent, "call-b", &requested, &src_ceiling()).expect("seeds");
tokio::join!(
write_file(a.as_ref(), "src/parser.rs", "written-by-a"),
write_file(b.as_ref(), "src/parser.rs", "written-by-b"),
);
assert!(
read_file(a.as_ref(), "src/parser.rs")
.await
.contains("written-by-a"),
"worker a lost its write to worker b"
);
assert!(
read_file(b.as_ref(), "src/parser.rs")
.await
.contains("written-by-b"),
"worker b lost its write to worker a"
);
std::fs::remove_dir_all(&root).ok();
}
#[tokio::test]
async fn the_registry_refuses_a_path_outside_the_ceiling() {
let root = tmp_root("share-in-ceiling");
let parent = registry_at(&root);
write_file(&parent, "secrets/token", "s3cret").await;
let err = refusal(worker(
&parent,
"call-a",
&["secrets/token".to_owned()],
&src_ceiling(),
));
assert!(
matches!(err, ShareInError::OutsideCeiling { .. }),
"{err:?}"
);
std::fs::remove_dir_all(&root).ok();
}
#[tokio::test]
async fn a_worker_of_an_unconfigured_agent_seeds_nothing() {
let root = tmp_root("share-in-closed");
let parent = registry_at(&root);
write_file(&parent, "src/parser.rs", "fn parse() {}").await;
let err = refusal(worker(
&parent,
"call-a",
&["src/parser.rs".to_owned()],
&ShareInCeiling::default(),
));
assert!(
matches!(err, ShareInError::OutsideCeiling { .. }),
"{err:?}"
);
std::fs::remove_dir_all(&root).ok();
}
#[tokio::test]
async fn a_worker_cannot_seed_from_a_siblings_subtree() {
let root = tmp_root("share-in-sibling");
let parent = registry_at(&root);
let (sibling, _) = worker(&parent, "call-b", &[], &src_ceiling()).expect("re-roots");
write_file(sibling.as_ref(), "notes.md", "the sibling's private work").await;
let sibling_dir = std::fs::read_dir(&root)
.expect("root readable")
.flatten()
.map(|e| e.file_name().to_string_lossy().into_owned())
.find(|name| name.starts_with(".worker-"))
.expect("the sibling's subtree exists on disk");
let err = refusal(worker(
&parent,
"call-a",
&[format!("{sibling_dir}/notes.md")],
&ShareInCeiling {
allow: vec!["**".to_owned()],
max_files: 8,
max_bytes: 4096,
},
));
assert!(matches!(err, ShareInError::WorkerSubtree { .. }), "{err:?}");
std::fs::remove_dir_all(&root).ok();
}
#[tokio::test]
async fn an_unseeded_worker_is_unchanged_from_the_fenced_behavior() {
let root = tmp_root("share-in-bare");
let parent = registry_at(&root);
write_file(&parent, "src/parser.rs", "fn parse() {}").await;
let (worker, seeded) = worker(&parent, "call-a", &[], &src_ceiling()).expect("re-roots");
assert!(seeded.is_empty());
let out = read_file(worker.as_ref(), "src/parser.rs").await;
assert!(
!out.contains("fn parse"),
"a worker that asked for nothing must see nothing: {out}"
);
std::fs::remove_dir_all(&root).ok();
}