| name | release-notes |
| description | Draft and prepend a new entry to RELEASE-NOTES.md for an upcoming production release of this monorepo, and produce a copy-paste-ready Discord announcement for the |
Release notes generator (project-scoped)
Generates the next entry for RELEASE-NOTES.md based on everything that landed since the previous production release. Owned by this repo because the tag conventions, file format, and source layout are repo-specific. See RELEASE.md for the full release flow.
When to run
- Right before triggering a production release workflow on a
release/production/<X.Y.Z> branch.
- Optionally during the staging cycle, to draft the section early so reviewers can comment as more changes land.
What this skill does NOT do
- Does not publish, tag, commit, or push the chore-release commit — that's the GitHub Action.
- Does not modify
package.json or CHANGELOG.md — those are owned by Nx.
- Does not invoke
nx release version — see RELEASE.md Case 3 for that flow.
- Does not commit or push
RELEASE-NOTES.md itself. You stop after writing the file; the user reviews, commits, and pushes.
Step 1 — Ask the user for the target version
Ask exactly:
What production version are we releasing? (e.g. 6.0.0)
Accept the version with or without a leading v. Reject prereleases — if the user answers 6.0.0-staging.7, 6.0.0-dev.239, or anything with a prerelease suffix, explain that release-notes entries always use the final production version and re-ask. Store the cleaned value (no leading v, no suffix) as NEW_VERSION.
Step 2 — Detect the previous production tag
Run:
git tag --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1
This skips every -dev.N / -staging.N / other prerelease tag and returns the highest clean semver tag.
Tell the user what you found and confirm:
The most recent production tag I see is v<X.Y.Z>. I'll collect everything between v<X.Y.Z> and HEAD on this branch. Confirm, or give me a different anchor tag.
Wait for confirmation. Store the chosen value as PREV_TAG (with leading v).
Sanity-check the working state — if the user is not on a release/production/<NEW_VERSION> branch (or, when drafting early, on the matching release/staging/<NEW_VERSION> branch), warn them and ask whether to continue. Proceed if they insist.
Step 3 — Collect source material (run in parallel)
-
Commit list:
git log <PREV_TAG>..HEAD --no-merges --pretty=format:"%h %s"
-
Changed files across the range (so you can see which packages are touched):
git log <PREV_TAG>..HEAD --name-only --pretty=format: | sort -u | grep -v '^$'
-
CHANGELOG.md at the repo root — read it and locate every ## <version> (...) heading whose version falls in (<PREV_TAG stripped of leading v>, <NEW_VERSION>]. The CHANGELOG entries are Nx-generated, already grouped under ### 🚀 Features / ### 🩹 Fixes with scope tags like **reactor-browser:**, **switchboard:**, and commit links. Treat them as a curated index of what changed — useful for picking out which scopes deserve a feature block — but not as the source of truth for descriptions or API shape.
-
Existing RELEASE-NOTES.md at the repo root — read it to absorb the section format, tone, emoji vocabulary, subsection order, and prior structure. Mirror the closest prior entry's style.
Step 4 — Triage commits
Bucket every commit you collected:
- breaking — commits with
! after the type (feat!:, refactor(api)!:) or commits whose diff contains a BREAKING CHANGE: footer.
- feat — new user-visible functionality worth surfacing.
- fix — user-visible bug fixes. Skip CI/build-only fixes unless they affected published artifacts.
- perf / refactor — include only if the change is user-visible (e.g. observable speed-up, public API shape change).
- docs — include only if the diff itself adds academy / docs URLs that should be linked from the notes.
- chore / ci / test — skip from the notes, but use them to validate the range covers what you expect.
Always skip:
chore(release): publish ... (autogenerated by the release pipeline)
- Lockfile-only diffs
- Dependency bumps that don't change runtime behavior
- Pure internal refactors with no public API surface change
For each surviving commit:
- For every breaking and every notable feat, run
git show <sha> and read the actual diff. Pull API shapes, env-var names, and code examples directly from the diff — not from the commit subject.
- For non-obvious cases (commit message is ambiguous, scope is unfamiliar), read the modified file at HEAD to confirm the current behavior.
Step 5 — Draft the section
Match the format already in RELEASE-NOTES.md. Reference skeleton (drop subsections that don't apply):
## 🚀 **v<NEW_VERSION>**
### ✨ Highlights
1. **<Theme 1>** — short framing sentence
2. **<Theme 2>** — short framing sentence
3. **<Theme 3>** — short framing sentence
### NEW FEATURES
#### <emoji> <Feature Title>
<2–4 sentence description grounded in the diff>
```typescript
// usage example, copied from real code in the diff (not invented)
```
✅ **What to try:** <action a consumer can take to exercise this feature>
### BREAKING CHANGES
#### <Title>
**Before (v<PREV_VERSION>):**
```typescript
// from git show <sha>, "before" side
```
**After (v<NEW_VERSION>):**
```typescript
// from git show <sha>, "after" side
```
**Migration:** <runnable steps for this specific breakage>
### MIGRATION GUIDE
1. <ordered, runnable step consolidating cross-cutting actions>
2. <ordered, runnable step>
### BUG FIXES AND IMPROVEMENTS
- <short bullet, user-visible>
- <short bullet>
### DOCUMENTATION
- [<Title>](url-from-diff) — only if the diff itself added/updated the link
Constraints, in priority order:
- No invented APIs, env vars, CLI flags, command names, type names, or URLs. If you can't pull it from the diff or from a file at HEAD, leave it out.
- No paraphrasing without verification. A commit subject is a starting point; the diff is the source of truth.
- Final production version only. The header is
## 🚀 **v<NEW_VERSION>**, never -staging.N or -dev.N.
- Don't reorder or rewrite existing entries. Only prepend.
- Match the existing emoji vocabulary: 🚀 version, ✨ highlights, 🔐 auth, 🛡️ permissions, 🔍 inspector, ⚡ perf, 🐞 bug fixes, 🛠️ tooling, ✍️ signing, 🔄 sync. When in doubt, mirror the closest prior entry.
- Keep highlights to 2–4 items maximum.
Step 6 — Prepend to RELEASE-NOTES.md
Insert the drafted section immediately after the # Release Changelog H1 line and before the existing top entry. Preserve spacing: one blank line between the H1 and your new section, one blank line between your new section and the previous top entry.
Do not commit or push. The user reviews next.
Step 7 — Generate the Discord announcement
After writing the file in Step 6, produce a separate, copy-paste-ready message that the user will post in the #coredev-releases Discord channel. Print it inside a fenced code block in chat (so the body copies cleanly) — never embed it into RELEASE-NOTES.md.
The Discord message is a condensed promo of the new section, not a copy of it. Surface the highlights and one academy link per theme; everything else stays in the long-form notes.
Discord constraints
- Hard limit: 2000 characters (Discord's default per-message limit). Aim for ≤ 1800 to leave headroom. If your draft exceeds 1900, trim ruthlessly: cap themes at 3, cap per-theme bullets at 2, drop "try this" lines first.
- No markdown headings. Discord does not render
#, ##, ###. Use bold + emoji prefixes for visual structure.
- Bare URLs only. Discord auto-links them. Do NOT use
[text](url) markdown — it renders as raw text.
- Allowed formatting:
**bold**, *italic*, - bullets, line breaks, Unicode emoji.
- Unicode emoji (🚀, ✨, 🔗, 💙, 🥷, 🤓), not
:emoji_name: shortcodes.
Format
Match the structure of prior announcements in the channel:
🚀 v<NEW_VERSION>
- <One framing sentence about the release>
- <Optional second framing line — e.g. "First production release after Z prereleases" or a notable theme>
Complete release notes & latest documentation can now be found on
https://academy.vetra.io/academy/ReleaseNotes 🤓
✨ Highlights of this release for you to try-out!
**<Theme 1 Title>** - <short description in one line>
- <key detail or feature bullet>
- 🔗 <bare academy URL — only if RELEASE-NOTES.md cites it>
- <optional "try this" line>
**<Theme 2 Title>** - <short description>
- <key detail>
- 🔗 <bare academy URL — only if cited>
**<Theme 3 Title>**
- <key detail>
- 🔗 <bare academy URL — only if cited>
Thank you 💙 Core-dev Team (& friends!)
Rules
- Themes map 1-to-1 to the Highlights subsection of the RELEASE-NOTES.md entry you just wrote. Cap at 4 themes; prefer 3.
- The "Complete release notes & latest documentation" line and the "Thank you 💙 Core-dev Team (& friends!)" footer are constants — always include them verbatim.
- The framing bullets at the top should be 1–2 lines. If there's no obvious framing, drop them and go straight to the "Complete release notes" line.
- Only include 🔗 URL bullets for links that already appear in
RELEASE-NOTES.md (which means they came from the diff). Never invent or guess academy URLs.
- Per-theme bullets: 2–4 max. Bullets should be observable behavior or things the reader can do, not internal mechanics.
- Count the characters before printing. If over 1900, trim and recount before emitting.
Step 8 — Report back and hand off
After printing the Discord message, summarize for the user in this order:
-
Range covered: <PREV_TAG>..HEAD — N commits inspected, M skipped as housekeeping.
-
Subsections produced in RELEASE-NOTES.md — list which ones (Highlights / NEW FEATURES / BREAKING CHANGES / MIGRATION GUIDE / BUG FIXES / DOCUMENTATION).
-
Discord message length: <N> / 2000 characters.
-
Notable items intentionally left out — anything ambiguous you skipped from the long-form notes, so the user can decide whether to fold it back in.
-
Sources cross-referenced — confirm you read CHANGELOG.md for the range and RELEASE-NOTES.md for format.
-
Review checklist the user must run before committing:
- Re-read every feature claim against
git show <sha> for the cited commit.
- Verify each linked URL resolves (both in the file and in the Discord message).
- Confirm migration steps are runnable as written.
- Cross-check breaking-change before/after blocks against the actual diff.
- Sanity-check the Discord message renders correctly (you can preview by pasting into a Discord DM to yourself before posting to
#coredev-releases).
-
Suggested commit & next steps — print, but do not execute:
git add RELEASE-NOTES.md
git commit -m "docs: release notes for v<NEW_VERSION>"
git push
Then trigger the Release Branch workflow on release/production/<NEW_VERSION> with release_mode=patch (see RELEASE.md). Once the workflow succeeds, paste the Discord message into #coredev-releases.