From e384fcc3b92181307d0d5c67e51029e97e96223f Mon Sep 17 00:00:00 2001 From: Martin Husbyn Date: Fri, 31 Jul 2026 17:01:42 +0100 Subject: [PATCH 1/2] ci: replace review plugin with a direct review prompt Mirror of the flow-api change. The code-review plugin never posts inside claude-code-action (it publishes via 'gh pr comment', which the action's tool sandbox denies). Give the action a direct review prompt that posts via its native inline-comment tool (allowlisted through claude_args), leading with this team's priorities and staying silent on a clean PR. Co-Authored-By: Claude Fable 5 --- .github/workflows/claude-code-review.yml | 52 +++++++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 4f6145b..a5d8915 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -21,8 +21,8 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - pull-requests: read - issues: read + pull-requests: write + issues: write id-token: write steps: @@ -36,9 +36,49 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' - plugins: 'code-review@claude-code-plugins' - prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' + use_sticky_comment: true + prompt: | + Review this pull request as an experienced engineer on this + codebase. This repo's CLAUDE.md is your rubric — follow it, and where + a more specific guideline applies, it wins. + + Priorities, most important first — this is what this team cares about: + 1. Make invalid states unrepresentable. Flag nullable/optional fields + with no real "absent" case, tri-state "omitted vs explicit null" + confusion in partial-update schemas, mode/boolean flags that should + be two functions, and fields only valid together but typed apart. + 2. Tests for new or changed behaviour — especially the negative and + edge cases (invalid input, missing record, empty input, the + default/omitted argument). A missing test for new behaviour is a + finding even when the code looks correct. + 3. Encapsulation — anything exposed that could be private (_-prefixed). + 4. Domain types over bare primitives for ids/paths/urls/tokens/counts, + applied where the value is created, not as casts at call sites. + 5. Reuse over duplication — logic a model, helper, or library already owns. + 6. Simplicity and placement — speculative abstraction, code in the wrong + module, dead code, and comments that state "what" instead of "why". + + Rules of engagement: + - Only comment when you are confident the issue is real and worth the + author's attention. Prefer a few high-value, design-level comments + over many small nits. + - A clean PR is a success. If nothing clears that bar, post NO comments + at all — never invent findings or restate the diff to look thorough. + - Do not report anything a formatter, linter, or type checker catches; + CI runs those. Do not report pre-existing issues on lines this PR + did not change. + + How to post (the PR branch is already checked out here): + - Leave each finding as an inline comment on the specific line with + `mcp__github_inline_comment__create_inline_comment` (pass + `confirmed: true`). Keep each short: what is wrong, why it matters + (cite CLAUDE.md where relevant), and what would resolve it. + - Only if you have findings, add one brief top-level summary with + `gh pr comment`. If the PR is clean, post nothing — call no comment + tool at all. + - Post feedback only through these GitHub tools; do not return review + text as your final message. + claude_args: | + --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)" # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md # or https://code.claude.com/docs/en/cli-reference for available options - From 6eaf01a365ca4632c8ea9d5d2c1b76c89eae96eb Mon Sep 17 00:00:00 2001 From: Martin Husbyn Date: Mon, 3 Aug 2026 17:13:50 +0100 Subject: [PATCH 2/2] ci(review): add implementbot verdict handshake On implementbot PRs (body carries the issue marker) the review always posts a single sticky verdict comment stamped with the head SHA and verdict=clean|changes, even when clean, so implementbot is resumed and converges. Human PRs stay silent-on-clean. Findings are split blocking vs optional (only blocking gates), and cancel-in-progress concurrency keeps only the latest commit's verdict. Co-Authored-By: Claude Fable 5 --- .github/workflows/claude-code-review.yml | 50 +++++++++++++++++++----- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index a5d8915..2966d03 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -10,6 +10,13 @@ on: # - "src/**/*.js" # - "src/**/*.jsx" +# One review per PR at a time: a new push cancels the in-flight review so the +# only verdict that lands is for the latest commit (implementbot keys off the +# verdict's SHA, so stale verdicts must not race the current one). +concurrency: + group: claude-review-${{ github.event.pull_request.number }} + cancel-in-progress: true + jobs: claude-review: # Optional: Filter by PR author @@ -36,12 +43,17 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} - use_sticky_comment: true prompt: | Review this pull request as an experienced engineer on this codebase. This repo's CLAUDE.md is your rubric — follow it, and where a more specific guideline applies, it wins. + Context for posting (do not review these values, just use them): + - Repository: ${{ github.repository }} + - PR number: ${{ github.event.pull_request.number }} + - Head commit SHA: ${{ github.event.pull_request.head.sha }} + - Opened by implementbot: ${{ contains(github.event.pull_request.body, 'implementbot:issue=') }} + Priorities, most important first — this is what this team cares about: 1. Make invalid states unrepresentable. Flag nullable/optional fields with no real "absent" case, tri-state "omitted vs explicit null" @@ -62,8 +74,11 @@ jobs: - Only comment when you are confident the issue is real and worth the author's attention. Prefer a few high-value, design-level comments over many small nits. - - A clean PR is a success. If nothing clears that bar, post NO comments - at all — never invent findings or restate the diff to look thorough. + - Classify each finding as BLOCKING (a real correctness, spec, or + guideline violation that should not merge as-is) or OPTIONAL (a + nice-to-have or minor improvement). Only blocking findings gate. + - A clean PR is a success. Never invent findings or restate the diff to + look thorough. - Do not report anything a formatter, linter, or type checker catches; CI runs those. Do not report pre-existing issues on lines this PR did not change. @@ -71,14 +86,31 @@ jobs: How to post (the PR branch is already checked out here): - Leave each finding as an inline comment on the specific line with `mcp__github_inline_comment__create_inline_comment` (pass - `confirmed: true`). Keep each short: what is wrong, why it matters - (cite CLAUDE.md where relevant), and what would resolve it. - - Only if you have findings, add one brief top-level summary with - `gh pr comment`. If the PR is clean, post nothing — call no comment - tool at all. + `confirmed: true`). Say whether it is BLOCKING or OPTIONAL, then what + is wrong, why it matters (cite CLAUDE.md where relevant), and what + would resolve it. + - Then handle the top-level verdict comment by whether implementbot + opened this PR (see the "Opened by implementbot" value above): + + * If TRUE — always post a verdict, even when the PR is clean, because + implementbot waits for it. Build the body with this exact first line: + `` + using the Head commit SHA above, and `changes` if you left any + BLOCKING finding else `clean`; follow it with one or two sentences + (and "details are inline" when there are findings). Post it as a + single STICKY comment — never a second one: first look for your + previous verdict with + `gh api "repos//issues//comments" --jq 'map(select(.body|startswith("