Parfii-bot
9c8c7c3598
fix(prepare): auto-generate agent-id when absent + dogfood ergonomics
...
Dogfood gap found: orchestrator running `kei-agent-runtime prepare
<task.toml>` hit "task.agent-id is empty" error. Required 3-step flow
(ledger fork → edit task.toml → prepare) for every spawn.
Fix: auto-generate `ag-<role>-<unix-ms-hex>-<4hex-rand>` if task.agent-id
empty. Orchestrator can still pre-allocate for deterministic ids;
auto-gen is ergonomic default. DNA compose sees the effective id via
clone+inject into TaskSpec before Dna::compose.
Helper `autogen_agent_id()` uses SystemTime millis + rand u16 — low
collision at orchestrator spawn rate (< 1 spawn/ms).
build_ledger_row() split: original preserved as thin wrapper, new
build_ledger_row_with_id() accepts explicit id for auto-gen path.
Verified end-to-end via `/tmp/keisei-dogfood/test-task.toml`:
prepare now emits complete AgentInvocation including composed prompt,
DNA, verify command — ready for orchestrator Agent-tool invocation
without pre-alloc step.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 05:23:55 +08:00
Parfii-bot
30a07e22ca
Merge feat/convergence-p3-role-dna — role expression + DNA identity
2026-04-23 04:47:30 +08:00
Parfii-bot
84319efcb6
feat(convergence/p3): Role expression (extends/relaxes) + DNA identity
...
Layer E + G. Role TOML gains extends/relaxes for parent-role
composition; agent spawn gets self-describing DNA identity alongside
UUID.
Role expression:
- _roles/*.toml gain optional `extends = "<parent>"` + `relaxes = [...]`
- compose.rs + verify.rs delegate to new role::resolve_role() with
recursive extends-chain resolution + cycle detection
- explorer.toml: 28→18 LOC (extends read-only)
- edit-shared.toml: 31→23 LOC (extends edit-local, relaxes
scope::files-whitelist for task-param override)
DNA identity:
- new dna.rs (159 LOC) — compose/render/parse round-trip
- AgentInvocation carries dna field (prepare.rs)
- Format: <role>::<caps-bitmap>::<sha4-scope>::<sha4-body>-<hex4-nonce>
- ≤ 80 chars total, greppable, parseable
- 11 capability codes in CAP_CODES table: NG, FW, FD, CP, CG, TG, ND,
RF, SG, DT, BA
kei-ledger schema v2:
- ADD COLUMN dna TEXT + prefix index
- `kei-ledger fork --dna <string>` optional flag
- AgentRow.dna: Option<String>
- Backward compat: schema migration detects + applies on open
Docs: AGENT-SUBSTRATE-SCHEMA.md Layer E + Layer G sections + CAP_CODES table.
New deps: sha2 (workspace), rand 0.8.
Tests: kei-agent-runtime 50 (was 41, +9: 4 role + 5 DNA), kei-ledger
10 (was 9, +1 DNA roundtrip).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 04:46:48 +08:00
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
Parfii-bot
e4b64418fc
feat(convergence/u2): capability renames + back-compat aliases
...
Pre-unlock wave U2. Task 3 from CONVERGENCE-PLAN — rename misleading
capability names, keep old names as deprecated aliases.
Renames:
- tools::read-only → tools::deny-tools (mechanism is tool-name denial,
not "read-only" metaphor)
- tools::cargo-only-bash → tools::bash-allowlist (mechanism is Bash
pattern allow-list; cargo-only is one config value)
Back-compat via registry.resolve_alias():
- Old dir _capabilities/tools/{read-only,cargo-only-bash}/ retained with
capability.toml-only stub: `alias = "<new-name>"` + `deprecated` field
- registry.rs loads alias stubs, redirects lookup before dispatch
- warn_deprecated_once() emits single-shot stderr per alias per process
via OnceLock<Mutex<HashSet>>
- Zero breaking change to existing manifests / task.toml referencing
old names
Rust impl files renamed in place:
- gates/tools_read_only.rs → gates/tools_deny_tools.rs (struct
DenyTools)
- gates/tools_cargo_only_bash.rs → gates/tools_bash_allowlist.rs
(struct BashAllowlist)
- gates/mod.rs + registry.rs + gate_smoke.rs updated
Roles updated (3): read-only.toml, explorer.toml, edit-local.toml —
reference new names directly.
Tests: kei-agent-runtime 41/41 (was 40, +1 deprecated_aliases_resolve
_to_new_names), _assembler 40/40 unchanged (substrate role expansion
follows new paths).
Docs updated: AGENT-ROLES.md, AGENT-SUBSTRATE-SCHEMA.md, 4 _manifests
referencing the old names (comment-only annotations).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:43:40 +08:00
Parfii-bot
d72ae51f16
feat(agent-substrate/wrapper): kei-agent-runtime prepare — orchestrator ergonomics
...
Single-command "prepare spawn" that emits everything orchestrator needs
to invoke the Agent tool: composed prompt, subagent_type (from role's
new claude-subagent-type field), isolation mode, verify command,
ledger row.
Before this: orchestrator ran compose + read prompt + manually
constructed Agent tool call + manually built verify command. 4 steps.
After: `kei-agent-runtime prepare <task.toml> --format=human` outputs
a single copy-paste-ready block. Orchestrator pastes into Agent tool
and records the verify command for return.
Files:
- src/prepare.rs (170 LOC) — prepare() returns AgentInvocation struct
(agent_id, prompt, subagent_type, isolation, description,
verify_command, ledger_row)
- src/main.rs (+39 LOC) — Prepare subcommand with --format=human|json|toml
- src/lib.rs (+2 LOC — pub mod prepare)
- _roles/*.toml (5 files) — new optional claude-subagent-type field:
- edit-local / edit-shared → "code-implementer"
- read-only → "critic" (default; "architect" override possible)
- explorer → "Explore"
- git-ops → "NOT-SPAWNABLE" (refused by prepare with RULE 0.13)
- tests/prepare_smoke.rs (3 tests) — happy path, unknown role, non-spawnable refusal
- docs/AGENT-SUBSTRATE-SCHEMA.md (+ ## Orchestrator ergonomics section)
Tests: 40/40 (was 37, +3 prepare_smoke). Same path exercised in tempfile
fixtures that the real CLI would hit end-to-end.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:25:14 +08:00
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