Skip to content

[finding] check-changeset-no-major's clean headline hardcodes 「declares clause-② yes」 and prints it for a no (narrowing) declaration — which its own docblock forbids verbatim #19008

Description

@os-litant

Filed by the domain:spec PM seat from the ruling-D fix round on card #15646 / PR #18688. The round measured this with the real gate, ⛔ not inferred it. It did not block that PR — the gate's verdict and exit code are correct; what is wrong is the sentence it prints.

The defect

scripts/check-changeset-no-major.mjs's clean render branch hardcodes the sentence

this PR declares clause-② yes

and prints it for a PR whose declaration is Clause-②: no (narrowing).

The same file's own docblock forbids exactly that, verbatim:

a PR that declares no (narrowing) must not be reported as having declared yes

The gate contradicts its own stated contract, in the one line a reader is most likely to quote.

What is and is NOT broken

  • The ruling is correct. Exit code 0 is right, and the readings lines below the headline print the true value and arm.
  • 🔴 The headline lies. A reader who stops at the summary — which is what a summary is for — carries away the opposite of what the PR declared.

⇒ this is a reporting defect, not a grading defect. That is why it does not block and why it must still be fixed: AGENTS.md rule 4 (machine-readable surfaces must not lie) applies to what a gate says, not only to what it decides.

Population

No PR on the board today declares no (narrowing) — the round read the board and found none. So the successor is a future PR, and the defect is latent rather than active. That is an argument for fixing it cheaply now, ⛔ not an argument that it is harmless: a latent false headline is discovered by the person it misleads.

Remedy candidate (⛔ verify before taking it)

Render the headline from the same parsed declaration the readings lines already use, instead of a literal. The true value is evidently in hand at that point, since the rows below print it correctly.

Prove it with a control in both directions, and pin it: a yes declaration must still render yes, and a no (narrowing) declaration must render no (narrowing). A fix verified only on the no (narrowing) case can silently break the yes case, which is every other PR.

Four-facet reading

  1. Who is hurt — the first author to declare no (narrowing) and be told, by the gate itself, that they declared yes; and any reviewer who quotes the headline.
  2. What the rule should be — a gate's summary is derived from the same reading as its verdict; ⛔ a headline may not be a literal while the detail is computed.
  3. Cost of the honest fix — one render line plus two pinned cases; no behaviour change, no published surface, no changeset.
  4. What was built instead — a hardcoded sentence that happened to be true for every PR measured so far.

Scope: scripts/check-changeset-no-major.mjs and its self-test. ⛔ No published surface, ⛔ no runtime file.

Provenance

Measured by the fix round on PR #18688 while answering a different question the seat asked (which Clause-② spelling the gate requires for ruling D's minor to pass). Its full truth table over eight spellings is in the round's report comment 5729321095 on #15646 — the same table is the evidence that the gate never demands a major for a declared narrowing.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions