Fix pnpm global-store transitive deps passing silently (#362) - #829
Open
Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
Open
Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
With pnpm's enableGlobalVirtualStore, a transitive dependency lives only in the machine-wide <store>/v<N>/links dir. The npm crawler never walked that dir, so agent apply treated the package as lockfile-only, exited 0 with "success", and Node kept loading the unpatched copy. The crawler now follows this project's links into the global store, and each entry's dependency links to sibling entries, so every copy the project loads is found at its real path. Apply then refuses it as shared, the same way it already refuses a direct dependency, and names the remedy. Packages other projects put in the store stay invisible. Fixes #362 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 5, 2026 07:08
Collaborator
Author
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0c5b583. Configure here.
Collaborator
Author
|
[burn-down agent] Marked Ready for review at head
Generated by Claude Code |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #362
Root cause
#365 fixed the custom
virtualStoreDirhalf of #362. With pnpm's global virtual store (enableGlobalVirtualStore),node_modules/.modules.yamlrecordsvirtualStoreDir: ../../store/v10/links, which is outside the project. The npm crawler deliberately ignores a store outside the importer. So a transitive dependency, which lives only at<store>/v<N>/links/@/<name>/<version>/<hash>/node_modules/<name>, was never found. Since #555 a lockfile-resolved miss counts as a calm "lockfile-only" skip, so agentapplyexited 0 withsuccessand Node kept loading the unpatched copy. A direct dependency is found through itsnode_modules/<dep>link and already got the loud shared-store refusal from #486.Fix
npm_crawler.rs: newreachable_pnpm_global_virtual_store_entries_sync. When.modules.yamlnames a real pnpm global virtual store (<store>/v<N>/linkswith the store'sfiles/beside it), the scan walk (gather_node_modules) and the apply/rollback resolver (find_by_purls) follow only this project's part of it. They start from the importer's links into the store, then follow each entry's dependency links to sibling entries, scoped ones included, with cycles handled. The sharedlinksdir is never listed, so packages other projects put in the store stay invisible.apply_failed,partialFailure, exit 1) with the "set enableGlobalVirtualStore to false and reinstall, or use hosted / vendored mode" remedy. It is no longer passed off as lockfile-only.shared_store.rs: the GVSlinksdir test is factored intois_pnpm_global_virtual_store_dir, so the crawler and the refusal gate share one definition.docs/ecosystems.md: describes the reachable-entries walk and the transitive refusal.npm/,pypi/andgem/only dispatch to the binary.Test evidence
applyrefuses, not lockfile-only success)tests/apply/pnpm_global_virtual_store.rs::transitive_global_virtual_store_dep_is_refused_not_skippedsuccess)…::other_projects_global_virtual_store_entries_stay_invisiblenpm_crawler::tests::test_pnpm_global_virtual_store_reachable_entries_are_walkedReal pnpm check (pnpm 10.28.0, Linux,
enableGlobalVirtualStore: true,is-odd@3.0.1→ transitiveis-number@6.0.0, hand-staged manifest):apply --offline --jsonnow givespartialFailure,apply_failed"Refusing to patch …/store/v10/links/@/is-number/6.0.0//node_modules/is-number: it is in pnpm's global virtual store …", exit 1, and the store copy is unchanged. Onmainthe same run givessuccess,package_not_installed"lockfile-only", exit 0.Local runs:
cargo clippy --workspace --all-features -- -D warnings: clean.cargo test --workspace --all-features: everything passes except 12 tests. All 12 rely on chmod-based write refusals that don't fire as root (this sandbox runs as root, CI doesn't), and none of them touch the crawler.e2e_safety_pnpm: needs patches-api access, which this sandbox doesn't have. CI covers it.CI on
0c5b583: every workflow is green. Bun compatibility (macOS 1.3.10) first failed on patches-api connect timeouts and passed on a single rerun. Bugbot reviewed0c5b583and found no issues.🤖 Generated with Claude Code
Generated by Claude Code