diff --git a/.claude/hooks/guard-governed-enqueue.selftest.sh b/.claude/hooks/guard-governed-enqueue.selftest.sh deleted file mode 100755 index 2d9f332ea51..00000000000 --- a/.claude/hooks/guard-governed-enqueue.selftest.sh +++ /dev/null @@ -1,633 +0,0 @@ -#!/usr/bin/env bash -# Self-test for guard-governed-enqueue.sh — run it after touching that hook: -# -# .claude/hooks/guard-governed-enqueue.selftest.sh -# -# Feeds the hook the same JSON payload shape Claude Code delivers on PreToolUse -# and asserts the block/allow verdict per case, plus the load-bearing sentences -# of the refusal. Modelled on guard-shared-stash.selftest.sh; the two matrices -# are kept in the same shape so neither drifts into its own idiom. -# -# NO NETWORK. The three GitHub reads come from `OS_GOVERNED_ENQUEUE_FIXTURE` -# (documented in the hook's header as test-only injection): a directory holding -# `pull.json` / `files.json` / `reviews.json`. What is NOT stubbed is the part -# that matters — both predicates run for real, so this matrix fails if the hook -# ever stops asking the register and the queue guard and starts deciding for -# itself. -# -# Needs `jq` (to build fixtures) and `node` (the two real predicates run). No -# pnpm install, no build: measured against a worktree with no `node_modules`. -# -# ⚠️ THE PURE-REGENERATION CASE IS AN AGREEMENT ASSERTION, NOT A FIXED VERDICT, -# and that is a repair rather than a preference: the first revision of this file -# hard-coded `expect allow` against the one exception row that was cheap to -# lift, and that row was retired upstream hours later — the case then went red -# over a register change the hook had nothing to do with. Copying a verdict out -# of the register makes this matrix a second register. It now ASKS the register -# and requires the hook to answer the same way; see that block for the detail. - -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 - -command -v jq >/dev/null 2>&1 || { echo "selftest needs jq to build payloads" >&2; exit 1; } -command -v node >/dev/null 2>&1 || { echo "selftest needs node: both predicates run for real" >&2; exit 1; } -[ -x "$hook" ] || { echo "hook is not executable: $hook" >&2; exit 1; } - -HEAD_SHA=b25f061c6a1d4e2f3c9b8a7d6e5f4a3b2c1d0e9f -OLD_SHA=0f9e8d7c6b5a4938271605f4e3d2c1b0a98877665 - -root="$(mktemp -d)" -trap 'rm -rf "$root"' EXIT INT TERM - -# fixture -> prints the directory -fixture() { - local dir="$root/$1" - mkdir -p "$dir" - jq -nc --arg s "$HEAD_SHA" '{head:{sha:$s}}' > "$dir/pull.json" - printf '%s' "$2" > "$dir/files.json" - printf '%s' "$3" > "$dir/reviews.json" - printf '%s' "$dir" -} - -files_of() { # files_of path... -> the /pulls/{n}/files body shape - local out="[]" p - for p in "$@"; do out="$(printf '%s' "$out" | jq -c --arg f "$p" '. + [{filename:$f}]')"; done - printf '%s' "$out" -} - -# A RENAME is the one entry shape `files_of` cannot build: every other status -# carries `filename` alone, a renamed one ALSO carries `previous_filename`. -# Measured on PR #17372 (`GET /pulls/17372/files`): `filename` is the NEW path, -# `previous_filename` the OLD one. `files_of` keeps its shape; this is the twin. -renamed_of() { # renamed_of -> the /files body for one RENAME - jq -nc --arg o "$1" --arg n "$2" '[{filename:$n,previous_filename:$o,status:"renamed"}]' -} - -approved_at() { # approved_at - jq -nc --arg l "$1" --arg c "$2" '[{state:"APPROVED",user:{login:$l},commit_id:$c}]' -} - -NO_REVIEWS='[]' -GOVERNED_FILES="$(files_of AGENTS.md packages/spec/src/index.ts)" -CLEAR_FILES="$(files_of packages/spec/src/index.ts README.md)" -# The incident's own file class, and four of them, the way it actually happened: -# `skills/*/references/_index.md` is a governed `skills/**` path whose generator -# (`gen:skill-refs`) owns it, so a byte-exact regeneration is lifted and needs no -# approval at all. Every path here must be one the generator DECLARES — a skill -# absent from its map is hand-authored content that stays governed, which is the -# ruling's own limit and not a bug to route around. -REGEN_PATHS="skills/objectstack-data/references/_index.md skills/objectstack-query/references/_index.md skills/objectstack-ui/references/_index.md skills/objectstack-api/references/_index.md" -# shellcheck disable=SC2086 -REGEN_FILES="$(files_of $REGEN_PATHS)" - -F_UNAPPROVED="$(fixture governed-unapproved "$GOVERNED_FILES" "$NO_REVIEWS")" -F_PINNED="$(fixture governed-pinned "$GOVERNED_FILES" "$(approved_at os-zhuang "$HEAD_SHA")")" -F_OLDER="$(fixture governed-approved-on-an-earlier-commit "$GOVERNED_FILES" "$(approved_at os-zhuang "$OLD_SHA")")" -F_OUTSIDER="$(fixture governed-outsider "$GOVERNED_FILES" "$(approved_at os-warren "$HEAD_SHA")")" -F_DISMISSED="$(fixture governed-dismissed "$GOVERNED_FILES" \ - "$(jq -nc --arg c "$HEAD_SHA" '[{state:"APPROVED",user:{login:"os-zhuang"},commit_id:$c},{state:"DISMISSED",user:{login:"os-zhuang"},commit_id:$c}]')")" -F_CLEAR="$(fixture not-governed "$CLEAR_FILES" "$NO_REVIEWS")" -F_REGEN="$(fixture pure-regeneration "$REGEN_FILES" "$NO_REVIEWS")" -F_EMPTY="$(fixture empty-diff '[]' "$NO_REVIEWS")" -F_RENAMED_OFF="$(fixture governed-renamed-off-the-surface "$(renamed_of AGENTS.md docs/AGENTS.md)" "$NO_REVIEWS")" -F_RENAMED_CLEAR="$(fixture rename-within-an-ordinary-prefix "$(renamed_of packages/spec/src/a.ts packages/spec/src/b.ts)" "$NO_REVIEWS")" - -mcp() { # mcp [owner] [repo] - jq -nc --arg t "$1" --argjson n "$2" --arg o "${3:-objectstack-ai}" --arg r "${4:-objectstack}" \ - '{tool_name:$t,tool_input:{owner:$o,repo:$r,pullNumber:$n}}' -} -bash_call() { jq -nc --arg c "$1" '{tool_name:"Bash",tool_input:{command:$c}}'; } - -AUTO=mcp__github__enable_pr_auto_merge -MERGE=mcp__github__merge_pull_request - -# The hook is the LAST element of the pipeline, so `$?` here is the HOOK's exit -# status and not some downstream reader's. That is the only shape in which -# reading a status after a pipe is safe, and it is why nothing is piped past it. -run() { # run [env assignments…] -> allow | block | exitN - local payload="$1"; shift - local rc - printf '%s' "$payload" | env "$@" "$hook_under_test" >/dev/null 2>&1 - rc=$? - case "$rc" in - 0) printf 'allow' ;; - 2) printf 'block' ;; - *) printf 'exit%s' "$rc" ;; - esac -} - -stderr_of() { # stderr_of [env…] - local payload="$1"; shift - printf '%s' "$payload" | env "$@" "$hook_under_test" 2>&1 >/dev/null -} - -expect() { # expect