Fix berry mode takeover reverting before gates (#468, #369) - #470
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
This was referenced Oct 1, 2026
Switching a yarn berry package between hosted and vendored mode removed the old mode's wiring before checking whether the new mode could wire that package. When the new mode then skipped or refused it, the package ended up patched in neither mode: - vendored -> hosted: a grant without the yarnBerry10c0 cache checksum deleted the vendored patch, then skipped the redirect, and the run still exited 0 saying the package was fully hosted (#468). - hosted -> vendored: another locked version of the name or a user-authored resolutions entry restored the registry entry, then failed vendoring with vendor_override_conflict (#369). Both takeovers now run the target mode's per-package gates first and leave the existing mode byte-identical, reporting the gate's own code, as CLI_CONTRACT.md already promises. Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 1, 2026 14:32
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 83bb9a9. Configure here.
Collaborator
Author
|
Ready for review at
Generated by Claude Code |
Mikola Lysenko (mikolalysenko)
enabled auto-merge (squash)
October 1, 2026 16:52
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 #468
Fixes #369
Summary
Switching a yarn berry package between hosted and vendored mode removed
the old mode's wiring before checking whether the new mode could wire
that package. When the new mode then skipped or refused it, the package
ended up patched in neither mode. Both takeovers now run the target
mode's per-package gates first and, on a refusal, leave the existing
mode byte-identical and report the gate's own code. This is what
CLI_CONTRACT.md already promises ("refuses before reverting").
Root cause (shared)
Each berry takeover preflight only covered the project-level gates
(line endings, cacheKey, compressionLevel). The per-package gates ran
after the revert:
commands/scan/hosted.rs, Vendored → hosted takeover on yarn berry deletes the vendored patch, then skips the hosted rewrite when the grant has no yarnBerry10c0 checksum, and still exits 0 "fully hosted" #468): the berryrewriter's per-dep
redirect_yarn_berry_missing_checksumgate (a grantwith no
yarnBerry10c0checksum, which vendored mode never needs) ranafter
dispatch_revert_onehad deleted the vendored wiring, ledgerentry and artifact. The run then exited 0 with "now fully hosted".
commands/vendor.rstakeover invendor_records_reusing, reached byscan/get --mode vendoredandvendorwith the service, Hosted → vendored takeover on yarn berry reverts the hosted redirect before a per-package vendor refusal, leaving the package unpatched in both modes #369):resolutions_gateandscan_berry_target(another locked version of the name, a userresolutionsoverride, non-npm protocol, mixed or duplicate entries)ran after
restore_upstreamhad already removed the hosted pin.Changes
patch/redirect: newpreflight_yarn_berry_hosted_dep(dep). Therewriter now uses it for its missing-checksum skip, and the takeover
uses it as well, so the two can't drift apart.
scan/hosted.rs: the takeover refusal also runs the per-dep gatefor berry-vendored entries. Refusal warnings are deduplicated by full
warning instead of by code, so each purl's detail is kept.
vendor/yarn_berry_lock.rs: newyarn_berry_vendor_target_preflight(root, purl)runs the backend'sresolutions_gate+scan_berry_targetagainst the still-hostedfiles. The verdict matches the restored files, because the hosted
redirect only rewrites the target entry's
resolution:/checksum:lines and never its key, other entries or package.json.
vendor.rs: the hosted→vendored takeover runs that per-targetpreflight after the cached project-level one, before
restore_upstream.Tests
crates/socket-patch-cli/tests/in_process_vendor.rs)berry_vendored_to_hosted_takeover_keeps_vendored_without_berry_checksum(wet +--dry-run)redirect_yarn_berry_missing_checksumrefusal; takeover announced)berry_hosted_to_vendored_takeover_runs_package_gates_first(other locked version, userresolutions; wet +--dry-run)vendor_takeover_reverted_redirect, hosted pin gone)The #369 test passes
--patch-server-urlso the vendor run recognisesthe hosted pin as a takeover. Without it, the run takes the eject path,
which was already safe.
Local runs:
cargo clippy --workspace --all-features -- -D warnings: clean.cargo test -p socket-patch-cli --test in_process_vendor berry_: 6/6 ok.scripts/yarn-berry-vex-matrix.sh 4.12.0(withCOREPACK_NPM_REGISTRY=https://registry.npmjs.org, becauserepo.yarnpkg.com is blocked in this sandbox): all yarn 4 suites ok. The
two
yarn@2.4.3legacy-cachekey legs could not get yarn 2 here (it isnot on the npm registry); they are unrelated refusal tests.
cargo test --workspace --all-features --no-fail-fast: everythingpasses except:
in this sandbox. They fail identically on a main-based branch.
mode_migration_npmberry_*_takeover_*(2): they panic in fixturesetup (
mode_migration_npm.rs:351, the test's ownreqwestfetch ofregistry metadata hits the sandbox's TLS proxy,
UnknownIssuer)before any CLI code runs. CI runs them.
cargo fmt --checkreports the same pre-existing diffs asmain(CIdoesn't gate on fmt); the files this PR adds are rustfmt-clean.
Follow-ups
packageManagerset: the two-document pnpm-lock.yaml makes vendor refuse, andvendor --revert, rollback and the hosted takeover half-revert the project and break frozen installs #466 item 4 (pnpm vendored → hosted) is the same takeover-orderingshape for pnpm, but its main cause is the two-document pnpm 12 lock.
It is tracked there and not changed here.
🤖 Generated with Claude Code
Note
Medium Risk
Changes ordering of yarn berry hosted/vendored takeover and revert paths; incorrect behavior previously left projects in a broken neither-mode state, so the fix is behavior-changing but aligns with the documented refuse-before-revert contract.
Overview
Fixes yarn berry mode takeovers (#468, #369) so the target mode’s per-package gates run before any revert of the current wiring. Previously, vendored→hosted could strip vendored state and then skip hosted redirect when the grant lacked
yarnBerry10c0; hosted→vendored could remove the hosted pin before berry’sresolutions/lock gates refused vendoring—leaving the package patched in neither mode while the CLI could still report success.Vendored→hosted (
hosted.rs): berry takeover refusal now includespreflight_yarn_berry_hosted_dep(shared with the berry rewriter in core). Refusal warnings dedupe by full warning JSON; skip reasons use the gate’s code.Hosted→vendored (
vendor.rs): after project-level berry preflight, runs newyarn_berry_vendor_target_preflighton the still-hosted tree beforerestore_upstream.Core: extracted
preflight_yarn_berry_hosted_dep; addedyarn_berry_vendor_target_preflightwrapping the backend’s per-target gates. Tests: regression coverage for missing berry checksum on takeover and for package gates before hosted→vendored revert (wet + dry-run).Reviewed by Cursor Bugbot for commit 83bb9a9. Configure here.
Generated by Claude Code