---
name: r-ship
description: >
Use when a plan is built and verified and you want to cut a release: preflight, verification, release prep, and publish.
---
You are running the /rdf:r-ship release workflow. This is a composite
workflow that verifies readiness, dispatches quality gates, prepares
release artifacts, and publishes a PR.
## Arguments
$ARGUMENTS (optional, any order):
- base branch override (default: auto-detect via
`git symbolic-ref refs/remotes/origin/HEAD` or fall back to `main`)
- `--version X.Y.Z`: the version this run ships. When absent, Setup prompts
for it (see *Target version* below)
## Setup
- Read .rdf/governance/index.md to understand the project
- Load governance/verification.md for project-specific release checks
- Load governance/conventions.md for commit/changelog format
- Determine project name, version, and branch from governance index
### Target version
Resolve the version *being shipped* before any gate runs. The on-disk version
still names the **previous** release until Stage 3 bumps it, so a gate that
reads it judges the wrong release.
1. If `$ARGUMENTS` carries `--version X.Y.Z`, that is the target.
2. Otherwise read the on-disk version (root `VERSION` file, or the project's
in-file `VERSION=` variable) and prompt, defaulting to the next minor:
`Target version for this release [next minor <MAJOR>.<MINOR+1>.0]:`
3. If no on-disk version is readable and the user supplies none, record
`VERSION: unknown`.
Write the answer to the progress file's `VERSION:` field. Stages 1d and 3c
read the target from there, so a resumed session gates the same release.
## Resume Detection
Source `~/.rdf/state/rdf-bus.sh` and call `rdf_session_init`. If the helper is
absent (helpers not yet bootstrapped: fresh plugin install before its first
session restart), skip resume detection and proceed without session-scoped
progress; restart the session (plugin) or run `rdf deploy claude-code`
(checkout) to deliver them. Then look for
`.rdf/work-output/ship-progress-${RDF_SESSION_ID}.md`. If not found, glob
`.rdf/work-output/ship-progress-*.md` and present candidates ordered by mtime.
If exactly one un-suffixed `.rdf/work-output/ship-progress.md` exists (legacy
from pre-3.1.0), prompt: "Found legacy progress file. Import? [Y/n]".
If a progress file is found:
1. Read the STAGE and STATUS fields
2. Offer: "Found interrupted ship session at stage {stage}. Resume from here? [Y/n]"
3. If Y: skip stages already marked complete, resume from the current stage
4. If N: delete `ship-progress-${RDF_SESSION_ID}.md` and start fresh
After each stage completes, write state to `.rdf/work-output/ship-progress-${RDF_SESSION_ID}.md`:
```
STAGE: {preflight|verify|prep|publish|report}
STATUS: {complete|in-progress}
PR_URL: {if created}
VERSION: {target release version, resolved at Setup}
```
## Stage 1: Preflight
Run all four checks and display results as a task list. Each check
is pass/fail: a checked box means the gate passed.
### 1a. Plan Completion Check
- Source `~/.rdf/state/rdf-bus.sh`; `rdf_session_init`. Resolve the active
plan: `plan_path="$(rdf_active_plan_path)"`.
- Read `$plan_path`: verify ALL phases are marked complete.
- If any phases are incomplete, report which ones and STOP.
- If no active plan resolves, skip this check (ad-hoc release).
### 1b. Working Tree Check
- Run `git status` (never `-uall`), `git diff --stat`
- If there are uncommitted changes, list them and ask the user
whether to commit, stash, or abort
- If working tree is clean, proceed
### 1c. Branch Check
- Verify current branch is not `main`/`master` (should be a
feature/release branch)
- Identify base branch for PR target
- Run `git log --oneline $(git merge-base HEAD origin/{base})..HEAD`
to summarize branch changes
### 1d. Platform Triage
Per-minor gate (D4, `docs/specs/2026-09-02-platform-alignment-spike-design.md`
§6): a minor release must not ship without a current platform re-triage
verdict; patch releases are unaffected.
- Split the **target version** from Setup (the progress file's `VERSION:`
field) into `MAJOR.MINOR.PATCH`. Do not read the on-disk `VERSION` here;
Stage 3 has not bumped it yet, so it names the previous release and would
gate the wrong one.
- If the target is `unknown`, mark `[x]` with *(skipped: no target version)*
and skip the remaining steps below.
- If `PATCH` is non-zero the gate does not apply: mark
`[x] **Platform triage**: *(skipped: patch release X.Y.Z)*` and skip the
remaining steps below.
- Otherwise grep `docs/platform-triage.md` for a block matching
`^## <MAJOR.MINOR> \(`:
- Present: `[x] **Platform triage**: \`<MAJOR.MINOR>\` ledger current`.
- Absent: `[ ] **Platform triage**: no \`## <MAJOR.MINOR> (<date>)\` block
in \`docs/platform-triage.md\`` and
`> **Blocked** (preflight failed): platform triage missing for
<MAJOR.MINOR>`.
### Preflight Display
Present results as a task list with inline code for values:
```
### Preflight: target `3.7.0`
- [x] **Plan**: all phases complete (`12`/`12`)
- [x] **Working tree**: clean
- [ ] **Branch**: on `main` (*expected a feature/release branch*)
- [x] **Platform triage**: `3.7` ledger current
```
A patch target renders the last line as
`- [x] **Platform triage**: *(skipped: patch release 3.7.1)*`.
If a check fails, use an unchecked box and add an italic reason.
If a check is skipped, use a checked box with *(skipped)* annotation.
> **Blocked** (preflight failed): {reason}
Use a blockquote for any blocker that halts the workflow.
## Stage 2: Verification (dispatches subagents)
Dispatch two subagents in parallel:
### 2a. QA Verification
Dispatch qa subagent with:
- Scope: full branch diff against base
- Instruction: run every check in governance/verification.md
- Instruction: produce structured pass/fail report
### 2b. Reviewer Sentinel
Dispatch reviewer subagent in sentinel mode with:
- Scope: full branch diff against base
- Instruction: run all 3 passes (anti-slop, regression, security)
- Instruction: produce structured verdict report
### 2c. Gate Evaluation
- Collect both subagent reports
- If QA reports FAIL: show failures, ask user to fix or override
- If reviewer reports MUST-FIX: show findings, ask user to fix or
override
- If both pass: proceed to Stage 3
- User can override gate failures with explicit confirmation
### Gate Display
Present gate results as a task list: checked = passed, unchecked =
failed or pending:
```
### Verification Gates
- [x] **QA**: *PASS*, `672` tests, `0` failures
- [ ] **Reviewer**: *MUST-FIX*, 2 findings (1 security, 1 regression)
```
If a gate fails, show the findings immediately below in a blockquote:
> **QA Gate Failed**: 3 test failures
> - `test/core.bats` line 42: expected `0`, got `1`
> - `test/trust.bats` line 118: timeout after 30s
> - `test/cli.bats` line 55: missing output line
Ask user to fix or explicitly override.
## Stage 3: Release Prep (main context)
### 3a. Changelog Generation
- Read existing CHANGELOG (and CHANGELOG.RELEASE if present)
- Generate entries from `git log` since last tag/release
- Use governance/conventions.md for changelog format
- Deduplicate entries (absorbs v2 rel-chg-dedup logic)
- Present changelog diff to user for approval
### 3b. AI Attribution Scrub
- If governance requires it (check conventions.md for attribution
policy): grep for Co-Authored-By, AI attribution, Claude/Anthropic
references in staged files
- Report any findings and offer to remove them
### 3c. Version String Verification
- Grep for version strings across the codebase (VERSION file,
package.json, setup.py, Cargo.toml, etc.)
- Verify all version references are consistent
- Verify the on-disk version now equals the target recorded at Setup; this is
what proves Stage 1d gated the release actually being shipped
- If mismatches found, report and ask user to fix
### 3d. Commit Release Prep
- Stage changelog updates and any scrub fixes
- Commit with project's message format from governance/conventions.md
- Push branch to origin
### 3e. Living-Spec Fold (docs/specs/CURRENT.md)
Fold this release's outcome into the maintained current-state spec. **Skipped
when `rdf_active_tier` is `bugfix`** (a defect fix does not change the
architecture) and when the plan File Map cannot be parsed (degrade, never
block the release).
1. `source ~/.rdf/state/rdf-bus.sh; tier="$(rdf_active_tier)"`. If `bugfix`, skip.
2. Read `docs/specs/CURRENT.md` (create with a living-spec header if absent).
3. Derive an ADDED / MODIFIED / REMOVED delta from the shipped plan's File
Map (New→ADDED, Modified→MODIFIED, Deleted→REMOVED) plus the changelog
entries from Stage 3a (one-line summaries). If the File Map cannot be
parsed, emit a notice and skip.
4. Present the delta to the user for approval (a few bullets; keep it light,
this is cheap, not ceremony).
5. On approval, prepend a `## <version> (<date>)` block to CURRENT.md and
stage it with the release commit (amend Stage 3d's commit or a follow-up).
OpenSpec precedent; this must stay lightweight, never ceremony.
### Clear the active-plan and tier pointers
After the release tag/commit lands, clear the session pointers:
```bash
source ~/.rdf/state/rdf-bus.sh
rdf_clear_active_plan
rdf_clear_active_tier
```
The plan file in `docs/plans/` is retained as historical record; only
the session-scoped pointers are removed so the next planning session
starts clean with no stale tier.
### Release Prep Display
Present release prep results as a task list:
```
### Release Prep
- [x] **Changelog**: updated, `12` entries added to `CHANGELOG`
- [x] **Attribution scrub**: clean, no AI references found
- [ ] **Version strings**: *mismatch*: `VERSION` says `2.0.2`, `setup.py` says `2.0.1`
- [x] **Commit**: `a1b2c3d` pushed to `origin/2.0.2`
```
If version mismatches are found, use a blockquote:
> **Version Mismatch**: resolve before proceeding
> - `files/apf`: `VERSION="2.0.2"`
> - `setup.py`: `version="2.0.1"`
## Stage 4: Publish (main context, user confirmation required)
### 4a. Create PR
- Use `gh pr create` with:
- Short title (under 70 chars) summarizing the release
- Structured body with ## Summary (from changelog), ## Verification
(QA + reviewer verdicts), ## Test Plan
- If PR already exists for this branch, print URL and skip creation
- Capture PR number and URL
### 4b. Monitor CI (if configured)
- Check for CI status checks on the PR
- If CI is running, poll periodically (up to 10 minutes)
- Report CI results as they complete
- If CI fails, report which checks failed
### 4c. User Confirmation
- Present final summary and ask user to confirm merge readiness
- Do NOT auto-merge; the user decides
### Publish Display
After PR creation, show a brief confirmation. Use inline code for
the PR URL and number so they stand out:
```
### PR Created
**PR** `#42`: {title}
**URL**: {url}
```
For CI monitoring, use a task list that updates as checks complete:
```
### CI Status
- [x] **lint**: *pass* (12s)
- [x] **test-debian12**: *pass* (1m 42s)
- [ ] **test-rocky9**: *running*
- [ ] **test-centos7**: *pending*
```
When CI completes, collapse into a single line in the final report.
## Stage 5: Final Report
Present a structured summary using tables, task lists, and
blockquotes. This is the final output the user sees; it must be
scannable at a glance.
```
## Ship Report: {project} `{version}`
| Property | Value | Property | Value |
|----------|-------|----------|-------|
| **PR** | {url} | **Commits** | `{count}` |
| **Branch** | `{branch}` -> `{base}` | **HEAD** | `{hash}` |
---
### Verification Gates
- [x] **QA**: *PASS*, `{test_count}` tests, `{fail_count}` failures
- [x] **Reviewer**: *APPROVE* ({summary})
### Release Prep
- [x] **Changelog**: updated, `{entry_count}` entries
- [x] **Attribution scrub**: clean
- [x] **Version strings**: consistent (`{version}`)
- [x] **Commit**: `{hash}` pushed to `origin/{branch}`
### CI
- [x] **Status**: *pass*, all checks green
---
### Verdict
**READY TO MERGE**: all gates passed, PR awaiting review
```
**Verdict styling**: use bold for the verdict keyword and a brief
reason. Three possible verdicts:
- **READY TO MERGE**: all gates passed, no action needed
- **ACTION NEEDED**: non-blocking findings or overridden gates
- **BLOCKED**: unresolved gate failures
When the verdict is not READY TO MERGE, use a blockquote to
highlight what needs attention:
> **ACTION NEEDED**: reviewer flagged 1 concern (overridden by user)
When the verdict is BLOCKED, list the blockers:
> **BLOCKED**: cannot merge
> - QA gate: *FAIL*, 3 test failures
> - Version strings: *mismatch* in `setup.py`
After presenting the final report, output the completion handoff:
> **Released**: PR `{url}`
> Merge when CI passes. Pipeline complete.
Delete `.rdf/work-output/ship-progress-${RDF_SESSION_ID}.md` after successful completion.
## Formatting Guide
All output from this workflow uses the markdown primitives below.
Follow these consistently across every stage.
| Primitive | Syntax | Use in this workflow |
|-----------|--------|----------------------|
| **Table** | `\| col \| col \|` | Ship report summary, PR metadata |
| **Task list** | `- [x]` / `- [ ]` | Preflight checks, gate results, release prep, CI status |
| **Blockquote** | `>` | Blockers, warnings, gate failures, version mismatches |
| **Bold** | `**text**` | Labels (PR, Branch, QA), verdict keywords |
| **Italic** | `*text*` | Status keywords (*PASS*, *FAIL*, *running*, *skipped*) |
| **Inline code** | `` `text` `` | Versions, hashes, branch names, paths, commands, counts |
| **Rule** | `---` | Section dividers in final report |
**Do NOT use** (not rendered in Claude Code):
HTML tags, `<details>`, ANSI color codes, Mermaid diagrams, footnotes.
**Conventions:**
- Task lists give instant pass/fail state: checked = passed,
unchecked = failed or pending
- Blockquotes draw the eye to blockers; use them for anything that
halts the workflow or needs user action
- Inline code makes values scannable; always wrap versions,
hashes, branch names, paths, and commands
- Bold labels on the left, values on the right, consistent
across task lists and tables
- Italic for status keywords only, to keep them visually distinct
from labels and values
## Constraints
- Never auto-merge; the user must confirm
- Never force-push
- Always show verification results before creating PR
- If governance/verification.md is missing, warn but proceed with
default checks (lint, test execution)
- Respect project commit protocol from governance/conventions.md