Repository navigation
Install adopts untagged copies of its own Claude Code hooks - #3172
Merged
Merged
Conversation
owns_entry recognized an entry only by its writer tag, so every entry an install wrote before the tag existed looked foreign forever: install appended its tagged entry beside it and each hook ran twice. An untagged entry whose every hook is one this package installs is now owned too, so the next install leaves one entry per hook. Foreign hooks stay. The hook dict has one owner, hook(), used by entry() and by the ownership test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
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.
Every agent-comms hook in a long-lived
~/.claude/settings.jsonwas registered twice: once untagged, written by an install from before thewritertag, and once tagged. Sorereadran twice per tool call,bounded-waitsandqueue-bypasstwice per Bash call, andsessionandskilltwice per SessionStart, at about 2.8 s of imports each.Cause
ClaudeHookProgram.owns_entry(src/agent_comms_hooks/__init__.py:129) recognized an entry only byentry["writer"] == "agent-comms".ClaudeCodeHarness.configure(src/agent_comms/harness_install.py:142-150) removes the owned entries and appends one tagged entry per program. An untagged copy of our own hook was never owned, so it survived every install, with the tagged entry appended beside it.Fix
owns_entryalso owns an untagged entry whose every hook is one this package installs. The next install deletes it and writes the tagged entry, so exactly one entry per hook survives. Entries running anything else stay, e.g.python3 -I ~/.claude/hooks/bounded-waits.py.{"type": "command", "command": ...}has one owner,hook().entry()builds from it and the ownership test compares against it.hooks()is cached, becausecommand()scans entry points.No hand edit to anyone's settings file: the next
agent-comms installrepairs the live one.Evidence
tests/test_claude_hook_install.py: a settings file holds an untagged copy of every program's entry, plus a foreign Bash hook and an unrelated setting. Install runs twice. The result is one entry per program per event, the foreign hook once, and the setting kept. It fails on the oldowns_entry(fix stashed) and passes with it.tests/test_commander_skill_hook.py: 25 pass.__init__.pyis on line 89, which is already on main.Hold: lands after install #15, with #3166 and #3170. It changes what install writes into
settings.json.🤖 Generated with Claude Code