Skip to content

Commit 1c2f708

Browse files
chore(skills): teach babysit about cubic, not just Greptile (#7372)
* chore(skills): teach babysit about cubic, not just Greptile The loop only re-triggered `@greptile` after a push. Two bots review this repo, so a round would end with Greptile at 5/5 and cubic's threads still open against an earlier commit, their findings never re-checked against the fix. Adds what distinguishes them: cubic has no score and reports only inline threads, posts a fresh review per run rather than editing one comment in place, answers to `@cubic-dev-ai review this PR` rather than `@cubic`, and reviews the commit that was HEAD when its run started — so a stale thread is a reply-and-resolve, not a fix. Both are now re-triggered as separate comments and confirmed `pending` before the loop waits, since a trigger that silently failed is indistinguishable from a reviewer that has not started. Also promotes CI to a stop condition. A red required check is not clean no matter what either reviewer says, and the lint and audit jobs routinely catch what a local run does not. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore(skills): treat a pending check as unfinished, not as passing Two defects in the round this adds, both caught in review. The stop condition tested only for a failing check, so a check still running when both reviewers finished counted as clean and the loop reported the PR ready before CI had its say. It now requires every check to have finished and passed, and sends a pending one back to the wait step. The thread-attribution note pointed at `author.login` per thread, but `PullRequestReviewThread` has no author field — GitHub rejects the query with `Field 'author' doesn't exist on type 'PullRequestReviewThread'`. Identity lives on the comments, so it now names the real path and says not to lift the field to the thread level. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 23e1663 commit 1c2f708

1 file changed

Lines changed: 59 additions & 15 deletions

File tree

.agents/skills/babysit/SKILL.md

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
---
22
name: babysit
3-
description: 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
3+
description: Drive a PR to a clean review (Greptile 5/5, zero open threads) — ships if needed, keeps it mergeable against staging, re-triggers both Greptile and cubic, fixes real findings, replies to and resolves every thread, and loops until clean
44
---
55

66
# Babysit PRs
77

88
Owns a PR end-to-end through review: ship it, wait for the automatic review round, and if it
99
isn't already clean, drive fix → reply → resolve → re-review cycles until Greptile reports 5/5
1010
and there are zero open comment threads, keeping the branch mergeable against staging along the
11-
way. Designed to be run under `/loop` (no fixed interval — let it self-pace on review latency)
11+
way. Two bots review this repo — Greptile and cubic — and they behave differently; see
12+
"Two reviewers" below. Designed to be run under `/loop` (no fixed interval — let it self-pace on review latency)
1213
so it survives across multiple wakeups in the same session.
1314

1415
## When to use
@@ -23,20 +24,49 @@ Needs a PR number. If none is given and there's no open PR for the current branc
2324
first (which includes the `origin/staging` sync check — see `.agents/skills/ship/SKILL.md`) to
2425
create one.
2526

27+
## Two reviewers
28+
29+
Both post inline threads that count toward "clean", and they need re-triggering separately:
30+
31+
| | Greptile (`greptile-apps`) | cubic (`cubic-dev-ai`) |
32+
|---|---|---|
33+
| Verdict | `Confidence Score: X/5` in a summary comment | no score — only inline threads |
34+
| Summary comment | edited in place across rounds | fresh review per run |
35+
| Re-trigger | `@greptile` | `@cubic-dev-ai review this PR` |
36+
| Latency | 1–3 min | 1–3 min |
37+
38+
Post **both** after every push, as two separate comments. Triggering only Greptile is the easy
39+
mistake: the PR then shows 5/5 with cubic's threads still open from an earlier commit, and its
40+
findings never get re-checked against the fix.
41+
42+
`@cubic-dev-ai review this PR` is the documented wording — `@cubic` alone does not trigger it.
43+
44+
cubic reviews the commit that was HEAD when its run started, so a thread can describe code the
45+
next commit already changed. Before treating a cubic finding as real, check whether the current
46+
HEAD still has the problem — a stale round is a reply-and-resolve, not a fix.
47+
2648
## Definition of "clean"
2749

28-
Both must hold:
50+
All three must hold:
2951
1. The latest Greptile summary comment reports **Confidence Score: 5/5**
30-
2. `reviewThreads` (GraphQL, see below) has **zero threads with `isResolved: false`**
52+
2. `reviewThreads` (GraphQL, see below) has **zero threads with `isResolved: false`**, from
53+
either bot
54+
3. Every check has **finished and passed**`gh pr checks <n>` shows no `fail` *and* no
55+
`pending`. A red run is not clean no matter what the reviewers say, and the lint/audit jobs
56+
routinely catch what a local run misses. A `pending` one is not clean either: it has not
57+
reported yet, and treating "not failing" as "passing" reports the PR clean before CI has
58+
had its say. Wait for it — the step-10 stop condition covers a check that never settles.
3159

3260
Do not stop early on "no new comments this round" alone — a thread can be open from an earlier
33-
round. Always check both conditions freshly after every push.
61+
round, and cubic often lands its first threads a round after Greptile's. Always check all three
62+
conditions freshly after every push.
3463

3564
## Loop
3665

3766
1. **Check current state** before doing anything, including whether the PR is still mergeable:
3867
```bash
3968
gh pr view <n> --json mergeable
69+
gh pr checks <n> | grep -v skipping
4070
gh pr view <n> --json comments -q '[.comments[] | select(.author.login=="greptile-apps")] | last | .body'
4171
gh api graphql -f query='
4272
query { repository(owner: "<owner>", name: "<repo>") { pullRequest(number: <n>) {
@@ -51,16 +81,22 @@ round. Always check both conditions freshly after every push.
5181
stop yet: re-run the same query with `after: "<endCursor>"` and keep paging until
5282
`hasNextPage` is `false` before evaluating "clean." A PR with more than 50 threads is rare but
5383
stopping on a partial page would silently miss unresolved ones past the cutoff.
54-
If `mergeable` is `CONFLICTING`, fix that first (step 2). Otherwise, if Greptile is 5/5 and
55-
every thread across all pages has `isResolved: true`, stop — report the outcome (see
56-
"Reporting" below) and skip the rest of this list.
84+
The query returns both bots' threads. A `ReviewThread` has no author of its own — identity
85+
lives on its comments, so read the opener's at `comments.nodes[0].author.login` and do not
86+
add an `author` field at the thread level, which makes the query fail to compile.
87+
If `mergeable` is `CONFLICTING`, fix that first (step 2). If a check is failing, fix that too
88+
— treat it exactly like a review finding. If a check is still `pending`, do not evaluate
89+
"clean" at all: go to step 9 and wait for it. Otherwise, if Greptile is 5/5, every thread
90+
across all pages has `isResolved: true`, and every check has finished and passed, stop —
91+
report the outcome (see "Reporting" below) and skip the rest of this list.
5792

5893
2. **If the PR has a merge conflict**, merge `origin/staging`, resolve the conflicts, run the
5994
usual pre-push checks, push, and go to step 8 to re-trigger review.
6095

61-
3. **If no review has run yet** (fresh PR, no Greptile comments): Greptile usually runs
62-
automatically on PR open — confirm via `gh pr checks <n>` (look for `Greptile Review`) and
63-
wait for that first round before doing anything else.
96+
3. **If no review has run yet** (fresh PR, no bot comments): both run automatically on PR open —
97+
confirm via `gh pr checks <n>` (look for `Greptile Review` and `cubic · AI code reviewer`) and
98+
wait for both before doing anything else. They finish at different times, so a PR that looks
99+
clean because only one has reported is not clean yet.
64100

65101
4. **If a review round has landed and it isn't clean**: for every thread where
66102
`isResolved: false`, triage the finding on its own merits — this is the part that requires
@@ -113,14 +149,19 @@ round. Always check both conditions freshly after every push.
113149
rounds; checking sync only before the push (step 6) and never after is how a bad push or a
114150
PR whose commit history quietly went stale between rounds goes unnoticed.
115151

116-
8. **Re-trigger review** by posting `@greptile` as its own PR comment:
152+
8. **Re-trigger both reviewers**, each as its own PR comment — a combined comment does not
153+
reliably trigger both:
117154
```bash
118155
gh pr comment <n> --body "@greptile"
156+
gh pr comment <n> --body "@cubic-dev-ai review this PR"
119157
```
158+
Then confirm both actually picked it up before waiting — `gh pr checks <n>` should show
159+
`Greptile Review` and `cubic · AI code reviewer` as `pending`. If one stayed `pass` from the
160+
previous round, its trigger did not land; re-post that one.
120161

121162
9. **Wait for the new round**, then go back to step 1. Pace the wait with `ScheduleWakeup` using
122-
a fallback delay of ~250–300s (Greptile typically takes 1–3 minutes) — never busy-poll
123-
in a sleep loop. Pass the same `/loop babysit PR <n>` prompt on each wakeup so the loop
163+
a fallback delay of ~300s — both bots take 1–3 minutes, and CI is usually the slowest of the
164+
three — never busy-poll in a sleep loop. Pass the same `/loop babysit PR <n>` prompt on each wakeup so the loop
124165
resumes correctly.
125166

126167
10. **Stop conditions**: clean state reached (see above), or the same unresolved finding or
@@ -130,7 +171,8 @@ round. Always check both conditions freshly after every push.
130171
## Reporting
131172

132173
When the loop ends, summarize: how many rounds it took, what was actually fixed (one line each),
133-
what was pushed back on as a false positive and why, and the final Greptile score / thread count.
174+
what was pushed back on as a false positive and why, and the final state — Greptile score, open
175+
thread count across both bots, and whether every check finished and passed.
134176

135177
## Public-repo hygiene
136178

@@ -150,4 +192,6 @@ notification email.
150192
- Never fix a finding with a hacky workaround — if the clean fix isn't obvious, find the sibling
151193
pattern elsewhere in the codebase solving the same class of problem and match it.
152194
- Never silently drop a finding — every thread gets either a code fix or a reasoned reply.
195+
- Never re-trigger only one reviewer. Both get a comment after every push, and both get confirmed
196+
`pending` before you start waiting.
153197
- Always re-run the `/ship`-style sync check before every push in the loop, not just the first.

0 commit comments

Comments
 (0)