From 8402fa3dde876a69b8c1542ac5de5eb5ad2bf3bf Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 07:56:13 +0000 Subject: [PATCH 1/2] fix(hooks): guard-governed-enqueue reads one slug, and it strips the `.git` a clone URL carries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `slug_of` and the inlined copy in the bare `gh pr merge ` target derivation ran the same sed, and the path character class owns `.` and is greedy, so the optional `\(\.git\)` group matched EMPTY: an origin of `https://github.com/objectstack-ai/cloud.git` read back as the slug `objectstack-ai/cloud.git`, which equals no `owner/repo` this guard is ever asked about. A sibling cloned with the URL `git clone` hands out therefore resolved nothing and was never audited, and a bare `gh pr merge ` in such a clone derived a slug the API answers 404 for — this guard's fail-open branch. One reader now, called from both sites, and the suffix comes off after the match rather than out of the character class, which still has to own `.` (`objectstack.ai` is a legitimate repository name) and whose race with the group GNU and BSD sed are free to settle differently. The self-test pins both shapes: four unpinned spellings of the sibling's origin (https/ssh x with and without `.git`, plus a trailing slash) resolve and are audited, and a bare `gh pr merge ` run from a checkout whose origin carries the suffix derives `objectstack-ai/objectstack#13794`. 56 passed / 0 failed before, 62 / 0 after. Claude-Session: https://claude.ai/code/session_01Bz6hxDBqK62NP2W1LATvnt Co-authored-by: Claude --- .../hooks/guard-governed-enqueue.selftest.sh | 72 ++++++++++++++++++- .claude/hooks/guard-governed-enqueue.sh | 32 +++++++-- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/.claude/hooks/guard-governed-enqueue.selftest.sh b/.claude/hooks/guard-governed-enqueue.selftest.sh index ecab98961e..81b686f34b 100755 --- a/.claude/hooks/guard-governed-enqueue.selftest.sh +++ b/.claude/hooks/guard-governed-enqueue.selftest.sh @@ -30,6 +30,11 @@ set -uo pipefail here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" hook="$here/guard-governed-enqueue.sh" +# The hook `run`/`stderr_of` actually invoke. It is `$hook` for every case but +# one: the bare `gh pr merge ` case asks the hook about a DIFFERENT checkout's +# origin, and the hook derives its repo root from its own path, so that case runs +# a copy sitting in a checkout it built — and restores this on the next line. +hook_under_test="$hook" repo_root="$(cd "$here/../.." && pwd)" pass=0 fail=0 @@ -112,7 +117,7 @@ MERGE=mcp__github__merge_pull_request run() { # run [env assignments…] -> allow | block | exitN local payload="$1"; shift local rc - printf '%s' "$payload" | env "$@" "$hook" >/dev/null 2>&1 + printf '%s' "$payload" | env "$@" "$hook_under_test" >/dev/null 2>&1 rc=$? case "$rc" in 0) printf 'allow' ;; @@ -123,7 +128,7 @@ run() { # run [env assignments…] -> allow | block | exitN stderr_of() { # stderr_of [env…] local payload="$1"; shift - printf '%s' "$payload" | env "$@" "$hook" 2>&1 >/dev/null + printf '%s' "$payload" | env "$@" "$hook_under_test" 2>&1 >/dev/null } expect() { # expect