"Ship a release — sync branch, run tests, audit coverage, push, open PR, then auto-chain → /landAndDeploy → /canary → /syncDocs (skip the deploy chain with --no-deploy)."
Install
npx skillscat add jthorare/agentic-workflow/shiprelease Install via the SkillsCat registry.
Ship Release
Syncs your branch, runs tests, audits coverage, pushes, opens a PR, and optionally invokes /syncDocs.
Before anything else: read $HOME/.agentic-workflow/toolkit/skills/_preamble.md and follow it (skill index, provider capability map, bootstrap check, session context). Run its Session Close section when this skill finishes.
Step 1: Pre-flight Checks
Confirm the working tree is clean:
git status --porcelainIf the output is non-empty, stop and ask the user to commit or stash their changes before continuing.
Parse arguments:
--base <branch>— the base branch to rebase onto and target for the PR. Default:main.--skip-docs— if present, skip the/syncDocsinvocation in the final auto-chain step.--no-deploy— if present, skip the/landAndDeployauto-chain (Step 7) and fall through directly to/syncDocs. Use for release-branch workflows where merge happens elsewhere or deployment is manual.--min-coverage <pct>— optional. If coverage is measurable and below this threshold, stop before push and report.
Derive the current branch name:
git branch --show-currentIf on
main(or the same as--base), stop and tell the user: "You are on the base branch. Check out a feature branch first."
Step 2: Sync
Fetch the latest from origin and rebase on the base branch:
git fetch origin
git rebase origin/{base}If the rebase encounters conflicts, stop immediately and tell the user:
"Rebase conflicts detected. Resolve them manually, then run
/shipReleaseagain."
Do not attempt to auto-resolve conflicts.
Step 3: Test
Resolve the shared dir from this skill's own symlink, then detect the runner:
SHARED_DIR="$HOME/.agentic-workflow/toolkit/skills/_shared"Read $SHARED_DIR/test-runner-detection.md and set TEST_CMD from its runner table. If no runner is detected, report "tests: n/a — excluded from scoring" and continue (never score an undetected runner as a failure).
Run TEST_CMD. If any tests fail, stop and report:
- Which test runner was used
- The full failure output
- A summary of which tests failed
Do not proceed to push or PR creation on test failure.
Step 4: Coverage Audit
Set COVERAGE_CMD from the coverage table in $SHARED_DIR/test-runner-detection.md (already read in Step 3).
If coverage tooling is available:
- Run
COVERAGE_CMDand report the overall coverage percentage. - List any files below 80% coverage as warnings (do not fail the release for low coverage).
- If
--min-coveragewas passed and overall coverage is below it, stop and report the shortfall.
If no coverage tools are detected, note "Coverage: not available" and continue.
Step 4.5: App Verification (user-facing diffs)
Check whether the diff touches UI or routes:
git diff origin/{base}..HEAD --name-onlyIf any changed file is a UI component, page, route, template, or stylesheet:
- Invoke skill
verify-appwith args--yes auto— auto mode infers screens from the diff;--yesskips the confirmation re-prompt. AFAILverdict blocks the push: stop and report the evidence-pack path. - Baseline check: if
~/.agentic-workflow/$REPO_SLUG/design/screens.jsonexists and any of its screens match the changed files/routes, also Invoke skilldesign-verify. A FAIL diff (>10%) blocks the push.
If the diff is not user-facing, note "verification: n/a (no UI/route changes)" and continue.
Step 5: Push
Push the branch to origin:
git push origin {branch}If the push fails (e.g., rejected due to non-fast-forward), report the error and stop.
Step 6: Open PR
Duplicate check first. If a PR already exists for this branch, report its URL and skip creation:
gh pr list --head {branch} --base {base} --json number,urlBuild the PR body from the template in $SHARED_DIR/pr-body.md (read it; re-source SHARED_DIR as in Step 3 — shell state does not persist between shell calls):
## Summary— commits since divergence:git log origin/{base}..HEAD --format="- %s" --no-merges, plus the "why".## Evidence— pull the newest verification pack:
Embed the pack'ssource "$SHARED_DIR/repo-slug.sh" ls -1dt "$AW_DIR/verification/"*/ 2>/dev/null | head -1evidencetext per$SHARED_DIR/evidence-pack.md: the verdict line, journey table, mockup diff %, and cross-check raw output — plus artifact paths. Never just a pointer.## Tests— runner + counts from Step 3.## Coverage— % from Step 4 (or "not available") + files below 80%.## Key decisions/## Review resolutionper the template (None.when empty).
Draft-only rule (CD13): if the diff is user-facing (Step 4.5) and the verification pack is missing or its verdict is FAIL, do NOT open a ready PR — create it with --draft and a warning checkbox noting the missing/failed evidence.
Create the PR with gh pr create --base {base} --head {branch} --title "{branch}" --body "..." (adding --draft when the rule above applies). Capture the PR URL and number for the report and the next step.
Step 7: Auto-chain /landAndDeploy
Unless --no-deploy was passed, first write the structured ship→deploy handoff (read + deleted by /landAndDeploy):
source "$SHARED_DIR/repo-slug.sh"
mkdir -p "$AW_DIR/releases"
cat > "$AW_DIR/releases/.pending-ship.json" <<EOF
{ "branch": "{branch}", "base": "{base}", "tip_sha": "{short-sha}",
"pr": {number}, "pr_url": "{url}", "tests": "passed ({N} tests)",
"coverage": "{pct}% | not available", "evidence_pack": "{newest pack dir or null}",
"shipped_at": "{ISO timestamp}" }
EOFThen Invoke skill landAndDeploy with args --wait --chained-from-ship, passing the PR number captured in Step 6. If the user passed --skip-docs to shipRelease, also pass --skip-docs to /landAndDeploy.
The --chained-from-ship flag tells /landAndDeploy to graceful-degrade if deploy.json is missing (a first-time user's shipRelease shouldn't hard-fail because the deploy wizard hasn't been run yet). It also tells /landAndDeploy to fold the ship-phase metadata from .pending-ship.json into its deploy.md output rather than it being written by shipRelease.
The --wait flag tells /landAndDeploy to poll for merge before deploying — so this step works correctly even though the PR may not yet be merged at the moment shipRelease completes.
The --skip-docs flag propagates through the entire chain: shipRelease → landAndDeploy → canary → syncDocs. Both /landAndDeploy and /canary forward the flag; /canary suppresses its own auto-/syncDocs invocation when the flag is set.
On successful deploy, /landAndDeploy auto-chains /canary, which on a HEALTHY verdict auto-chains /syncDocs (unless --skip-docs was propagated). The full chain becomes:
shipRelease → landAndDeploy → canary → syncDocsIf --no-deploy was passed, skip this step entirely and fall through to Step 8 (direct /syncDocs invocation). Use --no-deploy for release-branch workflows where merge happens elsewhere or deployment is manual.
Record whether the deploy chain was started or skipped, and whether --skip-docs was forwarded.
Step 8: Invoke /syncDocs (fallback)
If Step 7 was skipped (because --no-deploy was passed) and --skip-docs was not passed, invoke the /syncDocs skill directly to update documentation:
/syncDocsIf Step 7 ran, do not invoke /syncDocs here — the canary → syncDocs chain handles it.
If --skip-docs was passed, skip this step.
Record whether docs were updated, deferred to the canary chain, or skipped.
Step 9: Report
Release record handoff. The canonical release-id scheme (CD7) is <ISO-date>-<short-sha>, one dir per release: releases/<ISO-date>-<short-sha>/. In the default chain the short SHA is the merge commit SHA, generated by /landAndDeploy — the canonical post-merge identifier /canary also uses. shipRelease cannot know the merge SHA at push time (especially for squash merges), so:
Default chain (
/landAndDeployis invoked in Step 7): do NOT write a separateship.mdhere. The ship-phase metadata travels viareleases/.pending-ship.json(Step 7);/landAndDeployfolds it into a## Ship Phasesubsection at the top of itsdeploy.md. This guaranteesdeploy.mdandcanary.mdalways live in the samereleases/<ISO-date>-<short-sha>/subdir — no split across two dirs when tip-SHA ≠ merge-SHA.--no-deployinvocation (Step 7 skipped): since no/landAndDeploywill run, shipRelease writes a standalone ship summary to~/.agentic-workflow/$REPO_SLUG/releases/<ISO-date>-<tip-short-sha>/ship.md— same CD7 id form, using the tip SHA since no merge SHA exists yet (e.g.2026-05-15-a1b2c3d). Deploy information will not be available.# Release: {branch} - **Release ID:** {ISO-date}-{tip-short-sha} - **Date:** {ISO timestamp} - **Base:** {base} - **Branch:** {branch} - **Tip SHA:** {short-sha} - **Test result:** passed ({N} tests) - **Coverage:** {percentage}% (or "not available") - **Files below 80%:** {list or "none"} - **PR:** {url} - **Deploy chain:** skipped (--no-deploy) - **--skip-docs forwarded:** n/a (no deploy chain) - **Docs updated:** {yes / skipped}
Print a summary to the user:
Release shipped!
Branch: {branch} → {base}
Tests: passed
PR: {url}
Deploy: {chained via /landAndDeploy --wait --chained-from-ship | skipped (--no-deploy)}
Docs: {updated | deferred to canary chain | skipped}
Report: {handed to /landAndDeploy via .pending-ship.json | ~/.agentic-workflow/<repo-slug>/releases/{ISO-date}-{tip-short-sha}/ship.md}Next steps
- (auto)
/landAndDeploy— chained after PR creation, polls for merge then deploys (skip with--no-deploy) - (auto)
/canary— chained by/landAndDeployon successful deploy - (auto)
/syncDocs— chained by/canaryonHEALTHYverdict (or directly byshipReleaseif--no-deploy)