2026-03-05 11:23:58 -06:00
---
name: release
description: >
2026-03-09 08:49:42 -05:00
Coordinate a full Paperclip release across engineering verification, npm,
GitHub, website publishing, and announcement follow-up. Use when leadership
asks to ship a release, not merely to discuss version bumps.
2026-03-05 11:23:58 -06:00
---
# Release Coordination Skill
2026-03-09 08:49:42 -05:00
Run the full Paperclip release as a maintainer workflow, not just an npm publish.
2026-03-05 11:23:58 -06:00
This skill coordinates:
2026-03-09 08:49:42 -05:00
- stable changelog drafting via `release-changelog`
2026-03-09 13:55:30 -05:00
- release-train setup via `scripts/release-start.sh`
2026-03-09 08:49:42 -05:00
- prerelease canary publishing via `scripts/release.sh --canary`
- Docker smoke testing via `scripts/docker-onboard-smoke.sh`
- stable publishing via `scripts/release.sh`
2026-03-09 13:55:30 -05:00
- pushing the stable branch commit and tag
2026-03-09 08:49:42 -05:00
- GitHub Release creation via `scripts/create-github-release.sh`
- website / announcement follow-up tasks
2026-03-05 11:23:58 -06:00
## Trigger
Use this skill when leadership asks for:
2026-03-09 08:49:42 -05:00
2026-03-05 11:23:58 -06:00
- "do a release"
2026-03-09 08:49:42 -05:00
- "ship the next patch/minor/major"
2026-03-05 11:23:58 -06:00
- "release vX.Y.Z"
## Preconditions
Before proceeding, verify all of the following:
1. `skills/release-changelog/SKILL.md` exists and is usable.
2026-03-09 08:49:42 -05:00
2. The repo working tree is clean, including untracked files.
3. There are commits since the last stable tag.
4. The release SHA has passed the verification gate or is about to.
2026-03-09 13:55:30 -05:00
5. If package manifests changed, the CI-owned `pnpm-lock.yaml` refresh is already merged on `master` before the release branch is cut.
2026-03-09 10:43:04 -05:00
6. npm publish rights are available locally, or the GitHub release workflow is being used with trusted publishing.
7. If running through Paperclip, you have issue context for status updates and follow-up task creation.
2026-03-05 11:23:58 -06:00
If any precondition fails, stop and report the blocker.
## Inputs
Collect these inputs up front:
2026-03-09 08:49:42 -05:00
- requested bump: `patch` , `minor` , or `major`
- whether this run is a dry run or live release
- whether the release is being run locally or from GitHub Actions
- release issue / company context for website and announcement follow-up
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
## Step 0 — Release Model
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
Paperclip now uses this release model:
2026-03-05 11:38:09 -06:00
2026-03-09 13:55:30 -05:00
1. Start or resume `release/X.Y.Z`
2. Draft the **stable** changelog as `releases/vX.Y.Z.md`
3. Publish one or more **prerelease canaries** such as `X.Y.Z-canary.0`
4. Smoke test the canary via Docker
5. Publish the stable version `X.Y.Z`
6. Push the stable branch commit and tag
7. Create the GitHub Release
8. Merge `release/X.Y.Z` back to `master` without squash or rebase
9. Complete website and announcement surfaces
2026-03-05 11:38:09 -06:00
2026-03-09 08:49:42 -05:00
Critical consequence:
2026-03-05 11:38:09 -06:00
2026-03-09 08:49:42 -05:00
- Canaries do **not** use promote-by-dist-tag anymore.
- The changelog remains stable-only. Do not create `releases/vX.Y.Z-canary.N.md` .
2026-03-05 11:38:09 -06:00
2026-03-09 08:49:42 -05:00
## Step 1 — Decide the Stable Version
2026-03-05 11:38:09 -06:00
2026-03-09 13:55:30 -05:00
Start the release train first:
```bash
./scripts/release-start.sh {patch|minor|major}
```
Then run release preflight:
2026-03-09 09:06:45 -05:00
```bash
./scripts/release-preflight.sh canary {patch|minor|major}
# or
./scripts/release-preflight.sh stable {patch|minor|major}
```
Then use the last stable tag as the base:
2026-03-05 11:23:58 -06:00
```bash
2026-03-09 08:49:42 -05:00
LAST_TAG=$(git tag --list 'v*' --sort=-version:refname | head -1)
git log "${LAST_TAG}..HEAD" --oneline --no-merges
2026-03-05 11:23:58 -06:00
git diff --name-only "${LAST_TAG}..HEAD" -- packages/db/src/migrations/
git diff "${LAST_TAG}..HEAD" -- packages/db/src/schema/
git log "${LAST_TAG}..HEAD" --format="%s" | rg -n 'BREAKING CHANGE|BREAKING:|^[a-z]+!:' || true
```
Bump policy:
2026-03-09 08:49:42 -05:00
- destructive migrations, removed APIs, breaking config changes -> `major`
- additive migrations or clearly user-visible features -> at least `minor`
- fixes only -> `patch`
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
If the requested bump is too low, escalate it and explain why.
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
## Step 2 — Draft the Stable Changelog
2026-03-05 11:38:09 -06:00
2026-03-09 08:49:42 -05:00
Invoke `release-changelog` and generate:
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
- `releases/vX.Y.Z.md`
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
Rules:
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
- review the draft with a human before publish
- preserve manual edits if the file already exists
- keep the heading and filename stable-only, for example `v1.2.3`
- do not create a separate canary changelog file
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
## Step 3 — Verify the Release SHA
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
Run the standard gate:
2026-03-05 11:38:09 -06:00
```bash
2026-03-09 08:49:42 -05:00
pnpm -r typecheck
pnpm test:run
pnpm build
2026-03-05 11:38:09 -06:00
```
2026-03-09 08:49:42 -05:00
If the release will be run through GitHub Actions, the workflow can rerun this gate. Still report whether the local tree currently passes.
2026-03-05 11:38:09 -06:00
2026-03-09 10:43:04 -05:00
The GitHub Actions release workflow installs with `pnpm install --frozen-lockfile` . Treat that as a release invariant, not a nuisance: if manifests changed and the lockfile refresh PR has not landed yet, stop and wait for `master` to contain the committed lockfile before shipping.
2026-03-09 08:49:42 -05:00
## Step 4 — Publish a Canary
2026-03-05 15:57:23 -06:00
2026-03-09 13:55:30 -05:00
Run from the `release/X.Y.Z` branch:
2026-03-05 11:23:58 -06:00
```bash
2026-03-05 15:57:23 -06:00
./scripts/release.sh {patch|minor|major} --canary --dry-run
./scripts/release.sh {patch|minor|major} --canary
2026-03-05 11:23:58 -06:00
```
2026-03-09 08:49:42 -05:00
What this means:
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
- npm receives `X.Y.Z-canary.N` under dist-tag `canary`
- `latest` remains unchanged
- no git tag is created
- the script cleans the working tree afterward
2026-03-09 09:06:45 -05:00
Guard:
- if the current stable is `0.2.7` , the next patch canary is `0.2.8-canary.0`
- the tooling must never publish `0.2.7-canary.N` after `0.2.7` is already stable
2026-03-09 08:49:42 -05:00
After publish, verify:
2026-03-05 15:57:23 -06:00
```bash
npm view paperclipai@canary version
```
2026-03-09 08:49:42 -05:00
The user install path is:
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
```bash
npx paperclipai@canary onboard
```
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
## Step 5 — Smoke Test the Canary
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
Run:
2026-03-05 11:23:58 -06:00
```bash
2026-03-05 15:57:23 -06:00
PAPERCLIPAI_VERSION=canary ./scripts/docker-onboard-smoke.sh
2026-03-05 11:23:58 -06:00
```
2026-03-09 08:49:42 -05:00
Confirm:
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
1. install succeeds
2. onboarding completes
3. server boots
4. UI loads
5. basic company/dashboard flow works
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
If smoke testing fails:
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
- stop the stable release
- fix the issue
- publish another canary
- repeat the smoke test
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
Each retry should create a higher canary ordinal, while the stable target version can stay the same.
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
## Step 6 — Publish Stable
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
Once the SHA is vetted, run:
2026-03-05 15:57:23 -06:00
```bash
2026-03-09 08:49:42 -05:00
./scripts/release.sh {patch|minor|major} --dry-run
./scripts/release.sh {patch|minor|major}
2026-03-05 15:57:23 -06:00
```
2026-03-09 08:49:42 -05:00
Stable publish does this:
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
- publishes `X.Y.Z` to npm under `latest`
- creates the local release commit
- creates the local git tag `vX.Y.Z`
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
Stable publish does **not** push the release for you.
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
## Step 7 — Push and Create GitHub Release
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
After stable publish succeeds:
2026-03-05 15:57:23 -06:00
```bash
2026-03-09 13:55:30 -05:00
git push public-gh HEAD --follow-tags
2026-03-09 08:49:42 -05:00
./scripts/create-github-release.sh X.Y.Z
2026-03-05 15:57:23 -06:00
```
2026-03-09 08:49:42 -05:00
Use the stable changelog file as the GitHub Release notes source.
2026-03-05 15:57:23 -06:00
2026-03-09 13:55:30 -05:00
Then open the PR from `release/X.Y.Z` back to `master` and merge without squash or rebase.
2026-03-09 08:49:42 -05:00
## Step 8 — Finish the Other Surfaces
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
Create or verify follow-up work for:
2026-03-05 11:38:09 -06:00
2026-03-09 08:49:42 -05:00
- website changelog publishing
- launch post / social announcement
- any release summary in Paperclip issue context
2026-03-05 11:38:09 -06:00
2026-03-09 08:49:42 -05:00
These should reference the stable release, not the canary.
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
## Failure Handling
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
If the canary is bad:
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
- publish another canary, do not ship stable
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
If stable npm publish succeeds but push or GitHub release creation fails:
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
- fix the git/GitHub issue immediately from the same checkout
- do not republish the same version
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
If `latest` is bad after stable publish:
2026-03-05 15:57:23 -06:00
2026-03-09 08:49:42 -05:00
```bash
./scripts/rollback-latest.sh < last-good-version >
2026-03-05 15:57:23 -06:00
```
2026-03-09 08:49:42 -05:00
Then fix forward with a new patch release.
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
## Output
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
When the skill completes, provide:
2026-03-05 11:23:58 -06:00
2026-03-09 08:49:42 -05:00
- stable version and, if relevant, the final canary version tested
- verification status
- npm status
- git tag / GitHub Release status
- website / announcement follow-up status
- rollback recommendation if anything is still partially complete