|
1 | 1 | --- |
2 | 2 | name: pull-request |
3 | | -description: Full PR lifecycle — branch, commit, issue, draft PR, CI, ready, autonomous monitor loop (fix comments, resolve threads, iterate until CI green and zero unresolved threads). |
| 3 | +description: > |
| 4 | + Use this whenever the user asks to "open a PR", "ship this", "create the |
| 5 | + pull request", "make a PR", or once a feature/fix is verified and ready to |
| 6 | + push. Full lifecycle: branch → commit (commitizen) → issue → draft PR → CI |
| 7 | + → ready → autonomous monitor loop (fix comments, resolve threads, iterate |
| 8 | + until CI green + zero unresolved threads). `--perfect` adds a CodeRabbit |
| 9 | + convergence loop on top. Never works on `main`/`master`, never uses |
| 10 | + `--no-verify`. |
4 | 11 | --- |
5 | 12 |
|
6 | 13 | # Pull Request Skill |
@@ -108,112 +115,32 @@ gh pr ready <number> |
108 | 115 |
|
109 | 116 | ## 6. Monitor loop (autonomous) |
110 | 117 |
|
111 | | -Set these variables once before running any loop command: |
| 118 | +After `gh pr ready`, run an autonomous polling loop until either CI is green |
| 119 | +with zero unresolved threads for 3 consecutive passes (~9 min) or the safety |
| 120 | +limit (10 iterations) trips. |
112 | 121 |
|
113 | 122 | ```bash |
114 | 123 | OWNER=$(gh repo view --json owner -q .owner.login) |
115 | 124 | REPO=$(gh repo view --json name -q .name) |
116 | 125 | PR=<number> |
117 | 126 | ``` |
118 | 127 |
|
119 | | -After `gh pr ready`, enter an autonomous polling loop. Do not wait for the user — drive the loop yourself until the stop condition is met. |
120 | | - |
121 | | -### Loop procedure |
122 | | - |
123 | | -```text |
124 | | -consecutive_zero = 0 |
125 | | -
|
126 | | -REPEAT: |
127 | | - 1. Wait for CI → sleep 30 then gh pr checks $PR --watch |
128 | | - 2. If CI fails → fix, /verify, commit, push, consecutive_zero=0, GOTO 1 |
129 | | - 2b. Check mergeable status → STATUS=$(gh pr view $PR --json mergeable --jq .mergeable) |
130 | | - if STATUS == "UNKNOWN" → sleep 10, retry up to 3 times |
131 | | - if STATUS == "CONFLICTING" → report to user and STOP |
132 | | - 3. Grace period → sleep 180 + adaptive check (see 6b) |
133 | | - 4. Re-check pending review checks → gh pr checks $PR — if any still pending, GOTO 3 |
134 | | - 5. Read all feedback → unresolved threads only (see 6b) |
135 | | - 6. If actionable comments → fix all, /verify, commit, push, reply, resolve, consecutive_zero=0, GOTO 1 |
136 | | - 7. If non-actionable unresolved → reply all explaining why, resolve all, consecutive_zero=0, GOTO 5 |
137 | | - 8. If zero unresolved threads → consecutive_zero++ |
138 | | - if consecutive_zero >= 3 (~9 min) → check branch protection (see 6f), then STOP ✓ |
139 | | - else GOTO 3 |
140 | | -``` |
141 | | - |
142 | | -### 6a. Wait for CI |
143 | | - |
144 | | -After any push, wait 30s then watch: |
145 | | - |
146 | | -```bash |
147 | | -sleep 30 |
148 | | -gh pr checks "$PR" --watch |
149 | | -``` |
150 | | - |
151 | | -If `no checks reported`, retry up to 5 times (30s apart). If still no checks after 5 retries, report to user and stop. |
152 | | - |
153 | | -**If any check fails** → fix, `/verify`, commit, push, restart loop. Do not read review feedback until CI passes. |
154 | | - |
155 | | -### 6b. Read all feedback — unresolved threads only |
156 | | - |
157 | | -Grace period: `sleep 180`. If 0 bot comments after 3 min, wait 2 more min. |
158 | | - |
159 | | -Read **only unresolved threads** (resolved = ignored). Use `references/monitoring.md` as source of truth. |
160 | | - |
161 | | -```bash |
162 | | -# Optional context only (do not drive action from these): |
163 | | -# gh pr view $PR --json reviews,comments |
164 | | -# gh api repos/$OWNER/$REPO/pulls/$PR/comments --paginate | jq 'map({id, user: .user.login, body})' |
165 | | -# gh api repos/$OWNER/$REPO/issues/$PR/comments --paginate | jq 'map({id, user: .user.login, body})' |
166 | | -# Action source of truth: unresolved threads query in references/monitoring.md |
167 | | -``` |
168 | | - |
169 | | -**Actionable** (must fix): change requests, bug reports, missing tests, security issues, code suggestions. |
170 | | - |
171 | | -**Informational** (reply + resolve, no code change): approvals, coverage reports, style preferences without change request, false positives. PR-level comments (codecov, approvals) cannot be resolved via thread API — don't count as unresolved. |
172 | | - |
173 | | -### 6b-bis. Classify stack-level vs downstream comments (downstream projects only) |
174 | | - |
175 | | -Skip when running directly on the stack repo. Requires `devkit-node` remote (set up by `/update-stack`) — if missing, stop and report. |
176 | | - |
177 | | -For each actionable comment, check if the file exists unmodified in upstream: |
178 | | - |
179 | | -```bash |
180 | | -STACK_REPO=$(git remote get-url devkit-node 2>/dev/null | sed 's|.*github.com[:/]||;s|\.git$||') |
181 | | -STACK_DEFAULT_BRANCH=$(git remote show devkit-node 2>/dev/null | sed -n '/HEAD branch/s/.*: //p') |
182 | | -git fetch devkit-node "$STACK_DEFAULT_BRANCH" --quiet 2>/dev/null |
183 | | -# STACK if exists in upstream AND no local diff; else DOWNSTREAM |
184 | | -git cat-file -e "devkit-node/$STACK_DEFAULT_BRANCH:<file-path>" 2>/dev/null && \ |
185 | | - git diff --quiet "devkit-node/$STACK_DEFAULT_BRANCH" -- <file-path> 2>/dev/null |
186 | | -``` |
187 | | - |
188 | | -- **Stack-level** → create issue on stack repo with review comment details, reply with issue link, resolve thread. If `gh issue create` fails, fix locally instead. |
189 | | -- **Downstream** → fix locally (section 6c). |
190 | | - |
191 | | -### 6c. Fix all actionable comments from this pass |
192 | | - |
193 | | -Fix all actionable comments in one batch: `/verify` → commit → push → reply with SHA → resolve threads via GraphQL (see `references/monitoring.md`). One commit per pass. |
194 | | - |
195 | | -### 6d. Coverage gaps |
196 | | - |
197 | | -Add missing tests — **never lower thresholds**. Include in the same commit batch. |
198 | | - |
199 | | -### 6e. After pushing fixes |
200 | | - |
201 | | -Wait 30s before watching CI (regular or force-push). Loop back to 6a. Never post `@copilot review` — it invokes the coding agent, not the reviewer. |
202 | | - |
203 | | -### 6f. Stop condition |
204 | | - |
205 | | -CI green **and** 3 consecutive passes (~9 min of grace periods) with zero unresolved threads. Mergeable status is also checked after every CI pass (step 2b) — conflicts cause an early stop. Final branch protection check: |
206 | | - |
207 | | -```bash |
208 | | -gh pr view "$PR" --json reviewDecision,mergeable | jq '{reviewDecision, mergeable}' |
209 | | -``` |
210 | | - |
211 | | -- `APPROVED` + `MERGEABLE` → **STOP ✓** |
212 | | -- `REVIEW_REQUIRED` → report to user, stop |
213 | | -- `CHANGES_REQUESTED` → report to user, stop |
214 | | -- `BLOCKED` → report details to user |
215 | | - |
216 | | -**Safety limit:** 10 iterations max — report to user if still unresolved. |
| 128 | +Per pass: |
| 129 | +1. Wait CI → fix + /verify + commit + push if red, else continue |
| 130 | +2. Check mergeable — `CONFLICTING` stops, `UNKNOWN` retries |
| 131 | +3. Grace `sleep 180` + adaptive recheck of pending review checks |
| 132 | +4. Read **only unresolved threads** (see `references/monitoring.md`) |
| 133 | +5. Actionable → batch-fix in one commit, /verify, push, reply with SHA, |
| 134 | + resolve via GraphQL. Never resolve silently — reply is audit trail. |
| 135 | +6. Non-actionable → reply explaining why, resolve, continue |
| 136 | +7. Zero unresolved 3 passes in a row + CI green + branch protection |
| 137 | + `APPROVED`+`MERGEABLE` → STOP ✓ |
| 138 | +
|
| 139 | +Downstream projects: classify stack-level vs downstream comments via the |
| 140 | +`devkit-node` remote and open issues upstream for stack-level findings. |
| 141 | +
|
| 142 | +**Full procedure (commands, classification rules, stop condition matrix):** |
| 143 | +see `references/monitor-loop.md`. Load when running the loop. |
217 | 144 |
|
218 | 145 | ## 7. Perfect mode (`--perfect`) |
219 | 146 |
|
|
0 commit comments