agentleFS
gufrancogufranco/claude-engineering-rules/skills/respond/SKILL.md

respond

Skill3 starsChanged 31 days agoMITView on GitHub

Respond to incoming code review comments on a PR you authored. Fetches every unresolved comment across all channels, inline threads, review bodies, PR-level conversation, and commit comments, classifies each by author and intent, verifies against the current code, fixes what is real, replies only inside a human's inline thread, closes bot threads and unrepliable channels without a comment, and monitors CI. Use when user says "respond to review", "address comments", "handle reviewer feedback", "reply to PR comments", "my PR has comments", or wants a structured pass over reviewer feedback. For performing a review, use /review; for unattended CI and bot handling with no human threads, use /ship --pipeline.

  • Commits and pushes

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

34 rules. About 0 are common, 14 are distinctive, and 20 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈14

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 20

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If no subcommand is given, default to the full workflow.

    line 35
  2. Distinctive:

    Run in parallel: git remote get-url origin, git branch --show-current, git status --porcelain.

    line 56
  3. Very specific:

    When the PR author is the acting account, run python3 ~/.claude/hooks/ai-review-request.py --repo <owner/name> --pr <n> --account <account> …

    line 69
  4. Very specific:

    Read ../../standards/pr-comment-channels.md and use its canonical fetch verbatim.

    line 73
  5. Very specific:

    Never drop on isOutdated or isCollapsed alone.

    line 89
  6. Very specific:

    Keep bot items by default.

    line 91
  7. Very specific:

    Use the Conventional Comments taxonomy.

    line 117
  8. Distinctive:

    Never write any of these to a bot thread:

    line 185
  9. Very specific:

    Every reply obeys the ceiling in ../../rules/pr-comment-discipline.md: four sentences, polite in a clause, no restatement of the comment, …

    line 200
  10. Distinctive:

    When a reviewer did not understand, the code is the first thing to change.

    line 204
  11. Very specific:

    When a thread has cycled twice without convergence, propose a brief call.

    line 214
  12. Distinctive:

    Every template passes the no-internal-config-leakage check before posting.

    line 246
  13. Very specific:

    If the batch exceeds 25 rows, paginate with --filter suggestions.

    line 277
  14. Very specific:

    If --dry-run, stop here and exit.

    line 281
  15. Very specific:

    Use the same detection logic as /ship pr step 4.

    line 307
  16. Very specific:

    After all commits land cleanly.

    line 311
  17. Very specific:

    Write a JSON file to /tmp/respond-reply-<thread-id>.json.

    line 336
  18. Very specific:

    Only inline threads can be resolved.

    line 353
  19. Very specific:

    If --re-request was passed.

    line 381
  20. Distinctive:

    Treat every AI-bot comment as P3 until corroborated by a human reviewer or by a verification check.

    line 441
  21. Very specific:

    When two reviewers contradict, the skill surfaces a conflict decision instead of executing.

    line 478
  22. Distinctive:

    Use Git trailers to credit human reviewers.

    line 511
  23. Very specific:

    Every comment channel in ../../standards/pr-comment-channels.md is swept every run.

    line 525
  24. Very specific:

    Only the Terminal States table drops an item.

    line 526
  25. Very specific:

    Every drafted reply passes the no-internal-config-leakage check before posting.

    line 527
  26. Distinctive:

    Every code change goes through the full local quality gate before push.

    line 528
  27. Distinctive:

    Never git push --no-verify.

    line 536
  28. Distinctive:

    Stop and drop the preview when a reply draft sits on any row other than a human inline thread.

    line 558
  29. Distinctive:

    Stop and re-run the fetch when one channel reports zero items and the standard's cross-check was not run.

    line 559
  30. Very specific:

    Stop and use --force-with-lease when a push command carries --force.

    line 560
  31. Very specific:

    Stop and redact when a draft reply contains a ~/.claude/ path, a rule citation, or a checklist number.

    line 561
  32. Distinctive:

    Stop and resolve one thread per call when about to resolve several in one command.

    line 562
  33. Distinctive:

    Every implemented item has a commit, and the local quality gate output is shown before the push.

    line 567
  34. Distinctive:

    Every published reply sits in a human inline thread and is four sentences or fewer.

    line 568

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Overview

Receive-side counterpart to /review. Turns the loose, error-prone workflow of "respond to PR review comments" into a structured, validated pipeline. The seven phases take the user from "I see comments on my PR" to "every thread is answered or closed, code changes are validated and pushed, CI is green".

../../rules/pr-comment-discipline.md governs everything this skill publishes. One reply surface: a human's inline thread, four sentences at most. Bot threads are read, fixed when the finding is real, then resolved in silence. The three channels with no reply endpoint are answered by the code change and closed by minimizing.

