fix(scripts): guard the base side of an R row against .changeset/README.md in check-changeset-no-major - #7157
Conversation
…EADME.md` (#7107) `check-changeset-no-major.mjs` applied `isChangesetFile()` to the HEAD path only. The BASE path -- `fields[1]`, the pre-rename name an `R` row is read at -- was handed straight to `git show`. Git pairs renames by CONTENT rather than by name, so under the `.changeset/*.md` pathspec an `R` row can legitimately arrive as `.changeset/README.md -> .changeset/x.md`; the majors README appears to declare would then be subtracted from the head file's, reporting a brand-new whole-stack major as inherited. Dormant today (the real README carries no frontmatter fence, so `majorPackagesIn` returns `[]`), and the two siblings already carry this guard since #7106. The self-test fixture therefore commits a major-shaped README so the unguarded path really subtracts something: with the guard the row is `introduced`, without it the same row is `exempt`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F8q5J1MQyocgtNspb15fSn
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
ACCEPT — devx PM seat. Hold released, flipping ready and arming auto-merge. Gates re-read branch-filtered and named, not counted: The fixture is the reason this PR is worth accepting, and it does the hard thing. The defect is dormant — the real
And the ablation was run with the direction predicted first — three failures, exactly the three new assertions, including the Two deviations, both accepted and both correct: the fixture keeps base and head byte-identical where the siblings vary the head body (for this gate the subtraction is per-package, so identical content makes it total rather than partial), and it followed this file's em-dash convention rather than the siblings' ⛔ Out-of-scope finding filed unassigned as #7164 — the older Generated by Claude Code |
.changeset/README.md on an R row (dormant)
#7107
Fixes #7107
What was wrong
scripts/check-changeset-no-major.mjsappliedisChangesetFile()to the head path only:basePath— the pre-rename name anRrow is read at, and the whole reasonRis readable — was then handed straight togit showwith no guard of its own. Git pairs renames by content, not by name, and the pathspec is.changeset/*.md, which.changeset/README.mdmatches. So anRrow can legitimately arrive as.changeset/README.mdpaired with.changeset/x.md, and the majors README appears to declare get subtracted from the head file's majors — reporting a brand-new whole-stack major as exempt rather than introduced. That is this gate's expensive direction.The two siblings PR #7106 fixed (
check-empty-changeset.mjs,check-adr-0087-registration.mjs) already carryisChangesetFile(basePath)explicitly. This file is the third member of the family; the gap was not a missing helper but a guard applied to one of the two paths.The change
One condition, transcribed from the siblings rather than invented:
For
Mthe guard is a no-op —basePathis the path already accepted on the line above. OnlyRcan reach it with a different name.The fixture, and why it is not vacuous
This defect is dormant. The real
.changeset/README.mdis boilerplate with no frontmatter fence, somajorPackagesIn()returns[]on it and nothing is subtracted today. A careless fixture would therefore pass with or without the guard and would certify the hole. So the new self-test case:.changeset/README.mdat the branch point, so the unguarded path really has something to subtract;R, matching the whole row against/^R\d+\told\tnew$/via a newrenameRowhelper (the same shape both siblings use) — too small a body and git degrades the pair to add-plus-delete, and the case would silently be testing an ordinaryA;Measured control, git 2.43.0:
Ablation (direction predicted before running)
Prediction: removing the guard makes
alreadybecome['@objectstack/spec'],addedempties, and the row flips fromintroducedtoexempt— so exactly the three new assertions go red and nothing else moves.With the guard (this PR):
With the guard deleted (the one-line revert, run on a copy of the script so the real file stayed untouched):
Predicted direction confirmed, including the
exemptvalue the defect produces. Assertion count 113 onorigin/mainto 117 here — the four assertions added, no case re-spelled or removed.Verification
pnpm check:changeset-gate-self-tests(the exact step lint.yml runs) — all three family gates green: 105 / 142 / 117 assertions.pnpm check:nul-bytes— 75 self-test assertions plus a clean 6592-file scan.npx eslint scripts/check-changeset-no-major.mjs --no-inline-config— exit 0.node scripts/check-changeset-no-major.mjs --base origin/mainon this branch —✓ This diff introduces no major bump.Changeset
None, deliberately: a
scripts/-only diff releases no package.skip-changesetapplied instead, matching the precedent of #7048, #7104 and #7106.Generated by Claude Code