Explorar o código

fix(ci): give the review bot the pull request's own code and CI verdict

Three consecutive review runs (#6105, #6265, #6272) posted accurate findings
but ended with the same "nothing was verified" paragraph, and the transcripts
show why: under pull_request_target the only checkout is the base branch, so
every Read of a changed file returned the pre-merge version and the agent
fell back to fetching blobs one at a time through the API — 452 Bash calls on
#6105 alone. It tried `git fetch origin pull/N/head` in all three runs and was
denied every time.

Check the head out read-only beside the base tree and say so in the prompt, so
the reviewer greps the code actually under review. Nothing builds or executes
from pr-head/: this job carries a write-scoped token, which is exactly the
pwn-request REVIEW.md classes as blocking.

CI had already run the full gate on each head SHA, but no run ever looked —
`check-runs` appears in none of the three transcripts. Point the reviewer at
it so a red or missing required check becomes a finding instead of a
disclaimer.

Also pass an explicit review level: with none given the skill reuses the last
one typed, which in CI does not exist (ReportFindings recorded level=null on
#6272). And allow WebFetch/WebSearch — the PIA review was denied both while
trying to confirm the bundled PIA public key, then had to file that same check
as unverified.
Sanaei hai 13 horas
pai
achega
73a971c2d1
Modificáronse 1 ficheiros con 10 adicións e 3 borrados
  1. 10 3
      .github/workflows/claude-bot.yml

+ 10 - 3
.github/workflows/claude-bot.yml

@@ -494,6 +494,13 @@ jobs:
       - uses: actions/checkout@v7
         with:
           persist-credentials: false
+      # Read-only: this job holds a write-scoped token, so building or running
+      # anything out of pr-head/ would turn the review into a pwn-request.
+      - uses: actions/checkout@v7
+        with:
+          ref: refs/pull/${{ github.event.pull_request.number || github.event.issue.number }}/head
+          path: pr-head
+          persist-credentials: false
       - uses: anthropics/claude-code-action@v1
         with:
           github_token: ${{ secrets.GITHUB_TOKEN }}
@@ -501,13 +508,13 @@ jobs:
           allowed_non_write_users: "*"
           plugin_marketplaces: "https://github.com/anthropics/claude-code.git"
           plugins: "code-review@claude-code-plugins"
-          prompt: "/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number || github.event.issue.number }}"
+          prompt: "/code-review:code-review high --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number || github.event.issue.number }}"
           claude_args: |
             --model claude-opus-5
             --effort xhigh
             --max-turns 100
-            --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh api:*),Bash(gh pr diff:*),Read(//tmp/**),Write(//tmp/**),Edit(//tmp/**)"
-            --append-system-prompt "Before reviewing, read REVIEW.md at the repository root and follow it: it defines what counts as a blocking finding in this repository, what not to report, and the repo-specific checks. Three overrides apply here. First, the skip gate for already-reviewed PRs: an existing Claude review comment justifies skipping ONLY when its 'Reviewed head:' SHA equals the PR's current head SHA; when the head has moved on, or this run was triggered by an explicit '@claude review' comment, run the full review, focusing on the commits since the previously reviewed head. Second, this is a headless run that terminates the moment you end your turn: launch every subagent with run_in_background set to false and wait for its result inside the same turn - never end your turn while a subagent is still running, and never end it before the review comment is posted. A run that ends without posting the review has failed. Third, the comment you post is the only part of this run anyone can see: it must carry the coverage list REVIEW.md asks for, whether or not you found anything."
+            --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh api:*),Bash(gh pr diff:*),Read(//tmp/**),Write(//tmp/**),Edit(//tmp/**),WebFetch,WebSearch"
+            --append-system-prompt "Before reviewing, read REVIEW.md at the repository root and follow it: it defines what counts as a blocking finding in this repository, what not to report, and the repo-specific checks. Five overrides apply here. First, the skip gate for already-reviewed PRs: an existing Claude review comment justifies skipping ONLY when its 'Reviewed head:' SHA equals the PR's current head SHA; when the head has moved on, or this run was triggered by an explicit '@claude review' comment, run the full review, focusing on the commits since the previously reviewed head. Second, this is a headless run that terminates the moment you end your turn: launch every subagent with run_in_background set to false and wait for its result inside the same turn - never end your turn while a subagent is still running, and never end it before the review comment is posted. A run that ends without posting the review has failed. Third, the comment you post is the only part of this run anyone can see: it must carry the coverage list REVIEW.md asks for, whether or not you found anything. Fourth, the default working tree is the BASE branch, and a read-only checkout of the pull request head sits beside it in pr-head/: read and grep the changed files under pr-head/, and treat anything read outside it as the pre-merge baseline rather than as the code under review. Never build, install or execute anything from pr-head/ - this job holds a write-scoped token, so running pull-request code with it is the workflow vulnerability REVIEW.md itself calls blocking. Fifth, you cannot build or test here, but CI already did: read the head commit's checks with 'gh api repos/OWNER/REPO/commits/HEAD_SHA/check-runs' and report what they actually concluded instead of writing that verification was unavailable. A required check that failed, or that never ran on this head, is itself a finding."
       - name: Upload the run transcript
         if: always()
         env: