Skip to content

toolchain(node): promote Node 24 LTS baseline and qualify Node 26 before supported-lane adoption #569

Description

@qnbs

Context

WorldScript Studio currently declares:

"engines": {
  "node": ">=22.0.0",
  "pnpm": "11.22.0"
}

and required CI intentionally exercises both:

Node 22
Node 24

The matrix was deliberately made explicit rather than using node: current, so a new Node major cannot silently change CI without a repository decision.

As of 2026-09-01 the upstream lifecycle has moved on:

Node 24 = current LTS line
Node 22 = older LTS / maintenance-era supported line
Node 26 = Current release line, not yet the repository baseline

Official Node release information:
https://nodejs.org/en/blog/release

Node 22→24 migration guidance:
https://nodejs.org/en/blog/migrations/v22-to-v24

This issue owns WorldScript's Node support lifecycle and adoption gates, not general CI-cost optimization. Matrix cost/duplication remains #550.

Goal

  1. Make Node 24 the intentional developer/build-toolchain baseline once exact repository compatibility is proven.
  2. Preserve Node 22 compatibility only as long as it has an explicit support reason and meaningful evidence value.
  3. Add a non-blocking Node 26 qualification lane while it is Current.
  4. Promote Node 26 into the supported/required matrix only after it reaches an appropriate support maturity and WorldScript has proven the entire toolchain on it.

Node is a build/test/tooling runtime here; this issue does not change browser, Tauri WebView, Qt, or end-user JavaScript runtime support.


Current-state inventory

Before changing support policy, find every Node-version authority:

  • .nvmrc;
  • package.json#engines.node;
  • package.json#packageManager / Corepack expectations;
  • .github/actions/setup/action.yml;
  • CI quality matrix;
  • build/release/deploy workflows;
  • Vercel/Pages/Cloudflare/serverless configuration where Node affects build or runtime;
  • hooks and local CI scripts;
  • Docker images;
  • developer docs / CLAUDE.md / contributing guidance;
  • any package with a stricter Node engine than the root.

Produce one matrix:

Surface Current Node Authority Required? Target policy
local development
PR quality gate 22/24 CI yes
production web build
release tooling
serverless/API
Docker

No hidden runtime should continue using a floating major.


Phase A — Node 24 baseline

Run the complete repository toolchain with Node 24 as the default/baseline:

pnpm install --frozen-lockfile
pnpm install / fresh resolve in a disposable environment
pnpm run toolchain:check
pnpm run deps:verify
pnpm run lint
pnpm run typecheck
pnpm run test / coverage gate
pnpm run build
Storybook build/test
Playwright/E2E lanes
Lighthouse/VRT where Node executes the harness
release/build scripts
native-readiness / repository governance scripts

Particularly verify Node-24-specific behavior currently worked around by:

NODE_OPTIONS=--no-experimental-webstorage

Do not preserve compatibility flags forever without proving whether stable Node 24 still requires them. Conversely, do not remove them merely because the flag looks old.

Baseline authority

If evidence is clean, update the canonical local-development version (for example .nvmrc) to the selected Node 24 LTS patch/major policy.

Choose deliberately between:

PIN_EXACT_PATCH
PIN_LTS_MAJOR

according to how repository setup and CI already manage patch updates. Document the choice.


Node 22 support decision

Do not remove Node 22 merely to save CI minutes.

Inventory whether Node 22 is still needed for:

  • contributors/developer policy;
  • deployment provider runtime;
  • build portability;
  • downstream tooling;
  • release or packaging infrastructure;
  • compatibility evidence that has caught real defects.

Then classify:

KEEP_REQUIRED
KEEP_ADVISORY
RETIRE_WITH_NOTICE

If retiring Node 22:


Phase B — Node 26 qualification

While Node 26 is the upstream Current release line, add a deliberately non-authoritative qualification lane rather than immediately making it a protected-branch requirement.

Preferred semantics:

