Skip to content

fix(claude-code-review): disable self-review skip on mention or dispatch triggers - #417

Closed
d-morrison wants to merge 2 commits into
mainfrom
fix-self-review-mention-skip
Closed

fix(claude-code-review): disable self-review skip on mention or dispatch triggers#417
d-morrison wants to merge 2 commits into
mainfrom
fix-self-review-mention-skip

Conversation

@d-morrison

Copy link
Copy Markdown
Collaborator

Description

Bypasses the skip in when the workflow is executed via explicit mention (@claude review) or workflow_dispatch.

Behavior

  • Automatic pull_request runs: Continue to skip self-review if the PR edits the caller workflow file (avoiding 401 unmerged workflow validation errors).
  • Mention / workflow_dispatch runs: Bypass the skip so on-demand review requests succeed even on PRs that edit the workflow file.

Fixes an issue where @claude review on a PR editing the review workflow produced no verdict.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Antigravity Agent Report (Code-Review)

This single-pass code review evaluates Pull Request #417 (fix(claude-code-review): disable self-review skip on mention or dispatch triggers).


Overall Assessment

The logic change is well-targeted and addresses a real usability issue where on-demand review requests (@claude review, /review, or workflow_dispatch) were silently skipped when a PR edited the caller workflow file.

The documentation updates in CLAUDE.md accurately reflect this behavior shift. Below are specific actionable findings regarding performance optimization, repository policy compliance, and defense-in-depth script robustness.


Key Findings & Recommendations

1. Unnecessary GitHub API call on dispatched runs

Location: .github/workflows/claude-code-review.yml:L396-L405

Issue:
In the Skip self-review when the PR edits this workflow step, line 399 unconditionally fetches the list of changed PR files via gh api "repos/$REPO/pulls/$PR_NUMBER/files" ... before checking IS_DISPATCH.

files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
if [ "$IS_DISPATCH" != "true" ] && printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
  echo "self_mod=true" >> "$GITHUB_OUTPUT"
  echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
else
  echo "self_mod=false" >> "$GITHUB_OUTPUT"
fi

On every dispatched or mention-triggered run (@claude review, /review, or workflow_dispatch), IS_DISPATCH is "true". The step makes a network API call to GitHub and parses JSON, only to immediately discard $files because [ "$IS_DISPATCH" != "true" ] evaluates to false. This adds unnecessary network latency and consumes API rate limits on every on-demand review request.

Recommendation:
Branch on [ "$IS_DISPATCH" = "true" ] first so the gh api fetch is executed only on automatic pull_request runs (IS_DISPATCH is "false"):

-          files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
-          if [ "$IS_DISPATCH" != "true" ] && printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
-            echo "self_mod=true" >> "$GITHUB_OUTPUT"
-            echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
-          else
-            echo "self_mod=false" >> "$GITHUB_OUTPUT"
-          fi
+          if [ "$IS_DISPATCH" = "true" ]; then
+            echo "self_mod=false" >> "$GITHUB_OUTPUT"
+          else
+            files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
+            if printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
+              echo "self_mod=true" >> "$GITHUB_OUTPUT"
+              echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
+            else
+              echo "self_mod=false" >> "$GITHUB_OUTPUT"
+            fi
+          fi

2. Missing Changelog Fragment

Location: changelog.d/

Issue:
Per repository guidelines in CLAUDE.md:

Every PR that changes user-facing behavior should add a changelog fragment under changelog.d/ (a <slug>.<category>.md file — see changelog.d/README.md) rather than editing CHANGELOG.md directly...

This PR modifies user-facing capability behavior (enabling on-demand @claude review / /review reviews on PRs editing the workflow file), but does not include a fragment under changelog.d/.

Recommendation:
Add a fragment file, e.g. changelog.d/claude-review-self-review-dispatch.fixed.md:

