ship
Skill1 starsChanged 21 days agoMITView on GitHub
Execute one fully planned Task to a reviewable PR with isolated writers, immutable independent review, fresh CI/review coverage, and durable accounting.
194 other projects use a version of this.
Adopted by
Most recently taken up by
- wboayue/rust-ibapitheir own version, first seen Nov 9, 2026
- haiggoh/run-to-completiontheir own version, first seen Nov 8, 2026
- sanmidable/skillstheir own version, first seen Nov 8, 2026
- Yesterday-AI/ytstacktheir own version, first seen Nov 8, 2026
- gaoyu06/harnesstheir own version, first seen Nov 8, 2026
- PeanutGT/NutsSkillstheir own version, first seen Nov 8, 2026
Used with
Projects with it also use ios-sync, open-gstack-browser and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
Saqlain-811Skillios-sync
Regenerate the iOS debug bridge against the latest upstream gstack templates. (gstack)
Also in 6 projects that use this
seek888Skillopen-gstack-browser
Launch GStack Browser — AI-controlled Chromium with the sidebar extension baked in. Opens a visible browser window where you can watch every action in real time. The sidebar shows a live activity feed and chat. Anti-bot stealth built in. Use when asked to "open gstack browser", "launch browser", "connect chrome", "open chrome", "real browser", "launch chrome", "side panel", or "control my browser". Voice triggers (speech-to-text aliases): "show me the browser".
Also in 10 projects that use this
ayudaySkillsetup-deploy
Configure deployment settings for /land-and-deploy. Detects your deploy platform (Fly.io, Render, Vercel, Netlify, Heroku, GitHub Actions, custom), production URL, health check endpoints, and deploy status commands. Writes the configuration to CLAUDE.md so all future deploys are automatic. Use when: "setup deploy", "configure deployment", "set up land-and-deploy", "how do I deploy with gstack", "add deploy config".
Also in 19 projects that use this
ShreyRaviSkilllanding-report
Read-only queue dashboard for workspace-aware ship. Shows which VERSION slots are currently claimed by open PRs, which sibling Conductor workspaces have WIP work likely to ship soon, and what slot /ship would pick next. No mutations — just a snapshot. Use when asked to "landing report", "what's in the queue", "show me open PRs", or "which version do I claim next". (gstack)
Also in 9 projects that use this
zebbernSkilldebug-fix
Find and fix a bug or issue — from any source (GitHub issue, error message, user report, or observed behavior)
Also in 4 projects that use this
ramybarsoumSkilldocument-release
Post-ship documentation update. Reads all project docs, cross-references the diff, updates README/ARCHITECTURE/CONTRIBUTING/CLAUDE.md to match what shipped, polishes CHANGELOG voice, cleans up TODOS, and optionally bumps VERSION. Use when asked to "update the docs", "sync documentation", or "post-ship docs". Proactively suggest after a PR is merged or code is shipped.
Also in 23 projects that use this
Other versions194 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 194
- garrytan/gstack★ 141ksame name
- rtk-ai/rtk★ 86ksame name
- simstudioai/sim★ 30ksame name
- millionco/react-doctor★ 15ksame name
- BuilderIO/agent-native★ 7.6ksame name
- nightly-labs/openbot★ 6.3ksame name
- fallow-rs/fallow★ 5.3ksame name
- puncsky/system-design-and-architecture★ 3.6ksame name
- plugin87/ux-ui-agent-skills★ 3.1ksame name
- ShenSeanChen/waku-agent★ 2ksame name
184 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
We split this skill into the rules it gives an agent
6 rules. 0 are common, 2 are distinctive, and 4 are very specific to this project.
0
Common
Most of the 180 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 16
Before classifying state or dispatching any worker, the parent runs the tracker preflight …
- Very specific: line 18
Check plan-base freshness before building: material drift between PLAN_BASE_SHA and the ship base returns to /sy:spec.
- Very specific: line 21
Read small cohesive surfaces directly.
- Distinctive: line 27
Every writable delegate gets a caller-created, recorded worktree.
- Very specific: line 34
After merge authorization, one small bounded fix may land through the authorized bounded-fix → focused-delta-gate → merge sub-flow in …
- Distinctive: line 111
Do not preload mutually exclusive procedures.
“Common” is measured: kept by at least 6 in 10 of the 180 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Execute one planned Task to a reviewable PR. Never merge automatically. Explicit merge authorization enters references/merge-accounting.md.
$ARGUMENTS
Invariants
- Before classifying state or dispatching any worker, the parent runs the tracker preflight (
${CLAUDE_PLUGIN_ROOT}/skills/shared/references/preflight.md); a failure stops here with its single## Action neededblock — no worker starts against an unusable tracker. - The highest
# Execution Plan vNon the Task is the plan — enforced by theplan_filetool, which refuses when there is no plan comment, refuses by comment id rather than picking when two claim the same highest version, and refuses when avN (continued)stub sits at or above the selected version rather than falling back to an older complete plan; otherwise stop for/sy:spec. - Check plan-base freshness before building: material drift between
PLAN_BASE_SHAand the ship base returns to/sy:spec. - Resolve standards before code.
- Resolve tracker blockers before branching; decomposed/superseded closure is not delivery. One not-done blocker with exactly one open same-repo PR whose base is the target branch is resolved by stacking on that PR (
references/start-resume.md§ Stacked run), not by waiting; every other blocker shape keeps this rule. - Read small cohesive surfaces directly; delegate large/verbose work — standards resolution, verbose verification (test/lint/type runs), and CI triage all count as verbose, and every added delegate enters
agents_used. At most the resolvedlimits.max_depth_agentscap depth agents in flight — resolve per${CLAUDE_PLUGIN_ROOT}/skills/shared/references/config-values.md. - START, BUILD, and GATE each run as disposable autonomous worker subagents (
sy:ship-start/sy:ship-build/sy:ship-gate); the parent is a thin dispatcher owning durable state (state file, worktrees, and which Task/PR/branch this run is against), the HANDOFF retro/accounting, MERGE, and all user interaction. Owning that identity is not a ban on a worker writing to the tracker at all: START and GATE each hold the narrow status/assignment verbs their own phase names, pinned to an exact per-worker set byscripts/validate.py::check_agent_denylists. - Workers never prompt the user; each returns
done,needs-decision,bail-to-spec, orblockedper the worker contract, and BUILD additionally returnsneeds-trace, GATEhandover. § Worker contract owns how the parent resolves each, including the twoneeds-decisionreturns — taggedreason: max_gate_roundsorreason: reviewer_findings— that go straight toAskUserQuestioninstead of being resolved first. - Any phase return may carry
MEMORY_REFUTEcandidates —{title, evidence, correction}, an empty correction meaning tombstone — for a seeded memory anchor this phase's own direct observation contradicted, durably mirrored inship-state.yaml'smemory_refutations. No ship worker agent gainsmemory_add/memory_refutetool access: the parent holds every write against the user's global, cross-repo store (see${CLAUDE_PLUGIN_ROOT}/skills/shared/references/memory.md). - Checkpoints are slice/step-granular and idempotent: a continuation re-does no committed, pushed, or tracker-posted work and re-creates no recorded worktree. A phase exceeding the resolved
ship.escalation.max_needs_decisionthreshold ofneeds-decisionreturns escalates to/sy:specas underspecified; a phase exceeding the resolvedship.escalation.max_needs_tracethreshold ofneeds-tracereturns without reachingdoneescalates the same way, on its own separate count. A GATE phase whose fix-cycle rounds for the run reach the resolvedship.escalation.max_gate_roundsthreshold, except the terminal pass (references/immutable-gate.md§ Fix cycle), is the third member of that family, and the one that asks you rather than escalating on its own (references/immutable-gate.md§ Fix cycle). Resolve all three per${CLAUDE_PLUGIN_ROOT}/skills/shared/references/config-values.md. - A review or build finding that is small, adjacent, and low-risk is fixed in-branch as a recorded scope extension, not deferred to a follow-up (see
${CLAUDE_PLUGIN_ROOT}/skills/shared/references/scope-discipline.md). - Every writable delegate gets a caller-created, recorded worktree.
- Worktrees live under
<resolved worktree root>/<branch>, where the root is the valueget_config {"key": "worktree.root"}reports — by default the sibling directory beside the repo (e.g./path/to/myrepo→/path/to/myrepo-worktrees/<branch>), overridable viaworktree.rootin config — never nested inside the working tree. sy:gatereviews an isolated worktree pinned to exact base/head SHAs.- Current PR HEAD must equal CI-green SHA and reviewed SHA before handoff or merge.
- When the plan declares a pre-gate checkpoint, current PR HEAD must also equal that checkpoint's cleared SHA before GATE's first dispatch against that head (§ Pre-gate checkpoint); once GATE has been dispatched for that head (
pregate_checkpoint_gate_dispatched), its own fix-cycle commits and resumes never re-arm this check until BUILD's nextdoneclears it. A plan that declares none — the default — never blocks here. - Model tier is a quality floor, and the parent wires it mechanically. The parent never infers a phase's model from a single word and never assumes a worker inherits the parent session's model, because a worker's own frontmatter model always wins over an omitted override. The profile's
STARTandBUILDmodels are what those workers run at; the parent dispatches theGATEworker at the model and effortagent_model {"name": "ship-gate"}reports regardless of profile, and it is the GATE worker itself — not the parent — that consumes the profile'sGATEtier via its own Resolve-gate-model procedure (references/immutable-gate.md§ Resolve gate model) to set the model override for its nestedsy:gatecall. Each phase worker runs at least its declared tier (BUILD stays at least opus) and the ship profile may raise but never lower it: every floor lives inconfig/floors.json, and the resolver refuses by name a config that drops a worker below its own. The full dispatch rule is${CLAUDE_PLUGIN_ROOT}/skills/shared/references/model-dispatch.md. - Cost-scaling never touches the reviewer: the ship profile's effort may raise BUILD effort or lower START effort, within each worker's floor, but it never touches review:
sy:gatekeeps its frontier tier, max effort, and full coverage on every path — including the trivial-diff and bounded-fix paths.config/floors.jsonpinsgateatmin_model: frontier/min_effort: max, so this is enforced by the resolver, not only by this sentence. - After merge authorization, one small bounded fix may land through the authorized bounded-fix → focused-delta-gate → merge sub-flow in
references/merge-accounting.md: the delta review is valid only when the prior reviewed head is the immutable base and the new head is the immutable head; anything broader re-enters GATE. - Resolve START's and BUILD's models explicitly from the plan's stated per-phase tiers and the profile's effort, and the gate model and effort likewise, passing each as its Agent invocation's actual
modelandeffortparameters; record requested and transcript-observed models separately per phase (references/start-resume.md§ Resolve start model,references/implementation.md§ Resolve build model,references/immutable-gate.md§ Resolve gate model). - Token accounting must aggregate the main ship transcript and all nested subagent transcripts.
- Images stay out of the long-running context: figures/screenshots/plots are inspected only through short-lived
sy:img-inspectorsubagents that return text verdicts, and no imageReadappears in a BUILD or GATE transcript (see${CLAUDE_PLUGIN_ROOT}/skills/shared/references/image-inspection.md). - Tracker machine logs are small standalone JSON comments; never bury usage or metrics JSON inside retrospectives or plan comments.
- Talking to you follows exactly one of three modes per turn — status update,
AskUserQuestion, or an isolated## Action neededblock — never blended; see${CLAUDE_PLUGIN_ROOT}/skills/shared/references/user-interaction.md. - Mandated external writes obey write integrity: a posted record later overruled or found wrong is corrected on its own surface, and a denied write is never rerouted through another tool/path to force it through — surfaced loudly instead; see
${CLAUDE_PLUGIN_ROOT}/skills/shared/references/write-integrity.md.
Compression boundary
Agent-to-agent returns use each agent's compact return contract, and a return backs its load-bearing claims with checkable evidence pointers. The parent trusts an evidence-backed brief and spot-checks decisive spans rather than re-deriving ground truth; it re-verifies in full only a load-bearing claim the brief leaves unbacked. Seed every agent prompt with known anchors — paths, symbols, plan step, keys — and name ground already covered. Human-facing tracker/PR artifacts remain clear prose; machine logs remain compact JSON.
Worker contract
The parent dispatches each of START, BUILD, and GATE (and any resumed segment) to its worker agent (sy:ship-start/sy:ship-build/sy:ship-gate), seeded with the phase procedure reference and the compact state brief; it never runs those procedures inline. Immediately before each of those dispatches — fresh or a continuation, and whatever the reason for it — the parent stamps that phase's name into phase_active in ship-state.yaml, and it clears the field back to null as part of processing whatever that worker returns (below), so it is non-null only while a dispatch is genuinely in flight (§ State router). The one exception is a fresh run's own START dispatch: ship-state.yaml does not exist yet to stamp into, so START's own seed step writes phase_active: null as part of creating the file for the first time (references/start-resume.md § Fresh run); every dispatch from that file's creation onward stamps and clears normally. HANDOFF and MERGE run in the parent, with their verbose reads delegated. A worker runs autonomously and never blocks on long external state (CI, deploys) by polling in-context or self-resuming a monitor: it waits with a token-free background poller or returns blocked with a checkpoint. It returns exactly one:
done— phase complete; updated state brief (SHAs, PR,agents_used,accepted_deviations,memory_refutations) with checkable evidence backing every load-bearing claim.needs-decision— an idempotent checkpoint plus a question brief: what was attempted, why blocked, the options, and the plan/standards spans bearing on it.needs-trace(BUILD only) — an idempotent checkpoint plus a bounded empirical question: what is still unresolved, its seed anchors, and why it crossed the spot-check bound (the same bound as/sy:spec§3) instead of staying a direct read. No candidate options — only a question a trace can resolve.handover(GATE only) — the round is complete, the loop has not converged, redispatch me; the same idempotent checkpointneeds-decisioncarries. The parent's handling is unconditionally mechanical — drain, clearphase_active, persist the checkpoint, reconcile recorded state against ground truth (§ State router), dispatchsy:ship-gateagain from it — and neverAskUserQuestion, never an## Action neededblock, never counted towardship.escalation.max_needs_decisionormax_needs_trace, and it neither increments nor rebasesgate_rounds_total/gate_rounds_budget_base. Those stay the round bound's alone (references/immutable-gate.md§ Fix cycle), which is what bounds the handovers too.bail-to-spec— the plan's contract or architecture is invalidated; reason and offending anchors. Also the escape hatch when a phase keeps returningneeds-tracewithout converging.blocked— external cause (merge authorization, infrastructure); what is required.
On any return — done, needs-decision, needs-trace, handover, bail-to-spec, or blocked alike — the parent first applies every pending MEMORY_REFUTE candidate via memory_refute, rather than waiting for the HANDOFF retro, which a bail or a crash never reaches. Applying a candidate removes it from memory_refutations in state, and each worker emits only the candidates its own segment newly observed — never an accumulated history — so a continuation worker cannot re-apply an already-applied candidate over a newer correction that superseded it. Next the parent clears phase_active to null — for any of the six values alike, ordered here rather than after the branching below so that no branch can be the one that forgets. Then the parent advances on done; dispatches a GATE continuation from the checkpoint on handover; resolves needs-decision from plan/standards/code and dispatches a continuation worker from the checkpoint, asking via AskUserQuestion only when the choice is genuinely ambiguous; resolves needs-trace by dispatching a bounded, foreground sy:trace itself — mechanical, not a judgment call, so it never reaches you as a question — and resuming the worker from the checkpoint with the findings folded in as a new anchor; stops for /sy:spec on bail-to-spec; and surfaces blocked to you as an ## Action needed block naming the external cause. Parent-owned throughout (§ Invariants), including the START profile guard.
A phase_checkpoint is written twice, and only the second write is the parent's. The worker makes its own checkpoint durable before the return (hand-back rules: ${CLAUDE_PLUGIN_ROOT}/skills/shared/references/agent-returns.md), so a refused or lost hand-back still leaves one on disk; that value is a durability floor and is already stale by the time the round ends, because GATE's write lands before that round's fixes are pushed (references/immutable-gate.md § Fix cycle). The checkpoint the return carries is re-authored at return time against the post-push SHA (CHECKPOINT: <dispositioned vs pending + pushed SHA>), so the parent's persist of it updates the durable value rather than re-affirming it, and § State router's reconcile compares against that persisted post-push value, never the floor.
A needs-decision tagged reason: reviewer_findings (references/immutable-gate.md § Fix cycle) is the second member of that family: the parent skips the resolve-it-yourself step and puts the round's declined reviewer findings to you via AskUserQuestion — act on the ones you name (a GATE continuation from the checkpoint fixes them), or accept the worker's rejections as dispositioned, plus Other; never a plain "continue". Accepting them is what lets the stopping rule converge, so this can never deadlock the loop. It touches neither gate_rounds_total nor gate_rounds_budget_base, which stay the round bound's alone.
A needs-decision tagged reason: max_gate_rounds (references/immutable-gate.md § Fix cycle) is the one that skips the resolve-it-yourself step entirely and asks you directly, offering exactly two dispositions via AskUserQuestion — never a plain "continue", which is what the bound exists to stop. Raise the budget for this run: the parent stamps gate_rounds_budget_base to the current value of gate_rounds_total and dispatches a GATE continuation from the checkpoint, counting fresh against the same cap from that base. It never resets gate_rounds_total itself, which stays monotonic for the life of the run (references/handoff-accounting.md §3). That is a state change and never a config edit, so it cannot trip the mid-run config-fingerprint stop the way editing ship.escalation.max_gate_rounds under a running ship would. Or stop and return to /sy:spec, handled exactly as any bail-to-spec. Either way the two gate_rounds_* fields, never a checkpoint's descriptive count, remain the sole authority (references/immutable-gate.md § Fix cycle).
Pre-gate checkpoint
Honouring the plan's declared pre-gate checkpoint field is parent-owned and never a worker's, resolved the way the ship profile already is (references/start-resume.md § Resolve start model). START stamps the declared channel into pregate_checkpoint_channel once at dispatch; pregate_checkpoint_cleared_sha starts null, pregate_checkpoint_changes_requested starts 0, pregate_checkpoint_gate_dispatched starts false, and pregate_checkpoint_request_text starts null. A plan that declares nothing leaves the channel null, and a null channel skips this section entirely — including on a resume from an older state file that predates these fields, where an absent channel reads the same as a declared-none one, an absent pregate_checkpoint_gate_dispatched reads the same as false, and an absent pregate_checkpoint_request_text reads the same as null.
Before GATE's first dispatch against the current head_sha — fresh after BUILD's done, or on a resume that has not yet dispatched GATE for that head — the parent checks that the channel is set and that pregate_checkpoint_cleared_sha equals the current head_sha. Set and equal means this checkpoint is already cleared on this exact commit, so GATE goes out unchanged. (A null cleared_sha never counts as equal, even when head_sha is also still null — that pairing means the checkpoint has not been reached yet, not that it is cleared.) (pregate_checkpoint_gate_dispatched is stamped true at that dispatch, same as any other.) Set and unequal is the one case that pauses: the parent presents the draft PR URL (and, for a running-preview channel, a reminder that this is a local look you take yourself — this step never launches anything) and asks via AskUserQuestion per ${CLAUDE_PLUGIN_ROOT}/skills/shared/references/user-interaction.md, framed as whether this looks like the right thing to have built — product and UX judgment, offering proceed to GATE / request changes / other. It is never framed as a correctness review and never invites one: sy:gate alone owns correctness. Once pregate_checkpoint_gate_dispatched is true, GATE owns this head exclusively: a further resume that lands back on GATE — its own needs-decision checkpoint, a retry, anything short of a fresh BUILD done — skips this whole check and dispatches GATE directly, regardless of how far head_sha has since moved from pregate_checkpoint_cleared_sha; § State router carries the identical guard for the same reason.
Proceed records the current head_sha as pregate_checkpoint_cleared_sha, stamps pregate_checkpoint_gate_dispatched true, and dispatches GATE.
Request changes first collects what to change, since neither named option carries it by itself: an Other answer's own custom text is the request verbatim; the plain Request changes label carries no text, so the parent's very next turn asks one more AskUserQuestion dedicated to collecting it, offering a real way back out ("proceed to GATE after all", "this needs a fresh /sy:spec revision instead") alongside Other for the description itself — either path converges on one non-empty string. Picking the first escape ("proceed to GATE after all") re-routes exactly as Proceed does above, and none of the fold-in below ever runs. Picking the second ("this needs a fresh /sy:spec revision instead") stops here rather than dispatching BUILD at all — the same stop-for-/sy:spec handling the parent already gives any bail-to-spec (§ Worker contract). Both escapes are matched by intent, not literal label text: a free-text Other answer whose own words plainly mean the same thing as an escape routes identically to it, never as a change request. For any answer that is a real change request (not one of the two escapes above), the parent stamps that string into pregate_checkpoint_request_text, increments pregate_checkpoint_changes_requested by one, and dispatches a fresh BUILD continuation from BUILD's own phase_checkpoint — the identical continuation-from-checkpoint mechanism needs-decision already uses, so the worker contract stays closed at six: no worker signals, prompts for, or can even observe this checkpoint. That continuation's checkpoint holds no pending plan slice by construction — BUILD had integrated them all before returning done — so pregate_checkpoint_request_text is what gives it work, folded into BUILD's own manifest as one new pending slice (references/implementation.md § Delegated slice protocol). phase_checkpoint stays entirely worker-authored — the parent never writes a slice, only the field it hands off.
Whatever BUILD returns next from that continuation — done, needs-decision, needs-trace, bail-to-spec, or blocked — the parent's handling of that return is where pregate_checkpoint_request_text is cleared back to null, in the same write that persists whatever phase_checkpoint the return carries, never as a separate later step a crash could land between: a session that dies before BUILD ever returns can leave the text set against a manifest that already carries it, which is why folding it in is guarded by the dedup rule in ${CLAUDE_PLUGIN_ROOT}/skills/ship/references/implementation.md § Delegated slice protocol rather than by write ordering; and a blocked return (external cause, per § Worker contract) clears it too, since the fold-in already happened before whatever blocked BUILD did, and leaving it set would refold the same text on the eventual resume. Processing BUILD's eventual done is also where the parent — never BUILD, which is barred from naming the field at all — resets pregate_checkpoint_gate_dispatched back to false for the new head, in that same write; pregate_checkpoint_cleared_sha needs no matching reset, since it goes stale the moment head_sha changes.
GATE itself never re-enters this section once dispatched; pregate_checkpoint_gate_dispatched is what makes that mechanical. Its fix-cycle commits are review remediations bounded by ${CLAUDE_PLUGIN_ROOT}/skills/shared/references/scope-discipline.md, not the product/UX surface this checkpoint exists to catch.
State router
Preflight (above) runs once, first, ahead of this classification — including on resume, since a checkpoint can route straight to BUILD or GATE without ever passing through START.
The plan is materialised in that same step, for the same reason, on every session alike — fresh and resume: the parent calls plan_file on the Task, which resolves the highest plan version and writes that comment's ## For /sy:ship half to a file, and the parent then names that file's absolute path in whichever worker's dispatch prompt it goes on to send. It belongs here rather than in any phase procedure because no worker after the parent holds a tracker read at all. The parent's own context never takes on the plan text: the tool returns a path and the pin, never the body.
The pin comparison against recorded state is the resume-only half of that same call. On a fresh run there is nothing recorded to compare against and the returned path/comment_id/version are simply stamped into state as plan_path/plan_comment_id/plan_version (references/start-resume.md). On a resume the parent compares what plan_file just returned against what state already carries: unchanged, dispatch as the classification below decides; changed, the plan was revised mid-run and it is handled exactly as any bail-to-spec (§ Worker contract) — never resumed against a phase_checkpoint built from the plan that got superseded. State carrying none of the three fields is a file written before they existed and reads as null, which is nothing recorded rather than a mismatch; this step supplies them.
On resume the parent also loads ship-state.yaml here and drains it before dispatching whichever phase the classification lands on: any memory_refutations still listed are pending, not history, so the parent applies each via memory_refute and clears the list from state — the same drain rule as an in-flight worker return (§ Worker contract). It belongs in this pre-dispatch step for the reason the materialisation above does, and the HANDOFF retro deliberately does not backstop it; an undrained list means the refuted anchor is still read back as if it held.
phase_active is checked in that same pre-dispatch step and for the identical reason. A non-null value here means the last thing that happened was a dispatch whose return was never processed (§ Worker contract clears it on every return, including blocked), so the parent surfaces it in the state brief — the prior session ended without confirming its last dispatched phase finished cleanly, worth a quick sanity check of the recorded worktree before trusting the checkpoint — and then clears it to null unconditionally, because a stale flag left set reports the same crash again after a clean resume. This changes nothing about classification: it is a note attached to whatever phase the classification lands on, and an absent or null field means nothing was in flight.
The same reasoning covers a declared but unresolved pre-gate checkpoint. Before GATE's first dispatch against the current head — fresh after BUILD's done, or a resume classifying straight to GATE that finds pregate_checkpoint_gate_dispatched still false — the parent checks pregate_checkpoint_channel against pregate_checkpoint_cleared_sha == head_sha and, on a mismatch, routes into § Pre-gate checkpoint's same AskUserQuestion rather than dispatching GATE directly; a null/absent channel, or a true pregate_checkpoint_gate_dispatched, both fall straight through (§ Pre-gate checkpoint). A set pregate_checkpoint_request_text overrides all three: it means a BUILD continuation was dispatched to fold it in but has not yet returned, so any resume classifies to BUILD, not GATE, until that continuation's own return clears the field (§ Pre-gate checkpoint) — regardless of what channel, cleared_sha, or gate_dispatched say.
Stack detection runs before START's dispatch on a fresh run: call get-issue on each of the Task's dependencies entries (bare keys) for its status. With dependencies_truncated set, the blocker rule in § Invariants applies unchanged. For exactly one not-done blocker, run gh pr list --state open --search "<KEY>" --limit 100 --json number,title,headRefName,headRefOid,baseRefName,isDraft,isCrossRepository and match the key against headRefName (prefix <KEY>/) or title. Exactly one match with isCrossRepository false whose baseRefName is the target branch → pass {issue, pr, branch, head_sha} in START's dispatch prompt through the existing blocker hand-in (references/start-resume.md step 2); otherwise pass nothing new.
Before every GATE dispatch — the fresh one after BUILD's done, every handover continuation (§ Worker contract), and a resume that classifies to GATE — and on every resume whatever phase it lands on, the parent reconciles recorded state against ground truth. It runs after the pregate_checkpoint_cleared_sha == head_sha comparison above and never before it: stamping a moved head_sha first would re-raise a checkpoint already cleared for that head. Three reads: git log <recorded head>..origin/<branch> for commits the state file never saw; gh pr view --json headRefOid,isDraft, whose isDraft catches a PR promoted by a round whose return was refused, so the parent does not re-promote it (${CLAUDE_PLUGIN_ROOT}/skills/ship/references/handoff-accounting.md establishes that command shape only — its own field is mergedAt); and the worker_handbacks tool (tool names resolve per ${CLAUDE_PLUGIN_ROOT}/skills/shared/references/config-values.md) passed state's ship_session_id, for a return this session recorded as refused. A null or unresolvable id — references/start-resume.md seeds it only "if available" — skips the hand-back check and says so in the state brief, never an error. A non-empty warnings list on that report means the subagent tree was not fully read, so refused is a floor rather than an exact count, and it is surfaced in the state brief the same way.
One delta is expected rather than a mismatch: GATE writes the round's state before that round's fixes are dispatched (references/immutable-gate.md § Fix cycle), so at every handover the recorded head legitimately lags the pushed head by exactly that round's fix commits. A delta the handover checkpoint's own pushed SHA accounts for is normal and is not a mismatch; without this exemption the check fires on every converging round and the coverage it nulls was fine. For anything else, ground truth wins: stamp the live head into head_sha, null reviewed_sha/ci_green_sha that no longer cover it and record that a delta review is owed, and surface any mismatch, any refused hand-back, and any warnings in the state brief exactly as a stale phase_active already is. It only nulls coverage or restates the head — it never promotes, merges, or marks a round complete.
When stacked_on_pr is set and stacked_on_landed_sha is null, that same reconcile reads the blocker PR's state and isDraft first, on fresh and resume dispatches alike: MERGED → this GATE dispatch runs Blocker landed (references/immutable-gate.md § Fix cycle) before Pin scope; CLOSED → handle as bail-to-spec; OPEN and draft, before GATE's first dispatch for this head → no dispatch, end with ## Action needed: GATE starts once blocker PR #N is promoted, so re-run /sy:ship <task> then (BUILD's work is already pushed); OPEN and ready → dispatch.
Classify first, then load only the needed procedure:
START initialize/resume ownership → ship-start worker · references/start-resume.md
BUILD implement/integrate plan, draft PR → ship-build worker · references/implementation.md
GATE CI, immutable review, promote → ship-gate worker · references/immutable-gate.md
HANDOFF retro, usage, metrics → parent · references/handoff-accounting.md
MERGE direct user merge authorization → parent · references/merge-accounting.mdDo not preload mutually exclusive procedures; a worker loads only its own.
Completion bar
Normal completion is a reviewable PR with current acceptance evidence, green CI and independent review covering the same head, the automated reviewer explicitly requested with the request confirmed (when ship.request_ci_reviewer resolves true — see ${CLAUDE_PLUGIN_ROOT}/skills/shared/references/config-values.md), and every review thread that exists when GATE converges — bot and human — reconciled and answered rather than left for you, a doc-accuracy self-check over the shipped documentation diff, Task in-review, human retrospective, and standalone JSON usage/metrics comments. A review requested since promotion and still pending, or a thread opened since GATE's last pass and still unanswered, at handoff is a residual the handoff status names. Then stop at handoff.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