NODE_26_QUALIFICATION = advisory / scheduled / manual
MERGE_AUTHORITY       = current supported LTS lanes

The qualification should exercise at minimum:

  • dependency installation;
  • pnpm 11.22.0/Corepack behavior;
  • TypeScript/TS7 toolchain;
  • Biome;
  • Vitest including Web Storage/global changes;
  • Vite build;
  • Storybook;
  • Playwright harness;
  • repository scripts using ESM, child processes, crypto or filesystem APIs.

Record failures as actual compatibility evidence rather than suppressing the lane until it turns green.


Node 26 promotion gate

Promote Node 26 into the required supported matrix only when all are true:

UPSTREAM_SUPPORT_MATURITY_APPROPRIATE = YES
WORLD_SCRIPT_FULL_TOOLCHAIN_GREEN = YES
NO_UNRESOLVED_NODE26_RUNTIME_REGRESSION = YES
DEPLOYMENT_PROVIDER_SUPPORT = YES where relevant
DEPENDENCY_ENGINE_SUPPORT = YES

At promotion time, explicitly decide whether the matrix becomes:

24 + 26

or whether an older lane is retained for a documented reason.

Do not automatically create a 22/24/26 permanent triple matrix.


Dependency/tool compatibility audit

Pay special attention to packages/tooling that may use native binaries or Node-specific APIs:

  • @typescript/* / TypeScript 7;
  • pnpm/Corepack;
  • Vite/Rolldown;
  • Vitest/V8 coverage;
  • Playwright/browser installers;
  • Storybook;
  • Biome native binary;
  • tsx;
  • wrangler;
  • Tauri CLI Node wrapper;
  • DuckDB/WASM build/copy tooling;
  • codegraph/graphify tooling if Node-hosted;
  • serverless/provider build tooling.

A broad package engine range is evidence of declared support, not proof of repository behavior.


CI / efficiency relationship

#550 remains the owner for runner cost, duplicated setup, artifact reuse and matrix optimization.

This issue decides which Node versions are supported and why.

#550 may later optimize how those versions are exercised, but it must not remove a support oracle before this issue establishes that the lane is no longer required.

#446 should re-baseline coverage behavior if a Node-major change alters V8 coverage output or thresholds.


Rollback / failure handling

A Node-major promotion must remain reversible through version/config changes only.

Do not land application-source workarounds for a Node-Current-only regression unless that same source behavior affects an actually supported runtime.

If Node 26 exposes a tooling bug while Current:

QUALIFICATION = RED / KNOWN_UPSTREAM
REQUIRED_MATRIX = unchanged

rather than weakening production gates.


Acceptance criteria

  • Every repository/deployment Node-version authority is inventoried.
  • Node 24 LTS is proven across full install/typecheck/test/build/E2E/tooling workflows.
  • Canonical local/default Node version reflects the selected Node 24 policy.
  • Node-24-specific flags/workarounds are either proven necessary or removed with evidence.
  • Node 22 has an explicit KEEP_REQUIRED, KEEP_ADVISORY, or RETIRE_WITH_NOTICE decision.
  • engines.node, .nvmrc, CI and docs do not contradict each other.
  • Node 26 has a non-blocking qualification lane while Current.
  • Node 26 is not promoted to protected-branch authority until the full promotion gate passes.
  • Deployment providers/serverless/build runners are checked before a minimum-version increase.
  • Coverage/tooling changes caused by V8/Node are reconciled rather than hidden.
  • CI cost changes are coordinated with ci(efficiency): reduce redundant cost and latency without weakening required quality/security gates #550, not used as the support-policy authority.
  • No browser/Tauri/Qt runtime support claim is changed by this build-toolchain issue.

Non-goals

  • adopting Node Current immediately because it is newer;
  • dropping Node 22 solely to shorten CI;
  • keeping every historical Node LTS forever;
  • changing browser support;
  • changing Tauri/Qt runtime architecture;
  • bundling unrelated dependency upgrades;
  • weakening tests to make a new Node major pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions