close
Skip to content

build: target Node 24 LTS with a single 22+ floor everywhere (#1070) - #2415

Merged
pepmach merged 1 commit into
mainfrom
fix/node24-upgrade-1070
Aug 10, 2026
Merged

build: target Node 24 LTS with a single 22+ floor everywhere (#1070)#2415
pepmach merged 1 commit into
mainfrom
fix/node24-upgrade-1070

Conversation

@bolichen97

Copy link
Copy Markdown
Collaborator

Summary

Node 20 reached end-of-life on 2026-04-30 but remained the pinned target across 10 CI jobs, the exact vulnerability-scan pin, the bootstrap script, the installer, and the EC2 template — while the repo stated four contradictory minimum versions (16/18/20/22) that let kirocrew doctor report green on a Node that kirocrew chat refuses to start on.

This lands one coherent policy: Node 24 (Active LTS, EOL 2028-04-30) as the pinned target, floor 22 for contributors, plus a regression gate so the pins cannot silently rot again.

Pins → 24

  • All 13 workflow setup-node pins (10× 20, 3× 22) → 24; ota-test.yml keeps a comment documenting its load-bearing ≥ 22 WebSocket floor
  • Exact pin dependency-vulnerability.yml 20.19.424.19.0, with its coupled test assertion updated in the same commit
  • ensure-node.sh: TARGET_VERSION=24, GLIBC217_VERSION=24.19.0 (verified: unofficial-builds publishes linux-x64-glibc-217 for v24.19.0)
  • install.sh NODE_VERSION="24", EC2 template NodeSource pub_20.xpub_24.x, new root .nvmrc containing 24 (previously no local toolchain pin existed)

Floors → one shared 22

  • New kiro_crew.constants.MIN_NODE_MAJOR = 22 replaces the duplicated _MIN_NODE_VERSION = 16 in cli.py/cli_doctor.py, the inline < 20 gate in cli_chat.py, and the >= 16 message in cli_setup.py — doctor and chat can no longer disagree
  • ensure-node.sh floor 20.1922.12 (the vite 8 / rolldown ^20.19.0 || >=22.12.0 engines line, minus the EOL 20.x leg); _version_meets_floor drops the 20.x branch
  • install.sh gains a post-install major check so a distro-shipped Node below the floor is caught at install time instead of as a confusing frontend-build failure
  • Docs/messages state one floor everywhere: "Node.js 22+ (24 LTS recommended)"

engines / @types/node

  • website/package.json engines "20 || >=22"">=22"; @types/node 25.5.0 (Node 25 is EOL) → 24.13.3 (matches electron's resolution); minimal lockfile churn (8 lines)
  • site/package.json: adds an explicit @types/node 24.13.3 pin (was floating to 26.x) and bumps @vitejs/plugin-react ^4.3.2^6.0.5: npm 11 (bundled with Node 24) enforces peer ranges at npm ci time, and plugin-react 4.x declares vite ^4||^5||^6||^7 against the repo's vite 8 — the old lockfile fails bare npm ci under npm 11, so pages.yml on Node 24 would have gone red without this
  • website/electron lockfile untouched (already resolves @types/node 24.13.3 via electron 43)

Regression gate

  • New test/test_node_version_pins.py: every node-version in .github/workflows/** must track the .nvmrc major (floating pins equal it, exact pins at or above it). Static and offline — no network.

Testing

  • Backend: isort / flake8 / mypy clean; full pytest — failure set identical to pristine origin/main on this host (20 env-only sandbox-unavailable failures; verified by running the same subset on a clean worktree)
  • Frontend on Node 24: npx tsc -b clean; npx vitest run 11627 passed (869 files)
  • Electron on Node 24: npm test (node --test) 845/845 passed
  • site/ on Node 24 + npm 11: bare npm ci + npm run build + npm test all pass (the old lock reproducibly fails npm ci here)
  • Intl.DurationFormat empirically confirmed undefined on Node 22 and present on Node 24 before touching the format.ts baseline comments
  • bash -n on both shell scripts; set -euo pipefail behavior of the new install.sh check verified against a broken-node simulation
  • Brand gate, scrub-lint (content checks), docs-lint all pass

Out of scope

Electron upgrade (already ^43.2.0, embeds a Node 24-line runtime), Playwright pin in ensure-playwright.mjs, .vulnerability-exceptions.json retirement — separate issues per #1070.

Closes #1070

@bolichen97
bolichen97 requested a review from a team August 9, 2026 22:01
@bolichen97
bolichen97 requested a review from a team as a code owner August 9, 2026 22:01
@github-actions github-actions Bot added the readiness: checking Automated validation is still running label Aug 9, 2026
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review — ✅ no blocking findings

Reviewed 33145730e104b8ae30b640bb90ae8573d24ecaa5 — this comment is updated in place on each push.

Review details

No findings.

This PR is a mechanical Node toolchain bump (20 → 24, floor 22) across workflows, install scripts, docs, and lockfiles, plus a single-source MIN_NODE_MAJOR constant and a static consistency test. The ensure-node.sh floor logic correctly drops the maj==20 branch so 20.x now falls to return 1; the new install.sh floor probe defaults a broken binary to v0 and warns. No security control, guard clause, or data path is weakened, and no AUTOSDE rule with matching file-patterns is violated.

[OPUS-REVIEWED] 3314573

Verdict parsed from the review's SHA-scoped output markers for commit 33145730e104b8ae30b640bb90ae8573d24ecaa5.

False positive or not applicable? A repository writer can comment:
/ai-review override fable 33145730e104b8ae30b640bb90ae8573d24ecaa5: <one-sentence reason>

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

UX Review (Fable 5) — ✅ PASS

Advisory UX-level review of 33145730e104b8ae30b640bb90ae8573d24ecaa5 — updated in place on each push; does not block merge.

This PR is build-toolchain work (Node version pins); the only user-facing surfaces are CLI/installer messages and docs prerequisite lines. I checked every changed string against the flows they appear in (doctor, chat, setup, install) — the change collapses four contradictory version floors into one consistent, actionable message set ("Node.js 22+, 24 LTS recommended" with a fix link), and the new install-time warning fires before the failure it explains. No dashboard UI, no screenshots, no new interaction surfaces.

UX-Verdict: PASS

Every changed string now states one consistent floor with an actionable fix, replacing four contradictory versions that let doctor pass what chat rejected.

[UX-REVIEWED] 3314573

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5) — ✅ PASS

Advisory design-level review of 33145730e104b8ae30b640bb90ae8573d24ecaa5 — updated in place on each push; does not block merge.

Design-Verdict: PASS

Root-cause fix — one floor constant, one toolchain pin, and a regression gate that makes the drift class structurally impossible in CI.

Suggestions

  • The anti-rot gate covers only workflow pins vs .nvmrc; the floor itself still lives in four encodings (constants.MIN_NODE_MAJOR, install.sh NODE_MIN_MAJOR=22, ensure-node.sh MIN_VERSION="22.12", engines ">=22"). Extend test_node_version_pins.py to cross-check those too — otherwise the next floor bump can recreate exactly the doctor/installer disagreement this PR exists to kill.

[DESIGN-REVIEWED] 3314573

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review — ✅ no blocking findings

GPT 5.6 completed its review of 33145730e104b8ae30b640bb90ae8573d24ecaa5 and found no blocking issues.

This comment is updated in place on each push.

Review details

No findings.
[GPT-REVIEWED] 3314573

False positive or not applicable? A repository writer can comment:
/ai-review override gpt 33145730e104b8ae30b640bb90ae8573d24ecaa5: <one-sentence reason>

@github-actions github-actions Bot added readiness: passed Eligible automated validation passed for the current revision and removed readiness: checking Automated validation is still running labels Aug 9, 2026
@pepmach
pepmach enabled auto-merge (squash) August 9, 2026 22:52
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention and removed readiness: passed Eligible automated validation passed for the current revision readiness: checking Automated validation is still running labels Aug 9, 2026
Node 20 reached end-of-life on 2026-04-30 but remained the pinned target
across 10 CI jobs, the exact vulnerability-scan pin, the bootstrap script,
the installer, and the EC2 template, while the repo stated four different
minimum versions (16/18/20/22) that let 'kirocrew doctor' pass on a Node
'kirocrew chat' refuses to start on.

One coherent policy, applied everywhere:

- Target: Node 24 (Active LTS, EOL 2028-04-30) in all 13 workflow
  setup-node pins, install.sh, ensure-node.sh TARGET_VERSION, the
  NodeSource repo in the EC2 template, and a new root .nvmrc.
- Exact CI pin: 24.19.0 in dependency-vulnerability.yml and its coupled
  test assertion; the glibc-217 AL2 fallback moves to the same release.
- Floor: 22 for contributors. Python-side checks collapse to one shared
  constants.MIN_NODE_MAJOR consumed by cli.py, cli_doctor.py,
  cli_chat.py, and cli_setup.py so doctor and chat can never disagree
  again; ensure-node.sh enforces the finer 22.12 vite/rolldown floor and
  drops the EOL 20.x leg; install.sh gains a post-install major check so
  distro-shipped Node below the floor is caught at install time.
- engines/@types: website engines '>=22'; @types/node pinned to 24.13.3
  in website and newly pinned in site (was floating to 26.x); site's
  @vitejs/plugin-react bumped to ^6 because npm 11 (bundled with Node
  24) enforces peer ranges at 'npm ci' time and 4.x rejects vite 8.
- Docs and messages state one floor: 'Node.js 22+ (24 LTS recommended)'.
- Regression gate: test_node_version_pins.py asserts every workflow
  node-version tracks the .nvmrc major (floating pins equal it, exact
  pins at or above it), statically and offline.

ota-test.yml keeps a comment documenting its load-bearing >= 22
WebSocket floor. Verified on Node 24: website tsc -b + vitest (11627
tests), electron node --test (845), site npm ci + build + test.

Closes #1070
@bolichen97
bolichen97 force-pushed the fix/node24-upgrade-1070 branch from 71d1ca4 to 3314573 Compare August 10, 2026 00:53
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 10, 2026
@bolichen97

Copy link
Copy Markdown
Collaborator Author

🤖 Kiro Crew Auto-Pipeline [operator: bolichen97] — branch rebased onto latest main after base drift; remaining CI failures (jsdom script-loading in Frontend Tests, ContextVar/event-loop errors on Windows shard 1) are Node-24-related and a resume session has been dispatched to fix them.

@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: passed Eligible automated validation passed for the current revision and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 10, 2026
@pepmach
pepmach merged commit 11af0a2 into main Aug 10, 2026
77 of 80 checks passed
@pepmach
pepmach deleted the fix/node24-upgrade-1070 branch August 10, 2026 04:52
@github-actions github-actions Bot removed the readiness: passed Eligible automated validation passed for the current revision label Aug 10, 2026
encomjp pushed a commit to encomjp/kirocrew-customapi that referenced this pull request Aug 22, 2026
…dev#1070) (kirodotdev#2415)

Node 20 reached end-of-life on 2026-04-30 but remained the pinned target
across 10 CI jobs, the exact vulnerability-scan pin, the bootstrap script,
the installer, and the EC2 template, while the repo stated four different
minimum versions (16/18/20/22) that let 'kirocrew doctor' pass on a Node
'kirocrew chat' refuses to start on.

One coherent policy, applied everywhere:

- Target: Node 24 (Active LTS, EOL 2028-04-30) in all 13 workflow
  setup-node pins, install.sh, ensure-node.sh TARGET_VERSION, the
  NodeSource repo in the EC2 template, and a new root .nvmrc.
- Exact CI pin: 24.19.0 in dependency-vulnerability.yml and its coupled
  test assertion; the glibc-217 AL2 fallback moves to the same release.
- Floor: 22 for contributors. Python-side checks collapse to one shared
  constants.MIN_NODE_MAJOR consumed by cli.py, cli_doctor.py,
  cli_chat.py, and cli_setup.py so doctor and chat can never disagree
  again; ensure-node.sh enforces the finer 22.12 vite/rolldown floor and
  drops the EOL 20.x leg; install.sh gains a post-install major check so
  distro-shipped Node below the floor is caught at install time.
- engines/@types: website engines '>=22'; @types/node pinned to 24.13.3
  in website and newly pinned in site (was floating to 26.x); site's
  @vitejs/plugin-react bumped to ^6 because npm 11 (bundled with Node
  24) enforces peer ranges at 'npm ci' time and 4.x rejects vite 8.
- Docs and messages state one floor: 'Node.js 22+ (24 LTS recommended)'.
- Regression gate: test_node_version_pins.py asserts every workflow
  node-version tracks the .nvmrc major (floating pins equal it, exact
  pins at or above it), statically and offline.

ota-test.yml keeps a comment documenting its load-bearing >= 22
WebSocket floor. Verified on Node 24: website tsc -b + vitest (11627
tests), electron node --test (845), site npm ci + build + test.

Closes kirodotdev#1070

Co-authored-by: Stan Tian <pepmach7@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Node 20 is EOL (2026-04-30) and pinned in 11 CI jobs, the installer, and the desktop runtime

3 participants