Skip to content

Commit 9c256ad

Browse files
committed
chore: track the release maintainer skill in git
- add !.claude/skills/release/ gitignore exception - version-control the prospec release runbook (bump → tag → notes format)
1 parent bb511f3 commit 9c256ad

2 files changed

Lines changed: 179 additions & 1 deletion

File tree

.claude/skills/release/SKILL.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ Thumbs.db
3232
# Task scratch (per-branch todo / lessons)
3333
.tasks/
3434

35-
# Agents — track only prospec-* skills, ignore the rest.
35+
# Agents — track prospec-* skills + the release maintainer skill; ignore the rest.
3636
.claude/*
3737
!.claude/skills/
3838
.claude/skills/*
3939
!.claude/skills/prospec-*
40+
!.claude/skills/release/
4041
.agents/*
4142
!.agents/skills/
4243
.agents/skills/*

0 commit comments

Comments
 (0)