ship ยท diff
git:20261030.e91f1ca to git:20261030.03f7155
36 added, 39 removed. Audit A to A.
---
name: ship
description: >-
Finish a branch: infer which review passes the change warrants, run them, open the PR, babysit CI to green, triage bot comments, and refresh the body from a clean context.
argument-hint: "[--merge] [--effort <level>] [--simplify] [--human] [--skip <pass>] [--base <ref>]"
allowed-tools:
- Agent
- AskUserQuestion
- Bash(git diff:*)
- Bash(git status:*)
- Bash(git fetch:*)
- Bash(git rev-parse:*)
- Skill(plan:review)
- Skill(code-review)
- Skill(simplify)
- Skill(run)
- Skill(comments:audit)
- Skill(github:copilot)
- Skill(prompting:scan)
- Skill(prompting:prompting)
- Skill(writing:review)
- Skill(review:human)
- Skill(pull-request:create)
- Skill(pull-request:babysit)
- Skill(pull-request:follow-up)
---
# Ship
- Gate review passes on the diff, run them in order, open the PR, babysit CI to green, refresh the body from a clean context. Each pass fans out on its own; ship only gates and orders.
+ Gate review passes on the diff, run them in order, open the PR, babysit CI to green, and refresh the body from a clean context. Each pass manages its own fan-out. Ship gates and orders them.
- Default end state **green and ready**: CI green, bot comments triaged, body refreshed, stopped for your web review. `--merge` drives to merged.
+ Done means CI green, bot comments triaged, body refreshed, and a stop for your web review. With `--merge`, done means merged.
## Context
- Working tree: !`git status --short`
## Decide What Applies
- Resolve the base to a **remote** ref so ship's view matches what the PR merges against. From the base branch (default `main`, or `--base <parent>` on a stack), take its tracking ref via `git rev-parse --abbrev-ref --symbolic-full-name <base>@{u}`, falling back to `origin/<base>`. Fetch it first (`git fetch`) so a stale local `<base>` never inflates the diff with already-merged commits. Diff `git diff <resolved>...HEAD`, plus a plain `git diff` for uncommitted work, and thread the resolved ref as `--base` to every gated pass that takes it. `code-review` takes the range `<resolved>...HEAD` as its target instead. Gate each pass on the file set, its size, and the content behind any judgment call (new comments, refactor or new behavior). Full matrix and heuristics: [`references/passes.md`](references/passes.md).
+ Diff against the remote base, which is what the PR merges against. Take the base branch (`main`, or the `--base` parent on a stack), `git fetch`, and resolve its tracking ref with `git rev-parse --abbrev-ref --symbolic-full-name <base>@{u}`, falling back to `origin/<base>`. Read `git diff <resolved>...HEAD` plus a plain `git diff` for uncommitted work. Pass the resolved ref as `--base` to every pass that takes it. `code-review` takes the range `<resolved>...HEAD` as its target.
- - `plan:review`: a substantial approved plan is in context (`~/.claude/plans/` file) *and* the session ran long or redirected enough that the diff could have drifted from it. Skip otherwise ([full gate](references/passes.md#plan-review)).
- - Correctness and quality: code changed. Exactly one of `code-review <effort> --fix` (default) or `simplify` (pure refactor, no new behavior). Skip on docs/config-only.
- - `comments:audit`: diff adds code comments.
- - `pull-request:follow-up --local`: a supported review bot is available for the repo *and* the diff clears the [Bot Review Gate](references/passes.md#bot-review-gate). Runs the hosted reviewer locally before the PR exists.
- - `github:copilot`: code changed on a repo I own *and* the diff clears the [Cross-Model Gate](references/passes.md#cross-model-gate). A second model reads the diff before the PR exists.
- - `prompting:scan`: diff touches a document a model executes: `CLAUDE.md`, `AGENTS.md`, `SKILL.md`, a skill's `references/`, `.claude/agents`, `.claude/commands`, `.claude/rules`, or a `prompt/` or `prompts/` dir. Fix confirmed findings with the `prompting` skill.
- - `writing:review`: diff touches prose people read (READMEs, docs, `.mdx`, `.rst`), excluding the prompt files above. A diff with both runs both passes, each over its own files.
- - `run`: diff has a runtime surface. Drive the change in the real app, not just tests. Skip on docs-only and tests-only.
- - `review:human`: the diff clears the [Human Review Gate](references/passes.md#human-review-gate), which skips trivial diffs. Ben reads the cleaned diff last, for architecture and slop.
+ Gate each pass on the file set, its size, and the content behind any judgment call. Gates, effort inference, and the `code-review` versus `simplify` choice: [`references/passes.md`](references/passes.md).
- Infer, don't interrogate. Present the plan in one line, then proceed. `AskUserQuestion` only on a real toss-up: refactor versus behavior change, or `medium` versus `high` effort.
+ - `plan:review`: a substantial approved plan is in context (`~/.claude/plans/` file) and the session ran long or redirected enough for the diff to drift from it.
+ - Correctness and quality: code changed. Exactly one of `code-review <effort> --fix` (default) or `simplify` (pure refactor, no new behavior). Skip on docs- or config-only diffs.
+ - `comments:audit`: the diff adds code comments.
+ - `pull-request:follow-up --local`: a supported review bot is available for the repo and the diff clears the [Bot Review Gate](references/passes.md#bot-review-gate).
+ - `github:copilot`: code changed on a repo I own and the diff clears the [Cross-Model Gate](references/passes.md#cross-model-gate).
+ - `prompting:scan`: the diff touches a document a model executes: `CLAUDE.md`, `AGENTS.md`, `SKILL.md`, a skill's `references/`, `.claude/agents`, `.claude/commands`, `.claude/rules`, or a `prompt/` or `prompts/` dir.
+ - `writing:review`: the diff touches prose people read (READMEs, docs, `.mdx`, `.rst`) outside those prompt files. A diff with both kinds runs both passes, each over its own files.
+ - `run`: the diff has a runtime surface. Skip on docs-only and tests-only diffs.
+ - `review:human`: the diff clears the [Human Review Gate](references/passes.md#human-review-gate), which skips trivial diffs.
+ State the plan in one line and proceed. Use `AskUserQuestion` only for a real toss-up: refactor versus behavior change, or `medium` versus `high` effort.
+
## Flags
- - `--merge`: drive to merged (babysit `--merge`). Default: green and ready.
+ - `--merge`: drive to merged.
- `--effort <low|medium|high|xhigh>`: override inferred `code-review` effort.
- `--simplify`: force `simplify` over `code-review`.
- `--human`: force `review:human` on a diff the gate skips.
- - `--skip <pass>` (repeatable): drop a gated pass. Names: `plan`, `code-review` (the old `review:code` is accepted as an alias), `simplify`, `comments`, `bot`, `copilot`, `prompting`, `writing`, `run` (the old `verify` is accepted as an alias), `human`.
- - `--base <ref>`: base branch for gating. Default `main`; on a stack, the parent branch. Resolved to its upstream tracking ref (e.g. `origin/...`) before diffing.
+ - `--skip <pass>` (repeatable): drop a gated pass. Names: `plan`, `code-review` (alias `review:code`), `simplify`, `comments`, `bot`, `copilot`, `prompting`, `writing`, `run` (alias `verify`), `human`.
+ - `--base <ref>`: base branch, the parent branch on a stack. Default `main`.
## Pre-PR Reviews
- Serialized before create: `code-review --fix`, `simplify`, and comment trims all write to the branch. `plan:review`, when gated in, is read-only, so it runs as a background dispatch alongside these and joins before create rather than gating them. [`references/passes.md`](references/passes.md) has the DAG.
+ Run the gated passes in this order. The fix passes write to the branch, so they run serially. When `plan:review` is gated in, dispatch it in the background at the start, since it is read-only, and join it before `review:human`.
- 1. **`comments:audit`**: needs a clean tree (the fix passes dirty it), lands trims via fast-forward (see [Comment Trims](#comment-trims)). Its preflight fans out on its own at diff scale and asks only past ten agents.
- 2. **`pull-request:follow-up --local`**: reviews committed work only and commits its own fixes, so it runs while the tree is still clean, before the fix passes. Pass the resolved base.
- 3. **`github:copilot`**: the cross-model pass, in the same slot and for the same reason. Findings triage and fix in-branch. It spends a metered credit allotment. [`references/passes.md`](references/passes.md) gates it.
- 4. **Correctness and quality**: `code-review <effort> --fix` or `simplify`.
+ 1. **`comments:audit`**: needs a clean tree, so it runs first. See [Comment Trims](#comment-trims).
+ 2. **`pull-request:follow-up --local`** with the resolved base: reviews committed work and commits its own fixes, so it runs while the tree is still clean.
+ 3. **`github:copilot`**: same slot, same reason. Triage findings and fix in-branch.
+ 4. **`code-review <effort> --fix`** or **`simplify`**.
5. **`prompting:scan`** over touched prompt files. Fix confirmed findings with the `prompting` skill.
- 6. **`writing:review`** over touched human prose. Address salient findings before the body is written.
- 7. **`run`** to drive the change end to end.
- 8. **Join `plan:review`** when it was gated in, and act on fix-worthy drift before the human review sees the diff. Carry deferred follow-ups into the report.
- 9. **`review:human`** when gated in: after every fix pass and the join, so the cleaned diff is what gets seen ([Human Review Gate](references/passes.md#human-review-gate)). Terminal mode by default: it ends the turn, and Create runs only when the review resumes with approval.
+ 6. **`writing:review`** over touched human prose. Address salient findings.
+ 7. **`run`**: drive the change in the real app, end to end.
+ 8. **Join `plan:review`**: act on fix-worthy drift. Carry deferred follow-ups into the report.
+ 9. **`review:human`**: last, so Ben reads the cleaned diff. It ends the turn, and Create runs when the review resumes with approval.
- Dirty tree at the comment pass: ask whether to commit first. `comments:audit` operates on `HEAD` and needs a clean tree.
+ When the tree is dirty at the comment pass, ask whether to commit first.
#### Comment Trims
- `comments:audit` commits trims to a fresh `comments/audit-<hash>` branch off `HEAD`, leaving the tree untouched. Run `comments:audit --base <base> --fix` and capture the branch name. No branch means nothing to trim: skip. Otherwise dispatch a short-lived `general-purpose` Agent with that name to fast-forward and delete it (rationale and rejected alternatives: [`references/passes.md`](references/passes.md#comment-trims)):
+ Run `comments:audit --base <base> --fix`. It commits trims to a fresh `comments/audit-<hash>` branch off `HEAD` and prints the name. No branch printed means nothing to trim. Otherwise land and delete it:
```
git merge --ff-only comments/audit-<hash>
git branch -d comments/audit-<hash>
```
## Create
- The plan-review join and any human review are behind you. `pull-request:create` commits the working-tree fixes, pushes, opens the PR. Capture the URL: babysit and body-refresh need it.
-
- Pass `--no-review-body` through whenever `review:human` did not run, gated out or dropped by `--skip human`, so create's own body review honors the skip.
-
- Pass `--base <parent>` through when `/ship --base` named a stack parent. Create needs it to target the PR at the parent and to link the layer into the stack on GitHub. Without it the PR opens against the default branch and carries every lower layer's diff.
+ Run `pull-request:create`, which commits the working-tree fixes, pushes, and opens the PR. Capture the URL for babysit and the body refresh.
- Pass `--label review` only when the [Bot Review Gate](references/passes.md#bot-review-gate) routed to the hosted channel (local CLI unavailable); the review then starts with the PR. A local pass already covered the diff, so labeling after it pays a second credit for the same review.
+ - `--no-review-body` whenever `review:human` did not run.
+ - `--base <parent>` when `/ship --base` named a stack parent, so the PR targets the parent and links into the stack.
+ - `--label review` only when the [Bot Review Gate](references/passes.md#bot-review-gate) routed to the hosted channel. After a local pass, the label pays a second credit for the same review.
## Babysit
- `pull-request:babysit <url>` watches CI and fixes trivial failures to green.
-
- - `--reviews` (default on): after first green, hand bot comments to `pull-request:follow-up --auto`. Covers a bot review landing after the green push with no CI event to key off ([why](references/passes.md#babysit-and-reviews)).
- - `--merge`: only when `/ship --merge` was passed; else stop at green.
+ Run `pull-request:babysit <url> --reviews`, which fixes trivial CI failures to green and then hands bot comments to `pull-request:follow-up --auto`. Add `--merge` only when `/ship --merge` was passed.
## Refresh the Body
- Dispatch a background `general-purpose` Agent (cheaper model if set) to run `pull-request:update <url>` on every run that opened a PR. Never `fork`: it must read the final PR and diff cold, not this session's transcript, so the body describes the finished change with no review narration.
+ On every run that opened a PR, dispatch a background `general-purpose` Agent (cheaper model if set) to run `pull-request:update <url>`. Start it fresh, not as a `fork`, so it reads the final PR and diff cold and the body describes the finished change.
## Report
- PR link, passes run and gated out, final state (green and ready, or merging), and whether the body refresh was dispatched.
+ PR link, passes run and gated out, final state (green and ready, or merging), deferred `plan:review` follow-ups, and whether the body refresh was dispatched.