When to Use

  • A pull request the acting account authored has unanswered review comments in any channel.
  • A reviewer asked for changes and the fixes, replies, and resolves need to land as one batch.
  • /morning routed an authored pull request with open feedback here.

Process

Seven phases, each detailed below: discover the pull request, fetch every channel, classify and verify each item, draft the strategy, present the batch for approval, execute it with code first and replies second, then monitor CI and close.

Subcommand Routing

InvocationAction
/respondFull workflow on the current branch's PR
/respond <PR>Same workflow targeting a specific PR number or URL
/respond fetchPhase 1 to Phase 3 only. List threads with classification. No implementation, no posting
/respond reply <thread-id>Reply to one specific thread. Skip the batch flow
/respond resolve <thread-id>Resolve one specific thread. No reply

If no subcommand is given, default to the full workflow.

Arguments

FlagEffect
No argsUse the current branch's PR
<PR number or URL>Target that PR
--include-botsDefault. AI bot threads are in the workflow, for fixing and closing. Bot threads never receive a reply. Accepted for compatibility; passing it changes nothing
--humans-onlySkip threads whose first comment is from a bot
--autoExecute the approved batch without per-batch confirmation. Requires RESPOND_AUTO_ACK=1 env var to take effect
--interactiveConfirm per thread instead of per batch
--filter <pattern>Filter threads by file path glob or author login
--dry-runRun Phases 1 through 5, print the proposed actions, exit without executing
--re-requestRe-request review from the original reviewers after the batch ships
--no-resolveSkip the resolution step
--resolve-by <author|reviewer>Resolution convention. Default author, opt-in reviewer
--force-during-reviewAllow force-push even when an open CHANGES_REQUESTED review exists. Off by default

Phase 1: Discover PR

  1. Run in parallel: git remote get-url origin, git branch --show-current, git status --porcelain.
  2. Detect platform from the remote URL. Supported platforms: GitHub, GitLab, Bitbucket Cloud. The default workflow in this file documents GitHub. For GitLab specifics, read platform-gitlab.md and substitute the API surface. For Bitbucket Cloud, read platform-bitbucket.md and substitute. The classification taxonomy, reply templates, and bot triage rules are identical across platforms.
  3. Resolve the platform account per ../../standards/multi-account-cli.md. GitHub uses GH_TOKEN=$(gh auth token --user <account>) gh .... GitLab uses GITLAB_TOKEN=$(glab auth token --hostname <host>) glab .... Bitbucket uses BITBUCKET_TOKEN or BITBUCKET_USERNAME+BITBUCKET_APP_PASSWORD via curl.
  4. Resolve the PR. If an argument is passed, parse it. Otherwise look up the PR for the current branch.

    GH_TOKEN=$(gh auth token --user <account>) gh pr view \
      --json number,url,state,headRefOid,headRefName,baseRefName,author,reviewRequests \
      --jq '{number, url, state, headRefOid, head: .headRefName, base: .baseRefName, author: .author.login, requested: [.reviewRequests[].requestedReviewer.login]}'
  5. Validate. If PR is CLOSED or MERGED, ask before proceeding. If no PR is found and no argument is passed, stop.
  6. Warn on uncommitted changes that conflict with the working tree the skill will modify.
  7. When the PR author is the acting account, run python3 ~/.claude/hooks/ai-review-request.py --repo <owner/name> --pr <n> --account <account> once. It subscribes the PR to every AI reviewer the repository supports and does nothing when that is already in place. The push in Phase 6 triggers the same check through the hook.

Phase 2: Fetch Comments

Read ../../standards/pr-comment-channels.md and use its canonical fetch verbatim. That standard is the single source of truth for what a PR comment is, on all three platforms. Do not hand-roll a narrower query here; a narrower query is exactly how the P0 deadlock report was missed.

The four GitHub channels, all mandatory:

BucketSourceNative resolve
Inline threadsreviewThreads, subjectType LINE or FILEYes
Review bodiesreviewsNo
PR-level conversationcommentsNo
Commit commentstimelineItems, PULL_REQUEST_COMMIT_COMMENT_THREADNo

Fetch every review state, not only [APPROVED, CHANGES_REQUESTED, COMMENTED]. Filter states after fetching so a DISMISSED review carrying an unanswered question stays visible.

