Skip to content

Commit 2fc1482

Browse files
committed
fix(release): emit release notes as short bullets, not prose
Release notes were reviewed as too much text in too blocky a form, with a top paragraph reading like marketing. Two generators write docs/releases/<tag>.mdx and they disagreed with each other: the gaia-release skill's "Generation parameters" told the model GAIA's notes "read dry" and to make them "engaging", while the release-notes job in claude.yml asked for "comprehensive" notes with an Overview paragraph and emoji headings. Fixing one alone would have been undone by the other on the next tag. Both now share one spec: at most one summary sentence, short bullets grouped by section, and a word cap on the narrative part (350 patch / 600 minor-major). The cap deliberately excludes Bug Fixes, Known Issues, Contributors, and the changelog -- those are reference lists sized by how many fixes actually shipped, so capping them would hide work rather than tighten writing. Tone guidance is no longer restated in the skill; it points at CLAUDE.md's How You Communicate, per that file's own link-here-never-restate rule. Regenerating the last two releases under the new template cuts the narrative from 1705 to 538 words (v0.22.0) and 1119 to 280 (v0.23.0), with every PR link, contributor credit, and changelog entry preserved. Both samples still pass util/validate_release_notes.py unmodified. Closes #2961
1 parent e0d7f30 commit 2fc1482

3 files changed

Lines changed: 107 additions & 79 deletions

File tree

.claude/skills/gaia-release/SKILL.md

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ These map to [CLAUDE.md](../../../CLAUDE.md). Re-read them whenever this skill r
5454
- **Plain language first, in every artifact** — the release notes, PR body, Discord post, and your own between-phase status updates all follow [CLAUDE.md → How You Communicate](../../../CLAUDE.md#how-you-communicate): lead with what a user can now do, layer version numbers, SHAs, and pipeline mechanics underneath. Say each point once — don't restate a highlight in the changelog and again in the announcement.
5555
- **No Claude attribution anywhere** — not in PR titles, PR bodies, commit messages (no `Co-Authored-By: Claude ...` trailer), release notes, code comments, or the Discord announcement.
5656
- **No silent fallbacks** — if a validator fails, a step times out, or a workflow run isn't found, stop with an actionable error. Do not retry blindly. Do not "proceed anyway."
57-
- **Match house style for release notes** — see *Generation parameters* in Phase 1. In short: value-prop first, **local agents are the headline** (not the SDK), one agent/command per highlight, plain language, engaging but factual, and **no emoji, no fluff** (full banned-phrase list under *Generation parameters*). Read the **last 2–3 release notes** before drafting. Patch releases do **not** include a `pip install` block. Use the `Why upgrade:` framing with a short bullet list, then `## What's New`, then `## Bug Fixes`, then `## Full Changelog`.
57+
- **Release notes are bulleted, plain, and short** — see *Notes format* in Phase 1. Every entry is one bullet, never a prose block; no narrative overview paragraph; no emoji; a hard word budget that is checked, not eyeballed. Sections in order: `## Breaking Changes` (only if any), `## What's New`, `## Bug Fixes`, `## Known Issues` (only if any), `## Contributors`, `## Full Changelog`. Patch releases do **not** include a `pip install` block.
5858
- **Match the previous release PR body shape exactly** — read the most recent merged `Release vX.Y.Z` PR (e.g. `gh pr list --repo amd/gaia --state merged --search "Release v in:title" --limit 3`). Open with `# GAIA vX.Y.Z Release Notes` (no MDX frontmatter in the PR body), end with a `Release checklist` section. Style drift here costs review cycles.
5959
- **Bulletproof commits only** — every change made by this skill must satisfy the four criteria in CLAUDE.md (validated, critiqued, scope-clean, no half-finished work) before being committed.
6060
- **Pushing tags is irreversible.** Always confirm the SHA the tag will point to and the green status of the pre-tag verification run before `git push origin v<version>`.
@@ -91,48 +91,43 @@ These map to [CLAUDE.md](../../../CLAUDE.md). Re-read them whenever this skill r
9191

9292
If the requested version doesn't match the rubric, **stop and surface the mismatch**: *"You asked for `v<requested>` (patch). I see N feat commits since `<prev>` including `<one or two examples>` — this looks minor-shaped. Continue as patch, or bump to `v<suggested>`?"* Do not silently proceed.
9393

94-
2. **Read the last 2–3 release notes** to match structure and length (not tone — see *Generation parameters*).
95-
- [docs/releases/v0.17.4.mdx](../../../docs/releases/v0.17.4.mdx)
96-
- [docs/releases/v0.17.3.mdx](../../../docs/releases/v0.17.3.mdx)
97-
- [docs/releases/v0.17.2.mdx](../../../docs/releases/v0.17.2.mdx)
94+
2. **Read recent release notes for structure only** — frontmatter shape, section headings, PR-link format. Take **length and tone from *Notes format* below, not from the files**: [v0.21.1](../../../docs/releases/v0.21.1.mdx) is the model at 267 narrative words, while v0.22.0 (1705) and v0.23.0 (1119) were flagged in review as too much text in too-blocky a form — they are the regression this section exists to prevent.
9895

99-
Cross-check: same frontmatter shape, same section headings, same *structure* and length per entry — but **not** the prior tone. The last few releases predate the *Generation parameters* below; match their shape, not their dryness. Patch releases are short; minor/major releases include `pip install` and may have a "Highlights" block.
96+
Patch releases are short. Minor/major releases carry more bullets and a `pip install` block — the per-bullet shape is identical, only the count grows.
10097

10198
3. **Create [docs/releases/v<version>.mdx](../../../docs/releases/)** with this skeleton (adapt to whether it's patch / minor / major):
10299

103100
```mdx
104101
---
105102
title: "v<version>"
106-
description: "<one-line elevator pitch what shipped, who benefits>"
103+
description: "<one plain line: what shipped. Not a pitch.>"
107104
---
108105

109106
# GAIA v<version> Release Notes
110107

111-
<One-paragraph overview: what kind of release this is and what it covers.>
108+
<Optional single sentence naming what this release is about. Drop it entirely if
109+
the bullets already say it that is the common case. Never a paragraph.>
112110

113-
**Why upgrade:**
114-
- **<short title>** — <one-line value-and-mechanism>.
115-
- **<short title>** — <one-line value-and-mechanism>.
111+
## Breaking Changes
116112

117-
---
113+
- **<what changed>** — <what to do instead>. (PR [#NNN](https://github.com/amd/gaia/pull/NNN))
118114

119115
## What's New
120116

121-
### <What the user can now do> — `<gaia command>`
117+
- **<what the user can now do>**`<gaia command>`. <At most one more sentence, only
118+
if the title genuinely needs it.> (PRs [#NNN](https://github.com/amd/gaia/pull/NNN), [#NNN](https://github.com/amd/gaia/pull/NNN))
122119

123-
<Lead with the outcome and why it matters, in plain language that makes the reader
124-
want to try it. Then one line on how to run it, PR linked inline. One agent or
125-
command per entry add another `### ` block for the next one. Not every highlight
126-
is a command for UI / SDK / perf items, use a plain title with no trailing
127-
command.>
120+
## Bug Fixes
128121

129-
---
122+
- **<what was broken>** — <what now happens>. (PR [#NNN](https://github.com/amd/gaia/pull/NNN))
130123

131-
## Bug Fixes
124+
## Known Issues
132125

133-
- **<title>** (PR [#NNN](https://github.com/amd/gaia/pull/NNN)) <one-line description of fix and impact>.
126+
- **<what still does not work>** — <workaround, or "tracked in [#NNN](https://github.com/amd/gaia/issues/NNN)">.
134127

135-
---
128+
## Contributors
129+
130+
- [@handle](https://github.com/handle) — <what they contributed>. (PR [#NNN](https://github.com/amd/gaia/pull/NNN))
136131

137132
## Full Changelog
138133

@@ -144,6 +139,9 @@ These map to [CLAUDE.md](../../../CLAUDE.md). Re-read them whenever this skill r
144139
Full Changelog: [v<previous>...v<version>](https://github.com/amd/gaia/compare/v<previous>...v<version>)
145140
```
146141

142+
Omit `## Breaking Changes` and `## Known Issues` when empty — no "None" placeholder. Drop
143+
the `---` rules between sections; the headings already separate them.
144+
147145
**Generate the changelog by introspecting git, and escape it for MDX.** Do not
148146
hand-transcribe subjects, and do not pipe `git log` output in raw — a subject
149147
containing `<` or `{` is valid git and invalid MDX, which fails CI's `mintlify
@@ -168,40 +166,42 @@ These map to [CLAUDE.md](../../../CLAUDE.md). Re-read them whenever this skill r
168166
claimed 197 when the real count was 198). The claimed count, the listed lines, and
169167
`git log` must all agree.
170168

171-
**Generation parameters (apply to every entry — this is the point of the skill).**
172-
GAIA's notes have historically read dry and engineering-first: they say *what
173-
changed* but not *why a user should care or want to try it*. Generate against these
174-
every time:
175-
176-
- **Value-prop first.** Open each entry with what the user can now do and why it
177-
matters — the outcome, not the implementation. "Triage your inbox in one command"
178-
before "added EmailAgent with Gmail polling".
179-
- **Local agents are the headline.** Lead with the agents that solve real problems
180-
(`gaia browse`, `gaia analyze`, email triage, …); SDK / infra / refactors are
181-
supporting detail. People come for the agents, not the SDK.
182-
- **One agent or command per highlight.** `gaia browse` and `gaia analyze` each get
183-
their own `### ` entry with its own one-line utility — never lumped together.
184-
- **Plain, human language.** Write like you're telling a colleague what they can do
185-
now. Short sentences; plain words over jargon.
186-
- **Engaging, still factual.** Make the reader want to try it without overselling —
187-
no invented benchmarks, no "fastest ever". The pull comes from a clear, real
188-
capability, not adjectives.
189-
- **No fluff, no emoji.** Banned: emoji in headings or body, "we're excited to
190-
announce", "finally", "blazing(-fast)", "Here's the good stuff", "no more
191-
crashes", "silently", "game-changer".
192-
193-
**Example — one highlight, done right:**
194-
195-
> **Bad** (dry, implementation-first, no reason to care):
196-
> ### EmailAgent
197-
> Adds an EmailAgent with Gmail polling and a rules engine for classification.
198-
199-
> **Good** (value-first, plain, makes you want to try it):
169+
**Notes format (apply to every entry — this is the point of the skill).** Tone is
170+
already governed by [CLAUDE.md → How You Communicate](../../../CLAUDE.md#how-you-communicate)
171+
— plain language, outcome first, each point made exactly once. Do not restate or soften
172+
it here. What *is* release-notes-specific is the shape:
173+
174+
- **Bullets, not paragraphs.** Every entry is one bullet: a bold clause naming what the
175+
user can now do, then at most one sentence, then the PR links. No `###` prose blocks
176+
inside `What's New`.
177+
- **Say it once.** A highlight appears in the bullet list or in the opening sentence,
178+
never both. The frontmatter `description` is not a third copy.
179+
- **Factual, not promotional.** State the capability and stop. Banned: emoji, "we're
180+
excited to announce", "finally", "blazing(-fast)", "game-changer", "seamless",
181+
"powerful", "unlock", "Here's the good stuff", "makes X effortless", "no more
182+
crashes", invented benchmarks.
183+
- **Order by what users run.** Agents and commands first (`gaia hub`, `gaia email`, …);
184+
SDK, CI, and refactor work last, or omitted when it has no user-visible effect.
185+
- **Word budget — a cap, not a target.** **≤ 350 words** for a patch, **≤ 600** for a
186+
minor/major, measured from the top down to the first of `## Bug Fixes` / `## Known
187+
Issues` / `## Contributors` / `## Full Changelog`. Those four are reference lists —
188+
their length is set by how many fixes actually shipped, and squeezing them hides work.
189+
The cap is on the narrative part, which is what bloats. Over budget means cut entries,
190+
not reflow them. Step 8 checks it. (Calibration, same measure: v0.21.1 shipped at 267,
191+
v0.22.0 at 1705, v0.23.0 at 1119.)
192+
193+
**Example — one highlight:**
194+
195+
> **Bad** (prose block, promotional, three sentences where one works):
200196
> ### Triage your inbox from the terminal — `gaia email`
201197
> Point GAIA at your inbox and it sorts the noise from what needs you: drafts
202198
> replies to routine mail, flags what's urgent, leaves the rest. Runs locally, so
203199
> your mail never leaves your machine. Try it: `gaia email`.
204200
201+
> **Good** (one bullet, plain, factual):
202+
> - **Triage your inbox from the terminal**`gaia email` sorts mail, drafts replies to
203+
> routine messages, and flags what needs you. Runs locally. (PR [#1234](https://github.com/amd/gaia/pull/1234))
204+
205205
4. **Update [docs/docs.json](../../../docs/docs.json):**
206206
- Add `releases/v<version>` to the Releases tab.
207207
- Bump the navbar label (e.g. `v<previous-version> · Lemonade <previous-lemonade>``v<version> · Lemonade <current-lemonade>`). Read [src/gaia/version.py](../../../src/gaia/version.py) for the `LEMONADE_VERSION` constant — it is the source of truth, and the navbar may be drifted from it (Lemonade bumps land outside release PRs).
@@ -249,6 +249,11 @@ These map to [CLAUDE.md](../../../CLAUDE.md). Re-read them whenever this skill r
249249
```bash
250250
python util/validate_release_notes.py docs/releases/v<version>.mdx --tag v<version>
251251
(cd docs && npx -y mintlify@latest validate) # the docs.yml `validate` job — MUST also pass
252+
253+
# Word budget from *Notes format* — the narrative part only, not the reference lists.
254+
# Cap: 350 words for a patch, 600 for a minor/major. Over budget means cut entries.
255+
awk '/^## (Bug Fixes|Known Issues|Contributors|Full Changelog)/{exit} {print}' \
256+
docs/releases/v<version>.mdx | wc -w
252257
```
253258
Both must exit 0. Fix any errors before continuing. If either fails for reasons unrelated to your changes (missing dep, broken import), stop and surface that — do not silently bypass. `validate_release_notes.py` prints the first failing check (missing/renamed section, absent `compare/` link, tag mismatch) — read that line to localise the fix; it has no `--verbose` flag.
254259

@@ -460,7 +465,7 @@ Show the user the run URL, the **release PR number** (`#$RELEASE_PR`), and the *
460465
```
461466
Required artifacts: `.whl`, `.tar.gz`, `.deb`, `.AppImage`, `.dmg`, `.exe`, and the `latest*.yml` files for the Electron auto-updater. If any are missing, the corresponding build job didn't run or didn't upload — investigate.
462467

463-
3. **Draft the Discord announcement.** Read the just-shipped release notes (`docs/releases/v<version>.mdx`) to populate the highlight list — one bullet per "What's New" entry plus any Bug Fix worth surfacing, written in the same voice as the notes — apply the same *Generation parameters* (value-prop first, plain, engaging, no fluff/emoji).
468+
3. **Draft the Discord announcement.** Read the just-shipped release notes (`docs/releases/v<version>.mdx`) to populate the highlight list — reuse the `What's New` bullets near-verbatim plus any Bug Fix worth surfacing. Same *Notes format* rules apply: bullets, plain, factual, no emoji.
464469

465470
**The template and format rules live in**
466471
[`reference/discord-announcement.md`](reference/discord-announcement.md) — read it and

.claude/skills/gaia-release/reference/discord-announcement.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ The house format for the `#announcements` Discord post, cut at the end of Phase
44
[`gaia-release`](../SKILL.md) skill. This is the v0.22.0 shape — the format the maintainer
55
actually posts.
66

7-
Populate the highlights from the just-shipped `docs/releases/v<version>.mdx`, in the same
8-
voice as the notes: value-prop first, plain, engaging, no fluff, no emoji.
7+
Populate the highlights from the just-shipped `docs/releases/v<version>.mdx` — reuse its
8+
`What's New` bullets near-verbatim. Same rules as the notes (*Notes format* in the skill):
9+
one bullet per highlight, plain, factual, no emoji, no pitch.
910

1011
## Template (copy verbatim, fill the bracketed fields)
1112

0 commit comments

Comments
 (0)