Found while wiring #11514 (PR #11799), which runs every .claude/hooks/*.selftest.sh in CI. Filing rather than fixing: #11514 wires execution only and authoring a matrix is a .claude/** change.
Measured
.claude/hooks/ holds three hooks and two self-tests:
.claude/hooks/guard-main-checkout-bash.selftest.sh 121 cases
.claude/hooks/guard-main-checkout-bash.sh
.claude/hooks/guard-main-checkout.sh <-- no matrix
.claude/hooks/guard-shared-stash.selftest.sh 32 cases
.claude/hooks/guard-shared-stash.sh
guard-main-checkout.sh is the Edit/Write/NotebookEdit half of the worktree-first enforcement — the half named in CLAUDE.md and AGENTS.md as the primary guard. It has no self-test at all. Its Bash sibling, which exists only because #5790 found that the Edit/Write hook could be bypassed through sed -i / tee / redirection, has 121.
Why it matters now specifically
Once #11799 lands, CI runs every matrix in that directory, so a regression in guard-shared-stash.sh or guard-main-checkout-bash.sh goes red. guard-main-checkout.sh is the one hook for which the answer stays "nothing checks it" — and after the wiring, .claude/hooks/ reads as a covered directory, which is the more expensive state than being visibly uncovered. The wiring is discovery-based, so a matrix added for it is picked up with no workflow edit.
The failure direction is the quiet one: this hook fails open by design for anything it cannot parse, so a regression that makes it fail open more often produces no error anywhere — edits into the shared primary checkout simply start being allowed, and the symptom is another agent's tree being clobbered, attributed to something else.
Shape of the work
Port the case matrix the way guard-main-checkout-bash.selftest.sh was ported from objectui: hermetic fixture (its own git init + linked worktree + a non-repo dir under $TMPDIR), feed the hook the PreToolUse payload shape for Edit/Write/NotebookEdit, assert block/allow per case, exit 0 = all hold. The block/allow verdicts to pin are the ones its header already states, plus the OS_ALLOW_MAIN_EDITS=1 exception and the sibling-repo path cases (objectui, cloud), which are the ones prose alone has been carrying.
Prior art in the same directory
Found while wiring #11514 (PR #11799), which runs every
.claude/hooks/*.selftest.shin CI. Filing rather than fixing: #11514 wires execution only and authoring a matrix is a.claude/**change.Measured
.claude/hooks/holds three hooks and two self-tests:guard-main-checkout.shis theEdit/Write/NotebookEdithalf of the worktree-first enforcement — the half named in CLAUDE.md and AGENTS.md as the primary guard. It has no self-test at all. Its Bash sibling, which exists only because #5790 found that the Edit/Write hook could be bypassed throughsed -i/tee/ redirection, has 121.Why it matters now specifically
Once #11799 lands, CI runs every matrix in that directory, so a regression in
guard-shared-stash.shorguard-main-checkout-bash.shgoes red.guard-main-checkout.shis the one hook for which the answer stays "nothing checks it" — and after the wiring,.claude/hooks/reads as a covered directory, which is the more expensive state than being visibly uncovered. The wiring is discovery-based, so a matrix added for it is picked up with no workflow edit.The failure direction is the quiet one: this hook fails open by design for anything it cannot parse, so a regression that makes it fail open more often produces no error anywhere — edits into the shared primary checkout simply start being allowed, and the symptom is another agent's tree being clobbered, attributed to something else.
Shape of the work
Port the case matrix the way
guard-main-checkout-bash.selftest.shwas ported from objectui: hermetic fixture (its owngit init+ linked worktree + a non-repo dir under$TMPDIR), feed the hook thePreToolUsepayload shape forEdit/Write/NotebookEdit, assert block/allow per case, exit 0 = all hold. The block/allow verdicts to pin are the ones its header already states, plus theOS_ALLOW_MAIN_EDITS=1exception and the sibling-repo path cases (objectui,cloud), which are the ones prose alone has been carrying.Prior art in the same directory
guard-main-checkout-bash.selftest.sh— the matrix to mirrorsed -iinto the shared checkout is allowed through #11131 / guard-main-checkout-bash.sh reads a>inside a shell COMMENT as a redirect and false-blocks the command #10570 / [finding] guard-main-checkout-bash.sh does not strip#comments, so a comment containing;and>is analysed as a write and blocks the command #10720 — three real defects the Bash guard's matrix and reviewers caught; the Edit/Write hook has had no comparable pressureguard-shared-stash.sh, i.e. hooks in this directory do carry live defects