Record three confirmed v1.0.8 failure modes (expo prebuild native regressions, npm 10/11 lockfile divergence, local EAS build preconditions) and promote each into docs/releasing.md, a new docs/development/dependencies.md, and the release-preflight script. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2.4 KiB
id, date, status, scope, evidence, destination, review_after
| id | date | status | scope | evidence | destination | review_after |
|---|---|---|---|---|---|---|
| 2026-08-31-npm-lockfile-divergence | 2026-08-31 | promoted | root package.json, package-lock.json, apps/web dependencies, CI | v1.0.8 lockfile investigation, commits 90cde4a, 9609a90 |
docs/development/dependencies.md | 2026-11-30 |
Symptom
CI and the API Docker image (node 20.19.4/npm 10.8.2, per .nvmrc) broke
invisibly while a lockfile regenerated on this dev machine (node 26/npm
11.19) passed local npm ci. Pushes to staging bypass required status
checks, so the red CI ran unnoticed for hours.
Reproduction
Regenerate package-lock.json with npm 11 on a wildcard-range dependency
(react-native-worklets depends on @react-native/metro-config: "*"), then
run npm ci under node 20.19.4/npm 10.8.2. npm 10 requires 0.85.3 at that
tree position; npm 11 resolves/hoists 0.87.x there. npm ci fails with
"Invalid: lock file's ... does not satisfy". The reverse direction also
fails: a lock regenerated by npm 10 fails npm ci under npm 11 with missing
platform-optional binaries (@next/swc-linux-x64-gnu breaking next build,
@rollup/rollup-linux-x64-gnu breaking the API Docker tsup build, lightningcss
variants breaking local npm ci), matching the npm/cli#4828-style
optional-dependency resolution gap.
Cause
Two different npm major versions in active use (CI/Docker on npm 10, this dev machine on npm 11) resolve wildcard/range dependencies to different versions at the same tree position, and each npm's own platform-optional binary selection is not portable to the other npm's lockfile.
Remediation
Pin the wildcard-range dependency via a root package.json override
("@react-native/metro-config": "0.85.3", alongside the existing
rollup/react-native/expo pins). Pin apps/web @next/swc linux/darwin
binaries as direct optionalDependencies (must be bumped together with any
next version bump). Regenerate the lock and validate it both ways: local
npm ci plus npm run verify:fast, and
docker run --platform linux/amd64 node:20.19.4 ... npm ci (the
--platform flag is mandatory; Apple Silicon Docker otherwise runs arm64
and the platform-binary check is meaningless). After any push that bypassed
required status checks, check gh run list --branch staging.
Evidence
commits 90cde4a and 9609a90 add the override and optionalDependencies pins
and record a lockfile that passes both the amd64-emulated npm ci under
node 20.19.4 and local npm ci plus npm run verify:fast.