Skip to content
Back to skills

Babysit Pr

ASecurity

Use when an open apijack PR (base `dev`) is mid-review-cycle and needs to be driven to `first pass reviewed`. Picks up cold from any in-flight state — `changes requested`, `review in progress`, `needs review`, or freshly opened. Covers both interactive and `--non-interactive` (cron) modes.

  • 7 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 27, 2026
toolstypescriptrustgoshellbashcode-reviewgitapi

Works with

  • claude code
  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add normalled/apijack --skill babysit-pr --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Babysit Pr?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Babysit Pr
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/normalled-babysit-pr/badge)](https://www.skillsdirectory.com/skills/normalled-babysit-pr)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: babysit-pr
description: Use when an open apijack PR (base `dev`) is mid-review-cycle and needs to be driven to `first pass reviewed`. Picks up cold from any in-flight state — `changes requested`, `review in progress`, `needs review`, or freshly opened. Covers both interactive and `--non-interactive` (cron) modes.
---

# Babysit PR

Take over an open apijack PR mid-cycle and drive it to `first pass reviewed`. Loops review → respond → wait until done.

This skill **does not merge**. After `first pass reviewed` lands, stop and report — the `final-review` skill (with its soak window) owns the merge.

## When to Use

- An open apijack PR with base `dev` exists and you're picking it up cold.
- Current label is `changes requested`, `review in progress`, `needs review`, or no review-state label yet.

## When NOT to Use

- PR base is `main` → out of scope. That path is `ship-release` / `patch-deployer`.
- PR is closed or merged → nothing to do.
- Label is already `first pass reviewed` with no outstanding blocking items → report and stop; do not re-review.
- You are creating a brand-new PR → that's `implement-issue`.
- You are merging a `first pass reviewed` PR → that's `final-review`.

## Modes

**Interactive (default)**: a human is available to answer questions.

**Non-interactive**: triggered when **either** of:
- The skill is invoked with the literal flag `--non-interactive`.
- The prompt says "you are running non-interactively" or equivalent cron framing.

In non-interactive mode you make the best decision with the context you have, or halt and report — never ask the user.

## Steps

### 1. Identify the PR and refuse if out of scope

```bash
gh pr view <pr> --json number,state,baseRefName,headRefName,headRefOid,labels,reviewDecision,url
gh pr checks <pr>
```

Refuse and stop if `state` ≠ `OPEN` or `baseRefName` ≠ `dev`. Capture `headRefOid` — you'll re-check it before pushing to detect concurrent force-pushes.

### 2. Get on the branch

If a worktree exists at `../apijack-<slug>`, `cd` there. Otherwise:

```bash
gh pr checkout <pr>
```

### 3. Pull the FULL latest review (do not trust the prompt's summary)

The prompt may have pasted only an excerpt. Always re-fetch:

```bash
# Latest top-level review body
gh pr view <pr> --json reviews --jq '.reviews | sort_by(.submittedAt) | .[-1] | {state, author: .author.login, submittedAt, body}'

# Inline (line-anchored) review comments — often carry the specifics
gh api "repos/{owner}/{repo}/pulls/<pr>/comments" --jq '.[] | {path, line, user: .user.login, body, created_at}'

# Conversation comments (human follow-ups after the bot review)
gh pr view <pr> --comments --json comments --jq '.comments | sort_by(.createdAt) | .[] | {user: .author.login, createdAt, body}'
```

Treat the live review as truth. If it disagrees with the prompt's summary, the live review wins.

### 4. Branch on the current label

| Label | Action |
|-------|--------|
| `first pass reviewed` (no outstanding blockers) | Report and STOP. Done. |
| `review in progress`, `needs review`, no review-state label | Skip to step 8 (wait). |
| `changes requested` | Continue to step 5. |

### 5. Categorize each blocking item: simple vs non-trivial

For every blocking item in the latest review:

- **Simple**: localized (single file, ≲ 10 lines), unambiguous fix, no public-API or design impact. Examples: variable rename, typo, missing flag, exit-code propagation bug with a clearly correct patch suggested by the reviewer.
- **Non-trivial**: multi-file, public API or generated-code surface, design tradeoff, or you don't know what the right fix is.

> **Sanity-check the review against reality.** If the review references a symbol or path that doesn't exist (e.g., `tmpFile` in a file that has no such variable, or `src/plugins/` when the dir is `src/plugin/`), do not silently invent an interpretation. **Treat as non-trivial** and use step 7.

If **all** blocking items are simple → step 6. If **any** is non-trivial → step 7.

### 6. Apply simple fixes

Edit surgically. Do not "improve" adjacent code. Do not match verification depth to your enthusiasm — match it to the change:

- For shell-only changes: `bash -n <script>` is sufficient. Optionally `shellcheck` if available.
- For TypeScript/source changes: `bun test` and `bun run lint` (both must pass).
- Skip `bun test` only if no `.ts` file changed. `bun run lint` is cheap — always run it for source changes.

**Subagent code-review (`Skill(skill="superpowers:requesting-code-review")`) is OPTIONAL for one-line / single-file trivial fixes. REQUIRED for multi-file diffs or anything you'd hesitate to push without a second pair of eyes.**

Then go to step 9.

### 7. Non-trivial: gather context, then decide

#### 7a. Interactive mode

Ask the user with this exact menu structure (adapt the bulleted findings to the actual review):

```
The blocking items are:
- <item 1 with one-line classification: simple/non-trivial and why>
- <item 2 ...>
- <item 3 ...>

<short summary of what's hard about the non-trivial items>

Would you like me to:

1. Evaluate the full scope, background & reasoning of the PR (PR body, linked issue via "Closes #N", prior discussions, commit history)
2. Investigate the code changes directly (diff + relevant files)
3. Both 1 & 2 sequentially
4. Both 1 & 2 dispatched as parallel subagents
```

Wait for the answer. Then:
- **1** → load PR body + `gh issue view <linked>` + earlier reviews / discussions
- **2** → `gh pr diff <pr>` + targeted reads on the cited files
- **3** → 1 then 2
- **4** → invoke `superpowers:dispatching-parallel-agents` with two subagent prompts (one for scope, one for code)

When you have the context, **propose the fix to the user with explicit options** (e.g., rename / document / push back on reviewer). **Never silently pick.** It's fine to surface a third option the reviewer didn't mention if it's smaller / safer — but present it as an option, don't apply it. Once the user picks, return to step 6.

#### 7b. Non-interactive mode

Gather context progressively. Stop at the first level that gives you a confident, low-risk fix:

1. **Code first**: `gh pr diff <pr>` + read cited files.
2. **PR body**: PR description, prior reviews, comments.
3. **Linked issue**: `gh issue view <N>` for the issue referenced by `Closes #N`.

If after all three you still can't make a confident fix, **halt and report** (do not push a guess):

```bash
# Use the Write tool to write the report body to a tempfile, then:
gh pr comment <pr> --body-file <path>
exit 1
```

The comment must include:
- A clear "🤖 babysit-pr halted" header so a human can spot it.
- What context you gathered.
- Why you couldn't make a confident fix.
- What additional input is needed.

Always use `--body-file`, never inline `--body` — backticks get silently escaped otherwise (project CLAUDE.md).

### 8. Wait for the next review

The automated reviewer runs on a `*/5 * * * *` cron — every 5 minutes (e.g., 7:45, 7:50, 7:55). After a push, expect the verdict on the *next* tick plus reviewer wall time. Total wait is typically 5–10 minutes, sometimes more for big diffs.

**Use the existing wait script. Do not hand-roll polling.**

```bash
./scripts/wait-for-review.sh <pr>
```

In Claude Code: invoke via the Bash tool with `run_in_background: true`. The foreground 2-minute timeout would kill the script mid-wait. Background mode delivers a completion notification on exit, with the verdict and review body in the output.

The script captures the latest-review timestamp at start, so it correctly waits for the *next* review even across multiple push cycles.

When the notification fires, read the verdict and return to step 4.

### 9. Commit and push

```bash
# Re-confirm headRefOid hasn't changed underneath you
gh pr view <pr> --json headRefOid

git add <files>
git commit -m "<type>: <description> (#<issue>)"
git push
```

Conventional commit prefix:
- `chore:` — skill scripts, CI, automation, anything not in `@apijack/core`'s published surface.
- `fix:` — behavior bugs in published code.
- `feat:` — new published API (triggers minor bump).
- `BREAKING CHANGE:` trailer for breaking changes.

**No `Co-Authored-By` lines. No `--amend`. No `--force-push`.** Fresh commit on top.

Then go to step 8.

## Stop conditions

Halt and report (do not loop further) when:

- Latest verdict is `first pass reviewed` with no outstanding blocking items → success, report PR URL + verdict, stop.
- Non-interactive and stuck after all three context levels → posted a halt comment + exit non-zero.
- Two consecutive review cycles flag the *same* blocking item → you're misreading the request, escalate to a human (interactive: ask; non-interactive: PR comment + exit).
- Repo state diverged underneath you (force-push, branch deleted, `headRefOid` changed mid-fix) → report and stop.
- CI is red for a reason unrelated to your diff → report and stop.

## Red Flags

| Thought | Reality |
|---------|---------|
| "I'll merge this myself once it's clean" | STOP — that's `final-review`'s job. |
| "I'll skip `wait-for-review.sh` and use `/loop` or `ScheduleWakeup` or a `gh pr view` sleep" | STOP — the script is the only correct wait. |
| "The review is wrong, I'll quietly ignore it" | Push back explicitly via PR comment. Never silently. |
| "It's a one-liner, no need to lint" | `bun run lint` is cheap. Run it for source changes. |
| "It's a one-liner — I have to dispatch a subagent code-review" | Subagent review is OPTIONAL for trivial fixes. Match depth to change size. |
| "Non-trivial but I'll guess and push" | Interactive: ask the user with the 4-option menu. Non-interactive: progressive context, then halt-and-report. |
| "The review cites a symbol that doesn't exist; I'll patch the closest match" | Treat as non-trivial — sanity-check before fixing. |
| "I'll wait foreground" | `run_in_background: true` is mandatory in the Bash tool. |
| "The prompt's review summary is enough; I don't need to fetch the live one" | Always re-fetch the live review. The prompt may be stale or truncated. |
| "I'll only check the top-level review body" | Inline review comments often carry the actionable specifics — fetch them too. |
| "I'll force-push / amend" | Fresh commit on top. Never amend, never force. |

## Output

Either:
- **Success**: PR URL + final verdict (`first pass reviewed`) + one-liner of what changed in the fix commit(s).
- **Halt-and-report**: PR comment posted + non-zero exit (non-interactive) or message to user + stop (interactive).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.