What
The empty-changelog class is genuinely closed. Measured across all 40 providers/* + packages/* changelogs at 2d36880:
0.5.0: present in 40, empty 0
0.5.1: present in 40, empty 0
0.6.0: present in 40, empty 0
against 135 of 234 (58%) empty a week ago and 149 of 156 (96%) the week before. Packages with nothing to say now carry an explicit _No changes in this package._, which is an honest answer rather than a blank heading. That is real progress on #854/#903.
The mechanism that produced it attributes every repo-level commit to every package:
$ # changelogs carrying the join() "### Breaking Changes" entry at 0.5.0
39 of 40
$ git show --stat 5f83ae85f -- providers/mlx providers/playwright providers/electron
providers/electron/package.json | 2 +-
providers/mlx/package.json | 2 +-
providers/playwright/package.json | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
providers/mlx/CHANGELOG.md at 0.5.0 now reads:
## 0.5.0
### Breaking Changes
- **features(storage)**: add join() to ITabularStorage with SQL pushdown (#893)
### Features
#### storage
- add join() to ITabularStorage with SQL pushdown (#893)
@workglow/mlx is a 166-LOC stub with isAvailable() => false. Its entire involvement in 5f83ae85f was a one-line dependency version bump. A consumer reading its changelog is told 0.5.0 broke their code.
Why it matters
This is the mirror image of the finding this series pushed for five cycles. #854/#903 were about breaking changes shipping invisibly — a patch bump, no !, no footer. This window fixed that half properly: 5f83ae85f is the first !-marked commit and first BREAKING CHANGE footer in fifteen review snapshots, and it went out as a minor (0.4.9 → 0.5.0). Correct.
But an indiscriminate breaking-change marker is the fastest way to teach readers to ignore the marker. 38 of the 39 packages carrying it did not break. Next release, the one package that did break gets the same heading as the 38 that did not, and nobody reads it.
The same mechanism also mis-files real work. providers/playwright's only source change in nine review cycles — a genuine TOCTOU fix in PlaywrightBackend.connect(), where every handle was re-read from its field after an await and a concurrent disconnect() could null it — is recorded in its changelog as:
## 0.5.1
### Chores
- run format-check in CI, and turn on every staged-off lint rule
A reader of @workglow/playwright's changelog cannot tell that a correctness fix shipped.
Proposed fix
- Attribute a changelog entry to a package only when the commit touched that package's
src/. A version-only package.json bump is what _No changes in this package._ already exists to describe. This alone fixes both symptoms.
- If a dependency's break genuinely propagates, say that instead of restating the dependency's headline —
- Updated @workglow/storage to 0.5.0 (breaking: ITabularStorage.join) under a Dependencies heading, not under this package's Breaking Changes.
- For a sweep commit that touches many packages for different reasons (
509724031 is the live example — a lint-rule enablement that also carried the playwright fix), split it, or let the per-package entry be derived from that package's own hunks rather than the commit subject.
Found during the 2026-09-14 review of providers/. Verified against origin/main @ 2d36880. Relates to #903.
What
The empty-changelog class is genuinely closed. Measured across all 40
providers/*+packages/*changelogs at2d36880:against 135 of 234 (58%) empty a week ago and 149 of 156 (96%) the week before. Packages with nothing to say now carry an explicit
_No changes in this package._, which is an honest answer rather than a blank heading. That is real progress on #854/#903.The mechanism that produced it attributes every repo-level commit to every package:
providers/mlx/CHANGELOG.mdat 0.5.0 now reads:@workglow/mlxis a 166-LOC stub withisAvailable() => false. Its entire involvement in5f83ae85fwas a one-line dependency version bump. A consumer reading its changelog is told 0.5.0 broke their code.Why it matters
This is the mirror image of the finding this series pushed for five cycles. #854/#903 were about breaking changes shipping invisibly — a patch bump, no
!, no footer. This window fixed that half properly:5f83ae85fis the first!-marked commit and firstBREAKING CHANGEfooter in fifteen review snapshots, and it went out as a minor (0.4.9 → 0.5.0). Correct.But an indiscriminate breaking-change marker is the fastest way to teach readers to ignore the marker. 38 of the 39 packages carrying it did not break. Next release, the one package that did break gets the same heading as the 38 that did not, and nobody reads it.
The same mechanism also mis-files real work.
providers/playwright's only source change in nine review cycles — a genuine TOCTOU fix inPlaywrightBackend.connect(), where every handle was re-read from its field after anawaitand a concurrentdisconnect()could null it — is recorded in its changelog as:A reader of
@workglow/playwright's changelog cannot tell that a correctness fix shipped.Proposed fix
src/. A version-onlypackage.jsonbump is what_No changes in this package._already exists to describe. This alone fixes both symptoms.- Updated @workglow/storage to 0.5.0 (breaking: ITabularStorage.join)under a Dependencies heading, not under this package's Breaking Changes.509724031is the live example — a lint-rule enablement that also carried the playwright fix), split it, or let the per-package entry be derived from that package's own hunks rather than the commit subject.Found during the 2026-09-14 review of
providers/. Verified againstorigin/main@2d36880. Relates to #903.