feat(changelog): a fragment's BREAKING CHANGE text should reach the release's ### Upgrade section, which today reads None for a breaking release #1554

Open
opened 2026-10-06 00:09:27 +02:00 by claude · 0 comments
Member

Measured

v0.67.0 (#1553, cut on 2026-10-06) removed the six single-gate reusables (#1542). That is a breaking change for any adopter still wiring them.

  • The composed [v0.67.0] section carries the migration as one ### Removed bullet: "six single-gate reusables are gone: wire one pr.yml on reusable-pr-gates.yml and require pr / gates (pull_request) (#1542)".
  • ### Upgrade reads "None."
  • The fragment's BREAKING CHANGE: body, with the full list of removed files, the renamed status contexts and the steps, is not rendered anywhere. Only a fragment's summary line reaches the composed section (#854, since v0.48.0).

Why the section stays empty (review 7260):

  • upgrade is not a fragment kind. valid_kinds is added, changed, deprecated, removed, fixed, security and internal.
  • The changelog-format contract says ### Upgrade is "never produced by fragment folding". It is authored by hand under [Unreleased], or derived from commits only in a release with no fragments (ADR-0012).
  • docs/conventions.md offers "add a fragment, or ### Upgrade prose" for a breaking change. Taking the fragment branch leaves Upgrade empty by construction.
  • v0.65.0 shipped the same way.

For v0.67.0 this was harmless: all five adopters had already migrated at v0.66.0, so "Upgrade: None." was literally true for each. It is misleading for an outside adopter who reads the Upgrade section as the list of things to do before bumping.

Why it matters

The toolkit is meant for adopters outside this forge. A reader who checks only ### Upgrade before bumping a pin sees "None." on exactly the releases where action is required. The breaking information exists, in the fragment body and the commit's BREAKING CHANGE: footer, but never reaches the published notes.

Options (decision tree, AGENTS.md section 7)

  • Render a fragment's BREAKING CHANGE: paragraph under ### Upgrade for the release that consumes it. This is right when breaking changes should travel with the change that introduces them. It does not need a new fragment kind. It needs a rule for the paragraph's shape and a density check that covers it.
  • Add an upgrade fragment kind, rendered into ### Upgrade. This is right if an upgrade step should be written for readers, separately from the change's own summary. The cost is one more kind for authors to learn.
  • Keep it as it is, and make the PR-time gate require ### Upgrade prose under [Unreleased] whenever a fragment's body carries BREAKING CHANGE:. This is right if hand-written Upgrade text should stay the only source. It moves the burden onto the author, at PR time.

Acceptance criteria

  • A decision between the options above, recorded with its reasons (an ADR amendment if it changes ADR-0011 or ADR-0012's note-source rule).
  • Whichever is chosen, a release that consumes a breaking fragment can no longer publish ### Upgrade as "None." without an explicit, documented reason.
  • The changelog-format contract and docs/conventions.md agree with the result.
## Measured v0.67.0 (#1553, cut on 2026-10-06) removed the six single-gate reusables (#1542). That is a breaking change for any adopter still wiring them. - **The composed `[v0.67.0]` section carries the migration as one `### Removed` bullet:** "six single-gate reusables are gone: wire one `pr.yml` on `reusable-pr-gates.yml` and require `pr / gates (pull_request)` (#1542)". - **`### Upgrade` reads "None."** - **The fragment's `BREAKING CHANGE:` body,** with the full list of removed files, the renamed status contexts and the steps, is not rendered anywhere. Only a fragment's summary line reaches the composed section (#854, since v0.48.0). Why the section stays empty (review 7260): - `upgrade` is not a fragment kind. `valid_kinds` is added, changed, deprecated, removed, fixed, security and internal. - The changelog-format contract says `### Upgrade` is "never produced by fragment folding". It is authored by hand under `[Unreleased]`, or derived from commits only in a release with no fragments (ADR-0012). - `docs/conventions.md` offers "add a fragment, or `### Upgrade` prose" for a breaking change. Taking the fragment branch leaves Upgrade empty by construction. - v0.65.0 shipped the same way. For v0.67.0 this was harmless: all five adopters had already migrated at v0.66.0, so "Upgrade: None." was literally true for each. It is misleading for an outside adopter who reads the Upgrade section as the list of things to do before bumping. ## Why it matters The toolkit is meant for adopters outside this forge. A reader who checks only `### Upgrade` before bumping a pin sees "None." on exactly the releases where action is required. The breaking information exists, in the fragment body and the commit's `BREAKING CHANGE:` footer, but never reaches the published notes. ## Options (decision tree, AGENTS.md section 7) - **Render a fragment's `BREAKING CHANGE:` paragraph under `### Upgrade`** for the release that consumes it. This is right when breaking changes should travel with the change that introduces them. It does not need a new fragment kind. It needs a rule for the paragraph's shape and a density check that covers it. - **Add an `upgrade` fragment kind,** rendered into `### Upgrade`. This is right if an upgrade step should be written for readers, separately from the change's own summary. The cost is one more kind for authors to learn. - **Keep it as it is, and make the PR-time gate require `### Upgrade` prose** under `[Unreleased]` whenever a fragment's body carries `BREAKING CHANGE:`. This is right if hand-written Upgrade text should stay the only source. It moves the burden onto the author, at PR time. ## Acceptance criteria - [ ] A decision between the options above, recorded with its reasons (an ADR amendment if it changes ADR-0011 or ADR-0012's note-source rule). - [ ] Whichever is chosen, a release that consumes a breaking fragment can no longer publish `### Upgrade` as "None." without an explicit, documented reason. - [ ] The changelog-format contract and `docs/conventions.md` agree with the result.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
frankenbit/release-toolkit#1554
No description provided.