Repository navigation
Fix npm alias links missed from a member (#1494) - #1500
Merged
Mikola Lysenko (mikolalysenko) merged 4 commits intoOct 13, 2026
Merged
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Run from inside a vlt, pnpm or npm-linked workspace member, apply
reported a member's npm alias dependency ("lp": "npm:left-pad@1.3.0")
as package_not_installed and exited 1, and rollback could not restore
it, although scan had offered the patch. The member's node_modules is
the only root walked there, and its alias entry is only a link into
the root store, which the resolver never takes as a copy.
Apply's and rollback's lookups now add the root links whose target is
a requested package, the same pass path scoping got in #1470. Both
commands already act on each physical copy once, so a run from the
root still patches the store copy a single time.
Fixes #1494
Assisted-by: Claude Code:claude-opus-5-5
Apply, rollback, get and vendor now take a workspace member's alias link only for a package they found no other copy of. When a copy was found, apply already patches every store variant of it, so taking the link as well visited one variant twice and reported a phantom already_patched (or already-original on rollback). It also kept a first-party alias link beside a patched registry copy from turning a clean run into a refusal, and skips the link pass whenever every package resolves. Path-scoped scan and rollback still match every link. Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 13, 2026 20:05
Collaborator
Author
|
BugBot review Generated by Claude Code |
Run from a workspace member, apply now patches an alias dependency through the member's link into the root store, but apply --check and vex looked copies up without that link. The check reported the package as not installed and exited 0. They now use the same lookup as apply, which takes a root link only for a package with no other copy. Two vex_consumed tests assumed the resolver never returns a link. They now check that it returns the same copies the identity fallback finds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0195pcxXZ2GXtByX1L8egMhJ
Tanmay Singla (Tanmay182003)
approved these changes
Oct 13, 2026
Collaborator
Author
|
bugbot run 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 6104e76. Configure here.
Collaborator
Author
|
Ready for review (burn-down agent)
Generated by Claude Code |
Mikola Lysenko (mikolalysenko)
deleted the
agent/fix-npm-member-alias-link-lookup
branch
October 13, 2026 22:59
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 #1494
Summary
When run from inside a vlt, pnpm or npm-linked workspace member,
applyreported the member's npm alias dependency ("lp": "npm:left-pad@1.3.0") aspackage_not_installedand exited 1.rollbackcouldn't restore that dependency either, even thoughscanhad offered the patch through the same link. Both commands now patch and restore it.Root cause
From a member directory, the npm resolver's only root is the member's own
node_modules. Under a root-store layout the alias entrypackages/a/node_modules/lpis just a symlink into the root store. The resolver's direct probe looks fornode_modules/left-pad, and its alias pass skips links on purpose (#856), so no copy was found. #1470 had already closed the same gap for path-scoped matching only (find_package_paths_for_path_scope+npm_links_to).Fix (
crates/socket-patch-cli/src/ecosystem_dispatch.rs)dispatch_find_with_npm_links. It is now used by path scoping (every link, as before) and by the copy lookups:find_all_packages_for_purls(apply),find_all_packages_for_rollback[_reusing](rollback) andfind_packages_for_rollback_reusing(get, vendor).find_manifest_package_copies_reusing(apply --check,vex) gets the same unresolved-only pass (Bugbot finding: run from the member,--checkreported the patched copy aspackage_not_installed). Twovex_consumedtests whose setup assumed the resolver never returns a link now check that it returns the same copies as the identity fallback.NpmLinks::ForUnresolved). The pre-ready/code-review highshowed why this matters: when the resolver has already found a copy, the apply engine's store fan-out reaches every peer variant of it. Taking a member link to another variant on top of that visited it twice and brought back Agent-mode apply in a pnpm workspace reports each member-linked package twice, inflating the --json skipped count with duplicate already_patched events #633's phantomalready_patched/ already-original event. Restricting the pass also keeps a first-partyfile:alias link next to a patched registry copy from turning a clean run into a refusal. And the pass is skipped entirely when every purl resolves, so the common case pays nothing extra.Test evidence
.store)apply::in_process_npm_multicopy::apply_and_rollback_reach_a_member_alias_link_from_the_member: apply, re-apply and rollback from the member, then apply and rollback from the root (one visit)package_not_installed,partialFailureecosystem_dispatch::tests::multi_copy_lookups_take_a_member_alias_link_into_the_root_store--checkmisses member aliasapply --checksteppackage_not_installedapply::in_process_npm_multicopy::apply_and_rollback_visit_a_member_alias_peer_variant_onceI also reproduced the issue with real pnpm 10.28: a workspace with
packages/adepending on"lp": "npm:left-pad@1.3.0"and a hand-staged manifest. Run frompackages/awith the fixed binary,apply --offlineexits 0 withapplied, and the root store'sleft-pad/index.jsis patched (require.resolve('lp')resolves to it).rollbackthen givessuccesswithrolledBack: 1and restores the bytes.Local runs:
cargo fmt --all -- --check: cleancargo clippy --workspace --all-features -- -D warnings: cleancargo test -p socket-patch-core -p socket-patch-cli --all-features --lib --test apply --test rollback --test scan --test get --test in_process_vendor --test cli: every CLI target passes (920 lib, 135 apply, 111 rollback, 87, 133, 59, 131). 4socket-patch-corelib tests fail locally because they rely on read-only permissions and this sandbox runs as root (e.g.copy_tree::relax_loop_must_not_traverse_symlinked_root: "removal cannot succeed under a read-only parent"). This PR doesn't touch core, so CI is the check there.cargo test --workspaceran out of this sandbox's disk allowance while linking test binaries, so I ran the targeted suites above instead. CI covers the rest.Review findings not fixed
get_node_modules_pathserrors are swallowed and the walk is retried": this was already the behavior in path scoping, andNpmCrawler::get_node_modules_pathsalways returnsOk, so there's no real failure path.🤖 Generated with Claude Code
https://claude.ai/code/session_0195pcxXZ2GXtByX1L8egMhJ
Note
Medium Risk
Changes core npm package discovery for apply, rollback, check, and vex; behavior is gated to unresolved PURLs and covered by extensive regression tests for #633 and #1494.
Overview
Fixes #1494: when
apply,rollback,apply --check, orvexrun from a workspace member, npm alias dependencies that only exist as a rootnode_modulessymlink (vlt/pnpm/npm linked layouts) are no longer reported aspackage_not_installed.Package resolution now goes through shared
dispatch_find_with_npm_links, which runs the normal crawl and then optionally appends matching root-level symlinks vianpm_links_to. Copy lookups (find_all_packages_for_purls, rollback variants,find_manifest_package_copies_reusing) useNpmLinks::ForUnresolvedso links are added only when the crawler found no install path—avoiding a second visit when the root store copy already exists (#633 phantomalready_patched). Path scoping still usesNpmLinks::All(#1266).Tests cover member-alias apply/rollback/check across store layouts, resolver behavior from member vs root, and peer-variant alias links visited once from the repo root.
Reviewed by Cursor Bugbot for commit 6104e76. Configure here.
Generated by Claude Code