Specify and plan M3b: the runner and the tools
A draft spec for the owner's review and 13 offline tasks with their given tests: shared tool arguments and host rules in proto, the sealed fetch target (M3a finding 14), the toolkit tools and SOCKS5 egress proxy, and brokerd's [runner], podman argument lists, runtime and proxy lifecycle. Each task's tests were run against a reference at that task's end state (560 to 638 tests, clippy clean); the reference is not in the repository. Adds the runner-unavailable runbook entry and tip T23 (ETXTBSY in script tests). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
//! The four tools' arguments: `brokerd` writes them to a container's standard input, `toolkit`
|
||||
//! reads them back, and both use these types. Do not edit.
|
||||
|
||||
use proto::tools::{HttpFetchArgs, ReadFileArgs, ShellArgs, WriteFileArgs};
|
||||
|
||||
#[test]
|
||||
fn each_type_round_trips_in_field_order() {
|
||||
let read = ReadFileArgs {
|
||||
path: "/n/a.md".to_string(),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_string(&read).unwrap(),
|
||||
r#"{"path":"/n/a.md"}"#
|
||||
);
|
||||
let write = WriteFileArgs {
|
||||
path: "/n/a.md".to_string(),
|
||||
content: "hi\n".to_string(),
|
||||
};
|
||||
let text = serde_json::to_string(&write).unwrap();
|
||||
assert_eq!(text, r#"{"path":"/n/a.md","content":"hi\n"}"#);
|
||||
assert_eq!(serde_json::from_str::<WriteFileArgs>(&text).unwrap(), write);
|
||||
let fetch = HttpFetchArgs {
|
||||
url: "https://example.com/".to_string(),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_string(&fetch).unwrap(),
|
||||
r#"{"url":"https://example.com/"}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_shell_cwd_is_left_out_when_absent_and_may_be_null_or_missing() {
|
||||
let bare = ShellArgs {
|
||||
command: "ls".to_string(),
|
||||
cwd: None,
|
||||
};
|
||||
assert_eq!(serde_json::to_string(&bare).unwrap(), r#"{"command":"ls"}"#);
|
||||
for text in [r#"{"command":"ls"}"#, r#"{"command":"ls","cwd":null}"#] {
|
||||
assert_eq!(serde_json::from_str::<ShellArgs>(text).unwrap(), bare);
|
||||
}
|
||||
let with = ShellArgs {
|
||||
command: "ls".to_string(),
|
||||
cwd: Some("/n".to_string()),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_string(&with).unwrap(),
|
||||
r#"{"command":"ls","cwd":"/n"}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_and_missing_fields_are_refused() {
|
||||
assert!(serde_json::from_str::<ReadFileArgs>(r#"{"path":"/a","mode":"x"}"#).is_err());
|
||||
assert!(serde_json::from_str::<ReadFileArgs>(r#"{}"#).is_err());
|
||||
assert!(serde_json::from_str::<WriteFileArgs>(r#"{"path":"/a"}"#).is_err());
|
||||
assert!(serde_json::from_str::<ShellArgs>(r#"{"command":"ls","env":{}}"#).is_err());
|
||||
assert!(
|
||||
serde_json::from_str::<HttpFetchArgs>(r#"{"url":"https://a.b/","method":"POST"}"#).is_err()
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user