1010 # - "src/**/*.js"
1111 # - "src/**/*.jsx"
1212
13+ concurrency :
14+ group : claude-review-${{ github.event.pull_request.number }}
15+ cancel-in-progress : true
16+
1317jobs :
1418 claude-review :
1519 # Skip review for automated "Version Packages" PRs created by changesets
1620 if : github.event.pull_request.title != 'Version Packages'
1721
22+ timeout-minutes : 30
1823 runs-on : ubuntu-latest
1924 permissions :
2025 contents : read
21- pull-requests : read
26+ pull-requests : write
2227 issues : read
2328 id-token : write
2429
3338 uses : anthropics/claude-code-action@v1
3439 with :
3540 anthropic_api_key : ${{ secrets.ANTHROPIC_API_KEY }}
41+ plugin_marketplaces : |
42+ https://github.com/obra/superpowers-marketplace.git
43+ plugins : |
44+ superpowers@superpowers-marketplace
3645 prompt : |
3746 You are Claude reviewing PRs for the Cloudflare Sandbox SDK.
3847
@@ -52,54 +61,101 @@ jobs:
5261
5362 **Then review the diff with that context.**
5463
55- ### 2. Check for Previous Review (if this is an update )
64+ ### 2. Check for Previous Review (Internal Context Only )
5665
57- **Detect if this is a PR update:**
58- - Check for existing claude[bot] comment: `gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.author.login == "claude[bot]" or .author.login == "github-actions[bot]")'`
66+ Check if you've reviewed this PR before:
67+ ```bash
68+ gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.author.login == "claude[bot]" or .author.login == "github-actions[bot]")'
69+ ```
5970
60- **If previous review exists:**
61- - Identify what's new: `git log --oneline ${{ github.event.before }}..${{ github.event.after }}` (shows commits since last review)
62- - Check if history was rewritten: `git cat-file -t ${{ github.event.before }} 2>/dev/null` (if fails, force push occurred)
63- - Read the previous review to understand what was flagged
71+ If previous review exists:
72+ - Read it to understand what you said before
73+ - Note what commits have been added since: `git log --oneline ${{ github.event.before }}..${{ github.event.after }}`
74+ - Check if history was rewritten: `git cat-file -t ${{ github.event.before }} 2>/dev/null`
75+ - Use this context internally when writing your review
6476
65- **Your review should cover BOTH:**
66- 1. **Incremental**: What changed since last review? Were previous issues addressed?
67- 2. **Holistic**: How does the FULL PR look now? Any issues when viewing the complete picture?
77+ **Don't announce "Update N" or link to previous reviews** - just write naturally.
6878
6979 ### 3. Gather Context
7080 - Use `gh pr view ${{ github.event.pull_request.number }}` for PR description
7181 - Use `gh pr diff ${{ github.event.pull_request.number }}` for FULL diff (not just incremental)
7282 - Read CLAUDE.md for repo-specific conventions and architecture patterns
7383 - Use Read tool to examine key changed files
7484
75- ### 4. Internal Analysis
85+ ### 4. Check Documentation Impact
86+ Use `mcp__cloudflare-docs__search_cloudflare_documentation` to check if this PR requires doc updates:
87+ - Does it change existing documented behavior?
88+ - Does it add new features needing documentation?
89+ - Does it have security implications needing best practices docs?
90+ - If yes, call out specific doc sections that need updates
91+
92+ ### 5. Internal Analysis
7693 Before writing your review, analyze inside <analysis> tags (do NOT include in final comment):
7794 a. What is this PR accomplishing?
7895 b. Which packages/layers are affected?
7996 c. Are there architectural or security implications?
8097 d. What tests are needed?
8198 e. Does this need documentation updates?
8299
83- ### 5. Check Documentation Impact
84- Use `mcp__cloudflare-docs__search_cloudflare_documentation` to check if this PR requires doc updates:
85- - Does it change existing documented behavior?
86- - Does it add new features needing documentation?
87- - Does it have security implications needing best practices docs?
88- - If yes, call out specific doc sections that need updates
100+ ### 6. Fetch Existing Review Threads
89101
90- ### 6. Review Focus
102+ Before creating your review, fetch existing Claude review threads to enable thread continuity:
91103
92- **Prioritize** (things that slip through):
93- - Missing/inadequate tests (especially E2E for container interactions)
94- - Type safety violations (see CLAUDE.md TypeScript standards)
95- - Architecture violations (see CLAUDE.md patterns: client pattern, DI, layer separation)
96- - API design issues (see CLAUDE.md API Design: unclear naming, missing validation, poor error messages)
104+ ```bash
105+ # Get PR owner and repo name
106+ OWNER=$(gh repo view --json owner --jq '.owner.login')
107+ REPO=$(gh repo view --json name --jq '.name')
108+
109+ # Fetch all review threads
110+ gh api graphql -f query='
111+ query($owner: String!, $name: String!, $pr: Int!) {
112+ repository(owner: $owner, name: $name) {
113+ pullRequest(number: $pr) {
114+ reviewThreads(first: 100) {
115+ nodes {
116+ id
117+ isResolved
118+ path
119+ line
120+ comments(first: 10) {
121+ nodes {
122+ id
123+ databaseId
124+ body
125+ author { login }
126+ }
127+ }
128+ }
129+ }
130+ }
131+ }
132+ }' -f owner="$OWNER" -f name="$REPO" -F pr=${{ github.event.pull_request.number }}
133+ ```
97134
98- **Skip**:
99- - Code style/formatting (Biome handles it)
100- - Changeset reminders (bot handles it)
135+ **Parse the response** - structure is:
136+ ```
137+ .data.repository.pullRequest.reviewThreads.nodes[]
138+ ```
139+
140+ Filter for threads where `comments.nodes[0].author.login` is "claude" or "github-actions[bot]". These are your previous review comments.
141+
142+ **Important notes:**
143+ - `line` can be `null` for file-level comments (not line-specific)
144+ - Use `id` (format: PRRT_xxx) for resolveReviewThread mutations
145+ - Use `databaseId` (format: 2518555173) for comment replies
146+
147+ ### 7. Execute Review
101148
102- ### 7. Post Review
149+ Launch superpowers:code-reviewer subagent (Task tool) with the context gathered above:
150+ - Full PR diff from step 3
151+ - Relevant architecture patterns from CLAUDE.md
152+ - Documentation requirements from step 4
153+ - Previous review feedback (if incremental update from step 2)
154+ - Existing review threads from step 6
155+
156+ The code-reviewer will analyze correctness, architecture, testing, and code quality.
157+
158+ ### 8. Post Review
103159
104160 **Writing style**:
105161 - Be direct. One clear point per issue.
@@ -108,38 +164,75 @@ jobs:
108164 - If issues found: State the issue, reference location, explain why it matters. Move on.
109165
110166 **Format**:
111- - Reference code with file paths and line numbers (e.g., `packages/sandbox/src/file.ts:123`)
112- - Use markdown headings (### for sections) only if you have multiple distinct categories
167+ - **Inline comments**: Use for specific line-by-line code issues (file path, line number, comment)
168+ - **Main comment**: Summary only - overall assessment, architectural concerns, testing strategy, verdict. Do NOT duplicate inline comments here.
169+
170+ **Main comment - write naturally:**
171+ - Start with "## Claude Code Review"
172+ - If previous review exists, write conversationally: "The encoding issue is fixed. Tests look better too."
173+ - Mention what still needs work: "I still see the over-mocking in file-service.test.ts:45"
174+ - New concerns: "New issue: error handling in container.ts doesn't cover..."
175+ - Overall verdict: "Looks good" or "Needs fixes before merge"
176+
177+ **Handle existing threads before submitting new review:**
113178
114- **For incremental reviews** (when updating existing comment):
115- - Acknowledge fixed issues: "✓ [Previous issue] - addressed"
116- - Flag new issues found in new changes
117- - Flag any issues that emerged from holistic view
118- - Keep unaddressed issues from previous review
179+ For each thread from step 6, compare with your new findings:
180+ - **Issue is fixed:** Mark for resolution (save thread ID)
181+ - **Issue persists but needs update:** Mark for reply (save comment database ID)
182+ - **Issue no longer relevant:** Mark for resolution
119183
120- **Posting your review**:
184+ **Submit review as a single cohesive unit:**
121185
122- First, check for existing review comment :
186+ 1. Get the latest commit SHA :
123187 ```bash
124- COMMENT_ID=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments \
125- --jq '.[] | select(.user.login == "claude[bot]") | select(.body | startswith("## Claude Code Review")) | .id' | head -1)
188+ COMMIT_SHA=$(gh pr view ${{ github.event.pull_request.number }} --json headRefOid --jq '.headRefOid')
126189 ```
127190
128- If COMMENT_ID exists (previous review comment found):
129- - Update it: `gh api repos/${{ github.repository }}/issues/comments/$COMMENT_ID -X PATCH -f body="YOUR_REVIEW_HERE"`
130- - Make sure your review starts with "## Claude Code Review" to maintain consistency
191+ 2. Create review.json with ONLY NEW issues (don't duplicate existing thread issues):
192+ ```json
193+ {
194+ "body": "## Claude Code Review\n\nYour overall assessment here...",
195+ "event": "COMMENT",
196+ "commit_id": "COMMIT_SHA_HERE",
197+ "comments": [
198+ {
199+ "path": "path/to/file.ts",
200+ "line": 42,
201+ "body": "Your inline comment here"
202+ }
203+ ]
204+ }
205+ ```
206+
207+ 3. Post the unified review:
208+ ```bash
209+ gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews \
210+ --method POST \
211+ --input review.json
212+ ```
131213
132- If no existing comment:
133- - Create new: `gh pr comment ${{ github.event.pull_request.number }} --body "YOUR_REVIEW_HERE"`
134- - Start your review with "## Claude Code Review" header
214+ 4. **Manage existing threads (after review submission):**
135215
136- For inline code issues:
137- - Use `mcp__github_inline_comment__create_inline_comment` to highlight specific code issues
216+ Resolve fixed issues:
217+ ```bash
218+ gh api graphql -f query='
219+ mutation($threadId: ID!) {
220+ resolveReviewThread(input: {threadId: $threadId}) {
221+ thread { id isResolved }
222+ }
223+ }' -f threadId="THREAD_ID_FROM_STEP_6"
224+ ```
138225
139- Important: Only post GitHub comments - don't submit review text as messages.
226+ Reply to threads that need updates:
227+ ```bash
228+ gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/comments/COMMENT_DATABASE_ID/replies \
229+ --method POST \
230+ -f body="Update: Issue has been partially addressed but..."
231+ ```
140232
141- Your goal: Catch real issues. Respect the developer's time - be concise, but don't omit important details .
233+ **Important**: This workflow maintains conversation continuity - resolved issues show as "Resolved", ongoing issues have threaded replies, and only new issues create new comment threads .
142234
235+ Always post a NEW comment - never update previous ones. Natural conversation flow.
143236 # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
144237 # or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
145- claude_args : ' --allowedTools "mcp__github_inline_comment__create_inline_comment, mcp__cloudflare-docs__search_cloudflare_documentation,mcp__exa__get_code_context_exa,mcp__exa__web_search_exa,Bash(gh pr comment :*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh api:*)"'
238+ claude_args : ' --allowedTools "Task,Skill,Read,Glob,Grep,Write,TodoWrite, mcp__cloudflare-docs__search_cloudflare_documentation,mcp__exa__get_code_context_exa,mcp__exa__web_search_exa,Bash(gh pr view :*),Bash(gh pr diff:*),Bash(gh repo view:*),Bash(gh api:*),Bash(git log:*),Bash(git cat-file:*),Bash(git rev-parse:*),Bash(jq :*)"'
0 commit comments