agents/skills/pr/SKILL.md
Open a PR, wait for CI to pass, fix failures, address review comments, and loop until fully green. Use when opening a PR, fixing CI, or addressing review feedback.
npx skillsauth add drn/dots prInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
git branch --show-currentgit status --shortThis skill participates in a phase chain. Read ~/.claude/skills/_shared/resources/phase-protocol.md for the full protocol.
Before creating the PR: Check .context/phases/ for prior artifacts. If any exist, use them to enrich the PR description:
plan-*.md or think-*.md → use the goal/summary for PR contextbuild-*.md → use the changes summary and deviationsreview-*.md → reference review findings and their resolutiontest-*.md → include test results and coverage metricsAfter the PR is created and green: Write a ship-{ts}.md artifact to .context/phases/ (create with mkdir -p .context/phases). The Detail section should include the PR URL, CI status, and any fixes applied. The Handoff section should note the PR number for /merge.
Open a PR for the current branch, then loop until CI is fully green and all review comments are addressed. Do not return until the PR is in a mergeable, green state.
If a PR already exists for this branch, skip straight to Step 3 — even if there are no local changes or commits. Your job is to get the PR to a green, mergeable state, not just to open it. Never abort when a PR exists.
Determine the upstream repo slug (owner/name) — use upstream remote if it exists, otherwise origin. Use gh pr list --repo <owner/repo> --head '<fork-owner>:<branch>' --state open --json number,url to check if a PR already exists. If one exists, note the PR number and skip to Step 3.
If there are uncommitted changes (check git status), stage and commit them with an appropriate message before proceeding. Do this before anything else — uncommitted changes are work the user wants shipped.
Abort condition (only when NO PR exists): After committing any uncommitted changes, if there are STILL no commits ahead of the default branch, stop and tell the user: "Nothing to ship — no PR exists and there are no commits on this branch."
If the pending push touches any .md files, run prettier --check against them first. Markdown table edits (e.g., adding a row to one table) often force prettier to realign column widths in other tables in the same file, which trips qlty fmt in CI. Catching it before push avoids burning a CI cycle.
First determine the base ref (use git branch -r | grep -oE 'origin/(main|master)' | head -1), then load the changed .md files into a bash array so paths with spaces survive correctly:
mapfile -t md_files < <(git diff --name-only "$base_branch"...HEAD | grep -E '\.md$')
if [ ${#md_files[@]} -gt 0 ]; then
if ! npx --yes [email protected] --check "${md_files[@]}"; then
echo ":: prettier reformatted markdown — running --write and re-staging"
npx --yes [email protected] --write "${md_files[@]}"
git add "${md_files[@]}"
git commit -m "Format markdown via prettier"
fi
fi
The check is cheap (~2s for a typical PR) and catches the most common qlty fmt failure mode. Skip if no .md files are in the diff. If npx/prettier is not available, skip this step entirely rather than failing the push.
Push the current branch to origin. Use git push -u origin HEAD if no upstream is set. If there is nothing new to push, that is fine — continue to Step 3.
PR: <url> and skip to Step 4.Determine the base ref (use git branch -r to find origin/main or origin/master) (e.g., origin/master). Run git diff <base>...HEAD and git log <base>..HEAD --oneline to understand what changed. Classify the change complexity:
For each modified file, read the full file (not just the diff hunk) to understand the surrounding code.
For deleted or removed code: This is the most important case — reviewers need to understand why the code shouldn't exist. For each deletion:
For bug fixes: Trace the interaction between components that caused the bug. Read the files that call into or are called by the changed code. Identify the specific mechanism of failure (e.g., a race condition, a duplicated side effect, an incorrect assumption).
Scan the conversation history for context that should flow into the PR description:
Use gh pr create --repo <owner/repo> --base master --head <branch>. Keep the title under 70 characters.
Scale the body to match complexity:
Simple changes: title + 1–2 bullet summary.
Medium changes:
## Summary
- [What changed and why]
## Test plan
- [How to verify]
Complex changes (bug fixes, cross-file interactions, deletions):
## Summary
- [What changed]
## Root cause
[Explain the interaction between components that caused the issue.
Include brief code references — e.g., "create_transaction.rb:34 already
calls CreateTransactionEvent, so the explicit call in reverse_transaction.rb
created a duplicate." Show the mechanism, not just the symptom.]
## Production impact
[Only if the conversation contains impact data — e.g., "1,208 duplicate
events in the last 30 days." Omit this section if no data is available.]
## Test plan
- [How to verify]
[Link to triggering CI failure, Jira ticket, or Sentry error if available]
Print the PR URL on its own line, formatted exactly as:
PR: <url>
Repeat the following until CI is fully green and there are no unresolved review comments:
First, probe mergeability before polling. Run a one-shot:
gh pr view <number> --repo <owner/repo> --json mergeStateStatus,mergeable
mergeStateStatus == "DIRTY" or mergeable == "CONFLICTING", the branch has merge conflicts with the base. GitHub Actions may delay or skip running CI for the PR, and even if it runs, the merge step won't succeed. Do not enter the polling loop. Fetch the base branch (git fetch origin <base>), rebase onto it (git rebase origin/<base>), resolve any conflicts, and force-push with lease (git push --force-with-lease). Then re-probe mergeStateStatus and continue once it is no longer DIRTY.Then use gh pr checks <number> --repo <owner/repo> to see the current state of all checks.
gh pr checks with exponential backoff: wait 60s, then 120s, then 240s, capping at 300s between polls. Stop after 30 minutes total and report to the user.gh pr checks reports "no checks reported" for 3+ minutes and mergeStateStatus is not DIRTY, the workflow may be misconfigured, paused, or require approval — surface this to the user rather than continuing to poll silently.gh pr checks <number> --repo <owner/repo> to see which checks failed.mcp__github__get_job_logs with failed_only: true and the workflow run_id to read the failure logs.git push.This step handles both human and automated bot comments (CodeRabbit, qlty, Copilot, GitHub Actions, etc.). Every unresolved thread blocks mergeability.
Fetch unresolved threads using gh api graphql:
gh api graphql -f query='
query {
repository(owner: "<owner>", name: "<repo>") {
pullRequest(number: <number>) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 10) {
nodes {
body
author { login }
path
line
}
}
}
}
}
}
}'
Filter to threads where isResolved is false. If there are zero unresolved threads, this step is done — return to 4a (which will proceed to Step 5 if CI is also green).
For each unresolved thread, classify and respond:
Identify the author. Check the first comment author login. Bot usernames typically end in [bot] (e.g., coderabbitai[bot], qltysh[bot], github-actions[bot], copilot-pull-request-review[bot]).
Triage the comment. Read the comment body and the referenced code. Classify as one of:
For bot comments specifically: bot suggestions are frequently false positives or conflict with project conventions. Do not blindly apply every suggestion. Evaluate each on its merits. Complexity warnings from linter bots (qlty, CodeClimate) are almost always informational — the complexity is inherent to the function. Similar-code detection is usually informational when the code implements a shared interface pattern.
Reply to the thread. Always reply before resolving, so there is an audit trail:
Use mcp__github__create_pull_request_review_comment_reply to reply to the thread, passing the first comment ID as comment_id.
Resolve the thread via GraphQL mutation:
gh api graphql -f query='
mutation {
resolveReviewThread(input: {threadId: "<thread_node_id>"}) {
thread { isResolved }
}
}'
After addressing all threads: if any code changes were made, stage, commit, and push them before looping back.
After pushing fixes or addressing comments, loop back to wait for CI again. Continue until CI is fully green and no unresolved comments remain.
Important: If you are stuck in a loop (same failure 3+ times), stop and report the situation to the user rather than retrying the same fix.
When CI is green and all comments are addressed:
PR: <url>.development
Walk every unresolved review thread on a PR, triage each one, reply with a rationale of whether or not the comment will be acted upon, make the code change if warranted, and mark the thread resolved. Use when the user asks to address only the open PR comments without re-running CI, respond to review feedback, resolve review threads, or clear bot comments on a PR.
tools
Iteratively run /rereview, fix the findings, and loop until reviewers approve clean. Use for iterative automated review, when you want /rereview to loop until clean, or for a paranoid pre-merge review that auto-addresses every blocker.
development
Generate self-contained HTML visualizations with Plannotator theming. Use for implementation plans, PR explainers, architecture diagrams, data tables, slide decks, and any visual explanation of technical concepts. Plans and PR explainers follow Plannotator's prescriptive approach; all other visual content delegates to nicobailon/visual-explainer.
development
Create reviewed Codex goal setup packages for long-running /goal work. Use when the user wants to turn an idea, backlog, project mission, or vague objective into durable goal files under a project goals slug folder, with Plannotator review gates for brief, narrative plan with acceptance criteria, verification, blockers, and the final /goal prompt.