feat: cross-platform hook enforcement (Codex/Cursor/Gemini/VS Code) + 0.16.0 audit fixes - #54
Merged
Conversation
3-agent parallel audit of published 0.16.0 found 26 issues; fixed the material ones. HIGH: - H1 run_loop verify_cmd had no timeout → hung the MCP thread forever; now bounded by remaining deadline budget or 120s (SIGKILL), timeout → failed grade - H2 team_post sent unscrubbed content to the hub + stored it raw → secret exfiltration; now scrubSecrets at the engine layer (teams.post) + tool layer - H3 CCR maintain() had zero prod callers → unbounded disk growth; wired a conservative janitor into server startup (7d/2k hot, 10k cold) - H4 wiki log() rewrote the whole file on EVERY prompt (O(n^2) hot path); now O(1) append + size-capped rotation MED: - M1 wiki_ingest bypassed the adherence gate + wrote raw → gated + scrubbed - M2 strip-path skeleton could lose its recall marker (proxy: model can't retrieve) → marker now guaranteed present - M3 crash-stale loop-state poisoned the next loop (instant deadline/max-iters); goal wording change reset the caps → stale-age guard + normalized goal key - M4 run_loop save wiped the Stop-hook stopNudged flag → escape hatch broken; flag now carried across cycles - M5 substring dedup silently dropped distinct learnings → exact-equality at any length, fuzzy prefix only above an anchor length, empty never an anchor - M6 team board lost-update race → bounded mtime CAS with id-merge - M7 CCR get TOCTOU on tier transitions → ENOENT falls through to cold - M8 setup clobbered user-edited command/rules files → .bak before overwrite - M9 CLI outer loop had no wall-clock bound → --for <dur> + parseDuration LOW: L1 CCR put self-heals a corrupt hot file · L3 proxy cancels upstream on client disconnect · L7 README lists /goal · L8 onboard git execSync timeout. +10 tests (tests/audit-fixes.test.ts, closed-loop M3/M4). rm -rf dist && npm run verify EXIT=0 — 501 tests, consistency PASS, bench PASS lossless. No version bump (gated). Deferred: meter/calibration RMW races (accounting-only, self-correcting), L2/L4/L5/L6 (marginal).
…or/Gemini/VS Code + Claude
- src/hooks/adapters.ts: detectHookPlatform (payload fingerprints + env, vscode
checked before gemini to resolve the timestamp+PascalCase collision),
normalizeEventName/normalizeInput (cursor beforeReadFile->Read,
beforeShellExecution->Bash; vscode create_file/read_file/run_in_terminal ->
Write/Read/Bash + camelCase keys), adaptOutput (deny/stop/context per
platform dialect; vscode stop merges {continue:false,stopReason}; codex/gemini
can't replace tool output -> context pointer)
- src/hooks/index.ts: stdin once -> detect -> normalize -> decide* (unchanged,
claude-internal) -> adaptOutput; claude/codex byte-identical to before
- src/hooks/pretooluse.ts: brain->body constraint denial — CONSTRAINTS: line of
the composed workflow denies violating Bash/Write (publish/--force/--no-verify),
fail-open, back-compat io
- src/platforms.ts: CODEX_HOOKS/.codex/hooks.json, CURSOR_HOOKS/.cursor/hooks.json
(new json-merge-cursor-hooks: dedupe by command, keep user version+entries),
GEMINI_HOOKS/.gemini/settings.json, parameterized json-merge-hooks,
claudeLoopArtifacts -> .claude/commands/loop.md (/goal cross-ref), GOAL_FRAME
- src/setup.ts: gemini platform detection + artifact wiring
- src/mcp/tools.ts: LoopState.failures[] self-heal — last-3 failure history
injected into the NEXT cycle's directive (prior cycles only)
- tests: hook-adapters fixtures for all 5 platforms + emitter merge + constraint
denial + failures[] prune/surface (539 tests, verify EXIT=0)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Build 1 — hook adapters + ambient orchestration (docs/LOOP-ENGINEERING.md Tier-1.1) on top of the 0.16.0 production audit fixes (4 HIGH / 7 MED / 3 LOW).
Hook adapters (6764f71)
src/hooks/adapters.ts: oneknitbrain-hookbinary auto-detects the calling platform from payload fingerprints (vscode before gemini — timestamp+PascalCase collision) and speaks each host's dialect: deny / loop-block / context-inject for Claude Code, Codex CLI, Cursor, Gemini CLI, VS Code Copilot..codex/hooks.json,.cursor/hooks.json(dedupe-by-command merge, user entries preserved),.gemini/settings.json; VS Code rides.claude/settings.jsonnatively./loopcommand unified with/goal(one engine; loop = goal + time/iteration budget).LoopState.failures[]last-3 history injected into the next cycle's directive.Audit fixes (c327595)
H1 verify timeout · H2 team_post secret scrub at engine layer · H3 CCR maintain wired · H4 wiki log rotate · M1-M9 (ingest gating, strip-path marker, stale-loop guard, stopNudged carry, memory dedup, board CAS, cold fallback, .bak backups, loop --for) · L1/L3/L7/L8.
Verification
rm -rf dist && npm run verifyEXIT=0 (typecheck, lint, build, 539 tests, consistency, bench). Smoke: same deny decision through built binary → correct cursor + claude dialects, exit 0 both.Not in this PR
No version bump, no publish. Live adapters need
npm install -g .to dogfood.