Uh oh!
There was an error while loading. Please reload this page.
test(gate): assert the doc ledger's Node claims against the workflows - #6450
Merged
Merged
Conversation
The version-claim ledger's `ci-cd-pipeline.md :: Node 22.x` entry was `anchored` -- the strongest class this file has -- and for an entry carrying no machine-checked field the `why` string IS the anchor: a reviewer re-runs the command it describes. Both halves of that sentence had gone false, and nothing in this repository was in a position to notice. Measured on c8ea8af: $ grep -rhoP 'node-version:\s*\K\S+' .github/workflows/ | sort | uniq -c 1 '22' 27 '22.x' $ grep -rlP 'node-version:\s*\S+' .github/workflows/ | wc -l 23 The reason named "the 14 node-version: 22.x declarations across .github/workflows" -- half the tree's 28, in a spelling one lane does not use (`half-state-patrol.yml:196` writes `'22'`). It then credited this page's own pin test with covering the line: `ci-cd-pipeline-doc.test.ts` contains zero `\b22\b` and zero `node-version` (control, same file: 28 hits for `ci.yml`). Control for the census, same sweep and same directory: 20 `corepack enable` steps across 14 files. The CLAIM stayed true -- the page says Node 22.x and CI runs Node 22. What rotted is the sentence a reader re-measures it by. Correcting 14 to 28 reinstalls the same mechanism with a newer number, and the number moves whenever a lane is added -- twice on the day this was written. So `workflowVersionKey` joins `skeletonDep` as the second way an entry names its anchor and has the comparison RUN: it names the GitHub-Actions key whose declarations across `.github/workflows` are the anchor, and the new workflow-version assertion reads them on every run and demands the page state their major. Three entries carry it, not one. `building-crud-app.md` and `quick-start.md` state the same literal against the same anchor and both counts were stale too (each said 26 of 27; the tree holds 27 of 28). None of the three reasons states a count any more. The comparison is on the MAJOR, not the spelling. A spelling comparison has no correct branch available: demanding `'22.x'` paints the `'22'` lane red for agreeing with every other lane, and accepting whichever spelling the docs use makes the anchor mean whatever the docs mean. A value `majorOf` cannot read is REPORTED rather than skipped, and the line parser is cross-checked against a counter that knows only the key -- a regex that quietly stops matching a spelling would otherwise subtract a lane and look like a smaller CI. Left uncovered on purpose, each recorded in the header: the neighbouring `node-version: 20` entry, whose sentence is true exactly when this comparison would be false; the two `pnpm 10.x` reasons, same class but anchored on the root `packageManager` field rather than a workflow key; and the page's own prose absolute at ci-cd-pipeline.md:1744. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CZgmFFzqA9cX8tBMhvpFe
os-warren
marked this pull request as ready for review
August 26, 2026 01:14
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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#6400
Disposition B, as ruled: the
node-versionset is derived from.github/workflowsand the doc literal is asserted against it, so the anchor is machine-checked rather than restated.The measurement, re-taken on this branch's own base (
c8ea8af9c)28 declarations across 23 files (of 30 workflow files, all
.yml). 27 spell it'22.x'; one spells it'22'.Control, same sweep, same directory: 20
corepack enablesteps across 14 files — a non-zero second reading, so this is not a grep that found nothing and was read as agreement.The entry claimed 14. The half-state-patrol lane's
'22'is a spelling that sentence does not admit at all.The entry's second half, measured — "this page already has its own pin test (ci-cd-pipeline-doc.test.ts)":
True of the page, false of the line. Nothing re-measured either half.
Was B feasible, and why — in terms of what the entry shape can express
Yes, and the entry shape needed one new field, not a new mechanism.
KNOWN_CLAIMSalready had the precedent:skeletonDep(objectui#3855) is exactly "name the machine-readable truth and have the comparison RUN here rather than re-verified by a reviewer". What it could not express is a truth that is not a dependency range in a manifest. So this adds the sibling fieldworkflowVersionKey, naming the GitHub-Actions key whose declarations across.github/workflowsare the anchor, plusdescribe('doc version claims - the workflow-version assertion').The two conditions the file's own header sets for anchoring were both measurable here:
node-version:declaration is. (This is the testreactfails in the header: the repo pins19.2.8exactly for test determinism while the page states a consumer's caret range.)What made it feasible rather than merely desirable is that the anchor is unanimous on the version. It is not unanimous on the spelling — see below, which is where the design decision actually sat.
The
'22'outlier — handled by normalising on the MAJORmajorOfreduces every declaration to its major, and the comparison happens there. A spelling comparison has no correct branch available to it:'22.x'paintshalf-state-patrol.ymlred for agreeing with every other lane;The major is the fact the doc sentence states; the spelling is how one YAML file happened to write it.
This is load-bearing rather than cosmetic, and mutation A below proves it: the reverse-verification was run by moving that lane. A derivation admitting only
'22.x'would have stayed green while the outlier drifted anywhere at all — a new blind spot, shipped by a card about blind spots.Two further anti-blind-spot measures, both because a line regex's real risk is not matching at all:
majorOfcannot read (a matrix expression, anltsalias) is reported, not skipped — a parser that silently drops what it cannot read is how an anchor goes vacuous while every gate stays green;Scope: three entries, not one — declared
The card names
ci-cd-pipeline.md :: Node 22.x. Two more entries state the same literal against the same anchor, and both of their counts were also stale, measured on this base:ci-cd-pipeline.md :: Node 22.x22.x'22.x'building-crud-app.md :: Node 22.x'22.x'and the 27th reads'22'"quick-start.md :: Node 22.x'22.x')"All three now carry
workflowVersionKey: 'node-version'and none of their reasons states a count any more. Building a guard and then leaving two members of its own domain hand-written would have left the identical defect one line from its own repair — thesample-misfiling failure this file's header already records. Same defect class, same file, same gate family, one-line mechanical change each, evidence pinned by the derivation itself.Two-direction proof
The assertion must be able to go red, or it is prose with extra steps. Both mutations restored via
git checkout HEAD -- ABSOLUTE-PATHundertrap … EXIT INT TERM, and restore proven by hash, not by exit code.The two mutations exercise different branches: A the unanimity check (and, decisively, that the
'22'lane is inside the anchor set — note"22.x" in 27, i.e. the 28th was the mutated outlier), B the page-vs-anchor comparison the card is actually about.The red direction is also pinned permanently, not just demonstrated once:
it('treats two spellings as one anchor, and goes red when a lane and a page disagree')plants a temp workflow directory with'22.x'+'22'(one anchor), then a third major (split), then an unreadable value (reported, not dropped). A green anchor assertion looks exactly like an assertion that compared nothing — the failure this card was filed about — so the fixture is the witness, in the same spirit as objectui#6307's and objectui#6409's.Nothing here is a build/
distablation: this gate reads source files directly, so there is nodistleg to rebuild or preflight.Gates run — all at the final commit
2bc962f7epnpm exec vitest run scripts/__tests__/(whole tree, as instructed)pnpm type-check:scripts--listFilesconfirmsdoc-version-claims.test.tsis in the compiled set (1 hit), so this is not the "typecheck excludes tests" non-measurementpnpm lint:rootpnpm exec eslint scripts --format jsonpnpm check:control-bytesOK (scanned 5326 tracked text file(s)), exit 0[\x20-\x7e])node scripts/check-changeset-presence.mjsHeavy runs went through the container's shared verify lock;
VERDICT command-exit 0 · held the lock 57s · waited 0s.Declared narrowing: repo-wide
pnpm lint(turbo run lint, the per-package fan-out) was not run locally. My diff is entirely underscripts/and.changeset/, whichturbo run lintstructurally cannot reach —scripts/is not a workspace package, which is the same facttsconfig.scripts.json's own header records. The scope that does cover it,lint:root, was run to completion, andeslint scriptswas run separately with the file list read from eslint's own resolution rather than from my guess about which files count. Type-aware linting is not enabled ineslint.config.js(noproject,projectServiceorparserOptionsentry), so this diff cannot move the verdict on any file it does not touch. CI runs the full farm regardless.Out-of-scope findings, filed unassigned
pnpm 10.xreasons state 17corepack enablesteps across 12 workflow files; the tree has 20 across 14 #6447 — the same class, one entry over: the twopnpm 10.xreasons state 17corepack enablesteps across 12 workflow files; the tree has 20 across 14. Not repaired here because its anchor is a different source (the rootpackageManagerfield, not a workflow key), so it needs a second derivation rather than one more field on this one.ci-cd-pipeline.mdsays "every workflow declares'22.x'" — one lane declares'22', and that lane is the reason #6400's anchor normalises on the major #6448 —ci-cd-pipeline.md:1744says "every workflow declares'22.x'", which the one'22'lane falsifies. A spelling claim on a doc surface, and this assertion is blind to spelling by construction — so it is genuinely uncovered, not merely unfixed.Deliberately left uncovered, recorded in the header
ci-cd-pipeline.md :: node-version: 20(objectui#6409's entry) sits one line above and cannot share this field: it cites a value the workflows do not declare, so its sentence is true exactly when this comparison would be false. It stays reviewer-checked on purpose — and itswhyalready carried no count, which is the instinct this card generalised. objectui#6409's keyed recogniser and its pre-fix-recogniser fixture are untouched.Changeset
.changeset/6400-workflow-version-anchor.md, empty frontmatter — the explicit "not releasing" declaration. No package source changed. (This repo has noskip-changesetlabel; the empty-frontmatter changeset is the first-class equivalent here.)Generated by Claude Code