Skip to content

test(yarn): version-matrix e2e capstones — yarn2/3 refusal pins, berry workspaces + pnpm-linker install proofs - #200

Open
Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
mainfrom
test/yarn-version-matrix-capstones
Open

test(yarn): version-matrix e2e capstones — yarn2/3 refusal pins, berry workspaces + pnpm-linker install proofs#200
Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
mainfrom
test/yarn-version-matrix-capstones

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Why (empirical basis)

A 36-cell yarn version-matrix e2e sweep (2026-08-18, against real production data) proved three behaviors WORK today that no test pinned:

  1. yarn 2 (2.4.3) / yarn 3 (3.8.7) locks are refused cleanly by both lockfile-touching modes. Hosted redirect refuses per-file with warning code redirect_yarn_berry_cache_unsupported (scan exits 0, yarn.lock byte-identical); vendored refuses per-package with errorCode vendor_yarn_berry_cache_unsupported (exit 1, status partial_failure, zero mutations, no .socket/vendor artifacts). Until now the cacheKey gates were only unit-tested against synthetic lock strings — a regression against a REAL yarn 2/3 lock (e.g. a partial rewrite before the refusal fires) would have shipped unseen.
  2. yarn 4 workspaces (nodeLinker: node-modules, root + member with the patched dep): hosted redirect and vendored wiring both rewire the MEMBER's dep from a root scan; fresh --immutable --check-cache installs serve the patched bytes.
  3. yarn 4 nodeLinker: pnpm (berry's node_modules/.store symlink layout): discovery crawls the layout and hosted + vendored work end-to-end — previously unmentioned anywhere in code or tests.

What each capstone pins (test-only PR, no production code)

e2e_yarn_legacy_cachekey_refusal_build.rs (4 tests)

One cell per yarn-version × compression combo, each doing a REAL corepack yarn@2.4.3 / yarn@3.8.7 install of left-pad@1.3.0, then:

  • cacheKey pin: asserts the lock carries the empirically observed cacheKey — 7 / 7c0 (yarn 2, default / compressionLevel 0) and 8 / 8c0 (yarn 3). If a future corepack pin emits a different cacheKey this assertion fails FIRST with a self-describing message, so the refusal contract is never asserted against a lock the test no longer generates.
  • hosted refusal: scan --mode hosted → exit 0, status: success, redirect.redirected == 0, zero rewritten files, warning CODE redirect_yarn_berry_cache_unsupported (with the observed cacheKey named in the detail), yarn.lock + package.json byte-identical, no .socket/vendor.
  • vendored refusal: scan --mode vendored → exit 1, status: partial_failure, download.downloaded == 1 (the refusal is at the wiring step, not discovery), per-package failed event with errorCode vendor_yarn_berry_cache_unsupported, byte-identity of both files, no .socket/vendor, no spilled blobs.

e2e_yarn4_workspaces_build.rs (2 tests)

Root (ws-root, no deps) + packages/app member depending on left-pad@1.3.0, real corepack yarn@4.12.0:

  • hosted: root scan redirects the member's dep (__archiveUrl + real 10c0 checksum via the bootstrap-resolution trick from the redirect sibling), neither package.json touched, workspace lock entries stay workspace-resolved; fresh checkout of committable files only passes yarn install --immutable --check-cache offline-from-registry and the member resolves the PATCHED bytes through yarn node.
  • vendored: vendor --offline puts resolutions on the ROOT package.json (member byte-identical), file: locator in the lock; same fresh-checkout + member-resolution proof; --revert restores root package.json AND yarn.lock byte-for-byte and removes .socket/vendor.

e2e_yarn4_pnpm_linker_build.rs (2 tests)

Same shapes with .yarnrc.yml nodeLinker: pnpm, plus layout-specific assertions: node_modules/left-pad is a symlink, .store holds the backing entry (a left-pad-file-<hash> store entry for the vendored leg — proving the vendored tarball, not the registry, fed the store), and yarn node's require.resolve serves the patched bytes through the symlinks.

All three suites follow the existing sibling patterns exactly (e2e_redirect_yarn_berry_build.rs / e2e_vendor_yarn_berry_build.rs): corepack soft-skip with println, per-file wiremock helper, marker blob + hashes computed from installed bytes, cache_env::isolate cache sandbox, seed-then-scrub YARN_* tripwires. No [[test]] declarations needed (auto-discovered), no #[serial] (no tampered-twin cache hazard; every cell installs into its own tempdir with a private global folder).

CI-time note

Warm local timings: refusal suite 2.0s (4 tests), workspaces 1.9s, pnpm-linker 1.9s. Installs are left-pad-only. Cold CI adds one-time corepack downloads of yarn 2.4.3 and 3.8.7 (yarn 4.12.0 is already pulled by the existing berry suites) into the shared cache_env sandbox. All tests soft-skip with a println when corepack or the registry is unavailable.

Local evidence

  • cargo test -p socket-patch-cli --test e2e_yarn_legacy_cachekey_refusal_build — 9 passed (4 capstones + 5 cache_env selftests), refusal OK markers printed for all 8 legs (no skips)
  • cargo test -p socket-patch-cli --test e2e_yarn4_workspaces_build — 7 passed, HOSTED REWIRE / FRESH INSTALL + MEMBER RESOLUTION / VENDOR / REVERT all OK
  • cargo test -p socket-patch-cli --test e2e_yarn4_pnpm_linker_build — 7 passed, same markers incl. YARN NODE RESOLUTION
  • cargo clippy --workspace --all-features -- -D warnings — clean

No discrepancies vs the sweep: every behavior the sweep called pass reproduced under the new capstones.

🤖 Generated with Claude Code


Note

Low Risk
Adds integration tests only; no changes to CLI, core, or lockfile rewriting logic. CI may need corepack downloads for yarn 2/3 on cold runs.

Overview
Test-only PR — adds three new socket-patch-cli e2e suites (~1.9k lines) that pin Yarn Berry behaviors previously covered only by a matrix sweep or unit tests on synthetic locks. No production code changes.

e2e_yarn_legacy_cachekey_refusal_build.rs (4 tests) runs real corepack yarn@2.4.3 / yarn@3.8.7 installs, pins empirical cacheKey values (7/7c0, 8/8c0), and asserts hosted redirect and vendored scan refuse without mutating yarn.lock or package.json, with stable warning/error codes redirect_yarn_berry_cache_unsupported and vendor_yarn_berry_cache_unsupported.

e2e_yarn4_workspaces_build.rs (2 tests) uses a root + packages/app monorepo with yarn@4.12.0 and nodeLinker: node-modules: root scan --mode hosted rewires the member’s dep in the root lock; vendor --offline wires root resolutions and file: locator; fresh yarn install --immutable --check-cache and member yarn node resolution prove patched bytes; vendored --revert restores lockfiles byte-for-byte.

e2e_yarn4_pnpm_linker_build.rs (2 tests) mirrors hosted/vendored flows under nodeLinker: pnpm, with layout checks (node_modules/.store, symlinks, left-pad-file-* store entries) and yarn node resolution through the store layout.

All suites follow existing berry capstone patterns: cache_env::isolate, seed-then-scrub YARN_* env, wiremock for hosted legs, and soft-skip when corepack or the registry is unavailable.

Reviewed by Cursor Bugbot for commit 2c4a294. Configure here.

…y workspaces + pnpm-linker install proofs

A 36-cell yarn version-matrix e2e sweep (2026-08-18, real production
data) proved three behaviors work today that no test pinned:

1. yarn 2 (2.4.3) / yarn 3 (3.8.7) locks: hosted redirect refuses
   cleanly per-file (warning code redirect_yarn_berry_cache_unsupported,
   exit 0) and vendored wiring refuses per-package (errorCode
   vendor_yarn_berry_cache_unsupported, exit 1, partial_failure), both
   with zero mutations to yarn.lock/package.json and no .socket/vendor
   artifacts. The cacheKey gates were only unit-tested against synthetic
   strings — a partial rewrite before refusal on a REAL legacy lock
   would ship unseen.
2. yarn 4 workspaces (node-modules linker): a root scan rewires the
   MEMBER's dep in both hosted and vendored modes; fresh
   --immutable --check-cache installs serve the patched bytes and the
   member resolves them through yarn node.
3. yarn 4 nodeLinker: pnpm (.store symlink layout): discovery crawls
   the layout and hosted + vendored work end-to-end — previously
   unmentioned anywhere in code or tests.

New LOCAL capstones (corepack soft-skip, wiremock API, left-pad@1.3.0
marker blobs from installed bytes, cache_env isolation, seed-then-scrub
YARN_* tripwires — all mirroring the existing yarn berry siblings):

- e2e_yarn_legacy_cachekey_refusal_build.rs: 4 cells (yarn 2/3 ×
  default/compressionLevel-0), each pinning the empirically observed
  cacheKey (7, 7c0, 8, 8c0 — fails first with a self-describing message
  if a future corepack emits something else) and then the FULL hosted +
  vendored refusal contracts by CODE, exit status, envelope status, and
  byte-identity of yarn.lock/package.json.
- e2e_yarn4_workspaces_build.rs: hosted + vendored workspace capstones
  (root + packages/app member), incl. fresh-checkout install proofs,
  yarn-node member resolution, and byte-exact vendor revert.
- e2e_yarn4_pnpm_linker_build.rs: hosted + vendored pnpm-linker
  capstones, asserting the .store symlink layout (and the
  left-pad-file-<hash> store entry for the vendored leg) plus the same
  fresh-checkout, yarn-node, and revert proofs.

Test-only: no production source touched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2c4a294. Configure here.

// compact → pretty during install, so the on-disk bytes are the truth).
let lock_before = std::fs::read(&lock_path).unwrap();
let pkg_path = proj.join("package.json");
let pkg_before = std::fs::read(&pkg_path).unwrap();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bare unwraps in new tests

Low Severity

New e2e setup and fixture code uses bare .unwrap() on Result/Option values (tempfile::tempdir, std::fs::write/read/create_dir_all, serde_json helpers, and similar). That violates the project rule to prefer .expect("descriptive context") in new test code so CI panics name the failing step instead of a generic unwrap message.

Additional Locations (2)
Fix in Cursor Fix in Web

Triggered by learned rule: Prefer .expect("context") over bare .unwrap() in test code

Reviewed by Cursor Bugbot for commit 2c4a294. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant