Skip to content

Auto-address PR reviews: respond, push fixes, resolve threads - #120

Merged
fishjojo merged 5 commits into
mainfrom
claude-auto-address-reviews
Jun 2, 2026
Merged

Auto-address PR reviews: respond, push fixes, resolve threads#120
fishjojo merged 5 commits into
mainfrom
claude-auto-address-reviews

Conversation

@fishjojo

@fishjojo fishjojo commented Jun 2, 2026

Copy link
Copy Markdown
Owner

What this does

Lets Claude automatically respond to PR reviews, push fixes, and resolve the review threads it addressed — no @claude mention required. Motivated by #119, where Codex's review (P1/P2 inline threads) went unhandled because the bot's author_association is NONE and it never mentions @claude.

How it works

1. Auto-trigger on reviews (claude.yml if:)
A submitted pull_request_review now triggers Claude when either:

  • the reviewer is the Codex bot (chatgpt-codex-connector[bot]), or
  • the reviewer is a trusted human (OWNER/MEMBER/COLLABORATOR).

approved/dismissed reviews are skipped. The existing @claude mention path (all four events, trusted authors only) is unchanged. A github.actor != 'claude[bot]' guard prevents self-triggering.

2. allowed_bots
The action skips bot-triggered runs by default, so the Codex bot is added to allowed_bots (scoped, not '*') — otherwise the auto-run is silently skipped.

3. Resolve threads
Thread resolution has no REST endpoint, so the system prompt instructs Claude to:

  • enumerate unresolved threads via gh api graphql (reviewThreads),
  • fix valid findings, run tests, commit & push,
  • reply to each handled thread,
  • and call the resolveReviewThread GraphQL mutation only for threads it actually fixed — disputed/unfixable ones stay open with an explanation.

This uses the already-granted pull-requests: write permission.

4. Loop bounding
A per-PR concurrency group with cancel-in-progress collapses stacked runs (Claude pushes → Codex re-reviews → supersedes the prior run). Full convergence still relies on the reviewer settling; a maintainer can intervene.

Security / cost notes

  • Auto-runs are scoped to the Codex bot + trusted humans — not arbitrary external reviewers (avoids prompt-injection / cost abuse).
  • Every qualifying review spends one Opus run.

Verification

  • YAML + embedded settings JSON parse cleanly; if: parens/brackets balanced.
  • Confirmed the Codex login is exactly chatgpt-codex-connector[bot] (type Bot) via the reviews API.
  • actionlint not run (binary download blocked in this environment) — expression checked by hand.

🤖 Generated with Claude Code

Lets Claude automatically handle review feedback without an @claude
mention. A submitted PR review now triggers the workflow when the
reviewer is the Codex bot or a trusted human (OWNER/MEMBER/COLLABORATOR);
approved/dismissed reviews are skipped. The @claude mention path is
unchanged.

- Broaden the job 'if:' with a second (no-mention) trigger branch, and
  guard against self-triggering via github.actor != 'claude[bot]'.
- Add a per-PR concurrency group (cancel-in-progress) to bound the
  Claude<->reviewer feedback loop.
- Set allowed_bots to the Codex bot so the action does not skip the
  bot-triggered run (it skips bot actors by default).
- Extend the system prompt: enumerate unresolved review threads via
  GraphQL, fix valid findings, run tests, push, reply to each thread,
  and resolve ONLY the threads actually fixed (leave disputed ones open).

Needs pull-requests: write (already granted) for resolveReviewThread.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0dd8af14ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/claude.yml
Only auto-address reviews (the no-@claude path) on PRs opened by
claude[bot]. Reviews on human-authored PRs no longer trigger an Opus
run automatically; maintainers can still invoke Claude there with an
@claude mention. This narrows scope and further bounds the
Claude<->reviewer loop.

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

fishjojo commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@claude address codex's review

@claude

claude Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Claude finished @fishjojo's task in 5m 13s —— View job


