babysit
A configuration of loop-controller. That skill supplies the loop
machinery — primitive selection, the full guardrail stack, state
externalization. This skill supplies the three things specific to "keep a PR
healthy": the per-pass recipe (it schedules git-pr-feedback, it does
not re-implement it), the mechanical proof (zero open blocking findings +
mergeable), and the HITL boundary that decides what's AFK-safe vs what
pauses. Read loop-controller for the guardrails; they're inherited, not
repeated here.
Why disable-model-invocation: this loop commits, pushes, rebases, and
touches a live PR thread on its own, on a clock. It is user-driven — you want
to type /loop 5m /babysit (or /babysit), not have Claude silently start
tending a PR because a reviewer happened to comment.
The 5-part contract
| Part |
This loop |
| trigger |
an open PR of yours with potential review activity; scheduled via /loop 5m /babysit, or an explicit /babysit (optionally a PR number) |
| action |
ONE pass: fetch new review findings (Copilot + human) via git-pr-feedback → triage → address one root-cause finding (or rebase if base moved) → re-run the project gate → push → reconcile the PR thread. One change per pass; re-check the whole PR state after |
| proof |
the gh PR review/status query returns zero OPEN actionable/blocking comments AND mergeable == "MERGEABLE" (up to date with base, CI green) — default-FAIL: assume findings are unaddressed until the fetch proves otherwise (treat mergeable == "UNKNOWN" as not-yet-proven and re-check) |
| memory |
a per-PR fix log (findings addressed, findings deferred + why), git history, and the PR thread itself — all durable across the session-scoped /loop fires |
| stop |
zero blocking findings AND mergeable OR poll/iteration cap OR no-progress for 3 rounds (same finding unaddressed 3×) OR budget cap OR an HITL checkpoint is hit |
The proof: zero blocking findings AND mergeable, default-FAIL
"Healthy" is not "I replied to the last comment." It is two conditions
observed together from gh: the PR has zero open, actionable, blocking
review comments, and GitHub reports it mergeable (rebased onto base, CI
green). Assume the PR is not healthy until a fresh fetch proves both — that's
the default-FAIL stance, and it's why every pass re-fetches rather than
trusting last pass's verdict. A loop that stops after answering one comment ships
a PR that picked up three new ones and went stale behind a base push.
Name the artifact explicitly: a gh pr view --json mergeable,reviewDecision
plus the open-comments count from git-pr-feedback's fetch (see
references/scheduling.md for the exact query). Both must read clean in the
same pass.
Step 1 — One pass = one git-pr-feedback cycle
The per-pass work is git-pr-feedback: identify the PR, fetch inline +
issue comments + review summaries (paginated), triage each by author and
category, address what's clear, reply on GitHub. Do not re-document or
re-implement that — invoke it. babysit adds only the loop discipline around it:
one root-cause change per pass, then re-check the whole PR state. If the base
branch moved and the only blocker is staleness, the pass is a routine rebase (not
a finding fix). The full per-pass algorithm and the handoff are in
references/scheduling.md.
Step 2 — Schedule it with /loop (the watcher, not /goal)
Per loop-controller Step 1: this is a watch/poll job — you wait for review
activity to change on a cadence — so the primitive is /loop, the
scheduler, not /goal (which pushes to a finish line). The recipe is the
documented daily driver:
/loop 5m /babysit
/loop is session-scoped, expires after ~3 days, and does not catch up on
missed intervals — those mechanics (and the loop.md self-paced variant) live in
loop-controller's references/primitives.md; don't re-document them. What goes
in loop.md and how to scope the run to one PR are in
references/scheduling.md.
HITL is load-bearing for this loop
babysit runs only inside the reversible boundary unattended. The irreversible
or human-facing actions are HITL checkpoints — never autonomous:
- Force-push / rebasing a shared branch — pause. A fast-forward push of your
own commits is fine; a history rewrite of a branch others may have pulled is
not.
- Resolving or replying to a human reviewer's conversation — pause. A
bot/Copilot nit can be answered and resolved unattended; a human's thread is a
conversation, and you do not argue with a reviewer inside a loop. On any
substantive disagreement with a human reviewer, stop and surface it.
- Merging — never. babysit does not auto-merge, full stop. Reaching the
proof (zero blocking + mergeable) means ready for the human to merge, not
"merge it."
Within the boundary — addressing Copilot/bot nits, routine fast-forward rebases,
re-running the gate, fast-forward pushes — it is AFK-safe. The full AFK-safe vs
pause table is in references/scheduling.md.
Guardrails specific to this loop
Inherits the full stack from loop-controller → references/safety.md. The caps
this loop sets:
- Poll / iteration cap —
/loop's ~3-day session expiry is the outer bound;
set an inner per-PR pass cap (default ~20) so a wedged PR doesn't burn the
whole window. Hitting it is a stop-and-escalate, not a reason to loosen the
proof.
- No-progress detection — if the same blocking finding survives 3
consecutive passes (addressed but the reviewer/check still flags it, or it
can't be resolved within the reversible boundary), stop and surface it. Three
passes on one finding means it needs a human, not a fourth attempt.
- Budget cap — a watch loop that fires every 5 minutes for days adds up;
enforce a token/cost ceiling that terminates the loop (read it from
.claude/profile.yaml when present), not just warns.
- Never cheat the proof. Don't mark a thread resolved without addressing it,
don't dismiss a human reviewer's comment to clear the count, and don't merge to
make "mergeable" moot. A green that came from silencing a reviewer is a
finding, not a win.
Choosing the driver primitive
/loop 5m /babysit is the scheduler. The per-pass exit (this pass made one
clean, reversible change and re-checked the PR) is provable from gh output, so a
pass can run under auto mode unattended within the HITL boundary above. The loop
as a whole has no /goal finish line — it watches until you stop it or a stop
condition fires.
Long-run hygiene (wired per loop-controller Step 6)
This loop runs unattended for days, so the Claude 5 long-run rules are part of
its contract, not inherited ambience (drop-in text: model-adaptation →
references/long-run-hygiene.md):
- Evidence-backed progress — every per-pass report line (finding addressed,
rebase done, gate green) traces to a tool result from that pass: the
gh
query output, the gate's exit code, the push result. Never narrate a fix the
re-fetch didn't confirm.
- Don't end a pass on a promise — a pass ends with the change made and the
whole PR state re-checked, or at an explicit HITL stop; never with "I'll
rebase next pass" and no action. The autonomous-operation reminder applies
while the user is away — the HITL checkpoints above are the only sanctioned
pauses.
- Budget is a harness decision — the cost ceiling reads from externalized
state (
.claude/profile.yaml); don't surface a remaining-token countdown to
the working pass, and never summarize-and-quit on a phantom context worry.
- Effort per pass — routine nit/rebase passes run at
medium/high;
reserve xhigh for a genuinely hard finding (tiering: model-adaptation).
Reference files
references/scheduling.md — the per-pass algorithm and the git-pr-feedback
handoff, the scheduling recipe (/loop 5m /babysit, what to put in loop.md,
scoping to one PR, the exact gh proof query), and the HITL boundary table
(what's AFK-safe vs what pauses).
1---2name: babysit3description: Keep one of your open PRs healthy on a schedule: poll for new review activity, auto-address bot/Copilot nits and routine rebases, re-run the project gate, and reconcile the PR thread — looping until the PR has zero blocking findings and is mergeable, with HITL checkpoints on anything irreversible. This is the scheduled, guardrailed loop around git-pr-feedback (which does the per-pass fetch/triage/fix). Run it as Boris Cherny's daily-driver "/loop 5m /babysit", or invoke /babysit once. Use when you want a PR babysat while you work elsewhere, want review comments auto-handled on a cadence, or want a PR kept rebased and green. Trigger on "babysit my PR", "babysit prs", "watch this PR", "keep my PR green", "auto-address review comments on a schedule", "loop 5m babysit", "keep the PR rebased", "poll the PR for new feedback". Never auto-merges and never force-pushes a shared branch unattended. A configuration of loop-controller.4---56# babysit78> **A configuration of [`loop-controller`].** That skill supplies the loop9> machinery — primitive selection, the full guardrail stack, state10> externalization. This skill supplies the three things specific to "keep a PR11> healthy": the **per-pass recipe** (it schedules [`git-pr-feedback`], it does12> not re-implement it), the **mechanical proof** (zero open blocking findings +13> mergeable), and the **HITL boundary** that decides what's AFK-safe vs what14> pauses. Read `loop-controller` for the guardrails; they're inherited, not15> repeated here.16>17> **Why `disable-model-invocation`:** this loop commits, pushes, rebases, and18> touches a live PR thread on its own, on a clock. It is user-driven — you want19> to *type* `/loop 5m /babysit` (or `/babysit`), not have Claude silently start20> tending a PR because a reviewer happened to comment.2122## The 5-part contract2324| Part | This loop |25|---|---|26| **trigger** | an open PR of yours with potential review activity; scheduled via `/loop 5m /babysit`, or an explicit `/babysit` (optionally a PR number) |27| **action** | ONE pass: fetch new review findings (Copilot + human) via [`git-pr-feedback`] → triage → address **one root-cause finding** (or rebase if base moved) → re-run the project gate → push → reconcile the PR thread. One change per pass; re-check the whole PR state after |28| **proof** | the `gh` PR review/status query returns **zero OPEN actionable/blocking comments AND `mergeable == "MERGEABLE"`** (up to date with base, CI green) — default-FAIL: assume findings are unaddressed until the fetch proves otherwise (treat `mergeable == "UNKNOWN"` as not-yet-proven and re-check) |29| **memory** | a per-PR fix log (findings addressed, findings deferred + why), git history, and the PR thread itself — all durable across the session-scoped `/loop` fires |30| **stop** | zero blocking findings **AND** mergeable **OR** poll/iteration cap **OR** no-progress for 3 rounds (same finding unaddressed 3×) **OR** budget cap **OR** an HITL checkpoint is hit |3132## The proof: zero blocking findings AND mergeable, default-FAIL3334"Healthy" is not "I replied to the last comment." It is **two conditions35observed together from `gh`**: the PR has zero *open, actionable, blocking*36review comments, **and** GitHub reports it mergeable (rebased onto base, CI37green). Assume the PR is **not** healthy until a fresh fetch proves both — that's38the default-FAIL stance, and it's why every pass *re-fetches* rather than39trusting last pass's verdict. A loop that stops after answering one comment ships40a PR that picked up three new ones and went stale behind a base push.4142Name the artifact explicitly: a `gh pr view --json mergeable,reviewDecision`43plus the open-comments count from `git-pr-feedback`'s fetch (see44`references/scheduling.md` for the exact query). Both must read clean *in the45same pass*.4647## Step 1 — One pass = one git-pr-feedback cycle4849The per-pass work **is** [`git-pr-feedback`]: identify the PR, fetch inline +50issue comments + review summaries (paginated), triage each by author and51category, address what's clear, reply on GitHub. **Do not re-document or52re-implement that** — invoke it. babysit adds only the loop discipline around it:53one root-cause change per pass, then re-check the *whole* PR state. If the base54branch moved and the only blocker is staleness, the pass is a routine rebase (not55a finding fix). The full per-pass algorithm and the handoff are in56`references/scheduling.md`.5758## Step 2 — Schedule it with /loop (the watcher, not /goal)5960Per `loop-controller` Step 1: this is a **watch/poll** job — you wait for review61activity to *change* on a cadence — so the primitive is **`/loop`**, the62scheduler, **not** `/goal` (which pushes to a finish line). The recipe is the63documented daily driver:6465```66/loop 5m /babysit67```6869`/loop` is **session-scoped, expires after ~3 days, and does not catch up** on70missed intervals — those mechanics (and the `loop.md` self-paced variant) live in71`loop-controller`'s `references/primitives.md`; don't re-document them. What goes72in `loop.md` and how to scope the run to one PR are in73`references/scheduling.md`.7475## HITL is load-bearing for this loop7677babysit runs **only inside the reversible boundary** unattended. The irreversible78or human-facing actions are **HITL checkpoints — never autonomous**:7980- **Force-push / rebasing a shared branch** — pause. A fast-forward push of your81 own commits is fine; a history rewrite of a branch others may have pulled is82 not.83- **Resolving or replying to a *human* reviewer's conversation** — pause. A84 bot/Copilot nit can be answered and resolved unattended; a human's thread is a85 conversation, and **you do not argue with a reviewer inside a loop.** On any86 substantive disagreement with a human reviewer, stop and surface it.87- **Merging** — never. babysit does **not** auto-merge, full stop. Reaching the88 proof (zero blocking + mergeable) means *ready for the human to merge*, not89 "merge it."9091Within the boundary — addressing Copilot/bot nits, routine fast-forward rebases,92re-running the gate, fast-forward pushes — it is AFK-safe. The full AFK-safe vs93pause table is in `references/scheduling.md`.9495## Guardrails specific to this loop9697Inherits the full stack from `loop-controller` → `references/safety.md`. The caps98this loop sets:99100- **Poll / iteration cap** — `/loop`'s ~3-day session expiry is the outer bound;101 set an inner per-PR pass cap (default ~20) so a wedged PR doesn't burn the102 whole window. Hitting it is a *stop-and-escalate*, not a reason to loosen the103 proof.104- **No-progress detection** — if the **same blocking finding** survives **3105 consecutive passes** (addressed but the reviewer/check still flags it, or it106 can't be resolved within the reversible boundary), stop and surface it. Three107 passes on one finding means it needs a human, not a fourth attempt.108- **Budget cap** — a watch loop that fires every 5 minutes for days adds up;109 enforce a token/cost ceiling that *terminates* the loop (read it from110 `.claude/profile.yaml` when present), not just warns.111- **Never cheat the proof.** Don't mark a thread resolved without addressing it,112 don't dismiss a human reviewer's comment to clear the count, and don't merge to113 make "mergeable" moot. A green that came from silencing a reviewer is a114 *finding*, not a win.115116## Choosing the driver primitive117118`/loop 5m /babysit` is the scheduler. The *per-pass* exit (this pass made one119clean, reversible change and re-checked the PR) is provable from `gh` output, so a120pass can run under auto mode unattended within the HITL boundary above. The loop121as a whole has **no `/goal` finish line** — it watches until you stop it or a stop122condition fires.123124## Long-run hygiene (wired per loop-controller Step 6)125126This loop runs unattended for days, so the Claude 5 long-run rules are part of127its contract, not inherited ambience (drop-in text: `model-adaptation` →128`references/long-run-hygiene.md`):129130- **Evidence-backed progress** — every per-pass report line (finding addressed,131 rebase done, gate green) traces to a tool result from *that pass*: the `gh`132 query output, the gate's exit code, the push result. Never narrate a fix the133 re-fetch didn't confirm.134- **Don't end a pass on a promise** — a pass ends with the change made and the135 whole PR state re-checked, or at an explicit HITL stop; never with "I'll136 rebase next pass" and no action. The autonomous-operation reminder applies137 while the user is away — the HITL checkpoints above are the only sanctioned138 pauses.139- **Budget is a harness decision** — the cost ceiling reads from externalized140 state (`.claude/profile.yaml`); don't surface a remaining-token countdown to141 the working pass, and never summarize-and-quit on a phantom context worry.142- **Effort per pass** — routine nit/rebase passes run at `medium`/`high`;143 reserve `xhigh` for a genuinely hard finding (tiering: `model-adaptation`).144145## Reference files146147- `references/scheduling.md` — the per-pass algorithm and the `git-pr-feedback`148 handoff, the scheduling recipe (`/loop 5m /babysit`, what to put in `loop.md`,149 scoping to one PR, the exact `gh` proof query), and the HITL boundary table150 (what's AFK-safe vs what pauses).151152[`loop-controller`]: ../loop-controller/SKILL.md153[`git-pr-feedback`]: ../../git/git-pr-feedback/SKILL.md154[`git-pr`]: ../../git/git-pr/SKILL.md155[`git-commit`]: ../../git/git-commit/SKILL.md