Bypass the workflow self-modification review skip on explicit `@claude review`, `/review`, or `workflow_dispatch` runs so on-demand review requests succeed even when editing caller workflows.

3. Handling empty PR_NUMBER on empty workflow_dispatch inputs

Location: .github/workflows/claude-code-review.yml:L394

Issue:
PR_NUMBER is defined as:

PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr-number }}

If workflow_dispatch is triggered manually without supplying a PR number, PR_NUMBER will evaluate to an empty string "".
While gather-context's dispatch-guard step catches missing PR numbers when fetching PR metadata, if selfmod runs with IS_DISPATCH: true and an empty PR_NUMBER, self_mod will output false. Downstream steps attempting gh api calls with an empty PR_NUMBER will receive 404 Not Found or 422 Unprocessable Entity.

Recommendation:
In addition to the early short-circuit proposed in Finding #1, ensure PR_NUMBER is non-empty before logging notice messages or executing PR queries.


Summary Table of Actionable Findings

# File / Location Type Severity Description
1 .github/workflows/claude-code-review.yml:L396-L405 Performance Low Unconditional gh api call on dispatch runs before checking IS_DISPATCH.
2 changelog.d/ Policy Low Missing changelog fragment for user-facing fix.
3 .github/workflows/claude-code-review.yml:L394 Robustness Low Edge-case handling when PR_NUMBER is empty on manual dispatch.

Comment on lines 396 to 405
IS_DISPATCH: ${{ inputs.pr-number != '' || github.event_name == 'workflow_dispatch' }}
run: |
set -euo pipefail
files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
if printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
if [ "$IS_DISPATCH" != "true" ] && printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
echo "self_mod=true" >> "$GITHUB_OUTPUT"
echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping self-review (the action 401s on workflow validation until merged; it runs after merge)."
echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
else
echo "self_mod=false" >> "$GITHUB_OUTPUT"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1. Unnecessary GitHub API call on dispatched runs

(file:///home/runner/work/gha/gha/.github/workflows/claude-code-review.yml#L396-L405)

Issue:
In the Skip self-review when the PR edits this workflow step, line 399 unconditionally fetches the list of changed PR files via gh api "repos/$REPO/pulls/$PR_NUMBER/files" ... before checking IS_DISPATCH.

files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
if [ "$IS_DISPATCH" != "true" ] && printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
  echo "self_mod=true" >> "$GITHUB_OUTPUT"
  echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
else
  echo "self_mod=false" >> "$GITHUB_OUTPUT"
fi

On every dispatched or mention-triggered run (@claude review, /review, or workflow_dispatch), IS_DISPATCH is "true". The step makes a network API call to GitHub and parses JSON, only to immediately discard $files because [ "$IS_DISPATCH" != "true" ] evaluates to false. This adds unnecessary network latency and consumes API rate limits on every on-demand review request.

Recommendation:
Branch on [ "$IS_DISPATCH" = "true" ] first so the gh api fetch is executed only on automatic pull_request runs (IS_DISPATCH is "false"):

-          files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
-          if [ "$IS_DISPATCH" != "true" ] && printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
-            echo "self_mod=true" >> "$GITHUB_OUTPUT"
-            echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
-          else
-            echo "self_mod=false" >> "$GITHUB_OUTPUT"
-          fi
+          if [ "$IS_DISPATCH" = "true" ]; then
+            echo "self_mod=false" >> "$GITHUB_OUTPUT"
+          else
+            files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
+            if printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
+              echo "self_mod=true" >> "$GITHUB_OUTPUT"
+              echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
+            else
+              echo "self_mod=false" >> "$GITHUB_OUTPUT"
+            fi
+          fi

2. Missing Changelog Fragment

Location: changelog.d/

Issue:
Per repository guidelines in CLAUDE.md:

Every PR that changes user-facing behavior should add a changelog fragment under changelog.d/ (a <slug>.<category>.md file — see changelog.d/README.md) rather than editing CHANGELOG.md directly...

This PR modifies user-facing capability behavior (enabling on-demand @claude review / /review reviews on PRs editing the workflow file), but does not include a fragment under changelog.d/.

Recommendation:
Add a fragment file, e.g. changelog.d/claude-review-self-review-dispatch.fixed.md:

Bypass the workflow self-modification review skip on explicit `@claude review`, `/review`, or `workflow_dispatch` runs so on-demand review requests succeed even when editing caller workflows.

env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr-number }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3. Handling empty PR_NUMBER on empty workflow_dispatch inputs

(file:///home/runner/work/gha/gha/.github/workflows/claude-code-review.yml#L394)

Issue:
PR_NUMBER is defined as:

PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr-number }}

If workflow_dispatch is triggered manually without supplying a PR number, PR_NUMBER will evaluate to an empty string "".
While gather-context's dispatch-guard step catches missing PR numbers when fetching PR metadata, if selfmod runs with IS_DISPATCH: true and an empty PR_NUMBER, self_mod will output false. Downstream steps attempting gh api calls with an empty PR_NUMBER will receive 404 Not Found or 422 Unprocessable Entity.

Recommendation:
In addition to the early short-circuit proposed in Finding #1, ensure PR_NUMBER is non-empty before logging notice messages or executing PR queries.


Summary Table of Actionable Findings

# File / Location Type Severity Description
1 .github/workflows/claude-code-review.yml:L396-L405 Performance Low Unconditional gh api call on dispatch runs before checking IS_DISPATCH.
2 changelog.d/ Policy Low Missing changelog fragment for user-facing fix.
3 .github/workflows/claude-code-review.yml:L394 Robustness Low Edge-case handling when PR_NUMBER is empty on manual dispatch.

Comment on lines 393 to 405
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr-number }}
WF_PATH: ${{ steps.caller-wf.outputs.path }}
IS_DISPATCH: ${{ inputs.pr-number != '' || github.event_name == 'workflow_dispatch' }}
run: |
set -euo pipefail
files=$(gh api "repos/$REPO/pulls/$PR_NUMBER/files" --paginate --jq '.[].filename' 2>/dev/null || true)
if printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
if [ "$IS_DISPATCH" != "true" ] && printf '%s\n' "$files" | grep -qxF "$WF_PATH"; then
echo "self_mod=true" >> "$GITHUB_OUTPUT"
echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping self-review (the action 401s on workflow validation until merged; it runs after merge)."
echo "::notice::PR #$PR_NUMBER edits $WF_PATH — skipping automatic self-review (the action 401s on workflow validation until merged; it runs after merge)."
else
echo "self_mod=false" >> "$GITHUB_OUTPUT"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely doesn't fix gha#286 — converts a graceful skip into a real 401 failure.

The guard's own (unchanged) comment above this step says the 401 is caused by claude-code-action's App-token exchange requiring "the workflow to match the default branch" — i.e. it's keyed on the content of the running workflow file at its ref, not on how the run was triggered.

