|
| 1 | +--- |
| 2 | +name: release |
| 3 | +description: "Cut a prospec GitHub release — bump version strings, tag, and publish release notes in the established format so the Release Binaries workflow attaches multi-platform binaries. Triggers: release, publish release, cut a release, ship a version, 發布, 發佈, 出版本, 發版, 版本發布, 發布 release" |
| 4 | +--- |
| 5 | + |
| 6 | +# Release Skill |
| 7 | + |
| 8 | +Cut a new prospec release from `main`: bump the version strings, create the tag, and publish |
| 9 | +GitHub release notes in the house format. Publishing the release (`published` event) triggers |
| 10 | +`.github/workflows/release.yml`, which compiles the multi-platform standalone binaries and attaches |
| 11 | +them as compressed assets — so this skill's job is the version bump + notes, not the build. |
| 12 | + |
| 13 | +## Language |
| 14 | + |
| 15 | +The release notes, commit message, and everything this skill writes are in **English** — a release |
| 16 | +is trust-zone / public-facing technical output, exempt from the Traditional Chinese change-artifact |
| 17 | +rule (see project `CLAUDE.md`). Talk to the user in their language; write the artifacts in English. |
| 18 | + |
| 19 | +## Preconditions — do not release until all hold |
| 20 | + |
| 21 | +1. **All PRs for this version are merged to `main`** and `main` is checked out with a clean tree |
| 22 | + (`git status`). A release is cut from `main`, never a feature branch. |
| 23 | +2. **Each change is archived** (`/prospec-archive`) — REQs graduated, Knowledge synced, summary |
| 24 | + written. The release notes' Dogfood section reports this; it must already be true. |
| 25 | +3. **Counts are already synced.** `pnpm counts` runs as the last step of each *feature* commit, not |
| 26 | + here — READMEs / `index.md` / module READMEs already carry the right test/skill counts. Do not |
| 27 | + run `pnpm counts` during the bump. (See memory: counts are generated by `sync-counts.ts`.) |
| 28 | +4. **Green locally**: `pnpm test`, `pnpm typecheck`, `pnpm lint`, and `prospec check` (11 drift |
| 29 | + checks). Capture the numbers — they feed the "Quality & tests" section. Coverage: `coverage/` |
| 30 | + on disk may be stale (predates the current version); re-run `pnpm test:coverage` for a live |
| 31 | + figure. Read `prospec check` WARNs by type, not as one bucket: |
| 32 | + - **`knowledge-health` (stale module README)** — almost always a prior change's archive that |
| 33 | + changed a module's source but never touched its README (drift compares git commit times). |
| 34 | + **Fix it before releasing**: sync + commit that module README so the notes can honestly claim |
| 35 | + a green check. Then confirm the fix didn't tip **`knowledge-size`** over the 1000-token L2 |
| 36 | + budget — if it did, trim the README back under budget (net-neutral) rather than accept a new |
| 37 | + WARN. |
| 38 | + - **`knowledge-size` budget WARN** that pre-exists and is deliberate (the SC-002 signal) may be |
| 39 | + reported as such, mirroring how 0.5.2 framed it — do not thrash the README to chase it away. |
| 40 | + |
| 41 | +If a check FAILs, stop and resolve it — never paper over it in the notes. |
| 42 | + |
| 43 | +## Version & tag conventions |
| 44 | + |
| 45 | +- **SemVer.** Pick `X.Y.Z` from the scope since the last tag: new user-visible capability → minor; |
| 46 | + bug-fix / hardening / CI-only → patch. Confirm the number with the user before tagging. |
| 47 | +- **Tag = bare `X.Y.Z`** (no `v` prefix — the `v` was dropped at 0.5.0). Lightweight tag, created |
| 48 | + by `gh release create` at `main` HEAD (the bump commit). |
| 49 | +- **Release title** carries no `v` either (also dropped at 0.5.0): `X.Y.Z — Headline: subtitle`. |
| 50 | + |
| 51 | +## Step-by-step |
| 52 | + |
| 53 | +### 1. Gather the source material |
| 54 | + |
| 55 | +```bash |
| 56 | +LAST=$(git describe --tags --abbrev=0) # previous release tag, e.g. 0.5.2 |
| 57 | +git log --oneline "$LAST"..HEAD # what shipped |
| 58 | +git diff --shortstat "$LAST"..HEAD # "N files changed, +A, -B" for the stat line |
| 59 | +gh pr list --state merged --base main --limit 20 # PR numbers + titles since $LAST |
| 60 | +gh release view "$LAST" --json body # the canonical format to mirror |
| 61 | +``` |
| 62 | + |
| 63 | +Note the merged PR numbers and the previous version's test count (from that release's notes or the |
| 64 | +current `README.md`) — the notes report the delta. |
| 65 | + |
| 66 | +### 2. Bump the version strings (manual, no script exists) |
| 67 | + |
| 68 | +> If a `chore: bump version to X.Y.Z` commit is already on `main` (the bump often lands ahead of |
| 69 | +> running this skill), just confirm the strings below are correct and skip to step 5. Any release |
| 70 | +> commit you add afterwards (e.g. a Knowledge sync from step 4) becomes the tag target — that is |
| 71 | +> fine; the tag only needs to point at a tree carrying the right version. |
| 72 | +
|
| 73 | +Edit these three files, replacing the old version everywhere it appears: |
| 74 | + |
| 75 | +- `package.json` → `"version": "X.Y.Z"` |
| 76 | +- `.prospec.yaml` → `version: X.Y.Z` |
| 77 | +- `docs/index.html` → **two** spots: `"softwareVersion":"X.Y.Z"` (bare) **and** the nav brand |
| 78 | + `<span class="ver">vX.Y.Z</span>` (with `v`). If the release date differs, also update |
| 79 | + `"dateModified":"YYYY-MM-DD"` in the same block. |
| 80 | + |
| 81 | +Verify nothing was missed: `grep -rn "$LAST" package.json .prospec.yaml docs/index.html` should |
| 82 | +return no stale matches. |
| 83 | + |
| 84 | +### 3. Commit the bump |
| 85 | + |
| 86 | +```bash |
| 87 | +git commit -am "chore: bump version to X.Y.Z" |
| 88 | +``` |
| 89 | + |
| 90 | +Commit-message rules (project Constitution + memory): **bulleted body if any body is needed, no |
| 91 | +prose paragraphs; never add `Co-Authored-By` / AI attribution** (P2). The bump commit is typically |
| 92 | +body-less — the subject line suffices. |
| 93 | + |
| 94 | +### 4. Push `main` |
| 95 | + |
| 96 | +```bash |
| 97 | +git push origin main |
| 98 | +``` |
| 99 | + |
| 100 | +### 5. Draft the release notes |
| 101 | + |
| 102 | +Write to a scratch file (git-ignored), e.g. `.tasks/<branch>/release-notes-X.Y.Z.md`, following the |
| 103 | +template below. **The file's entire contents ARE the release description, verbatim** — it is fed to |
| 104 | +`--notes-file` as-is. So it must contain only the body (first line `# Prospec X.Y.Z`, then the |
| 105 | +notes). Do **not** add worksheet scaffolding — no `# Release Notes X.Y.Z`, no `## Release Title`, no |
| 106 | +`## Release Body`, no fenced title block; the title is a separate `--title` argument, never repeated |
| 107 | +in the body. Show the draft to the user and get sign-off before publishing — the notes are public |
| 108 | +and hard to un-see. |
| 109 | + |
| 110 | +### 6. Publish (this builds & attaches the binaries) |
| 111 | + |
| 112 | +```bash |
| 113 | +gh release create X.Y.Z \ |
| 114 | + --title "X.Y.Z — Headline: subtitle" \ |
| 115 | + --notes-file .tasks/<branch>/release-notes-X.Y.Z.md |
| 116 | +``` |
| 117 | + |
| 118 | +`gh release create` creates the lightweight tag at HEAD and fires the `published` event → |
| 119 | +`release.yml` compiles `bun` binaries for linux-x64 / macos-arm64 / macos-x64 / windows-x64, |
| 120 | +packages them (`.tar.gz` / `.zip`), and uploads them to the release. |
| 121 | + |
| 122 | +### 7. Verify the release landed |
| 123 | + |
| 124 | +```bash |
| 125 | +gh run list --workflow=release.yml --limit 1 # watch it go green |
| 126 | +gh release view X.Y.Z # 4 archive assets attached, notes render |
| 127 | +``` |
| 128 | + |
| 129 | +Confirm the workflow succeeded and all four platform archives are attached. Report the release URL. |
| 130 | + |
| 131 | +## Release-notes format |
| 132 | + |
| 133 | +Mirror the last two releases exactly (`gh release view <LAST>` is the living reference). Structure: |
| 134 | + |
| 135 | +**Title** — one line, no `v`, passed only via `--title` (never inside the body): |
| 136 | +``` |
| 137 | +X.Y.Z — <Headline Name>: <2–4 comma/colon-joined themes> |
| 138 | +``` |
| 139 | + |
| 140 | +**Body** (Markdown) = the literal `--notes-file` contents, sections in this order — omit a section |
| 141 | +only when it genuinely has no content: |
| 142 | + |
| 143 | +0. **`# Prospec X.Y.Z`** — the body's first line, an H1 (matches every prior release). Nothing |
| 144 | + precedes it; no worksheet labels wrap the notes (see step 5). |
| 145 | +1. **Lead paragraph** — one paragraph directly under the H1: `X.Y.Z is a <correctness / optimization |
| 146 | + / feature / …> release that <what it does and why it matters>.` |
| 147 | +2. **Stat line** — one line, right after the lead: |
| 148 | + `N files changed · +A / −B · M merged PRs ([#n](https://github.com/benwu95/prospec/pull/n), …)` |
| 149 | + append `+ CI maintenance` when applicable. Use the numbers from step 1. |
| 150 | +3. `---` |
| 151 | +4. `## ✨ Headline feature` (or `features`) — one `### <Feature Name> (PR [#n](…))` block per major |
| 152 | + item; prose first, then bullets for enumerable specifics (forms, flags, sources of truth). |
| 153 | +5. `## 🐛 Bug fixes` — bulleted; each starts with a **bold** one-line symptom, then the mechanism |
| 154 | + and the fix. (Only if the release fixes bugs.) |
| 155 | +6. `## 🔧 CI maintenance` — pinned-action bumps, workflow tweaks. (Only if applicable.) |
| 156 | +7. `## 🔁 Dogfood` — how the change was driven through prospec's own SDD loop |
| 157 | + (`story → plan → tasks → implement → review → verify grade <S/A> → archive`), plus which REQs |
| 158 | + graduated into which Knowledge modules. |
| 159 | +8. `## 🧪 Quality & tests` — bulleted: **N tests passing (F files)** up from the prev count and what |
| 160 | + was added; **~XX.X% line coverage**; drift-check status (`prospec check`: pass/skip counts, note |
| 161 | + any deliberate WARN); zero typecheck/lint warnings. |
| 162 | +9. `## 📊 Compared to <LAST>` — a table `| Comparison | <LAST> | X.Y.Z |` with one row per changed |
| 163 | + dimension; **bold** the new-version cell; last row is usually **Passing tests**. |
| 164 | +10. `## ⬆️ Upgrade notes` — numbered downstream steps: re-run the installer (`install.sh` / |
| 165 | + `install.ps1`, which pull `releases/latest`), run `prospec check`, plus any migration caveats |
| 166 | + (state "no config change required" when true). |
| 167 | + |
| 168 | +Keep the emoji headers consistent: `✨ 🐛 🔧 🔁 🧪 📊 ⬆️`. Every claim (counts, coverage, PR |
| 169 | +numbers, file stats) must be real — derive them in step 1, never invent. |
| 170 | + |
| 171 | +## Notes |
| 172 | + |
| 173 | +- **This is maintainer tooling for the prospec repo itself**, not a prospec SDD skill shipped to |
| 174 | + users. It has no `.hbs` template and is not produced by `prospec agent sync`. |
| 175 | +- It lives under `.claude/skills/` and is version-controlled via an explicit |
| 176 | + `!.claude/skills/release/` exception in `.gitignore` (the repo otherwise tracks only |
| 177 | + `.claude/skills/prospec-*`). It has no `.agents/` mirror — it is a Claude Code skill only. |
0 commit comments