You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[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
Hit directly while running a pure-curl command from the devx PM seat. .claude/** is a
governed surface, so this is filed as a finding rather than fixed. Filed unassigned.
What happened
The command was four curl calls plus one bash comment:
# sitting 1 landed; card stays open and ready for sitting 2 -> pm:dispatched must go, pm:queue returns
The hook blocked it:
⛔ Blocked: this Bash command WRITES into the shared PRIMARY checkout, not a worktree.
command: card stays open and ready for sitting 2 -> pm:dispatched must go, pm:queue returns
target: pm:dispatched
repo: /home/user/objectstack
There is no write in that command. The hook read the comment.
Mechanism, from the hook's own source
split_segments() (:128-139) splits on ; | & ( ) { } \n, honouring quotes. My comment
contains a ;, so it is cut in two and the trailing clause becomes its own "segment".
Nothing strips # comments. The hook strips heredoc bodies (strip_heredocs, :97)
and it makes separators inert inside quotes — but a # comment is neither, so the tail of the
comment is analysed as a command.
That tail contains ->. The tokenizer marks > as an unquoted redirection operator
(:171, :244-245) and takes the next token, pm:dispatched, as the redirect target.
target_is_shared_checkout() (:189) resolves that relative target against the cwd — the
shared primary checkout — and the guard fires.
Why this is a defect rather than acceptable over-blocking
The hook's own header declares "PRECISION OVER RECALL" (:32) and deliberately declines
several genuinely-ambiguous shapes: node -e, awk >, targets containing $VAR / globs,
relative targets with no cwd. The intent is explicit at :125:
"A separator inside '…' or "…" does NOT split, so writing about the ban is never
caught."
That is exactly the property a comment should have, and it is implemented for quotes and for
heredocs but not for #. A comment is the purest case of writing about a write rather than
performing one.
The concrete harm is the remedy the block points at. The message's only escape is OS_ALLOW_MAIN_EDITS=1, which disables the guard for the whole command. A false positive on
a harmless comment trains the operator to reach for the total-override flag on commands that
genuinely do not need it — and the next command it is reached for might. A guard whose false
positives are cheapest to resolve by turning it off is being pushed in the wrong direction.
Same family as #5790, which is why this hook exists at all: the Edit-only guard let the
identical write slip through as a shell command. This is that lesson's mirror image — the shell
parser now sees writes the Edit hook could not, including ones that are not there.
Direction (not a decision)
Strip # comments before split_segments(), with the same care strip_heredocs() already
takes: a # only begins a comment at the start of a word, and never inside '…', "…", or a
heredoc body — so curl 'https://…/#frag', sed 's/#//' and grep '#' must be untouched. The
existing quote-aware scanner already has the state needed to decide that.
⛔ Not proposing any change to what the hook blocks once it has a real command. The recall side
is right; this is only about what counts as a command.
Repro
Any Bash command containing a comment with both a ; and a > — e.g. # step one; then a -> b — from a cwd inside the shared checkout.
Refs
.claude/hooks/guard-main-checkout-bash.sh:32, :97, :125, :128-139, :171, :189, :244-245 · #5790 (why the Bash-side guard exists) · governed surface, Prime Directive #14
Triage (dedup): duplicate of #10570 (filed 03:44Z today, domain:skills · finding) — same defect, same file: guard-main-checkout-bash.sh does not strip # comments, so an unquoted > inside a comment is analysed as a redirect and false-blocks the command. Closing this one as the later filing; the mechanism walkthrough, the "precision over recall" argument, the total-override-flag harm analysis and the proposed fix direction in this card's body are the richer record — whoever grades/implements #10570 should read this card alongside it (cross-linked there). No information lost: closed cards remain readable.
Activity
os-zhuang commentedon Aug 21, 2026
Triage (dedup): duplicate of #10570 (filed 03:44Z today,
domain:skills·finding) — same defect, same file:guard-main-checkout-bash.shdoes not strip#comments, so an unquoted>inside a comment is analysed as a redirect and false-blocks the command. Closing this one as the later filing; the mechanism walkthrough, the "precision over recall" argument, the total-override-flag harm analysis and the proposed fix direction in this card's body are the richer record — whoever grades/implements #10570 should read this card alongside it (cross-linked there). No information lost: closed cards remain readable.Generated by Claude Code
>inside a shell COMMENT as a redirect and false-blocks the command #10570