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.
221 lines
8.4 KiB
Rust
221 lines
8.4 KiB
Rust
//! Verify smoke tests — one happy + one fail per verify capability.
|
|
//!
|
|
//! Git-dependent verifies use an init-ed tempdir with `main` branch.
|
|
|
|
use kei_agent_runtime::capability::{RunMode, TaskSpec, VerifyContext, VerifyResult};
|
|
use kei_agent_runtime::registry;
|
|
use std::path::{Path, PathBuf};
|
|
use std::process::Command;
|
|
use std::sync::Mutex;
|
|
use tempfile::TempDir;
|
|
|
|
/// Serialise access to env vars across parallel tests.
|
|
static ENV_LOCK: Mutex<()> = Mutex::new(());
|
|
|
|
fn vctx<'a>(
|
|
task: &'a TaskSpec,
|
|
worktree: &'a Path,
|
|
main: &'a Path,
|
|
agent_id: &'a str,
|
|
) -> VerifyContext<'a> {
|
|
VerifyContext {
|
|
agent_id,
|
|
task,
|
|
worktree_path: worktree,
|
|
main_repo: main,
|
|
run_mode: RunMode::Worktree,
|
|
simulated_merge_path: None,
|
|
}
|
|
}
|
|
|
|
fn init_git_repo(dir: &Path) {
|
|
Command::new("git").args(["init", "-q", "-b", "main"]).current_dir(dir).output().unwrap();
|
|
Command::new("git").args(["config", "user.email", "t@t"]).current_dir(dir).output().unwrap();
|
|
Command::new("git").args(["config", "user.name", "t"]).current_dir(dir).output().unwrap();
|
|
std::fs::write(dir.join("README.md"), "seed\n").unwrap();
|
|
Command::new("git").args(["add", "."]).current_dir(dir).output().unwrap();
|
|
Command::new("git").args(["commit", "-q", "-m", "seed"]).current_dir(dir).output().unwrap();
|
|
}
|
|
|
|
fn commit_all(dir: &Path, msg: &str) {
|
|
Command::new("git").args(["add", "."]).current_dir(dir).output().unwrap();
|
|
Command::new("git").args(["commit", "-q", "-m", msg]).current_dir(dir).output().unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn constructor_pattern_pass_on_small_file() {
|
|
let tmp = TempDir::new().unwrap();
|
|
std::fs::write(tmp.path().join("small.rs"), "fn x() -> i32 { 1 }\n").unwrap();
|
|
let cap = registry::get_verify("quality::constructor-pattern").unwrap();
|
|
let task = TaskSpec::default();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
assert_eq!(cap.verify(&ctx), VerifyResult::Pass);
|
|
}
|
|
|
|
#[test]
|
|
fn constructor_pattern_fails_on_large_file() {
|
|
let tmp = TempDir::new().unwrap();
|
|
let big = (0..250).map(|i| format!("// line {i}")).collect::<Vec<_>>().join("\n");
|
|
std::fs::write(tmp.path().join("big.rs"), big).unwrap();
|
|
let cap = registry::get_verify("quality::constructor-pattern").unwrap();
|
|
let task = TaskSpec::default();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
matches!(cap.verify(&ctx), VerifyResult::Fail { .. });
|
|
}
|
|
|
|
#[test]
|
|
fn constructor_pattern_fails_on_long_fn() {
|
|
let tmp = TempDir::new().unwrap();
|
|
let body = (0..40).map(|_| " let _ = 0;").collect::<Vec<_>>().join("\n");
|
|
let src = format!("fn long() {{\n{body}\n}}\n");
|
|
std::fs::write(tmp.path().join("longfn.rs"), src).unwrap();
|
|
let cap = registry::get_verify("quality::constructor-pattern").unwrap();
|
|
let task = TaskSpec::default();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
matches!(cap.verify(&ctx), VerifyResult::Fail { .. });
|
|
}
|
|
|
|
#[test]
|
|
fn tests_green_passes_with_no_crates_configured() {
|
|
let tmp = TempDir::new().unwrap();
|
|
let cap = registry::get_verify("quality::tests-green").unwrap();
|
|
let task = TaskSpec::default(); // empty cargo-test-crates
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
assert_eq!(cap.verify(&ctx), VerifyResult::Pass);
|
|
}
|
|
|
|
#[test]
|
|
fn scope_whitelist_verify_passes_on_matching_diff() {
|
|
let tmp = TempDir::new().unwrap();
|
|
init_git_repo(tmp.path());
|
|
std::fs::create_dir_all(tmp.path().join("allowed")).unwrap();
|
|
std::fs::write(tmp.path().join("allowed/f.rs"), "fn x() {}\n").unwrap();
|
|
commit_all(tmp.path(), "add");
|
|
let mut task = TaskSpec::default();
|
|
task.scope.files_whitelist = vec!["allowed/**".into()];
|
|
let cap = registry::get_verify("scope::files-whitelist").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
// diff against main: no new changes beyond what's already committed → PASS trivially
|
|
assert_eq!(cap.verify(&ctx), VerifyResult::Pass);
|
|
}
|
|
|
|
#[test]
|
|
fn scope_whitelist_verify_fails_on_outside_diff() {
|
|
let tmp = TempDir::new().unwrap();
|
|
init_git_repo(tmp.path());
|
|
// Create branch off main with an outside edit
|
|
Command::new("git")
|
|
.args(["checkout", "-q", "-b", "feature"])
|
|
.current_dir(tmp.path())
|
|
.output()
|
|
.unwrap();
|
|
std::fs::write(tmp.path().join("outside.rs"), "fn x() {}\n").unwrap();
|
|
commit_all(tmp.path(), "outside");
|
|
let mut task = TaskSpec::default();
|
|
task.scope.files_whitelist = vec!["allowed/**".into()];
|
|
let cap = registry::get_verify("scope::files-whitelist").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
matches!(cap.verify(&ctx), VerifyResult::Fail { .. });
|
|
}
|
|
|
|
#[test]
|
|
fn scope_denylist_verify_fails_on_denied_path() {
|
|
let tmp = TempDir::new().unwrap();
|
|
init_git_repo(tmp.path());
|
|
Command::new("git")
|
|
.args(["checkout", "-q", "-b", "feature"])
|
|
.current_dir(tmp.path())
|
|
.output()
|
|
.unwrap();
|
|
std::fs::write(tmp.path().join("Cargo.toml"), "[package]\n").unwrap();
|
|
commit_all(tmp.path(), "bad");
|
|
let mut task = TaskSpec::default();
|
|
task.scope.files_denylist = vec!["Cargo.toml".into()];
|
|
let cap = registry::get_verify("scope::files-denylist").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
matches!(cap.verify(&ctx), VerifyResult::Fail { .. });
|
|
}
|
|
|
|
#[test]
|
|
fn safety_no_dep_bump_verify_passes_with_no_version_diff() {
|
|
let tmp = TempDir::new().unwrap();
|
|
init_git_repo(tmp.path());
|
|
let task = TaskSpec::default();
|
|
let cap = registry::get_verify("safety::no-dep-bump").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
assert_eq!(cap.verify(&ctx), VerifyResult::Pass);
|
|
}
|
|
|
|
#[test]
|
|
fn safety_no_dep_bump_verify_fails_on_version_diff() {
|
|
let tmp = TempDir::new().unwrap();
|
|
init_git_repo(tmp.path());
|
|
std::fs::write(tmp.path().join("Cargo.toml"), "version = \"0.1.0\"\n").unwrap();
|
|
commit_all(tmp.path(), "seed version");
|
|
Command::new("git")
|
|
.args(["checkout", "-q", "-b", "feature"])
|
|
.current_dir(tmp.path())
|
|
.output()
|
|
.unwrap();
|
|
std::fs::write(tmp.path().join("Cargo.toml"), "version = \"0.2.0\"\n").unwrap();
|
|
commit_all(tmp.path(), "bump");
|
|
let task = TaskSpec::default();
|
|
let cap = registry::get_verify("safety::no-dep-bump").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
matches!(cap.verify(&ctx), VerifyResult::Fail { .. });
|
|
}
|
|
|
|
#[test]
|
|
fn output_report_format_passes_when_fields_present() {
|
|
let _guard = ENV_LOCK.lock().unwrap();
|
|
let tmp = TempDir::new().unwrap();
|
|
let report_path: PathBuf = tmp.path().join("report.md");
|
|
std::fs::write(
|
|
&report_path,
|
|
"## Summary\n\nfiles-touched: 3\ncargo-check: PASS\n",
|
|
)
|
|
.unwrap();
|
|
std::env::set_var("AGENT_REPORT_PATH", &report_path);
|
|
let mut task = TaskSpec::default();
|
|
task.output.report_fields_required =
|
|
vec!["files-touched".into(), "cargo-check".into()];
|
|
let cap = registry::get_verify("output::report-format").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
let r = cap.verify(&ctx);
|
|
std::env::remove_var("AGENT_REPORT_PATH");
|
|
assert_eq!(r, VerifyResult::Pass);
|
|
}
|
|
|
|
#[test]
|
|
fn output_report_format_fails_when_missing() {
|
|
let _guard = ENV_LOCK.lock().unwrap();
|
|
let tmp = TempDir::new().unwrap();
|
|
let report_path: PathBuf = tmp.path().join("report.md");
|
|
std::fs::write(&report_path, "only summary").unwrap();
|
|
std::env::set_var("AGENT_REPORT_PATH", &report_path);
|
|
let mut task = TaskSpec::default();
|
|
task.output.report_fields_required = vec!["files-touched".into()];
|
|
let cap = registry::get_verify("output::report-format").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
let r = cap.verify(&ctx);
|
|
std::env::remove_var("AGENT_REPORT_PATH");
|
|
match r {
|
|
VerifyResult::Fail { .. } => {}
|
|
other => panic!("expected Fail, got {other:?}"),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn output_severity_grade_accepts_high() {
|
|
let _guard = ENV_LOCK.lock().unwrap();
|
|
let tmp = TempDir::new().unwrap();
|
|
let report_path: PathBuf = tmp.path().join("r.md");
|
|
std::fs::write(&report_path, "**HIGH**: foo\n").unwrap();
|
|
std::env::set_var("AGENT_REPORT_PATH", &report_path);
|
|
let task = TaskSpec::default();
|
|
let cap = registry::get_verify("output::severity-grade").unwrap();
|
|
let ctx = vctx(&task, tmp.path(), tmp.path(), "t");
|
|
let r = cap.verify(&ctx);
|
|
std::env::remove_var("AGENT_REPORT_PATH");
|
|
assert_eq!(r, VerifyResult::Pass);
|
|
}
|