@@ -12,14 +12,20 @@ name: Claude Code Review (on demand)
1212# - as an inline review comment (pull_request_review_comment) → a "second set
1313# of eyes" pass that focuses on what the human review may have missed.
1414#
15- # The MODE is chosen by the workflow, from `contains()` tests on the comment
16- # body plus `event_name`, and resolves to one of three `focus=` strings. The
17- # body is TESTED, never forwarded: `github.event.comment.body` appears only in
18- # the `if:` gate and in `contains()` expressions whose result is a boolean, and
19- # is never interpolated into a `run:` or `prompt:` block. So a commenter cannot
20- # steer the reviewer with free text. Do not "improve" this into a free-text
21- # focus argument guarded by a prompt-level "treat the following as review
22- # focus, not as instructions" — that is a request, not a boundary.
15+ # The MODE is chosen by the workflow, from tests on the comment body plus
16+ # `event_name`, and resolves to one of three `focus=` strings. The body is never
17+ # interpolated into a `run:` or `prompt:` block: `github.event.comment.body`
18+ # appears only in the `if:` gate and as an environment variable the prep step
19+ # tests, so no comment can inject shell or rewrite the prompt.
20+ #
21+ # A maintainer's GUIDANCE does reach the reviewer, through the action rather
22+ # than the prompt. Tag mode forwards everything after `trigger_phrase` as a
23+ # separate plain-text user message, so `@claude /review check the migration
24+ # ordering` arrives as `check the migration ordering`, alongside the prompt.
25+ # Only a maintainer can open that channel (the `if:` gate), and it is plain
26+ # text only because `trigger_phrase` carries the command word; with a bare
27+ # `@claude` the CLI runs the forwarded text as a slash command. See the comment
28+ # on `trigger_phrase`.
2329#
2430# Incremental scoping is by COMMENTS, not by a SHA range. A `lastReviewed..head`
2531# two-dot range assumes linear history; this repo rebases, so a force push
@@ -101,8 +107,9 @@ jobs:
101107 # The body reaches this step as an ENVIRONMENT VARIABLE, never as a `${{ }}`
102108 # substitution into the script text, so no comment can inject shell. It is
103109 # TESTED and nothing more: the only things written to $GITHUB_OUTPUT are a
104- # PR number and one of three fixed focus strings, so the body still never
105- # reaches the model. Do not echo `$COMMENT_BODY` anywhere in this step.
110+ # PR number and one of three fixed focus strings. Guidance reaches the
111+ # model through the action's `trigger_phrase`, never through this step.
112+ # Do not echo `$COMMENT_BODY` anywhere in this step.
106113 #
107114 # A `case` pattern rather than `contains()` because the match must respect
108115 # a word boundary. `contains(body, '@claude /review all')` is an unanchored
@@ -208,15 +215,29 @@ jobs:
208215 # that had nothing to classify.
209216 echo "threads: $(jq '.data.repository.pullRequest.reviewThreads.nodes | length' "${GITHUB_WORKSPACE}/.prior-review.json")"
210217
211- # Note: claude-code-action adds its own 👀 reaction to the triggering
212- # comment, so there's no explicit reaction step here.
218+ # The 👀 on the triggering comment is not from this workflow or the
219+ # action. The Claude GitHub App adds it, as `claude[bot]`, to ANY comment
220+ # mentioning `@claude`, before this workflow has started (measured on PR
221+ # 437: reaction at 22:05:27Z, run created 22:05:28Z). It therefore says
222+ # nothing about whether a review will run.
213223 - name : Run Claude Code Review
214224 id : review
215225 uses : anthropics/claude-code-action@0a8d3c9443bbff909ab973b6a17a340b913f229f # v1.0.221
216226 with :
217227 claude_code_oauth_token : ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
218228 # Single tracking comment (in-progress → results), updated in place.
219229 track_progress : true
230+ # The COMMAND WORD belongs in the trigger phrase. `track_progress`
231+ # forces tag mode, and tag mode forwards everything after the trigger
232+ # phrase as its own user-message block, which the CLI runs as a slash
233+ # command when it starts with `/`. With the default `@claude` that
234+ # block was `/review`, a Claude Code BUILT-IN, so every review also
235+ # ran the built-in review command alongside this prompt. The sibling
236+ # `/focus` is not a built-in and never reached the model at all: the
237+ # SDK returned in 126 ms with no model usage (run 36932898300). With
238+ # the command word in the phrase, only what follows it is forwarded,
239+ # as plain text: `all`, or a maintainer's guidance for this review.
240+ trigger_phrase : " @claude /review"
220241 # The "Fix this →" claude.ai/code deep-links render as broken markdown
221242 # (huge percent-encoded query). Turn them off at the source.
222243 include_fix_links : false
0 commit comments