mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-11-06 05:17:15 +00:00
pnpm 12.15.0 (native executable) installs every JS workspace from one pnpm-lock.yaml, imported from package-lock.json with the same resolved versions. website/, the WhatsApp bridge and the photon sidecar stay separate npm projects. Configuration moves from .npmrc and the root manifest into pnpm-workspace.yaml: the 14-day minimumReleaseAge and its excludes, overrides, allowBuilds (the old allowScripts set, with strictDepBuilds failing any unlisted build script), engineStrict, sideEffectsCache: false (in-place rebuilds must not write into the store) and verifyDepsBeforeRun: false (a `pnpm run` never installs). The pnpm version is pinned in pm/lock.json and in root devEngines. pmOnFail: ignore keeps that pin out of pnpm-lock.yaml: a leading pin document makes osv-scanner read zero packages. scripts/build/node-deps.mjs enforces the exact version instead, and every lock reader refuses a multi-document lock. A root preinstall refuses `npm install`; devEngines onFail is warn so npx (MCP servers, the tsc linter) keeps working inside the checkout. User-machine installs run --frozen-lockfile --trust-lockfile (release age is checked when locking, in CI, not per user). node-deps removes npm-era node_modules trees before the first pnpm install. Nix builds the store with fetchPnpmDeps and a hash file that CI checks.
60 lines
2.5 KiB
TypeScript
60 lines
2.5 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
|
|
import { load } from 'js-yaml'
|
|
// semver ships no declarations in this lock; type the two library calls used here.
|
|
const semver: { valid(version: string): string | null; satisfies(version: string, range: string): boolean } = require('semver')
|
|
import { test } from 'vitest'
|
|
|
|
interface Engines { node?: string }
|
|
interface Manifest {
|
|
engines?: Engines
|
|
devEngines?: { packageManager?: { name?: string; version?: string; onFail?: string } }
|
|
}
|
|
interface Lockfile { packages?: Record<string, Manifest> }
|
|
interface PmLock { packages: { node: { version: string }; pnpm: { version: string } } }
|
|
|
|
function read(relativePath: string): string {
|
|
return fs.readFileSync(path.resolve(__dirname, '..', relativePath), 'utf8')
|
|
}
|
|
|
|
// SAFETY: these are repository-owned manifest/lock inputs, checked below.
|
|
const root = JSON.parse(read('package.json')) as Manifest
|
|
const desktop = JSON.parse(read('apps/desktop/package.json')) as Manifest
|
|
const lock = load(read('pnpm-lock.yaml')) as Lockfile
|
|
const pins = (JSON.parse(read('pm/lock.json')) as PmLock).packages
|
|
|
|
function nodeRange(manifest: Manifest): string {
|
|
assert.ok(manifest.engines?.node, 'workspace must declare engines.node')
|
|
|
|
return manifest.engines.node
|
|
}
|
|
|
|
test.each([
|
|
['26.0.0', true], ['26.12.1', true], ['27.0.0', true],
|
|
['22.22.0', false], ['22.23.1', false], ['24.11.0', false], ['24.18.2', false], ['25.2.1', false], ['26.0.0-rc.1', false],
|
|
] as const)('workspace Node policy for %s is %s', (version: string, accepted: boolean): void => {
|
|
for (const manifest of [root, desktop]) {
|
|
assert.equal(semver.satisfies(version, nodeRange(manifest)), accepted)
|
|
}
|
|
})
|
|
|
|
test('exact independently managed Node satisfies all declared lockfile engines', (): void => {
|
|
assert.ok(semver.valid(pins.node.version), 'node must be an exact pin')
|
|
assert.ok(Object.keys(lock.packages ?? {}).length > 0, 'pnpm-lock.yaml has no packages')
|
|
|
|
for (const [name, manifest] of Object.entries({ ...lock.packages, root, desktop })) {
|
|
const range = manifest.engines?.node
|
|
|
|
if (range) {
|
|
assert.ok(semver.satisfies(pins.node.version, range), `${name}: pinned node ${pins.node.version} violates ${range}`)
|
|
}
|
|
}
|
|
})
|
|
|
|
test('the managed pnpm is exactly the one the repository requires, and any other fails', (): void => {
|
|
assert.ok(semver.valid(pins.pnpm.version), 'pnpm must be an exact pin')
|
|
assert.deepEqual(root.devEngines?.packageManager, { name: 'pnpm', version: pins.pnpm.version, onFail: 'warn' })
|
|
})
|