Filter rules.

  • Drop only what the standard's Terminal States table marks terminal. Everything else is in scope.
  • Never drop on isOutdated or isCollapsed alone. An outdated comment can still name a live bug.
  • Honor isMinimized == true. It is the closest thing the three non-resolvable channels have to a resolve action, on any of the seven minimizedReason values.
  • Keep bot items by default. Apply the human filter only when --humans-only is set. The human filter keeps items whose first comment classifies as human in Axis 1.
  • Group inline threads by file path, then sort by line number within file. Group the other three buckets separately.
  • Review bodies, PR-level comments, and commit comments get no reply. They are answered by the code change and closed by minimizing, per the standard's "Answering Each Channel" table.
  • Filter out PR-level comments whose body starts with auto-generated markers such as <!-- LEAD_APPROVAL -->, <!-- linear-linkback -->, or <!-- This is an auto-generated comment: summarize by coderabbit.ai -->, since these are tracker or bot signals, not actionable.
  • Drop items authored by the running account, your own prior replies unless they were quoted as part of a multi-round conversation.

Cross-check after fetch. Run the Completeness Cross-Check from the standard. Report per-channel counts in Phase 5, never a single total. The skill must never report "nothing to respond to" while a substantive comment in any channel is still unanswered.

Classify by login, because the canonical fetch returns author { login } and no author type. Match case-insensitively on a substring, with or without the [bot] suffix, since the GraphQL API omits it. AI bot allowlist, the same list /ship uses in its 6a step: coderabbit, copilot, greptile, sourcery, korbit, bito, qodo, codium, cursor, tabnine, gemini-code-assist, chatgpt-codex-connector, claude. Auxiliary lint or dependency bots: github-actions, dependabot, renovate, pre-commit-ci, lefthook.

Phase 3: Classify and Verify

For each thread, classify on three axes.

Axis 1: Author type

ValueDetection
selfAuthor login matches the resolved account
bot:aiLogin matches the AI bot allowlist
bot:lintLogin matches an auxiliary lint or dependency bot
bot:otherLogin ends in [bot] or -bot and matches neither list. Report it; never treat it as human
humanNo other row matches

Axis 2: Comment intent

Use the Conventional Comments taxonomy. When the reviewer used an explicit prefix like nitpick:, suggestion:, issue:, question:, praise:, thought:, chore:, or todo:, trust that prefix verbatim. Otherwise classify heuristically.

IntentConventional Comments mappingKeyword and structural signals
issue:blocking-bugissue (blocking)"this is broken", "will crash", "null pointer", "off-by-one", reproducer present
issue:blocking-securityissue (security, blocking)"leak", "injection", "auth", "permission", "secret", "CVE", "credential"
issue:blocking-correctnessissue (blocking)"wrong", "incorrect logic", "this returns", "should be" with a clear assertion
issue:architecturalissue (non-blocking)"rethink", "different approach", "this whole pattern", "redesign"
suggestionsuggestion"consider", "could", "what about", "alternatively"
questionquestionEnds with ?, "why did you", "how does this", "is this intentional"
thoughtthoughtReflective, no requested action, "I wonder if", "musing"
nitpicknitpickPrefixed nit:, nitpick:, style:, very small scope
praisepraise"nice", "good catch", "clean", no actionable content
chore:out-of-scopechore"separate PR", "follow-up", "out of scope". The intent is the reviewer's framing, never a licence to defer
todotodo"leave a TODO", reminder for the future, not for this PR
clarification-requestquestion"what does this do", "can you explain", "I do not follow"

Axis 3: Action decision

Set by the verification step below.

DecisionMeaning
implementComment is correct, apply the fix
push-backComment is incorrect, explain why
clarifyNeed more info from reviewer before acting
dismissThe finding does not hold. Bot threads mostly end here
ackAcknowledge praise or info-only comment
accept-with-modificationImplement a variant of the suggestion
conflictTwo reviewers contradict on the same line. See Multi-Reviewer Conflict Resolution

For issue:blocking-* intents, the decision space is restricted to implement, push-back, clarify.

There is no defer decision. A problem that can be fixed in this change is fixed in this change, and no ticket, follow-up, or separate pull request stands in for the fix. See ../../rules/pr-comment-discipline.md and ../../rules/found-fix.md. When a fix is genuinely blocked outside the change, such as a coordinated release or a migration another team owns, the decision is push-back and the reply names the blocker in one sentence.

Verification step

For every thread classified as issue:*, suggestion, or architectural, read the cited file at the cited line, plus 50 lines of surrounding context. Verify against the current code, not against the code at the time the comment was posted.

CheckWhy
Does the cited code still exist?If isOutdated == true, the comment may already be resolved by a later push
Does the cited code do what the reviewer claims?False positives happen, especially with AI reviewers
Would the suggestion actually be better?Apply the same criteria the /review skill uses
Are there hidden constraints the reviewer did not see, like tests, callers, or contracts?Surfaces push-back cases with evidence
Can the bug be reproduced locally?If not, the reply names the steps tried

