---
name: release
description: >-
  GitHub release creation for cc-foundry plugins: per-plugin tags, release notes as the changelog, and post-merge
  publishing. Invoke whenever task involves merging a pull request into master, releasing or publishing a plugin
  version, bumping plugin versions, or writing release notes.
---

# Plugin Releases

Every plugin version bump that lands on master ships with a GitHub release. The release notes are the plugin's changelog
— there are no CHANGELOG.md files (see [ADR 1.5](/design-docs/adr/1.5-plugin-changelog.md)). A merged version bump
without a release is an incomplete ship.

## Before the Push

Run `vp run cli check --pre-push` and push only when it reports no error. It fails on a plugin whose shipped files
changed since `origin/master` while its version did not — a change that never reaches an install, because Claude Code
keys its plugin cache on the version.

## When to Release

- After every merge into master, check the merged range for plugin version bumps; create one release per plugin whose
  version changed.
- The user's authorization to merge covers release creation — do not ask a second time.
- Repo-level changes that bump no plugin version (ADRs, root docs, the dev CLI in `src/`, CI, this skill) get no
  release.
- Several plugins bumped in one merge → one release each.

## Identify What to Release

1. Find bumped plugins in the merged range: `git diff <old-origin-head>..origin/master -- '*/plugin.json'`. When the old
   head is unknown, compare each plugin's `plugin.json` version against its latest `<plugin>-v*` tag from
   `gh release list`.
2. For each bumped plugin, resolve:
   - the commit on master that changed its `plugin.json` version — the release target
   - the previous release tag `<plugin>-v*`, if any — the notes range and compare-link anchor
3. Collect source material: `git log <prev-tag>..<target> -- plugins/<name>/` plus the diff of that range. For a first
   release, use the commits of the bump itself.

## Tag and Title Scheme

- **Tag** — `<plugin>-v<X.Y.Z>`, e.g. `the-coder-v1.5.0`
- **Title** — `<plugin> v<X.Y.Z>`, e.g. `the-coder v1.5.0`
- **Target** — the commit on master that landed the version bump, as its **full 40-character SHA**. GitHub rejects an
  abbreviated SHA with `HTTP 422 Validation Failed` and the misleading trio `tag_name is not a valid tag`,
  `Release.target_commitish is invalid`, `Published releases must have a valid tag`. A rebase-merged pull request gives
  every commit a new SHA, so take the target from `origin/master` after the merge, never from the branch. Resolve it
  with `git rev-parse <short-sha>`; a branch name also works.
- Never run `git tag` — `gh release create` creates the tag on the remote at publish time.

## Release Notes

Written for people who install the plugin, not for repo contributors.

<prerequisite>
Invoke `the-writer:humanize` before drafting. All release prose — the lead sentence and every bullet — is written in
its writing mode and passes its self-audit before `gh release create`. If the skill is unavailable, ask the user to
install the `the-writer` plugin before proceeding.
</prerequisite>

- Lead with one sentence stating what the release is about.
- Segment by changed component, one `###` section per component: ``### `<name>` skill``, ``### `<name>` output style`` —
  same pattern for hooks, commands, and agents. A plugin bumps its version even when a single component moved; the
  segments tell the installer exactly which parts did.
- Plugin-wide changes that belong to no component (README, packaging, licensing) go under a final `### Plugin` section.
- Within a segment, prefix each bullet with its change type in bold — `**Added:**`, `**Changed:**`, `**Fixed:**`,
  `**Removed:**` — ordered Added → Changed → Fixed → Removed.
- Each bullet states the change and, where not obvious, why it matters to a plugin user.
- Distill from commit messages and the diff. Never paste a commit list, shortlog, or auto-generated notes.
- No session artifacts (test counts, CI status) and no repo-internal jargon that means nothing to an installer.
- End with a compare link when a previous tag exists:
  `**Full diff:** https://github.com/xobotyi/cc-foundry/compare/<prev-tag>...<new-tag>`
- First release of a plugin: no compare link; notes cover this version's changes only, not the plugin's history.

### Example

```markdown
Sharpens commit-message validation and adds trailer support.

### `commit-message` skill

- **Added:** `Task:` and `Refs:` trailer validation — malformed trailers now fail validation instead of landing
  silently.
- **Changed:** subject-length limit aligned with git conventions: 50 soft / 72 hard (was a flat 72).

### `commit` skill

- **Fixed:** validator crashed on commit messages containing unescaped backticks.

**Full diff:** https://github.com/xobotyi/cc-foundry/compare/git-commit-v1.1.3...git-commit-v1.1.4
```

## Create the Release

Write the notes to a scratchpad file first — `--notes-file` avoids shell-quoting damage:

```bash
gh release create <plugin>-v<X.Y.Z> \
  --target <bump-commit-sha> \
  --title "<plugin> v<X.Y.Z>" \
  --notes-file <path-to-notes.md>
```

- To stage a release for user review, add `--draft` (visible to collaborators only; the tag is created at publish, not
  at draft creation). Publish with `gh release edit <tag> --draft=false` — re-set `--target` to the bump commit first if
  the draft was created before the merge.

## Verify

- `gh release view <tag>` — confirm title, target, and notes.
- Cross-check: every plugin bumped in the merged range has a release; `plugin.json` version equals the latest tag.
