Repository navigation
A trailing YAML comment hides a bump entry from all three changeset frontmatter parsers #7004
Description
Measured while adding --self-test fixtures to scripts/check-changeset-no-major.mjs (#6923). Not fixed there — it is a family-wide change across three scripts with a different consequence in each, so it is out of that PR's fix face. Filed per Prime Directive #10. Unclaimed.
The observation
All three changeset frontmatter parsers share one entry regex:
/^\s*["']?([^"':]+)["']?\s*:\s*([A-Za-z]+)\s*$/The bump group is anchored ([A-Za-z]+)\s*$, so anything after the bump word defeats the match. A trailing YAML comment is the reachable case.
Measured on origin/main @ d3e53f2d8, by extracting each function's real source text and loading it standalone (no top-level main executed), so this is the shipped code and not a re-implementation:
■ '"@objectstack/spec": major # keep'
check-empty-changeset.declaredBumpsIn : {"fenced":true,"packages":[]} <== judged EMPTY-FRONTMATTER
check-adr-0087.parseChangeset : []
check-changeset-no-major.majorPackagesIn : []
■ control, the same line without the comment
check-empty-changeset.declaredBumpsIn : {"fenced":true,"packages":["@objectstack/spec"]}
check-adr-0087.parseChangeset : [{"pkg":"@objectstack/spec","bump":"major"}]
check-changeset-no-major.majorPackagesIn : ["@objectstack/spec"]
And the ground truth it is measured against — @changesets/parse@0.4.3, the version this repo resolves:
trailing comment => [{"name":"@objectstack/spec","type":"major"}]
So changesets reads it as a real major. All three gates read it as nothing.
Why it is three different bugs, not one
| script | what it misses | direction |
|---|---|---|
check-changeset-no-major.mjs |
the major itself |
false GREEN — a whole-stack major promoted past a guard that printed a tick |
check-empty-changeset.mjs |
the whole declaration ⇒ the file reads as empty-frontmatter | false RED — a PR that added a perfectly valid changeset is rejected under #5471 |
check-adr-0087-registration.mjs |
signal (1) major in breakingDeclaration |
partial — signals (2) **BREAKING and (3) the ! summary can still carry it |
The false-RED one is the likelier to be hit first (an author writes a comment, the gate tells them their changeset is empty), and the false-GREEN one is the one that matters, because it is silent and it is aimed at the release train.
Extra force behind the "keep them identical" argument
All three functions carry a comment saying the three parsers deliberately read the same block and must agree. That claim is now true for leading blank lines (PR for #6923 aligned the third one) and it is true here too — they agree by all being wrong together. A family-wide fix keeps the claim true; fixing one alone would make it false again, which is why #6923 did not.
Impact, stated honestly
- No known instance. No changeset in the current stock (1552 files, measured) uses a trailing comment.
- The no-major half is additionally dormant today:
.changeset/pre.jsonis"mode": "pre", so that guard stands aside entirely (Observation:check-changeset-no-major.mjshas no--self-test, and its enforcing half is unexecuted on every run today (pre-mode) #6923). - The gap is reachable by an ordinary authoring act, and one of its two live directions rejects a valid PR.
Candidate dispositions (no conclusion presumed)
- Strip a trailing
#comment before matching, in all three parsers, in one PR — plus the fixture in each.check-changeset-no-major.mjsalready has a pinned assertion for the current behaviour that is written to be flipped rather than deleted when this lands. - Tighten instead of loosen: reject a frontmatter line that is entry-shaped but does not fully match, so an unparseable line is loud rather than invisible. Larger blast radius — worth measuring against the stock first.
- Rule the shape out of bounds for authors and say so in the prescription. Cheapest, but it is a convention with no enforcement, which is the class of thing this repo keeps converting into gates.
Leaning 1. Left to triage.
Activity
os-project-manager commentedon Aug 9, 2026
Triage (pass #2, 2026-08-09, registered on #6015): routed
domain:devx, gradedpm:queue. A trailing YAML comment silently hides a bump entry from all three changeset parsers — oncheck-changeset-no-major.mjsthat is a fail-open hole in the release train's major-bump guard (a hiddenmajorsails through). One shared regex fix (([A-Za-z]+)\s*(?:#.*)?$or strip-comment-first) applied to the family, with a trailing-comment fixture in each script's self-test; coordinate with #6923/#7005 (same files in flight — serialize or combine).Generated by Claude Code
os-project-manager commentedon Aug 9, 2026
Claiming. Session
session_01F8q5J1MQyocgtNspb15fSn(dev agent, dispatched by thedomain:devxPM seat). Branch:claude/issue-7004-changeset-trailing-comment.Plan: family-wide fix (disposition 1) across all three parsers in one PR, with a trailing-comment fixture in each self-test, re-verified against the real
@changesets/parse@0.4.3the way the filer measured it. Will flip (not delete) the pinned assertion #7008 left incheck-changeset-no-major.mjs. Coordinating with #7005, which is in flight on the same file.Generated by Claude Code
fix(scripts): give the objectui changeset digest objectstack-ai#6923'…