Skip to content
Back to skills

R Ship

ASecurity

Use when a plan is built and verified and you want to cut a release: preflight, verification, release prep, and publish.

  • 20 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
developmentrustgobashgitsecurity

Works with

  • claude code
  • cli

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add rfxn/rdf --skill r-ship --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of R Ship?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for R Ship
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rfxn-r-ship/badge)](https://www.skillsdirectory.com/skills/rfxn-r-ship)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.