babysit
Drive a PR to a clean review (Greptile 5/5, zero open threads) — ships if needed, keeps it mergeable against staging, triggers Greptile, fixes real findings, replies to and resolves every thread, and loops until clean
git clone --depth 1 https://github.com/simstudioai/sim /tmp/babysit && cp -r /tmp/babysit/.agents/skills/babysit ~/.claude/skills/babysitSKILL.md
# Babysit PRs
Owns a PR end-to-end through review: ship it, wait for the automatic review round, and if it
isn't already clean, drive fix → reply → resolve → re-review cycles until Greptile reports 5/5
and there are zero open comment threads, keeping the branch mergeable against staging along the
way. Designed to be run under `/loop` (no fixed interval — let it self-pace on review latency)
so it survives across multiple wakeups in the same session.
## When to use
- The user says "babysit this PR", "keep working the reviews until it's clean", or similar
- As the natural follow-up to `/ship` when the user wants the review loop automated rather than
manually re-triggering reviews and answering comments themselves
## Inputs
Needs a PR number. If none is given and there's no open PR for the current branch, run `/ship`
first (which includes the `origin/staging` sync check — see `.agents/skills/ship/SKILL.md`) to
create one.
## Definition of "clean"
Both must hold:
1. The latest Greptile summary comment reports **Confidence Score: 5/5**
2. `reviewThreads` (GraphQL, see below) has **zero threads with `isResolved: false`**
Do not stop early on "no new comments this round" alone — a thread can be open from an earlier
round. Always check both conditions freshly after every push.
## Loop
1. **Check current state** before doing anything, including whether the PR is still mergeable:
```bash
gh pr view <n> --json mergeable
gh pr view <n> --json comments -q '[.comments[] | select(.author.login=="greptile-apps")] | last | .body'
gh api graphql -f query='
query { repository(owner: "<owner>", name: "<repo>") { pullRequest(number: <n>) {
reviewThreads(first: 50) { pageInfo { hasNextPage endCursor } nodes { id isResolved path line
comments(first: 5) { nodes { id databaseId author { login } body } } } } } } }'
```
`[.comments[]] | last | .body`, not `... | .body | tail -1` — the latter pipes every matching
comment's full multi-line body through the pipeline and keeps only the final *line* of that
combined output (usually the "Reviews (n): Last reviewed commit..." footer), not the last
*comment*, so it silently misses the actual "Confidence Score: X/5" line.
`reviewThreads(first: 50)` is a single page — check `pageInfo.hasNextPage`. If `true`, don't
stop yet: re-run the same query with `after: "<endCursor>"` and keep paging until
`hasNextPage` is `false` before evaluating "clean." A PR with more than 50 threads is rare but
stopping on a partial page would silently miss unresolved ones past the cutoff.
If `mergeable` is `CONFLICTING`, fix that first (step 2). Otherwise, if Greptile is 5/5 and
every thread across all pages has `isResolved: true`, stop — report the outcome (see
"Reporting" below) and skip the rest of this list.
2. **If the PR has a merge conflict**, merge `origin/staging`, resolve the conflicts, run the
usual pre-push checks, push, and go to step 8 to re-trigger review.
3. **If no review has run yet** (fresh PR, no Greptile comments): Greptile usually runs
automatically on PR open — confirm via `gh pr checks <n>` (look for `Greptile Review`) and
wait for that first round before doing anything else.
4. **If a review round has landed and it isn't clean**: for every thread where
`isResolved: false`, triage the finding on its own merits — this is the part that requires
judgment, not a mechanical loop:
- **Real bug**: fix it in the cleanest way available. Match the codebase's existing
conventions for that kind of problem before inventing a new one (e.g. an SSRF-prone
user-supplied-host fetch should use whatever `validateUrlWithDNS`/`secureFetchWithPinnedIP`
pattern the rest of the codebase already uses for that exact situation — grep for a sibling
integration solving the same problem first). Never patch around a finding with a
workaround, a broad try/catch, or a suppression comment — fix the actual cause.
- **False positive**: don't change code. Reply with the specific reason it doesn't apply
(cite the type definition, the established pattern it matches, or the doc it follows) so
the reviewer bot and a human skimming later both understand why it was left as-is.
- **Already fixed by an earlier finding in the same round**: note that and resolve without a
duplicate code change.
5. **Reply to every thread individually** before resolving it — never resolve silently:
```bash
gh api repos/<owner>/<repo>/pulls/<n>/comments/<databaseId>/replies -f body="<what was done and why>"
```
Then resolve via GraphQL (needs the thread `id` from step 1, not the comment id):
```bash
gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "<threadId>"}) { thread { isResolved } } }'
```
6. **Before pushing, re-run the full sync check from `/ship` step 2** — not just the log command,
the whole check-and-recover flow (stash WIP if needed, rebase, verify the rebase didn't just
cleanly replay stray commits, cherry-pick rebuild if it did or if it conflicted). A babysit
loop spanning a long session is exactly the scenario where a branch can drift, and pushing
review fixes on top of undetected drift is how an oversized PR happens even after the branch
was fixed once. Then run the repo's pre-ship checks the same way `/ship` does before
committing — not just lint/typecheck/boundary-validation, but also the conditional `/cleanup`
(if this round's fix touched UI code) and `/db-migrate` (if it touched schema/migrations)
gates from `/ship` steps 4 and 5. A review-fix round is still a code change and can trip
either gate just as easily as the original commit did.
7. **Commit and push** the round's fixes as one commit — `--force-with-lease` whenever step 6's
sync check rewrote history, which includes a plain `git rebase origin/staging` that completed
with no conflicts, not only the cherry-pick rebuild path; both rewrite commiCreate or update a Sim integration block with correct subBlocks, conditions, dependsOn, modes, canonicalParamId usage, outputs, and tool wiring. Use when working on `apps/sim/blocks/blocks/{service}.ts` or aligning a block with its tools.
Add or update a Sim knowledge base connector for syncing documents from an external source, including auth mode, config fields, pagination, document mapping, tags, and registry wiring. Use when working in `apps/sim/connectors/{service}/` or adding a new external document source.
Add a code-defined table enrichment (registry entry) under `apps/sim/enrichments/` backed by an ordered provider cascade, ensuring every provider tool it calls has hosted-key support. Use when adding a per-row table enrichment that fills cells via existing Sim tools.
Add hosted API key support to a tool so Sim provides the key (metered and billed to the workspace) when a user has not brought their own. Use when adding a `hosting` config to a tool under `apps/sim/tools/{service}/`.
Add a complete Sim integration from API docs, covering tools, block, icon, optional triggers, registrations, resolved-secret/model-input safety, and integration conventions. Use when introducing a new service under `apps/sim/tools`, `apps/sim/blocks`, and `apps/sim/triggers`.
Add a new LLM model to apps/sim/providers/models.ts with specs verified against the provider's live API docs (no hallucination)
Create tool configurations for a Sim integration by reading API docs
Create webhook or polling triggers for a Sim integration