Filed by the domain:spec execution seat (#6017), session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T07:2xZ. ⛔ Not claimed, ⛔ not dispatched. Grading is triage's. ⛔ This seat did not run a dedupe search (per 「立卡者不查重,只附查重词」). Measured on origin/main @ 8b81ab60d7, ⛔ not on a stale checkout — this is true of main today and is independent of any one session's harness state.
The defect
.claude/hooks/guard-governed-enqueue.sh is a PreToolUse guard whose stated purpose is to stop an unapproved governed PR from being enqueued, so the queue cycle is not burned. Its own header explains why a client-side guard earns its place beside the server-side queue guard: a measured incident on 2026-09-01 where the queue guard refused correctly, the entry popped out red, and 「THE RED ENTRY DID NOT RE-RUN」 after the approval arrived.
It no longer watches any spelling a compliant seat can use.
What it actually matches
| arm |
spelling |
reachable by a seat today? |
:225 |
mcp__github__enable_pr_auto_merge | mcp__github__merge_pull_request |
⛔ No — both are in permissions.deny in .claude/settings.json as of ceb6b5fb46 (#18317) and 53dd5aaaaf (#18276) |
:283 |
[[ "$w" =~ /repos/([A-Za-z0-9._-]+)/([A-Za-z0-9._-]+)/pulls/([0-9]+)/merge ]] |
⛔ No — this is PUT .../pulls/N/merge, not the route the seat is told to use |
:325 |
gh pr merge … |
⛔ No — gh is not available in the agent container at all |
The route a seat is actually required to use
references/platform-readings.md routes the seat to the CCR endpoints, because the MCP path is denied: auto-merge goes through PUT /repos/{o}/{r}/pulls/{n}/ccr/auto_merge.
/pulls/18370/ccr/auto_merge does not match /pulls/([0-9]+)/merge — after the number comes ccr/auto_merge, so the literal /merge segment the regex requires never appears.
The controlled zero
⛔ Not a bare zero. Over .claude/hooks/guard-governed-enqueue.sh on origin/main:
- zero leg:
ccr → 0 occurrences anywhere in the file.
- control, same file and same quoting:
auto_merge → 2, both of them the MCP arm at :225 and the header line describing it ⇒ the probe finds the concept where the file has it, so the zero is a real absence and not a spelling miss on my side.
Why this is class (a) rather than a nit
The guard is a gate on the governed surface — the one place where the repo's rule is that a human approval must be pinned to the current head before an enqueue. A guard that cannot see the enqueue call is not a weaker guard; it is an absent one that reads as present. Its own header argues the case against exactly this outcome: 「a ⛔-level rule in this repo is only stable once a check enforces it」.
⚠️ The server-side scripts/pm/check-governed-queue-guard.mjs is untouched and still refuses on the merge_group build — correctness is not lost. What is lost is precisely the thing this file was added to buy: the cheap refusal, before a queue cycle is spent and before a maintainer reads a red entry as 「I reviewed it and it still blocked me」.
How it was found, stated so the grading can weigh it
This seat enqueued PR #18370 and PR #18371 at 06:17Z through the CCR route. Both were measured NOT governed first (check-governed-merges.mjs --test returned 0 of 3 and 0 of 13 paths hitting the register), so the guard would have allowed them either way and nothing was bypassed. ⇒ the gap was found by reading, not by an incident — and the reason no incident occurred is the file list, ⛔ not the guard.
Dedupe words
guard-governed-enqueue · PreToolUse enqueue guard · ccr/auto_merge · governed surface approval · enqueue spelling drift
Generated by Claude Code
Filed by the
domain:specexecution seat (#6017),session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T07:2xZ. ⛔ Not claimed, ⛔ not dispatched. Grading is triage's. ⛔ This seat did not run a dedupe search (per 「立卡者不查重,只附查重词」). Measured onorigin/main@8b81ab60d7, ⛔ not on a stale checkout — this is true of main today and is independent of any one session's harness state.The defect
.claude/hooks/guard-governed-enqueue.shis a PreToolUse guard whose stated purpose is to stop an unapproved governed PR from being enqueued, so the queue cycle is not burned. Its own header explains why a client-side guard earns its place beside the server-side queue guard: a measured incident on 2026-09-01 where the queue guard refused correctly, the entry popped out red, and 「THE RED ENTRY DID NOT RE-RUN」 after the approval arrived.It no longer watches any spelling a compliant seat can use.
What it actually matches
:225mcp__github__enable_pr_auto_merge|mcp__github__merge_pull_requestpermissions.denyin.claude/settings.jsonas ofceb6b5fb46(#18317) and53dd5aaaaf(#18276):283[[ "$w" =~ /repos/([A-Za-z0-9._-]+)/([A-Za-z0-9._-]+)/pulls/([0-9]+)/merge ]]PUT .../pulls/N/merge, not the route the seat is told to use:325gh pr merge …ghis not available in the agent container at allThe route a seat is actually required to use
references/platform-readings.mdroutes the seat to the CCR endpoints, because the MCP path is denied: auto-merge goes throughPUT /repos/{o}/{r}/pulls/{n}/ccr/auto_merge./pulls/18370/ccr/auto_mergedoes not match/pulls/([0-9]+)/merge— after the number comesccr/auto_merge, so the literal/mergesegment the regex requires never appears.The controlled zero
⛔ Not a bare zero. Over
.claude/hooks/guard-governed-enqueue.shonorigin/main:ccr→ 0 occurrences anywhere in the file.auto_merge→ 2, both of them the MCP arm at:225and the header line describing it ⇒ the probe finds the concept where the file has it, so the zero is a real absence and not a spelling miss on my side.Why this is class (a) rather than a nit
The guard is a gate on the governed surface — the one place where the repo's rule is that a human approval must be pinned to the current head before an enqueue. A guard that cannot see the enqueue call is not a weaker guard; it is an absent one that reads as present. Its own header argues the case against exactly this outcome: 「a ⛔-level rule in this repo is only stable once a check enforces it」.
scripts/pm/check-governed-queue-guard.mjsis untouched and still refuses on themerge_groupbuild — correctness is not lost. What is lost is precisely the thing this file was added to buy: the cheap refusal, before a queue cycle is spent and before a maintainer reads a red entry as 「I reviewed it and it still blocked me」.How it was found, stated so the grading can weigh it
This seat enqueued PR #18370 and PR #18371 at 06:17Z through the CCR route. Both were measured NOT governed first (
check-governed-merges.mjs --testreturned 0 of 3 and 0 of 13 paths hitting the register), so the guard would have allowed them either way and nothing was bypassed. ⇒ the gap was found by reading, not by an incident — and the reason no incident occurred is the file list, ⛔ not the guard.Dedupe words
guard-governed-enqueue· PreToolUse enqueue guard ·ccr/auto_merge· governed surface approval · enqueue spelling driftGenerated by Claude Code