Skip to content

Commit 5d0ee8f

Browse files
fix(scripts): derive check-changeset-no-major's level headline from the parsed declaration (#19163)
Fixes #19008 Clause-②: no ## What was wrong, as measured (not as assumed) `judgeLevel` reaches the `not-declared` lane on `value === 'no' && arm !== 'narrowing'`. **Past that lane the verdict is decided by `refusable` and `offenders.length` alone — `declaration.value` plays no further part.** So a `Clause-②: no (narrowing)` declaration flows straight into `enforce`, `discharged` and `clean`, and every one of those headlines stated `yes` as a literal, while the `readings` rows 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: > a PR that declares `no (narrowing)` must not be reported as having declared `yes` ### 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 real `declarationFromPullRequest` / `judgeLevel` / `renderLevel` at `8b8258d91`: | reachable branch | channel | what it said before | verdict / exit | |---|---|---|---| | `clean` | stdout | "declares clause-② \`yes\`" 🔴 | `clean` / 0 | | `discharged` | stdout | "declares clause-② \`yes\` … the declared **widening** is accounted for" 🔴 (two claims, both false) | `discharged` / 0 | | `enforce` | **stderr** | "This PR declares clause-② **YES**" 🔴 | `enforce` / 1 | | `enforce` | **check-run annotation title** | "clause-② declares **YES** while no moved package is graded \`minor\`" 🔴 — ⭐ **a fourth literal the card did not name, and the only one that crosses out of the step log** | `enforce` / 1 | | `unreadable-diff` | stderr | makes no claim about the declaration — correct as written | `unreadable-diff` / 1 | And the two lanes the dispatch left open, now measured rather than assumed: **`not-measured-material` and `not-measured-moot` are NOT reachable under a narrowing declaration.** Both sit behind `declaration?.value === null || undefined`, and a narrowing declaration has `value === 'no'`; the enumeration run confirms every `no (narrowing)` row lands in `enforce` / `discharged` / `clean` / `unreadable-diff` and never in a `not-measured-*`. `payload-unreadable` and `no-pull-request` are likewise unreachable: `payload: false` is written by one place, which returns `value: null` beside it. ## The fix 1. **The parsed declaration travels on the verdict** as `declared: { value, arm }`, beside `carrier` and for the same stated reason: `renderLevel` must not assert a declaration it did not read. 2. **One exported speller, `declaredClause2`, renders all five headlines** — the four that lied plus `not-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. 3. **The arm is carried through**, so the headline is *the declaration as written* and a reader can grep the PR body for the string the gate printed (`yes`, `yes (widening)`, `no`, `no (narrowing)`). 4. **The `discharged` sentence derives its noun too** — a declared narrowing is no longer "accounted for" as a *widening*. 5. `value: null` spells `NOT MEASURED` rather 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 #4690's direction is that such a run says so. 6. The verdict table in the `judgeLevel` docblock stopped describing `clean` / `discharged` / `enforce` as "declared \`yes\`" — that was the same misstatement in the documentation half, in the same file. ⛔ **No `verdict` and no `exitCode` moves.** 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: - each lane reaches its own verdict on **both** a `yes` and a `no (narrowing)` declaration; - each lane's exit code is **unchanged in both directions** (the grading-is-untouched pin); - on a narrowing: the true declaration appears, and `clause-② \`yes\`` / `clause-② YES` appears **nowhere** — stdout, stderr and the annotation title alike; - ⛔ **controls:** a bare `yes` still renders `yes` on all three lanes (that is every other PR in this repo), and `yes (widening)` renders its arm; - the annotation title is pinned separately, still exactly one, still one line; - a bare `no` still stands the axis down at exit 0 on the very tree the narrowing refuses, and still prints the `no` it always printed; - `declaredClause2` unit rows, including both `NOT MEASURED` spellings. ### Reverse verification (ablation), at `4e3cbe10` One-line mutation of `declaredClause2` back to the literal this card removes, with the mutation proved on disk before the run and the restore proved by blob hash: ``` HEAD blob = 4d72a0f ON-DISK PROOF: removed-text count 1 -> 0 ; injected-text count 0 -> 1 mutated blob = aea6bdf92c0249d83e0714f7513f82322701e004 (differs from HEAD) VERDICT ablation-exit=1 (12 failures) restored blob = 4d72a0f RESTORE PROVED: blob hash matches HEAD and `git diff HEAD` is empty VERDICT restore-leg-exit=0 ``` ⭐ 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, the `no` lane, the speller). The `LANE IDENTITY` and `GRADING IS UNTOUCHED` pins stayed **green** through the mutation, and so did the bare-`yes` controls — 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: - The `enforce` refusal'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 (the `readings` line 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. - `readClause2Line` accepts `yes (narrowing)` (only `no` + `widening` is 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 - One file: `scripts/check-changeset-no-major.mjs`, its `--self-test` included. No published surface, no runtime file, no workflow file. - **`skip-changeset`**: nothing published moves. `scripts/**` ships in no package's `files[]`, so this PR releases nothing. --- _Generated by [Claude Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8f42b17 commit 5d0ee8f

1 file changed

Lines changed: 190 additions & 19 deletions

File tree

0 commit comments

Comments
 (0)