Uh oh!
There was an error while loading. Please reload this page.
fix(repo): declare the Node/pnpm floors the toolchain actually requires - #6311
Merged
Conversation
Root `engines` said `node: ">=22"` / `pnpm: ">=9"`, admitting Node 22.0-22.10
and pnpm 9 - versions `@changesets/cli@3` refuses outright. Nothing enforces the
declaration (no `engine-strict`, `packageManager` pinned to pnpm@10.31.0, every
workflow on `node-version: '22.x'`), so this was a false declaration rather than
an outage: a contributor picking a version by reading `engines` got a toolchain
combination that does not work, with no guard to say so.
Per the maintainer ruling of 2026-08-25, the minimal truthful correction:
"engines": { "node": ">=22.11", "pnpm": ">=10" }
The segmented range `^22.11 || ^24 || >=26` was considered and rejected as an
ongoing maintenance tax; `engine-strict=true` is ruled a separate follow-up card
and is deliberately NOT part of this change.
Second half - the surfaces that restate those floors:
- `QUICK_REFERENCE.md`'s pnpm row is pinned to `engines.pnpm` by
`scripts/__tests__/quick-reference-current-release-4143.test.ts`; regenerated
with `pnpm quick-reference:sync` (the Node row is derived as the first integer
of the range, so `>=22.11` still reads "≥ 22" and does not move).
- `CONTRIBUTING.md` claimed "Node.js 18.0 or higher" and a Node 18.x/20.x test
matrix; CI has no Node matrix at all - it shards the suite four ways on 22.x.
- `scripts/setup.sh`, the automated setup README points contributors at, checked
for Node >= 20 and pnpm >= 9. It now READS both floors out of `engines` rather
than repeating them, so the script cannot drift from the manifest again, and
it compares full versions (`sort -V`) instead of majors, which is what makes
a 22.11 floor expressible at all.
- `content/docs/guide/deployment.md` built this workspace with
`corepack prepare pnpm@9` and Netlify `NODE_VERSION = "20"` / `PNPM_VERSION = "9"`.
This was referenced Aug 25, 2026
os-warren
marked this pull request as ready for review
August 25, 2026 12:31
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 25, 2026
os-warren pushed a commit
that referenced
this pull request
Aug 25, 2026
objectui#6313: the pin at scripts/__tests__/quick-reference-current-release-4143.test.ts and the sync generator (scripts/sync-quick-reference-release.mjs) derived the Node/pnpm version floors with `match(/(\d+)/)?.[1]`, keeping only the leading integer group. Against root `engines.node: ">=22.11"` (objectui#5306 / PR #6311) that produced a floor of `22`, silently discarding the `.11` — so a row reading exactly `≥ 22` passed a pin whose entire premise is disagreeing with its own cited anchor. Both derivations now strip the comparator and keep the whole version string. `pnpm quick-reference:sync` regenerated the Node.js row to `≥ 22.11`. Added regression coverage pinning that a `≥ 22`-shaped row is now rejected and that a `≥ 220`-shaped row still is (objectui#4913), and corrected the test file's docblock sentence that had gone stale on the same anchor one decimal place up. No published package source changed; changeset declares no release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CZgmFFzqA9cX8tBMhvpFe
This was referenced Aug 25, 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 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#5306
Implements the maintainer ruling of 2026-08-25T05:50Z exactly, by the numbers rather than the option letters (the letters in the ruling do not line up with the letters in the analysis comment; the numbers govern):
⛔ The segmented range
^22.11 || ^24 || >=26was ruled out as an ongoing maintenance tax, and the jsdom^22.22.2measurement is not re-litigated here — the maintainer had it in front of them when they chose the minimal correction. ⛔engine-strict=trueis out of scope by the same ruling;.npmrcis untouched and #6264 is not edited.Verified before implementing:
>=22.11is not actively wrong. CI resolvesnode-version: '22.x'to 22.23.2 (PM's job-log read on this card), this container runs 22.22.2, andpnpm install --frozen-lockfileis clean under the new floor — quoted below. Nothing had to be excluded that CI or contributors actually use.What moved, and why each one is load-bearing
package.jsonnode: ">=22"→">=22.11",pnpm: ">=9"→">=10"QUICK_REFERENCE.md≥ 9→≥ 10scripts/__tests__/quick-reference-current-release-4143.test.tspins this row toengines.pnpm; without it the change is red. Regenerated withpnpm quick-reference:sync, not by hand.CONTRIBUTING.md:23-24CONTRIBUTING.md:378ci.ymlat all — the matrix isshard: [1,2,3,4], all onnode-version: '22.x'.scripts/setup.shengines; compares full versionsREADME.md:465points contributors at. It enforced Node ≥ 20 / pnpm ≥ 9 in hard-coded integers.content/docs/guide/deployment.mdcorepack prepare pnpm@9→pnpm@10; NetlifyNODE_VERSION20 → 22,PNPM_VERSION9 → 10pnpm-workspace.yaml,packages/,apps/and publishesapps/console/dist), so its toolchain versions are claims about the repo, not about a reader's app.QUICK_REFERENCE.mddeliberately does not move. Its pin derives the floor as the first integer of the range (engines.node.match(/(\d+)/)), so>=22.11still reads≥ 22. Changing that row to≥ 22.11would go red. Called out because "the Node floor changed but the Node row didn't" looks like an oversight and is not.Three edits outside
package.json+CONTRIBUTING.md, declared rather than slipped inscripts/setup.sh, thedeployment.mdversions and the pnpm half of theCONTRIBUTING.mdprerequisites are in-place fixes of the same defect this card exists to close (a stated Node/pnpm floor disagreeing with the toolchain), each with its correct form pinned by evidence already in the tree — the ruling's numbers,packageManager: pnpm@10.31.0, and the workflows' ownnode-version: '22.x'. None of them adds a verification surface. Naming them here because an unnamed drive-by fix is unreviewable sprawl.setup.shreads the floors instead of repeating them, which is the only version of this fix that cannot drift again:The old check compared majors (
cut -d'.' -f1), so a 22.11 floor was not even expressible in it —-lt 22would have accepted 22.0–22.10 while the message next to it claimed 22.11, re-creating this card's defect one order of magnitude smaller.Two premises in the dispatch, measured
CONTRIBUTING.mddoes say "Node.js 18.0 or higher" — line 23, and it is fixed here. The PM's grep found only line 378 because the line reads- **Node.js** 18.0 or higher: the bold markers sit between the name and the number, so a contiguousNode.js 18pattern misses it. Not "already fixed" — the pattern missed it.content/docssweep is NOT empty. Paired with a control (grep -rl pnpm content/docs→ 19 files of 184, so the sweep reaches the tree), four pages carry Node/pnpm version prose. One is fixed here (deployment.md); one is already correct and self-anchoring (content/docs/utilities/cli.mdx:300points at theenginesfield rather than restating it); two are deliberately not touched and filed instead — see below. My own first pattern also returned zero onQUICK_REFERENCE.md, for the same bold-marker reason, which is how a one-pattern zero reads as an empty sweep twice in a row on this card.⛔
content/docs/releases/untouched.content/docs/guide/release-notes.md's historicalNode.js >= 18compatibility matrix for the shipped v3.3.0 release untouched — rewriting a past release's stated compatibility misrepresents history.Deliberately left alone, filed instead
**bold**#6307 —content/docs/guide/quick-start.md:12-13andbuilding-crud-app.md:12stateNode.js 20+/pnpm 9+for a reader building their own app (pnpm create vite my-app), not this workspace. Measured: 0 of 40 packages declareengines, so those numbers restate no manifest in this tree. Rewriting them to 22.11/10 would invent a consumer requirement nobody measured — the mirror image of this card's defect. Filed with the reason no gate objected:doc-version-claims' separator class excludes*, so**Node.js** 20+is invisible to the ledger that exists to catch exactly this.setup-node@v4+node-version: 20+pnpm/action-setup, none of which this repo uses #6308 —ci-cd-pipeline.md:1626-1637teachesactions/setup-node@v4+node-version: 20+pnpm/action-setup@v4as "the existing pattern", against a repo with 27×setup-node@v7,node-version: '22.x'everywhere and zeropnpm/action-setup. Same family, but a multi-part snippet rewrite on a page carrying its own pin test — a separate change, not a rider.Cross-lane
content/docs/guide/, where PR #6082 (card #5923) is in flight. Checked immediately before pushing: #6082's file list iscontent/docs/guide/layout.mdonly — no overlap withdeployment.md.origin/mainwas re-fetched at push time and is still090927f4f(0 commits since my base), so nothing landed undercontent/docs/guide/or on rootpackage.jsonwhile I worked.Gates
All run on the final commit
12052c180, exit codes captured by redirect before any pipe, each quoted from the gate's own verdict line.pnpm install --frozen-lockfile(new floor)Lockfile is up to date, resolution step is skipped/Already up to date/Done in 2.6s using pnpm v10.31.0— no engine warningnode scripts/check-changeset-presence.mjs✅ No source of a released package changed in this range, so no changeset is owed.pnpm quick-reference:check✅ QUICK_REFERENCE.md's "Current Release" block already states every anchor.vitest run× 4 pin filesTest Files 4 passed (4)/Tests 139 passed (139)pnpm check:control-bytes✅ check-control-bytes: OK (scanned 5195 tracked text file(s); skipped 85 binary).pnpm check:shell-escape-residue✅ check-shell-escape-residue: OK (4/4 root(s) resolved …)pnpm check:doc-fences✅ check:doc-fences — every TypeScript block in 223 document(s) is fenced ts/tsx/typescript …pnpm docs:check-linksLinks are valid across 17 scan roots.Pin files run:
quick-reference-current-release-4143,sync-quick-reference-release,doc-version-claims,check-doc-links.No changeset, on the gate's verdict rather than on my judgement — nothing published changed. ⛔ No
skip-changesetlabel: #4912 records that no workflow reads it in this repo.Repo-wide
pnpm lintnarrowed, and the narrowing is measured, not assumed.eslint --format jsonover all five changed paths returns five results, every one of themFile ignored because no matching configuration was supplied.— eslint's own config, not my guess, says this diff contains zero files it judges (a.json, three.md, one.sh). No type-aware linting is configured, so no untouched file's verdict can move either. CI runs the full farm regardless.Reverse verification — the pin is live, not vacuously green
Committed first, then mutated, then restored (never against an uncommitted edit):
≥ 9. Mutation proven on disk by blob hash, not by an editor's exit code:git hash-objectmoved from0708d493d…(HEAD) toef00feb7f…, and the old/new row spellings counted 1/0.vitest run scripts/__tests__/quick-reference-current-release-4143.test.ts→ exit 1,Tests 2 failed | 6 passed, on exactly the right assertion:AssertionError: QUICK_REFERENCE.md's pnpm row must state exactly the floor "≥ 10" and the pinned "pnpm@10.31.0": expected [ '10.31.0', '≥9' ] to deeply equal [ '10.31.0', '≥10' ]git checkout HEAD -- QUICK_REFERENCE.md(namingHEAD, not a bare checkout that would re-read the polluted index), under anEXIT INT TERMtrap using an absolute repo root. Restore proven the same way as the mutation: blob hash back to0708d493d…,git diff HEADempty. Both legs re-run green afterwards.No build/
distleg applies here: the pin readsQUICK_REFERENCE.mdandpackage.jsonoff disk, so there is no compiled artifact that could keep a mutation alive or hide it.Generated by Claude Code