Found while implementing #5442 (npm-presence publish predicate). Out of that card's scope — filing rather than fixing, and #5442 deliberately leaves the detector untouched.
The reading
.github/workflows/changeset-release.yml's Detect pending changesets step carries an explicit, load-bearing declaration:
⛔ This must stay a faithful mirror of readChangesetState in changesets/action's src/index.ts (it re-exports @changesets/read) […]
- every
.changeset/*.md counts EXCEPT README.md;
Measured against the copy actually installed in this repository — node_modules/.pnpm/@changesets+read@1.0.0/node_modules/@changesets/read/dist/index.mjs — the reader does two things the mirror does not:
constignoredMdFiles=[/^README\.md$/i,"AGENTS.md","CLAUDE.md","GEMINI.md"];
and, separately, it also pulls in a whole second directory:
changesets.push(...(awaitfs.readdir(path.join(changesetBase,"pre"))).map((file)=>`pre/${file}`));So the two disagree in both directions:
| case | @changesets/read@1.0.0 | the mirror in the workflow |
|---|
.changeset/AGENTS.md | ignored | counted as pending |
.changeset/CLAUDE.md | ignored | counted as pending |
.changeset/GEMINI.md | ignored | counted as pending |
.changeset/ReadMe.MD | ignored (regex is /i) | counted as pending (exact 'README.md' compare) |
.changeset/pre/*.md | counted as pending | not seen at all |
Confirmed empirically: with a pre/probe.md plus AGENTS.md and CLAUDE.md added to a copy of the real .changeset/, readChangesets returned 161, counting pre/probe.md and ignoring the other two.
Why it is dormant right now, and why that is not reassuring
None of .changeset/AGENTS.md, CLAUDE.md, GEMINI.md, .changeset/pre/ or a non-canonically-cased README exists today, so the disagreement is currently unobservable. The first of those files anyone adds makes it live, and .changeset/AGENTS.md is a plausible thing to add — it is exactly where per-directory agent instructions go in this repo's conventions, and the changesets reader ignores it because people do that.
The blast radius depends on which predicate the release job is on:
That is a real reduction in severity, but it does not make the declaration true, and the comment still tells the next reader that one name is the whole exclusion list.
Also worth checking, and not checked here
The mirror is declared against changesets/action's bundled copy, not against this repository's @changesets/read@1.0.0. Those can be different versions with different ignoredMdFiles. The correct fix should establish which copy is authoritative for the mirror before matching it — matching the wrong one would replace a known drift with a confident one.
Not proposing a fix here
There is a real choice to make (restate the list in the comment and the shell; or factor the mirror into one shared script that both the workflow and a unit test can call, which would make it testable for the first time), and it is worth a look at whether the mirror still needs to be exact now that #5442 removed its publish-gating role.
⛔ No workflow was changed by this issue and no release was executed. Filed unassigned.
Found while implementing #5442 (npm-presence publish predicate). Out of that card's scope — filing rather than fixing, and #5442 deliberately leaves the detector untouched.
The reading
.github/workflows/changeset-release.yml'sDetect pending changesetsstep carries an explicit, load-bearing declaration:Measured against the copy actually installed in this repository —
node_modules/.pnpm/@changesets+read@1.0.0/node_modules/@changesets/read/dist/index.mjs— the reader does two things the mirror does not:and, separately, it also pulls in a whole second directory:
So the two disagree in both directions:
@changesets/read@1.0.0.changeset/AGENTS.md.changeset/CLAUDE.md.changeset/GEMINI.md.changeset/ReadMe.MD/i)'README.md'compare).changeset/pre/*.mdConfirmed empirically: with a
pre/probe.mdplusAGENTS.mdandCLAUDE.mdadded to a copy of the real.changeset/,readChangesetsreturned 161, countingpre/probe.mdand ignoring the other two.Why it is dormant right now, and why that is not reassuring
None of
.changeset/AGENTS.md,CLAUDE.md,GEMINI.md,.changeset/pre/or a non-canonically-cased README exists today, so the disagreement is currently unobservable. The first of those files anyone adds makes it live, and.changeset/AGENTS.mdis a plausible thing to add — it is exactly where per-directory agent instructions go in this repo's conventions, and the changesets reader ignores it because people do that.The blast radius depends on which predicate the release job is on:
.changeset/AGENTS.mdwould have madepending_changesetspermanentlytrueand skipped the release job on every push — silently, and indistinguishably from the defect 16 of 90 versioned releases never reached npm — a release-PR merge that lands with changesets pending versions again instead of publishing (npm is currently a release behind: repo 17.6.0, npm 17.5.0) #5442 was filed for.That is a real reduction in severity, but it does not make the declaration true, and the comment still tells the next reader that one name is the whole exclusion list.
Also worth checking, and not checked here
The mirror is declared against
changesets/action's bundled copy, not against this repository's@changesets/read@1.0.0. Those can be different versions with differentignoredMdFiles. The correct fix should establish which copy is authoritative for the mirror before matching it — matching the wrong one would replace a known drift with a confident one.Not proposing a fix here
There is a real choice to make (restate the list in the comment and the shell; or factor the mirror into one shared script that both the workflow and a unit test can call, which would make it testable for the first time), and it is worth a look at whether the mirror still needs to be exact now that #5442 removed its publish-gating role.
⛔ No workflow was changed by this issue and no release was executed. Filed unassigned.