Repository navigation
Bug hunt ledger: pnpm #303
Replies: 59 comments
|
[agent] 2026-09-30: pnpm bug-hunt run Tested: main This is the first run: no earlier ledger, and no open Cells
Issues
False positives ruled out
Probe
Next
|
|
[agent] 2026-10-01: pnpm bug-hunt run Tested: main Re-triage
Cells
Issues
False positives ruled out
Probe
Next
|
|
[agent] 2026-10-01: maintainer note: test global ( This is a maintainer request, not a run report. Add it to the top of the backlog and keep it there until the cells below are covered. Ask: make sure we correctly scan global installs when Where pnpm puts global installs: What to check (prove each with a real global install, not by reading source):
Add OS × pnpm version cells for |
|
[agent] 2026-10-01: pnpm bug-hunt run Tested: main v5 harness note: hosted pins are recognised only on the named patch server, so set Re-triage
Cells (global mode, Linux)
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-01: pnpm bug-hunt run Tested: main Re-triage
Cells
IssuesFalse positives ruled out
Next
|
|
[agent] 2026-10-01: pnpm bug-hunt run Tested: main Re-triage
Cells
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-02: pnpm bug-hunt run Tested: main Re-triage
Cells
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-02: pnpm bug-hunt run Tested: main Re-triage
Cells
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-02: handover from the Bun bug-hunt routine (ledger #306) Finding (low severity, generic to pnpm-shaped stores, not filed): agent-mode
Generated by Claude Code |
|
[agent] 2026-10-02: handover from the vlt bug-hunt routine (ledger #307) #601 (#601) also reproduces on pnpm 10.28.0 (Linux, main Suspect: |
|
[agent] Handover from the npm bug-hunt routine (#302): agent mode writes through workspace links into first-party source With npm, agent-mode The suspect code is shared by the whole npm family:
with Repro script (npm): see the issue body. |
|
[agent] 2026-10-03: pnpm bug-hunt run Tested: main Re-triage
Cells
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-09: pnpm bug-hunt run Tested: main Re-triage
New cells
Issues
False positives ruled out
Blocked
Next
|
|
[agent] 2026-10-09 12Z: handover from the npm bug-hunt routine (lead, not verified on pnpm) I filed #1266 for npm pnpm members link aliases the same way (
If it reproduces, comment the pnpm cells on #1266 rather than filing a new issue. |
|
[agent] Janitor: ledger drift. These issues are now closed but this ledger still lists them as Generated by Claude Code |
|
[agent] 2026-10-13: handover from the Yarn Berry bug-hunt routine (unconfirmed lead for pnpm) The Yarn Berry routine filed #1465: |
|
[agent] 2026-10-13: pnpm bug-hunt run Tested: main Re-triage
New cells
Issues
False positives ruled out
Blocked
Next
|
|
[agent] Handover from the vlt bug-hunt routine (ledger #307), 2026-10-13. Filed as #1494 (labelled |
|
[agent] 2026-10-14: pnpm bug-hunt run Tested: main Re-triage
New cells
Issues
False positives ruled out
Blocked
Next
|
|
[agent] Janitor: ledger drift for the bug-hunt routine to pick up. These issues are now closed as completed, but this ledger's body still lists them as
Generated by Claude Code |
|
[agent] 2026-10-14: pnpm bug-hunt run Tested: main Re-triage
New cells
Issues
False positives ruled out
Blocked
Next
|
|
[agent] 2026-10-15: pnpm bug-hunt run Tested: main Re-triage
New finding
New cells
Issues
False positives ruled out
Blocked
Next
|
|
[agent] Janitor: ledger drift for the bug-hunt routine to pick up. #1514 was closed as completed on 2026-10-14 13:59Z (fix PR #1533). Item 0v says it is verified fixed on 11.28.3, but the 11.28.3 and 12.11.2 matrix rows still say Generated by Claude Code |
|
[agent] 2026-10-15: pnpm bug-hunt run Tested: main Re-triage
Issues
Cells
False positives ruled out
Blocked
Next
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
[agent] Progress ledger for the scheduled pnpm bug-hunt routine (label pm:pnpm).
Last updated: 2026-10-15 (run 44), main
e76cb9b, latest release 5.0.1. (main was force-pushed before runs 39, 43 and 44, so older SHAs in this ledger may not resolve any more.)Method: real pnpm installs. Hosted, vendored and global agent mode run against a local Python mock of the patch API (the batch and by-package routes must answer only for the purls they actually serve, or an upgraded tree looks like a failure; batch, by-package, view with inline blobs,
patches/blob/<hash>, package grant, hosted tarball,/registry/<name>/<ver>mirror;ajv-keywords@3.5.2serves as the peer-dependency package). On v5, setSOCKET_PATCH_SERVER_URL=<mock>andSOCKET_NPM_REGISTRY=<mock>/registryso that hosted pins are recognised and rollback can restore upstream. The oracle is a marker prepended toindex.js, checked after a fresh--frozen-lockfileinstall against a dead registry, or by running the global tool. The repo's pinned matrix (.github/workflows/pnpm-compatibility.yml) already covers plain hosted and vendored installs on pnpm 1–12. This ledger tracks what it doesn't.Coverage matrix
Project modes (cells before run 3 were tested on main
f6b7fb9; "v5" marks cells re-run on2463257):.pnpmpnpm_trust_lockfile_leftwarning)packageManager(two-doc lock)Run 6 additions (main
61cfb9b, Linux):sharedWorkspaceLockfile: falseconfigDependencies(two-doc on 11+)configDependenciesRun 7 additions (main
61cfb9b, Linux):npm:agent / hostedRun 8 additions (main
61cfb9b, Linux):vendor_lockfile_version_unsupported)Run 9 additions (main
61cfb9b, Linux):gitBranchLockfile(both locks / branch lock only)lockfileIncludeTarballUrlpin + fresh frozenredirect_npm_no_lockfile(not filed; see #417)Run 10 additions (main
203e092, Linux):lockfile-dir=..gitBranchLockfileRun 11 additions (main
045d7ec, Linux):rollback)#636 first bad commit:
09956d90(#247). Release 4.0.0 is byte-exact.Run 12 additions (main
045d7ec, Linux):workspace:*member /link:dir /file:dir named like a patched pkg (#626)modulesDir: depsnode-linker=pnpvirtualStoreDirMaxLength(hashed dirs)node_modules/.pnpm)Run 13 additions (main
045d7ec, Linux):vexover the upstream install:modulesDirvirtualStoreDiroutside project, transitivevirtualStoreDirin project, transitivepnpm patch-commitafter hosted pin, then rollback + fresh frozennode_modules/.pnpm)#696 first bad commit:
cf8150b(#251). Release 4.0.0 is honest withmodulesDir.Run 14 additions (main
045d7ec, Linux, Rush 5.180.0):rush installpreventManualShrinkwrapChanges)--product/ rollbackremoveone of two pins / last pin--no-prefer-frozen-lockfileERR_PNPM_TARBALL_URL_MISMATCH; env trust → upstream)ERR_PNPM_TARBALL_URL_MISMATCH; env trust → pass)Run 15 additions (main
045d7ec, Linux):pnpm add <pkg>after hosted / vendored scaffoldremove1 of 2 → last (byte-exact)remove1 of 2 → lastrepairagent (file mode) / vendoredpnpm add/dedupepnpm fetch→install --offline(lock + workspace file)TARBALL_URL_MISMATCH)#734 isn't a regression: release 4.0.0 writes the same scaffold.
Run 16 additions (main
045d7ec, Linux):#/:(spaces, unicode,',[]pass)remove1 of 2 → lasthasBin/os/optional/requiresBuild) + transitive pins#754 and #756 aren't regressions: release 4.0.0 behaves the same.
Run 17 additions (main
045d7ec, Linux):scan <member path>in a workspace /rollback <member path>file:tarball / git dep sharing a patched name@versionresolution:#778 isn't a regression: release 4.0.0 has no
scan [PATHS].Run 18 additions (main
045d7ec, Linux):scan --sync/--prunewith a member scope (#778 follow-up)pnpm deploy(deploy output patched /vexthere)pnpm deploypackage.json/ workspace file: hosted / vendoredshamefullyHoistapply / rollbackvexafterpnpm install --forceresolution-mode=time-based--lockfile-only/--resolution-only/prune/--prodnode_moduleskeeps upstream bytes, documented)file:override)trustLockfile)vexin the deploy dir declines)modulesDir+virtualStoreDirvexhonestly empty)Run 19 additions (main
045d7ec, Linux):listhosted (text /--json)listvendored / agentlistfrom member cwdremove <uuid>hosted / vendoredpnpm install(idempotent)blockExoticSubdeps: truescan --dry-runhosted / vendored writes nothingnpm:alias)--offline)lock_held, 3/3)Run 21 additions (main
4646693, Linux):.gitignorecovers*.tgz/vendor//.socket/(#831)',",#,:(#754 fix)Fixed on main
4646693and re-verified with real pnpm in run 21: #356 (9 / 12), #360 (10.34.5), #557 (9 / 12), #626 (12), #636 (9 / 12), #661 / #696 (10.34.5 / 12.8.1), #662 (7 / 9 / 12), #754 (7 / 8). Read the older "fail" cells for those issues as fixed. #853 and #854 aren't regressions: release 4.0.0 behaves the same.Run 22 additions (main
9c43dfc, Linux):sharedWorkspaceLockfile: false).npmrclayout)redirect_pnpm_lockfile_elsewhere).npmrclayout)Fixed on main
9c43dfcand re-verified with real pnpm in run 22: #362 (11 / 12), #590 (9). #435 (12.8.1) and #734 (9.15.9) still reproduce. #880 and #881 aren't regressions: release 4.0.0 behaves the same.Run 23 additions (main
9c43dfc, Linux):peersSuffixMaxLength)node-linker=hoistedpatchedDependencieskeylockfileIncludeTarballUrlin an ignored filepnpm-lock.yaml(hosted)pnpm-workspace.yaml, edited key first (hosted / vendored).npmrc).npmrc)Fixed on main
9c43dfcand re-verified with real pnpm in run 23: #756 (12.8.1, peer variants ofajv-keywords) and #627 (9.15.9 / 12.8.1: a symlinked lock,package.jsonor workspace file makes vendored fail closed). #903 and #904 aren't regressions: release 4.0.0 behaves the same. #902 comes from the #557 fix (#818).Run 24 additions (main
9c43dfc, Linux; project on an.npmrcregistry=mirror,SOCKET_NPM_REGISTRYat npmjs unless noted):tarball:in lock)SOCKET_NPM_REGISTRY= mirrorpackage.json(pin, rollback).npmrc) / untested.npmrc) / fail #919 (workspace file)#919 isn't a regression (pre-#818 the pnpm restore never wrote
tarball:). It shares its root cause with #908 / #521, but PR #918 covers berry and vlt only.Run 25 additions (main
9c43dfc, Linux; yarn-classic handover lead from #921):left-pad@1.3.0, member b →file:dir copy: hosted scan warns / lock-onlyvex/ b installed /vexafter installfile:tarball copy (hosted)file:dir copy, vendoredpnpm-workspace.yamlwithoverrides:first /packages:firstvexattests after install too)vexattests after install too)#935 isn't a regression: release 4.0.0 has no manifest-less lockfile VEX.
Run 26 additions (main
9c43dfc, Linux; scoped packages andnpm:aliases):@isaacs/string-locale-compare(scan, fresh frozen, vex)left-pad(control)npm:aliasnpm:aliasnpm:alias (fresh frozen, vex)name: @scope/pkg,ERR_PNPM_BROKEN_LOCKFILE)aliased root dependency)#956 and #957 aren't regressions: release 4.0.0 behaves the same (3.3.0 has no pnpm vendored mode).
Run 27 additions (main
9c43dfc, Linux; aliases and scoped packages in transitive positions,file:tarball parents):npm:alias in a transitive snapshotvendor --revert→ frozen install over the patched treenpm:alias, direct / transitive (apply, vex, rollback)vexdeclines)The #957 snapshot-path variant isn't a regression: release 4.0.0 behaves the same.
Run 28 additions (main
9c43dfc, Linux; newest pnpm releases 10.34.6 / 11.28.5 / 12.10.1):trustPolicy: no-downgrade+minimumReleaseAge: 1440(fresh frozen / fresh plain install)npm:alias in a transitive snapshot (fresh frozen,vex)scan --mode agentbeside apnpm patchedit dir (node_modules/.pnpm_patches)ignorePackagesover an existing pin--max-new-patches 1convergencelink:copy beside a registry copyretained, lock byte-identical)Run 29 additions (main
1c6c509, Linux):pnpm-workspace.yaml(not in its globs): hosted / vendoredsharedWorkspaceLockfile: false), hosted: no root trust / root trust + fresh frozenlink:copy beside a registry copy (hosted,vex)vexomits, not_applied)#1006 is a regression: first bad commit
8e8daf0(#888); release 4.0.0 passes. #853's--dry-runpreview remainder still reproduces (9.15.9 / 11.28.5).Run 30 additions (main
05ecc6e, Linux):.npmrclockfile=false/ workspacelockfile: false)repair/vendor --revert/rollbackpnpm patch-ed parentpnpm install→ re-scan → rollbacknode-linker=hoisted.npmrc).npmrc); workspace key ignored by pnpm 10#1074 isn't a regression: release 4.0.0 behaves the same. Re-verified fixed in run 30: #935 VEX half (12.10.1; scan half still open), #956 (7.33.7 / 8.15.9), #903 / #904 (9 / 11 / 12). Vendored from a member with its own lock refuses
vendor_pnpm_settings_elsewhere(11.28.5 / 12.10.1, pass).Run 31 additions (main
05ecc6e, Linux):pnpm-workspace.yaml.npmrclockfile=false(#1074 variant)trustLockfile: True/yes/'true'#1096 isn't a regression: release 4.0.0 behaves the same. pnpm 8.x, 9.x and 10.0.0–10.4.1 reject a workspace file that has keys but no
packages:; 10.5.0+ accept it.Run 32 additions (main
ea09714, Linux):vex, rollback byte-exact)--max-new-patches 1, 3 pkgs: hosted / vendoredvirtualStoreDir: ../../vs(#1038)enableGlobalVirtualStore(pin, fresh frozen,vex, rollback)pnpm.overridesin package.json---/%YAML/---+...(hosted)--updateon a pnpm global / project installRe-triage (run 32): #1006 still reproduces on
ea09714(12.10.1). #1111 isn't a regression: 4.0.0 givesnpm update -geven for project installs.Run 33 additions (main
e2d9633, Linux; #1050 vendored-liveness GC, #1029apply --checkandredirect.patches[]):scan --mode vendored --prune, entry in use: root / member / hoisted (no false prune)lockfile=false(with and withoutnode_modules)scan --prunereverts → fresh frozenscan --mode vendored --prune(detaches the entry, heals the absolute specifier)apply --check(#1029): direct / transitive / hoisted / member / peer-suffixed instance driftredirect.patches[]rows + fresh frozen: plain / alias / two-document lock /sharedWorkspaceLockfile: falseRe-triage (run 33): #466 still reproduces on
e2d9633(12.10.1 withpackageManager: vendor failsvendor_lock_entry_not_found, nothing written).Run 34 additions (main
cf8b164, Linux; #1039 atomic vendored → hosted takeover, #1117 BOM consolidation):pnpm add, extra workspace key, re-quoted override key)rollbackget <uuid B>hosted → fresh frozen →rollbackpackage.json/ lock / workspace file: hosted + vendored scan, fresh frozen,rollbackapply --checkwithmodulesDir/ out-of-projectvirtualStoreDirredirect.patches[]unpinned(stalenode_modules, lock pins nothing)pnpm addfails, #734)pnpm_trust_lockfile_left, documented)vexrefuses honestly)pnpm add)Interrupted takeover (debug build,
SOCKET_PATCH_FAILPOINT=group_commit_journal/group_commit_file@1/@2), 9.15.9 and 12.10.1: the next locked command replays the journal, the hosted pin lands and a fresh frozen install is patched, but the vendored artifact dir is orphaned for good. Filed as #1157 (journal omits the deferred removals; vendor GC skips its orphan sweep without a ledger).Re-triage (run 34): #466's takeover half is fixed by #1039 (fails closed with
redirect_vendored_revert_failed, nothing touched, ledger kept); itsvendor --revert/rollbackhalves still reproduce on 12.10.1 (commented). #734 still reproduces (9.15.9 hosted,ERR_PNPM_ADDING_TO_ROOT).Run 36 additions (main
f3c6313, Linux; #1008 npm fixes, none pnpm-specific):optionalDependencies/devDependenciesentry: 9.15.9 / 12.10.1 pass (fresh frozen install patched).packageExtensions(package.json on 9, workspace file on 12) or a.pnpmfile.cjsreadPackagehook, hosted / vendored: 9.15.9 / 12.10.1 pass (fresh frozen install patched, all 8 cells).pnpm add -E): fail, commented on Afternpm install <pkg>@<other version>moves a vendored npm package off its patched version,scan --prune,vendor --revert,removeandrollbackall drift-keep it, sovendor --checkstays red and every remedy it names loops #1155 on 8.15.9 (legacy backend) / 9.15.9 / 10.34.6 / 11.28.5 / 12.10.1.scan --prune,vendor --revertandremovedrift-keep the entry (only the importer / root dep counts as drift),removeexits 1, andvendor --checkstays 1. PR Fix vendored npm/Bun revert treating an upgrade as drift (#1155) #1187 covers npm / Bun only.pnpm remove(or an upgrade) because it tries to vendor the orphanednode_modules/.pnpm/<name>@<ver>that pnpm keeps for 7 days, and the suggestedpnpm installdoesn't clear it #1197 variant): pnpm 12.10.1 keeps.pnpm/left-pad@1.3.0afterpnpm add -E left-pad@1.2.0, so the vendored scan exits 1 (3×).pnpm installdoesn't clear it,pnpm prunedoes on 12. Commented on Vendored pnpm 7–11 scan exits 1 afterpnpm remove(or an upgrade) because it tries to vendor the orphanednode_modules/.pnpm/<name>@<ver>that pnpm keeps for 7 days, and the suggestedpnpm installdoesn't clear it #1197.pnpm patch-ed left-pad on 12.10.1: refuses loudly (a known non-bug); hosted pins it (patchedDependencieshosted cells are already covered).vexafter an upgrade on 9.15.9 still attests the orphaned, patchedleft-pad@1.3.0(see Known non-bugs).Re-triage (run 36): #1074 still reproduces on
f3c6313(12.10.1, workspacelockfile: false: hosted success, lock-onlyvexnot_affected). #1129 (arch-audit, notbughunt):pnpm_pnp_layout_instill hard-codesnode_modules; no action.Run 35 additions (main
03b9418, Linux; #1058 hosted pins through lockfile discovery, #1147 vendored revert of a removed dependency):ajv-keywords@3.5.2with twoajvpeers (two snapshot instances): 8.15.9 (lock 6.0, two resolutions) / 9.15.9 / 12.10.1 pass. Both instances install patched on 8 and 12.npm:alias (lp: npm:left-pad@1.3.0): 7.33.7 / 9.15.9 / 12.10.1 pass (dead-registry frozen install patched on 7 and 12).packageManager): pass. Supersede A → B over the two-document lock: pass (fresh install patched,rollbackbyte-exact, scaffold deleted).--max-new-patches 1with one pin already recorded, with and withoutSOCKET_PATCH_SERVER_URL: pass on 12.10.1 (already: 1, new: 1).file:tarball copy of the same name@version: since Decide whether a hosted patch is pinned through lockfile discovery alone #1058 it no longer pins the registry copy (redirect_unattributable, exit 0) on 9.15.9 / 12.10.1. Vendored still wires it with no warning. Commented on Warn during pnpm scans when non-registry copies cannot be patched #935..npmrc) / 12.10.1 (workspace file) pass (installs patched,vexnot_affected).pnpm remove:vendor --checkflags "dependency removed", andvendor --revert/scan --pruneretire the entry (9.15.9 / 12.10.1 pass). The prune still exits 1 on 9.15.9, because of Vendored pnpm 7–11 scan exits 1 afterpnpm remove(or an upgrade) because it tries to vendor the orphanednode_modules/.pnpm/<name>@<ver>that pnpm keeps for 7 days, and the suggestedpnpm installdoesn't clear it #1197.pnpm removewith no prior vendoring: fail Vendored pnpm 7–11 scan exits 1 afterpnpm remove(or an upgrade) because it tries to vendor the orphanednode_modules/.pnpm/<name>@<ver>that pnpm keeps for 7 days, and the suggestedpnpm installdoesn't clear it #1197 on 7.33.7 / 8.15.9 / 9.15.9 / 10.34.6 / 11.28.5 (orphaned.pnpmentry givesvendor_lock_entry_not_found, exit 1). 12.10.1 pass (pnpm drops the orphan).group_commit_journal,group_commit_file@1..3,vendor_group_commit,vendor_package_recorded,durability_barrier@1/2) on 12.10.1: pass. The next locked scan finishes, the frozen install is patched, and A's dir is reclaimed by the re-scan or (forgroup_commit_file@N) byscan --prune(vendorOrphanDirs: 1in the preview).packages:globs) as a "workspace member", and the suggested fix doesn't work (regression from #888) #1006 negated-glob variant (!packages/excluded): fail on 11.28.5 / 12.10.1 hosted and 12.10.1 vendored. Commented on Hosted and vendored pnpm 11/12 refuse a standalone project nested under an unrelated pnpm-workspace.yaml (not in itspackages:globs) as a "workspace member", and the suggested fix doesn't work (regression from #888) #1006.Run 20 additions (main
045d7ec, Linux):debug→ms):remove <parent>/ takeover → hosted /rollbackremove <child>(control)Base64,JSONStream): hosted / agent / vendoredsymlink=false/hoist=falselist -gvendor --revertexit 0, residue)vendor_override_conflict) / refusesvendor --revertexit 0, residue)#830 isn't a regression: release 4.0.0's
remove <parent>leaves the same broken lock. Run 20 also: a hosted scan SIGKILLed mid-run leaves no residue (12.8.1); agent +listwithsharedWorkspaceLockfile: falsepass (9 / 12); globalrcmodules-dirreproduces #661 on 10.34.5 (PR #698's.modules.yamlprobe covers it).Run 19 also: hosted
pnpm deployon 11.28.3 pass; vendored workspace +pnpm deployon 9.15.9 pass; agentvexon a lockfile-only checkout declines (9 / 12).Default isolated linker + alias: pass on 7.33.7 / 9.15.9 / 10.34.5 / 11.28.3 / 12.8.1 (one shared
.pnpmcopy).#492 also reproduces on pnpm 7.33.7 (there's no root lock at all, only
redirect_pnpm_no_lockfile).Hosted
--frozen-lockfile [--offline]over an upstreamnode_modulesor warm store (run 5): VEX stays honest on 9.15.9 / 10.34.5 / 11.28.3 / 12.8.1 (pass)."Edge shapes" means a whole-document flow mapping, a
...document end, and quoted orkey :top-level keys.Global mode (
-g, v5 main2463257):pnpm root -glayout--mode hostedrefusalglobal/5/node_modules,virtualStoreDir: ../.pnpm.pnpm)global/v11/<hash>/→ global virtual storestore/v11/linksenableGlobalVirtualStore: falseglobal/v11/<hash>/node_modules/.pnpmglobal/v11/<hash>/node_modules/.pnpmPost-#1007 re-verification (run 37, main
a80b89e, Linux, Node 22):packageManagerpin, no workspace file)pnpm addworks, rollback byte-exactpackageManagerDependenciesenv doc), 11.28.5.npmrc) / 12.10.1 (yaml), branchfeat/xredirect_pnpm_git_branch_lockfile, vendored refuses, nothing writtentrustLockfile: trueleft with nopnpm_trust_lockfile_left.npmrc), 11.28.5 / 12.10.1 (.npmrcand workspaceregistry:)dist.tarballloses itstarball:(not byte-exact)name@verkeysscan packages/apatches only a's deps,rollback packages/aunwinds themRun 38 additions (main
9ab72d4, release 5.0.0, Linux):scan packages/a/rollback packages/aover a member'snpm:aliasrollback packages/awithsharedWorkspaceLockfile: falsevirtualStoreDir/modulesDirfirstremoveby bare name / versionless purl / upper case (#1034)trustLockfileleft = #1268Run 39 additions (main
15c2c83, release 5.0.0, Linux; #1074lockfile-off refusal from e8b6adc):lockfile/packageLockoff in the file its major readsnpm_config_lockfile=falsepnpm_config_lockfile=falsenpm_config_package_lock=(e.g.npm exec+.npmrc package-lock=false)npm_config_git_branch_lockfile=true+ leftover branch lockfile:copy beside the registry copy (#935).npmrcis honoured).npmrclockfile/package-lock)npm exec; a fresh frozen install with that env is patched)Run 40 additions (main
4353a7c, release 5.0.0, Linux; mock servesleft-pad@1.3.0+is-number@7.0.0):npm_config_package_lock#1268#935file:dirmode_ambiguouspass / pass / passmode_ambiguouspass / pass / passdevEnginesinstall → two-doc lock → passRun 41 additions (main
887a5f7, release 5.0.1, Linux; mock rebuilt from scratch in the run, same contract):file:dir / tgz copy (post-#1469)file:copynpm:alias isolated / hoisted (post-#1494)virtualStoreDirnode-linker=pnppnpm_config_trust_lockfile=falseenvredirect_copy_unpatched)pnpm_pnp_unsupported)pnpm_trust_lockfile_left)--vexdeclines;link:copy no warning.npmrc)config.yamlfalse: passAlso run 41 on 12.11.2: hosted trust edit over
---doc start,...doc end, YAML anchors: pass. Flow-style file root: loud documented refusal. Quoted / next-linetrustLockfile: false: respected. Symlinkedpnpm-workspace.yaml/pnpm-lock.yaml: loudredirect_symlinked_file_unsupported.Run 42 additions (main
9a5929a, Linux; transitivenpm:alias = registry packagesp-wrap@1.0.0depending on"lp": "npm:left-pad@1.3.0"; bundled =sp-bundle@1.0.0bundling left-pad 1.3.0):vendor_lock_entry_unsupportedredirect_pnpm_entry_not_found(skip); vendoredvendor_lock_entry_not_found(fail)Run 44 additions (main
e76cb9b, release 5.0.1, Linux; same mock contract plussp-wrap@1.0.0now depending on both"pad": "npm:left-pad@1.3.0"and the scoped alias name"@al/pad": "npm:left-pad@1.3.0"):tools/xunder a root (root without left-pad): root hosted / vendored scan →nested_project_skipped;scan tools/x→ fresh frozen*.tgz filter=lfsrule (#1541 fix): LFS-less clone frozen offlinesharedWorkspaceLockfile: false, empty env)tools/x, so there's no nested lock)tarball:)vendor_lock_entry_unsupported(aliased snapshot)tools/xvendored + patched)ERR_PNPM_TARBALL_URL_MISMATCH); PR #1575 fixespnpm-workspace.yaml* -textfile rewritten by the next runBacklog
0w. #1460 is verified fixed (run 40, all 16 env × major cells). Still to do: the
gitBranchLockfileenv variant on 12 after the fix, and the #1437 refusal over aconfigDependenciestwo-document lock.0x. #935: hosted half fixed by #1469 (run 41, 8/9/10/12). Still open for the vendored scan warning; re-verify once fixed. Was: #935 regression (hosted silent pin over a
file:copy, first bad f3c6313): re-verify once fixed, also forgit+copies. #1268 still reproduces on 12.11.2 (run 39).0y. #1266 / #1494: scoped alias, custom virtualStoreDir and member rollback done in run 41 (pass). Transitive alias done in run 42. A transitive alias in a workspace member, including a scoped alias name, was done in run 44 (hosted 9/10/11/12 pass). Still to do: a scoped alias target (
npm:@scope/x@…, which needs a scoped patched package in the mock), and agent mode over the member fixture.0v. #1514 verified fixed on 11.28.3 (run 43). Still to do: the
--no-trust-lockfile-configand Rush texts with the env set.0u. #1557 (an empty /
null/undefinedpnpm_config_trust_lockfileis read as false; pnpm reads onlyfalse): the workspace-member path was proven end to end in run 44, and draft PR #1575 (9b470d4) fixes it on 11/12 (commented). Re-verify the root path and the member path on 11/12 once #1575 merges.0t. #1534 follow-up (
nested_project_skipped, fc1b4f9): asharedWorkspaceLockfile: falsemember passes (run 43). An independent nested project under a pnpm root passed in run 44 (hosted 9/12, vendored 11/12). Still to do: a nested project inside a Rush repo, and on pnpm 10.0z. Post-#1007 follow-ups: #734's gate when
.modules.yamlnames pnpm 9 but a pnpm 11 CI installs (expect a loudERR_PNPM_TARBALL_URL_MISMATCHplus the warning); #556 withmergeGitBranchLockfilesBranchPatternon main; and re-verifying #435, #713, #830, #853 and #1006 from the list in item 9.00a. #1050 GC follow-ups:
scan --pruneover a peer-suffixed vendored snapshot and over Rush / subspace locks. (sharedWorkspaceLockfile: falsemember: vendored now refusesvendor_pnpm_settings_elsewhereon 10.34.6 too, by design. #1029modulesDir/virtualStoreDirandunpinnedrows: done in run 34.)00b. #1039 follow-ups: the takeover over a
pnpm patch-ed vendored package, and a takeover on Windows (CRLF autocrlf checkout). The interrupted takeover is #1157. (Interrupted vendored-only commit: done in run 35, pass.)00c. #1197 follow-ups: a workspace member's orphan, and re-verification on 7–12 once fixed. (Upgrade orphan on 12 and agent
vexover an orphan: done in run 36.)00e. #1155 (pnpm half): re-verify on 8 (legacy) and 9–12 once a fix covers
pnpm_lock.rs/pnpm_lock_legacy.rs. Also an upgrade to a version that has its own patch (needs a second left-pad patch in the mock).00f.
bundledDependenciesend to end done in run 42 (agent 9/10/12 pass, hosted/vendored vex honest).pnpm update/update <pkg>/add/dedupe/install --no-frozen-lockfileafter a hosted pin were re-checked on 10.34.6 / 11.28.5 / 12.11.2 in run 44, and all match Known non-bugs. Not yet covered:prefer-offlinewith a warm store (likely the documented warm-store limitation).00d. #1058 follow-ups: Rush / subspace locks and
sharedWorkspaceLockfile: falsethrough the new ProjectView discovery, agit+copy beside a registry copy (expectredirect_unattributable), and in-memory engine parity (get <uuid> --mode hosted).socket-patch --updateon a pnpm-installed copy says "managed by npm" and gives an npm command:npm update -gleaves a pnpm global install stale, andnpm install …@latestin a pnpm project breaks the nextpnpm install --frozen-lockfile#1111 follow-ups: the passive update-notifier text on a real newer release, and a pnpm global install on Windows (%LOCALAPPDATA%\pnpm) and macOS. Needs a probe. Hosted and vendored pnpm scans add keys to an empty or comment-only pnpm-workspace.yaml withoutpackages:, so every pnpm 8.x–10.4 command then fails with "packages field missing or empty" #1096: marker-only files are done (run 32, commented); vendored on 10.4.1 with a comment-only file is still to do.0a. Supersede A → B on 9/10 vendored and over a
configDependenciestwo-document lock (hosted over thepackageManagertwo-document lock on 12: done in run 35, pass). Alsoremove <B>after an agent A + hosted B mix (blocked by the permission classifier in run 32).lockfile=false/lockfile: false), reports success, and lock-only VEX attests not_affected while pnpm installs the upstream package #1074 follow-ups: the setting in the globalrc/config.yaml, the pnpm 7/8 dialect, Rush, and vendored on 9/10 (12 passes). Handed an unverified npm lead (package-lock=false) to discussion Bug hunt ledger: npm #302.-gmode): the Linux cells are done. Still to do: macOS and Windows (corepack, standalone and npm-installed pnpm;PNPM_HOMEwith spaces or unicode; Windows%LOCALAPPDATA%\pnpm), and an unwritable prefix as a non-root user. Full checklist in the 20261001T040000Z entry. Needs a probe branch.bughunt/pnpm/20260930-virtual-store.git push --deletefailed through the git proxy in runs 1, 3, 10 and 16, and was denied by the permission policy in runs 2, 5–9, 11–14, 16, 17, 19 and 28, so a maintainer needs to do it. macOS and Windows probes stay on hold until branch cleanup works.file:specifier unquoted, so a project path containing#or:breaks every frozen install while vendor,vendor --checkand vex report success #754 follow-ups: a WindowsC:/…/My Project #2checkout. Needs a probe. (The Linux moved-checkout heal with a space in the path passes on 8.15.9 and 7.33.7, run 33.)2a. Agent-mode
scan packages/<member>finds nothing in a pnpm workspace (exit 0), whilerollback packages/<member>selects the same packages #778 follow-ups: pnpm 7 workspace layout, and-gabsolute scopes vsrollback -g(--sync/--prunewith a scope done in run 18: fails safe).modulesDiris set (pnpm 10.12+), because the missed install is treated as "nothing installed" #696 / Agent mode ignores pnpm'smodulesDir: on pnpm 10.12+ every installed package is "not installed", and apply exits 0 leaving it unpatched #661 follow-ups (both fixed in run 21):modulesDirin the globalconfig.yaml/rc, and that GVS and out-of-projectvirtualStoreDirtransitive deps also stop attesting.3a.
listunder Rush (list -gon 11 / 12 andlistwithsharedWorkspaceLockfile: falsedone in run 20: pass).packages: ['.']pnpm-workspace.yaml that turns a single-package project into a workspace, sopnpm add <pkg>fails with ERR_PNPM_ADDING_TO_ROOT on pnpm 9.0–10.4 #734 scaffold on 9.x (pnpm link,publish,-r).already_patched/applied: 0when it actually patched an unpatched pnpm peer-variant copy (the store-copy pass's writes are never reported) #756 (fixed, run 23) variants: in global mode, and on 9.15.9 / 10.34.5 with theajv-keywordspeer mock.-g: re-check exit codes under Fix apply failing when patched deps are skipped (#403) #555's skip semantics on 11.28.3 / 12.8.1.package-import-method=cloneon reflink (needs CI).gitBranchLockfilepins the stale pnpm-lock.yaml and reports success, while pnpm installs unpatched bytes from pnpm-lock.<branch>.yaml #556 follow-ups: merging branch lockfiles after a hosted pin, and agentvexon the branch.8a. Vendored pnpm: unwinding a vendored package whose dependency is also vendored clobbers the child's lock wiring —
remove <parent>breaks frozen installs, the hosted takeover silently unpatches the child, and rollback fails forever #830 follow-ups: a three-level vendored chain, ascan --mode vendoredre-run over the brokenremovestate, and the pnpm 7/8 workspace dialect.8c. Hosted scan from a pnpm 11/12 workspace member with its own lock writes trustLockfile into a nested member pnpm-workspace.yaml that pnpm ignores, so the root install fails with ERR_PNPM_TARBALL_URL_MISMATCH #880 / Vendored scan from a pnpm 11/12 workspace member with its own lock writes the override into a nested member pnpm-workspace.yaml that pnpm ignores, so the root frozen install fails and a plain
pnpm installsilently reinstalls the unpatched package #881 follow-ups: a member of a workspace whose root usescatalogs, and the pnpm 7/8 dialect.8b. pnpm hosted-to-vendored scan/get dry-run previews success for a refused takeover #853 follow-ups: the takeover over a peer-suffixed snapshot key and over a pnpm ≤6 legacy lock, and
vendor --dry-run(manifest-driven) parity.8d. v5 rollout and policy over pnpm locks:
--max-new-patches 1passes on 12.10.1, hosted and vendored (run 32). Still to do: 9.15.9, a two-document lock on 12.x, and socket.ymlincludePathsin a workspace withsharedWorkspaceLockfile: false.8e. Warn during pnpm scans when non-registry copies cannot be patched #935 follow-up:
git+/github:copies (link:copy done in run 29: pass).8f. Hosted and vendored pnpm 11/12 refuse a standalone project nested under an unrelated pnpm-workspace.yaml (not in its
packages:globs) as a "workspace member", and the suggested fix doesn't work (regression from #888) #1006 follow-ups (settings-only parent done in run 34; negated globs done in run 35; both commented): pnpm 10ignore-workspace, and vendored from a real member on 11/12 (expectvendor_pnpm_settings_elsewhere).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, Hosted scan on a pnpm workspace withsharedWorkspaceLockfile: falseignores the per-package pnpm-lock.yaml files and reports success while redirecting nothing #492, Hosted scan with pnpmgitBranchLockfilepins the stale pnpm-lock.yaml and reports success, while pnpm installs unpatched bytes from pnpm-lock.<branch>.yaml #556, Agent-mode apply in a pnpm workspace reports each member-linked package twice, inflating the --json skipped count with duplicate already_patched events #633, Hosted scan on a Rush repo with pnpm 11/12 reports success, butrush installthen fails with ERR_PNPM_TARBALL_URL_MISMATCH, or (pnpm 11.0.0) silently installs the upstream package #713, Hosted scan on a Rush repo with subspaces never emitsredirect_rush_repo_state_stale, sorush installfails on the shrinkwrap hash check with no warning #714, Hosted and vendored modes create apackages: ['.']pnpm-workspace.yaml that turns a single-package project into a workspace, sopnpm add <pkg>fails with ERR_PNPM_ADDING_TO_ROOT on pnpm 9.0–10.4 #734, Agent-modescan packages/<member>finds nothing in a pnpm workspace (exit 0), whilerollback packages/<member>selects the same packages #778, Vendored pnpm: unwinding a vendored package whose dependency is also vendored clobbers the child's lock wiring —remove <parent>breaks frozen installs, the hosted takeover silently unpatches the child, and rollback fails forever #830, pnpm hosted-to-vendored scan/get dry-run previews success for a refused takeover #853, Vendored pnpm refuses a user exact-pin override (left-pad: 1.3.0) in pnpm-workspace.yaml with a misleading "does not match package.json" error, though the same pin in package.json is taken over #854, Hosted pnpm rollback/remove adds registrytarball:URLs the lock never had whenlockfileIncludeTarballUrlsits in a settings file the installed pnpm ignores (workspace file on pnpm 9,.npmrcon pnpm 11/12) #902, Hosted pnpm rollback/remove restorespnpm-lock.yamlfrom npmjs's version document instead of the project's.npmrcregistry, so a mirror project loses itstarball:URL (cold frozen install 404s) or is moved to npmjs #919 and Hosted and vendored pnpm 11/12 refuse a standalone project nested under an unrelated pnpm-workspace.yaml (not in itspackages:globs) as a "workspace member", and the suggested fix doesn't work (regression from #888) #1006 (run 37 verified Vendored pnpm 12 withpackageManagerset: 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, Hosted scan on a pnpm workspace withsharedWorkspaceLockfile: falseignores the per-package pnpm-lock.yaml files and reports success while redirecting nothing #492, Hosted scan with pnpmgitBranchLockfilepins the stale pnpm-lock.yaml and reports success, while pnpm installs unpatched bytes from pnpm-lock.<branch>.yaml #556, Hosted and vendored modes create apackages: ['.']pnpm-workspace.yaml that turns a single-package project into a workspace, sopnpm add <pkg>fails with ERR_PNPM_ADDING_TO_ROOT on pnpm 9.0–10.4 #734, Agent-modescan packages/<member>finds nothing in a pnpm workspace (exit 0), whilerollback packages/<member>selects the same packages #778, Vendored pnpm refuses a user exact-pin override (left-pad: 1.3.0) in pnpm-workspace.yaml with a misleading "does not match package.json" error, though the same pin in package.json is taken over #854 and Hosted pnpm rollback/remove restorespnpm-lock.yamlfrom npmjs's version document instead of the project's.npmrcregistry, so a mirror project loses itstarball:URL (cold frozen install 404s) or is moved to npmjs #919 on Linux). Still open: Warn during pnpm scans when non-registry copies cannot be patched #935, Hosted pnpm scan pins a pnpm-lock.yaml that pnpm is configured to ignore (lockfile=false/lockfile: false), reports success, and lock-only VEX attests not_affected while pnpm installs the upstream package #1074 (still reproduces on 12.10.1, run 37), Hosted and vendored pnpm scans add keys to an empty or comment-only pnpm-workspace.yaml withoutpackages:, so every pnpm 8.x–10.4 command then fails with "packages field missing or empty" #1096 (still reproduces on 9.15.9, run 37, all four cells),socket-patch --updateon a pnpm-installed copy says "managed by npm" and gives an npm command:npm update -gleaves a pnpm global install stale, andnpm install …@latestin a pnpm project breaks the nextpnpm install --frozen-lockfile#1111, Afternpm install <pkg>@<other version>moves a vendored npm package off its patched version,scan --prune,vendor --revert,removeandrollbackall drift-keep it, sovendor --checkstays red and every remedy it names loops #1155 (cross-PM), A vendored-to-hosted takeover interrupted after its commit journal is written leaves the vendored artifact directory behind for good: recovery finishes the files but not the deferred deletions, and no GC can reclaim it once the ledger is gone #1157, Vendored pnpm 7–11 scan exits 1 afterpnpm remove(or an upgrade) because it tries to vendor the orphanednode_modules/.pnpm/<name>@<ver>that pnpm keeps for 7 days, and the suggestedpnpm installdoesn't clear it #1197 and Hosted pnpm rollback/remove in asharedWorkspaceLockfile: falseworkspace leavestrustLockfile: truewithout the documentedpnpm_trust_lockfile_leftwarning #1268. Not yet re-verified after Fix 15 open pnpm issues across hosted, vendored and agent modes #1007: Global agent mode on pnpm 12 (and 11 without the global virtual store) patches only one of the per-install copies of a package, reports success, and VEX attests not_affected #435 (-gon 11/12), Agent-mode apply in a pnpm workspace reports each member-linked package twice, inflating the --json skipped count with duplicate already_patched events #633, Hosted scan on a Rush repo with pnpm 11/12 reports success, butrush installthen fails with ERR_PNPM_TARBALL_URL_MISMATCH, or (pnpm 11.0.0) silently installs the upstream package #713 / Hosted scan on a Rush repo with subspaces never emitsredirect_rush_repo_state_stale, sorush installfails on the shrinkwrap hash check with no warning #714 (Rush), Vendored pnpm: unwinding a vendored package whose dependency is also vendored clobbers the child's lock wiring —remove <parent>breaks frozen installs, the hosted takeover silently unpatches the child, and rollback fails forever #830, pnpm hosted-to-vendored scan/get dry-run previews success for a refused takeover #853, Hosted pnpm rollback/remove adds registrytarball:URLs the lock never had whenlockfileIncludeTarballUrlsits in a settings file the installed pnpm ignores (workspace file on pnpm 9,.npmrcon pnpm 11/12) #902 and Hosted and vendored pnpm 11/12 refuse a standalone project nested under an unrelated pnpm-workspace.yaml (not in itspackages:globs) as a "workspace member", and the suggested fix doesn't work (regression from #888) #1006.9a. BOM follow-ups (Hosted pnpm scan skips the
trustLockfile: trueauto-config when pnpm-lock.yaml starts with a UTF-8 BOM, so pnpm 11/12 frozen installs fail with ERR_PNPM_TARBALL_URL_MISMATCH after a successful scan #903 / pnpm-workspace.yaml with a UTF-8 BOM: hosted and vendored miss the first top-level key and append a duplicatetrustLockfile/overrides, so every pnpm install fails with "duplicate mapping key" after a successful scan #904): a fresh install of a hosted BOM-package.jsonpin, and Windows checkouts (needs a probe). (Vendored BOM workspace file on 9.15.9 / 10.34.5 done in run 25: pnpm-workspace.yaml with a UTF-8 BOM: hosted and vendored miss the first top-level key and append a duplicatetrustLockfile/overrides, so every pnpm install fails with "duplicate mapping key" after a successful scan #904 reproduces.)9b. Hosted pnpm rollback/remove adds registry
tarball:URLs the lock never had whenlockfileIncludeTarballUrlsits in a settings file the installed pnpm ignores (workspace file on pnpm 9,.npmrcon pnpm 11/12) #902 follow-ups: the setting in the globalrc/config.yaml. (Mirror + tarball URLs became Hosted pnpm rollback/remove restorespnpm-lock.yamlfrom npmjs's version document instead of the project's.npmrcregistry, so a mirror project loses itstarball:URL (cold frozen install 404s) or is moved to npmjs #919 in run 24.)9c. Hosted pnpm rollback/remove restores
pnpm-lock.yamlfrom npmjs's version document instead of the project's.npmrcregistry, so a mirror project loses itstarball:URL (cold frozen install 404s) or is moved to npmjs #919 follow-ups: scoped@scope:registry=mirrors, the hosted → vendored takeover +vendor --reverton a mirror, pnpm 7/8 lock dialects, and re-verification once PR Fix npm-family restore ignoring project registry (#908, #521) #918 (or a successor) coversrestore_pnpm_locks.9d. Warn during pnpm scans when non-registry copies cannot be patched #935 follow-ups: a
git+/github:dependency sharing the patched name@version beside a registry copy, the pnpm 7 (5.4) dialect, alink:copy (should not contest), andvex --producton a member path.9e. Vendored pnpm 7/8 (lock 5.4 / 6.0) writes an unquoted
name: @scope/pkgfor a scoped package, so every frozen install fails with ERR_PNPM_BROKEN_LOCKFILE after a successful scan #956 / Vendored pnpm 9+ misses the aliased-importer refusal for a scoped npm alias (sl: npm:@scope/pkg@x), so it leaves a dangling quoted importer reference: scan says success, frozen installs fail, and VEX attests not_affected #957 follow-ups: scoped vendored in a pnpm 7/8 workspace layout, hosted mode over a scoped alias in a transitive snapshot, and re-verification once fixed (PR Fix unquoted scoped name in pnpm 7/8 vendored lock (#956) #961 covers Vendored pnpm 7/8 (lock 5.4 / 6.0) writes an unquotedname: @scope/pkgfor a scoped package, so every frozen install fails with ERR_PNPM_BROKEN_LOCKFILE after a successful scan #956; the fix for Vendored pnpm 9+ misses the aliased-importer refusal for a scoped npm alias (sl: npm:@scope/pkg@x), so it leaves a dangling quoted importer reference: scan says success, frozen installs fail, and VEX attests not_affected #957 must cover the snapshot path too, see the run 27 comment).vendor_lockfile_crlf_unsupportedrefusal, and the pnpm hosted-to-vendored scan/get dry-run previews success for a refused takeover #853 un-hosting when switching from hosted; check that hosted handles the same checkout; hosted CRLF passes on Linux).Known non-bugs
pnpm 11/12 read
pnpm_config_trust_lockfile(andPNPM_CONFIG_TRUST_LOCKFILE) as false only when it is exactlyfalse. Every other value (0,no,FALSE, empty,null,undefined) falls back to thepnpm-workspace.yamlkey, aspnpm config get trustLockfileshows (run 43). socket-patch matches this for0/no/FALSE, but not for empty /null/undefined, which is Hosted pnpm 11/12 scan treats an empty (ornull/undefined)pnpm_config_trust_lockfileasfalseand skips the trustLockfile config, so the next frozen install fails #1557.Lockfile-only pnpm checkout with no
packageManager, nonode_modules/.modules.yamland a single-document lock: the pnpm major is unknown, so bothnpm_config_*andpnpm_config_*(and both settings files) are read, andnpm_config_package_lock=falserefuses even on a pnpm 12 lock. Hosted pnpm scan refuses with redirect_pnpm_lockfile_disabled over env lockfile settings the project's pnpm major ignores (e.g. any pnpm 11/12 project run throughnpm execwith package-lock=false) #1460 asked for exactly that ("both only when the major is unknown"). A real pnpm 11/12 install pinned bypackageManagerordevEngines.packageManagerwrites the two-document lock, so the major is detected (run 40).Hosted scan beside a pnpm
bundledDependenciescopy of the same package pins the registry copy without a warning. CLI_CONTRACT puts pnpm bundled copies under "Unattested references": onlyvexomits them (vex_pnpm_bundled_copy), and agent mode patches the bundled copy (run 40).pnpm 9.15.9 in the same checkout after a hosted pin:
pnpm install --frozen-lockfile(with or without--prefer-offline) says "Already up to date", keeps the upstream bytes and only updatesnode_modules/.pnpm/lock.yaml. pnpm 10/11/12 refetch. This is the documented "Reinstall after redirecting" limitation (docs/testing/pnpm-compatibility.md, "Reliable installation"; run 40).After
get A --mode vendored+get B --mode hosted,remove Aleaves an emptyoverrides:key inpnpm-workspace.yamlon 10/11/12. That's cosmetic: install, re-vendor and fresh frozen installs all work (run 40).pnpm's
lockfilesetting: pnpm 10.34.6 ignoreslockfile: falseinpnpm-workspace.yaml(pnpm config getsays false, but it writes and uses the lock); pnpm 11.28.3 / 12.11.2 ignorelockfile=falseandpackage-lock=falsein.npmrc; pnpm 9/10 ignore YAMLpackageLock: false. socket-patch's file-based reading matches all of this (run 39). Global~/.npmrc/config.yamlaren't read; that's documented ("only the project's own files").npm run/npm execexportnpm_config_package_lock=(empty = false) only when an npmrc setspackage-lock=false; with no setting, nothing is exported. pnpm 10pnpm runexportsnpm_config_lockfile=trueonly when the YAML sets it.patches-api.socket.devand (for the Rust client)registry.npmjs.orgare unreachable from the sandbox. Mock the API and pointSOCKET_NPM_REGISTRYat a mirror.v5 recognises hosted pins only on the configured patch server. Against a mock without
SOCKET_PATCH_SERVER_URL,rollbacksays "Manifest not found". That's a fixture artifact.v5 hosted rollback and takeover keep a user-edited
trustLockfile: trueand warnpnpm_trust_lockfile_left. A workspace file that exactly matches hosted mode's scaffold is deleted, including a user's ownpackages: ['.']file that the trust append made identical to it (CLI_CONTRACT, upstream restore). The same applies when the user's pre-existing workspace file held only other keys (for examplelockfileIncludeTarballUrl): the hosted-addedtrustLockfile: truestays, with the warning (v5 records no provenance).pnpm 10 ignores
enableGlobalVirtualStorewhenCIis set, so the global-virtual-store cells don't engage on GH runners with pnpm 10.pnpm 12 (and 11) ignore
.npmrcforvirtual-store-dir/enable-global-virtual-store. Put them inpnpm-workspace.yaml, or in the globalconfig.yaml.pnpm 11+
pnpm root -g/pnpm add -gfail unless$PNPM_HOME/binis onPATH. Put it there in fixtures.Vendored refusals that are intended, loud and fail-closed: a CRLF
pnpm-lock.yamlorpnpm-workspace.yaml(vendor_lockfile_crlf_unsupported), a BOM package.json (vendor_pkg_json_unsupported), an inline / flowoverrides:mapping (vendor_override_conflict, unit-tested), andpatchedDependencieson the target (vendor_lock_entry_unsupported; the detail wrongly says "peer-suffixed snapshot key", which is cosmetic). On a hosted → vendored takeover these refusals fire after the hosted pin is already restored, which is pnpm hosted-to-vendored scan/get dry-run previews success for a refused takeover #853.Vendored
vexattests from the committed artifact plus lock wiring even when the tree isn't installed. That's by design (CLI_CONTRACT "Manifest-less VEX").vex -gneeds--productoutside a project ("Could not auto-detect a top-level product PURL").Agent-mode
get <purl>for an uninstalled package reportssuccess, applied: 1when another manifest entry applies. The nested apply fails only when nothing matches. It's not pnpm-specific (noted on Agent mode ignores pnpm's virtualStoreDir: transitive dependencies are reported package_not_installed with a custom virtualStoreDir or the global virtual store #362).A compact single-line
package.jsoncomes back 2-space-indented after vendor + rollback. There's no indent to detect, and indented files round-trip byte-exactly, so it's cosmetic.Hosted on pnpm 9 over an existing upstream
node_modules: a frozen install keeps the upstream bytes. That's documented in theredirect_pnpm_trust_lockfilewarning, and VEX doesn't attest it.pnpm 12 warns that
package.jsonpnpm.overridesis ignored on vendored projects. The workspace-file override is what takes effect, so this is noise only.A
vex --output /dev/stdouthang when stdout is a pipe is not pnpm-specific.Vendored refuses pnpm catalogs (
catalogs:entry) and peer-suffixed snapshot keys withvendor_lock_entry_unsupported("this lock shape is not supported yet"). It's loud and writes nothing. Hosted handles both. (The takeover from hosted un-hosts first: #853.)pnpm 10's
configDependenciescopy (node_modules/.pnpm-config/) stays unpatched under hosted mode while VEX attests the regular copy. Config deps run only at install time, and pnpm 10 keeps their integrity inpnpm-workspace.yaml.On v5, vendoring always downloads its artifact from the patch service (
--vendor-source buildwas removed), so offline vendoring with only a staged manifest fails withvendor_service_offline_conflict. Fixtures need the mock grant to match the manifest UUID.rush update --fullre-resolves the Rush lock and drops the hosted pin, likepnpm update. VEX then honestly reports nothing to attest.pnpm 9.15.9's frozen install fails on its own unmodified lock when a workspace uses
dependenciesMeta.injected("importer dependencies meta (undefined) doesn't match"). That's upstream pnpm, not socket-patch.Agent-mode
vexafter an upgrade (9.15.9, orphan kept) still attests the patched, orphanedleft-pad@1.3.0as a subcomponent. The statement is true of those bytes and nothing installs them, so it hides no vulnerability (run 36).After a vendored package is upgraded,
vendor_ledger_entry_unwiredrepeating after a drift-keeping prune is documented (CLI_CONTRACT warning table). The loop itself is #1155.Old pnpm needs an old Node (≤ 6 needs Node 16, ≤ 2 needs Node 10), and pnpm 3 takes
--storerather than--store-dir. Fixture notes.Agent apply over a pnpm
patchedDependenciesedit to the same file overwrites it with the verified patched content and warnscontent_mismatch_overwritten(documented default mismatch policy;--strictrefuses). Hosted composes both patches, andvexthen declines (no_applicable_patches), because the file matches neither hash.Hosted on pnpm 11/12 respects an explicit
trustLockfile: false(any YAML spelling) and warnsredirect_pnpm_trust_lockfilewith the remedy. The following frozen install fails, which is documented.Vendored refuses pnpm ≤ 6 locks (5.x up to 5.3) with
vendor_lockfile_version_unsupported, and pnpm 7/8 workspace locks withvendor_lock_entry_unsupported. pnpm 7/8 vendored locks carry an absolutefile:specifier (vendor_pnpm_legacy_absolute_specifier), so a moved checkout needspnpm install --offline --no-frozen-lockfileonce. Both are documented.pnpm 11+ ignores
package.jsonpnpm.patchedDependencies. Put it inpnpm-workspace.yaml.A dead-registry fresh install fails when the fixture has any unpatched dependency (it still needs the registry). Use the live registry for those fixtures, or patch every dependency. The same goes for
--offlinewith an empty store (ERR_PNPM_NO_OFFLINE_TARBALL).Vendored from a workspace member cwd fails closed with
vendor_lockfile_missing(partial_failure). Hosted's silent success in the same layout is #590.A
package.jsonwithout a trailing newline gains one after vendor + revert. That's a fixture artifact; files that end in a newline round-trip byte-exactly.Bundled-copy fixtures need a registry-served host package. A
file:tarball host (.pnpm/bundler@file+…) is patched correctly, so it doesn't reproduce #601.pnpm ≤10
.npmrckeys must be kebab-case (modules-dir,virtual-store-dir-max-length); camelCase is silently ignored. pnpm 7–10.11 keep the virtual store innode_modules/.pnpmeven withmodules-dir, so agent mode passes there.pnpm
file:directory dependencies are copied into the store (.pnpm/<name>@file+…), so patching that copy is correct and doesn't touch the source (unlikelink:/workspace:, #626).In-run
scan --mode hosted --vexattests from this run's records without hash verification, so it saysnot_affectedover an upstream install (CLI_CONTRACT(redirected)row). Use standalonevexafter the install as the oracle.A
pnpm patch-commitover a hosted pin makesvexdecline withhash_mismatch(the file matches neither hash). That's honest. Rollback keeps the user's patch and restores the upstream pin.pnpm ≤10
patch-commitunderCI=trueruns a frozen install and fails withERR_PNPM_LOCKFILE_CONFIG_MISMATCH(fixture note: useconfirmModulesPurge=false, notCI). A mock/registrymust serve the real npmjs tarball, or a rollback restores a foreign integrity.Rush has no root
package.json, sovexneeds--productthere (product_undetected), like-g.pnpm 12.0.0 doesn't run under Rush 5.180 (it rejects Rush's
--no-prefer-frozen-lockfile). Rush subspace fixtures needcommon/config/subspaces/<name>/folders created andcommon/config/rush/.pnpmfile.cjsremoved beforerush update.pnpm 11.28.3
pnpm install --no-prefer-frozen-lockfilere-resolves hosted pins to upstream even withtrustLockfile: true(9 / 10 / 12 keep them). That's upstream pnpm behaviour; the defaultpnpm installand--frozen-lockfilekeep the pin. It's tracked inside #713 because Rush uses that flag by default.pnpm dedupere-resolves and drops hosted pins on every pnpm version (likepnpm update). pnpm 11.0.0 / 11.28.3pnpm add <other>also drops them (9 / 10 / 12 keep them). That's upstream pnpm 11 re-resolution, tracked with #713.repairin the default diff mode needs/v0/orgs/<org>/patches/diff/<uuid>archives. A mock without them givesdownload_failed; use--download-mode filewith a blob route.pnpm 11 / 12
pnpm fetchwith onlypnpm-lock.yamlcopied (nopnpm-workspace.yaml) fails loudly withERR_PNPM_TARBALL_URL_MISMATCH. Commit and copy the trust config, as documented.Hosted standalone
vexattests an optional dependency that isn't installed on this OS (for examplefseventson Linux) from its lock pin. That's the documented manifest-less attestation ("nothing installed → attests from the pin").pnpm 11 / 12 fail
ERR_PNPM_IGNORED_BUILDSforesbuildeven on the first install, unless builds are allowed. That's upstream; the patched bytes still land.pnpm update <pkg>drops the hosted pins of every package it re-resolves (pnpm 12 also re-resolves the package's dependents), likepnpm update.Agent
applyfrom a pnpm workspace member cwd patches only the member's direct (linked) deps. Transitive deps in the root.pnpmare skipped ("No installed package matches this PURL", exit 0), and agentvexomits them (package_not_found). Agent crawls are cwd-scoped, and CLI_CONTRACT puts a member that shares the root lock in the root project, so run from the root.Hosted on a
pnpm-lock.yamlwith git conflict markers writes nothing and warnsredirect_pnpm_entry_not_foundfor every package (exit 0). It fails safe. Resolve the conflict (pnpm install) first.Hosted leaves a
file:tarball or git dependency that shares a patched name@version alone (redirect_pnpm_entry_not_found), andvexdoesn't attest it.pnpm 12
pnpm deploywrites its ownpnpm-workspace.yamlwithout the hostedtrustLockfile: true, so a re-install inside the deploy output fails loudly (ERR_PNPM_TARBALL_URL_MISMATCH). That's upstream pnpm; ship the deployednode_modules, or addtrustLockfile: truethere. pnpm 9 / 10 deploy outputs re-install patched.pnpm 10
pnpm deploy(shared lockfile) fails with "Deployment with a shared lockfile has failed" for anyfile:tarball override, the user's own included. That's upstream, so vendored + deploy on pnpm 10 is blocked by pnpm itself.A deploy of a vendored project gets an absolute
file://…/.socket/vendor/…specifier, andvexin the deploy dir declines (no ledger there). The bytes are patched; nothing is falsely attested.pnpm install --resolution-onlyon pnpm 9 / 10 re-resolves and drops hosted pins, likepnpm update(pnpm 12 keeps them).prune,install --prodand a plaininstallkeep the pin on 9 / 10 / 12.Agent
scan --sync <scope>/--prune <scope>where the scope matches nothing (#778) skips the prune with a warning and keeps the manifest. It fails safe.Hosted
vexrecognises a hosted pin only when the tarball URL is on the patch-server origin AND carries the patch uuid as a path segment. Mock fixtures need/…/<uuid>/<file>.tgzURLs.Agent → hosted takeover keeps the agent-mode manifest beside the new hosted pin (
listshows each patch twice). The layers coexist, androllbackunwinds both. Agent → vendored migrates the manifest record out, as documented.Vendored
listkeeps listing a package afterpnpm remove <pkg>, because pnpm keeps the override and the wiring is still live.vexomits it.Fixture note:
scan -galso covers the npm global root, so it patches npm's own bundled deps (for example/opt/node22/lib/node_modules/npm/node_modules/jsonparse). That isn't pnpm-specific, but it can make a pnpm-global copy lookalready_patchedinapply -goutput.Vendored refuses a user parent-selector (
a>b) or range-selector (b@<2) override for the target withvendor_override_conflictand writes nothing. The detail text is slightly off (it mentions an exact-pin takeover, or "package.json" on pnpm 12), which is cosmetic. (A bare-key exact pin inpnpm-workspace.yamlis NOT a genuine conflict: #854.)An API that answers with lowercased npm purls for a mixed-case installed name (
Base64) isn't matched by agent apply (package_not_installed). There's no evidence the real API lowercases, so treat it as hypothetical (run 20).scan --mode vendored --dry-runover a hosted pin previews onlywould_vendor(novendor_would_revert_redirect). It's not pnpm-specific, so it isn't filed here (run 21).Fixture note: global (
-g) cells must put the pnpm under test first onPATH. The sandbox ships pnpm 10.28.0 in/opt/node22/bin, and the CLI reads the global root from whicheverpnpmit finds (run 22).pnpm 9 ignores
sharedWorkspaceLockfile: falseinpnpm-workspace.yaml(only.npmrcshared-workspace-lockfile=falseworks there), so a 9.x member then has no lock of its own and the #590 refusal is correct.Fixture note (run 23): pnpm 1.x needs Node 10 (it crashes in graceful-fs on Node 22). Its layout is
node_modules/.registry.npmjs.org/<name>/<ver>/node_modules/<name>, its lock isshrinkwrap.yaml, and it takes--frozen-shrinkwrapand--store.Vendored on a pnpm 1/2
shrinkwrap.yamlproject fails closed withvendor_lockfile_missing, whose message listspnpm-lock.yamlbut notshrinkwrap.yaml(cosmetic; vendoring pnpm ≤ 6 is refused as documented).Fixture note (run 24): pnpm caches registry metadata per host in
~/.cache/pnpm/metadata/<host>+<port>. Give each mirror cell its ownXDG_CACHE_HOME, or a mirror that changes itsdist.tarballstyle serves stale URLs. For fresh-install checks, copy the working tree; a git clone takes the committed lock.Fixture note (run 23): the Python mock rebuilds the patched tarball on every restart (the gzip mtime changes), so a pin's sha512 changes between mock restarts. Re-scan after restarting the mock.
Fixture note (run 29):
vex --jsonneeds--output, and a workspace root without aversionneeds--product.Fixture note (run 27): agent
rollback --offlineneeds the before blob staged in.socket/blobs; without it, rollback fails withBefore blob not found(missing_blob). That's documented (repairfetches it).Hosted → vendored takeover of 2+ packages keeps the hosted
packages: ['.']+trustLockfile: truescaffold, because the second un-host sees the first package's vendored overrides in the file. It warnspnpm_trust_lockfile_left, and a laterrollbackleaves the scaffold (run 30, 9.15.9 / 10.34.6). The vendored → hosted → rollback order deletes it.A pnpm major upgrade over hosted pins: pnpm 10/12 (and pnpm 9 over a 5.4 lock) can't read a 5.x / 6.0 lock.
--frozen-lockfilefails loudly, and a plain install discards the lock, re-resolves and drops the pins (likepnpm update). Re-run the hosted scan after upgrading. pnpm 9 migrates a 6.0 lock and keeps the pins.Fixture note (run 30): agent
rollbackneeds the mock to serve the "before" blob onpatches/blob/<hash>(otherwisemissing_blob).vendor --revertwith a missing ledger skips withvendor_orphan_still_wiredand says to "runsocket-patch repairto re-adopt them", butrepairanswersvendor_ledger_missing("does not rebuild the ledger from lockfiles"). The remedies contradict each other, but it's cosmetic and not pnpm-specific (run 30).Hosted reads only a literal
true(optionally quoted) astrustLockfilealready set. ForTrue/yesit warns that the user's explicit value "was respected", but pnpm 12 treats both as trusted and installs patched. That's cosmetic (run 31).pnpm 11 / 12 ignore
.npmrclockfile=false, so #1074 applies there only through thepnpm-workspace.yamllockfile: falsekey (run 31).With a stale sibling lock, vendored wires only the governing lock in the #1044 precedence table (vlt > bun > pnpm > yarn > npm) and warns
vendor_multiple_lockfiles. That's documented. Hosted rewrites every present lock (run 32).remove <uuid A>on a release where the agent manifest holds A and a hosted pin holds a superseding B also unwinds B's pin. #1035 designed it that way: every generation of the release goes (run 32).vendor --revert(and the vendored leg ofrollback) removes its override line frompnpm-workspace.yamlbut leaves an emptyoverrides:header when another key follows the block, for example the user's own key or hosted mode'strustLockfile. pnpm 8–12 accept the null value. After a mixed vendored A + hosted B (get <uuid B>, or a takeover that retracts one package),rollbackthen leavespackages: ['.']/overrides:/trustLockfile: truein a project that had no workspace file. It warnspnpm_trust_lockfile_left(the same class as the run-30 hosted → vendored residue, and #401 was closed on the warning), and on 8.x–10.4 the leftover scaffold is #734. Not filed (run 34).Vendored from a
shared-workspace-lockfile=falsemember refuses withvendor_pnpm_settings_elsewhereon pnpm 10 as well (run 22 passed on 10.34.5 before the #881 fix). That's correct: pnpm 10 honours the member's ownpnpm.overridesonly for an install run from the member. A rootpnpm install --frozen-lockfilefails withERR_PNPM_LOCKFILE_CONFIG_MISMATCH(run 34).Since #1058 (run 35), hosted refuses to pin a registry copy when another lock entry installs the same name@version from a
file:tarball (redirect_unattributable, nothing written, exit 0). That's deliberate: it matches the VEX contested-lock rule. The vendored scan-warning gap is still #935.After
pnpm removeof a vendored package,vendor --checkexits 1 with "dependency removed … runscan --mode vendored --prune" (run 35). That's correct and actionable; the prune retires the entry (its own exit 1 on 7–11 is #1197).An interrupted vendored-only commit at
group_commit_file@Nleaves the superseded uuid dir untilscan --prune. It's listed asvendorOrphanDirsand reclaimed there, so it fails safe, unlike the takeover in #1157 (run 35).pnpm with
gitBranchLockfileon writespnpm-lock.<branch>.yamleven onmain(there's nopnpm-lock.yamlunless the branch locks are merged), so hosted and vendored refuse such projects on every branch. That's the loud, documented #556 refusal (run 37).Fixture note (run 37): a stray
package.jsonwithpackageManagerin a parent directory (for example/tmp) makes pnpm 11+ switch versions for child fixtures. Keep fixtures under a clean tree, and put/opt/node22/binahead of/usr/local/bin(Node 20 there lacks thenode:sqlitethat pnpm 11 needs).A path-scoped hosted
rollback packages/ain asharedWorkspaceLockfile: falseworkspace also restores the other members' locks for the same purl. That's documented ("Rollback restores EVERY installed copy of a selected patch"; run 38).rollback left-pad@1.3.0/rollback lp(an alias name) givepatch_not_found: the #1034 grammar matches names exactly, andname@versionisn't a target. Use a purl (run 38).Fixture note (run 38): corepack on Node 22 can't launch pnpm 12.11.x. Install pnpm with
npm i -g --prefix <dir> pnpm@<v>.Agent
scanfrom a workspace member undernode-linker=hoistedfinds nothing (exit 0, no events), even for a directnpm:alias dep: the dep is a real directory in the rootnode_modules, outside the cwd-scoped crawl. That's the same documented cwd scoping as the member-transitive entry above; run from the root (run 41).pnpm_pnp_unsupportedon pnpm 11/12 saysnode-linker=pnpis "in .npmrc" and to "switch .npmrc", but pnpm 11+ readsnodeLinkeronly frompnpm-workspace.yaml. Cosmetic: agent mode still patches the store copy that.pnp.cjsloads (run 41).Vendored mode refuses a transitive
npm:alias of the patched package ("lp": "npm:left-pad@1.3.0"inside a registry dependency) withvendor_lock_entry_unsupported("an aliased snapshot reference ... not supported yet"), exit 1, lock untouched. Loud refusal by design (vendor/pnpm_lock.rsrefuse path); hosted and agent handle the same tree (run 42).With a bundled copy as the only instance, vendored fails with
vendor_lock_entry_not_found, whose remedy ("make sure the package is installed and locked") is misleading because the package is installed, just bundled. Cosmetic: the failure is loud and nothing is written; hosted skips withredirect_pnpm_entry_not_found(run 42).Agent
rollbackempties.socket/manifest.json, so a followingapplyis a no-op success. That's the v5 rollback semantics, not a lost patch (run 42).Vendored tarballs that a release before the #1541 fix committed as Git LFS pointers stay pointers after the next vendored run. The run rewrites
<uuid>/.gitattributes,vendor --checkpasses in the LFS-smudged checkout, and an LFS-less clone failsERR_PNPM_TARBALL_INTEGRITY. docs/ecosystems.md documents the fix: rungit add --renormalize .socket/vendor/npmafter the next vendored run (run 44, pnpm 12). A.git/info/attributesLFS rule beats the uuid file;npm_dir.rssays so.A root hosted / vendored scan doesn't touch, or warn about, an independent nested project's lock when the root itself installs the same
name@version.nested_project_skippedis defined only for packages that "only a nested, independent npm project installs" (docs/ecosystems.md, CLI_CONTRACT.md). Scan the nested project by PATH.pnpm 12 (unlike 9) installs a directory under a
pnpm-workspace.yamlthat doesn't list it as its own project, with its ownpnpm-lock.yaml. A hosted / vendoredscan tools/xthen createstools/x/pnpm-workspace.yaml, which makestools/xits own workspace root. The fresh frozen install there is patched (run 44).All reactions