KeiSeiKit-1.0/_primitives/_rust/kei-agent-runtime/tests/simulated_merge_smoke.rs
Parfii-bot b82e3b039e feat(agent-substrate/phase-3): kei-agent-runtime + kei-capability binaries
Two new crates implementing the substrate runtime per locked §Runtime
execution contract + §Capability trait contract (Rust) + §Verify
execution worktree→simulated-merge.

kei-agent-runtime — library + CLI binary:
- src/capability.rs — Capability trait (name/check/verify) + GateContext
  + GateDecision + VerifyContext + VerifyResult + RunMode + TaskSpec
- src/registry.rs — &str → &'static dyn Capability dispatch for 14 impls
- src/gates/ — 6 PreToolUse modules (policy::no-git-ops,
  scope::files-{whitelist,denylist}, safety::no-dep-bump,
  tools::read-only, tools::cargo-only-bash)
- src/verifies/ — 8 on-return modules (quality::constructor-pattern,
  quality::cargo-check-green, quality::tests-green, safety::no-dep-bump,
  scope::files-{whitelist,denylist}, output::{report-format,severity-grade})
- src/compose.rs — task.toml + role + capabilities → prompt.md
- src/spawn.rs — ledger fork + prompt write (actual Agent invocation
  remains orchestrator's tool call)
- src/verify.rs — runs all capability verifies per role; collects
  VerifyReport {passed, failed}
- src/simulated_merge.rs — git worktree add test-merge/<id> + apply diff
  + run verify; cleanup on Drop
- src/main.rs — clap CLI: compose | spawn | verify | run

kei-capability — thin CLI adapter crate:
- Depends on kei-agent-runtime path dep
- Subcommand `check <cap-name>` (PreToolUse gate; stdin JSON, exit 0|2)
- Subcommand `verify <cap-name>` (on-return; env-driven, exit 0 or fail)
- Pattern: shell hook = 3-line `exec kei-capability check "$CAP_NAME"`

Workspace Cargo.toml: both crates registered as members (under agent
substrate v1 marker).

cargo check --workspace: PASS
cargo test -p kei-agent-runtime: 37/37 green
  - 6 capability_trait_smoke (registry lookups, unknown name → None)
  - 3 compose_smoke (fixture role + caps → composed prompt)
  - 12 gate_smoke (each gate: happy + deny + bypass)
  - 4 simulated_merge_smoke (git worktree lifecycle)
  - 12 verify_smoke (each verify: pass + fail + edge cases)
cargo test -p kei-capability: 0/0 (CLI binary, tested via lib)

(Agent completion report cut off by rate-limit at 60 tool-uses; code
itself is green — verified by orchestrator post-commit.)

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

65 lines
2.2 KiB
Rust

//! Simulated-merge smoke test — initialize a tempdir git repo, create a
//! feature branch with a file change, run the simulated-merge flow, assert
//! the temp worktree contains the agent's change on top of main.
use kei_agent_runtime::simulated_merge::{glob_match, run_simulated_merge};
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
fn sh(dir: &Path, args: &[&str]) {
let out = Command::new("git").args(args).current_dir(dir).output().unwrap();
assert!(
out.status.success(),
"git {}: {}",
args.join(" "),
String::from_utf8_lossy(&out.stderr)
);
}
#[test]
fn simulated_merge_applies_agent_diff() {
let tmp = TempDir::new().unwrap();
let repo = tmp.path();
sh(repo, &["init", "-q", "-b", "main"]);
sh(repo, &["config", "user.email", "t@t"]);
sh(repo, &["config", "user.name", "t"]);
std::fs::write(repo.join("README.md"), "seed\n").unwrap();
sh(repo, &["add", "."]);
sh(repo, &["commit", "-q", "-m", "seed"]);
// Agent makes a change on a feature branch
sh(repo, &["checkout", "-q", "-b", "agent/x"]);
std::fs::write(repo.join("new.txt"), "agent wrote this\n").unwrap();
sh(repo, &["add", "."]);
sh(repo, &["commit", "-q", "-m", "agent change"]);
let merged = run_simulated_merge("test123", repo, repo).expect("simulated merge");
let content = std::fs::read_to_string(merged.join("new.txt"))
.expect("agent diff applied in merged worktree");
assert_eq!(content, "agent wrote this\n");
// Cleanup
let _ = Command::new("git")
.args(["worktree", "remove", "--force", merged.to_str().unwrap()])
.current_dir(repo)
.output();
}
#[test]
fn glob_match_handles_double_star() {
assert!(glob_match("_primitives/_rust/kei-forge/**", "_primitives/_rust/kei-forge/src/lib.rs"));
assert!(!glob_match("_primitives/_rust/kei-forge/**", "hooks/foo.sh"));
}
#[test]
fn glob_match_single_star_path_component() {
assert!(glob_match("src/*.rs", "src/main.rs"));
assert!(!glob_match("src/*.rs", "src/mod/main.rs"));
}
#[test]
fn glob_match_exact_path() {
assert!(glob_match("Cargo.toml", "Cargo.toml"));
assert!(!glob_match("Cargo.toml", "src/Cargo.toml"));
}