Repository navigation
feat(scripts): read one changeset against itself, and date the contradiction - #9850
Merged
os-try-charles merged 3 commits intoSep 18, 2026
Merged
Conversation
…diction (objectui#9841) A `.changeset/*.md` that declares a package in its front matter while its body says that package did not move contradicts itself, and both halves publish verbatim into that package's CHANGELOG. Four structural gates read `.changeset/` and all four judge the front matter; the two readings already in `check-changeset-claims.mjs` judge a body against a diff. Nobody read the two halves of one file against each other. The falsification pass the card demanded ran first, and it CORRECTS the card. Measured over every pending changeset in this tree plus every released CHANGELOG entry beside a `package.json`, the card's own proposed coordinate — "a sentence that names a declared package adjacent to a negation of change" — pairs repeatedly and every single pairing is legitimate: it negates an ASPECT of the package (a face, a surface, an export, one symbol, one file), never the package. Building that coordinate would have shipped a reader that is wrong every time it speaks. Requiring the negation to attach DIRECTLY to a bare package spelling, with nothing between them but a copula, drops all of them and keeps the attested instance. `--census` re-derives both numbers rather than recording either. The BORN FALSE / WENT FALSE split is dated from the branch's own revisions, because it cannot be read off the head. At `2bc8fd12e2` the carded changeset already said its sentence and declared one package; at `21896172a9` the same commit that moved 62 lines in `packages/types/src/overlay.ts` added the second declaration. Against the merge base the net diff shows the file simply added, with both halves present, which reads as born false. It was not. A range that carries no revision of the claim is reported UNDATED rather than guessed at. Two distinct floors, one level apart, neither printing what the other prints and neither printing the clean tick: an empty corpus, and a corpus read whose bodies declare no bump. The reading is hermetic by construction — it takes no environment, no event payload and no pull request body — and the pin asserts its section is byte-identical with `GITHUB_EVENT_PATH` poisoned. Report-only and exit 0 throughout, inside the posture this gate already has. No new gate, no new npm script, no new CI context. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz
…ainst (objectui#9841) The branch walk alone gets the oldest WENT FALSE there is exactly backwards. A changeset can sit pending for weeks carrying a true sentence, and a later change falsifies it by adding one line to its front matter — the shape `check-changeset-overwrite.mjs` calls its case 2, so it is a case this repository already expects to see. Walking only `base..head` finds the single commit that added that line, sees the declaration in it, and reports BORN FALSE: an accusation that the author wrote something untrue, weeks before the branch making it existed. That is precisely the misreading this card forbids. The base revision is read first. If the claim is already standing there, the base's own front matter decides the verdict, and the branch walk is reached only for a claim this change itself brought. Pinned by a fixture whose changeset exists at the base declaring another package and is falsified by one front-matter line at the head. The pin reads the verdict off the finding line, so a reader that answered `born` here fails it rather than satisfying a substring search. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz
…cided (objectui#9841) The comment step decides whether to CREATE the claim comment from a sum of finding counts, and that sum carried two of the gate's three readings. A run whose only finding was a self-contradiction rendered its comment and then never posted it: measured, rendered, delivered nowhere. objectui#9140 put that channel at zero answers out of four when findings went to the job log, which is why the delivery exists at all, so shipping a third reading into a sum that drops it would have been that ruling undone on purpose. One more term, same expression, same step. No new step, job, permission or context, and the doc-parity pin is untouched because nothing here adds a command. The pin is asserted AS ITS OWN TERM rather than as the whole sum. A pin matching the sum verbatim reddens on a harmless rewording, and it gets repaired by pasting whatever the file now says — which is how a dropped term gets blessed. The new one goes red for exactly one reason: this reading stopped being counted. A third case walks all three terms, so the next reading's author is told, where they will be standing, that a reading without a term here reaches nobody. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015h79niBMyoB1xcaQje3uiz
os-try-charles
marked this pull request as ready for review
September 18, 2026 10:43
os-try-charles
deleted the
claude/issue-9841-changeset-self-contradiction
branch
September 18, 2026 11:03
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 #9841
A
.changeset/*.mdthat declares a package in its front matter while its own body says that package did not move contradicts itself, and both halves publish verbatim into that package's CHANGELOG. The four structural changeset gates all judge the front matter; the two readings already incheck-changeset-claims.mjsjudge a body against a diff. Nobody read the two halves of one file against each other.The falsification pass ran FIRST, and it corrects the card
The card made this the first deliverable and said outright that its filer had not run it. It is run here, both halves, each with a positive control taken before its zeros were believed.
Pending corpus — every
.changeset/*.mdin this tree: 1,686 files read, 1,153 of them publishing a body (the rest declare no bump and reach no CHANGELOG).Released corpus — every
CHANGELOG.mdwith apackage.jsonbeside it: 42 files, 3,279 released version sections, 24,557 entries, versions 0.0.1 through 17.6.0. 883 of those entries carry a negation-of-change word.types,layout)⭐ Every one of those 19 pairings at the card's coordinate is LEGITIMATE. Read one at a time, they all negate an ASPECT of the package and never the package: «
@object-ui/fieldsre-exports all four names unchanged», «Both are internal to@object-ui/app-shell; no package export moves», «packages/app-shelltype-checks unchanged», «@object-ui/console's/resolver is unchanged». ⇒ the card's step 2 as written is the noise its own falsification test was looking for, and it is not built here. Requiring the negation to ATTACH to the package drops all 19 and keeps the attested instance.Positive controls, both corpora. Planting the carded instance verbatim moves every counter: pending 1,686 → 1,687, publishing 1,153 → 1,154, card's coordinate 11 → 12, attached 0 → 1 and it names the clause. Injecting the same clause as one released entry moves the released side 24,557 → 24,558 and attached 0 → 1. Both plants were removed and
git diff HEADverified empty.What landed
A third reading in the same script, in the same report-only, exit-0 posture. ⛔ No new gate, ⛔ no new npm script, ⛔ no new CI context, so no command-parity doc edit.
.changeset/*.mdthis change adds or modifies, read out of this tree.packages/types, never@object-ui/types, so a reading that knew only npm names would have been silent on the one artefact it exists for.--censusre-derives both coordinates over whatever corpus the tree carries, so no number above is written down anywhere (AGENTS.md 完善设计器的每一个细节 #9).BORN FALSE vs WENT FALSE, dated from the branch's own revisions
⛔ It cannot be read off the head, and this is measured on the artefact rather than assumed:
2bc8fd12e2, the commit that ADDED the carded changeset, the body already said «packages/typesis untouched» and the front matter declared@object-ui/componentsand nothing else — the sentence was true;21896172a9, the same commit that moved 62 lines inpackages/types/src/overlay.ts(+35 −27, verified on that commit) added'@object-ui/types': patchto that same front matter.Against the merge base the net diff shows the file simply ADDED with both halves present, which reads as born false. It was not. So the verdict is dated from the revisions of that file, and a range carrying none of them is reported UNDATED, ⛔ never defaulted to either verdict.
check-changeset-overwrite.mjscalls its case 2, so this repository already expects to see it. Walking onlybase..headfinds the single commit that added that line, sees the declaration in it, and reports BORN FALSE — accusing an author of writing something untrue weeks before the branch making it existed, which is the exact misreading this card forbids, on the case where the sentence most obviously stood on its own. If the claim is already standing at the base, the base's own front matter decides; the branch walk is reached only for a claim this change itself brought.The two mandated defences
Two distinct floors (objectui#9744). A
0from a reader that read nothing and a0from a clean corpus are the same character. Floor one: this change adds and modifies no changeset. Floor two, one level in: a corpus was read but every body declares no bump, so there is no front matter for a body to contradict. Neither prints what the other prints, neither prints the clean tick, and each is pinned withnot.toContainagainst the other two.Hermeticity is structural, not conventional. This reading takes NO ambient input: no
GITHUB_EVENT_PATH, no pull request body, no environment. Its corpus isgit diff --name-onlyunder the root it was given. The pin runs the same fixture twice — once clean, once withGITHUB_EVENT_PATHpointing at a payload whose body is the carded contradiction verbatim — and asserts the section is byte-identical, plus asserts the variable WAS live for that run (the born-false reading above it does read it and its report moves), so the comparison cannot be vacuous.Acceptance notes
The delivery seam is CLOSED, under an explicit surface extension. The first round stopped at the file-surface boundary and reported that
changeset-presence.ymldecided comment creation fromfindings.length + bornFalse.length, so a self-contradiction-only finding rendered its comment and was never posted. The seat extended the declared surface to that one file and the third commit adds one term to that one sum — ⛔ no new step, job, permission or context, and the command-parity doc pin is untouched because nothing here adds a command. The declared surface for this work is nowscripts/,scripts/__tests__/,.changeset/and.github/workflows/changeset-presence.yml, and nothing outside it was touched.The new expression, verbatim:
⭐ The pin asserts the new term on its own, ⛔ never the sum verbatim. A pin matching the whole sum reddens on a harmless rewording, and it gets repaired by pasting whatever the file now says — which is how a dropped term gets blessed. A third case walks all three terms, so the next reading's author is told, where they will be standing, that a reading without a term here reaches nobody.
The known false positive, documented instead of carved out: a body that declares a package to carry a DEPENDENT bump and says so — «
@object-ui/reactis unchanged; it bumps because core's types moved». That sentence pairs, and it is honest. It occurs zero times in the corpus--censusreads, and a carve-out for a shape nobody writes is a hole nobody is watching.The first commit shipped a dating defect and the second fixes it, kept as two commits rather than squashed in place. The gap is worth the record: the branch-walk-only reading passed all seven controls and every pin in the suite, and was wrong on the case the card cares most about. Leg C of the ablation below is the pin that now holds it.
One pre-existing assertion moved rather than widened: the born-false hermeticity case counted
PASSlines across the WHOLE output. A third control suite prints its own, so that count is now scoped to the born-false section.noted, not filed:
--auditand--censusare two population readings in one script with no shared frame; a future round that adds a fourth reading will want one.Verification
pnpm exec vitest runover all ten suites that readchangeset-presence.ymlci-cd-pipeline-doc.test.ts, which is what says no command-parity doc edit is owedpnpm type-check:scriptspnpm lint:root(the wired task that reachesscripts/;turbo run lintdepends on it)pnpm check:changeset-claimspnpm check:control-bytespnpm check:pending-changeset-literalspnpm check:new-line-citationspnpm check:unreferenced-sourcespnpm check:test-path-rootspnpm check:shell-escape-residuepnpm check:comment-mask-corpusnode scripts/check-changeset-presence.mjspnpm check:required-check-set·pnpm check:merge-queue-head·pnpm check:governed-queue-guardnode scripts/check-governed-queue-guard.mjs --test(both rounds' paths).github/workflows/**is not one of the five ruled surfacesAblation — the split's pins actually redden, three legs. Each leg runs from a committed tree, mutates one deciding line, proves the mutation reached disk by blob hash AND by occurrence counts (deciding line 1 → 0, injected marker 0 → 1), re-runs the suite, then restores with
git checkout HEAD --and re-verifies by blob hash and an emptygit diff HEAD.2dd38efbbdateClaimcollapsed to'born'(blob5b05a3c6→deaf6adb)WENT FALSEpin fails — 1 failed / 106 passed2dd38efbbdateClaimcollapsed to'went'(blob5b05a3c6→9b1ad4d2)BORN FALSEpin fails — 1 failed / 106 passed74d723cb329919d26→2ac4bd83)6ca8d4259selfContradictionterm dropped from the workflow's comment gate (blobcb79f55d→6d2f14ae)⭐ Leg D is the one worth reading: the ablated sum is still valid JavaScript and still counts two of the three readings, so it looks healthy — and that is exactly the shape a whole-sum pin blesses. The born-false pin staying green through it is what shows the new pin is specific rather than a blanket string match. Legs A–C redden exactly one assertion each and move nothing else, so the distinction is pinned by the verdict itself and ⛔ not by a count that happens to move. The verdicts are read off the finding lines rather than searched for in the section, because the section's closing prose explains what a WENT FALSE verdict is and is not — a substring search there would have reported a verdict never reached, and it did on the first run.
Session reference, as prose because a footer does not survive a body edit here:
session_015h79niBMyoB1xcaQje3uiz.Generated by Claude Code