fix(arborist): remove stale .bin shims after uninstall under linked (#9632)
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`, `npm uninstall <pkg>` removed the package's top-level symlink and its `.store` entry but left its shim in `node_modules/.bin` behind as a dangling link. The leftover shim can break tools that enumerate `node_modules/.bin`, shadow a later-installed binary of the same name, and is not healed by a subsequent `npm install`. ## Why A linked reify builds the actual tree for the diff from the ideal tree (`#buildLinkedActualForDiff`), so a removed dependency is never compared against what is on disk and the diff emits no action to drop its bin shim. The top-level symlink and store entry are already cleaned by the post-reify sweep, but bin shims were not covered by it. ## How `reify.js` `#cleanOrphanedStoreEntries` now also builds `binsByDir`: while collecting the valid top-level links per `node_modules` directory, it records the bin names each still-linked package provides from `child.package.bin`. The new `#cleanStaleBinLinks` then removes any `.bin` entry whose base name (after stripping a `.cmd`/`.ps1` suffix) is not provided by a surviving package, or which is a dangling symlink. Matching by name keeps the check cross-platform across POSIX symlink shims and Windows `.cmd`/`.ps1` shim files, and reuses data already in the ideal tree without adding a dependency. Shims for packages that survive the uninstall are preserved. ## References Fixes #9613
M
Manzoor Wani committed
981e2498589c83859b3c9e8b92a2cc67562dc06b
Parent: 6968015
Committed by GitHub <noreply@github.com>
on 6/24/2026, 6:17:22 PM