fix: add Node LTS-only engine constraints to block odd-version installs

Installing @openrig/cli under Node 25 (homebrew default) silently
succeeds at npm but the daemon fails at runtime because
better-sqlite3 native prebuilds only ship for even-numbered LTS
lines (20, 22, 24). No engines field existed in packages/cli or
packages/daemon package.json to warn on install; README said
"Node.js 20+" with no upper bound.

Added engines.node "^20 || ^22 || ^24" to:
- packages/cli/package.json (published to npm; npm warns on
  mismatch when engine-strict or --engine-strict is set)
- packages/daemon/package.json (private; consistency)
- package.json (monorepo root; local dev)

Updated README Requirements to name supported LTS versions
explicitly and explain why odd releases are unsupported.

Added scripts/check-engines.test.mjs (runs under npm run
test:repo) to verify all three package.json files carry the
LTS-only constraint, preventing silent drift back to ">=20".

Postinstall ABI check deferred to separate scope (would require
VM gate for install-time validation under multiple Node versions).

Gates: check-engines 3/3; daemon 1792/1792; tsc + build clean.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
mvschwarz
2026-04-22 12:06:01 -07:00
co-authored by Claude Opus 4.6
parent cb4eb96952
commit 587206db6d
5 changed files with 33 additions and 3 deletions
+2 -2
View File
@@ -103,7 +103,7 @@ Hono HTTP daemon
- **CLI**: 40+ commands designed for both humans and agents. Every mutating command ends with what happened, current state, and next action.
- **UI**: Explorer sidebar, topology graph with pod grouping, node detail panel, system log, chatroom.
- **MCP**: 17 tools so agents can manage their own topology (`rig_up`, `rig_ps`, `rig_send`, `rig_chatroom_send`, etc.)
- **Runtimes**: Claude Code, Codex, and terminal nodes. Adapters for Pi and OpenHands in development.
- **Runtimes**: Claude Code, Codex, and terminal nodes. Adapters for Pi and OpenCode in development.
## Key Concepts
@@ -129,7 +129,7 @@ Requires Docker for service-backed rigs.
## Requirements
- Node.js 20+
- Node.js 20, 22, or 24 (even-numbered LTS releases; odd releases like 25 lack native addon prebuilds)
- tmux
Optional:
+1 -1
View File
@@ -18,6 +18,6 @@
"build:package": "bash scripts/build-package.sh"
},
"engines": {
"node": ">=20"
"node": "^20 || ^22 || ^24"
}
}
+3
View File
@@ -55,5 +55,8 @@
"@types/node": "^22.0.0",
"typescript": "^5.7.0",
"vitest": "^3.0.0"
},
"engines": {
"node": "^20 || ^22 || ^24"
}
}
+3
View File
@@ -25,5 +25,8 @@
"tsx": "^4.19.0",
"typescript": "^5.7.0",
"vitest": "^3.0.0"
},
"engines": {
"node": "^20 || ^22 || ^24"
}
}
+24
View File
@@ -0,0 +1,24 @@
import { readFileSync } from "node:fs";
import { test } from "node:test";
import assert from "node:assert/strict";
const EXPECTED_ENGINE = "^20 || ^22 || ^24";
const PACKAGE_PATHS = [
"package.json",
"packages/cli/package.json",
"packages/daemon/package.json",
];
for (const pkgPath of PACKAGE_PATHS) {
test(`${pkgPath} has engines.node set to LTS-only constraint`, () => {
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
assert.ok(pkg.engines, `${pkgPath} is missing an "engines" field`);
assert.ok(pkg.engines.node, `${pkgPath} is missing "engines.node"`);
assert.equal(
pkg.engines.node,
EXPECTED_ENGINE,
`${pkgPath} engines.node should be "${EXPECTED_ENGINE}" (even-numbered LTS only) but got "${pkg.engines.node}"`
);
});
}