Skip to content

Every pull request carries a release note for users, checked by CI - #169

Merged
danipen merged 13 commits into
mainfrom
chore/release-notes-harness
Oct 30, 2026
Merged

danipen merged 13 commits into
mainfrom
chore/release-notes-harness

Conversation

@danipen

@danipen danipen commented Oct 30, 2026

Copy link
Copy Markdown
Member

What does this pull request do?

Every pull request now carries a release note written for the app's users, separate from the title and body written for reviewers, and CI fails a pull request without one.

Release note

None: changes how pull requests are written and checked; nothing changes in the app.

Current behavior

The release notes are GitHub's generated list of pull request titles ("… by @user in https://github.com/…/pull/156"). Titles are written for reviewers, so What's New and the releases page read like a changelog for developers.

Behavior with this pull request

  • The pull request template has a ## Release note section: ### New:, ### Improved: or ### Fixed: and a title users understand, then a short Markdown description (a picture, table or code only when words aren't enough); or None: and why users have nothing to read.
  • A new Release note check reads that section on every change to the pull request, editing its description included, and fails when it is missing, empty, still holds the template's placeholders, has no kind or no description, holds two notes, or says None without a reason. Dependabot's pull requests are left out.
  • Agents write the note with the new release-notes skill, give it to the reviewer, and the reviewer checks it as user-facing copy.

How it was implemented

  • readReleaseNote (scripts/build/releaseNote.ts): reads the section line by line, no Markdown package, so Node runs it as it is (.nvmrc's Node strips types). It removes HTML comments first, finds the section outside fenced code (a fence closes only on its own character and length, as in CommonMark), and returns { kind, title, description }, { kind: 'none', reason } or a problem worded for the author. Run as a command it reads PULL_REQUEST_BODY and exits 1 on a problem.
  • .github/workflows/release-note.yml: pull_request (opened, edited, reopened, synchronize), read-only token, the body passed through the environment, never the command line. It is its own workflow so editing the description doesn't rebuild on every OS. It also triggers on merge_group, where the job skips itself (counted as passing), so it can be made a required check; mergeQueueTrigger.test.ts now guards that trigger too.
  • .claude/skills/release-notes/SKILL.md: who notes are for, how to pick New/Improved/Fixed by what users get (not by the branch name), titles under 80 characters, a description always (fixes say what users saw and what happens now), the app's words only, and a before/after table built from real titles.
  • Harness: CLAUDE.md "Delivering work" steps 4 and 6 and the "Rules the tests enforce" table, AGENTS.md's skills, the reviewer's brief (a missing note, or one written for reviewers, is a must-fix), docs/features/updates.md.
  • Dropped: classifying by branch name or by labels. The agent writing the note knows what the change delivers better than a branch name chosen before the work, and a word in the note is edited where labels must be maintained.

Next, in their own pull requests: the Release workflow joins these notes into the release description (## New, ## Improved, ## Fixed, a ### per note), which GitHub renders on the releases page; and What's New shows them grouped, with a filter, rendering their Markdown, pictures and tables included.

Behavior changes

  • Pull requests need a ## Release note section. Once this merges, Release note can be added to main's required checks.
  • The template gains that section.

Checklist

  • npm run typecheck and npm test pass (8,519). What the new tests cover: every kind; None: with and without a reason, with a note or a second paragraph under it, and lookalikes ("None.", "None of the views…"); missing and empty sections; the real template as it is; placeholders; no kind, a lower-case kind, no title, no description, two notes; ## lines in code and comments; tilde and backtick fences; CRLF; non-ASCII; the workflow's triggers.
  • Seen working in the app: nothing visible changes. The command was run by hand on a valid and an invalid body (exit 0 and 1).
  • npm run e2e: not needed, nothing in the app changes.
  • Other areas the change reaches: pinnedActions.test.ts covers the new workflow (same SHAs as ci.yml).
  • Reviewed in a clean context. Fixed for it: None read too loosely (colon now required, one line, no note under it); fences closing on the wrong character and comments holding ## or fences; placeholders left in; the merge-queue trigger unguarded; the reviewer not given the note; test nits; wording. Declined in this pull request: "the skill promises pictures, tables and #### headings What's New doesn't show". The What's New pull request, built now, renders them, and lands with this one.
  • docs/ says what's now true: docs/features/updates.md "What's New" and "CI".

Fixed issues

None.

🤖 Generated with Claude Code

danipen and others added 13 commits October 30, 2026 10:38
…escription, or why it has none

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ion, or why it has none

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… it delivers, or says why it doesn't

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t it delivers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…view checks it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne:" are read exactly

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the template's placeholders and a "None:" holding a note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…quired never stalls the queue

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aracters, the queue's checks include the note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s or leave a code block open

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… block, which would break the release's groups

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@danipen
danipen added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit dd9f739 Oct 30, 2026
10 checks passed
@danipen
danipen deleted the chore/release-notes-harness branch October 30, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant