From 6b550f21c4fd11c6f42f366d7a1ccaa8ff22b28d Mon Sep 17 00:00:00 2001 From: Luna Smith Date: Tue, 22 Sep 2026 07:43:07 +1000 Subject: [PATCH 1/2] fix(setup): require supported Node releases Move the setup wizard support floor to Node 22 and keep its package metadata, refusal message, boundary tests, and published guidance aligned. Older Node releases no longer receive security fixes.\n\nAuthored and validated by autonomous OpenAI Codex; no human pre-submission review is claimed. --- README.md | 7 ++-- apps/sysknife-cli/README.md | 2 +- docs/introduction.md | 2 +- docs/mcp.md | 2 +- docs/quickstart.md | 2 +- packages/setup/node-preflight.js | 9 +++-- packages/setup/package.json | 2 +- packages/setup/tests/node-preflight.test.mjs | 38 +++++++++++++++++--- 8 files changed, 49 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c442fcbf..42ae6ca5 100644 --- a/README.md +++ b/README.md @@ -83,8 +83,9 @@ plan and execute from chat. npx sysknife-setup ``` -Needs **Node 18 or newer**. On Ubuntu 22.04 `apt install nodejs` gives Node 12, -which is too old; the installer says so and how to get a current Node. No Rust +Needs **Node 22 or newer**; older Node releases no longer receive security fixes. +On Ubuntu 22.04 `apt install nodejs` gives Node 12, which is too old; the installer +says so and how to get a current Node. No Rust toolchain and no compile: it downloads verified prebuilt binaries. [![npm version](https://img.shields.io/npm/v/sysknife-setup?style=flat-square&logo=npm)](https://www.npmjs.com/package/sysknife-setup) @@ -427,7 +428,7 @@ helps other people find the project. | Channel | Install | Notes | |---------|---------|-------| -| **npm** | `npx sysknife-setup` | [npmjs.com/package/sysknife-setup](https://www.npmjs.com/package/sysknife-setup) — setup wizard; needs Node 18+, no compile | +| **npm** | `npx sysknife-setup` | [npmjs.com/package/sysknife-setup](https://www.npmjs.com/package/sysknife-setup) — setup wizard; needs Node 22+, no compile | | **crates.io** | `cargo install sysknife-cli` / `cargo install sysknife-daemon` | Needs `build-essential`; ~7-12 min build. Published by reviewed version tags; see [docs/release.md](docs/release.md) | | **MCP Registry** | `io.github.lacs-project/sysknife` | [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io) — resolves to the crates.io install above. Directory pages that sandbox a server list every tool but cannot call the ones needing the daemon; [docs/mcp-registry.md](docs/mcp-registry.md#what-a-directory-sandbox-can-and-cannot-tell-you) explains the split | | **GitHub Releases** | Download from [Releases](https://github.com/lacs-project/sysknife/releases) | Prebuilt x86_64 + aarch64 binaries with SHA-256 checksums on every tag | diff --git a/apps/sysknife-cli/README.md b/apps/sysknife-cli/README.md index 2bb0bcf1..ccb6c920 100644 --- a/apps/sysknife-cli/README.md +++ b/apps/sysknife-cli/README.md @@ -37,7 +37,7 @@ containers, 6m56s on 24.04 and 11m43s on 22.04. `cmake` is **not** required. Faster, and it installs both halves plus your MCP client config: ```sh -npx sysknife-setup # needs Node 18+ +npx sysknife-setup # needs Node 22+ ``` The wizard downloads SHA-256-verified binaries from the release page, so there diff --git a/docs/introduction.md b/docs/introduction.md index 84276b5b..23900b5c 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -124,7 +124,7 @@ sudo systemctl enable --now sysknife-daemon sysknife "show disk usage" ``` -For prebuilt binaries instead of a build, run `npx sysknife-setup` (Node 18+). +For prebuilt binaries instead of a build, run `npx sysknife-setup` (Node 22+). See the canonical [Quick Start](quickstart.md). No API key needed if you have [Ollama](https://ollama.com) running locally — diff --git a/docs/mcp.md b/docs/mcp.md index 88744008..670ee125 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -182,7 +182,7 @@ the security boundary. npx sysknife-setup ``` -Needs Node 18 or newer (Ubuntu 22.04's apt Node is 12, which is too old). The +Needs Node 22 or newer (Ubuntu 22.04's apt Node is 12, which is too old). The wizard detects your installed `sysknife` binary, asks for the daemon socket and LLM provider, and then asks which integration to configure. No manual file editing needed. For install options and prerequisites in full, see the diff --git a/docs/quickstart.md b/docs/quickstart.md index 60621b9c..8d9668b8 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -20,7 +20,7 @@ needs both. npx sysknife-setup ``` -**Prerequisites:** Node 18 or newer. On Ubuntu 22.04, `apt install nodejs` +**Prerequisites:** Node 22 or newer. On Ubuntu 22.04, `apt install nodejs` installs Node 12, which is too old — the installer will tell you so and how to get a current Node. It downloads SHA-256-verified binaries from the release page, installs the daemon service, and writes your MCP client config. diff --git a/packages/setup/node-preflight.js b/packages/setup/node-preflight.js index 111fa415..6ed56efa 100644 --- a/packages/setup/node-preflight.js +++ b/packages/setup/node-preflight.js @@ -15,7 +15,7 @@ */ /** Oldest Node the wizard's own syntax and APIs require. Keep in sync with `engines.node`. */ -var MIN_MAJOR = 18; +var MIN_MAJOR = 22; /** * Explain, actionably, why this Node cannot run the wizard. @@ -33,7 +33,12 @@ function unsupportedMessage(version) { if (!isNaN(major) && major >= MIN_MAJOR) return null; return ( - 'sysknife-setup needs Node ' + MIN_MAJOR + ' or newer. You are running ' + shown + '.\n' + + 'sysknife-setup needs Node ' + + MIN_MAJOR + + ' or newer because older releases no longer receive security fixes. ' + + 'You are running ' + + shown + + '.\n' + '\n' + "Ubuntu 22.04's `apt install nodejs` gives Node 12, which cannot run this\n" + 'installer. Pick whichever of these suits the machine:\n' + diff --git a/packages/setup/package.json b/packages/setup/package.json index 4a154422..7a9331ce 100644 --- a/packages/setup/package.json +++ b/packages/setup/package.json @@ -15,7 +15,7 @@ "sysknife-mcp": "mcp-launcher.js" }, "engines": { - "node": ">=18" + "node": ">=22" }, "files": [ "index.js", diff --git a/packages/setup/tests/node-preflight.test.mjs b/packages/setup/tests/node-preflight.test.mjs index 87ab4753..ee5f900a 100644 --- a/packages/setup/tests/node-preflight.test.mjs +++ b/packages/setup/tests/node-preflight.test.mjs @@ -44,17 +44,28 @@ test('rejects the Node that Ubuntu 22.04 ships, and says how to fix it', () => { const msg = unsupportedMessage('12.22.9'); assert.ok(msg, 'Node 12 must be rejected'); assert.match(msg, /12\.22\.9/, 'names the version actually in use'); - assert.match(msg, /\b18\b/, 'names the minimum'); + assert.match(msg, /\b22\b/, 'names the minimum'); + assert.match(msg, /end.of.life|security fixes/i, 'explains why the floor moved'); // Actionable: at least one runnable command, not just a complaint. assert.match(msg, /nodesource|nvm|snap|fnm/i, 'suggests a way to get a newer Node'); assert.match(msg, /releases/, 'offers the no-Node escape hatch (prebuilt binaries)'); }); test('rejects every major below the minimum and accepts every one at or above', () => { - for (const v of ['0.10.48', '4.9.1', '8.17.0', '12.22.9', '14.21.3', '16.20.2']) { + for (const v of [ + '0.10.48', + '4.9.1', + '8.17.0', + '12.22.9', + '14.21.3', + '16.20.2', + '18.20.8', + '20.19.5', + '21.7.3', + ]) { assert.ok(unsupportedMessage(v), `${v} must be rejected`); } - for (const v of ['18.0.0', '18.19.1', '20.11.0', '22.5.1', '24.0.0']) { + for (const v of ['22.0.0', '22.5.1', '24.0.0']) { assert.equal(unsupportedMessage(v), null, `${v} must be accepted`); } }); @@ -66,8 +77,25 @@ test('an unparseable version is not silently treated as supported', () => { }); test('the minimum matches what package.json advertises', () => { - assert.equal(MIN_MAJOR, 18); - assert.match(pkg.engines.node, />=\s*18/); + assert.equal(MIN_MAJOR, 22); + assert.match(pkg.engines.node, />=\s*22/); +}); + +test('published setup guidance names Node 22 and no longer claims Node 18 support', () => { + const repoRoot = path.resolve(pkgDir, '..', '..'); + const publishedClaims = [ + 'README.md', + 'docs/quickstart.md', + 'docs/mcp.md', + 'apps/sysknife-cli/README.md', + 'docs/introduction.md', + ]; + + for (const file of publishedClaims) { + const src = fs.readFileSync(path.join(repoRoot, file), 'utf8'); + assert.doesNotMatch(src, /Node 18/i, `${file} must not retain the old support floor`); + assert.match(src, /Node 22/i, `${file} must name the new support floor`); + } }); // --------------------------------------------------------------------------- From c8adedfaf9a78cf4b79c5cd386fa5e7ae0b4c805 Mon Sep 17 00:00:00 2001 From: Vladimir Rotariu Date: Mon, 21 Sep 2026 20:30:34 -0600 Subject: [PATCH 2/2] docs(changelog): record the Node 22 support floor The maintainer's half of the merge, not a review finding. A dropped support floor is something an existing user notices, so it belongs in Changed rather than Fixed. Also merges main, which brought #461's test baseline (1,866) into the same three files this branch edits. Both survive: the Node 22 statements and the baseline figure, checked file by file rather than trusting the auto-merge. --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c58a450..f7cdd57e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ Releases before `0.2.5` predate the public launch; their notes live in the ## [Unreleased] +### Changed + +- `sysknife-setup` requires Node 22 or newer. Node 18 and 20 no longer receive + security fixes, so this drops support for them rather than retiring an + untested claim: `engines.node`, the preflight guard and all six published + support statements move together, and the refusal message says why the floor + moved. Nothing in CI is affected; every job that touches JavaScript already + runs Node 24 (#327). + ### Fixed - `sysknife audit verify` now reports `cannot_verify` and exits 2 over an empty