Iterate on PR Until CI Passes
Goal: fix actionable CI failures and high/medium review feedback. Stop and report human approval, draft-readiness, and merge-readiness gates.
Requires:
- authenticated
gh
uv
- target repository root as cwd
- skill-root-relative script paths, for example
scripts/fetch_pr_checks.py
Bundled Scripts
| Script |
Run |
Output |
scripts/fetch_pr_checks.py |
uv run scripts/fetch_pr_checks.py [--pr NUMBER] |
JSON: pr, summary, checks, failure snippets |
scripts/fetch_pr_feedback.py |
uv run scripts/fetch_pr_feedback.py [--pr NUMBER] |
JSON buckets: high, medium, low, bot, resolved |
scripts/monitor_pr_checks.py |
uv run scripts/monitor_pr_checks.py [--pr NUMBER] |
terminal marker plus tab-separated checks |
scripts/reply_to_thread.py |
uv run scripts/reply_to_thread.py THREAD_ID BODY [...] |
JSON reply results |
Check summary fields include failed, pending, actionable_pending, and human_gate_pending.
Monitor markers:
ALL_CHECKS_PASSED
CHECKS_DONE_WITH_FAILURES
NO_CHECKS_REGISTERED
DRAFT_PR_WITH_NO_CHECKS
CHECKS_BLOCKED_BY_REVIEW_GATE
Workflow
1. Identify PR
Run:
gh pr view --json number,url,headRefName,isDraft,reviewDecision
Stop when:
- no PR exists
- draft PR has no checks after monitor grace period: report
DRAFT_PR_WITH_NO_CHECKS
Draft rule: inspect existing checks/feedback only. Do not mark ready for review unless asked.
2. Handle Feedback
Run uv run scripts/fetch_pr_feedback.py [--pr NUMBER].
| Bucket |
Action |
high |
fix |
medium |
fix |
low |
ask user which to address |
bot |
skip informational comments |
resolved |
skip |
Feedback fix checklist:
- verify root cause
- search related code
- fix all instances
- for
review_bot: true: fix real issues, explain false positives
Low-priority prompt format:
Found 3 low-priority suggestions:
1. [l] "Consider renaming this variable" - @reviewer in api.py:42
2. [nit] "Could use a list comprehension" - @reviewer in utils.py:18
3. [style] "Add a docstring" - @reviewer in models.py:55
Which should I address? ("1,3", "all", or "none")
3. Check CI Status
Run uv run scripts/fetch_pr_checks.py [--pr NUMBER].
| State |
Action |
failed > 0 and actionable_pending == 0 |
fix failures |
actionable_pending > 0 |
wait; poll feedback while waiting |
pending > 0 and actionable_pending == 0 |
report CHECKS_BLOCKED_BY_REVIEW_GATE |
| no checks after grace period |
report NO_CHECKS_REGISTERED or DRAFT_PR_WITH_NO_CHECKS |
| all actionable checks passed |
run post-CI feedback check |
Wait for actionable review bots: sentry, warden, cursor, bugbot, seer, codeql.
Do not wait for approval, isDraft, REVIEW_REQUIRED, Codecov, or informational bots.
4. Fix CI Failures
For each failure:
- read full log:
gh run view <run-id> --log-failed
- trace from assertion/exception/lint rule to source
- state the cause before editing: "fails because X, affected by Y"
- search related call sites/patterns
- fix root cause, not symptom
- add focused test coverage when needed
5. Verify Locally, Then Commit and Push
Before commit:
- test fix: rerun specific test
- lint/type fix: rerun affected checker
- code fix: rerun covering tests
- local failure: fix before pushing
git add <files>
git commit -m "fix: <descriptive message>"
git push
6. Monitor CI and Address Feedback
Loop:
- run
uv run scripts/fetch_pr_checks.py
- handle table in step 3
- while
actionable_pending > 0, run uv run scripts/fetch_pr_feedback.py
- fix new high/medium feedback immediately
- if changed, verify, commit, push, restart loop
- otherwise sleep 30 seconds and repeat
- after checks pass, wait 10 seconds, fetch feedback once more
- if new high/medium feedback exists, return to step 4
Claude Code optional: run uv run scripts/monitor_pr_checks.py through MonitorTool with persistent: false; set timeout to normal repo CI duration. Restart the monitor after every push.
Exit Conditions
| Exit |
Conditions |
| Success |
actionable CI passed; post-CI feedback clean; low-priority choice handled |
| Ask user |
same failure after 2 attempts; feedback unclear; infrastructure issue |
| Stop |
no PR; branch needs rebase; no checks; draft no-checks; only human gates remain |
Fallback
If scripts fail, use gh CLI directly:
gh pr view --json number,url,headRefName,isDraft,reviewDecision
gh pr checks --json name,state,bucket,description,link
gh run view <run-id> --log-failed
gh api repos/{owner}/{repo}/pulls/{number}/comments
1---2name: iterate-pr3description: Iterate on a PR until actionable CI passes and high/medium review feedback is addressed. Use for PR CI failures, review feedback, or green-check loops; do not wait for human approval, draft status, or merge gates.4---56# Iterate on PR Until CI Passes78Goal: fix actionable CI failures and high/medium review feedback. Stop and report human approval, draft-readiness, and merge-readiness gates.910Requires:11- authenticated `gh`12- `uv`13- target repository root as cwd14- skill-root-relative script paths, for example `scripts/fetch_pr_checks.py`1516## Bundled Scripts1718| Script | Run | Output |19|--------|-----|--------|20| `scripts/fetch_pr_checks.py` | `uv run scripts/fetch_pr_checks.py [--pr NUMBER]` | JSON: `pr`, `summary`, `checks`, failure snippets |21| `scripts/fetch_pr_feedback.py` | `uv run scripts/fetch_pr_feedback.py [--pr NUMBER]` | JSON buckets: `high`, `medium`, `low`, `bot`, `resolved` |22| `scripts/monitor_pr_checks.py` | `uv run scripts/monitor_pr_checks.py [--pr NUMBER]` | terminal marker plus tab-separated checks |23| `scripts/reply_to_thread.py` | `uv run scripts/reply_to_thread.py THREAD_ID BODY [...]` | JSON reply results |2425Check summary fields include `failed`, `pending`, `actionable_pending`, and `human_gate_pending`.2627Monitor markers:28- `ALL_CHECKS_PASSED`29- `CHECKS_DONE_WITH_FAILURES`30- `NO_CHECKS_REGISTERED`31- `DRAFT_PR_WITH_NO_CHECKS`32- `CHECKS_BLOCKED_BY_REVIEW_GATE`3334## Workflow3536### 1. Identify PR3738Run:39```bash40gh pr view --json number,url,headRefName,isDraft,reviewDecision41```4243Stop when:44- no PR exists45- draft PR has no checks after monitor grace period: report `DRAFT_PR_WITH_NO_CHECKS`4647Draft rule: inspect existing checks/feedback only. Do not mark ready for review unless asked.4849### 2. Handle Feedback5051Run `uv run scripts/fetch_pr_feedback.py [--pr NUMBER]`.5253| Bucket | Action |54|--------|--------|55| `high` | fix |56| `medium` | fix |57| `low` | ask user which to address |58| `bot` | skip informational comments |59| `resolved` | skip |6061Feedback fix checklist:62- verify root cause63- search related code64- fix all instances65- for `review_bot: true`: fix real issues, explain false positives6667Low-priority prompt format:68```text69Found 3 low-priority suggestions:701. [l] "Consider renaming this variable" - @reviewer in api.py:42712. [nit] "Could use a list comprehension" - @reviewer in utils.py:18723. [style] "Add a docstring" - @reviewer in models.py:557374Which should I address? ("1,3", "all", or "none")75```7677### 3. Check CI Status7879Run `uv run scripts/fetch_pr_checks.py [--pr NUMBER]`.8081| State | Action |82|-------|--------|83| `failed > 0` and `actionable_pending == 0` | fix failures |84| `actionable_pending > 0` | wait; poll feedback while waiting |85| `pending > 0` and `actionable_pending == 0` | report `CHECKS_BLOCKED_BY_REVIEW_GATE` |86| no checks after grace period | report `NO_CHECKS_REGISTERED` or `DRAFT_PR_WITH_NO_CHECKS` |87| all actionable checks passed | run post-CI feedback check |8889Wait for actionable review bots: sentry, warden, cursor, bugbot, seer, codeql.90Do not wait for approval, `isDraft`, `REVIEW_REQUIRED`, Codecov, or informational bots.9192### 4. Fix CI Failures9394For each failure:951. read full log: `gh run view <run-id> --log-failed`962. trace from assertion/exception/lint rule to source973. state the cause before editing: "fails because X, affected by Y"984. search related call sites/patterns995. fix root cause, not symptom1006. add focused test coverage when needed101102### 5. Verify Locally, Then Commit and Push103104Before commit:105- test fix: rerun specific test106- lint/type fix: rerun affected checker107- code fix: rerun covering tests108- local failure: fix before pushing109110```bash111git add <files>112git commit -m "fix: <descriptive message>"113git push114```115116### 6. Monitor CI and Address Feedback117118Loop:1191. run `uv run scripts/fetch_pr_checks.py`1202. handle table in step 31213. while `actionable_pending > 0`, run `uv run scripts/fetch_pr_feedback.py`1224. fix new high/medium feedback immediately1235. if changed, verify, commit, push, restart loop1246. otherwise sleep 30 seconds and repeat1257. after checks pass, wait 10 seconds, fetch feedback once more1268. if new high/medium feedback exists, return to step 4127128Claude Code optional: run `uv run scripts/monitor_pr_checks.py` through `MonitorTool` with `persistent: false`; set timeout to normal repo CI duration. Restart the monitor after every push.129130## Exit Conditions131132| Exit | Conditions |133|------|------------|134| Success | actionable CI passed; post-CI feedback clean; low-priority choice handled |135| Ask user | same failure after 2 attempts; feedback unclear; infrastructure issue |136| Stop | no PR; branch needs rebase; no checks; draft no-checks; only human gates remain |137138## Fallback139140If scripts fail, use `gh` CLI directly:141- `gh pr view --json number,url,headRefName,isDraft,reviewDecision`142- `gh pr checks --json name,state,bucket,description,link`143- `gh run view <run-id> --log-failed`144- `gh api repos/{owner}/{repo}/pulls/{number}/comments`