fix(scripts): derive check-changeset-no-major's level headline from the parsed declaration - #19163
Merged
os-try-charles merged 1 commit intoSep 19, 2026
Conversation
…he parsed declaration Past the `not-declared` lane the level verdict is decided by `refusable` and `offenders.length` alone — `declaration.value` plays no further part — so `clean`, `discharged` and `enforce` are each reachable on a `Clause-②: no (narrowing)` declaration. All three stated `yes` as a LITERAL, and `enforce` did it twice: once on stderr and once in the check-run annotation title, which is the only one of the three that crosses out of the step log. The rows underneath printed the true value and arm the whole time. That made the arm docblock's own rule false in the line a reader quotes: "a PR that declares `no (narrowing)` must not be reported as having declared `yes`". The parsed declaration now travels on the verdict as `declared`, beside `carrier` and for the same reason, and one exported speller (`declaredClause2`) renders all four headlines plus the `not-declared` one from it. The arm is carried through, so the headline is the declaration as written and a reader can grep the PR body for it. The `discharged` sentence derives its noun too — a declared narrowing is no longer "accounted for" as a widening. ⛔ No verdict and no exit code moves: 30 new pins assert the grade unchanged in both directions on all three lanes, with the `yes` and `yes (widening)` rows as the controls that matter — they are every other PR in the repo. Claude-Session: https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 19, 2026
os-try-charles
marked this pull request as ready for review
September 19, 2026 02:42
os-try-charles
deleted the
claude/issue-19008-headline-from-the-parsed-declaration
branch
September 19, 2026 03:06
This was referenced Sep 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #19008
Clause-②: no
What was wrong, as measured (not as assumed)
judgeLevelreaches thenot-declaredlane onvalue === 'no' && arm !== 'narrowing'. Past that lane the verdict is decided byrefusableandoffenders.lengthalone —declaration.valueplays no further part. So aClause-②: no (narrowing)declaration flows straight intoenforce,dischargedandclean, and every one of those headlines statedyesas a literal, while thereadingsrows two lines below printed the true value and arm.That made the arm docblock's own rule false in the one line a reader quotes:
The enumeration (the card named one branch; the tree has four literals in three lanes)
Every render branch reachable with
value === 'no' && arm === 'narrowing', driven through the realdeclarationFromPullRequest/judgeLevel/renderLevelat8b8258d91:cleanclean/ 0dischargeddischarged/ 0enforceenforce/ 1enforceenforce/ 1unreadable-diffunreadable-diff/ 1And the two lanes the dispatch left open, now measured rather than assumed:
not-measured-materialandnot-measured-mootare NOT reachable under a narrowing declaration. Both sit behinddeclaration?.value === null || undefined, and a narrowing declaration hasvalue === 'no'; the enumeration run confirms everyno (narrowing)row lands inenforce/discharged/clean/unreadable-diffand never in anot-measured-*.payload-unreadableandno-pull-requestare likewise unreachable:payload: falseis written by one place, which returnsvalue: nullbeside it.The fix
declared: { value, arm }, besidecarrierand for the same stated reason:renderLevelmust not assert a declaration it did not read.declaredClause2, renders all five headlines — the four that lied plusnot-declared, which was already correct and stays byte-identical on every input that reaches it. ⛔ No literal is left in a headline, so the rule above is now structural rather than per-branch.yes,yes (widening),no,no (narrowing)).dischargedsentence derives its noun too — a declared narrowing is no longer "accounted for" as a widening.value: nullspellsNOT MEASUREDrather than guessing. The three carried lanes cannot be reached with a null value, so a result arriving without one is a caller that dropped the axis, and check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690's direction is that such a run says so.judgeLeveldocblock stopped describingclean/discharged/enforceas "declared `yes`" — that was the same misstatement in the documentation half, in the same file.⛔ No
verdictand noexitCodemoves. This is a reporting repair; that is pinned, not asserted — see below.Both directions, pinned
New self-test battery
#19008: the level headline is the parsed declaration, not a literal, floor 30 cases (roster floor 19 → 20). Three lanes × both directions, with the lane identity asserted first so a headline pin cannot read a row it does not name:yesand ano (narrowing)declaration;clause-② \yes`/clause-② YES` appears nowhere — stdout, stderr and the annotation title alike;yesstill rendersyeson all three lanes (that is every other PR in this repo), andyes (widening)renders its arm;nostill stands the axis down at exit 0 on the very tree the narrowing refuses, and still prints thenoit always printed;declaredClause2unit rows, including bothNOT MEASUREDspellings.Reverse verification (ablation), at
4e3cbe10One-line mutation of
declaredClause2back to the literal this card removes, with the mutation proved on disk before the run and the restore proved by blob hash:⭐ The shape of that red is the evidence, not the count: the 12 that fired are all reporting pins (the three lanes' narrowing rows, the three
yes (widening)controls, the annotation title, thenolane, the speller). TheLANE IDENTITYandGRADING IS UNTOUCHEDpins stayed green through the mutation, and so did the bare-yescontrols — which is exactly the claim this PR makes: the literal was reporting, and only reporting.Acceptance notes
Observed while enumerating, ⛔ not changed here and ⛔ not filed as cards:
enforcerefusal's remedy prose still cites only the "purely additive widening takes AT LEAST `minor`" ruling and still says "raise the widened package to `minor`". Under a declared narrowing the reading that actually drove the verdict is the arm's launch-window breaking rule (thereadingsline says so: "a BREAKING change; during the launch window it ships `minor`"), and the package was narrowed, not widened. That is a different sentence from the headline this card governs, and correcting it is a judgement call about what the remedy should say — ⛔ not the mechanical derivation this card asked for. Reported to the PM with dedupe words rather than folded in here.readClause2Lineacceptsyes (narrowing)(onlyno+wideningis treated as a contradiction). The new speller renders it faithfully; whether that combination should be declarable at all is a parser question, not a reporting one.Scope
scripts/check-changeset-no-major.mjs, its--self-testincluded. No published surface, no runtime file, no workflow file.skip-changeset: nothing published moves.scripts/**ships in no package'sfiles[], so this PR releases nothing.Generated by Claude Code