Skip to content

fix(lockfile): avoid lossy npm metadata drift rewrites#753

Merged
jdx merged 1 commit into
mainfrom
fix/npm-lock-overrides-roundtrip
May 18, 2026
Merged

fix(lockfile): avoid lossy npm metadata drift rewrites#753
jdx merged 1 commit into
mainfrom
fix/npm-lock-overrides-roundtrip

Conversation

@jdx

@jdx jdx commented May 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • make install drift checks aware of the parsed lockfile format
  • skip override / ignored optional metadata comparisons for npm and yarn locks because those formats do not round-trip that metadata as a lockfile-level snapshot
  • keep strict override drift behavior for aube-lock.yaml, pnpm-lock.yaml, and bun.lock

Root cause

package-lock.json does not serialize the top-level override snapshot that aube/pnpm/bun locks use for drift detection. Any non-empty package.json overrides block therefore made an npm lock look stale, so install re-resolved and rewrote the package-lock graph even when the override was unrelated.

That rewrite was npm-readable, but it could be lossy relative to npm’s original package-lock shape: platform optional package entries, optional flags, and peer metadata could be reshaped even though the user did not make a dependency change requiring a lockfile update.

Validation

  • cargo fmt --check
  • cargo test -p aube-lockfile
  • cargo test -p aube --no-run
  • cargo test -p aube-lockfile fresh_when_npm_lockfile_cannot_record_overrides
  • cargo test -p aube-lockfile stale_when_bun_lockfile_can_record_overrides
  • Discussion npm package-lock.json round-trip corrupts graph when package.json has any non-empty `overrides` #752 repro: npm package-lock.json stayed byte-identical after aube install --ignore-scripts
  • Forced rewrite check: npm accepted the aube-written package-lock via npm install --package-lock-only and npm ls --package-lock-only --all
  • Verified bun 1.3.14 writes top-level "overrides" into bun.lock, so bun remains strict
  • Verified Yarn 1.22.22 and Yarn 4.12.0 apply resolutions into package entries but do not write a top-level resolutions snapshot

Fixes discussion #752.

@greptile-apps

greptile-apps Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes spurious re-resolves for npm (and yarn) lockfiles caused by package.json override blocks that package-lock.json cannot serialise, so any non-empty overrides always made the npm lock look stale. The fix gates the overrides/ignoredOptionalDependencies drift comparison on a new kind_records_resolution_metadata predicate, keeping strict checking only for formats that actually round-trip that metadata (aube, pnpm, bun).

  • check_drift_workspace_for_kind / check_drift_for_kind are added as the new public API; all three call-sites in resolve.rs are migrated to pass the LockfileKind from the parse result.
  • resolution_metadata_drift_reason extracts the override + ignored-optional comparison into one helper, and the kind_records_resolution_metadata gate is a single matches! expression easy to audit against the full variant list.
  • Two regression tests are added: one confirming npm lockfile stays Fresh when the manifest has overrides, another confirming Bun stays Stale (bun.lock does serialise overrides, so strict checking is correct there).

Confidence Score: 5/5

Safe to merge — the change narrows when a lockfile is considered stale for npm/yarn formats, matching their actual on-disk capabilities, and the production install paths are all updated to pass the lockfile kind through the drift check.

The logic is straightforward: a single predicate gates the override/ignored-optional comparison on whether the lockfile format can round-trip that metadata. The bun.lock format does serialise overrides (confirmed in bun/read.rs and bun/write.rs), so treating Bun as strict is correct. All three call-sites in resolve.rs are migrated consistently. No existing strict-checking paths for aube or pnpm are changed.

No files require special attention.

Important Files Changed

Filename Overview
crates/aube-lockfile/src/drift.rs Refactors drift checks to accept a check_resolution_metadata bool; adds check_drift_for_kind / check_drift_workspace_for_kind public APIs; extracts resolution_metadata_drift_reason; adds kind_records_resolution_metadata gate (true for Aube/Pnpm/Bun, false for Npm/NpmShrinkwrap/Yarn/YarnBerry); two new regression tests verify npm lockfile stays Fresh with overrides and Bun stays Stale.
crates/aube/src/commands/install/resolve.rs All three check_drift_workspace call sites in run_lockfile_only and select_lockfile_result are updated to check_drift_workspace_for_kind, threading the LockfileKind from the parse result through the drift check.

Reviews (2): Last reviewed commit: "fix(lockfile): avoid npm override drift ..." | Re-trigger Greptile

Comment thread crates/aube-lockfile/src/drift.rs
Comment thread crates/aube-lockfile/src/drift.rs
@jdx jdx force-pushed the fix/npm-lock-overrides-roundtrip branch from e20727f to 960ef0b Compare May 18, 2026 13:56
@jdx jdx changed the title fix(lockfile): avoid npm override drift rewrites fix(lockfile): avoid lossy npm metadata drift rewrites May 18, 2026
@jdx jdx merged commit 21701d3 into main May 18, 2026
18 checks passed
@jdx jdx deleted the fix/npm-lock-overrides-roundtrip branch May 18, 2026 14:09
@greptile-apps greptile-apps Bot mentioned this pull request May 20, 2026
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