babysit · v1.1.0 · 2026-07-22 · sha256 e67cfc6b7dd8edc3
babysit v1.1.0A
Immutable. This exact content never changes and is served at /api/v1/blob/e67cfc6b7dd8edc3.
--- name: babysit version: 1.1.0 description: >- 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. requires_claude_code: true min_plan: starter disable-model-invocation: true allowed-tools: ["Read", "Edit", "Bash", "Grep", "Glob"] composes_with: ["loop-controller", "git-pr-feedback", "git-pr", "git-commit", "loop"] spawned_by: [] --- # 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). [`loop-controller`]: ../loop-controller/SKILL.md [`git-pr-feedback`]: ../../git/git-pr-feedback/SKILL.md [`git-pr`]: ../../git/git-pr/SKILL.md [`git-commit`]: ../../git/git-commit/SKILL.md