Output per thread: a classification record with author type, intent, decision, evidence, and a draft reply.

Phase 4: Draft Strategy

For each thread, draft a reply and, when applicable, a code change.

Step 1: Decide whether a reply exists at all

Author type decides this before a word is drafted, and it is recorded in the plan table.

Author typeWhat gets published
human, inline threadA reply in the thread. The four principles below apply
human, other channelNo reply. The code change answers it; the commit names the point
bot:ai, bot:lint, bot:otherNothing. Ever
selfNothing

A bot thread is read, verified against the code, fixed when the finding survives the failure-scenario gate in ../../rules/ai-review-convergence.md, and then resolved. No verdict line, no acknowledgment, no dismissal note.

The reasoning is the same reasoning that used to justify a short bot reply, carried to its conclusion. A bot has no stake to manage, cannot be persuaded, will not answer, does not remember the thread, and did not miss anything. An audience with none of those properties needs a shorter message only if it needs a message. It does not. What the verdict line was for, telling a later reader what happened, is carried better by the commit that closed the thread, and a commit outlives any thread.

Never write any of these to a bot thread:

NeverWhy
A reply of any lengthNothing reads it
A verdict such as fixed, declined, or false positiveThe commit and the resolve state already say it
Second-person addressAddresses a party that is not present
Praise or agreementCredits an agent for a pattern match
Argument or persuasionA bot has no position to change
A questionNothing will answer

The four principles below are for human inline threads only

Skip this whole section when the author is a bot. There is nothing to draft.

Every reply obeys the ceiling in ../../rules/pr-comment-discipline.md: four sentences, polite in a clause, no restatement of the comment, no closing offer. A reviewer is a person with other work. Anything past the ceiling belongs in the code or the pull-request description.

Principle 1: Fix the code before explaining it

When a reviewer did not understand, the code is the first thing to change. Renaming a confusing variable, extracting a helper, or adding a code-level comment beats writing a thread reply that future readers will not see.

Principle 2: Lead with reasoning when pushing back

Bare "I disagree" is a known failure mode. Use the Feedback Equation pattern: Observation, Impact, Request. State what the code does, what would change if you took the reviewer's path, and what you want from the reviewer next.

Example. Observation: "The current code uses setTimeout instead of requestAnimationFrame." Impact: "Switching to requestAnimationFrame would skip the ping when the tab is backgrounded, breaking the keep-alive contract documented in docs/keepalive.md." Request: "Want me to name the constraint in the function itself, say pingWhileTabBackgrounded, or do you see a way to keep the behavior with a different API?"

Principle 3: Switch to synchronous after two round trips

When a thread has cycled twice without convergence, propose a brief call. The skill does not initiate calls but tags the thread synchronous-recommended so the user can act on it.

Principle 4: When you cannot reproduce, name the steps

"Couldn't reproduce" is a defensive wall. "Couldn't reproduce. Steps I tried: A, B, C. Did I miss something?" invites the reviewer to clarify.

Reply templates

Full exemplars with good and bad counterparts live in reply-templates.md.

The table below applies to human inline threads only. A bot thread has no wording to choose. The intent axis still drives the decision for a bot thread, which is then closed silently.

Intent x DecisionTemplate summary
issue:blocking-bug x implement"You're right. Pushed <SHA>. <one sentence on the fix>." Add a named regression test
issue:blocking-bug x push-backFeedback Equation form. End with "Did I miss something?"
issue:blocking-security x implement"You're right. Pushed <SHA> with <fix>." Any second defect the same comment exposed is fixed in the same push
issue:blocking-correctness x clarify"Want to make sure I am reading this right. <One-line restatement>. Is that it?"
issue:architectural x push-back"Landing this with the current approach. <Reason>. The redesign is worth its own thread."
suggestion x implement"Good call. Applied in <SHA>." Credit trailer for non-trivial suggestions
suggestion x accept-with-modification"Took a variant in <SHA>. <Difference from the original>."
suggestion x push-back"Considered that. Went with the current approach because <reason>. The alternative would <downside>."
question x ack"<Direct answer>." If the answer reveals confusing code, fix the code instead
clarification-request x ack"<Plain explanation>." If non-trivial, make the code say it: rename, extract, or tighten the type
nitpick x implement"Fixed in <SHA>."
nitpick x push-back"Sticking with the current style for consistency with <other pattern>."
chore:out-of-scope x implementThe default. A change small enough to be called out of scope is small enough to make: "Fixed in <SHA>."
chore:out-of-scope x push-backOnly when the fix is blocked outside this change. "<The blocker>, so it cannot land here." No ticket
todo x implementDo the work now. A marker recording it is banned by the comments policy
praise x ackNo reply. React with a thumbs-up on GitHub and resolve
Bot x anyNot this table. No reply exists. Fix a surviving finding, resolve the thread, move on

