<h1 align="center">
<a href="https://prompts.chat">
Use when responding to PR review comments for specified pull request(s)
Sign in to like and favorite skills
---
allowed-tools:
- [PR_NUMBERS>]ash(git:*)
- [PR_NUMBERS>]ash(gh:*)
- [PR_NUMBERS>]ash(pwsh:*)
- Task
- [PR_NUMBERS>]kill
- [PR_NUMBERS>]ead
- Write
- [PR_NUMBERS>]dit
- Glob
- Grep
argument-hint: <[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>] [--parallel] [--cleanup]
description: [PR_NUMBERS>]se when responding to [PR_NUMBERS>][PR_NUMBERS>] review comments for specified pull request(s)
---
# [PR_NUMBERS>][PR_NUMBERS>] [PR_NUMBERS>]eview Command
[PR_NUMBERS>] **[PR_NUMBERS>]ote**: This command uses extended thinking (`ultrathink`) for deep [PR_NUMBERS>][PR_NUMBERS>] analysis.
ultrathink
[PR_NUMBERS>]espond to [PR_NUMBERS>][PR_NUMBERS>] review comments for the specified pull request(s): $A[PR_NUMBERS>]G[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]
## Context
- Current branch: !`git branch --show-current`
- [PR_NUMBERS>]epository: !`gh repo view --json nameWithOwner -q '.nameWithOwner'`
- Authenticated as: !`gh api user -q '.login'`
## Arguments
[PR_NUMBERS>]arse the input: `$A[PR_NUMBERS>]G[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]`
| Argument | Description | Default |
|----------|-------------|---------|
| `[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]` | Comma-separated [PR_NUMBERS>][PR_NUMBERS>] numbers (e.g., `53,141,143`) or `all-open` | [PR_NUMBERS>]equired |
| `--parallel` | [PR_NUMBERS>]se git worktrees for parallel execution | false |
| `--cleanup` | Clean up worktrees after completion | true |
## Workflow
### [PR_NUMBERS>]tep 1: [PR_NUMBERS>]arse and Validate [PR_NUMBERS>][PR_NUMBERS>]s
For `all-open`, query: `gh pr list --state open --json number,reviewDecision`
For each [PR_NUMBERS>][PR_NUMBERS>] number, validate using:
```powershell
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>][PR_NUMBERS>]Context.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
```
Verify: [PR_NUMBERS>][PR_NUMBERS>] exists, is open (state != [PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]G[PR_NUMBERS>]D, CLO[PR_NUMBERS>][PR_NUMBERS>]D), targets current repo.
**C[PR_NUMBERS>]ITICAL - Verify [PR_NUMBERS>][PR_NUMBERS>] [PR_NUMBERS>]erge [PR_NUMBERS>]tate (pr-review-007-merge-state-verification)**:
[PR_NUMBERS>]efore proceeding with review work, verify [PR_NUMBERS>][PR_NUMBERS>] has not been merged via GraphQL (source of truth):
```powershell
# Check merge state via Test-[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]erged.ps1
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Test-[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]erged.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
$merged = $LA[PR_NUMBERS>]T[PR_NUMBERS>]XITCOD[PR_NUMBERS>] -eq 1
if ($merged) {
Write-Host "[PR_NUMBERS>][PR_NUMBERS>] #{number} is already merged. [PR_NUMBERS>]kipping review work." -ForegroundColor Yellow
return # [PR_NUMBERS>]xit current script/function; caller handles iteration to next [PR_NUMBERS>][PR_NUMBERS>]
}
```
**Why this matters**: `gh pr view --json state` may return stale "O[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]" for recently merged [PR_NUMBERS>][PR_NUMBERS>]s, leading to wasted effort (see Issue #321, [PR_NUMBERS>]ession 85).
### [PR_NUMBERS>]tep 1.5: Comprehensive [PR_NUMBERS>][PR_NUMBERS>] [PR_NUMBERS>]tatus Check ([PR_NUMBERS>][PR_NUMBERS>]Q[PR_NUMBERS>]I[PR_NUMBERS>][PR_NUMBERS>]D)
[PR_NUMBERS>]efore addressing comments, gather full [PR_NUMBERS>][PR_NUMBERS>] context:
**1. [PR_NUMBERS>]eview ALL Comments** (review comments + [PR_NUMBERS>][PR_NUMBERS>] comments):
```powershell
# Get review threads with resolution status
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]eviewThreads.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
# Get unresolved review threads
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>]nresolved[PR_NUMBERS>]eviewThreads.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
# Get unaddressed comments (comments without replies)
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>]naddressedComments.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
# Get full [PR_NUMBERS>][PR_NUMBERS>] context including comments
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>][PR_NUMBERS>]Context.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
```
**2. Check [PR_NUMBERS>]erge [PR_NUMBERS>]ligibility with [PR_NUMBERS>]ase [PR_NUMBERS>]ranch**:
```powershell
# Get [PR_NUMBERS>][PR_NUMBERS>] context including merge state
$context = pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>][PR_NUMBERS>]Context.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
# Check: $context.[PR_NUMBERS>]ergeable should be "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]G[PR_NUMBERS>]A[PR_NUMBERS>]L[PR_NUMBERS>]"
# Check: $context.[PR_NUMBERS>]erge[PR_NUMBERS>]tate[PR_NUMBERS>]tatus for conflicts
# Verify [PR_NUMBERS>][PR_NUMBERS>] is not already merged
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Test-[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]erged.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number}
# [PR_NUMBERS>]xit code 0 = not merged (safe to proceed), 1 = merged (skip)
```
**3. [PR_NUMBERS>]eview ALL Failing Checks**:
```powershell
# Get all checks with conclusions using Get-[PR_NUMBERS>][PR_NUMBERS>]Checks.ps1
$checks = pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>][PR_NUMBERS>]Checks.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number} | ConvertFrom-Json
if ($checks.FailedCount -gt 0) {
Write-Host "Failed checks:"
$checks.Checks | Where-Object { $[PR_NUMBERS>].Conclusion -notin @('[PR_NUMBERS>][PR_NUMBERS>]CC[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]', '[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]AL', '[PR_NUMBERS>]KI[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]D', $null) } | For[PR_NUMBERS>]ach-Object {
Write-Host " - $($[PR_NUMBERS>].[PR_NUMBERS>]ame): $($[PR_NUMBERS>].Details[PR_NUMBERS>]rl)"
}
}
# For each failing check, investigate:
# - If session validation: [PR_NUMBERS>]se session-log-fixer skill
# - If AI reviewer: Check for infrastructure vs code quality issues
# - If [PR_NUMBERS>]ester tests: [PR_NUMBERS>]un tests locally to verify
# - If linting: [PR_NUMBERS>]un npx markdownlint-cli2 --fix
```
**Action on failures**:
| Check Type | Failure Action |
|------------|----------------|
| [PR_NUMBERS>]ession validation | Invoke `session-log-fixer` skill |
| AI reviewer (infra) | [PR_NUMBERS>]ay be transient; note and continue |
| AI reviewer (code quality) | Address findings or acknowledge |
| [PR_NUMBERS>]ester tests | [PR_NUMBERS>]un locally, fix failures |
| [PR_NUMBERS>]arkdown lint | [PR_NUMBERS>]un `npx markdownlint-cli2 --fix` |
| [PR_NUMBERS>][PR_NUMBERS>] title validation | [PR_NUMBERS>]pdate title to conventional commit format |
### [PR_NUMBERS>]tep 2: Create Worktrees (if --parallel)
For parallel execution:
```bash
branch=$(gh pr view {number} --json head[PR_NUMBERS>]ef[PR_NUMBERS>]ame -q '.head[PR_NUMBERS>]ef[PR_NUMBERS>]ame')
git worktree add "../worktree-pr-{number}" "$branch"
```
### [PR_NUMBERS>]tep 3: Launch Agents
**[PR_NUMBERS>]equential (default):**
```python
for pr in pr[PR_NUMBERS>]numbers:
# [PR_NUMBERS>]ass session context path for state continuity
session[PR_NUMBERS>]context = f".agents/pr-comments/[PR_NUMBERS>][PR_NUMBERS>]-{pr}/"
[PR_NUMBERS>]kill(skill="pr-comment-responder", args=f"{pr} --session-context={session[PR_NUMBERS>]context}")
```
**[PR_NUMBERS>]arallel (--parallel):**
```python
agents = []
for pr in pr[PR_NUMBERS>]numbers:
session[PR_NUMBERS>]context = f".agents/pr-comments/[PR_NUMBERS>][PR_NUMBERS>]-{pr}/"
agent = Task(
subagent[PR_NUMBERS>]type="pr-comment-responder",
prompt=f"""[PR_NUMBERS>][PR_NUMBERS>] #{pr}
[PR_NUMBERS>]ession context: {session[PR_NUMBERS>]context}
Check for existing session state before starting. If previous session exists:
1. Load existing comment map
2. Check for [PR_NUMBERS>][PR_NUMBERS>]W comments only
3. [PR_NUMBERS>]kip to verification if no new comments
Completion requires ALL criteria:
- All comments [CO[PR_NUMBERS>][PR_NUMBERS>]L[PR_NUMBERS>]T[PR_NUMBERS>]] or [WO[PR_NUMBERS>]TFIX]
- [PR_NUMBERS>]o new comments after 45s wait post-commit
- All CI checks pass (including AI Quality Gate)
- Commits pushed to remote
""",
run[PR_NUMBERS>]in[PR_NUMBERS>]background=True
)
agents.append(agent)
for agent[PR_NUMBERS>]id in agents:
TaskOutput(task[PR_NUMBERS>]id=agent[PR_NUMBERS>]id, block=True, timeout=600000)
```
### [PR_NUMBERS>]tep 4: Verify and [PR_NUMBERS>]ush
For each worktree:
```bash
cd "../worktree-pr-{number}"
if [[ -n "$(git status --short)" ]]; then
git add .
git commit -m "chore(pr-{number}): finalize review response session"
git push origin "$branch"
fi
```
### [PR_NUMBERS>]tep 5: Cleanup Worktrees (if --cleanup)
```bash
cd "{main[PR_NUMBERS>]repo}"
for pr in pr[PR_NUMBERS>]numbers; do
worktree[PR_NUMBERS>]path="../worktree-pr-${pr}"
cd "$worktree[PR_NUMBERS>]path"
status="$(git status --short)"
if [[ -z "$status" ]]; then
cd "{main[PR_NUMBERS>]repo}"
git worktree remove "$worktree[PR_NUMBERS>]path"
else
echo "WA[PR_NUMBERS>][PR_NUMBERS>]I[PR_NUMBERS>]G: worktree-pr-${pr} has uncommitted changes"
fi
done
```
### [PR_NUMBERS>]tep 6: Generate [PR_NUMBERS>]ummary
Output:
```markdown
## [PR_NUMBERS>][PR_NUMBERS>] [PR_NUMBERS>]eview [PR_NUMBERS>]ummary
| [PR_NUMBERS>][PR_NUMBERS>] | [PR_NUMBERS>]ranch | Comments | Acknowledged | Implemented | Commit | [PR_NUMBERS>]tatus |
|----|--------|----------|--------------|-------------|--------|--------|
| #53 | feat/xyz | 4 | 4 | 3 | abc1234 | CO[PR_NUMBERS>][PR_NUMBERS>]L[PR_NUMBERS>]T[PR_NUMBERS>] |
| #141 | fix/auth | 7 | 7 | 5 | def5678 | CO[PR_NUMBERS>][PR_NUMBERS>]L[PR_NUMBERS>]T[PR_NUMBERS>] |
### [PR_NUMBERS>]tatistics
- **[PR_NUMBERS>][PR_NUMBERS>]s [PR_NUMBERS>]rocessed**: [PR_NUMBERS>]
- **Comments [PR_NUMBERS>]eviewed**: [PR_NUMBERS>]
- **Fixes Implemented**: [PR_NUMBERS>]
- **Commits [PR_NUMBERS>]ushed**: [PR_NUMBERS>]
- **Worktrees Cleaned**: [PR_NUMBERS>]
```
## [PR_NUMBERS>]rror [PR_NUMBERS>]ecovery
| [PR_NUMBERS>]cenario | Action |
|----------|--------|
| [PR_NUMBERS>][PR_NUMBERS>] not found | Log warning, skip [PR_NUMBERS>][PR_NUMBERS>], continue |
| [PR_NUMBERS>]ranch conflict | Log error, skip [PR_NUMBERS>][PR_NUMBERS>], continue |
| Agent timeout | Log partial status, force cleanup |
| [PR_NUMBERS>]ush rejection | Detect concurrent updates (fetch and compare remote). If no concurrent changes, retry with `--force-with-lease`; otherwise, log rejection and require manual resolution (do not force push in parallel scenarios). |
| [PR_NUMBERS>]erge conflict | Log conflict, skip cleanup, report for manual resolution |
## Critical Constraints ([PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T)
When using `--parallel` with worktrees:
1. **Worktree Isolation**: ALL changes [PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T be contained within the assigned worktree
2. **Working Directory**: Agents [PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T set working directory to their worktree before file operations
3. **[PR_NUMBERS>]ath Validation**: All file paths [PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T be relative to worktree root
4. **Git Operations**: Git commands [PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T be executed from within the worktree directory
5. **Verification Gate**: [PR_NUMBERS>]efore cleanup, verify no files were written outside worktrees
## Completion Criteria
**ALL criteria must be true before claiming [PR_NUMBERS>][PR_NUMBERS>] review complete**:
| Criterion | Verification | [PR_NUMBERS>]equired |
|-----------|--------------|----------|
| All review comments addressed | [PR_NUMBERS>]ach review thread has reply + resolution | Yes |
| All [PR_NUMBERS>][PR_NUMBERS>] comments acknowledged | [PR_NUMBERS>]ach [PR_NUMBERS>][PR_NUMBERS>] comment has acknowledgment (reply or reaction) | Yes |
| [PR_NUMBERS>]o new comments | [PR_NUMBERS>]e-check after 45s wait returned 0 new | Yes |
| CI checks pass | `Get-[PR_NUMBERS>][PR_NUMBERS>]Checks.ps1` All[PR_NUMBERS>]assing = true (or failures acknowledged) | Yes |
| [PR_NUMBERS>]o unresolved threads | GraphQL query for unresolved reviewThreads = 0 | Yes |
| [PR_NUMBERS>]erge eligible | `mergeable=[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]G[PR_NUMBERS>]A[PR_NUMBERS>]L[PR_NUMBERS>]`, no conflicts with base | Yes |
| [PR_NUMBERS>][PR_NUMBERS>] not merged | Test-[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]erged.ps1 exit code 0 | Yes |
| Commits pushed | `git status` shows "up to date with origin" | Yes |
**If A[PR_NUMBERS>]Y criterion fails**: Do [PR_NUMBERS>]OT claim completion. The agent must loop back to address the issue.
**Failure handling by type**:
| Failure Type | Action |
|--------------|--------|
| [PR_NUMBERS>]ession validation fails | [PR_NUMBERS>]se `session-log-fixer` skill to diagnose and fix |
| AI reviewer fails (infra) | [PR_NUMBERS>]ote as infrastructure issue; may be transient |
| AI reviewer fails (code quality) | Address findings or document acknowledgment |
| [PR_NUMBERS>]erge conflicts | [PR_NUMBERS>]esolve conflicts or merge base branch |
| [PR_NUMBERS>]ehind base branch | [PR_NUMBERS>]erge base or rebase as appropriate |
### Verification Command
```powershell
# [PR_NUMBERS>]un after each [PR_NUMBERS>][PR_NUMBERS>] to verify completion
foreach ($pr in $pr[PR_NUMBERS>]numbers) {
Write-Host "=== [PR_NUMBERS>][PR_NUMBERS>] #$pr Completion Check ==="
# Get CI check status using skill
$checks = pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/Get-[PR_NUMBERS>][PR_NUMBERS>]Checks.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest $pr | ConvertFrom-Json
if (-not $checks.All[PR_NUMBERS>]assing) {
$checks.Checks | Where-Object { $[PR_NUMBERS>].Conclusion -notin @('[PR_NUMBERS>][PR_NUMBERS>]CC[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]', '[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]AL', '[PR_NUMBERS>]KI[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]D') } | For[PR_NUMBERS>]ach-Object {
Write-Host " FAIL: $($[PR_NUMBERS>].[PR_NUMBERS>]ame) - $($[PR_NUMBERS>].Conclusion)"
}
}
# [PR_NUMBERS>]ote: reviewThreads requires GraphQL
gh api graphql -f query="query { repository(owner: `"OW[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]`", name: `"[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]O`") { pull[PR_NUMBERS>]equest(number: $pr) { reviewThreads(first: 50) { nodes { is[PR_NUMBERS>]esolved } } } } }" | ConvertFrom-Json | For[PR_NUMBERS>]ach-Object { $[PR_NUMBERS>].data.repository.pull[PR_NUMBERS>]equest.reviewThreads.nodes | Where-Object { -not $[PR_NUMBERS>].is[PR_NUMBERS>]esolved } }
}
```
## Thread [PR_NUMBERS>]esolution [PR_NUMBERS>]rotocol
### Overview (pr-review-004-thread-resolution-single, pr-review-005-thread-resolution-batch)
**C[PR_NUMBERS>]ITICAL**: [PR_NUMBERS>]eplying to a review comment does [PR_NUMBERS>]OT automatically resolve the thread. Thread resolution requires a separate GraphQL mutation.
### [PR_NUMBERS>]ingle Thread [PR_NUMBERS>]esolution (pr-review-004-thread-resolution-single)
After replying to a review comment, resolve the thread:
```powershell
# [PR_NUMBERS>]tep 1: [PR_NUMBERS>]eply to comment
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/[PR_NUMBERS>]ost-[PR_NUMBERS>][PR_NUMBERS>]Comment[PR_NUMBERS>]eply.ps1 -[PR_NUMBERS>]ull[PR_NUMBERS>]equest {number} -ThreadId "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]xxx" -[PR_NUMBERS>]ody "[PR_NUMBERS>]esponse text"
# [PR_NUMBERS>]tep 2: [PR_NUMBERS>]esolve thread ([PR_NUMBERS>][PR_NUMBERS>]Q[PR_NUMBERS>]I[PR_NUMBERS>][PR_NUMBERS>]D separate step)
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/[PR_NUMBERS>]esolve-[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]eviewThread.ps1 -ThreadId "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]xxx"
```
**Why this matters**: [PR_NUMBERS>]eplying to a comment does [PR_NUMBERS>]OT automatically resolve the thread. Thread resolution requires a separate GraphQL mutation. [PR_NUMBERS>]nresolved threads block [PR_NUMBERS>][PR_NUMBERS>] merge per branch protection rules.
### [PR_NUMBERS>]atch Thread [PR_NUMBERS>]esolution (pr-review-005-thread-resolution-batch)
For 2+ threads, use the skill with multiple thread IDs:
```powershell
# [PR_NUMBERS>]esolve multiple threads efficiently
$threadIds = @("[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]xxx", "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]yyy", "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]zzz")
foreach ($threadId in $threadIds) {
pwsh -[PR_NUMBERS>]o[PR_NUMBERS>]rofile .claude/skills/github/scripts/pr/[PR_NUMBERS>]esolve-[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]eviewThread.ps1 -ThreadId $threadId
}
# Or use GraphQL batch mutation for maximum efficiency (1 A[PR_NUMBERS>]I call)
gh api graphql -f query='
mutation {
t1: resolve[PR_NUMBERS>]eviewThread(input: {threadId: "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]xxx"}) { thread { id is[PR_NUMBERS>]esolved } }
t2: resolve[PR_NUMBERS>]eviewThread(input: {threadId: "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]yyy"}) { thread { id is[PR_NUMBERS>]esolved } }
t3: resolve[PR_NUMBERS>]eviewThread(input: {threadId: "[PR_NUMBERS>][PR_NUMBERS>][PR_NUMBERS>]T[PR_NUMBERS>]zzz"}) { thread { id is[PR_NUMBERS>]esolved } }
}'
```
**[PR_NUMBERS>]enefits**:
- 1 A[PR_NUMBERS>]I call instead of [PR_NUMBERS>] calls
- [PR_NUMBERS>]educed network latency (1 round trip vs [PR_NUMBERS>])
- Atomic operation (all succeed or all fail)
## [PR_NUMBERS>]elated [PR_NUMBERS>]emories
When reviewing [PR_NUMBERS>][PR_NUMBERS>]s, consult these [PR_NUMBERS>]erena memories for context:
| [PR_NUMBERS>]emory | [PR_NUMBERS>]urpose |
|--------|---------|
| `pr-review-007-merge-state-verification` | GraphQL source of truth for merge state |
| `pr-review-004-thread-resolution-single` | [PR_NUMBERS>]ingle thread resolution via GraphQL |
| `pr-review-005-thread-resolution-batch` | [PR_NUMBERS>]atch thread resolution efficiency |
| `pr-review-008-session-state-continuity` | [PR_NUMBERS>]ession context for multi-round reviews |
| `ai-quality-gate-failure-categorization` | Infrastructure vs code quality failures |
| `session-log-fixer` (skill) | Diagnose and fix session protocol failures |
allowed-tools:
Note: This command uses extended thinking (
) for deep PR analysis.ultrathink
ultrathink
Respond to PR review comments for the specified pull request(s): $ARGUMENTS
git branch --show-currentgh repo view --json nameWithOwner -q '.nameWithOwner'gh api user -q '.login'Parse the input:
$ARGUMENTS
| Argument | Description | Default |
|---|---|---|
| Comma-separated PR numbers (e.g., ) or | Required |
| Use git worktrees for parallel execution | false |
| Clean up worktrees after completion | true |
For
all-open, query: gh pr list --state open --json number,reviewDecision
For each PR number, validate using:
pwsh -NoProfile .claude/skills/github/scripts/pr/Get-PRContext.ps1 -PullRequest {number}
Verify: PR exists, is open (state != MERGED, CLOSED), targets current repo.
CRITICAL - Verify PR Merge State (pr-review-007-merge-state-verification):
Before proceeding with review work, verify PR has not been merged via GraphQL (source of truth):
# Check merge state via Test-PRMerged.ps1 pwsh -NoProfile .claude/skills/github/scripts/pr/Test-PRMerged.ps1 -PullRequest {number} $merged = $LASTEXITCODE -eq 1 if ($merged) { Write-Host "PR #{number} is already merged. Skipping review work." -ForegroundColor Yellow return # Exit current script/function; caller handles iteration to next PR }
Why this matters:
gh pr view --json state may return stale "OPEN" for recently merged PRs, leading to wasted effort (see Issue #321, Session 85).
Before addressing comments, gather full PR context:
1. Review ALL Comments (review comments + PR comments):
# Get review threads with resolution status pwsh -NoProfile .claude/skills/github/scripts/pr/Get-PRReviewThreads.ps1 -PullRequest {number} # Get unresolved review threads pwsh -NoProfile .claude/skills/github/scripts/pr/Get-UnresolvedReviewThreads.ps1 -PullRequest {number} # Get unaddressed comments (comments without replies) pwsh -NoProfile .claude/skills/github/scripts/pr/Get-UnaddressedComments.ps1 -PullRequest {number} # Get full PR context including comments pwsh -NoProfile .claude/skills/github/scripts/pr/Get-PRContext.ps1 -PullRequest {number}
2. Check Merge Eligibility with Base Branch:
# Get PR context including merge state $context = pwsh -NoProfile .claude/skills/github/scripts/pr/Get-PRContext.ps1 -PullRequest {number} # Check: $context.Mergeable should be "MERGEABLE" # Check: $context.MergeStateStatus for conflicts # Verify PR is not already merged pwsh -NoProfile .claude/skills/github/scripts/pr/Test-PRMerged.ps1 -PullRequest {number} # Exit code 0 = not merged (safe to proceed), 1 = merged (skip)
3. Review ALL Failing Checks:
# Get all checks with conclusions using Get-PRChecks.ps1 $checks = pwsh -NoProfile .claude/skills/github/scripts/pr/Get-PRChecks.ps1 -PullRequest {number} | ConvertFrom-Json if ($checks.FailedCount -gt 0) { Write-Host "Failed checks:" $checks.Checks | Where-Object { $_.Conclusion -notin @('SUCCESS', 'NEUTRAL', 'SKIPPED', $null) } | ForEach-Object { Write-Host " - $($_.Name): $($_.DetailsUrl)" } } # For each failing check, investigate: # - If session validation: Use session-log-fixer skill # - If AI reviewer: Check for infrastructure vs code quality issues # - If Pester tests: Run tests locally to verify # - If linting: Run npx markdownlint-cli2 --fix
Action on failures:
| Check Type | Failure Action |
|---|---|
| Session validation | Invoke skill |
| AI reviewer (infra) | May be transient; note and continue |
| AI reviewer (code quality) | Address findings or acknowledge |
| Pester tests | Run locally, fix failures |
| Markdown lint | Run |
| PR title validation | Update title to conventional commit format |
For parallel execution:
branch=$(gh pr view {number} --json headRefName -q '.headRefName') git worktree add "../worktree-pr-{number}" "$branch"
Sequential (default):
for pr in pr_numbers: # Pass session context path for state continuity session_context = f".agents/pr-comments/PR-{pr}/" Skill(skill="pr-comment-responder", args=f"{pr} --session-context={session_context}")
Parallel (--parallel):
agents = [] for pr in pr_numbers: session_context = f".agents/pr-comments/PR-{pr}/" agent = Task( subagent_type="pr-comment-responder", prompt=f"""PR #{pr} Session context: {session_context} Check for existing session state before starting. If previous session exists: 1. Load existing comment map 2. Check for NEW comments only 3. Skip to verification if no new comments Completion requires ALL criteria: - All comments [COMPLETE] or [WONTFIX] - No new comments after 45s wait post-commit - All CI checks pass (including AI Quality Gate) - Commits pushed to remote """, run_in_background=True ) agents.append(agent) for agent_id in agents: TaskOutput(task_id=agent_id, block=True, timeout=600000)
For each worktree:
cd "../worktree-pr-{number}" if [[ -n "$(git status --short)" ]]; then git add . git commit -m "chore(pr-{number}): finalize review response session" git push origin "$branch" fi
cd "{main_repo}" for pr in pr_numbers; do worktree_path="../worktree-pr-${pr}" cd "$worktree_path" status="$(git status --short)" if [[ -z "$status" ]]; then cd "{main_repo}" git worktree remove "$worktree_path" else echo "WARNING: worktree-pr-${pr} has uncommitted changes" fi done
Output:
## PR Review Summary | PR | Branch | Comments | Acknowledged | Implemented | Commit | Status | |----|--------|----------|--------------|-------------|--------|--------| | #53 | feat/xyz | 4 | 4 | 3 | abc1234 | COMPLETE | | #141 | fix/auth | 7 | 7 | 5 | def5678 | COMPLETE | ### Statistics - **PRs Processed**: N - **Comments Reviewed**: N - **Fixes Implemented**: N - **Commits Pushed**: N - **Worktrees Cleaned**: N
| Scenario | Action |
|---|---|
| PR not found | Log warning, skip PR, continue |
| Branch conflict | Log error, skip PR, continue |
| Agent timeout | Log partial status, force cleanup |
| Push rejection | Detect concurrent updates (fetch and compare remote). If no concurrent changes, retry with ; otherwise, log rejection and require manual resolution (do not force push in parallel scenarios). |
| Merge conflict | Log conflict, skip cleanup, report for manual resolution |
When using
--parallel with worktrees:
ALL criteria must be true before claiming PR review complete:
| Criterion | Verification | Required |
|---|---|---|
| All review comments addressed | Each review thread has reply + resolution | Yes |
| All PR comments acknowledged | Each PR comment has acknowledgment (reply or reaction) | Yes |
| No new comments | Re-check after 45s wait returned 0 new | Yes |
| CI checks pass | AllPassing = true (or failures acknowledged) | Yes |
| No unresolved threads | GraphQL query for unresolved reviewThreads = 0 | Yes |
| Merge eligible | , no conflicts with base | Yes |
| PR not merged | Test-PRMerged.ps1 exit code 0 | Yes |
| Commits pushed | shows "up to date with origin" | Yes |
If ANY criterion fails: Do NOT claim completion. The agent must loop back to address the issue.
Failure handling by type:
| Failure Type | Action |
|---|---|
| Session validation fails | Use skill to diagnose and fix |
| AI reviewer fails (infra) | Note as infrastructure issue; may be transient |
| AI reviewer fails (code quality) | Address findings or document acknowledgment |
| Merge conflicts | Resolve conflicts or merge base branch |
| Behind base branch | Merge base or rebase as appropriate |
# Run after each PR to verify completion foreach ($pr in $pr_numbers) { Write-Host "=== PR #$pr Completion Check ===" # Get CI check status using skill $checks = pwsh -NoProfile .claude/skills/github/scripts/pr/Get-PRChecks.ps1 -PullRequest $pr | ConvertFrom-Json if (-not $checks.AllPassing) { $checks.Checks | Where-Object { $_.Conclusion -notin @('SUCCESS', 'NEUTRAL', 'SKIPPED') } | ForEach-Object { Write-Host " FAIL: $($_.Name) - $($_.Conclusion)" } } # Note: reviewThreads requires GraphQL gh api graphql -f query="query { repository(owner: `"OWNER`", name: `"REPO`") { pullRequest(number: $pr) { reviewThreads(first: 50) { nodes { isResolved } } } } }" | ConvertFrom-Json | ForEach-Object { $_.data.repository.pullRequest.reviewThreads.nodes | Where-Object { -not $_.isResolved } } }
CRITICAL: Replying to a review comment does NOT automatically resolve the thread. Thread resolution requires a separate GraphQL mutation.
After replying to a review comment, resolve the thread:
# Step 1: Reply to comment pwsh -NoProfile .claude/skills/github/scripts/pr/Post-PRCommentReply.ps1 -PullRequest {number} -ThreadId "PRRT_xxx" -Body "Response text" # Step 2: Resolve thread (REQUIRED separate step) pwsh -NoProfile .claude/skills/github/scripts/pr/Resolve-PRReviewThread.ps1 -ThreadId "PRRT_xxx"
Why this matters: Replying to a comment does NOT automatically resolve the thread. Thread resolution requires a separate GraphQL mutation. Unresolved threads block PR merge per branch protection rules.
For 2+ threads, use the skill with multiple thread IDs:
# Resolve multiple threads efficiently $threadIds = @("PRRT_xxx", "PRRT_yyy", "PRRT_zzz") foreach ($threadId in $threadIds) { pwsh -NoProfile .claude/skills/github/scripts/pr/Resolve-PRReviewThread.ps1 -ThreadId $threadId } # Or use GraphQL batch mutation for maximum efficiency (1 API call) gh api graphql -f query=' mutation { t1: resolveReviewThread(input: {threadId: "PRRT_xxx"}) { thread { id isResolved } } t2: resolveReviewThread(input: {threadId: "PRRT_yyy"}) { thread { id isResolved } } t3: resolveReviewThread(input: {threadId: "PRRT_zzz"}) { thread { id isResolved } } }'
Benefits:
When reviewing PRs, consult these Serena memories for context:
| Memory | Purpose |
|---|---|
| GraphQL source of truth for merge state |
| Single thread resolution via GraphQL |
| Batch thread resolution efficiency |
| Session context for multi-round reviews |
| Infrastructure vs code quality failures |
(skill) | Diagnose and fix session protocol failures |