← スキル一覧に戻る
handling-pr-comments
dsifry / goodtogo
⭐ 27🍴 1📅 2026年1月18日
Deterministic PR readiness detection for AI coding agents
SKILL.md
# handling-pr-comments
Use when addressing PR review feedback, after receiving review comments from CodeRabbit, Cursor, or human reviewers - ensures systematic responses to each comment thread with proper attribution and thread resolution.
## When to Activate
Activate this skill when ANY of these conditions are true:
- User asks to "address PR comments" or "handle review feedback"
- User mentions CodeRabbit, Cursor bot, or reviewer comments
- User is working on fixes requested in a PR review
- User asks to "check PR comments" or "respond to reviewers"
- After making fixes to address review feedback
## CRITICAL: The Complete Workflow
**Most developers forget steps 4-6. This skill ensures they happen.**
### Phase 1: Discover and Filter Comments
First, run `gtg` to get a quick overview of PR status and actionable comments:
```bash
# Get PR status and actionable comments
OWNER=$(gh repo view --json owner -q .owner.login)
REPO=$(gh repo view --json name -q .name)
gtg "$PR_NUMBER" --repo "$OWNER/$REPO" --format json > /tmp/gtg-status.json
# Show status
echo "Status: $(jq -r '.status' /tmp/gtg-status.json)"
echo "Actionable comments: $(jq -r '.actionable_comments | length' /tmp/gtg-status.json)"
echo "Unresolved threads: $(jq -r '.threads.unresolved' /tmp/gtg-status.json)"
# List action items
echo "Action items:"
jq -r '.action_items[]' /tmp/gtg-status.json
```
For detailed filtering and categorization, also run the filtering script:
```bash
# Filter actionable vs non-actionable comments
bin/pr-comments-filter.sh <PR_NUMBER>
```
This script:
- Filters out non-actionable comments (confirmations, acknowledgments, fingerprinting)
- Categorizes actionable comments by priority (Critical → Low)
- Shows comment IDs and details for processing
### Phase 2: Triage Actionable Comments
The filter script categorizes by priority:
| Priority | Marker | Action |
| --------------- | -------------------------------------------------------- | ---------------- |
| 🔴 **CRITICAL** | `_⚠️ Potential issue_ \| _🔴 Critical_` | Fix immediately |
| 🟠 **HIGH** | `_⚠️ Potential issue_ \| _🟠 Major_` | Fix before merge |
| 🟡 **MEDIUM** | `_🟡 Minor_` or `_🛠️ Refactor suggestion_ \| _🟠 Major_` | Should fix |
| 🔵 **LOW** | `_🔵 Trivial_` / `_🧹 Nitpick_` | Fix if quick |
| 👤 **HUMAN** | Non-bot comments | Always process |
For each actionable comment, further categorize as:
1. **Bug/Issue** - Must fix
2. **Enhancement** - Should fix
3. **Nitpick** - Nice to fix
4. **Question** - Needs clarification
5. **Intentional** - Decline with explanation
6. **Out-of-Scope** - See Phase 2b
### Phase 2b: Extract "Outside Diff Range" Comments from Review Bodies (CRITICAL)
**⚠️ COMMONLY MISSED**: CodeRabbit posts "Outside diff range" comments in the **review body**, not as inline threads. These are actionable feedback that MUST be addressed.
```bash
# Extract Outside diff range comments from review bodies
PR_NUMBER=<number>
OWNER=$(gh repo view --json owner -q .owner.login)
REPO_NAME=$(gh repo view --json name -q .name)
echo "=== OUTSIDE DIFF RANGE COMMENTS ==="
gh api "repos/$OWNER/$REPO_NAME/pulls/$PR_NUMBER/reviews" --paginate | \
jq -r '.[] | select(.body | test("Outside diff range"; "i")) |
"Review ID: \(.id)\n\(.body)\n---"'
```
**These comments are NOT in threads** - they cannot be replied to inline. You must:
1. Parse the file paths and line numbers from the review body
2. Address the feedback in your code
3. Commit and push
4. Leave a general PR comment acknowledging you addressed them
### Phase 2c: Handle Other Out-of-Scope Comments
Run the out-of-scope detection script:
```bash
# Detect out-of-scope comments
bin/pr-comments-out-of-scope.sh <PR_NUMBER>
```
This script detects comments that:
- Reference lines NOT in the PR diff
- Are marked "outdated" by GitHub (GraphQL `isOutdated` flag)
- Are general PR discussion comments
**IMPORTANT**: Treat out-of-scope comments as **IN SCOPE** by default.
#### Evaluation Process
Use **ultrathink** to evaluate each out-of-scope comment:
```text
ultrathink: Analyze this out-of-scope review comment:
- What is the reviewer asking for?
- How complex is this change? (lines of code, files affected)
- Does it require refactoring other systems?
- Can I complete this in under 30 minutes?
- Are there any risks or dependencies?
Recommend: FIX_NOW or CREATE_ISSUE
```
#### Decision Matrix
| Criteria | Action |
| --------------------------------------------- | ----------------------------------------- |
| Simple fix (< 30 min, < 3 files, no refactor) | **FIX_NOW** - Make the change immediately |
| Medium complexity (unclear scope) | **ASK_USER** - Present options |
| Major refactor (multiple systems, risky) | **CREATE_ISSUE** - Document for follow-up |
#### For FIX_NOW
1. Make the fix
2. Commit with descriptive message
3. Push to the PR branch
4. Reply: "Fixed in commit <hash>. This was outside the original PR scope but straightforward to address."
5. Resolve the thread
#### For CREATE_ISSUE
1. Create GitHub issue with context
2. Reply: "Created issue #<number> to track this."
3. Resolve the thread
### Phase 3: Make Fixes
Fix the actual code issues. Commit and push.
### Phase 4: RESPOND TO EACH THREAD (Often Forgotten!)
**After pushing fixes, respond to EACH comment thread individually:**
```bash
PR_NUMBER=<number>
OWNER=$(gh repo view --json owner -q .owner.login)
REPO_NAME=$(gh repo view --json name -q .name)
CURRENT_USER=$(gh api user -q '.login')
COMMENT_ID=<id-from-filter-script>
gh api "/repos/$OWNER/$REPO_NAME/pulls/$PR_NUMBER/comments/$COMMENT_ID/replies" \
-X POST \
-f body="Fixed in commit $(git rev-parse --short HEAD).
*(Response by Claude on behalf of @$CURRENT_USER)*"
```
### Phase 5: Resolve ALL Threads
**Every thread must be resolved after responding.** Use GraphQL to resolve:
```bash
THREAD_ID="PRRT_kwDOK-xA485..." # From GraphQL query
gh api graphql -f query='mutation {
resolveReviewThread(input: {threadId: "'"$THREAD_ID"'"}) {
thread { id isResolved }
}
}'
```
### Phase 6: Handle Threads That Can't Be Resolved
1. **Query the comment author** asking for specific follow-up
2. **Do NOT leave unresolved** - either resolve after responding, or ask for clarification
3. If waiting for author response, mark as needing user input
### Phase 7: Post-Push Iteration Check (MANDATORY)
**⚠️ THE #1 WORKFLOW FAILURE: Stopping after Phase 5-6 without checking for NEW comments.**
Automated reviewers (CodeRabbit, Cursor) analyze EVERY commit you push. They post NEW comments during/after their check runs.
```bash
# STEP 1: Wait for ALL CI/CD checks to complete
PR_NUMBER=<number>
echo "⏳ Waiting for CI/CD checks to complete..."
gh pr checks $PR_NUMBER --watch
# STEP 2: Check for NEW comments since your last response
OWNER=$(gh repo view --json owner -q .owner.login)
REPO_NAME=$(gh repo view --json name -q .name)
CURRENT_USER=$(gh api user -q '.login')
# Get timestamp of your last reply
LAST_REPLY=$(gh api "repos/$OWNER/$REPO_NAME/pulls/$PR_NUMBER/comments" --paginate | \
jq -r "[.[] | select(.user.login == \"$CURRENT_USER\") | select(.in_reply_to_id)] | sort_by(.created_at) | last | .created_at")
# Handle case where user has no previous replies
if [ -z "$LAST_REPLY" ] || [ "$LAST_REPLY" = "null" ]; then
echo "⚠️ No previous replies found - checking all comments as new"
LAST_REPLY="1970-01-01T00:00:00Z" # Unix epoch - treat all comments as new
fi
# Check for new comments after that time
NEW_COUNT=$(gh api "repos/$OWNER/$REPO_NAME/pulls/$PR_NUMBER/comments" --paginate | \
jq -r --arg time "$LAST_REPLY" '[.[] | select(.in_reply_to_id == null) | select(.created_at > $time)] | length')
# STEP 3: Also check review bodies for new "Outside diff range" comments
NEW_REVIEWS=$(gh api "repos/$OWNER/$REPO_NAME/pulls/$PR_NUMBER/reviews" --paginate | \
jq -r --arg time "$LAST_REPLY" '[.[] | select(.submitted_at > $time) | select(.body | test("Outside diff range"; "i"))] | length')
TOTAL_NEW=$((NEW_COUNT + NEW_REVIEWS))
if [ "$TOTAL_NEW" -gt 0 ]; then
echo "🚨 $NEW_COUNT NEW INLINE COMMENT(S) + $NEW_REVIEWS NEW REVIEW BODY COMMENT(S) DETECTED"
echo "ACTION: Return to Phase 1 and iterate"
else
echo "✅ No new comments - safe to proceed to verification"
fi
```
**If NEW comments found**: Return to Phase 1. DO NOT proceed to verification.
**Iteration Loop**:
```text
REPEAT:
Phase 1: Discover comments
Phase 2: Triage
Phase 3: Fix
Phase 4: Respond
Phase 5: Resolve threads
Phase 6: Handle unclear threads
Phase 7: Check for NEW comments after push
IF new comments found → GO TO Phase 1
IF no new comments → proceed to verification
```
## Response Templates
### For Fixes Made
```text
Fixed in commit <hash>.
*(Response by Claude on behalf of @username)*
```
### For Acknowledged Nitpicks
```text
Acknowledged - this is a valid suggestion. Deferring to a future cleanup PR to keep this PR focused.
*(Response by Claude on behalf of @username)*
```
### For Intentional Decisions
```text
This is intentional because [reason]. The [thing] is designed to [explanation].
*(Response by Claude on behalf of @username)*
```
## Mandatory Pre-Completion Check
**⚠️ BLOCKING: You MUST run this script and show its output before declaring ANY PR ready:**
```bash
bin/pr-comments-check.sh <PR_NUMBER>
```
This script:
- Returns exit code 0 if all comments addressed
- Returns exit code 1 if ANY unaddressed comments exist
- Shows ✅/❌ status for each comment
**If the script shows ANY ❌, you are NOT done.** Address each unaddressed comment:
1. If actionable → Fix it and reply confirming the fix
2. If out-of-scope → Reply explaining deferral (create issue if needed)
3. If disagree → Reply with reasoning
4. **NEVER ignore silently**
**You must show the script output in your response** as proof that all comments are addressed. Example:
```
🔍 Checking PR #908 for unaddressed comments...
=== Inline Code Review Comments ===
✅ Comment 123 by cursor[bot] - 1 reply(s)
✅ Comment 456 by coderabbitai[bot] - 1 reply(s)
=== General PR Discussion Comments ===
ℹ️ coderabbitai[bot]: <!-- summary -->...
✅ All inline review comments have been addressed
```
A PR is NOT ready until this script returns ✅.
## Verification Checklist
Before declaring PR comments handled:
- [ ] Ran `bin/pr-comments-filter.sh <PR>` to identify actionable comments
- [ ] **⚠️ CRITICAL**: Extracted "Outside diff range" comments from review bodies (Phase 2b)
- [ ] Ran `bin/pr-comments-out-of-scope.sh <PR>` to find other out-of-scope feedback
- [ ] Code fixes have been made and pushed
- [ ] Each comment thread has a response posted
- [ ] "Outside diff range" comments addressed with a general PR comment
- [ ] **⚠️ POST-PUSH CHECK**: Waited for CI/CD to complete, checked for NEW comments
- [ ] **NO new comments found** after the post-push check (iterate if found)
- [ ] **ALL threads have been resolved** (no unresolved threads remaining)
- [ ] All responses include proper attribution
- [ ] Out-of-scope comments have been either fixed OR have GitHub issues created
**⚠️ DO NOT skip the "Outside diff range" check (Phase 2b) - this is the #2 cause of incomplete PR handling.**
## Reference
For the complete detailed workflow with all edge cases and troubleshooting, see:
`.claude/commands/handle-pr-comments.md`