Addressing Codex's review

  • Read the workflow and Codex's P1 finding
  • Verify how claude-code-action@v1 selects tag vs. agent mode when prompt is empty
  • Decide on a fix for the no-mention auto-review path
  • Prepare the change (patch below — I can't push .github/workflows/, so please apply it manually)

Codex's P1 is correct — confirmed in the action source

I traced anthropics/claude-code-action@v1. For a pull_request_review with no @claude mention and no prompt:

  1. src/modes/detector.ts — review events return tag mode only if (checkContainsTrigger(context)) (i.e. an @claude mention). With none, it falls through to the final return "agent" (commented "which won't trigger without a prompt").
  2. src/entrypoints/prepare.ts — the run gate is:
    const containsTrigger = modeName === "tag"
        ? isEntityContext(context) && checkContainsTrigger(context)
        : !!context.inputs?.prompt;        // agent mode
    if (!containsTrigger) { /* skip */ }
    In agent mode with an empty prompt this is falsethe run is skipped entirely.
  3. Even if it ran, src/modes/agent/index.ts sets promptContent = context.inputs.prompt || "Repository: owner/repo" and claudeCommentId: undefined — so no PR/review context and no tracking comment.

So the intended no-mention auto-address path would silently no-op. (The actor check is fine: checkHumanActor honors allowed_bots, so the Codex bot passes.)

Fix

Set a prompt only for the no-mention auto-review case. A non-empty prompt selects agent mode and makes containsTrigger true, so the run proceeds with the PR number + task in-context. Every other trigger (all @claude paths) evaluates to '' → tag mode, unchanged. The detailed thread-handling procedure already lives in --append-system-prompt, which applies in both modes.

Apply this to .github/workflows/claude.yml (replaces the # NOTE: no prompt: comment block, just before the claude_args section):

@@ jobs.claude.steps[Run Claude Code].with @@
-          # NOTE: no `prompt:` input. Setting `prompt:` forces the action into
-          # "agent mode", which runs headlessly and does NOT post a reply back to
-          # the issue/PR. Omitting it selects "tag mode", which responds to the
-          # @claude mention and manages a response comment automatically. The
-          # behavioral guidance that used to live in `prompt:` is moved into
-          # `--append-system-prompt` below so tag mode keeps it.
+          # PROMPT / MODE SELECTION.
+          # claude-code-action auto-detects "tag" vs "agent" mode:
+          #   - tag mode (empty prompt + @claude mention): posts/updates a tracking
+          #     comment and auto-fetches PR context. This is the @claude path.
+          #   - agent mode (non-empty prompt): runs headlessly; the prepare step
+          #     only proceeds when `prompt` is non-empty.
+          # A pull_request_review submitted WITHOUT an @claude mention matches
+          # neither the tag trigger (no mention) nor the agent trigger (empty
+          # prompt). With an empty prompt that run is SKIPPED — and even if it ran,
+          # agent mode would only see "Repository: owner/repo" with no PR/review
+          # context. So set a prompt ONLY for that no-mention auto-review case: it
+          # selects agent mode, lets the run proceed, and carries the PR number +
+          # task. Every other trigger yields '' -> tag mode, unchanged. The detailed
+          # thread-handling procedure stays in `--append-system-prompt` below and
+          # applies in both modes.
+          prompt: >-
+            ${{ (github.event_name == 'pull_request_review'
+                 && !contains(github.event.review.body, '@claude'))
+                && format('A pull request review was submitted on PR #{0} of {1} without an @claude mention. Follow the review-handling procedure in your system prompt: enumerate the PR''s unresolved review threads with `gh api graphql`, fix the valid findings, run the relevant tests when you touch code, commit and push to the PR branch, reply to each thread you handled, resolve ONLY the threads you actually fixed, and post one summary comment of what you fixed and what you left open.', github.event.pull_request.number, github.repository)
+                || '' }}
+
           #

Notes

  • The @claude paths (and trusted-human reviews that do mention @claude) keep tag mode with its tracking comment — the expression yields '' for them.
  • '' inside format(...) is escaped as PR''s; the ${{ }} expression spans multiple lines, which is valid (whitespace/newlines inside an expression are ignored by the Actions expression engine).
  • Verified locally: the edited file parses as valid YAML and the prompt key resolves to the expression above.
  • Tradeoff worth knowing: agent mode does not create a managed tracking comment, so on the no-mention path Claude posts its summary via gh instead. If you'd rather keep the tracking-comment UX there too, an alternative is to set both track_progress: true and the same conditional prompt (the track_progress branch in detector.ts forces tag mode for review events, and the non-empty prompt flips checkContainsTrigger to true). I went with the minimal agent-mode change since it most directly matches Codex's suggestion.

I can't commit changes under .github/workflows/ (GitHub App workflow-permission restriction), so this needs to be applied by a maintainer.
claude-auto-address-reviews

Codex P1 (verified against the claude-code-action@v1 source): a
pull_request_review with no @claude mention and no prompt resolves to
agent mode (detector.ts default), and the prepare step skips agent-mode
runs when the prompt is empty (prepare.ts gates on a non-empty prompt).
So the no-mention auto-address path silently no-opped.

Set a conditional 'prompt' that is non-empty ONLY for the no-mention
pull_request_review case. A non-empty prompt selects agent mode and makes
checkContainsTrigger true (trigger.ts: prompt provided -> always trigger),
so the run proceeds with the PR number + task in context. Every other
trigger evaluates to '' -> tag mode, unchanged. The prompt also tells
Claude to 'gh pr checkout' the PR branch first, since the run starts on
the base branch in this event. The detailed thread-handling procedure
remains in --append-system-prompt and applies in both modes.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a5782d1b95

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/claude.yml Outdated
Comment thread .github/workflows/claude.yml Outdated
Two follow-up findings on the auto-address-review path:

1. Body-only review feedback (P2): the auto prompt only told Claude to
   enumerate inline reviewThreads, so a COMMENTED/CHANGES_REQUESTED review
   whose feedback lives only in the top-level review body would be missed
   (the body is not a review thread, and agent mode does not auto-fetch
   the triggering review). Pass github.event.review.body into the prompt
   and instruct Claude to address it in addition to inline threads.

2. Over-broad concurrency (P2): the per-PR group with cancel-in-progress
   would cancel an in-flight @claude mention run whenever any later event
   hit the same PR/issue. Make the group conditional: a shared per-PR
   group ('claude-autoreview-<pr>') only for the auto-review path so a
   newer review supersedes the in-flight auto-run (the loop bound), and a
   unique group ('claude-mention-<id>') keyed by the triggering
   comment/review/issue id for mention runs so they always run to
   completion.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99366cf9fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/claude.yml Outdated
Codex P2: the workflow-level concurrency group is evaluated before the
job-level if, so an ineligible pull_request_review (approved/dismissed,
untrusted reviewer, non-Claude PR, or an @claude mention) still mapped to
the shared 'claude-autoreview-<pr>' group and, with cancel-in-progress,
would cancel a legitimate in-flight auto-fix run before its own job was
skipped.

Duplicate the auto-path eligibility checks from the job 'if' into the
group expression: only reviews the job would actually accept for the auto
path share 'claude-autoreview-<pr>'; every other event gets a unique
'claude-solo-<id>' group and cancels nothing. Added a comment to keep the
two predicates in sync.

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

fishjojo commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@fishjojo
fishjojo merged commit 23e45d1 into main Jun 2, 2026
11 checks passed
@fishjojo
fishjojo deleted the claude-auto-address-reviews branch June 19, 2026 21:18
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