Repository navigation
fix(runtime): doctor fails Node 22.13.0 to 22.22.0, whose TextDecoder loses windows-1252 - #284
Merged
Merged
Conversation
… loses windows-1252 What changed: lib/runtime.mjs gains nodeDecodesWindows1252(version), a version rule beside nodeHonoursEnvProxy: false for 22.13.0 up to and including 22.22.0, true elsewhere; nodeParts now reads the patch number. nodeLine returns a second `fail` for those builds, after the major floor and before the odd-line warn, naming the defect (nodejs/node#60888: a page's euro signs, curly quotes and dashes captured as control characters, with no warning) and the fix (22.22.1 or newer on the 22 line, or 24). doctor's `node` finding carries it unchanged. The doctor test's Node-line case gains six rows (22.13.0, 22.21.0, 22.22.0 fail naming windows-1252 and 22.22.1; 22.12.0, 22.22.1, 22.23.3 pass). The README requirement reads "Node 22.22.1+ or 24+" in both READMEs, with the reason; the support-policy test that pins the requirement's presence accepts a patch-spelled floor. ADR-0159 records the decision and its index row; the runtime.mjs map row gains the clause; CHANGELOG Unreleased. The inventory is unchanged (rows in existing registrations, README stays 1787). Why: the kit decodes a page by its declared charset (G7), and that reading is Node's TextDecoder. On 22.13.0 through 22.22.0 it reads windows-1252 as Latin-1 (nodejs/node#60888, a regression after the line went LTS, fixed by nodejs/node#60893 and backported), so a capture taken on such a build silently lost 0x80-0x9F and was hashed into the ledger as fetched, while doctor reported the Node line as pass and the suite's two G7 tests went red (#282, found 2026-10-11 running the suite on a container's 22.22.0: 1785 passed, 2 failed, the same on an untouched main). CI never met it: setup-node resolves '22' to the newest 22.x, 22.23.3 that day. Alternatives set aside, recorded in ADR-0159: a table decoder for 0x80-0x9F behind a runtime probe (a second decoder beside the one the kit trusts; a feature under the freeze), refusing those builds in checkNode (would refuse doctor, the command that explains it), documenting only (doctor would still say READY on a machine whose captures are wrong). A Node release update, which the freeze admits (ADR-0117). What it touched: research-kit/lib/runtime.mjs (nodeParts, nodeDecodesWindows1252, nodeLine); research-kit/test/doctor.test.mjs (six rows in the Node-line test); research-kit/test/support-policy.test.mjs (the requirement regex); research-kit/README.md and README.md (the Node requirement, three places); docs/adr/0159-...md and docs/adr/README.md (the decision and its row); docs/ARCHITECTURE.md (the runtime.mjs row); CHANGELOG.md (Unreleased). No new command, flag, key, format or check: the `node` finding existed, it gains a second reason to fail. What you verified: - verified: the boundary, by hand on 2026-10-11 with `new TextDecoder('windows-1252').decode(Uint8Array.of(0x80, 0x93))` - 22.12.0 U+20AC U+201C (right); 22.13.0, 22.21.0, 22.22.0 U+0080 U+0093 (wrong); 22.22.1, 22.22.3, 22.23.0, 22.23.3, 24.21.0 right; 20.20.0 wrong. Each installed through nvm in this container. - verified: red first - with only the doctor test rows in place, `selftest.mjs doctor`: 65 passed, 1 failed, "22.13.0 decodes windows-1252 as Latin-1 and was reported as pass". Node 24.21.0 linux. - verified: after the fix, `selftest.mjs doctor runtime support-policy`: 98 passed, 0 failed; nodeLine by hand: 22.12.0 pass, 22.13.0 fail, 22.21.1 fail, 22.22.0 fail, 22.22.1 pass, 22.23.3 pass, 24.21.0 pass, 20.20.0 fail (the major floor). - verified: `doctor` on this container's 22.22.0 prints "fail node node 22.22.0 decodes windows-1252 pages as Latin-1 (nodejs/node#60888): ..." and exits 1; on 24.21.0 "pass node node 24.21.0". - verified: the full offline suite from the repository root on Node 24.21.0 linux: 1787 passed, 0 failed, 0 unsupported, 202.2 s, exit 0. - verified: git diff --check clean; the nine files LF-only. - untested when written: this commit's all-seven CI, and the installed commit gate (not installed in this container; the suite was run by hand instead). What you got wrong and fixed: mistake - the README's new requirement "Node 22.22.1+ or 24+" no longer matched the support-policy test's /Node 22\+/ check; where - research-kit/test/support-policy.test.mjs, "the prerequisites named in the policy are the ones the suite actually needs"; impact - one red test in the focused support-policy run before commit, nothing delivered affected; cause - the check pinned the spelling, not the fact; fix - the regex accepts a patch-spelled 22 floor, /Node 22(\.\d+)*\+/, with the reason in a comment; verified - `selftest.mjs support-policy` 20 passed, 0 failed, and the full suite below. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gg4isLfN2Ng16zr5DwTnH9
…252-floor-20261011 # Conflicts: # CHANGELOG.md
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 #282. Records ADR-0159.
What changed
lib/runtime.mjsgainsnodeDecodesWindows1252(version), a version rule besidenodeHonoursEnvProxy: false for Node 22.13.0 through 22.22.0, true elsewhere.nodeLinereturns a secondfailfor those builds, naming the defect (nodejs/node#60888) and the first good build (22.22.1 on the 22 line, or 24), sodoctor'snodefinding carries it. Both READMEs now require "Node 22.22.1+ or 24+" with the reason. Six rows in the doctor Node-line test; the support-policy test that pins the requirement's presence accepts a patch-spelled floor. ADR-0159 with its index row, theruntime.mjsmap row, and a CHANGELOG bullet are in the same commit. Inventory unchanged (1787).Why
The kit decodes a page by its declared charset, and that reading is Node's
TextDecoder. On 22.13.0 through 22.22.0 it readswindows-1252as Latin-1, so a capture taken on such a build silently lost its euro signs, curly quotes and dashes and was hashed into the ledger as fetched, whiledoctorsaid the Node line passed. CI never met it becausesetup-noderesolves'22'to the newest 22.x.Measured boundary (byte 0x80 under the
windows-1252label, each Node installed here):The hard floor every command refuses below stays at 22: it would refuse
doctor, the command that explains the finding. Rejected alternatives (a table decoder behind a runtime probe, refusing incheckNode, documenting only) are in the ADR.Verified
selftest.mjs doctor65 passed, 1 failed with only the test rows in place.selftest.mjs doctor runtime support-policy98 passed, 0 failed.doctoron this container's Node 22.22.0 prints the failingnodeline and exits 1; on 24.21.0 it passes.git diff --checkclean; nine files LF-only.Got wrong and fixed
The new README wording no longer matched the support-policy test's
/Node 22\+/check (one red in the focused run before commit). The regex now accepts a patch-spelled 22 floor, with the reason in a comment; the group and the full suite pass.Untested
This PR's all-seven CI.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Gg4isLfN2Ng16zr5DwTnH9
Generated by Claude Code