| name | ship |
| description | Take a tracker issue to a merge-ready PR in one unattended run, stopping only at a human merge gate. Composes the `tdd` and `code-review` skills. Use when the user wants to ship an issue or take an issue through to a PR; also invoked by the cloud ship routine. |
| argument-hint | [issue-number] |
| metadata | {"internal":true} |
ship
Drive one issue from nothing to a merge-ready PR, hands-off, stopping only at
a final human merge gate. You run /ship <issue>, walk away, and come back to a
PR implemented test-first, integration-tested, self-reviewed, bot-reviewed, and
CI-green — every decision summarized for you to approve before the merge.
This skill is generic — everything repo-specific lives in that repo's
project instructions (CLAUDE.md / AGENTS.md). Read them first and pull
what the phases below need; if any is missing, surface the gap — don't guess: the
test command (run from a worktree), integrated/live-test targets + creds,
the full local-gate set CI runs (not a fixed triad), docs-sync rules, the
commit-subject convention, and whether a review bot exists — its round-1
vs push-triggered role and how each is triggered. This copy also ships the
repo-specific deterministic steps as executables — see Scripts below.
Scripts — deterministic steps are encoded, not prose
scripts/ holds each deterministic step as an executable: it prints a
one-screen summary (JSON, or pass/fail lines plus only the failing output), and
its exit code is the step's completion criterion. When a phase names a script,
run it instead of re-deriving the calls it wraps — the script is the single
source of truth for that step's mechanics (REST-over-GraphQL, the one-retry on
gh's 401 flake, output projection).
| Script | Phase | GitHub API |
|---|
scripts/preflight.sh <issue> | 0 pre-flight | yes |
scripts/isolate.sh <type> <slug> <issue> | 0 worktree (when EnterWorktree is absent) | no |
scripts/claim.sh <issue> | 1 claim | yes |
scripts/local-gate.sh [--small <node>] | 5 local gate | no |
scripts/poll-pr.sh <pr> [--await-review <login>] | 7/8 poll | yes |
scripts/merge-and-verify.sh <pr> [issue] | 9 on approval | yes |
The GitHub-API scripts assume direct api.github.com access via gh. In a
sandbox that gates it (the cloud-ship fire), skip them and use the caller's MCP
mapping; the local-only scripts still apply.
The autonomy contract
/ship runs unattended through implementation, testing, review, and CI, to one
guaranteed stop: the merge gate — your single review point. It pauses in only
three places:
- Merge gate (always). Merging to the default branch is effectively
irreversible; a human approves it. Never auto-merge.
- Ambiguity rail (phase 1, only if needed). Issue too underspecified to derive
a plan → stop and ask rather than build the wrong thing.
- Integrated-test hand-off (phase 3, only if needed). Live-test creds absent →
hand the exact command back and wait.
Everything else — triaging your own and the bot's findings, fixing, re-running —
is autonomous, no mid-loop pause.
Never proceed on red. Any failure before the merge gate (failing test, lint,
type-check, CI) gets a bounded self-fix-and-retry (~2 attempts). Still red after that, or the
failure means the approach is wrong → stop and report; never merge on red.
Make the report a fast yes: attach the concrete evidence (failing output /
live error) and, if cheap, a verified-working alternative — a one-glance
approve-or-redirect, not an open-ended "what now?".
Argument
$ARGUMENTS is the issue number. Omitted → ask which issue. Free text rather than
a number → treat it as the task spec directly and skip the issue fetch in phase 1.
Consult current docs — don't trust training data for APIs
While implementing (phase 2) or triaging findings (phases 4, 7), verify against
current docs, not memory — your training data may lag the installed version.
Use context7 (ctx7 CLI / MCP) for any library/SDK/CLI, and Microsoft
Learn (MCP) for Microsoft / Dataverse / Power Platform / Azure when relevant.
This matters most when a review comment cites an API detail: confirm the claim
against the pinned version before acting — a bot may "remember" an API the
installed version doesn't have, and acting on it would be a regression.
Model tiers — match the model to the work
Use the cheapest model that fits; reserve the strong model for judgment. Tag every
subagent and the poll loop with a model explicitly — never default-inherit.
| Work | Model |
|---|
| Investigation / mapping | haiku |
| Phase-2 execution from a settled plan (split in reference/implement.md) | sonnet |
Mechanical edits & fixes, docs-sync helper, code-review skill's Spec axis | sonnet |
Triage judgment (phases 4 & 7), phase-2 judgment (classification, plan, design), code-review skill's Standards / code axis | opus |
Triage and code review are judgment — running them on the cheap tier under-reads
diffs. Poll loops and gate runs are scripts (see Scripts) — no model at
all; a subagent there burns budget to relay what an exit code already says. When
you invoke the code-review skill, tier its two axes yourself (Standards =
opus, Spec = sonnet — rows above). Fall back to the nearest available tier
rather than running everything on one model.
The lanes
Every run is full lane until the change proves it's small — all three keys
hold (assert at phase 2, announced like the class; when unsure, it's not small):
- No public-surface change. The public surface is the documented,
user-visible contract: commands, flags, options, choices, defaults, output
formats, API/output shapes, documented behavior. A small change adds, removes,
renames, and changes none of it.
- Provable without a live call — a unit/regression test fully proves it; no
need to hit the live target.
- Single-concern — no new dependency, no new logic branch beyond the fix itself.
Behavior change is allowed — a bugfix is one. Small means narrow + locally
provable + invisible to the public surface, not zero-behavior. Small → read
reference/small-lane.md — the reduced spine: what
collapses, the floor that never does, when the lane revokes — before continuing.
The pipeline
Work the phases in order; keep the main thread on orchestration and decisions,
delegating noisy work to subagents. First, read
reference/context-discipline.md — it opens
with the delegation rule (when a subagent earns its cost), covers how to keep
this long run from bloating the window, and names your required first action:
creating the run's ten-item task list (one per phase below). Don't start phase 0
until that list exists.
Compose, don't reinline. Load the tdd skill (phase 2) and the code-review skill
(phases 4, 7) through the Skill tool when their phase begins — never hand-roll
their logic. Set the code-review skill's per-axis tiers yourself when you invoke it
(opus code / sonnet spec, table above); run finding-triage at the judgment tier,
mechanical helpers at the cheap tier (table above).
0 · Isolate. Pre-flight: run scripts/preflight.sh <issue> — if it
reports not actionable (closed, existing open/merged PR, existing branch,
already claimed), stop and report its reasons instead of opening a
duplicate. (A picker-based runner like the cloud routine relies on the phase-1
agent-working claim to block concurrent re-picks; this guard catches a
manual re-run or an already-shipped issue, where there is no picker.) Then
create an isolated workspace on a fresh branch off the default branch —
EnterWorktree, or scripts/isolate.sh <type> <slug> <issue> when that tool is
absent. Name the
branch <type>/<slug>-<issue> where <type> matches the issue (feat/fix/…). All
work, commits, and the PR happen from this branch; clean it up after merge.
Commit as you go — intermediate messages don't matter, but the PR needs real
commits. (The branch
<type> is just a label — the commit/PR Conventional-Commit type may differ once
you see the change, e.g. a feat/-branched enhancement best committed as test:
or docs:. The squash subject, not the branch, drives release tooling.)
1 · Understand. Fetch the issue and its comments. Derive what success looks
like. A later authoritative comment can supersede the issue body — spec
precedence, detailed in reference/implement.md. If
it's too vague to plan, stop and ask (the ambiguity rail).
Claim it before implementing — scripts/claim.sh <issue> (idempotent) marks
the issue in-progress so a concurrent run can't double-pick it; skip if
there's no issue or no documented claim convention. Don't claim if you stopped on the
ambiguity rail; if you claim then stop blocked, hand the issue back.
2 · Implement. Classify the change as docs / code / infra, announce the
class and the skip path it implies — and whether it passes the three lane keys
(if so, announce that and follow
reference/small-lane.md) — then implement
test-first per class —
full detail (classes, TDD override, external-claim verification, and the
judgment/execution split that puts execution on a sonnet subagent) in
reference/implement.md. Stay surgical — implement
only what the issue asks; every changed line should trace to it. An adjacent bug or
cleanup you spot is out of scope: file a needs-triage issue for it and move
on, don't fix it inline. Keep a deviations log from the first edit: whenever
the territory forces a departure from the issue/brief/plan — an edge case the
spec missed, a wrong assumption, a known unknown the brief flagged — resolve
it by the conservative option, log what + why, and keep going; the log lands
verbatim in the PR body's Deviations from plan section (phase 6) and the
merge summary. If the core work itself balloons mid-flight — the diff
outgrows what one PR can carry, or the fix demands a redesign the issue never
scoped — stop and report with a split proposal instead of pushing through (the
ambiguity rail applies mid-run too).
3 · Integrated test. Live-test only what you touched, on the environment
the bug was reported against — detail in
reference/implement.md. A docs change — or a
small-lane one (key 2) — has nothing to integration-test; skip to the local
gate.
4 · Sync docs, then self-review. Sync docs before reviewing, so the review
reads the docs edits as part of the diff (the whole point of this ordering: a review
run on a docs-less diff never checks the docs).
Docs-sync (conditional) — do this first. Fire only if this change altered
the public surface (The lanes, key 1) or observable behavior. Then bring
the project's documented
artifacts (README, docs/, any shipped skill, tests/coverage) back in line per
the project's docs-sync rules — using the project's docs-sync subagent at the
mechanical tier if it has one, else by hand — and fold the edits into this change.
Skip when nothing user-visible changed — an internal refactor (infra), a
bugfix that restores already-documented behavior, test-only / build / tooling
changes, or pure comments; when you skip, say so in one line at the merge gate.
Self-review. Invoke the code-review skill against the diff — now including the
docs-sync edits — (it runs its two axes on their own tiers — opus for code, sonnet
for spec). Auto-triage each finding (this is the canonical definition — phase 7
reuses it): harden rather than rip out capability,
verify nits against the pinned dependency versions, reject known non-issues; fix
the valid ones; record a one-line disposition per finding for the merge summary.
5 · Local gate. Precondition: phase 3 passed or the class is docs — if
neither holds, you skipped a verification; stop and go back.
Run scripts/local-gate.sh green before opening the PR — it mirrors the checks
CI actually runs (tests, lint, format, type-check, security scan, docs build —
which now covers the phase-4 docs-sync edits — plus the workflow linters when
workflows changed) and prints per-check pass/fail with only the failing lines.
Run it inline: it projects its own output, so a subagent adds nothing. If a
check exists in CI that the script can't run locally, at least anticipate it.
Small lane: scripts/local-gate.sh --small <node> per
reference/small-lane.md.
6 · Open PR. Open a ready (non-draft) PR — drafts may not trigger the
project's automated review. Title it as a Conventional-Commit subject derived from
the issue (release tooling reads this on squash-merge). If the repo has a PR
template (.github/PULL_REQUEST_TEMPLATE.md / docs/pull_request_template.md),
fill it in — write the summary and tick / strike-through each checklist item
honestly against the work you did, keeping the Closes #<issue> keyword, and
copy the phase-2 deviations log into the Deviations from plan section
("None" only if the plan genuinely held). Don't
pass a raw --body that bypasses the template; let it populate, then edit. (No
template → a plain body that closes the issue.) An
automated round-1 review may fire on PR creation — don't re-request round 1.
Reflect the PR back on the issue right after opening (typically a comment
linking the PR) so a scheduled run won't re-pick it; skip if no documented
convention.
7 · Review-bot loop. Only if the repo has an automated reviewer configured
(per project instructions — never an assumption). If not, skip: phase-4 self-review
plus green CI is the review gate. Two reviewer roles, per project instructions: a
round-1 reviewer whose auto-review on PR creation is dispositioned once and
never re-requested in the ship flow, and a push-triggered reviewer (if the
repo runs one) that owns iteration — its rounds are free, so batch fixes one
push per round, disposition every thread, and drive it to quiet. Auto-triage every
comment (phase 4's definition, judgment tier). Converged = the iterating reviewer
quiet on the latest push + all round-1 threads dispositioned (no iterating
reviewer → round-1 threads dispositioned + green CI). Mechanics,
disposition rules, and traps: reference/copilot-loop.md.
8 · CI. CI usually runs concurrently from PR-open, so phases 7 and 8 overlap.
scripts/poll-pr.sh <pr> covers this phase: it reports the check conclusions
and surfaces a conflict immediately (mergeable_state: dirty). A
conflicted PR has no merge ref, so merge-commit checks never start and CI sits
pending forever — don't wait on it. Resolve: fetch the latest default branch,
rebase (or merge) it in, fix conflicts, re-run the local gate (phase 5), and
push — that recomputes the merge ref and lets CI run. Then land the checks green.
If CI goes red after review converged, fix and push, then proceed on green —
the push-triggered reviewer re-reviews the fix on its own; the round-1 reviewer is
not re-requested (a lint/format/flake fix earns no review anyway).
9 · Merge gate. Hard stop. Post the summary and wait for the user's
explicit "merge"; on approval, squash-merge, delete the branch, clean up the
worktree. Summary format and merge mechanics:
reference/merge-gate.md.
Reference files
reference/context-discipline.md — the delegation rule; keeping the long run
from bloating context; the required first-action task list.
reference/small-lane.md — the reduced spine for small changes: what collapses,
the floor, revocation.
reference/implement.md — phases 1–3: spec precedence, change classification,
external-claim verification, run-where-it-failed.
reference/copilot-loop.md — phase 7: the round-1 vs iterating reviewer roles,
the converged bar, poll mechanics, bot infra flakes and known non-issues.
reference/merge-gate.md — phase 9: the merge-summary template and the
squash-merge / cleanup mechanics.