But every dispatch entry point this IS_DISPATCH bypass is meant to unblock resolves the run against the PR's own branch:

  • claude.yml dispatches with gh workflow run "$REVIEW_WF" --ref "$PR_BRANCH" -f pr_number=... (e.g. claude.yml#L1112-L1117, and again at ~L1202, L1243, L1415).
  • claude-review.yml's /review dispatch does the same.

So when the PR under review edits the caller workflow file, a dispatched/mentioned run executes that PR's modified copy — exactly the "doesn't match the default branch" condition the guard exists to avoid. IS_DISPATCH only skips the skip; it doesn't change what the review action runs against, and run-claude-review-attempt/action.yml passes no github_token override, so anthropics/claude-code-action still goes through the default OIDC App-token exchange that 401s.

Net effect for the exact scenario in the PR description (@claude review on a PR editing claude-review.yml): instead of a green skip with no verdict (gha#286's symptom), the review now runs and should 401, turning claude-review/require-review red — arguably worse, since it's now a required-check failure rather than a silently-missing review. Worth verifying empirically against a real PR (e.g. via workflow_dispatch on a branch that edits this file) before merging, since this repo's own dogfood review can't self-verify the fix pre-merge (per this file's own "@v2 tag" limitation).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed empirically — you are right. I ran the live test (throwaway PR #420 editing claude-review.yml, callee repointed at this branch, then workflow_dispatch with pr_number set so IS_DISPATCH=true). Two runs, identical result:

Exchanging OIDC token for app token...
Skipping action due to workflow validation: Workflow validation failed.
The workflow file must exist and have identical content to the version on
the repository's default branch...
Exiting due to workflow validation skip
→ Claude review produced no execution output — treating as a failed review.

So the guard bypass lets the action be invoked, but it then fails workflow-validation (the caller workflow differs from default), exits with no output, and claude-review/require-review both go red — a required-check failure, no verdict, exactly as you predicted. The validation keys on workflow content vs default, not on trigger type. Leaving this thread open pending a decision (see the top-level comment).

Comment thread CLAUDE.md Outdated
Comment on lines +1399 to +1403
step past the guard shows `skipped`, and no verdict comment is ever posted. This
is deliberate (the action's own App-token exchange 401s on an automatic workflow
file that doesn't match the default branch's content until merge — see the guard's
own comment), but a green `claude-review` check is easy to mistake for a real
review.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the action's own App-token exchange 401s on an automatic workflow file that doesn't match the default branch's content" is an undefended, and likely inaccurate, factual claim — see code review guideline 4 ("check that every factual claim is defended... a bare assertion with neither is a finding even when it turns out to be true").

The App-token 401 is a property of the workflow file's content at the ref being run, not the trigger type — nothing in claude-code-action's OIDC validation distinguishes "automatic" from "dispatched." A dispatched run against a PR branch that edits the workflow file hits the identical mismatch (see the inline comment on .github/workflows/claude-code-review.yml's IS_DISPATCH logic in this same PR). "Automatic" here modifies "workflow file," which doesn't parse — a file isn't automatic — and the intended meaning (the 401 only happens on automatic runs) appears to be the unverified premise the whole code change rests on.

Comment thread CLAUDE.md Outdated
produced only a `$0.60` cost comment, no verdict — the guard had set
`self_mod=true` and skipped straight through, because the PR touched
`claude-review.yml` itself.)
of what `@v2` currently points at.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deletes the gha#286 incident record ("an @claude review comment produced only a $0.60 cost comment, no verdict...") outright rather than updating it. That anecdote was the concrete, defended evidence for the surrounding claim that a green claude-review check is easy to mistake for a real review — CLAUDE.md's own convention elsewhere (e.g. the WORKFLOW_TOKEN push-failure section) is to append new context to a historical incident rather than remove the original description. Given the finding above (this PR likely doesn't fully fix the dispatched-run case — it changes the failure mode rather than eliminating it), deleting the only cited real-world example here removes debugging context that may still be relevant, and does so before the fix is confirmed to hold.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Claude finished reviewView run


All three inline comments posted successfully. Here's the final review summary.

Code review: PR #417

Summary: This PR adds an IS_DISPATCH bypass to claude-code-review.yml's self-review skip guard so @claude review mentions and workflow_dispatch runs no longer skip review of PRs that edit the caller review-workflow file, fixing the gha#286 symptom (silent skip, no verdict). CLAUDE.md is updated in parallel to document the new behavior.

Findings (posted inline)

  1. .github/workflows/claude-code-review.yml:393-405 (blocking, high confidence) — The fix likely does not fix gha#286; it changes the failure mode instead. The guard's own unchanged comment says the App-token 401 is keyed on the workflow file's content at the ref being run vs. the default branch — not on trigger type. Every dispatch path (claude.yml, claude-review.yml's /review handler) dispatches with --ref "$PR_BRANCH", so a dispatched/mentioned run on a PR that edits the caller workflow executes that PR's modified copy — the exact mismatch condition that 401s. run-claude-review-attempt/action.yml passes no github_token override, so the default OIDC App-token exchange still applies. Net effect: @claude review on such a PR goes from a graceful skip (no verdict) to a real 401 that should redden claude-review/require-review — a required-check failure, arguably worse than the original bug. This needs empirical verification (e.g. a real dispatched run against a branch editing the file) before merging, and can't be self-verified via this repo's own dogfood review pre-merge.
  2. CLAUDE.md:1399-1403 — "401s on an automatic workflow file" is an undefended and likely inaccurate claim (per CLAUDE.md's own code-review guideline 4) — it's the load-bearing premise for finding 1, asserted without support, and doesn't correctly parse ("automatic" modifying "workflow file").
  3. CLAUDE.md:1420 — Deletes the gha#286 incident anecdote outright rather than updating it, removing the one concrete, cited example — contrary to this file's own pattern of appending new context to historical incidents rather than removing them, and premature given finding 1.

Also noted (not inline — no single anchor line)

  • Missing changelog.d/ fragment. This changes observable behavior of a @v2-consumed reusable workflow (a bug-fix touching every downstream consumer), which CLAUDE.md's Layout section explicitly asks for a <slug>.fixed.md fragment to accompany. None was added. Not CI-enforced, but explicit guidance the PR doesn't follow.
  • All four independent review passes (2 CLAUDE.md-compliance, 2 bug-hunting) converged independently on the same core mechanism finding above, which I then verified directly against claude.yml, claude-review.yml, and run-claude-review-attempt/action.yml in the actual repo — the --ref "$PR_BRANCH" dispatch pattern and the absence of a github_token override are both confirmed in the current tree.
  • No security issue found: inputs.pr-number isn't attacker-controllable (dispatch requires write access / trusted-author gating upstream).

Verdict

Needs more work — the core logic change should be verified empirically (or reasoned through more carefully) before merge; as written, it appears to trade a silent-skip bug for a red required-check failure on the same class of PRs, rather than fixing the underlying issue.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

💰 Cost: $7.9607 (review) — run

@d-morrison

Copy link
Copy Markdown
Collaborator Author

Empirical test result — finding 1 confirmed (fix is counterproductive as-written)

I ran the live test @claude-review recommended (throwaway PR #420, now closed): a PR editing claude-review.yml with its callee repointed at this branch, reviewed via workflow_dispatch with pr_number set (→ IS_DISPATCH=true, bypassing the skip). Two runs, identical outcome: the claude-code-action is invoked, hits Workflow validation failed (caller content ≠ default branch), "gracefully skips" with no execution output, and the guard turns claude-review + require-review red — no verdict produced.

Conclusion: bypassing the self-review skip on dispatch/mention does not fix gha#286. It trades a silent green skip for a red required-check failure on the same PR class. The validation is keyed on workflow content vs. the default branch, independent of trigger type.

Two ways forward (your call):

  1. Rework — pass a github_token override (a PAT / GitHub App token with the needed scopes) to claude-code-action in run-claude-review-attempt, so it skips the OIDC App-token exchange (and its workflow-validation) and can actually review workflow-editing PRs. Security/secret decision (which token). Would need its own live test.
  2. Abandon — close fix(claude-code-review): disable self-review skip on mention or dispatch triggers #417 and keep the silent skip, since bypassing it only reddens the check without yielding a review. gha#286's silent-skip remains a known, documented limitation.

Findings 2 & 3 (the CLAUDE.md wording / deleted anecdote) are downstream of this and only make sense to finalize once the direction is chosen.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

👀 Picked up by workflow run #31057346945. Setup runs first; Claude itself responds after that.

Empirical test (#420) confirmed the IS_DISPATCH bypass
trades gha#286's silent skip for a red required-check failure instead
of fixing it: a dispatched/mentioned run on a PR editing the caller
workflow still executes that PR's modified copy, so claude-code-action's
App-token exchange 401s regardless of trigger type. Reverting both the
workflow change and its CLAUDE.md documentation back to main; gha#286's
silent-skip limitation remains open and documented as-is. A real fix
would need to pass claude-code-action a non-OIDC github_token override,
which is a separate security/secret decision left for a future PR.
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Decision: abandon (option 2)

Per the empirical test in #420: bypassing the self-review skip on mention/workflow_dispatch doesn't fix gha#286 — it trades a silent green skip for a red required-check failure on the same PR class, since claude-code-action's App-token exchange is keyed on workflow content vs. the default branch, not on trigger type.

I'm going with abandon rather than rework, because the rework path (passing claude-code-action a non-OIDC github_token override) is a standalone security/secret decision — which token, what scope, whether a new secret needs provisioning — that deserves its own scoped PR and live test rather than being folded into closing this one out.

I've committed a revert of this branch's change (both .github/workflows/claude-code-review.yml and the CLAUDE.md doc update) back to match main exactly — the post-step will push it. Findings 2 & 3 from the earlier review (the CLAUDE.md wording, the deleted gha#286 anecdote) are moot now that the code change is reverted; main's existing text already covers gha#286 correctly.

One thing I couldn't finish: I don't have write access to post PR comments or close PRs from this session (gh pr comment/gh pr close were both blocked by the permission sandbox). Since the fix is fully reverted and there's nothing left to merge, PR #417 should be closed by a maintainer — it's now a no-op diff against main. I'd also suggest filing a follow-up issue for the "rework" option (passing a github_token override to run-claude-review-attempt) if one doesn't already exist, since that's the only path that would actually fix gha#286.

— posted by @claude post-step from workflow run

💰 Cost: $1.5731745

@d-morrison

Copy link
Copy Markdown
Collaborator Author

Abandoning per maintainer decision.

The live empirical test (throwaway PR #420) confirmed this fix is counterproductive: bypassing the self-review skip on @claude review/dispatch lets the action run, but it then fails anthropics/claude-code-action's OIDC workflow-validation (the caller workflow differs from the default branch), exits with no output, and turns claude-review/require-review red with no verdict — worse than the silent skip it replaced. The validation keys on workflow content vs. default branch, not on trigger type, so no trigger-based bypass can fix gha#286.

Keeping the documented silent-skip limitation. The real fix, if we ever want @claude review to work on workflow-editing PRs, is a github_token override on the action (skips the OIDC exchange) — a secret/scoping decision that would need its own live test. Leaving that as a future option rather than a rushed change.

The workflow-validation-skip diagnosis this test produced is being recorded in #422.

@d-morrison d-morrison closed this Aug 6, 2026
@d-morrison
d-morrison deleted the fix-self-review-mention-skip branch August 6, 2026 00:36
d-morrison added a commit that referenced this pull request Aug 6, 2026
Address #422 review:
- Fix the factual framing: dispatch does NOT bypass self_mod today (the
  guard's PR_NUMBER resolves the same regardless of trigger, per the
  gha#286 example); bypassing it was gha#417's proposal, now abandoned.
  Reframe as 'why the guard exists / why bypassing it fails', past-tense.
- Timing tell is step-level (~4-11s), not a job-level ~15s; note total
  job time is unreliable (checkout/installs run first).
- Name the caller workflow claude-review.yml; use self_mod terminology;
  keep '@claude review' code spans intact on one line.
- Same corrections in the changelog fragment.
d-morrison added a commit that referenced this pull request Aug 6, 2026
- The validation skip is reachable today, not only via a deliberate
  bypass: the self_mod guard reads files via 'gh api ... || true', so a
  transient gh api failure fails open (self_mod=false) on a caller-editing
  PR and the review proceeds into the content-validation skip. Note both
  paths (deliberate #417-style bypass; live fail-open).
- Drop the self-contradictory '(e.g. by the github_token fix below)' from
  the diagnostic-tells intro (the override prevents the skip, and it was a
  forward reference).
- Downgrade 'the real fix (proven via #420)' to 'likely (untested) fix':
  #420 only proved the bypass counterproductive; the override was never
  exercised and has no input wired up. Same softening in the changelog.
d-morrison added a commit that referenced this pull request Aug 6, 2026
#422)

* docs: record the claude-code-action workflow-validation skip signature

A PR that edits the review workflow and bypasses the self-review skip guard
(e.g. an @claude review dispatch, as #417 attempted) still gets no verdict:
anthropics/claude-code-action validates its own content against the default
branch and gracefully skips on a mismatch, producing outcome=success, a
sub-15s run, and no execution output -- so check-review-execution.sh reddens
claude-review/require-review with no verdict.

Record that this does NOT surface as a literal 401 in the log (the signature
is 'Workflow validation failed' / 'Exiting due to workflow validation skip'),
the diagnostic tells, that bypassing the self-review skip does not help since
validation keys on workflow content vs the default branch, and that a
github_token override on the action is the real fix. Proven empirically via
throwaway test PR #420 on 2026-08-05.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs: correct workflow-validation-skip note now that #417 is abandoned

Address #422 review:
- Fix the factual framing: dispatch does NOT bypass self_mod today (the
  guard's PR_NUMBER resolves the same regardless of trigger, per the
  gha#286 example); bypassing it was gha#417's proposal, now abandoned.
  Reframe as 'why the guard exists / why bypassing it fails', past-tense.
- Timing tell is step-level (~4-11s), not a job-level ~15s; note total
  job time is unreliable (checkout/installs run first).
- Name the caller workflow claude-review.yml; use self_mod terminology;
  keep '@claude review' code spans intact on one line.
- Same corrections in the changelog fragment.

* docs: correct fail-open path and untested-fix overclaim (#422 review)

- The validation skip is reachable today, not only via a deliberate
  bypass: the self_mod guard reads files via 'gh api ... || true', so a
  transient gh api failure fails open (self_mod=false) on a caller-editing
  PR and the review proceeds into the content-validation skip. Note both
  paths (deliberate #417-style bypass; live fail-open).
- Drop the self-contradictory '(e.g. by the github_token fix below)' from
  the diagnostic-tells intro (the override prevents the skip, and it was a
  forward reference).
- Downgrade 'the real fix (proven via #420)' to 'likely (untested) fix':
  #420 only proved the bypass counterproductive; the override was never
  exercised and has no input wired up. Same softening in the changelog.

* docs: semantic line breaks in the fail-open paragraph (one sentence per line)

* docs: 'skips every step of the review job' (job runs green, not skipped)

Address #422 review: the self_mod guard is step-level; the job still runs
and reports success (green), so 'skips the whole review job' was imprecise
and contradicted the paragraph's own 'green job, every post-guard step
skipped' clause.

* docs: cross-link the two OIDC-validation sections; reconcile github_token confidence; add fail-open path to changelog

Address #422 review round 4:
- Cross-link the workflow-validation-skip note and the 'Test changes
  against a template repo' section (same OIDC mechanism, two angles) so
  neither re-derives the other uncited (item 10).
- Add the 'untested' caveat to that section's github_token mention so both
  passages state the fix with the same confidence.
- Fold the fail-open gh-api path into the changelog fragment, which had
  only the deliberate-bypass path (a changelog reader lacks the CLAUDE.md
  context).

* docs: drop forward-ref to 'Never just theorize' section; add (#422) to changelog bullet

* docs: drop 'for the reason below' forward signpost (reason emerges inline)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant