KeiSeiKit-1.0/scripts/kei-mcp-wire-grok.sh
KeiSei84 4e5e6bd2c0
Some checks are pending
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / preflight (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / vps-smoke (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:frustration-matrix,kei-frustration-loop,kei-skill-importer,kei-projects-index,kei-projects-watcher,kei-gdrive-import,kei-leak-matrix,kei-skills,kei-gateway,kei-cron-scheduler,kei-export-trajectories,kei-backend-daytona,kei-d… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-compute-baremetal,kei-compute-vultr,kei-compute-linode,kei-compute-digitalocean,kei-svc-systemd,kei-llm-bridge-mlx name:hosted-sleep-compute]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-diff,kei-scheduler,kei-watch,kei-prune,kei-discover,kei-brain-view,kei-hibernate,kei-ledger-sign,kei-fork name:wave13-15]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-git-gitea,kei-git-forgejo,kei-git-gitlab,kei-git-bitbucket,kei-memory-sled,kei-memory-redis,kei-memory-postgres,kei-memory-sqlite,kei-auth-google,kei-auth-apple,kei-auth-magiclink,kei-auth-webauthn,kei-notify-slack,kei-n… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-ledger,kei-migrate,kei-changelog,kei-memory,kei-store,kei-conflict-scan,kei-refactor-engine,kei-graph-check,kei-shared,kei-dna-index,kei-pet name:core]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-machine-probe,kei-llm-ollama,kei-llm-llamacpp,kei-llm-mlx,kei-llm-router,kei-model name:llm-stack]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-router,kei-sage,kei-task,kei-chat-store,kei-crossdomain,kei-search-core,kei-content-store,kei-social-store,kei-curator,kei-auth,kei-artifact name:mcp-lbm]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:keisei,kei-forge,kei-runtime,kei-runtime-core,kei-atom-discovery,kei-agent-runtime,kei-capability,kei-provision,kei-entity-store,kei-pipe,kei-cache,kei-spawn,kei-replay name:atom-substrate]) (push) Blocked by required conditions
feat(phase-C): cross-CLI hook enforcement via kei_bash/kei_edit/kei_write MCP tools
Closes the "hooks only fire on Claude" gap. Phase C extends KeiSeiKit safety
enforcement (no-github-push, safety-guard, destructive-guard, citation-verify,
numeric-claims-guard) to any MCP-capable LLM CLI through a 3-tier honesty model.

## 3-tier model

TIER 1 (full native): claude (existing), grok (port hooks to grok settings.json)
TIER 2 (MCP-wrapped): copilot (--excluded-tools=shell + force kei_bash via MCP)
TIER 3 (advisory):    agy + kimi (cannot disable native shell; prompt-level only)

## Design (Constructor Pattern)

1. hooks/_lib/policy-chain.toml — SSoT: which hooks gate which tool (bash/edit/write)
2. _primitives/_rust/kei-mcp/src/handlers/safe_tools.rs — new module, 3 built-in
   MCP tools that synthesize Claude PreToolUse JSON, run hook chain, abort on
   exit-2, exec on all-pass. Same input contract → hooks reused as-is, no rewrite.
3. tools.rs short-circuit: kei_bash/kei_edit/kei_write dispatched before atom layer
4. 6 wire scripts: orchestrator + one per CLI (Constructor Pattern, no mixin)
5. bin/kei mcp-wire arm
6. docs/encyclopedia/cross-cli-policy.md — honest 3-tier matrix + verification

## Double-enforcement guard

If kei-mcp invoked from a process with $CLAUDECODE=1 or $GROKCODE=1, the chain
SKIPS — native hooks already fired. Wire scripts set these env vars in the
MCP server registration for claude/grok respectively. On copilot/agy/kimi the
env is unset → chain runs.

## Smoke (verified live)

Block: kei_bash{command: forbidden-push-pattern}
  → JSON-RPC error -32603 with full "BLOCK — RULE 0.1 NO GITHUB PUSH" stderr ✓
Pass:  kei_bash{command: "echo HELLO-FROM-KEI-BASH"}
  → result.content[0].text = "HELLO-FROM-KEI-BASH" ✓
tools/list: 4 built-ins present (spawn_agent + kei_bash + kei_edit + kei_write) ✓

