From 376a5ff4bbe4451a2e15719b5f7c57bb3a0de67c Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Sat, 18 Apr 2026 12:10:50 -0700 Subject: [PATCH] fix: match documented [skip-claude-review: reason] form in grep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The escape-hatch grep at line 305 used `grep -qF '[skip-claude-review]'` (fixed-string, bare brackets), but every user-facing error message and the workflow header comment advertise the `[skip-claude-review: reason]` form. That form does not contain `[skip-claude-review]` as a substring — the `]` sits after the reason, not after `review` — so the grep never matched the documented marker. Users who followed the advice literally (like PR #1162 last session) watched their reruns fail identically, with no diagnostic pointing at the grep/message mismatch. The only working form was the bare token the docs never mentioned. Switch to an extended regex that matches both shapes: - [skip-claude-review] (existing behavior, unchanged) - [skip-claude-review: reason] (what every error message promises) - [skip-claude-review:] (degenerate, harmless) Tested locally against the match matrix from the AAR: MATCH : [skip-claude-review] MATCH : [skip-claude-review: doc-only diff, infrastructure flake] MATCH : [skip-claude-review:] NOMATCH: [skip-claude-review (unclosed/malformed) NOMATCH: [skip-claude-reviewfoo] (similar-looking prefix) NOMATCH: no marker here NOMATCH: skip-claude-review without brackets Keep all documentation/error messages on the `: reason` form — it's the better UX because it forces an audit trail in the bypass. Closes #38. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/claude-blocking-review.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/claude-blocking-review.yml b/.github/workflows/claude-blocking-review.yml index 9ed83a3..d635abd 100644 --- a/.github/workflows/claude-blocking-review.yml +++ b/.github/workflows/claude-blocking-review.yml @@ -300,10 +300,13 @@ jobs: PR_NUMBER: ${{ inputs.pr_number }} CLAUDE_OUTCOME: ${{ steps.claude-review.outcome }} run: | - # Escape hatch: [skip-claude-review: reason] in PR body bypasses enforcement + # Escape hatch: [skip-claude-review] or [skip-claude-review: reason] in PR body + # bypasses enforcement. The extended regex matches both the bare token and the + # documented `: reason` form advertised by our error messages. See issue #38 + # for the prior -F fixed-string pattern that only matched the bare form. PR_BODY=$(gh pr view "$PR_NUMBER" --json body -q .body 2>/dev/null || echo "") - if echo "$PR_BODY" | grep -qF '[skip-claude-review]'; then - echo "::notice::Claude Code Review enforcement skipped via [skip-claude-review] in PR body." + if echo "$PR_BODY" | grep -qE '\[skip-claude-review(\]|:)'; then + echo "::notice::Claude Code Review enforcement skipped via [skip-claude-review] marker in PR body." echo "## Claude Code Review" >> "$GITHUB_STEP_SUMMARY" echo "**Verdict:** SKIPPED (override in PR body)" >> "$GITHUB_STEP_SUMMARY" exit 0