Repository navigation
Fix yarn berry missing portal:/link: copies (#1561) - #1571
Open
Mikola Lysenko (mikolalysenko) wants to merge 6 commits into
Open
Mikola Lysenko (mikolalysenko) wants to merge 6 commits into
Mikola Lysenko (mikolalysenko) wants to merge 6 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
A yarn berry portal: or link: dependency under another name whose relative target directory is missing (for example a git submodule CI didn't check out) is silently dropped today: hosted and vendored scans report success and vex attests not_affected, while the install that has the directory links an unpatched copy. Add regression tests for #1561 on the vex discovery, vendored berry and hosted engine paths. They fail on main. Assisted-by: Claude Code:claude-opus-5-5
A yarn berry portal: or link: dependency under another name gets its package and version only from its package.json. When a relative target was missing (an uninitialized git submodule, a generated or gitignored directory) or its package.json couldn't be read, the copy was treated like a link: to a plain asset directory and dropped. Scans reported success and vex attested not_affected, while the install that had the directory linked an unpatched copy. Such a copy is now unknown, like an absolute one: hosted warns redirect_copy_unpatched, vendored warns vendor_copy_unpatched, and vex withholds every package the lock wires. A link: to a directory that exists with no package.json is still ignored. Fixes #1561 Assisted-by: Claude Code:claude-opus-5-5
Say that a relative portal: or link: copy whose target is missing is treated like an absolute one, and that a link: to a directory with no package.json is not a package copy. Refs #1561 Assisted-by: Claude Code:claude-opus-5-5
A git submodule CI never checked out leaves an empty directory, not a missing one, and a package.json that is a Git LFS pointer or encrypted blob reads fine but is no JSON. Both were still dropped like a link: to plain assets, so scans stayed clean and vex attested not_affected. An empty target directory and a package.json that doesn't parse now make the copy unknown too. Only a non-empty directory with no package.json, or a parsed manifest with no versioned package, is still ignored. Also pass the root as "" to the project view so hosted and disk agree on portal:. targets, and share the hosted test fixture. Refs #1561 Assisted-by: Claude Code:claude-opus-5-5
Refs #1561 Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 15, 2026 09:33
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 1018077. Configure here.
Collaborator
Author
|
Ready for review at
Slack announcement not sent this run (Slack send unavailable); the next run retries. Generated by Claude Code |
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 #1561
Summary
A yarn berry
portal:/link:dependency under another name ("lp2": "portal:./vend/lp") whose relative target can't be read is now treated as an unknown copy of any version of any package, the same as an absolute one (#1540). Hosted warnsredirect_copy_unpatched, vendored warnsvendor_copy_unpatched, andvexwithholds every package that lock wires. Before this change the copy was dropped: scans reported success and VEX attestednot_affected, while the install with the target present linked unpatched bytes asnode_modules/lp2.Root cause
Such a copy's lock version is the placeholder
0.0.0-use.local, so only itspackage.jsonsays what it is. When reading that manifest yielded no identity, both the vendored/hosted copy finder (vendor/yarn_copies.rsother_name_copies) and VEX lockfile discovery (vex/discover/yarn.rsrecord_copies) treated "the read failed" the same as "read and found to hold no versioned package" (alink:to plain assets), and skipped the copy unless the path was absolute.Fix
One shared predicate,
yarn_copies::linked_copy_unknown, used by both callers. A linked copy is unknown when it is:portal:/link:copy with an absolute path, so hosted and vendored scans succeed and every VEX path attests not_affected while that copy installs unpatched #1540),package.jsonthat isn't a readable regular file, or isn't JSON (a Git LFS pointer, an encrypted blob).It is not a package copy, and so stays ignored per the #1551 review intent, only when it is a non-empty directory with no
package.json, or a parsed manifest naming no versioned package.CopyRef::is_unread_linkedis folded into the predicate. The berry vendored warning keeps the "installs a package" wording for every unidentified linked copy.docs/ecosystems.mdnow spells out the missing / empty / LFS cases.Tests (red → green)
vex::discover::yarn::tests::issue_1561_unreadable_relative_portal_and_link_targets_contest_every_ref(portal/link × missing, empty, manifest-is-a-directory, LFS pointer)vendor::yarn_berry_lock::tests::issue_1561_missing_relative_portal_and_link_targets_are_named(portal/link × missing, empty, LFS pointer; plain asset directory control stays unnamed)vendor_copy_unpatchedhosted_memory_engine::issue_1561_berry_missing_relative_portal_and_link_copies_are_named(+ control: a target whosepackage.jsonnames another package is not flagged)redirect_copy_unpatchedThe first commit (87d9321) holds only the tests, which failed on main as listed. The
empty/lfs-pointervariants came from the pre-ready/code-review highpass.Commands run locally (Linux, as root):
cargo fmt --all -- --check: okcargo clippy --workspace --all-features -- -D warnings: okcargo test --workspace --all-features --no-fail-fast: 14,563 passed. The 10 failures are environment-only and touch no yarn code: write-failure / read-only-parent tests that can't fail when run as root (e.g.copy_tree::relax_loop_must_not_traverse_symlinked_root,pypi_requirements::wire_failure_rolls_back_already_written_files,repair_*,redirect_json_mode_write_failures_emit_error_envelope), ande2e_bun_lockb::binary_shared_bundled_record_hosted_pin_is_managed, which needs the live patch API (sandbox tunnel blocked). CI runs non-root with network.SOCKET_PATCH_YARN_E2E_REQUIRED=1):e2e_redirect_yarn_berry_build37/37,e2e_vendor_yarn_berry_build44/44,e2e_yarn4_pnpm_linker_build40/40,e2e_yarn4_workspaces_build39/39.npm/,pypi/,gem/) only dispatch to the binary and need no change./code-review high: findings not fixed
package.jsonin the snapshot (the new control test shows such a file is read and honoured). When the host leaves it out, the copy is now flagged as possibly unpatched instead of silently dropped. Dropping it was the fail-open this issue reports. Flagging matches how memory mode already treats an unreadfile:directory copy at its lock version (Yarn classic renamed-copy detection (#1489) misses afile:copy outside the project root and a tarball whose root isn'tpackage/, so scans succeed and VEX attests while that copy installs unpatched #1516). Teaching path selection to fetch linked targets' manifests would mean parsing yarn.lock before the fetch, which is a separate change. Follow-up if wanted.other_name_copiesprobes withProjectView::Disk(syncis_dir) rather than group-commit-aware helpers. The read beside it usesread_regular_to_byteson the same disk path. No caller runs this inside an open group commit before the lock rewrite, and onestatper linked candidate is negligible. Left as is.🤖 Generated with Claude Code
Generated by Claude Code