fix(arborist): repair wrong-but-existing symlink target in linked strategy (#9628)
In continuation of our exploration of using `install-strategy=linked` in the [Gutenberg monorepo](https://github.com/WordPress/gutenberg/pull/75814), which powers the WordPress Block Editor. Under `install-strategy=linked`, if a top-level `node_modules/<dep>` symlink points to a store key that exists on disk but is the **wrong version**, re-running `npm install` does not repair it. npm reports success and leaves the dependency resolving to the wrong version. This is the state an interrupted update leaves behind: the new store key is extracted but the symlink has not yet been repointed. A symlink pointing at a **non-existent** target is already repaired on reinstall; only a wrong-but-existing target slips through, because cleanup validates the link name, not its target. ## Why For linked installs, `#buildLinkedActualForDiff` synthesizes the "actual" tree the diff compares against from the **ideal** children, never reading the real on-disk symlink target. So a link whose on-disk target is a valid-but-wrong store key looks identical to the ideal node, the diff reports no change, and the symlink is left untouched. The hoisted strategy is unaffected because it self-heals the analogous corruption. ## How In `#buildLinkedActualForDiff`, when an existing link's resolved on-disk target differs from its ideal target, skip creating a synthetic actual entry for it. With no actual entry to match, the diff treats the link as an `ADD`, and `#reifyNode` removes the old symlink and recreates it pointing at the correct store key. A new `#linkTargetMismatch` helper compares the two resolved targets; it runs only after the existing `existsSync` guards, so both paths are known to exist. This repairs both the top-level symlink and wrong transitive/sibling links inside the store, and leaves already-correct trees untouched (no spurious relinking on an idempotent reinstall). ## References Fixes #9611
M
Manzoor Wani committed
0ffce98cb6f2e189fa3a866c1ba1209293fb48f9
Parent: 981e249
Committed by GitHub <noreply@github.com>
on 6/24/2026, 6:33:55 PM