## Tests

kei-mcp: 3/3 (tools_list assertions updated for atoms+4 built-ins).
Build clean with toml = "0.8" dep added.

## Out of scope (deferred)

- Codex CLI wiring (not installed locally)
- ACP middleware proxy (transport, not middleware — ruled out at research)
- Container/firejail sandboxing for agy/kimi (heavy; documented limit instead)
- Native Rust PatternGate migration (optimization, separate phase)
2026-05-26 18:03:33 +08:00

77 lines
2.7 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# kei-mcp-wire-grok — TIER 1: port KeiSeiKit hooks to Grok's PreToolUse pipeline.
#
# Grok CLI supports Claude-Code-compatible PreToolUse hooks via
# ~/.grok/settings.json. Same JSON input contract → our existing
# ~/.claude/hooks/*.sh scripts run unchanged.
#
# We register THREE hook entries (one per Bash-gating safety hook) plus
# the kei-mcp MCP server so Grok can also call spawn_agent.
#
# Idempotent: jq-merge into existing settings.json; foreign entries survive.
set -eu
CFG="$HOME/.grok/settings.json"
HOOKS_DIR="$HOME/.claude/hooks"
KEI_MCP_BIN="$HOME/.claude/_primitives/_rust/target/release/kei-mcp"
[ -f "$KEI_MCP_BIN" ] || KEI_MCP_BIN="$(command -v kei-mcp 2>/dev/null || true)"
mkdir -p "$(dirname "$CFG")"
[ -f "$CFG" ] || echo '{}' > "$CFG"
# Build the hook block — three Bash hooks + two Edit/Write hooks (same as
# Claude's policy-chain.toml).
desired=$(cat <<JSON
{
"hooks": {
"PreToolUse": [
{"matcher": "Bash", "hooks": [{"type": "command", "command": "$HOOKS_DIR/no-github-push.sh"}]},
{"matcher": "Bash", "hooks": [{"type": "command", "command": "$HOOKS_DIR/safety-guard.sh"}]},
{"matcher": "Bash", "hooks": [{"type": "command", "command": "$HOOKS_DIR/destructive-guard.sh"}]},
{"matcher": "Edit", "hooks": [{"type": "command", "command": "$HOOKS_DIR/citation-verify.sh"}]},
{"matcher": "Edit", "hooks": [{"type": "command", "command": "$HOOKS_DIR/numeric-claims-guard.sh"}]},
{"matcher": "Write", "hooks": [{"type": "command", "command": "$HOOKS_DIR/citation-verify.sh"}]},
{"matcher": "Write", "hooks": [{"type": "command", "command": "$HOOKS_DIR/numeric-claims-guard.sh"}]}
]
}
}
JSON
)
mcp_block=""
if [ -n "$KEI_MCP_BIN" ] && [ -x "$KEI_MCP_BIN" ]; then
mcp_block=$(cat <<JSON
{
"mcpServers": {
"kei-mcp": {
"command": "$KEI_MCP_BIN",
"env": { "GROKCODE": "1" }
}
}
}
JSON
)
fi
if [ "${KEI_WIRE_DRY_RUN:-0}" = "1" ] || [ "${KEI_WIRE_CHECK:-0}" = "1" ]; then
echo " grok: would merge into $CFG:"
printf '%s\n' "$desired"
[ -n "$mcp_block" ] && printf '%s\n' "$mcp_block"
exit 0
fi
# Merge: existing | desired (desired wins on key conflict; arrays are
# replaced, not appended — Grok PreToolUse semantics).
tmp=$(mktemp)
if [ -n "$mcp_block" ]; then
jq -s '.[0] * .[1] * .[2]' "$CFG" <(printf '%s\n' "$desired") <(printf '%s\n' "$mcp_block") > "$tmp"
else
jq -s '.[0] * .[1]' "$CFG" <(printf '%s\n' "$desired") > "$tmp"
fi
mv "$tmp" "$CFG"
echo " grok: wired PreToolUse hooks → $CFG"
echo " 5 hook entries (Bash×3 + Edit×2 + Write×2)"
[ -n "$mcp_block" ] && echo " kei-mcp MCP server registered (with GROKCODE=1 guard)"
echo " Same enforcement as Claude Code."