The gap
Requirement 4 of host-setup/agent-safety/README.md denies explicit-bypass flags unconditionally, naming --admin on a merge and --no-verify on a commit or push. --no-verify is the flag that skips a committed git hook, so the requirement reads as covering that class.
It does not. Git also lets a single invocation relocate the hooks path through an inline -c configuration override, which skips every hook without using any flag the guard recognizes. Measured against claude/gh-write-guard.py: such a push returns no deny, while the same push with --no-verify returns a deny. The guard's source contains no reference to the hooks-path configuration key at all.
Why it matters now
PR #1125 adds .husky/pre-push, the first committed hook in this repo that gates behavior rather than formatting. Its design decision recorded at the time was that no new guard requirement was needed, because the existing --no-verify denial already covered the only bypass of a committed hook. That premise is what this issue reports as false. PR #1125's own prose was corrected to describe the hook as a backstop rather than a seal, so nothing in the repo currently claims otherwise, and the hook remains deliberately bypassable for a human.
The question is whether the guard should close the agent-facing half. A committed hook is meant to be bypassable on purpose, and requirement 4 exists because an agent choosing the bypass unprompted is the failure it guards. An override that reaches the same result without the recognized flag sits on the wrong side of that line.
What a fix would need
- A spec change to requirement 4 covering an inline configuration override that relocates or disables the hooks path, alongside the flags it already names.
- The implementation in
claude/gh-write-guard.py, following that requirement's existing precision-over-recall stance and its handling of global options placed before the subcommand.
- Selftest cases for the deny, and for the shapes that must stay allowed, since an inline
-c carrying an unrelated key is ordinary and common.
Deliberately not written here: the exact invocation. The requirement text and the selftest are where it belongs, not in an issue body that is the first thing a search reaches.
Decision
The maintainer chose to file this rather than grow #1125, which has already run ten local review rounds.
The gap
Requirement 4 of
host-setup/agent-safety/README.mddenies explicit-bypass flags unconditionally, naming--adminon a merge and--no-verifyon a commit or push.--no-verifyis the flag that skips a committed git hook, so the requirement reads as covering that class.It does not. Git also lets a single invocation relocate the hooks path through an inline
-cconfiguration override, which skips every hook without using any flag the guard recognizes. Measured againstclaude/gh-write-guard.py: such a push returns no deny, while the same push with--no-verifyreturns a deny. The guard's source contains no reference to the hooks-path configuration key at all.Why it matters now
PR #1125 adds
.husky/pre-push, the first committed hook in this repo that gates behavior rather than formatting. Its design decision recorded at the time was that no new guard requirement was needed, because the existing--no-verifydenial already covered the only bypass of a committed hook. That premise is what this issue reports as false. PR #1125's own prose was corrected to describe the hook as a backstop rather than a seal, so nothing in the repo currently claims otherwise, and the hook remains deliberately bypassable for a human.The question is whether the guard should close the agent-facing half. A committed hook is meant to be bypassable on purpose, and requirement 4 exists because an agent choosing the bypass unprompted is the failure it guards. An override that reaches the same result without the recognized flag sits on the wrong side of that line.
What a fix would need
claude/gh-write-guard.py, following that requirement's existing precision-over-recall stance and its handling of global options placed before the subcommand.-ccarrying an unrelated key is ordinary and common.Deliberately not written here: the exact invocation. The requirement text and the selftest are where it belongs, not in an issue body that is the first thing a search reaches.
Decision
The maintainer chose to file this rather than grow #1125, which has already run ten local review rounds.