| name | pr-review-merge |
| description | Resolving PR review comments and merging stacked PRs — gathering all feedback, addressing every finding, delegating to expert subagents, managing review states, and merging bottom-to-top |
PR Review and Stack Merge Workflow
Execute this workflow immediately and completely. Do not ask the user whether
to proceed — loading this skill is authorization to act. The goal is: gather all
feedback, address every finding, push fixes, hand off the merge to @github-ops.
Step 1: Gather ALL Feedback
Pull every feedback source before touching any code. All four calls are
mandatory — skipping any of them is incomplete feedback gathering:
mcp__github__pull_request_read (get_comments) # issue-style PR comments ← START HERE
mcp__github__pull_request_read (get_reviews) # review decisions + body
mcp__github__pull_request_read (get_review_comments) # threaded inline comments
mcp__github__pull_request_read (get_status) # CI/check status
get_comments (issue-style PR comments) is listed first because it is the
most commonly skipped and often contains the most important feedback.
Architectural concerns, conceptual objections, and design questions are
typically left as PR comments, not inline review comments. Inline comments
address local code issues. PR comments address the PR as a whole.
These are separate API endpoints. Calling one does not return the other.
A PR with zero inline review comments may still have critical PR comments.
Mandatory: Produce a Full Finding List
Before acting on anything, write out every piece of feedback found across all
four sources. Format:
PR comments (get_comments):
- [author, timestamp]: "[quote or summary]"
- ...
Review decisions (get_reviews):
- [author]: APPROVED / CHANGES_REQUESTED / COMMENTED
"[review body if present]"
Inline comments (get_review_comments):
- [author, file:line]: "[quote or summary]"
- ...
CI status: passing / failing / pending
A later comment may contradict or supersede an earlier one — read everything
before acting on anything.
Step 2: Triage Review States
| State | Action |
|---|
APPROVED | Proceed — still address any inline comments left |
CHANGES_REQUESTED | Must address all findings before merging |
COMMENTED | Non-blocking — use judgment on suggestions |
DISMISSED | Treat as informational |
| No review | User invocation of this skill is sufficient authorization to proceed |
Never merge with unresolved CHANGES_REQUESTED unless a maintainer has
dismissed the review with documented rationale.
Step 3: Address Every Finding — No Exceptions
Every comment has exactly two valid outcomes:
- Fix it — make the change (or a better alternative)
- Track it — create a GitHub issue, reply to the comment with the issue link:
"Good catch. Out of scope here — tracked in #N."
Never silently skip a finding. Never mark a thread resolved without acting on it.
Conflicting feedback: Pick the better approach, post a PR comment explaining
the choice. If it surfaces a genuine design question, create an issue and link it.
Then proceed — do not stall.
Step 4: Delegate to Expert Subagents
Do not solve everything yourself. Spawn the right specialist:
| Finding type | Delegate to | What to pass |
|---|
| Architecture concerns | @architect | Exact quote + file/line + context |
| Security vulnerability | @security-reviewer | Quote + proposed fix to validate |
| Missing/broken tests | @test-engineer | Function/module + scenario from review |
| Docstring/docs gaps | @technical-writer | Function signature + what's missing |
| LLM pipeline issues | @llm-engineer | Quote + chain context |
| Infrastructure/Docker | @devops-engineer | Quote + Dockerfile/compose context |
Security findings are never deferred — fix in this PR.
Step 5: Commit and Push (Push-Minimizing Strategy)
Group fixes logically — not one commit per comment:
git add <files>
git commit -m "fix: address PR #N review comments
- Fix [finding] in src/foo.py
- Add missing tests for [scenario]
- Create issue #M for deferred [concern]"
Never amend — always new commits. Squash-merging will clean history at
merge time. Amending rewrites history reviewers already read.
When to Push
Push is expensive — every push triggers CI runs and bot reviews. Batch all
fixes locally and push once:
- Single PR: Commit all fixes, then
git push once.
- Stacked PRs: Push ONLY the current PR (bottom-up). See "Stack-Aware Push
Strategy" below. Dependent PRs stay local until their turn.
git push
Stack-Aware Push Strategy (CRITICAL for stacked PRs)
When resolving reviews on a stack (P1 → P2 → P3), process one PR at a time,
bottom-up. This prevents wasted CI runs on intermediate state.
Order of operations for the full stack:
- Gather feedback for ALL PRs in the stack (Step 1) — read everything first
- Resolve P1 completely: commit all fixes locally → push once → wait for
CI + bot reviews → iterate if new comments arrive
- Do NOT push P2 or P3 while P1 is in review. You may rebase them locally
to keep them current, but pushing triggers CI on code that will change again.
- After P1 is green/merged, prepare P2:
- Rebase P2 onto updated main (or green P1)
- Address ALL existing review comments on P2 (from Step 1 gathering)
- Run tests/lints locally to verify
- Push once (with
--force-with-lease if rebased)
- Retarget PR base:
gh pr edit <PR2> --base main
- Wait for P2 CI + reviews. Iterate if needed.
- Repeat for P3.
Why: Pushing P2 before P1 is resolved means CI runs on a base that will
change (when P1's fixes land). Bot reviewers comment on intermediate code.
Both are pure waste — you already know P2 will need rebasing after P1 settles.
Step 6: Reply to Every Comment — No Exceptions
After pushing, reply individually to every piece of feedback from the finding
list. Every comment gets exactly one of these replies:
| Outcome | Reply format |
|---|
| Fixed | "Fixed in <commit sha>. [One sentence explaining what changed and why.]" |
| Deferred | "Good catch — out of scope here. Tracked in #N." |
| Intentionally not changed | "Intentionally kept as-is: [reason]. Happy to discuss if you disagree." |
Requires GitHub MCP access — load tools via ToolSearch if not yet available. Use MCP tools directly, not gh api.
PR comments (issue-style) — use mcp__github__add_issue_comment:
mcp__github__add_issue_comment
owner: <owner>
repo: <repo>
issue_number: <pr-number> # PRs share the issue number namespace
body: "Fixed in abc1234. Extracted the validation logic into a separate
validator class as suggested."
Inline review comments — reply to the thread using mcp__github__add_reply_to_pull_request_comment:
mcp__github__add_reply_to_pull_request_comment
owner: <owner>
repo: <repo>
pull_number: <pr-number>
comment_id: <comment_id> # from get_review_comments in Step 1
body: "Fixed in abc1234. Renamed for clarity."
After replying, resolve the thread via gh api (no MCP tool for resolution):
gh api repos/{owner}/{repo}/pulls/comments/{comment_id} \
--method PATCH --field "subjectType=line"
Never resolve a thread without replying first. Resolution without a reply
is invisible — it looks like the comment was acknowledged but leaves no record
of what was done or why.
Work through the finding list item by item. When every comment has a reply,
proceed to the summary.
Step 6b: Leave Summary Comment
gh pr comment <number> --body "Addressed all review comments:
- Fixed [X] (commit abc1234)
- Added tests for [scenario]
- Created #N to track [deferred concern]"
The summary is a high-level roll-up. Individual replies (Step 6) handle the
per-comment accountability. Both are required.
Step 6c: Pre-Merge Conformance Gate (Mandatory)
Before handing off to @github-ops, run @architect-reviewer on the final state of the branch:
Invoke @architect-reviewer with:
- The design document sections relevant to the changed code
- The full PR diff (
gh pr diff <number>)
- The original issue being fixed, if one exists (
gh issue view <N>)
This is a fresh run on the final diff — not a repeat of the pre-PR check. Review cycles can negotiate away spec requirements ("just track it in a follow-up") or fixup commits can inadvertently break a previously CONFORMANT item.
| Finding | Action |
|---|
| All CONFORMANT | Proceed to Step 6d |
| Any PARTIAL | Fix, push, return to Step 5 |
| Any MISSING / DEAD | Fix, push, return to Step 5 — no exceptions |
Step 6d: Bot Review Loop
This project uses automated reviewers. Trigger both before merging:
Claude bot reviews automatically on every push — no action needed.
Gemini bot must be triggered manually:
gh pr comment <number> --body "/gemini review"
Then wait for both bots to complete their reviews. Evaluate:
| Outcome | Action |
|---|
| Both LGTM or COMMENTED only | Proceed to Step 7 |
| Either has CHANGES_REQUESTED | Address all findings (Step 3–5), reply to each comment (Step 6), push, Claude re-reviews automatically, post /gemini review again, repeat from Step 6d |
LGTM from both bots is the merge gate. Do not hand off to @github-ops until this is satisfied.
Step 7: Iterative Merge (One PR at a Time)
Merge the stack bottom-up, one PR per @github-ops invocation. Every push
triggers new bot reviews, so the primary agent must stay in the loop between
merges to address any new findings.
For each PR in the stack (starting from the bottom):
7a. Ensure this PR is merge-ready
Before handing off, verify:
- CI is green (
gh pr checks <number>)
- Bot review loop passed (Step 6d) — no outstanding
CHANGES_REQUESTED or
must-fix findings in the latest bot comments
7b. Hand off ONE PR to @github-ops
@github-ops Merge PR #<current> (squash, delete branch). Then retarget PR
#<next> to main, rebase it onto origin/main, and push with --force-with-lease.
Do NOT wait for reviews on #<next> — just push and return.
For the last PR in the stack (no next PR):
@github-ops Merge PR #<current> (squash, delete branch). This is the last PR
in the stack — no retarget/rebase needed.
7c. Address new reviews on the next PR
After @github-ops returns, the rebased PR has been pushed and new bot reviews
are running. Wait for them, then loop back:
- Gather feedback on the next PR (Step 1 —
get_comments, get_reviews,
get_review_comments, get_status)
- If new blocking findings: address them (Steps 3–6), push, wait for bot
reviews, iterate until clean
- When clean: proceed to Step 7b for this PR
Why one at a time?
@github-ops cannot fix code. If it merges the bottom and then pushes the next
PR, the push triggers bot reviews that may flag new issues. If @github-ops
owns the whole stack, it either merges through blocking reviews (the bug this
fixes) or has to stop and report back (wasting its context on review
interpretation it can't act on). Keeping the primary agent in the loop after
every merge is simpler and more reliable.
Step 8: Store Memories
Call mcp__mem0__add_memory for non-obvious findings from this review cycle:
"PR review pattern in {repo}: {reviewer} flags {pattern}. Prefer {approach}. (PR #{N})"
"Fix for {issue}: {non-obvious solution}. Discovered in PR #{N} review, {repo}."
"Issue #{N} created: {concern} deferred from PR #{M} in {repo}."
Do not store routine style fixes. Store patterns that will save time in future PRs.
Common Pitfalls
- Skipping
get_comments — the most common failure. PR comments contain
architectural and conceptual feedback that inline comments never capture.
A PR can have zero inline comments and still have blocking concerns in get_comments.
- Treating
get_reviews as sufficient — review decisions (APPROVED etc.) are
separate from review body text, which is separate from inline comments, which is
separate from PR comments. Four calls, not one.
- Producing no finding list before acting — without writing out all feedback first,
early findings get acted on before later ones are read, causing contradictions to be missed.
- Marking threads resolved without acting — resolved ≠ addressed
- Merging with CHANGES_REQUESTED outstanding — always check review state explicitly
- Amending commits — breaks reviewers' diff context; always new commits
- Merging top-to-bottom — always merge bottom-to-top for stacked PRs