Skip to content

Fix yarn classic copy identity read two ways (#1951) - #1984

Merged
Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-yarn-classic-copy-identity
Nov 2, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-yarn-classic-copy-identity

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1951

Summary

Hosted scans now identify a yarn classic file: directory or tarball-URL copy through formats::yarn::copy (classic_copy_ref, CopyRef::read_path, CopyRef::identity). That is the reader vendored and VEX already use. The second reader in formats/yarn/source.rs (classic_file_directory, classic_copy_real_name) and its third dir/package.json join are deleted.

Root cause

classic_file_directory normalized the file: path through a Cargo helper (cargo_workspace::normalize_rel) that drops any path leaving the root. For lp2@file:../ext/lpdir, hosted never read the copy's package.json, so the yarn rewriter never named it. Only the engine's generic post-run fallback (redirect_copy_unpatched) caught it, whereas an in-root copy gets redirect_yarn_classic_directory_skipped and is counted in bundled_skipped_uuids. Vendored and VEX read the same copy (#1516), so the modes disagreed.

Changes

  • formats/yarn/copy.rs: new classic_copy_name(patterns, resolved, version, read_text) over classic_copy_ref + identity. It is gated to the Directory and RemoteTarball-URL copies the old function handled; a file: tarball still needs bytes, which a text reader can't give.
  • hosted/engine.rs: reads each directory copy's manifest at CopyRef::read_path(). Out-of-root paths are read, as vendored and VEX read them; absolute paths are never read.
  • patch/redirect/mod.rs: the yarn classic rewriter calls classic_copy_name.
  • formats/yarn/source.rs: the duplicate reader is deleted.
  • e2e_redirect_yarn_classic_build: classic_outside_root_copy_under_another_name_is_named_and_not_attested now expects the out-of-root copy to be named exactly once, with the code an in-root copy gets (redirect_yarn_classic_directory_skipped). The VEX assertions are unchanged.

Test evidence

Issue Regression test Without fix With fix
#1951 patch::redirect::tests::issue_1951_yarn_classic_copy_named_as_vendored_reads_it (in-root, file:../ext, file:/abs and codeload: hosted names a copy iff vendored identifies it) FAIL (out-of-root directory: []) pass
#1951 hosted::engine::tests::issue_1951_yarn_classic_copy_manifests_read_as_vendored_reads_them (disk view reads ../ext/lpdir/package.json, never the absolute one) FAIL (None) pass

Run locally on 0c263ae:

  • cargo fmt --all -- --check: ok.
  • cargo clippy --workspace --all-features -- -D warnings: ok.
  • cargo test -p socket-patch-core --all-features: 6997 passed. 4 failed, and the same 4 fail on main in this container, because it runs as uid 0, so chmod-based write-failure tests can't fail: copy_tree::relax_loop_must_not_traverse_symlinked_root, vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry, pypi_poetry::wire_write_failure_maps_error_and_leaves_lock_untouched and pypi_requirements::wire_failure_rolls_back_already_written_files.
  • cargo test -p socket-patch-cli --all-features --lib: 940 passed.
  • scripts/yarn-classic-vex-matrix.sh 1.22.22: every VEX cell passed. e2e_redirect_yarn_classic_build failed only on the out-of-root test above, as expected, and passes 42/42 after the update.
  • The full cargo test --workspace ran out of the container's disk building all CLI test binaries, so CI covers the rest of the CLI integration suites.

No wrapper changes are needed: npm/, pypi/ and gem/ only dispatch to the binary.

/code-review high: findings not fixed here

https://claude.ai/code/session_011f9aeRqL3jx1o1HYCU4NK4


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
Hosted scans name a yarn classic file: directory copy through their
own reader, which drops a copy outside the project root (file:../x)
that vendored and VEX read and name. Add regression tests for the
rewriter and the hosted manifest read, plus the shared reader they
will use.

Refs #1951

Assisted-by: Claude Code:claude-opus-5-5
A hosted scan named a yarn classic file: directory or url copy
through its own reader in formats/yarn/source.rs, which dropped a
directory outside the project root (file:../ext/x). Vendored and VEX
read that copy and named it, so hosted reported a clean pin while
yarn kept installing the unpatched out-of-root copy, without the
directory-skipped warning vendored gives.

Hosted now reads the copy's manifest and identity through
formats::yarn::copy (classic_copy_ref, CopyRef::read_path and
identity), the same reader vendored and VEX use: out-of-root copies
are read, absolute paths never are. The second reader and its third
dir/package.json join are deleted.

Fixes #1951

Assisted-by: Claude Code:claude-opus-5-5
A yarn classic file: directory copy outside the project root is now
named by the yarn rewriter, with the same
redirect_yarn_classic_directory_skipped warning an in-root copy gets,
instead of the engine's generic redirect_copy_unpatched fallback. The
e2e now asserts that code, and that the copy is named exactly once.
The rewriter test's doc says what it compares: which package the copy
holds.

Refs #1951

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review November 2, 2026 11:00
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 0c263ae. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Nov 2, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[burn-down agent] Labeled Ready for review at 0c263ae.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Final review brief

What it does. Hosted scans now read which package a yarn classic file: directory or tarball-URL copy holds through the same reader vendored and VEX already use (classic_copy_ref + CopyRef::identity), and the duplicate reader in formats/yarn/source.rs is deleted. So an out-of-root copy like lp2@file:../ext/lpdir is now named by the yarn rewriter (redirect_yarn_classic_directory_skipped) exactly as an in-root copy is, instead of only by the generic post-run fallback.

Risk: low. Narrow change in one rewriter's identity lookup. The one widening is that hosted now reads package.json from out-of-root relative paths named in the lock; this matches what vendored and VEX already read (#1516), absolute paths are still never read, and these manifests are advisory only: I checked that no rewriter writes them back (the yarn rewriter only inserts yarn.lock).

Look here

  • copy.rs:177: new classic_copy_name, gated to Directory/RemoteTarball copies
  • engine.rs:700: which manifests the hosted run reads (now CopyRef::read_path, out-of-root allowed, absolute refused)
  • redirect/mod.rs:4593: rewriter switched to the shared reader
  • redirect/mod.rs:13765 and engine.rs:4337: regression tests (in-root / ../ / absolute / codeload)
  • e2e_redirect_yarn_classic_build.rs:1639:`` e2e expectation now asserts the copy is named once, with the in-root code

Verified

  • Read the full diff; description matches the code; no CHANGELOG.md change, no debug leftovers.
  • cargo test -p socket-patch-core --all-features --lib -- issue_1951 yarn on 0c263ae: 403 passed.
  • CI on 0c263ae: ci-ok and clippy green (32 success, 50 skipped by path filters, 0 failed). Bugbot: passed. No unresolved review threads.

Changes I made: none.

Open questions: none blocking. The PR body lists pre-existing gaps it leaves alone (hosted still skips an unidentified copy that vendored keeps as a possible copy; file: tarball copies under another name). Worth a follow-up issue, not this PR.

Auto-merge is armed, so approving sends it straight to the merge queue.


Generated by Claude Code

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[agent] Reviewed 0c263aedcbccdd28b505b97cf6378a072f5943c6. Checked shared Yarn classic copy identity and advisory directory-manifest reads. No major correctness issues found. Validation: source and regression-test review plus the available exact-head CI checks; no local test pass is claimed.

@mikolalysenko
Mikola Lysenko (mikolalysenko) added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit bd2db4b Nov 2, 2026
82 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/fix-yarn-classic-copy-identity branch November 2, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resolve a yarn classic file:/url copy's identity through formats::yarn::copy only: source.rs keeps a drifted second reader that hosted uses

3 participants