test(self): gate hooks parity between settings.json and hooks.json (#140) - #196
Conversation
…#140) Three hooks are hand-duplicated between the repo-local .claude/settings.json (self-hosted, $CLAUDE_PROJECT_DIR paths) and the shipped .claude/hooks/hooks.json (consumers, ${CLAUDE_PLUGIN_ROOT} paths), with nothing to catch drift — which is how a hook ended up reCode-only for weeks. Add do_hooks_parity to .claude/self/checks.sh, wired into do_build (and therefore gate.sh build/test): it normalizes each file's .hooks into (event, matcher, command) triples, stripping the environment-specific path prefix so both forms collapse to the same value, diffs both directions, and fails on any divergence not covered by an explicit ALLOWLIST. The allowlist currently covers log-worker-tool.sh's PostToolUse hook, which is deliberately self-only (it mirrors worker tool calls into reCode's own cockpit worker-session panel; consumers have no such panel to feed). Add .claude/scripts/hooks-parity.test.sh (auto-discovered by do_test): asserts the check passes born-green on the real repo files, and fails on synthetic divergence in both directions, via the new HOOKS_SETTINGS_FILE / HOOKS_PLUGIN_FILE env-var override seam. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
test(self): gate hooks parity between settings.json and hooks.json (#140) (not yet reviewed) |
|
Is it necessary to maintain this copy of hooks? Can you inform me of a better way of keeping the hooks the same (same location) instead? |
|
Re: is the duplicated hooks copy necessary? (answered by Claude on the owner's behalf) Yes, two files are structurally required today — they feed two different Claude Code loaders, and neither can read the other's file:
There is no include/reference mechanism between them, and installing reCode as a plugin into itself would make self-sessions run the cached snapshot instead of the working tree — the exact stale-scripts drift this repo has already been bitten by downstream. But the hand-maintenance isn't necessary: the right follow-up is to make Filed as a follow-up issue; recommendation is to merge this PR as-is. |
Closes #140.
Problem
Three hooks are hand-duplicated between reCode's repo-local
.claude/settings.json(self-hosted sessions,$CLAUDE_PROJECT_DIRpaths) and the shipped.claude/hooks/hooks.json(consumers,${CLAUDE_PLUGIN_ROOT}paths). Nothing checked they stayed in sync — which is how a hook (the tool-mirror hook, #137) ended up reCode-only for weeks with an empty cockpit workers panel in every consumer.Change
do_hooks_parityto.claude/self/checks.sh, wired into thebuildphase (and thereforetest). It parses.hooksfrom both files, normalizes each hook into an(event, matcher, normalized-command)triple — stripping the two environment-specific path prefixes (quoted"$CLAUDE_PROJECT_DIR/.claude/and unquoted${CLAUDE_PLUGIN_ROOT}/) plus quotes so equal hooks compare equal — and diffs both directions. Settings-only triples must appear in an explicit documentedALLOWLIST; consumer-only triples always fail.PostToolUse/Bash|Edit|Write/log-worker-tool.sh, commented as deliberately self-only (worker tool-mirror logging feeds a cockpit worker-session panel that only exists in this self-hosted repo). The gate is born green..claude/scripts/hooks-parity.test.sh(auto-discovered bydo_test): hermetic/offline, uses temp copies viaHOOKS_SETTINGS_FILE/HOOKS_PLUGIN_FILEenv overrides. Proves the born-green path, both fail-on-divergence directions, and a synthetic matching pair.Gates
GATES_FILE=.claude/self/gates.jsonbuild / lint / test all green, includinghooks-parity.test.sh: PASS (4 checks).Review
correctness (opus) + tests (sonnet) lenses — both APPROVE, consensus=all. Only non-blocking nits (narrow normalization regexes; allowlist covered indirectly by the born-green assertion).
🤖 Generated with Claude Code