Copilot PR autopilot
Drive a pull request through repeated GitHub Copilot review rounds until every loop-owned thread has a fix acknowledgement, decline rationale, or explicit hand-off, with one focused commit per round and proof that HEAD was reviewed.
When to invoke
- "Address Copilot comments on this PR."
- "Run a Copilot review loop."
- "Fix this PR based on Copilot feedback."
- "Request Copilot review and iterate until clean."
- "Triage all open review threads."
Prerequisites and context
ghCLI must be installed and authenticated. Every script dot-sourcesscripts/_lib.ps1, which runsAssert-GhReadyand halts before work ifghis missing orgh auth statusfails.- PowerShell must be on PATH: Windows PowerShell 5.1+ (
powershell.exe) or PowerShell 7+ (pwsh). - Full multi-round autopilot requires Triage or Write permission on the target repo because GitHub's public API for adding the Copilot bot reviewer through GraphQL
requestReviewsByLoginis permission-gated. - If
scripts/01-request-review.ps1fails because GitHub Copilot Code Review is unavailable, run a single iteration over existing human, advanced-security, or other bot threads by skipping trigger and wait.
| Actor | What works |
|---|---|
| Repo collaborator with Triage / Write | Full loop: 01 triggers Copilot, 02 waits, 04–08 triage, fix, reply, then loop. |
| External PR author without write permission | 01 errors. Use -SingleIteration, address current findings once, then ask the maintainer to trigger review in the UI or push a substantive commit to fire synchronize. |
In single-iteration mode, Converged: true means OpenThreadsAwaitingReply == 0; maintainer-side re-trigger drives later rounds.
Procedure
- Request review with
scripts/01-request-review.ps1, followingreferences/01-request-review.md. - Wait for review with the 20-minute cap in
references/02-wait.md. - List and categorize open threads with
references/03-list-threads.mdandscripts/03-list-open-threads.ps1. - Triage each batch with
references/04-triage.md: fix, decline, or escalate-to-user. - Fix with parallel bounded sub-agents as allowed by
references/05-fix.md. - Build, test, and lint using repository conventions from
CONTRIBUTING,AGENTS,README,package.json, orMakefile, followingreferences/06-build-test.md. - Commit and push one focused commit per round using
references/07-commit-push.md. - Reply and resolve with
references/08-reply-resolve.mdandscripts/08-reply-and-resolve.ps1; use-NoResolvefor escalate-to-user hand-offs. - Verify convergence with
references/09-convergence.mdandscripts/02-check-review-status.ps1. - If
Converged: false, loop back to step 1. IfConverged: true, run cleanup once withreferences/10-cleanup.mdandscripts/10-cleanup-outdated.ps1.
At every 10th round, run the round-cap recap gate in references/09-convergence.md#round-cap--recap-gate-circuit-breaker. Recap all prior rounds against the PR's original scope and choose CONTINUE, REVERT-AND-SHIP, or HAND-OFF.
Loop ownership rules
| Thread type | Default disposition |
|---|---|
| GitHub Copilot thread | Loop-owned: fix or decline, then reply and resolve when disposition is complete. |
| Human reviewer thread | Default to escalate-to-user; reply with analysis and leave open unless the user explicitly owns resolution. |
github-advanced-security thread |
Default to escalate-to-user unless a safe fix is clearly in scope. |
| Design tradeoff | Decline with rationale or hand off; do not over-engineer to satisfy speculative feedback. |
| Outdated unresolved thread | Still reply and resolve if loop-owned; unresolved state is source of truth. |
Convergence requires HEAD-match, zero-awaiting, and at-HEAD review. Print proof fields such as HeadOid, LatestCopilotReview.commitOid, and submittedAt in the completion message. Do not call task_complete before Converged: true.
Gotchas
- Reply to every open thread: resolve only
fixanddeclinedispositions; leaveescalate-to-useropen with08-reply-and-resolve.ps1 -NoResolve. - One focused commit per round: bundling rounds destroys the audit trail and hurts
git bisect. - Use the repo's own build/test/lint commands: do not invent tooling.
- Trust bundled scripts for invariants:
copilot_work_startedevent id,Converged, HEAD match, zero-awaiting, at-HEAD review, single-iteration fallback, and PR-state guard are enforced there. - Read
references/api-quirks.mdbefore modifying scripts: it documentsgh api graphql -Ftype coercion,git stash push -mpositional parsing, and the three GraphQL reviewer mutation traps.
Troubleshooting
| Issue | Resolution |
|---|---|
prerequisite missing — gh CLI is not on PATH |
Install gh from https://cli.github.com or with winget install GitHub.cli on Windows and brew install gh on macOS; then run gh auth login. Surface the script message and stop. |
prerequisite missing — gh CLI is not authenticated |
Run gh auth login; stop until complete. |
Trigger fails or no copilot_work_started event lands |
Push a substantive non-whitespace commit; persistent failure may mean Copilot Code Review is disabled in repo settings or account-level Copilot Pro/Pro+. |
| No new review after about 10 minutes | Quiet period or trivial-diff suppression. Push a substantive commit and retry; do not blindly rerun 01-request-review.ps1 while it reports InFlight. |
| Outdated unresolved threads appear | Expected; unresolved state is source of truth. Reply and resolve loop-owned items, then let 10-cleanup-outdated.ps1 run only as final safety net. |
| Unsure fix vs decline | Use references/04-triage.md. |
| Need reply phrasing | Use templates/reply-fix.md, templates/reply-decline.md, templates/reply-drift.md, or templates/reply-partial.md. |
Progressive disclosure and bundled resources
references/orchestration.md: time-boxing, extension protocol, sub-agent map, single-iteration fallback, and loop-wide notes.references/01-request-review.mdthroughreferences/10-cleanup.md: per-step contracts for request, wait, list, triage, fix, build-test, commit-push, reply-resolve, convergence, and cleanup.references/api-quirks.md: GitHub API behavior and GraphQL traps.templates/reply-fix.md,templates/reply-decline.md,templates/reply-drift.md,templates/reply-partial.md: reply templates.scripts/_lib.ps1:Invoke-Gh,Invoke-GhGraphQL,Resolve-RepoCoords, andAssert-GhReady.scripts/01-request-review.ps1: trigger Copilot review and verify pickup.scripts/02-check-review-status.ps1: snapshot review state; emitsConverged: trueonly when all conditions hold.scripts/03-list-open-threads.ps1: unresolved PR review threads from all reviewers.scripts/08-reply-and-resolve.ps1: post a reply and resolve in one call.scripts/10-cleanup-outdated.ps1: final outdated Copilot thread safety net.
Output template
### Copilot PR autopilot result
**Status:** converged | single-iteration complete | hand-off | blocked
**PR:** <owner/repo#number>
**Rounds:** <count>
**HeadOid:** `<sha>`
**LatestCopilotReview.commitOid:** `<sha or none>`
**submittedAt:** `<timestamp or none>`
| Round | Threads triaged | Fixed | Declined | Escalated | Commit | Validation |
| --- | ---: | ---: | ---: | ---: | --- | --- |
| <n> | <count> | <count> | <count> | <count> | `<sha>` | <build/test/lint result> |
**OpenThreadsAwaitingReply:** <count>
**Converged:** true | false
**Remaining open hand-offs:** <human/design/security threads or none>
Quality gate
-
ghand authentication prerequisites were checked byAssert-GhReady. - Full loop used only when the actor had Triage or Write permission; otherwise single-iteration mode was used.
- Every open thread was categorized as fix, decline, or escalate-to-user.
- Every loop-owned thread received a reply and was resolved only when appropriate.
- Build/test/lint followed repository conventions.
- Each round produced one focused commit or documented why no commit was needed.
- The 10th-round recap gate ran on rounds 10, 20, 30, and so on.
- Completion included
HeadOid,LatestCopilotReview.commitOid,submittedAt, andConverged: trueproof.