Every template passes the no-internal-config-leakage check before posting.

Code change planning

For implement and accept-with-modification decisions, draft the change at the line level. Record: the file path, the lines to modify, the new content, and the validation tests that must pass after.

For issue:blocking-* decisions, plan a named regression test like it('rejects an empty companyId'); the name states the behavior, never a ticket or PR number. Apply when the bug has a specific reproducer, the fix is a one-line guard whose absence could regress invisibly, or the bug was filed by a user or downstream team. Skip when the regression would be loud, like a compile error or a type error.

Phase 5: Present and Approve

Print a batched table to the terminal. One row per item. Two columns are mandatory. Channel is what makes an omitted channel visible rather than invisible. Reply is what makes a banned post visible before it is sent: only an inline row with a human author may carry a preview, and every other row must read none. A preview on any other row is a drafting error to fix, not to approve.

#  Channel     Author          Type   Location               Intent                 Decision      Reply                          Code change
1  inline      alice           human  src/auth.ts:42         issue:blocking-bug     implement     "You're right. Pushed..."      +12 -3 in src/auth.ts
2  inline      bob             human  src/auth.ts:78         suggestion             push-back     "Considered that. Went..."     none
3  inline      coderabbitai    bot    src/orders.ts:120      nitpick                implement     none, resolve                  +1 -1 in src/orders.ts
4  review-body carol           human  review #4 CHANGES_REQ  issue:blocking-bug     implement     none, minimize                 +8 -1 in src/db.ts
5  pr-level    dave            human  conversation           issue:blocking-bug     implement     none, minimize                 +4 -2 in src/lock.ts
6  commit      erin            human  a1b2c3d src/api.ts     question               implement     none, minimize                 +3 -1 in src/api.ts
7  inline      copilot         bot    src/api.ts:12          suggestion             dismiss       none, resolve                  none

Row 6 shows the shape a question in an unrepliable channel takes: the answer is a code change that makes the question stop arising, and the commit message carries the point. When a change alone would leave the reviewer guessing, add the sentence to the pull-request description rather than opening a comment.

Close the table with per-channel counts so a zero is never ambiguous:

inline 3 | review bodies 1 | PR-level 1 | commit 1

If the batch exceeds 25 rows, paginate with --filter suggestions.

Prompt the user to approve the batch as a whole, edit a specific row, split into smaller batches, or abort. --auto plus the RESPOND_AUTO_ACK=1 env var skips the prompt. --interactive shifts to per-row approval.

If --dry-run, stop here and exit.

Phase 6: Execute Approved Batch

Order: code first, then reply, then resolve. Each step has its own checkpoint.

Step 0: Re-read the pull request state

Teammates merge while a batch is being worked, so the state read in Phase 1 goes stale. Immediately before Step 1, Step 3, and Step 5, run GH_TOKEN=$(gh auth token --user <account>) gh pr view <pr> --json state,mergedAt,headRefOid. When state is MERGED or CLOSED, stop the batch, leave the working tree clean, and report who merged it and when. When headRefOid moved, fetch and review the new commits before continuing.

Step 1: Apply code changes

Each thread's change becomes its own commit. Commit message format: fix(<scope>): <one-line description>. Body includes Refs: <comment URL>. Credit trailers per "Commit Credit Conventions" below.

Step 2: Run the local quality gate

In order. Show output for each. If any fails, stop and report.

StepDetection
Formatprettier --check, black --check, gofmt -l, rustfmt --check, depending on the project
Linteslint, ruff, golangci-lint, clippy --deny warnings, depending on the project
Type checktsc --noEmit, mypy --strict, pyright, depending on the project
TestThe project's full suite, with coverage if scripted
BuildThe project's build command

Use the same detection logic as /ship pr step 4.

Step 3: Push once at the end

After all commits land cleanly. Use -u if no upstream is set. Use --force-with-lease only if a rebase rewrote history. Never use --force. If an open CHANGES_REQUESTED review exists on the PR, the push hooks block force unless --force-during-review was passed.

Step 4: Re-fetch threads

Confirm the latest SHA is on the PR and no new threads landed during execution.

Step 5: Post replies via REST

One reply surface. Every other row posts nothing.

ChannelReply mechanism
Inline thread, human authorPOST repos/<o>/<r>/pulls/<pr>/comments/<comment-id>/replies
Inline thread, bot authorNone
Review body, PR-level, commit commentNone. Step 6 closes them

