name: release-plannotator description: Prepare and execute a Plannotator release — draft release notes with full contributor credit, bump versions across all package files, build in dependency order, and kick off the tag-driven release pipeline. Use this skill whenever the user mentions preparing a release, bumping versions, writing release notes, tagging a release, or publishing. Also trigger when the user says things like "let's ship", "prep a release", "what's changed since last release", or "time to cut a new version".
Plannotator Release
The process has four phases. Phase 1 (release notes) is where most of the work happens — present the draft for review before proceeding to later phases.
Phase 1: Draft Release Notes
This is the most important phase. The release notes are the public face of each version and the primary way the community sees their contributions recognized.
Step 1: Determine scope
- Find the latest release tag:
git tag --sort=-v:refname | head -1 - Determine the new version number. Ask the user if unclear (patch, minor, or major).
- Gather all changes since the last tag:
git log --oneline <last-tag>..HEADfor commit historygit log --merges --oneline <last-tag>..HEADfor merged PRs
- For each PR, use
gh pr view <number> --json title,author,body,closedIssues,labelsto get details.
Step 2: Research contributors
This is critical. Every person who participated in the release gets credit — not just PR authors.
For each PR and linked issue, collect:
- PR authors — the person who wrote the code
- Issue reporters — who filed the bug or feature request
- Issue commenters — who participated in the discussion with useful context
- Discussion creators — who started relevant GitHub Discussions
- Feature requestors — check the linked "closes #N" issues and their authors
Use the GitHub API via gh:
# Get issue details including author
gh issue view <number> --json author,title,body
# Get issue comments to find participants
gh api repos/backnotprop/plannotator/issues/<number>/comments --jq '.[].user.login'
# Get PR review comments
gh api repos/backnotprop/plannotator/pulls/<number>/comments --jq '.[].user.login'
Step 3: Write the release notes
Read the reference release notes in references/ for the canonical template structure. These are real release notes from previous versions — match their tone, structure, and level of detail.
release-notes-v0.13.0.md— large release, 14 PRs, 3 first-time contributors, "New Contributors" + narrative "Contributors" sectionrelease-notes-v0.12.0.md— large community release, 14 PRs, 10 external, detailed narrative "Contributors" sectionrelease-notes-v0.13.1.md— small patch release, 2 PRs, no external authors, "Community" section focused on issue reporters
Pay attention to how each reference handles contributor crediting differently. Pick the pattern that fits the release's contributor profile — a release with many external PRs warrants a narrative "Contributors" section; a patch driven by issue reports uses a lighter "Community" section.
Write the file to the repo root as RELEASE_NOTES_v<VERSION>.md.
Structure
-
X/Twitter follow link — first line, always the same:
Follow [@plannotator](https://x.com/plannotator) on X for updates -
"Missed recent releases?" collapsible table — copy from the previous release's notes, then:
- Add the previous release (the one you're succeeding) as the newest row
- Keep roughly 10-12 rows; drop the oldest if needed
- Each row: version link + comma-separated feature highlights (short phrases)
-
"What's New in vX.Y.Z" — the heart of the notes
- Open with 1-3 sentences summarizing the release theme and scope. Mention how many PRs, how many from external contributors, any first-timers.
- Each major feature/fix gets its own
###subsection with:- A descriptive heading (not the PR title verbatim — rephrase for clarity)
- 1-4 paragraphs explaining what changed and why it matters. Be specific and concrete. Describe the problem that existed before, what the change does, and how users experience it.
- Credit line at the bottom: PR link, linked issues with
closing [#N], and contributor attribution
- Minor changes go under
### Additional Changesas bold-titled bullets
-
Install / Update — standard block, read from the previous release notes and reuse verbatim
-
"What's Changed" — bullet list of every PR in the release:
- feat: descriptive PR title by @author in [#N](url) -
"New Contributors" — if any first-time contributors:
- @username made their first contribution in [#N](url) -
"Contributors" or "Community" — narrative section recognizing everyone who participated:
- PR authors get a sentence about what they built
- Issue reporters and commenters get listed with what they reported/discussed
- Group community issue reporters in a bullet list at the end
-
Full Changelog link:
**Full Changelog**: https://github.com/backnotprop/plannotator/compare/<prev-tag>...<new-tag>
Writing guidelines
- Narrative over noise. Write in clear, readable prose. Not marketing-speak, not changelog-dump. Explain what changed and why someone should care, in plain language.
- Bullets where they help. Use bullet lists for enumerating discrete items (additional changes, contributor lists). Use paragraphs for explaining features.
- No cliches or buzzwords. Don't say "exciting", "game-changing", "seamless", "powerful". Just describe what happened.
- No punchlines. Don't end sections with a clever quip or a summary zinger. Let the feature speak for itself.
- Speak through practical benefit. Describe what changed and what it means for the user in concrete, reliable terms. Not aspirational, not hype — just what it does.
- Don't overuse em dashes. One or two per release is fine. If you notice them stacking up, restructure the sentence instead.
- Grammatical structure matters. Vary sentence structure. Active voice. Concrete subjects and verbs.
- Contributor tags. Use
@username— bare at-mentions, not markdown links like[@user](url). GitHub renders bare@mentionswith avatar icons in release notes. This is important for community recognition. - Every contributor counts. Everyone who filed an issue, left a comment that shaped a decision, or participated in a discussion gets mentioned. This project's community is its lifeblood.
Step 4: Present for review
Write the draft to RELEASE_NOTES_v<VERSION>.md in the repo root and tell the user it's ready for review. Do not git add or commit this file — release notes are kept untracked by design. Wait for their feedback before proceeding to Phase 2.
Phase 2: Version Bump
Bump the version string in these 7 files (and only these — other package.json files use stub versions):
| File | Field |
|---|---|
package.json (root) | "version" |
apps/opencode-plugin/package.json | "version" |
apps/pi-extension/package.json | "version" |
apps/hook/.claude-plugin/plugin.json | "version" |
apps/copilot/plugin.json | "version" |
openpackage.yml (root) | version: |
packages/server/package.json | "version" |
Read each file, confirm the current version matches expectations, then update all 7 atomically.
Do not bump the VS Code extension (apps/vscode-extension/package.json) — it has independent versioning.
Phase 3: Build
Run builds in dependency order:
bun run build:review # 1. Code review editor (standalone Vite build)
bun run build:hook # 2. Plan review + hook server (copies review's built HTML into hook dist)
bun run build:opencode # 3. OpenCode plugin (copies built HTML from hook + review)
bun run build:pi # 4. Pi extension (chains review → hook → pi internally, safe to run after 1-2)
build:pi chains review and hook internally, so after steps 1-2 it only runs the pi-specific build.
Verify all builds succeed before proceeding.
Pi Parity Gate
After builds pass, audit the Pi extension to ensure all server-side imports resolve in the published package. This catches missing files before they reach npm.
-
Check imports vs
filesarray. Trace all local imports (starting with./or../) fromindex.ts,server.ts,tool-scope.ts, and every file inserver/. Verify each target is covered by a pattern in thefilesarray ofapps/pi-extension/package.json. -
Check
vendor.shcovers all shared/ai imports. Every../generated/*.jsimport in the server files must have a corresponding entry invendor.sh's copy loops. If a new shared module or AI module was added topackages/shared/orpackages/ai/and is imported by Pi's server code, it must be added tovendor.sh. -
Dry-run the pack. Run
cd apps/pi-extension && bun pm pack --dry-runand verify the output includes every file the server imports. Look specifically for any newly added files since the last release. -
Quick smoke test. Confirm
generated/contains all expected files after build, especially any new ones (e.g., a new shared module added in this release cycle).
If anything is missing, fix it before proceeding to Phase 4. Common fixes:
- Add the file to
vendor.sh's copy loop - Add the file or directory to the
filesarray inpackage.json - Add an import path fix (Pi uses
../generated/not@plannotator/sharedor@plannotator/ai)
Phase 4: Commit, Tag, and Release
-
Commit the version bump:
chore: bump version to X.Y.ZStage only the 7 version-bumped files. Do not stage the release notes file (it's untracked by design).
-
Create and push the tag:
git tag vX.Y.Z git push origin main git push origin vX.Y.ZThe
v*tag push triggers the release pipeline (.github/workflows/release.yml). -
The pipeline handles everything else:
- Runs tests
- Cross-compiles binaries for 6 platforms (macOS ARM64/x64, Linux x64/ARM64, Windows x64/ARM64)
- Compiles paste service binaries (same 6 platforms)
- Generates SLSA build provenance attestations for all 12 binaries via
actions/attest-build-provenance(signed through Sigstore, recorded in Rekor) - Creates the GitHub Release with all binaries attached
- Publishes
@plannotator/opencodeand@plannotator/pi-extensionto npm with provenance
Note on immutable releases: The repo has GitHub Immutable Releases enabled, so once the
v*tag is pushed and the release is created, the tag→commit and tag→asset bindings are permanent. You cannot delete and re-create a tag to "fix" a bad release — you must ship a new version. Release notes remain editable (see step 5), but everything else is locked. -
Monitor the pipeline: Watch the release workflow run until it completes:
gh run list --workflow=release.yml --limit=1 gh run view <run-id> --logVerify:
- All jobs pass (test, build, release, npm-publish)
- The GitHub Release was created with all binary artifacts
- npm packages published successfully (check with
npm view @plannotator/opencode versionandnpm view @plannotator/pi-extension version)
If anything fails, investigate the logs and report to the user before retrying.
-
Replace the release notes: Once the release is live and verified, replace the auto-generated notes body with the drafted release notes:
gh release edit vX.Y.Z --notes-file RELEASE_NOTES_v<VERSION>.md
Checklist
Before tagging, verify:
- All 7 version files bumped consistently
- Release notes drafted and reviewed
-
bun run build:reviewsucceeded -
bun run build:hooksucceeded -
bun run build:opencodesucceeded -
bun run build:pisucceeded (or pi-specific build step) - Version bump committed
- Pi parity gate passed (imports, vendor.sh, dry-run pack)
- No stale build artifacts (clean builds, no cache issues — run
bun installfirst if dependencies changed)
After tagging, verify:
- Release workflow completed (all 4 jobs green)
- GitHub Release created with all binaries
- npm packages published at correct version
- Release notes replaced via
gh release edit