Skip to main content

babysit-pr

Monitor a PR and fix CI or review feedback. Use standalone, or from /ship to continue through its authorized guarded merge instead of stopping at green.

Datos de origen

Repositorio
BuilderIO/agent-native
Última actividad en el origen
8 de octubre de 2026 a las 03:53
Idioma detectado de SKILL.md
inglés
Estrellas
7119
Forks
646

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
babysit-pr
description
Monitor a PR and fix CI or review feedback. Use standalone, or from /ship to continue through its authorized guarded merge instead of stopping at green.
user-invocable
true
scope
dev
metadata
{"internal":true}
Monitor PR #$ARGUMENTS in the current repo and fix CI failures and human or bot review feedback. A standalone `/babysit-pr` may stop after 30 minutes of green CI and no new feedback. When invoked by `/ship`, honor its inherited `ship_mode` and reuse `/ship`'s same-thread heartbeat in Codex; do not create a second automation. Standalone `/babysit-pr` stays foreground-only and does not create or resume an automation unless the user explicitly asks for recurring follow-up. Do not use PR leases. A request to monitor or fix a PR does not authorize pushing to a PR authored by someone else. Push to that PR only when the user explicitly authorizes a push to that exact PR in the current request. A linked PR or inherited general ship authorization is insufficient. That permits only a push; merging that PR needs separate authorization in the current request. Before an authorized push, verify the live PR author, head repository, branch, head OID, and base; recheck the head before every normal fast-forward push. Before each push, resolve the active GitHub login with `gh api user --jq .login`, include `author` in the live PR query, and compare `author.login` with that login. If they differ, require the current-request authorization for that exact PR. Determine comment authorization from the live PR author before drafting or posting any PR communication. On a PR authored by the active user, concise replies in existing review threads and a concise top-level recap when feedback appears only in a review body are routine dispositions and need no extra authorization. This covers only comments needed to fix, decline, or otherwise disposition review feedback; do not add proactive or unrelated comments, tags, assignments, or mentions without an explicit request. On another person's PR, do not post any comment, including an inline reply or review-body recap, unless the current request explicitly authorizes commenting on that exact PR. Review, monitor, fix, push, or merge authorization alone does not authorize comments. Without that authorization, draft the response, leave the feedback unresolved, and do not claim the PR is ready or merge it. A worktree is a valid PR checkout. When monitoring from one, keep Git and GitHub commands in that worktree's cwd and current branch; do not copy changes to the shared checkout or require that an agent publish from the root checkout. In a shared checkout, keep its branch unchanged. When the user explicitly asks to update this PR and the checkout cannot safely serve as its source, follow `new-branch` to isolate the PR work in a managed task-owned worktree without asking. Carry only changes belonging to this PR. If they cannot be isolated safely, preserve state and report the exact paths or commits without asking for branch or worktree permission. For an existing PR update, record `headRepository.nameWithOwner`, `headRefName`, and `headRefOid`, then base the isolated task branch on that exact head. Resolve a remote for that exact head repository; `origin` is correct only when its URL matches. If needed, add a uniquely named remote for the verified head repository. Never infer the push target from the base repository or a matching branch name. If no writable head repository is available, preserve state and report the blocker. `ship:push` always commits publishable paths and pushes `origin/<local branch>`. Use it for an existing PR only when `origin` matches the recorded head repository and the local branch name equals `headRefName`. Otherwise, stage only this task's paths, commit with a specific subject, and push `HEAD:refs/heads/$headRefName` to `head_remote` after rechecking the live OID. Before each push, inspect any worktree using that head branch for unpublished PR commits. If the head moved, follow Setup's non-fast-forward recovery: fetch the refreshed head and merge it into the clean task branch, resolve and test, then recheck before pushing. Preserve state and report only when peer or unpublished work, or conflicts that cannot be safely resolved, block recovery. Never replace an existing PR's history, rebase, or force-push. ## Branch-wide Snapshot Rule During `/babysit-pr`, the PR remains the unit of review and the shared checkout is the branch snapshot. At the first tick, record dirty paths and unpushed commits; publish the requested initial work only after verifying that every candidate belongs to this PR's requested fix. If unrelated or incomplete concurrent work is present in a shared checkout, continue in the managed worktree using the existing PR's live head and carry only this task's fixes. Preserve the shared checkout. If safe isolation is impossible, report exact paths or commits without asking. On later ticks, inspect the tree before every push. Publish only a complete, coherent set of currently known fixes for failing CI, PR feedback, a real merge conflict, or an explicit user request. Batch multiple feedback items and delegate changes into one update; do not create a commit for each finding, checkpoint, or timer tick. Every new head reruns affected checks and resets the soak. Publish to the verified PR target as described above; `ship:push` rejects an omitted or generic subject. A clean tree, `origin/main` drift, queued checks, or a timer tick is not a reason to commit or push. Never publish unrelated concurrent work, and never revert, stash, or overwrite it. When an actionable fix is changing, collect all known related CI and review findings, validate the combined fix, then publish one coherent snapshot to the existing PR. Do not push incremental snapshots just to start CI early; the latest head needs a stable run before merge. The final clean-tree and merge-soak gates still apply before merging, except when the user explicitly invokes `/ship-now`. **If no PR number is given**, auto-detect it: get the current branch (`git branch --show-current`), find the open PR for it (`gh pr list --head <branch> --state open --json number --limit 1`). If no open PR exists, check recent merged/closed PRs. Only ask the user if no PR can be found. ## Setup At the start and on every resumed tick, resolve the active GitHub login and query the PR, including its author: ```bash gh api user --jq .login gh pr view <number> --json state,mergedAt,closedAt,author,headRepository,headRepositoryOwner,headRefName,headRefOid,baseRefName,mergeCommit ``` If the query fails or is ambiguous, do not act on cached evidence. Retry only after live state is available. Keep retrying the live query in the foreground at a short, interruptible cadence; under `/ship`, the verified same-thread heartbeat is an additional reentry path, not a replacement for that retry. A closed, unmerged PR ends babysitting and is reported as unsuccessful. If a PR is already merged under inherited `ship_mode=merge-authorized`, continue the post-merge path here. Standalone and ready-only invocations report an unexpected merge without rotating. 1. Run one foreground tick immediately. Under `/ship`, preserve its goal and task-scoped heartbeat through this mode's endpoint. Standalone babysitting continues in the foreground without automation unless recurring follow-up was explicitly requested. Never create a duplicate heartbeat. 2. Before each PR write, reread the live state. Push normally (never force). Query and record `headRepository.nameWithOwner`, `headRefName`, and `headRefOid`. Resolve the writable push remote by matching its URL to that exact repository; `origin` is valid only when it matches. If none exists, add a uniquely named remote for the exact head repository. Fetch the PR head from that remote at setup and on each tick. On a non-fast-forward rejection or changed `headRefOid`, verify the fetched head against live PR metadata. If it already contains the local commits, do not push them again. Otherwise confirm the tree is clean and those commits belong to this PR, merge the refreshed `<head_remote>/<headRefName>` into the current branch, resolve and test, then recheck the live head before pushing normally to the same remote and ref. Never retry the same stale push, rebase, or force-push. If peer or unpublished work or unresolvable conflicts block recovery, preserve state and report exact blockers. Never update from `origin/main` unless GitHub reports a confirmed `CONFLICTING` PR; then use a normal merge, never a rebase. A behind count or pending checks are not conflicts. Guard PR merges with `--match-head-commit <live_head_oid>`; a stale-head rejection is a retry signal, not a reason to stop the requested work. 3. Track the last actionable item: new human/bot feedback, a CI fix, conflict resolution, or an intentional commit/push. 4. For standalone `/babysit-pr`, stop after 30 minutes with green GitHub Actions CI and no new actionable item. Under `/ship` with `ship_mode=merge-authorized`, keep working through the 10-minute merge gate and guarded merge. With `ship_mode=ready-only`, fix CI and review feedback until the ready-PR gate holds, then leave the PR open. After an actionable fix or push, reset the applicable clock: standalone's 30-minute quiet-green timer or `/ship`'s 10-minute merge soak. The `/ship` soak starts only once every merge condition below holds; it never waits for 30 minutes of quiet. ### Loop discipline — read this, it is the part people get wrong - **Cadence: tick every 60–120 seconds while the PR is active** (CI running, recent pushes, or feedback within the last few minutes). Only relax toward ~3 minutes once the PR is genuinely quiet (all checks green, no new commits or comments for a while). Tight cadence is for observing status, not for publishing more often. Coordinate concurrent edits with the owning task; delegates do not publish. - **Keep the foreground loop moving.** Do not end `/ship` because CI, review, or a background command is pending. Use short interruptible waits and check again in this task. - **Do not publish an incomplete snapshot to avoid slow local validation.** Use the narrowest meaningful local check when full validation is slow or contaminated, record exact results, and let the current head's CI finish. If CI or review identifies a fix, batch the currently known actionable items and publish one complete update. - **Every tick, expect new local files.** On an active shared branch, concurrent agents may edit the checkout continuously. Re-run Step 0 every single tick to detect actionable changes, but publish only the fixes allowed by the Branch-wide Snapshot Rule above. ## Each tick **Step 0 — always do this first, before anything else:** ```bash if ! git fetch origin --quiet; then echo "Cannot refresh origin refs; stop before checking unpublished commits." >&2 exit 1 fi ``` Immediately resolve the active GitHub login with `gh api user --jq .login`, then query the live PR state with `gh pr view $ARGUMENTS --json state,mergedAt,closedAt,author,headRepository,headRepositoryOwner,headRefName,headRefOid,baseRefName,mergeCommit`. If the query fails, do not run branch, review, or CI checks; retry on the next foreground tick. A closed but unmerged PR ends babysitting and is reported as unsuccessful. A merged PR is a terminal state for standalone `/babysit-pr` and inherited `ship_mode=ready-only` (report the unexpected merge and do not rotate). Under inherited `ship_mode=merge-authorized`, continue the `/ship` post-merge path below before cleanup. Never treat PR merge alone as completion of the parent ship goal. For an open PR, resolve `head_remote` by matching a configured remote URL to `headRepository.nameWithOwner`; `origin` is valid only when it matches. If no remote exists, add a uniquely named one for the exact head repository. Fetch the live head with an explicit refspec into `refs/remotes/$head_remote/$headRefName`, then verify that ref's OID matches live PR metadata before using it as the task branch base, comparison ref, or push target. If no writable head repository is available, preserve state and report that blocker. For an open PR, inspect the branch snapshot: ```bash git fetch "$head_remote" "refs/heads/$headRefName:refs/remotes/$head_remote/$headRefName" git status --short git diff --name-only if git show-ref --verify --quiet "refs/remotes/$head_remote/$headRefName"; then git log --oneline --decorate "refs/remotes/$head_remote/$headRefName"..HEAD -- . ':(exclude)learnings.md' ':(exclude)bridge/**' ':(exclude)data/**' else git log --oneline --decorate HEAD --not --remotes="$head_remote" -- . ':(exclude)learnings.md' ':(exclude)bridge/**' ':(exclude)data/**' fi ``` After the status check, publish only an intentional fix for a concrete CI failure, PR feedback, merge conflict, or explicit user request, using the verified target path above. If the tree is clean and already pushed, do nothing. If it is clean with unpushed commits, push them directly only when those commits are already an intentional actionable fix; never create a maintenance commit merely to make the branch look current. Every tick starts here, no exceptions: on an active shared branch local files can change within minutes, so re-check before every actionable push. **Never `git stash` concurrent changes.** Stashes get orphaned, and a stash named `babysit-tickN-concurrent-work-*` left on the source branch while babysit-pr's PR ships without it is exactly how real work gets lost. If you see local changes you don't recognize, preserve them for their owner; do not hide them in a stash or commit them here. **Step 1 — check for merge conflicts:** 1. Run `gh pr view $ARGUMENTS --json mergeable --jq '.mergeable'`. 2. If `CONFLICTING`: bring `main` in and resolve. First inspect the worktree and unpushed commits; do not run the merge until the publishable-path check `git status --short -- . ':(exclude)learnings.md' ':(exclude)bridge/**' ':(exclude)data/**'` and the branch-specific unpublished-commit check in Step 0 are empty. The unpublished-commit check is also scoped to publishable paths, so excluded-only commits do not block recovery. Preserve and report excluded paths; they do not block recovery unless the merge itself touches them. Before merging, compare the local checkout with the live PR head: ```bash pr_head=$(gh pr view $ARGUMENTS --json headRefOid --jq '.headRefOid') if [ "$(git rev-parse HEAD)" != "$pr_head" ]; then echo "Local HEAD is not the live PR head; stop and let the branch owner reconcile it." >&2 exit 1 fi ``` If either publishable-path check is non-empty, do not attempt an in-place isolation. Preserve the exact dirty paths and unpublished commits, leave the checkout untouched, and wait for the owning session to publish or move its work. A separate clean PR worktree may perform this recovery when one is already available. Never use `git stash`, reset, restore, or a temporary branch as a substitute for retaining concurrent work. Do not merge an obsolete local head. **Publish any intentional actionable fix first (Step 0)**, after verifying every dirty path and unpushed commit belongs to that fix; then prefer a **merge** over a rebase — `git fetch origin main && git merge --no-edit origin/main` — because this branch is shared with concurrent agents and a rebase would rewrite history and require a force-push that can clobber their unpushed commits. Resolve the conflicts (for `pnpm-lock.yaml`, take one side with `git checkout --theirs -- pnpm-lock.yaml` then regenerate with `pnpm install --lockfile-only` against the merged `package.json`), complete the merge commit, and push (a normal push, never `--force`). This resets the soak timer. If unrelated or incomplete concurrent work keeps the worktree dirty, preserve it and wait for its owner instead of stashing, restoring, or forcing the merge. Do not merge `origin/main` again while the PR is `MERGEABLE` or `UNKNOWN`, or while checks are merely pending; a conflict-free PR does not need another main sync. Merge from main only to resolve a confirmed conflict. Because this branch is shared, use a normal merge; never rebase. 3. If `MERGEABLE` or `UNKNOWN`: proceed. (`mergeStateStatus: BLOCKED` with `mergeable: MERGEABLE` just means required checks are still pending/red — that is not a conflict; keep going.) ## Latest-feedback handoff If the PR body or branch cites `/review-latest-feedback`, treat its start cursor, grouped reports, evidence links, and disposition table as part of the PR's review state. At the first tick, record that handoff. On every later tick before the merge gate, re-read the handoff and check for new Slack replies, GitHub feedback, and Sentry findings after its cursor using the configured connectors. Re-query first-party Agent-Native Analytics error issues with `list-error-issues` and its available filters; it has no time cursor and caps results at 100, so record bounded coverage and do not claim exhaustive newness. A new actionable report resets the soak timer and must reach either a verified **Fixed** result with a concise reply and `✅`, a verified **Shipped** result with a concise reply, a verified **Live verified** result (reply only when informative), or a non-fixed terminal ledger disposition with its existing `👀` before merge (`✅` only for **Fixed**). An active/evidence-limited disposition or a reply without one of those outcomes blocks merge; the eye remains on every claimed item. Reactions are append-only; newer thread evidence controls the current disposition. Evidence-limited or active dispositions retain the workflow's eye; it remains after resolution. Keep active and terminal state in thread text or linked work; do not repeat a status already recorded. If a connector is unavailable, record it as unavailable in the recap rather than treating it as no findings. **Then proceed with PR checks:** 1. Check for review comments and review summaries from humans and bots — **EVERY tick, with no exceptions.** > ⚠️ **Review bots (Builder, Copilot, etc.) RE-REVIEW on every push and post a brand-new round of comments each time.** A PR commonly accumulates several rounds. You MUST re-check on every single tick — including "quiet" ticks where you're only waiting on CI — and you must keep checking right up until the moment you merge. > > **Never filter comments by a "since <timestamp>" window.** A forward-looking timestamp silently skips rounds that were posted *before* your last reply (e.g. a round that landed between the first review and when you replied), and "0 new since X" reads as "all addressed" when it is not. This exact mistake left two whole review rounds unanswered on PR #1097 (2026-06-08). Instead, determine coverage by **reply state**: list every top-level review comment that does **not** yet have a reply, across all pages and all rounds. Stream every comment with `--jq '.[]'` (concatenates cleanly across pages), then slurp: ```bash gh api --paginate repos/{owner}/{repo}/pulls/$ARGUMENTS/comments --jq '.[]' \ | jq -s ' ([ .[] | .in_reply_to_id // empty ]) as $replied | .[] | select((.in_reply_to_id // null) == null) # top-level comments only | select(.id as $id | ($replied | index($id)) | not) # …with no reply yet | {id, user: .user.login, path, line: (.line // .original_line), snippet: (.body[0:200])}' ``` (Bind the id with `.id as $id` first — `index(.id)` would evaluate `.id` against the `$replied` array, not the comment, and error out.) If that command prints anything, there is unaddressed feedback. Fix it or disposition it under the comment-authorization rule; if a reply is not authorized, draft it and leave the item unresolved, so the PR cannot be called clean or merged. Also re-read the latest review **summary** bodies each tick (bots restate their findings here): ```bash gh api repos/{owner}/{repo}/pulls/$ARGUMENTS/reviews --jq '.[] | select(.body != null and .body != "") | {user: .user.login, state, submitted_at, body: .body[0:1000]}' ``` Treat the count of unaddressed comments (not a timestamp) as the source of truth for "is there feedback to handle". 2. Check CI status: ```bash gh pr checks $ARGUMENTS ``` 3. **If new human or bot feedback includes real bugs or requested changes**: - Read the relevant files - Fix the issues - Run `pnpm run prep` to verify locally - Publish the complete fix snapshot to the verified PR head using the target path above - Respond according to the ownership gate above: on the active user's own PR, reply inline to addressed comments or post a concise top-level recap when feedback appeared only in a review body. On another person's PR, either comment requires explicit authorization for that exact PR; without it, draft the response and leave the feedback unresolved. - Reset the applicable clock described above 4. **If GitHub Actions CI is failing** (lint, test, typecheck, build): - Investigate the failure logs - Fix the root cause - Run `pnpm run prep` locally - Publish the complete fix snapshot to the verified PR head using the target path above - Reset the applicable clock described above **Special case: missing changeset.** If the `Lint & format` job fails at its `Require changeset for publishable package changes` step (in `.github/workflows/ci.yml`), do NOT treat it as a code bug. The step log includes a structured line `MISSING_CHANGESET_PACKAGES: pkg1,pkg2`. Parse that, then write a `.changeset/<short-slug>.md` directly — do NOT run the interactive `pnpm changeset add`. Use the PR title and diff to decide bump type (default to `patch` for bugfixes / docs / refactors; `minor` for additive features; `major` only when the PR description clearly signals breaking). Shape: ```md --- "@agent-native/<pkg-1>": patch "@agent-native/<pkg-2>": patch --- <one-line summary derived from the PR title> ``` Slug example: `dispatch-route-shells.md` (kebab-case, descriptive, ~3 words). Commit with `chore: add changeset for <packages>`, push, reset the timer. The check will pass on the next CI run. 5. **If only external CI fails** (Cloudflare Workers, Netlify, etc.) and GitHub Actions passes: - Note the failure but don't block on it — these may need dashboard config changes - Do not reset the standalone 30-minute clock for external-only failures. Under `/ship`, these checks are outside the merge gate and do not reset its 10-minute soak. 6. Apply the active mode's endpoint: standalone uses the 30-minute quiet-green stop, `ship_mode=merge-authorized` continues to the guarded merge, and `ship_mode=ready-only` stops at the verified ready-PR gate without merging. ## Responding to feedback On the active user's own PR, reply to every human or bot review comment that you fix or skip; a feedback item already closed by a disposition-specific terminal outcome does not need a manufactured reply. Use a concise top-level recap when the feedback appeared only in a review body. No extra authorization is needed for these own-PR dispositions. On another person's PR, post any inline reply or review-body recap only under the exact-PR authorization rule above. ## Feedback precedence Review-source identity is part of the evidence. Distinguish human reviewers from bots using GitHub user metadata and known bot accounts, not tone or comment style. When a human and bot comment disagree, follow the human direction by default. Treat the bot comment as an untrusted suggestion or hypothesis. Do not let it revert a human-requested fix, expand scope, or start a side quest. Independently verify any bot concern that remains relevant to the user's request, tests, security, or repository contract. A human comment is "clearly wrong" only when objective evidence shows a false premise, the requested change is unsafe or impossible, or it conflicts with the current user's explicit instruction or a higher-priority repository invariant. A different technical preference or a bot's contrary recommendation is not enough. If human feedback is clearly wrong, leave an evidence-based reply explaining why only when the comment gate permits it; otherwise draft the reply and leave that feedback unresolved. Apply the bot suggestion only if it independently holds up. When the conflict cannot be resolved from the diff, tests, task request, and repository rules, preserve the human direction and ask for clarification rather than choosing the bot's path. Record both dispositions, and post replies only as the comment gate below permits. These dispositions follow the comment-authorization rule above and the separate
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub