Problem
packages/katana-client uses npm with a committed package-lock.json that CI installs
via npm ci (npm 10.9.8, node 22). Nothing pins the package-manager version, so a
contributor on a newer toolchain resolves the lockfile differently. Concretely: running
npm install under npm 11 (node 24/25) prunes platform-specific optional native
deps (@emnapi/core, @emnapi/runtime, and other @rollup/rollup-* / @esbuild/* /
@biomejs/cli-* variants) that npm 10's npm ci then reports as
Missing: @emnapi/core from lock file → red CI. Hit live while preparing #976; had to
rebuild the lockfile with npx npm@10.9.8 to get a lockfile CI accepts.
This will bite any contributor whose default npm ≠ CI's.
Options
- Pin npm via
packageManager + Corepack (recommended, do first). Add
"packageManager": "npm@10.9.8" to packages/katana-client/package.json (or root),
corepack enable in CI and dev setup. Everyone resolves the lockfile identically
regardless of their installed node/npm. Zero format migration, smallest change,
directly kills the drift class. Bump the pinned version deliberately, in a PR.
- Unify on pnpm (larger, worth evaluating). The repo root already uses a pnpm
workspace (its lockfile is currently untracked). Moving the TS client to pnpm gives
one package manager across the monorepo and stronger cross-platform lockfile
determinism. Cost: rewrite the typescript-client job (pnpm install --frozen-lockfile vs npm ci), convert to pnpm-lock.yaml and gate it, verify
@hey-api/openapi-ts + biome/esbuild binaries resolve under pnpm's strict
node_modules, update CLAUDE.md quick-start (npm --prefix ... ci) and docs.
- Bump CI to npm 11 — only WITH a pin. Bumping unpinned just inverts the mismatch
(npm-10 contributors now drift), and npm 11 needs node 24+, coupling a node upgrade
in. If chosen, still pin via packageManager.
Recommendation
Do (1) now — cheap, stops the bleeding. Then evaluate (2) as a monorepo-consistency
follow-up (single PM across root + TS client). Avoid (3) unpinned.
Acceptance
- Package-manager version is pinned and enforced (Corepack) so
npm ci / install is
deterministic across contributor machines and CI.
- Decision on pnpm-unification recorded (ADR or issue resolution).
Problem
packages/katana-clientuses npm with a committedpackage-lock.jsonthat CI installsvia
npm ci(npm 10.9.8, node 22). Nothing pins the package-manager version, so acontributor on a newer toolchain resolves the lockfile differently. Concretely: running
npm installunder npm 11 (node 24/25) prunes platform-specific optional nativedeps (
@emnapi/core,@emnapi/runtime, and other@rollup/rollup-*/@esbuild/*/@biomejs/cli-*variants) that npm 10'snpm cithen reports asMissing: @emnapi/core from lock file→ red CI. Hit live while preparing #976; had torebuild the lockfile with
npx npm@10.9.8to get a lockfile CI accepts.This will bite any contributor whose default npm ≠ CI's.
Options
packageManager+ Corepack (recommended, do first). Add"packageManager": "npm@10.9.8"topackages/katana-client/package.json(or root),corepack enablein CI and dev setup. Everyone resolves the lockfile identicallyregardless of their installed node/npm. Zero format migration, smallest change,
directly kills the drift class. Bump the pinned version deliberately, in a PR.
workspace (its lockfile is currently untracked). Moving the TS client to pnpm gives
one package manager across the monorepo and stronger cross-platform lockfile
determinism. Cost: rewrite the
typescript-clientjob (pnpm install --frozen-lockfilevsnpm ci), convert topnpm-lock.yamland gate it, verify@hey-api/openapi-ts+ biome/esbuild binaries resolve under pnpm's strictnode_modules, updateCLAUDE.mdquick-start (npm --prefix ... ci) and docs.(npm-10 contributors now drift), and npm 11 needs node 24+, coupling a node upgrade
in. If chosen, still pin via
packageManager.Recommendation
Do (1) now — cheap, stops the bleeding. Then evaluate (2) as a monorepo-consistency
follow-up (single PM across root + TS client). Avoid (3) unpinned.
Acceptance
npm ci/ install isdeterministic across contributor machines and CI.