Get the FREE Ultimate OpenClaw Setup Guide →

resolve-pr-feedback-bubbles

Scanned
npx machina-cli add skill n1ddeh/fantastic-skills/resolve-pr-feedback-bubbles --openclaw
Files (1)
SKILL.md
13.9 KB

Address PR Comments

Discover all active PRs with unresolved review comments, dispatch parallel agents to evaluate and resolve each PR's feedback, then present a summary with drafted replies for approval.

Options

  • --auto-reply — Skip all user confirmation prompts and automatically proceed at every step: PR list confirmation, reply approval (post all drafted replies including disagree), and summary comments. Bubbles handles everything end-to-end without pausing.

Process

Phase 1: Discovery

  1. Find eligible PRs using open-graphite-stacks:

    Invoke the open-graphite-stacks skill to get all open PRs grouped by repo and stack. Filter to PRs where resolvedThreads < totalThreads (i.e., unresolved threads exist). Skip draft PRs (marked [DRAFT]).

  2. Fetch unresolved review threads per PR via GraphQL:

    {
      repository(owner: "{owner}", name: "{repo}") {
        pullRequest(number: {number}) {
          body
          reviewThreads(first: 100) {
            nodes {
              id
              isResolved
              comments(first: 20) {
                nodes {
                  id
                  databaseId
                  body
                  author { login }
                  path
                  line
                }
              }
            }
          }
        }
      }
    }
    

    A PR is eligible if it has any isResolved: false review threads.

  3. Detect local repo paths and extract owner/repo. Resolve repo paths using the following priority order:

    1. Automation clones (preferred — isolated from user's working tree): ~/.claude/repos/{repoName}
    2. User working directories: ~/Documents/projects/**/{repoName}, ~/{repoName}

    Always prefer automation clones when they exist. These are dedicated clones that the skill can modify freely without affecting the user's active work (uncommitted changes, current branch, mid-rebase state). Before using an automation clone, sync it:

    cd {localRepoPath}
    git fetch --all --prune
    

    If an automation clone does not exist for a repo, fall back to the user working directory. If neither is found, skip the repo and report it in the summary.

    For each found repo, extract the GitHub owner and repo name from the git remote:

    git -C {localRepoPath} remote get-url origin
    # git@github.com:YourOrg/your-repo.git → owner=YourOrg, repo=your-repo
    # https://github.com/YourOrg/your-repo.git → owner=YourOrg, repo=your-repo
    

    Parse the URL (SSH or HTTPS) to extract {owner} and {repo}. Use these values in all subsequent GraphQL and REST API calls (gh api repos/{owner}/{repo}/...).

  4. Display the eligible PR list (number, title, repo, comment count) before proceeding. If --auto-reply is set, proceed immediately. Otherwise, wait for user confirmation.

Phase 2: Agent Dispatch

Stacks and standalone PRs are handled differently. Dispatch all agents in parallel:

  • One orchestrator agent per stack (sequential, trunk-to-tip)
  • One agent per standalone PR (parallel, same as before)

Stack Orchestrator Workflow

Each stack orchestrator receives:

  • The ordered list of eligible PRs in the stack (trunk-to-tip), each with unresolved comment details and branch name
  • The local repo path

The orchestrator works through PRs sequentially, starting from position [1] (closest to trunk). For each PR in order:

Step 1 — Get branch:

cd {localRepoPath}
gt get {branchName}

Step 2 — Gather context:

  • Extract Linear ticket ID from branch name (pattern: [A-Z]+-\d+)
  • If found, use the Linear MCP get_issue tool to fetch issue details and list_comments
  • Read the PR description for requirements and scope

Step 3 — Evaluate each unresolved comment (same logic as standalone, see below)

Step 4 — Update and run tests:

  • If any code changes were made, check for related test files and update them if needed
  • Run the relevant tests and verify they pass before proceeding
  • If tests fail, fix the implementation until they pass

Step 5 — Commit:

  • If any code changes were made: gt modify -c -m "[bot] 🐳 address review feedback on PR #{number}"
  • If no code changes, skip

Step 6 — Restack: After committing (or if no changes), run:

gt restack

This rebases all upstack branches onto the new commit. If merge conflicts arise, resolve them before continuing to the next PR.

Step 7 — Move to next PR and repeat Steps 1–6.

Step 8 — Submit the entire stack after all PRs are addressed:

gt submit --stack --no-interactive

Step 9 — Return structured report for all PRs in the stack (same format as standalone report below).


Standalone PR Agent Workflow

Dispatch one Task subagent per eligible standalone PR in parallel. Each agent receives:

  • The PR number, repo, branch name, and local repo path
  • The list of unresolved review thread comments
  • The PR body/description

Step 1 — Create worktree:

cd {localRepoPath}
git fetch origin {branchName}
git worktree add .worktrees/pr-{number} origin/{branchName}

Verify .worktrees/ is gitignored with git check-ignore .worktrees. If not, add it to .gitignore first.

Step 2 — Gather context:

  • Extract Linear ticket ID from branch name (pattern: [A-Z]+-\d+)
  • If found, use the Linear MCP get_issue tool to fetch issue details and list_comments
  • Read the PR description for requirements and scope

Step 3 — Evaluate each unresolved comment:

  1. Read the file at the path referenced by the comment
  2. Read surrounding code — callers (1 level up), types, related files in the same module
  3. Understand the reviewer's intent: code fix request, question, style nit, or architectural concern
  4. Assess merit before acting. For every comment (including concrete code-fix requests), ask:
    • Does this change improve correctness, readability, or safety?
    • Does it align with the Linear ticket's scope and intent?
    • Could it introduce regressions, over-engineering, or unnecessary churn?
    • Is there existing code context the reviewer may not have seen?
  5. Categorize:
    • code-fix — reviewer's request is valid; implement it
    • discussion — architectural concern, question, or open-ended topic that needs a thoughtful reply
    • acknowledged — simple agreement ("good point, fixed")
    • disagree — Bubbles believes the ask is incorrect, out of scope, or would make things worse after careful evaluation
  6. If code-fix: Implement the change, stage it
  7. If disagree: Do NOT implement the change. Instead, draft a reply that:
    • Acknowledges the reviewer's perspective and the concern behind it ("Bubbles can see why this looks like X…")
    • Explains the reasoning for disagreeing — citing specific code context, ticket scope, or downstream effects
    • Offers an alternative if one exists, or explains why the current approach is preferable
    • Keeps the door open ("happy to chat more if Bubbles is missing something!")
    • Tone: warm, curious, never dismissive. Bubbles genuinely wants to understand the reviewer's angle, even when disagreeing.
  8. For all categories: Draft a reply in the voice of Bubbles 🐳. Always prefix with [bot] 🐳 Bubbles and write in third person (e.g., "[bot] 🐳 Bubbles fixed the off-by-one error — i now starts at 0 instead of 1"). For code fixes, confirm what was changed. For discussion, form a position based on code understanding and Linear context. For disagree, follow the guidelines in step 7.

Step 4 — Update and run tests:

  • If any code changes were made, check for related test files and update them if needed
  • Run the relevant tests and verify they pass before proceeding
  • If tests fail, fix the implementation until they pass

Step 5 — Commit and push:

  • If any code changes were made: git add -A && git commit -m "address review feedback on PR #{number}" then git push origin {branchName}
  • If no code changes, skip

Step 6 — Return structured report:

PR #{number} — {title}
URL: {prUrl}
Commit: {sha or "no changes"}

⚠️ Disagreements (review before posting):
1. [disagree] {file}:{line} — @{reviewer}
   Comment: {first 100 chars of body}...
   Bubbles' reasoning: {why Bubbles disagrees}
   Draft reply: [bot] 🐳 Bubbles {the drafted reply text}

Comments:
1. [{category}] {file}:{line} — @{reviewer}
   Comment: {first 100 chars of body}...
   Action: {what was done}
   Draft reply: [bot] 🐳 Bubbles {the drafted reply text}

2. [{category}] ...

Step 7 — Cleanup worktree:

cd {localRepoPath}
git worktree remove .worktrees/pr-{number}

Phase 3: Summary and Approval

After all agents (stack orchestrators and standalone agents) complete:

  1. Present per-PR summary:

    • PR title + URL
    • Comment breakdown: code-fix / discussion / acknowledged counts
    • Commit SHA if code was pushed
    • Each comment with reviewer, snippet, category, action, and draft reply
  2. Reply approval flow:

    • If --auto-reply is set, skip the presentation and post all drafted replies immediately (including disagree)
    • Otherwise, present disagree replies first, grouped separately with a ⚠️ header — these need the most attention
    • Then present all other drafted replies grouped by PR
    • Ask user to approve all, approve individually, edit, or skip
    • Post approved replies (or all replies if --auto-reply) via:
      gh api repos/{owner}/{repo}/pulls/{number}/comments -f body="{reply}" -F in_reply_to={commentDatabaseId}
      
    • After posting each reply, resolve the thread using the GraphQL thread node id:
      gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "{threadNodeId}"}) { thread { isResolved } } }'
      
  3. Post summary comment on each PR:

    After posting replies for a PR, automatically post a top-level PR summary comment (no user confirmation needed). This gives reviewers a single place to see everything Bubbles did.

    The comment must include:

    • The ## [bot] 🐳 Bubbles' Summary heading is always visible
    • Everything else is wrapped in a <details> tag with <summary>What Bubbles did</summary> so it's collapsed by default
    • Stats: comment counts by category (code-fix / discussion / acknowledged / disagree)
    • Commit SHA if code was pushed, or "no code changes" if not
    • A list of each comment addressed with category, file:line, and a one-line summary of the action taken
    • If any disagree items exist, a separate subsection highlighting them with Bubbles' reasoning
    gh api repos/{owner}/{repo}/issues/{number}/comments -f body="$(cat <<'EOF'
    ### [bot] 🐳 Bubbles' Summary
    
    <details>
    <summary>**What Bubbles did**</summary>
    
    | Stat | Count |
    |------|-------|
    | Code fixes | 2 |
    | Discussions | 1 |
    | Acknowledged | 0 |
    | ⚠️ Disagreements | 1 |
    
    **Commit:** `abc1234` — address review feedback on PR #2580
    
    ### Changes made
    - [code-fix] `src/path/File.tsx:42` — Added null check on `user.profile` per @reviewer's catch
    - [discussion] `src/path/Service.ts:88` — Bubbles explained why the retry logic uses exponential backoff here
    - [disagree] `src/path/OtherFile.tsx:15` — Bubbles respectfully pushed back on extracting this to a util (see thread for reasoning)
    
    </details>
    EOF
    )"
    
  4. Re-request reviews:

    After posting replies and the summary comment for each PR, re-request review from the humans who left the addressed comments. This notifies them that Bubbles has responded.

    Collect the unique reviewer logins from the addressed comment threads (exclude the PR author and bots like coderabbitai, graphite-app, github-actions). Then:

    gh api repos/{owner}/{repo}/pulls/{number}/requested_reviewers \
      -f 'reviewers[]=reviewer1' -f 'reviewers[]=reviewer2'
    

    If no human reviewers remain (e.g., all comments were from the PR author or bots), skip this step. Log which reviewers were re-requested in the final report.

  5. Final report:

    ## PR Comments Addressed
    
    ### PR #2580 — PROJ-123 Refactor e2e tests
    - 4 comments: 2 code fixes (pushed abc1234), 1 discussion, ⚠️ 1 disagree
    - Replies: 4 posted
    - Summary comment: posted
    
    ### Skipped
    - PR #2587 — no unresolved comments
    - my-frontend — repo not found locally
    

Important Notes

  • Filter comments by isResolved: false using the GraphQL API (REST API does not expose resolution status)
  • Bot comments (coderabbitai, graphite-app, etc.) should be evaluated like human comments — they often contain valid code fixes
  • Skip comments that are replies (non-root comments in a thread) — only evaluate the root comment of each thread
  • When implementing code fixes, verify the suggestion makes sense in context before applying blindly
  • The in_reply_to field for posting replies uses the REST API databaseId, not the GraphQL node id
  • Stack ordering matters: Always address the trunk-most PR first. Changes to a lower PR affect all branches above it — gt restack propagates them upward
  • Do not post replies for stack PRs until after gt submit --stack — submitting updates the remote branches; replies posted before that may reference stale diffs
  • Stack orchestrators use gt checkout to switch branches directly in the working tree — do NOT use worktrees for stack PRs, as Graphite tracks branch relationships in the repo root
  • Automation clones (~/.claude/repos/{repoName}) are the preferred working directory. Always git fetch --all --prune before starting work in an automation clone. These clones exist specifically so that the skill can run without interfering with the user's active working tree, uncommitted changes, or current branch

Source

git clone https://github.com/n1ddeh/fantastic-skills/blob/main/resolve-pr-feedback-bubbles/SKILL.mdView on GitHub

