Use when a branch or PR is implementation-complete and the user wants it taken through the explicit merge gate and cleanup.
Install
npx skillscat add taloncjones/dotfiles/ship Install via the SkillsCat registry.
Ship
Ship completes implementation, tests, release-version work, one final
co-review, then asks for explicit merge permission. It never treats a comment
or a historical review as present-session authority.
Target resolution
- A PR number or URL selects that PR.
- Otherwise use the current branch's open PR (
gh pr view). If none exists,
offer to create one under the existing PR rules. - State the selected PR, target branch, and linked Jira ticket before work.
- If the PR is already merged, go directly to
post-mergecleanup.
For a PR, verify that origin is its real base repository using the pulls REST
response and git remote get-url origin. A fork's origin cannot resolve the
target base. Stop if either identity is unavailable or mismatched.
Steps
Complete the change. Make only authorized implementation changes. Use
review-changefor development feedback when useful; advisory feedback is
not an automatic fix queue. Resolve concrete blockers and run the relevant
tests before the final gate.Version work. If the repository versions releases, make the authorized
version change now and rerun affected tests. Do not change a version after
final co-review. Skip when the repository has no release version.Final gate. Invoke
co-reviewonce against the live PR target, with its
realbaseRefName. The active workflow retains the resulting report and its
independently created expected-identity file.CHANGESreturns concrete
blockers to development.INCOMPLETEstates the missing evidence. Do not
auto-fix and relaunch a full gate. An explicitly user-invokedco-review --fixsupplies its scoped repair authorization; existing
development authorization also covers that handoff. It uses its own bounded
coordinator policy, including one follow-up verification of repairs and
affected contracts with evidenced carried coverage. Exhaustion stops ship
and the outer development workflow. A changed head, diagnosis or resumed
session cannot renew the allowance; only new explicit user direction after
the stop can. Changed identity or interruption invalidates approval and is
a stop, not permission to automatically launch another gate.co-reviewself-classifies the frozen diff (lessons for a diff touching onlyclaude/rules/personal/agent-lessons.md, light for other prose-only changes,
small for a code change of at most 3 files and 40 changed lines with a test
and green CI, full otherwise); pass--fullwhen a prose change alters a machine-read
contract, such as a SKILL.md block a test greps.
A herdr brief lineherdr-ship-brief: tier=autoruns plainco-review(the
classifier picks the tier) with the caps from `herdr-ship-small-caps:
/and the prefixes fromherdr-ship-small-sensitive:passed toclassify. herdr-ship-brief: tier=fullrunsco-review --full. herdr-ship-brief: tier=deltarunsco-review --deltawith the prior report, expected identity and digests read from theship.jsonnamed byherdr-ship-prior-handoff:, the caps from herdr-ship-delta-caps:, and the head bound by herdr-ship-delta-head:; the co-review Delta tier section decides the final tier. A delta or small gate's escalate: "full"` is not a relaunch after a fix: in a herdr launch it ends the launch, and
interactively the co-review Delta tier or Small tier section runs its one
fresh full gate.
Recheck gate evidence. Immediately before presenting a merge-ready
result, fetch live PR head, base branch, target base (the live tip fromgit ls-remote origin refs/heads/<base branch>, not the laggingbaseRefOid), and CI. The active
report path and successfully finalized expected-identity path must both be
present from this same uninterrupted workflow. Cleanup failure invalidates
and removes the active expected identity, so it always requires a new gate.
Read the expected file and stop unless its
repository, PR number, head, and base branch exactly equal the live
values. Also stop unlessgate_report.py base-check --repo <repo> --expected EXPECTED --head <head> --live-base <live-base>exits 0; it
re-derives the reviewed tree from the gated base and refuses a head that
no longer merges cleanly with the live base. Refresh its CI artifact: rungate_report.py ci-capture --repo <repo> --expected EXPECTED --out <the report's preconditions.ci artifact path>. Exit 0 continues; an exit 1
whosereasonsis exactly["CI evidence is missing"]continues only
when the report carriespreconditions.no_cievidence; any other nonzero
exit stops. Write its printedsha256into the report'spreconditions.ci.sha256, then
invokegate_report.py evaluate --report REPORT --expected EXPECTED. The
co-review snapshot has already been verified and cleaned; this step checks
live source/PR identity and retained report artifacts, not a deleted manifest.
A changed identity, failed evaluation, absent active files, or session interruption
invalidates approval and stops this workflow. A fresh review needs the
caller authorization described above; historical PR comments never resume
this step. One exception: a head whose only new commits since the gated
head merge the base branch keeps the verdict when the co-review skill'scarry-forwardcommand exits 0 against this workflow's retained report and
expected identity and their digests; keep its record, redo this step's live
recheck against the new head, and continue without a new round.Audit comment. Only in this same uninterrupted workflow, right after
step 4 passes (an interrupted workflow stops under the existing step 3/4
rules and never posts from its report):uv run --no-project python "$GATE_REPORT" audit-comment --report REPORT --expected EXPECTED >"$RUN_DIR/audit-comment.md"; a nonzero exit means
no post. For a head carried by step 4's exception, write the
carry-forward record'saudit_commentto that file instead; its marker
line names the new head, so the same dedupe applies.gh api --paginate "repos/{owner}/{repo}/issues/<n>/comments" --jq '.[].body' >"$RUN_DIR/pr-comments.txt". If that fails, do not post and
report "audit comment not posted". If any body containsco-review-audit head=<head>, do not post.- Otherwise
gh pr comment <n> --body-file "$RUN_DIR/audit-comment.md".
On an error, list once more; a present marker counts as posted,
otherwise report the failure. Never retry blindly.
The marker is read only to avoid a duplicate, never as review authority. A
missing audit comment does not block the merge step; report it. This is
the standing authorization for the post (roadmap, 2026-09-23).Merge gate. A run whose brief contains the line
herdr-ship-brief: stop-after-gateends after step 4: it skips steps 5-7,
writes theship.jsonhandoff the brief names, and never merges; the
herdr director merges in a personal repository and a human merges in a
work repository. Every other run presents the findings disposition,
test results, CI state, version change, and active evaluator result, and
asks for explicit merge confirmation. Required human approvals remain
separate from evaluator approval. On confirmation, squash merge withgh pr merge --squash --match-head-commit <expected-head>so the server
refuses a moved head.Cleanup. Invoke
post-merge, then report remaining cleanup state.
Notes
- Stop on a failed test, red or pending required CI, merge conflict, missing
active report, missing human approval, or evaluator failure. shipauthorizes the delivery workflow. The explicit step 6 confirmation
authorizes the merge.- Command-mode redesign, PR metadata automation, and
/readyremoval remain
deferred to the separate shipping-workflow change.