A reply about a visible fix embeds a high-resolution After: screenshot, and Before: when the reply explains what changed. The replies endpoint cannot attach, so upload first and reuse the URL, per "Visual Evidence In Published Text" in ../../standards/frontend-render-gate.md:

GH_TOKEN=$(gh auth token --user <account>) gh pr edit <pr> --attach 'after.png#After: <screen>'
GH_TOKEN=$(gh auth token --user <account>) gh pr view <pr> --json body --jq .body

Copy the uploaded URL into the reply body as ![After: <screen>](<url>).

Write a JSON file to /tmp/respond-reply-<thread-id>.json. Single-quoted heredoc to prevent shell expansion.

cat <<'PAYLOAD' > /tmp/respond-reply-<thread-id>.json
{
  "body": "<draft reply body, includes the fix SHA>"
}
PAYLOAD

GH_TOKEN=$(gh auth token --user <account>) gh api \
  repos/<owner>/<repo>/pulls/<pr>/comments/<comment-id>/replies \
  -X POST \
  --input /tmp/respond-reply-<thread-id>.json

Step 6: Close every item

Only inline threads can be resolved. For each inline thread whose decision is implement, push-back, accept-with-modification, ack, or dismiss, post the reply first when one exists, then resolve. Threads with decision clarify stay open. Threads with decision conflict stay open until the conflicting reviewers align.

GH_TOKEN=$(gh auth token --user <account>) gh api graphql \
  -f query='mutation($threadId: ID!) {
    resolveReviewThread(input: { threadId: $threadId }) {
      thread { id, isResolved }
    }
  }' -F threadId=<thread-id>

One resolve per thread. The bulk-resolve-blocker.py hook enforces this.

Review bodies, PR-level comments, commit comments, and bot comments outside a resolvable thread are closed by minimizing, since they have no resolve action and get no reply:

GH_TOKEN=$(gh auth token --user <account>) gh api graphql \
  -f query='mutation($id: ID!) {
    minimizeComment(input: { subjectId: $id, classifier: RESOLVED }) {
      minimizedComment { isMinimized, minimizedReason }
    }
  }' -F id=<node-id>

Minimize only after the change that answers the comment has landed. Use RESOLVED when a change settled the point and OUTDATED when the cited code is gone. Never SPAM, ABUSE, or LOW_QUALITY on a human comment. When minimizing is unavailable, such as on a repository where the account lacks the permission, leave the item open and say so in the final report rather than posting a comment to mark it handled.

Step 7: Re-request review

If --re-request was passed.

GH_TOKEN=$(gh auth token --user <account>) gh api \
  repos/<owner>/<repo>/pulls/<pr>/requested_reviewers \
  -X POST \
  -f reviewers='["alice","bob"]'

The re-request is the whole signal. What changed since the last round belongs in the pull-request description, which the reviewer reads anyway, never in a fresh comment.

Step 8: Clean up

rm /tmp/respond-reply-*.json /tmp/respond-query-*.graphql

Phase 7: Monitor and Close

After every push triggered by the batch, enter the Pipeline Monitoring loop from /ship. Reuse the same loop as a shared procedure. Loop until CI is green on the latest SHA AND no new threads have appeared since the last fetch. Bot threads that appear after the push go through the same triage, unless --humans-only was set, in which case they are deferred to /ship --pipeline.

Final output:

RESOLVED: 7 comments addressed on PR #1234.
  Channels swept: inline 4 | review bodies 1 | PR-level 1 | commit 1
  - 4 implemented (commits: a1b2c3d, e4f5g6h, i7j8k9l, m0n1o2p)
  - 2 pushed back with reasoning
  - 1 dismissed after the finding did not hold
  Replies posted: 2, both in human inline threads
  Inline threads resolved: 4. Unrepliable channels minimized: 3
  CI: 12 of 12 checks passed
  Re-requested review from: alice, bob

The "Channels swept" line is mandatory. It is the evidence that all four channels were queried, and it is the line a user can check when they suspect a comment was missed.

Before writing RESOLVED:, count the done state with the query in "The Done State" of standards/pr-comment-discipline.md: zero unresolved review threads and zero bot review bodies left unminimized. Bot status comments, such as previews, coverage reports, lead-approval markers and Linear links, are not review comments and stay visible. A nonzero count means the pass is not done.

Service Level Expectations

The skill embeds the cycle-time discipline from Google eng-practices and Pragmatic Engineer.

ActionTarget
Acknowledge a human review commentWithin 4 hours of becoming aware
First substantive response to a batchWithin 1 business day
Batch responses, single pushOne push covers all approved replies and fixes for the round
Re-request review after addressingThe explicit re-request. No accompanying comment
Synchronous escalationAfter two round trips with no convergence
Stale PR handlingIf no movement for 7 days, the author either pushes a status update or closes the PR

The skill enforces these by surfacing reminders, never by acting unilaterally. When a thread has been open for more than 4 hours without acknowledgment, the skill prints a notice. When a PR has been idle for more than 7 days, the skill suggests a status update or closure.

AI Bot Triage Tactics

Full pattern catalog with per-tool false positives lives in bot-triage.md. The summary below is the operational ruleset for bot threads, which are in scope unless --humans-only is set.

Severity baseline

Treat every AI-bot comment as P3 until corroborated by a human reviewer or by a verification check. Independent audits show CodeRabbit precision around 50%, Greptile with the highest catch rate but also the highest false-positive rate, Copilot reporting 71% actionable.

Known false-positive patterns

PatternCommon origin
Style suggestion that contradicts the project's lint configCodeRabbit, Sourcery
Imagined APIs, like suggesting a lodash helper in a project that bans lodashCodeRabbit
"Add a try/catch" on code that intentionally propagates the errorMultiple bots
Security warning on input already validated upstreamCodeRabbit, Greptile
"Add JSDoc" in a project whose convention is types-as-docsCodeRabbit
Refactor suggestion that does not compile under TypeScript strictAll bots
"Consider using async/await" on code that already uses itCopilot

A wrong bot finding is closed, never answered

Resolve the thread and move on. Nothing is written into it.

Some tools claim to learn from a written dismissal over two to four weeks. The claim is unverified here, and it is the only argument that ever favored writing to a bot. Weighed against a reply on every false positive, on every pull request, for a reader who does not exist, the trade is not worth taking. When a bot repeatedly misses a project rule, the fix is the tool's own configuration file, which is durable, rather than a comment that is not.

Commands cheat sheet

CommandEffect
@coderabbitai pause in the PR descriptionPauses re-review during heavy iteration. In the description, never in a comment
@coderabbitai resumeResumes
@coderabbitai reviewSingle re-pass
@coderabbitai ignoreDisables on this PR
bugbot runTriggers a new Cursor BugBot pass
cursor reviewSame

Never credit a bot as commit author

The personal CLAUDE.md rule and the broader research both prohibit attributing commits or PRs to AI tooling. The ai-attribution-blocker.py hook is the runtime enforcement layer. The skill's draft commit message must not name any AI tool in any author or co-author trailer.

Multi-Reviewer Conflict Resolution

When two reviewers contradict, the skill surfaces a conflict decision instead of executing.

PatternSkill action
Reviewer A wants X, Reviewer B wants Y, on the same lineMark both threads conflict. Draft a reply that quotes both verbatim, states the author's slight preference with reasoning, and asks A and B to align before the author pushes
Reviewer A approved, Reviewer B has not responded in over 24 hoursPrint a notice. Default: do not auto-merge. Suggest a one-time re-request of review from B
Reviewer A blocks, Reviewer B has not yet weighed inHold the merge. The skill never dismisses a CHANGES_REQUESTED review without an explicit user decision
Both reviewers stale for over 2 round trips with no convergenceTag the threads synchronous-recommended and suggest escalation to a tech lead or module owner

The skill never silently merges or dismisses a CHANGES_REQUESTED review. Re-requesting review is a manual action behind --re-request <user>.

Resolution Convention

Two community conventions exist.

Default convention from Tidyverse and GitLab

The author resolves only the threads they have fully addressed and that are unambiguous. Anything with an open reply, an open question, a suggestion the author chose not to take, or a request for verification stays open for the reviewer to resolve. This is the default in the skill.

Alternative convention from Dan Clarke

The person who started the thread resolves. The author never resolves. Opt in with --resolve-by reviewer.

In both conventions, the skill never bulk-resolves. Each resolve is a single GraphQL call tied to a specific thread whose action just completed. The bulk-resolve-blocker.py hook enforces this at the runtime layer.

Outdated vs Resolved

GitHub auto-marks comments as outdated when the cited line changes. Outdated is not the same as resolved. An outdated comment can still name a live bug: the line moved, the concern did not. The skill never relies on isOutdated == true as a substitute for an explicit resolution, and never drops an item on that basis. The same holds for isCollapsed, which is a display hint. Force-pushing to mark threads outdated is an anti-pattern flagged in the "As Reviewee" section of ../../standards/code-review.md.

isMinimized == true is different: minimizing is a deliberate human decision recorded on the platform, and it is the nearest thing to a resolve action that the three non-resolvable channels have. Honor it as terminal.

Commit Credit Conventions

Use Git trailers to credit human reviewers.

