Files
compound-engineering-plugin…/docs/guides/ce-babysit-pr.md

13 KiB

ce-babysit-pr

Watch an open GitHub PR and keep it moving toward merge-ready. Report when it looks ready. Land only if you asked.

ce-babysit-pr is the post-open watch. It is a git-workflow skill, not a core-loop step. After /ce-commit-push-pr opens a PR, this skill watches three streams (review comments, CI, base-branch movement) until the PR looks ready, is blocked, hits a budget, or is merged/closed.

It is a conductor. It does not fix comments or diagnose CI itself. Comments go to /ce-resolve-pr-feedback. Real CI failures go to /ce-debug. This skill owns the loop, the order, dedup across ticks, the settle window, bounded branch maintenance, and the stop.

That is the contrast with /ce-resolve-pr-feedback, which is a one-pass "fix the comments now" skill. Use that when you want a single round you watch. Use this when you want the PR driven over time.

Posture sets the scope. Default is target (the named PR only). On a confirmed managed stack you can choose stack-ready (advance upstack as soon as a layer has nothing actionable — even while its CI is still running — with lower layers kept under probe; no merge) or stack-land (same walk, plus gh stack merge of the bottom-most open settled prefix). Settled is not merged. A layer can look ready and still be OPEN.

It cannot promise merge-readiness. A reviewer can still comment later. Required checks can change. Under target and stack-ready, you merge. Selecting stack-land is land authorization for that managed prefix.

GitHub only, including GitHub Enterprise that gh is configured for.


TL;DR

Question Answer
What does it do? Watches an open PR (or a confirmed managed stack) and reacts to comments, CI, and base movement
When to use it A PR is open and you want it driven toward merge without handling each round yourself
What it produces Delegated comment and CI fixes, surfaced needs-human items, optional stack-layer moves, and an outcome-first summary
How it works Delegates comments to /ce-resolve-pr-feedback and CI to /ce-debug. Owns the loop, posture, and stop.
Modes In-session watch (default) or Checkpoint. Postures: target / stack-ready / stack-land.

Example invocations

Empty invoke watches the current branch's PR. A number or URL pins the PR. watch / checkpoint force the loop style. posture: is separate from that.

# Current branch's PR. In-session watch if the harness can wake you; else one checkpoint tick.
/ce-babysit-pr

# Named PR
/ce-babysit-pr 1234
/ce-babysit-pr https://github.com/acme/widgets/pull/1234

# One tick, persist, print the exact resume command. Monitoring is paused.
/ce-babysit-pr 1234 checkpoint

# Force the in-session watch even if the harness would have picked checkpoint
/ce-babysit-pr 1234 watch

# Cap the active-time budget (default is 8 hours of active watch time)
/ce-babysit-pr 1234 2 hours

# Confirmed managed stack: walk upstack as layers go quiet (CI may still run). Do not merge.
/ce-babysit-pr posture:stack-ready

# Same walk, and land the settled prefix when green
/ce-babysit-pr posture:stack-land

For a single pass over comments you want to watch yourself, use /ce-resolve-pr-feedback instead.


The Problem

Hand-babysitting, or a naive loop, usually fails in the same ways:

  • Wait for the whole CI run, then read comments. A comment fix pushes and retriggers CI, so that wait burned a cycle
  • CI goes green, the loop says ready, and review lands after
  • The watcher reimplements feedback resolution and CI debugging, then drifts from those skills
  • An in-session sleep loop cannot run in a sandboxed GUI harness, and Claude Code blocks foreground sleep
  • The run stops and you cannot tell what it did, or you get a wall of per-thread receipts

The Solution

Each tick is stateless and resumable from disk. The harness only has to wake the agent when something changed.

  • Comments first. New review threads and non-thread comments are handled before CI. After that pass, if a commit was pushed, the old CI failure is against a dead SHA and is skipped
  • Delegation. /ce-resolve-pr-feedback for comments, /ce-debug for real failures (once per new signature). The only inline CI work is a cheap flaky-vs-real split
  • Consumption-only branch currency. The base is merged or updated into the PR only when the snapshot emits a branch_currency item (BEHIND via GitHub's update-branch endpoint, DIRTY via an exact-base local repair) and only after it is claimed; ordinary base movement on a CLEAN PR, a sibling merging, or someone saying "update the branch" never triggers one. A disputable conflict becomes a sticky needs-human; an unrequested base merge on the head is flagged as a defect
  • Settle window. "Looks ready" needs GitHub CLEAN, no open feedback, no parked needs-human, and enough quiet time. A started-but-unfinished review waits at least 15 quiet minutes and at most 30
  • In-session watch by default. pr-snapshot watch polls with no agent tokens and prints BABYSIT_WAKE only on an actionable change. If the harness cannot background-and-wake, the skill runs one checkpoint tick and prints the resume command
  • Posture for confirmed managed stacks. target stops at the named PR. stack-ready continues upstack without merging. stack-land continues and lands the settled prefix

A needs-human item blocks the ready call. It does not end the watch. New comments and CI still get handled.


What Makes It Novel

Comments before CI, then drop the stale SHA

Within a tick: terminal check, then comments, then re-check the head SHA, then CI only if that SHA did not move. A CI fix is never applied against a pre-comment commit.

The same rule applies to an in-progress review (an 👀 or a "reviewing…" note). Already-posted comments are handled immediately. The signal only withholds the "looks ready" call.

One tick, any driver

State lives under /tmp/compound-engineering-<effective-uid>/ce-babysit-pr/<host>-<owner>-<repo>-<pr>/ (under $TMPDIR/compound-engineering-<effective-uid>/ instead when /tmp cannot host a writable private root, as in a sandbox that only allowlists $TMPDIR). A later invoke, a checkpoint resume, or a durable scheduler all drive the same tick. That is why the skill can run in a CLI session or fall back in a GUI harness that cannot keep a background wait.

Default budget is 8 hours of active watch time (laptop-sleep gaps are excluded). A 3-calendar-day wall-clock backstop caps every run. You can pass a shorter duration at invoke.

Looks ready is a cooling-off judgment

Ready is not "CI is green." GitHub must report the PR mergeable against the current base, the attention set must be empty, and the quiet window (default 5 minutes when no review signal was seen) must have elapsed. An incomplete review lifecycle uses the 15 / 30 minute bounds above. Even then the summary says "looks ready, your call" or "cautiously looks ready."

When a fork PR's CI is waiting on maintainer approval, the skill drains review for a bounded window (5, 15, or 30 minutes) and then hands back. It never approves the workflow run. Pipeline mode returns that blocker immediately.

Posture is a run value, not a keyword guess

Only a fresh probe with manager_status == "confirmed" activates stack-wide continuation. A manual base/head chain never does.

Posture Behavior
target Named PR only. Stop at looks-ready. May offer once to continue upstack. Never merges.
stack-ready Once a layer is quiescent (zero actionable backlog, no standing residual), continue to the next open non-draft layer that needs work; lower layers stay probed and pull the walk back if they re-open. Never merges.
stack-land Like stack-ready, plus gh stack merge of the bottom-most open settled PR, then gh stack sync.

A just-landed MERGED under stack-land is a layer transition, not the end of the whole run.


Quick Example

/ce-commit-push-pr opens PR #1234 and hands off. /ce-babysit-pr confirms GitHub, checks out the PR head, and starts pr-snapshot watch.

A review bot posts three inline threads while CI is still running. The next tick sends them to /ce-resolve-pr-feedback, which fixes two and parks one as needs-human. That push invalidates the in-flight CI SHA, so the skill does not debug the old failure.

New CI comes back red on a real test. /ce-debug fixes and pushes. Base moves; the PR is BEHIND. Host branch-update succeeds because the merge is mechanical.

The parked thread still blocks "ready." A reviewer answers it. The next tick resolves the rest, waits out the settle window, and reports looks-ready. You merge.


When to Reach For It

Use ce-babysit-pr when:

  • A PR is open and you want it driven toward merge without handling each round
  • You are about to context-switch and still want comments and CI handled
  • /ce-commit-push-pr just opened a PR (handoff is the default)
  • You own a confirmed managed stack and want stack-ready or stack-land

Skip it when:

  • The remote is not GitHub (GitLab, Bitbucket). The skill stops up front rather than half-running
  • No PR exists, or the PR is already merged or closed
  • An automatic handoff landed on a draft. A direct invoke that resolves to that draft is fine; watch / checkpoint also arms it
  • You want to approve each fix before it is pushed -> /ce-resolve-pr-feedback one pass at a time
  • The only issue is one known bug -> /ce-debug

Chain Position

On-demand, after a PR exists.

/ce-work  ->  /ce-commit-push-pr  ->  /ce-babysit-pr
                                       |-- new comments -> /ce-resolve-pr-feedback
                                       |-- real CI      -> /ce-debug
                                       |-- base moved   -> bounded branch maintenance

Use /ce-resolve-pr-feedback directly when you want one manual pass. Use this skill when you want that pass (and CI, and base movement) repeated until ready.


Use Standalone

  • Current branch: /ce-babysit-pr
  • Specific PR: /ce-babysit-pr 1234 or a URL
  • One tick: /ce-babysit-pr 1234 checkpoint
  • Stack: /ce-babysit-pr posture:stack-ready or posture:stack-land

Reference

Argument Effect
(empty) Current branch's PR. Mode from harness capability. Posture target.
<PR number or URL> That PR
watch / checkpoint Force the execution mode
<duration> Active-time budget (default 8 hours). Example: 2 hours.
posture:target|stack-ready|stack-land Run scope on a confirmed managed stack
mode:pipeline Bounded synchronous ticks for an orchestrator. No settle wait. Structured return.

scripts/pr-snapshot is the snapshot and state helper: it paginates review threads, records CI and branch currency, and emits the per-tick attention set. Its watch subcommand is the token-free change detector (with --downstack-pr it also probes lower stack layers so the walk returns when one re-opens). A newer successful invoke takes ownership; older wakes are stale hints. The skill body itself is a short always-loaded kernel; the tick commands, currency routes, stack contract, settle policy, and report shape live in the skill's references/ (tick.md, branch-currency.md, stack.md, settle.md, report.md, watch-loop.md).


FAQ

Does it merge the PR? Under target and stack-ready, no. It tells you when the PR looks ready. For a managed stack it prints the exact gh stack merge command when ready-as-next. Under stack-land, that posture authorizes landing the bottom-most open settled prefix via gh stack merge + sync.

Why not wait for CI, then handle comments? A comment fix pushes and retriggers CI. Handling comments during the run collapses the two timelines.

How does it avoid "green, then surprise review"? It never calls ready on one green snapshot. It needs CLEAN, an empty attention set, and a settle window. A started review gets 15 to 30 quiet minutes. Late activity resets the clock. The wording stays "looks ready, your call."

Does it run forever in the background? The default is an in-session watch: a token-free detector wakes the agent only when something changed. Close the session and re-invoke to resume from disk. For a multi-day unattended watch, use a durable scheduler (or cron running the resume command). It never fakes a loop with foreground sleep.

Does it fix CI itself? It classifies (flaky -> one rerun; real -> /ce-debug) and delegates. Comments go to /ce-resolve-pr-feedback.

What about merge conflicts? It previews the exact observed base first. It completes a merge only when every conflict has one mechanical answer that preserves the PR's intent, and when push authority to that head is known. Otherwise it parks a needs-human. It never rebases or force-pushes. Managed stacks stay on the manager's restack path.

What happens when the base keeps moving? Each distinct head/base/status observation has a bounded claim-and-confirm cycle. Routine movement can be applied many times. The same unchanged observation is not retried across restarts. A parked semantic conflict stays parked when later base commits do not change the conflict.


See Also