KeiSeiKit-1.0/_primitives/_rust/kei-agent-runtime/tests/command_verify_smoke.rs
Parfii-bot 360a20a942 feat(convergence/p2): PatternGate + CommandVerify unified traits
Layer C + D. 6 gate modules + 3 verify modules → 1 generic struct per
family + const declarations. Data-driven, not module-per-capability.

New:
- src/gates/pattern_gate.rs (192 LOC) — PatternGate struct with
  GateMode::{DenyIfMatch, AllowIfMatch}, static regex compilation via
  once_cell, bypass env support, Capability trait impl
- src/verifies/command_verify.rs (142 LOC) — CommandVerify struct with
  WorkDir::{WorkspaceRoot, CrateDir, MainRepoSub}, subprocess exec +
  exit-code check, extra_env support, Capability trait impl

Converted (const declarations, ~15-27 LOC each):
- gates/policy_no_git_ops.rs (49→22)
- gates/safety_no_dep_bump.rs (35→19)
- gates/scope_files_whitelist.rs (37→16)
- gates/scope_files_denylist.rs (35→16)
- gates/tools_bash_allowlist.rs (58→27)
- verifies/quality_cargo_check_green.rs (41→18)
- verifies/quality_tests_green.rs (75→80, folded common shape)
- verifies/safety_no_dep_bump.rs (39→47)

Kept separate (different shape, not PatternGate/CommandVerify):
- gates/tools_deny_tools.rs (tool-name match, not pattern)
- verifies/quality_constructor_pattern.rs (LOC walker)
- verifies/output/report_format.rs + severity_grade.rs (text parsers)
- verifies/scope_files_{whitelist,denylist}.rs (diff-walkers)

Registry.rs preserves alias table + deprecation warnings + all_names().

Tests: 57/57 green (was 41, +16: 10 pattern_gate_smoke + 6 command_verify_smoke).

LOC net: 5 gates 214→100 (-53%), shared PatternGate+CommandVerify 334
LOC absorb duplication. Amortization breaks even around 3-4 new gates
added later.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 04:46:47 +08:00

131 lines
3.7 KiB
Rust

//! Smoke tests for the generic `CommandVerify` (Layer D convergence).
//!
//! Covers default exit-code mapper (pass + fail), custom runner path,
//! and WorkDir resolution.
use kei_agent_runtime::capability::{Capability, RunMode, TaskSpec, VerifyContext, VerifyResult};
use kei_agent_runtime::verifies::command_verify::{CommandVerify, WorkDir};
use std::path::Path;
use tempfile::TempDir;
fn vctx<'a>(task: &'a TaskSpec, worktree: &'a Path, agent_id: &'a str) -> VerifyContext<'a> {
VerifyContext {
agent_id,
task,
worktree_path: worktree,
main_repo: worktree,
run_mode: RunMode::Worktree,
simulated_merge_path: None,
}
}
const TRUE_VERIFY: CommandVerify = CommandVerify {
name: "test::true",
program: "true",
base_args: &[],
work_dir: WorkDir::RunDir,
expected_exit: 0,
fail_reason: "true somehow failed",
custom_runner: None,
arg_builder: None,
result_mapper: None,
};
const FALSE_VERIFY: CommandVerify = CommandVerify {
name: "test::false",
program: "false",
base_args: &[],
work_dir: WorkDir::RunDir,
expected_exit: 0,
fail_reason: "false returned non-zero",
custom_runner: None,
arg_builder: None,
result_mapper: None,
};
#[test]
fn default_runner_passes_on_zero_exit() {
let tmp = TempDir::new().unwrap();
let task = TaskSpec::default();
let ctx = vctx(&task, tmp.path(), "t");
assert_eq!(TRUE_VERIFY.verify(&ctx), VerifyResult::Pass);
}
#[test]
fn default_runner_fails_on_nonzero_exit() {
let tmp = TempDir::new().unwrap();
let task = TaskSpec::default();
let ctx = vctx(&task, tmp.path(), "t");
match FALSE_VERIFY.verify(&ctx) {
VerifyResult::Fail { .. } => {}
other => panic!("expected Fail, got {other:?}"),
}
}
#[test]
fn custom_runner_is_invoked() {
const MARKER_VERIFY: CommandVerify = CommandVerify {
name: "test::custom",
program: "/does/not/matter",
base_args: &[],
work_dir: WorkDir::RunDir,
expected_exit: 0,
fail_reason: "",
custom_runner: Some(|_cv, _ctx| VerifyResult::Pass),
arg_builder: None,
result_mapper: None,
};
let tmp = TempDir::new().unwrap();
let task = TaskSpec::default();
let ctx = vctx(&task, tmp.path(), "t");
assert_eq!(MARKER_VERIFY.verify(&ctx), VerifyResult::Pass);
}
#[test]
fn workspace_root_resolves_to_primitives_rust_when_present() {
let tmp = TempDir::new().unwrap();
let prims = tmp.path().join("_primitives/_rust");
std::fs::create_dir_all(&prims).unwrap();
let cv = CommandVerify {
name: "test::dir",
program: "true",
base_args: &[],
work_dir: WorkDir::WorkspaceRoot,
expected_exit: 0,
fail_reason: "",
custom_runner: None,
arg_builder: None,
result_mapper: None,
};
let task = TaskSpec::default();
let ctx = vctx(&task, tmp.path(), "t");
let resolved = cv.resolve_dir(&ctx);
assert_eq!(resolved, prims);
}
#[test]
fn workspace_root_falls_back_to_run_dir() {
let tmp = TempDir::new().unwrap();
let cv = CommandVerify {
name: "test::dir-fallback",
program: "true",
base_args: &[],
work_dir: WorkDir::WorkspaceRoot,
expected_exit: 0,
fail_reason: "",
custom_runner: None,
arg_builder: None,
result_mapper: None,
};
let task = TaskSpec::default();
let ctx = vctx(&task, tmp.path(), "t");
let resolved = cv.resolve_dir(&ctx);
assert_eq!(resolved, tmp.path().to_path_buf());
}
#[test]
fn cargo_check_green_const_is_registered() {
use kei_agent_runtime::registry;
let c = registry::get_verify("quality::cargo-check-green").unwrap();
assert_eq!(c.name(), "quality::cargo-check-green");
}