Skip to content

fix(deps): restore nested ajv and bundled emnapi entries to the lockfile - #72

Merged
chriskehayias merged 1 commit into
mainfrom
fix/deps-ajv-lockfile-drift
Aug 21, 2026
Merged

fix(deps): restore nested ajv and bundled emnapi entries to the lockfile#72
chriskehayias merged 1 commit into
mainfrom
fix/deps-ajv-lockfile-drift

Conversation

@chriskehayias

Copy link
Copy Markdown
Contributor

Why

CI has been red on main since 64f18f0 ("Package Update Cleanup"). npm ci fails in ~8s before any test runs, on every branch:

npm error Invalid: lock file's ajv@6.15.0 does not satisfy ajv@8.20.0
npm error Missing: fast-uri@3.1.5 from lock file
npm error Invalid: lock file's json-schema-traverse@0.4.1 does not satisfy json-schema-traverse@1.0.0

The run before 64f18f0 was green; that one and every run since are red with a byte-identical error. No PR has been verifiable by CI since.

Cause

ajv is an optional peer dep of @hookform/resolvers (peerDependenciesMeta.ajv.optional: true), and we don't use the ajv resolver — so it shouldn't be installed at all.

The lockfile instead carried a single hoisted top-level ajv@6.15.0 marked devOptional, a dedupe of eslint's own ajv@6, while npm's ideal tree wanted ajv@8.20.0 in that slot to satisfy the optional peer. Lock and ideal tree disagreed, and npm ci refuses to guess.

Fix

npm install --package-lock-only --os=linux --cpu=x64

142 lines, +116/−26:

  • drops the bogus hoisted top-level ajv@6.15.0 and json-schema-traverse@0.4.1
  • gives eslint and @eslint/eslintrc their own nested ajv@6.15.0 subtrees
  • restores the bundled @tailwindcss/oxide-wasm32-wasi@emnapi/* subtree (core, runtime, wasi-threads, @napi-rs/wasm-runtime, @tybys/wasm-util, tslib) that a previous Windows install had pruned

package.json is untouched and no dependency versions changed — this is purely a lockfile tree-shape repair.

That last bullet also clears the drift tracked in investigate-emnapi-lockfile-drift.md, so the manual re-add workaround that TODO describes is no longer needed.

Verification

  • npm ci on Linux (container): exit 0, 587 packages
  • ✅ resulting tree: no top-level ajv; eslint/node_modules/ajv at 6.15.0
  • the lockfile stays cross-platform. Platform entry counts are identical before and after — win32 76, darwin 75, linux-x64 46, android 40. --os/--cpu steer resolution without narrowing the lockfile to one platform, and --package-lock-only never touches node_modules.

⚠️ The full suite could not be run in the container. The only image Docker Hub would serve was node 20, and jsdom 30's undici requires node ≥22 (webidl.util.markAsUncloneable is not a function). CI runs node 22, so the check on this PR is the real test verification — it should be green for the first time since 64f18f0.

TODO housekeeping

  • removed ci-broken-ajv-lockfile-drift.md — resolved by this commit
  • updated investigate-emnapi-lockfile-drift.md — marks option 2 confirmed working, with the exact flags and the evidence above, and narrows the remaining work to the one thing still missing: a CI guard running npm ci --dry-run on any lockfile change

That guard is the real fix. Both incidents reached main and were caught a merge later; the manual recipe is now solved, but without the guard there will be a third. Left as the open item in that TODO rather than bundled here.

Test plan

  • npm ci on Linux — exit 0
  • Tree layout correct (no top-level ajv, nested eslint ajv@6)
  • Platform-specific entries unchanged (no narrowing)
  • package.json untouched; no version changes
  • CI green on this PR — the authoritative check

🤖 Generated with Claude Code

CI has been red on main since 64f18f0 ("Package Update Cleanup"): `npm ci`
failed in ~8s on a lockfile mismatch, before any test ran, on every branch.

    npm error Invalid: lock file's ajv@6.15.0 does not satisfy ajv@8.20.0
    npm error Missing: fast-uri@3.1.5 from lock file
    npm error Invalid: lock file's json-schema-traverse@0.4.1
                       does not satisfy json-schema-traverse@1.0.0

Cause

`ajv` is an *optional* peer dep of @hookform/resolvers
(peerDependenciesMeta.ajv.optional = true), and we do not use the ajv
resolver, so it should not be installed at all. The lockfile instead carried a
single hoisted top-level ajv@6.15.0 marked `devOptional` — a dedupe of
eslint's own ajv@6 — while npm's ideal tree wanted ajv@8.20.0 there to satisfy
the optional peer. Lock and ideal tree disagreed, and `npm ci` refuses to
guess.

Fix

Regenerated with:

    npm install --package-lock-only --os=linux --cpu=x64

Net effect (142 lines, +116/-26):
- drops the bogus hoisted top-level ajv@6.15.0 and json-schema-traverse@0.4.1
- gives eslint and @eslint/eslintrc their own nested ajv@6.15.0 subtrees
- restores the bundled @tailwindcss/oxide-wasm32-wasi -> @emnapi/* subtree
  (@emnapi/core, runtime, wasi-threads, @napi-rs/wasm-runtime, @tybys/wasm-util,
  tslib) that a previous Windows install had pruned

That last part also clears the drift tracked in
.claude/TODO/investigate-emnapi-lockfile-drift.md, so the manual re-add
workaround that TODO describes is no longer needed.

package.json is untouched. No dependency versions changed — this is purely a
lockfile tree-shape repair.

Verification

- `npm ci` on Linux (container): exit 0, 587 packages
- resulting tree: no top-level ajv; eslint/node_modules/ajv at 6.15.0
- platform coverage unchanged, so the lockfile stays cross-platform:
  win32 76, darwin 75, linux-x64 46, android 40 — identical before and after.
  `--os`/`--cpu` steer resolution without narrowing the lockfile, and
  `--package-lock-only` leaves node_modules alone.

The full suite could not run in the container — the only image that would pull
is node 20, and jsdom 30's undici needs node >= 22
(`webidl.util.markAsUncloneable is not a function`). CI runs node 22, so the
run on this PR is the real test check.

TODO housekeeping

- removed ci-broken-ajv-lockfile-drift.md — resolved by this commit
- updated investigate-emnapi-lockfile-drift.md: marks option 2 confirmed
  working with the exact flags and the evidence, and narrows the remaining work
  to the one thing still missing — a CI guard running `npm ci --dry-run` on any
  lockfile change. Both incidents reached main and were caught a merge later;
  without that guard there will be a third.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@chriskehayias
chriskehayias merged commit 9de8875 into main Aug 21, 2026
2 checks passed
@chriskehayias
chriskehayias deleted the fix/deps-ajv-lockfile-drift branch August 21, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant