PR Babysitter
SkillDev toolsBabysit a GitHub pull request after creation by continuously polling CI checks/workflow runs, new review comments, and mergeability state until the PR is ready to merge (or merged/closed). Diagnose failures, retry likely flaky failures up to 3 times, auto-fix and push branch-related issues when appropriate, and stop only when user help is required (e.g. CI infrastructure issues, exhausted flaky retries, or ambiguous/blocking review feedback). Use when the user asks to monitor a PR, watch CI, handle review comments, or keep an eye on failures and feedback on an open PR.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the PR Babysitter skill
What this skill tells your AI
The instructions your AI receives, as published by rock3r/spectre in .agents/skills/babysit-pr/SKILL.md and read by ahel’s review.
Monitor a PR persistently until one of the terminal states is reached:
- PR merged or closed
- CI fully green, no unaddressed review comments, no merge conflicts
- A situation requiring user intervention
Inputs
- No PR argument — infer from current branch (
--pr auto) - PR number — e.g.
123 - PR URL — e.g.
https://github.com/ADUX-sandbox/Compose-Pi/pull/123
Core workflow
- Before running any script, output a single line so the user knows which PR this conversation is tracking — e.g.
Babysitting PR [#123](https://github.com/ADUX-sandbox/Compose-Pi/pull/123). Resolve the PR number/URL from the user's input or the current branch first if needed. - Start with
--once(default) — it blocks until something needs your attention, then returns. - Run the watcher to snapshot PR/CI/review state.
- Inspect the
actionslist in the JSON output. - Diagnose CI failures — classify as branch-related (fix and push) vs. flaky (retry).
- Process actionable review comments from trusted humans and Codex.
- Verify mergeability on each loop.
- After any push, relaunch
--watchin the same turn. - Continue until a terminal stop condition is reached.
Key commands
# Wait until something needs attention, then return one snapshot (default)
python3 .agents/skills/babysit-pr/scripts/gh_pr_watch.py --pr auto --once
# Instant snapshot of current state (no waiting)
python3 .agents/skills/babysit-pr/scripts/gh_pr_watch.py --pr auto --snapshot
# Continuously poll, emitting JSONL snapshots (for streaming-capable consumers)
python3 .agents/skills/babysit-pr/scripts/gh_pr_watch.py --pr auto --watch
# Trigger a rerun of failed jobs for the current SHA
python3 .agents/skills/babysit-pr/scripts/gh_pr_watch.py --pr auto --retry-failed-now
# Explicit PR number or URL
python3 .agents/skills/babysit-pr/scripts/gh_pr_watch.py --pr 42 --once
python3 .agents/skills/babysit-pr/scripts/gh_pr_watch.py --pr https://github.com/ADUX-sandbox/Compose-Pi/pull/42 --snapshot
Stop conditions
actions value | Meaning |
|---|---|
stop_pr_closed | PR was merged or closed — done |
stop_ready_to_merge | CI green, no blocking reviews, no conflicts |
stop_exhausted_retries | Flaky reruns hit the retry limit — user must investigate |
stop_non_retryable_failure | Terminal failure is not in retry-eligible workflows — diagnose/fix before continuing |
stop_session_timeout | --max-session-minutes elapsed (default 90 min) — stop and report |
diagnose_hung_check | A pending check has exceeded its hung threshold (30 min) — stop and report |
diagnose_merge_conflict | PR is merge-conflicted (CONFLICTING / DIRTY) — resolve conflicts before waiting on checks |
diagnose_branch_behind | PR head is BEHIND the base branch — update the branch (rebase or merge base) before waiting on checks; stop_ready_to_merge is never emitted while behind |
diagnose_skipping_checks | One or more checks completed with neutral/skipping — investigate why |
wait_codex | Codex is still reviewing (👀 reaction present on the PR) — do not push or merge |
Keep polling when CI is running (idle), when new review items arrive (process_review_comment),
when Codex is still reviewing (wait_codex), or when CI is green but the PR is
awaiting approval.
Post-merge cleanup (when stop_pr_closed and PR is merged)
After a PR is merged, clean up the local environment automatically:
-
If currently on the PR branch, switch away first (for example to
main):git checkout main -
Delete the local branch (squash merges leave it unmerged by default):
git branch -D <head_branch> -
Remove the git worktree, if the branch was checked out in one:
# Find worktrees for this branch git worktree list # Remove if found (adjust path as needed) git worktree remove /path/to/worktree
How to detect a worktree: run git worktree list and check if any entry's branch matches the PR's head_branch. If the current working directory IS the worktree, cd to the main checkout first before removing it.
Only delete the local branch and worktree — never touch remote branches (the remote is already deleted by GitHub's "delete branch on merge" setting or the --delete-branch flag used at merge time).
Skip silently if the branch or worktree doesn't exist locally.
Push discipline — batch all fixes before pushing (cost control)
Each push triggers new Codex runs. Never push until all of the following are true:
./gradlew checkpasses locally (no CI failures to fix after the push).- Codex is not still reviewing — so its comments, if any, can be collected and fixed in the same push.
- You have incorporated all currently visible actionable Codex and human review comments into the pending local fix batch.
After pushing the fix batch, resolve all bot threads on GitHub (or reply + resolve when no code change is needed). No open bot threads should remain when the PR is merged.
Workflow when fixes are needed:
- Collect all outstanding issues: failed CI logs + any Codex or human review comments already posted.
- Fix everything locally in one pass.
- Run
./gradlew checkto confirm green. - Only then push — one push per fix cycle.
If a bot finishes while you are mid-fix and posts new comments, incorporate those fixes into the same commit before pushing.
Conflict + review-bot batching strategy (use this when PR shows CONFLICTING/DIRTY)
When GitHub reports merge conflicts while Codex/CI is still running:
- Do not push immediately. Wait until Codex is no longer reviewing.
- Snapshot latest status/comments.
- If conflict remains, rebase branch onto
origin/main(or merge main if repo policy prefers). - Resolve conflicts and in the same fix cycle apply all actionable Codex and human review comments.
- Run
./gradlew check. - Push once.
Rationale: this avoids paying for multiple Codex reruns and prevents a ping-pong where a conflict-fix push is immediately followed by a second bot-fix push.
Codex merge gate (mandatory)
Never merge until Codex reports clean.
Cursor Bugbot and CodeRabbit have both been removed and no longer gate anything. A leftover check from either on an old PR is now treated like any other check: if it completes
neutral/skippingit shows up underdiagnose_skipping_checks, not as a dedicated gate. CodeRabbit comments are no longer surfaced as actionable review items either.
Codex (emoji reaction)
Codex does not use a CI check. Instead it uses emoji reactions on the PR:
- 👀 reaction present from
chatgpt-codex-connector[bot]→ Codex is actively reviewing. Thecodex_gate.reviewingfield will betrueand await_codexaction will be emitted. Do not push or merge. - 👀 reaction removed, no new review comments → Codex is satisfied. Proceed.
- 👀 reaction removed, review comments posted → Codex found issues. Fix them locally and batch them into the next push (see push discipline).
The watcher automatically detects the 👀 reaction via the PR reactions API and surfaces codex_gate in the snapshot.
Decision rules
See references/heuristics.md for the full classification checklist:
- Branch-related failure: edit the code, collect all other pending issues (Codex, human reviews), fix everything, run
./gradlew check, then push once. - Likely flaky/unrelated: rerun via
--retry-failed-now; retry budget defaults to 3 per SHA.- The watcher only auto-reruns retry-eligible workflows (currently E2E-style workflows).
- CI/check workflow failures are treated as diagnose/fix-first by default.
- Ambiguous or requires product decision: stop and ask the user.
Review bots
The watcher surfaces feedback from:
- chatgpt-codex-connector[bot] — OpenAI Codex (emoji reaction-based code review)
- cursor[bot] — retired Cursor Bugbot; its login stays in
REVIEW_BOT_LOGIN_KEYWORDSso any leftover comment is still surfaced, but it no longer gates anything - Trusted humans: authors with
OWNER,MEMBER, orCOLLABORATORassociation
Note: if additional review bots are enabled on the repo (e.g. GitHub Actions summary bots), add their login keyword to
REVIEW_BOT_LOGIN_KEYWORDSinscripts/gh_pr_watch.py.
Worktree gotchas
When working from a git worktree, watch out for ktfmt CLI vs Gradle plugin version
mismatches and rebases silently reverting fixes. Always run ./gradlew check
before pushing — see the
pre-push checklist in AGENTS.md.
Choosing a mode based on harness capabilities
The right mode depends on whether the harness can stream bash tool stdout back to the model while the command is still running, or only delivers the final output after exit.
Harness streams tool output to the model (e.g. Claude Code subagents)
Use --watch. The script runs continuously, emitting JSONL snapshots as events. The
model sees each snapshot as it arrives and can act on it (retry, fix, merge) without
waiting for the script to exit. The script exits on terminal stop conditions.
Harness only returns output after tool exit (e.g. Pi, most tool-use loops)
Use --once (the default). The script blocks internally, polling every 30 seconds,
and only returns to the model when something needs agent attention — a CI failure to
diagnose, a review comment to process, a merge readiness signal, etc. The model never
sleeps blindly; the script handles all waiting. After acting on the result, the model
calls --once again to wait for the next event.
Typical agent loop:
- Run
--once→ script blocks until CI finishes, review arrives, etc. - Model reads the snapshot, acts on
actions(fix code, retry, merge). - If not terminal, run
--onceagain → repeat.
Quick debugging / one-off inspection
Use --snapshot for an instant point-in-time view with no waiting.
Output format
All modes emit newline-delimited JSON.
--once/--snapshot/--retry-failed-now: emit a top-level snapshot/result object whereactionsis directly available.--watch: emits event envelopes:{"event":"snapshot","payload":{"snapshot":{...},"state_file":"...","next_poll_seconds":30}}{"event":"stop","payload":{...}}
In --watch, read actions from payload.snapshot.actions for snapshot events and payload.actions for stop events.
blocking_review_items contains actionable unresolved inline review comments. When thread-resolution lookup is unavailable, the watcher fails closed: comments whose resolution state is unknown stay blocking regardless of age or commit. While non-empty, stop_ready_to_merge is not emitted.
Example snapshot payload shape (--once / --snapshot, or --watch under payload.snapshot):
{
"pr": { "number": 42, "head_sha": "abc123", "mergeable": "MERGEABLE", ... },
"checks": { "pending_count": 0, "failed_count": 1, "passed_count": 8, "skipping_count": 0, "all_terminal": true },
"failed_runs": [{ "run_id": 123, "workflow_name": "CI", "conclusion": "failure", "retry_eligible": false, ... }],
"codex_gate": { "reviewing": false, "status": "idle" },
"hung_checks": [{ "name": "CI", "elapsed_seconds": 1920, "threshold_seconds": 1800 }],
"new_review_items": [],
"blocking_review_items": [],
"actions": ["diagnose_ci_failure", "stop_non_retryable_failure"],
"retry_state": { "current_sha_retries_used": 0, "max_flaky_retries": 3 }
}
Signals
- GitHub stars
- 35
- Last commit
- Sep 2026
ahel review
K4blow
destructive-scoped
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
babysit-pr-rock3r- Source
- github.com/rock3r/spectre