Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
130 lines
3.9 KiB
Rust
130 lines
3.9 KiB
Rust
//! drive_smoke — integration tests for `kei-spawn drive` subcommand.
|
|
//!
|
|
//! The drive subcommand shells the full pipeline:
|
|
//! 1. spawn_from_task (prepare + ledger fork)
|
|
//! 2. SpawnOutput JSON → stdout
|
|
//! 3. ManualDriver::invoke → NotImplemented → stderr + exit 64
|
|
//!
|
|
//! Because exit-code assertions require invoking the real binary, these
|
|
//! tests use `CARGO_BIN_EXE_kei-spawn` (populated by cargo for integration
|
|
//! tests) with `KEI_SPAWN_LEDGER_NOOP=1` set so the ledger subprocess is
|
|
//! a no-op.
|
|
|
|
use std::path::Path;
|
|
use std::process::Command;
|
|
use tempfile::TempDir;
|
|
|
|
fn write_capability(root: &Path, cat: &str, slug: &str, body: &str) {
|
|
let dir = root.join("_capabilities").join(cat).join(slug);
|
|
std::fs::create_dir_all(&dir).unwrap();
|
|
std::fs::write(dir.join("text.md"), body).unwrap();
|
|
}
|
|
|
|
fn write_role(root: &Path, name: &str, toml: &str) {
|
|
std::fs::create_dir_all(root.join("_roles")).unwrap();
|
|
std::fs::write(root.join("_roles").join(format!("{name}.toml")), toml).unwrap();
|
|
}
|
|
|
|
fn write_task(root: &Path, toml: &str) -> std::path::PathBuf {
|
|
let path = root.join("task.toml");
|
|
std::fs::write(&path, toml).unwrap();
|
|
path
|
|
}
|
|
|
|
fn minimal_kit(root: &Path) {
|
|
write_capability(root, "policy", "no-git-ops", "## Never git.\n");
|
|
write_capability(root, "output", "report-format", "## Report fields.\n");
|
|
write_role(
|
|
root,
|
|
"edit-local",
|
|
r#"
|
|
[role]
|
|
name = "edit-local"
|
|
spawnable = true
|
|
claude-subagent-type = "code-implementer"
|
|
|
|
[capabilities]
|
|
required = ["policy::no-git-ops", "output::report-format"]
|
|
"#,
|
|
);
|
|
}
|
|
|
|
fn bin() -> Command {
|
|
let mut c = Command::new(env!("CARGO_BIN_EXE_kei-spawn"));
|
|
c.env("KEI_SPAWN_LEDGER_NOOP", "1");
|
|
c
|
|
}
|
|
|
|
#[test]
|
|
fn drive_on_valid_task_emits_spawn_json_and_exits_64() {
|
|
let tmp = TempDir::new().unwrap();
|
|
let root = tmp.path();
|
|
minimal_kit(root);
|
|
let task_path = write_task(
|
|
root,
|
|
r#"
|
|
[task]
|
|
role = "edit-local"
|
|
|
|
[body]
|
|
text = "Drive smoke test."
|
|
"#,
|
|
);
|
|
|
|
let output = bin()
|
|
.arg("drive")
|
|
.arg(&task_path)
|
|
.arg("--kit-root")
|
|
.arg(root)
|
|
.output()
|
|
.expect("run kei-spawn drive");
|
|
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
// Stdout must be SpawnOutput JSON (contain agent_id + prompt fields).
|
|
assert!(stdout.contains("\"agent_id\""), "stdout missing agent_id: {stdout}");
|
|
assert!(stdout.contains("\"subagent_type\""), "stdout missing subagent_type: {stdout}");
|
|
assert!(stdout.contains("\"prompt\""), "stdout missing prompt: {stdout}");
|
|
// Stderr must explain the v0.1 NotImplemented state.
|
|
assert!(
|
|
stderr.contains("HTTP Anthropic-API integration not yet wired"),
|
|
"stderr missing NotImplemented msg: {stderr}"
|
|
);
|
|
// Exit code 64 (EX_USAGE range, NotImplemented convention).
|
|
assert_eq!(output.status.code(), Some(64), "exit code must be 64, got: {:?}; stderr={stderr}", output.status.code());
|
|
}
|
|
|
|
#[test]
|
|
fn drive_on_unknown_role_exits_nonzero_with_spawn_error() {
|
|
let tmp = TempDir::new().unwrap();
|
|
let root = tmp.path();
|
|
// NO minimal_kit — role cannot resolve.
|
|
let task_path = write_task(
|
|
root,
|
|
r#"
|
|
[task]
|
|
role = "ghost-role"
|
|
|
|
[body]
|
|
text = "x"
|
|
"#,
|
|
);
|
|
|
|
let output = bin()
|
|
.arg("drive")
|
|
.arg(&task_path)
|
|
.arg("--kit-root")
|
|
.arg(root)
|
|
.output()
|
|
.expect("run kei-spawn drive");
|
|
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(
|
|
stderr.contains("drive") || stderr.contains("role") || stderr.contains("ghost-role"),
|
|
"stderr should reference the spawn failure: {stderr}"
|
|
);
|
|
// Spawn error surfaces as exit 1 (not 64); must NOT be success.
|
|
let code = output.status.code();
|
|
assert_ne!(code, Some(0), "unknown role must fail");
|
|
assert_ne!(code, Some(64), "unknown role must not be NotImplemented: stderr={stderr}");
|
|
}
|