Files
jjbruntonandClaude Fable 5 7a76936829 docs(agents): promote v1.0.8 release learnings
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>
2026-08-31 16:03:02 +01:00

2.8 KiB

Dependency and lockfile discipline

Two npm realities

CI runners and the API Docker image use the node version pinned in .nvmrc (node 20.19.4 with npm 10.8.2). A developer machine can run a newer npm (for example npm 11). npm 10 and npm 11 resolve wildcard or range dependencies differently at the same place in the dependency tree, and each npm's platform-optional binary selection is not portable to a lockfile regenerated by the other npm. A lockfile that passes npm ci under one npm major version can fail it under the other with either an "Invalid: lock file's ... does not satisfy" error or missing platform-optional binaries (for example @next/swc-linux-x64-gnu breaking next build, @rollup/rollup-linux-x64-gnu breaking the API Docker tsup build, or a missing lightningcss variant breaking local npm ci).

Pin wildcard-range dependencies with root overrides

When a transitive dependency declares a wildcard or wide range (for example react-native-worklets depending on @react-native/metro-config: "*"), pin the exact version the app needs in the root package.json overrides block rather than leaving it to whichever npm resolved the lockfile last:

"overrides": {
  "rollup": "4.54.0",
  "react-native": "0.85.3",
  "expo": "~56.0.0",
  "@react-native/metro-config": "0.85.3"
}

Pin platform-optional binaries that must travel with the framework version

apps/web/package.json pins the @next/swc linux and darwin binaries as direct optionalDependencies so npm does not have to infer them per platform:

"optionalDependencies": {
  "@next/swc-linux-x64-gnu": "15.5.24",
  "@next/swc-linux-x64-musl": "15.5.24",
  "@next/swc-darwin-arm64": "15.5.24"
}

These versions must be bumped together with any next version bump, or the pinned binaries will drift from the framework version and npm ci or next build can fail on the platform that needs the stale binary.

Validate a regenerated lockfile both ways

After changing overrides or any dependency version, regenerate package-lock.json and validate it under both npm majors before committing:

# Local npm (matches this machine's npm major)
npm ci
npm run verify:fast

# The CI/Docker npm major, emulated on Apple Silicon
docker run --rm --platform linux/amd64 -v "$PWD:/repo" -w /repo node:20.19.4 npm ci

The --platform linux/amd64 flag is mandatory on Apple Silicon: without it, Docker runs the arm64 image and the platform-binary check proves nothing.

After any bypassed push

Pushes to staging bypass required status checks. After any such push, check gh run list --branch staging to confirm CI is actually green rather than assuming it ran and passed.

Do not pipe npm commands through tail when diagnosing a lockfile or build failure; it can swallow the command's exit code and the detail needed to find the root cause.