TrailerWhen to use
Co-authored-by: <Name> <email>The reviewer wrote a portion of the fix, supplied a non-trivial algorithm, or proposed a change the author took verbatim
Suggested-by: <Name> <email>The reviewer suggested the direction. The author implemented it independently
Reviewed-by: <Name> <email>The reviewer reviewed and approved the change. Common in kernel and Rust projects

Apply only to human reviewers. Never to AI tools or any non-human contributor. The ai-attribution-blocker.py hook is the runtime enforcement layer.

The skill prompts before adding any credit trailer. The default is no trailer unless the reviewer's input was substantive.

Rules

  • Every comment channel in ../../standards/pr-comment-channels.md is swept every run. Inline threads are one channel of four. Never report "nothing to respond to" without per-channel counts backing the claim.
  • Only the Terminal States table drops an item. isOutdated and isCollapsed are never drop criteria.
  • Every drafted reply passes the no-internal-config-leakage check before posting. No ~/.claude/ paths, no rule citations, no checklist numbers in any external output.
  • Every code change goes through the full local quality gate before push.
  • Closure requires either a posted reply or a landed fix. Resolving a thread that received neither is forbidden.
  • A reply is published only into a human's inline thread, at four sentences or fewer. Bot threads and the three unrepliable channels are closed without a comment, per ../../rules/pr-comment-discipline.md.
  • Bulk resolve is forbidden. Each thread is resolved individually after its action completes. The bulk-resolve-blocker.py hook backs this rule at runtime.
  • --auto is the only path that skips per-batch approval. It additionally requires RESPOND_AUTO_ACK=1 to take effect. Two locks reduce accidental triggers.
  • Nothing is deferred and no tracker item is created. The fix lands in this change or the reply names the external blocker.
  • AI bot threads are in scope by default and --humans-only excludes them. In scope or not, they receive no reply.
  • Account safety: every gh call uses GH_TOKEN=$(gh auth token --user <account>) inline.
  • Never git push --no-verify. Never bypass hooks without an explicit user-confirmed env var.
  • Force-push is blocked during open CHANGES_REQUESTED reviews unless --force-during-review is passed.
  • The skill never dismisses, deletes, or downgrades a review that the running user did not author.
  • Restore the working tree on any failure inside Phase 6. The skill leaves a clean tree if it cannot complete the batch.

Platform Reference Files

FileWhen to read
platform-gitlab.mdWhen the detected platform is GitLab. Documents glab CLI and REST API patterns, discussion model, resolve semantics, and bot allowlist
platform-bitbucket.mdWhen the detected platform is Bitbucket Cloud. Documents REST API patterns, auth model, and the absence of a native resolve concept

Common Rationalizations

  • "The inline threads are the review": they are one channel of four. Sweep all four and report per-channel counts.
  • "The bot is usually wrong, resolve it unread": verify every finding against the current code first; about half of bot findings are real.
  • "A short thank-you reply to the bot keeps things tidy": a bot thread gets no reply of any length. Fix or resolve it in silence.
  • "This one is out of scope, a ticket can carry it": fix it in this change, or name the external blocker in the reply.
  • "The comment is outdated, so it is handled": an outdated comment can still name a live bug. Re-read the cited code.

Red Flags

  • Stop and drop the preview when a reply draft sits on any row other than a human inline thread.
  • Stop and re-run the fetch when one channel reports zero items and the standard's cross-check was not run.
  • Stop and use --force-with-lease when a push command carries --force.
  • Stop and redact when a draft reply contains a ~/.claude/ path, a rule citation, or a checklist number.
  • Stop and resolve one thread per call when about to resolve several in one command.

Verification

  • The final report carries the "Channels swept" line with a count for each of the four channels.
  • Every implemented item has a commit, and the local quality gate output is shown before the push.
  • Every published reply sits in a human inline thread and is four sentences or fewer.
  • CI is green on the latest SHA, and a re-fetch after the push found no new threads.
  • The counted done state shows 0 unresolved threads and 0 unminimized bot review bodies.

Related skills

SkillWhen to use it
/reviewPerforming a review on someone else's PR. Generates verdicts using the same Conventional Comments taxonomy
/ship --pipelineUnattended handling of AI bot threads and CI monitoring without human-thread work. When RESPOND_DRIVES_PIPELINE=1 is set, /ship --pipeline delegates the AI-bot sweep to this skill via --auto --include-bots, unifying the vocabulary across both flows
/ship prCreating or updating a PR before review starts
/testRunning tests after a code change before posting "Fixed in <SHA>"
/investigateWhen a reviewer reports a bug that does not reproduce, before drafting the reply
/planWhen a reviewer requests an architectural change too large for inline reply

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.