Overview

This skill automatically handles PR review feedback by drafting replies, applying code fixes, and pushing back when suggestions would worsen outcomes. It coordinates multiple agents in parallel, and can run end-to-end in auto mode to save time on PR back-and-forth.

How This Skill Works

It discovers open PRs with unresolved review threads using open-graphite-stacks and GraphQL, then resolves repo paths by preferring automation clones. It drafts replies, applies fixes via code changes, and uses REST calls to post updates, then dispatches stack orchestrators and per-PR agents to process PRs in trunk-to-tip order.

When to Use It

  • You have a backlog of PRs with unresolved review comments across multiple repos
  • You want end-to-end automation using --auto-reply to post replies and fixes without prompts
  • You need drafted replies and potential code changes pushed back to PRs
  • You manage multiple repos and need to derive owner/repo from git remotes for API calls
  • You want a summarized report of addressed PR feedback after processing

Quick Start

  1. Step 1: Run the skill with optional --auto-reply to skip prompts
  2. Step 2: It discovers eligible PRs, drafts replies, and applies fixes in parallel
  3. Step 3: Review the generated summary or let it auto-post if --auto-reply is used

Best Practices

  • Keep automation clones up to date by syncing before processing (git fetch --all --prune)
  • Prefer automation clones over user working directories to avoid disrupting active work
  • Review drafted replies and fixes before posting unless using --auto-reply
  • Validate remote URL parsing to reliably extract owner and repo for API calls
  • Test on a small set of PRs before scaling to a larger backlog

Example Use Cases

  • Auto-resolve feedback on a frontend PR with multiple unresolved threads across files
  • Process feedback across several repos in one stack and draft unified replies
  • Draft replies and apply minor code fixes for a backend refactor with reviewer comments
  • Generate a concise summary of PR feedback after batch processing
  • Use --auto-reply to push all drafted replies and fixes without manual prompts

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers