Problem
The 2026-05-27 benchmarks.vlt.sh chart (pacquet 0.2.12 vs pnpm 11.3.0) shows the lockfile+node_modules row still 1.92–9.09× slower than pnpm across next, astro, vue, large, babylon, and the same family hits cache+lockfile+node_modules × large = 1.57× and × babylon = 2.87×. Per the tracker comment, pacquet 0.2.12 includes the optimistic_repeat_install port (#11943) and the workspace-state-fix (#11946), so the fast path should fire here.
Locally on the same fixture set, optimistic_repeat_install does fire — post-#11946 local re-bench had next × lockfile+node_modules = 0.07× and the babylon × *+node_modules cells at 0.07–0.17×. Something about vlt's exact scenario keeps the fast path from firing.
What lockfile+node_modules.sh actually does
From vltpkg/benchmarks/scripts/variations/lockfile+node_modules.sh:
--setup="bash …/clean-helpers.sh clean_all" — full wipe once, before all pkg managers
--prepare="sleep 1; bash …/clean-helpers.sh clean_all_cache clean_package_manager_files" — wipes caches + transient pkg-manager files between each iteration; node_modules and pnpm-lock.yaml carry over
--cleanup="bash …/clean-helpers.sh clean_all" — full wipe after all pkg managers
clean_pacquet_cache removes ~/.cache/pnpm and ~/.local/share/pnpm/store. The workspace state file lives at node_modules/.pnpm-workspace-state-v1.json, which is not in the cache, so it should survive a prepare cycle.
Hypotheses
clean_pacquet_cache wipes something the optimistic check depends on. The check itself reads node_modules/.pnpm-workspace-state-v1.json and package.json mtimes — neither lives under ~/.cache/pnpm. But pacquet_store_dir::register_project writes into the store registry, which lives at ~/.local/share/pnpm/store/<version>/registry.json (or similar) — wiped between iterations. If the optimistic check transitively touches that, it might fail.
- First-iteration cross-PM contamination. hyperfine runs each pkg manager's
warmup+runs cycle in sequence, so pacquet's first warmup iteration sees a node_modules written by the previous pkg manager. .pnpm-workspace-state-v1.json is either pnpm-format (potentially incompatible field set) or missing (bun/vlt didn't write it). Pacquet's first iteration falls through to full install, then writes its own state. Iteration 2+ should match. With BENCH_WARMUP=1, BENCH_RUNS=3, the mean of 3 fast iterations should still be near pnpm.
- mtime mismatch on the largest fixtures.
babylon × lockfile+node_modules = 9.09× is the worst cell; the workspace state file has 87 importers. If any importer's package.json mtime is touched by clean_package_manager_files/clean_all_cache between iterations, the optimistic check rejects.
- Settings comparison fails.
current_settings (in pacquet/crates/package-manager/src/optimistic_repeat_install.rs) builds the settings record from config + node_linker + included. If vlt's invocation environment differs from what was recorded in the state file (e.g. a default that changed between pacquet versions inside the iteration), the comparison fails every time.
Reproduction
Clone vltpkg/benchmarks, install pacquet@0.2.12 and pnpm@11.3.0, then run only the cell that's worst (babylon × lockfile+node_modules):
cd benchmarks
git clone https://github.com/babel/babel.git fixtures/babylon
# Run the variation in isolation
BENCH_INCLUDE_PACQUET=1 BENCH_INCLUDE_PNPM=1 BENCH_WARMUP=1 BENCH_RUNS=3 \
RUST_LOG=pacquet=debug \
bash scripts/variations/lockfile+node_modules.sh fixtures/babylon
Grep the captured pacquet-output-*.log files for optimistic_repeat_install decisions. Each measured iteration should log either UpToDate (fast path) or a Skipped { reason: ... } with the rejection cause.
Fix shape
Falls out of the diagnosis. If (1), narrow clean_pacquet_cache upstream in vlt's bench. If (2)/(3), the fix is in pacquet (mtime comparison tolerance, or accept a foreign-written state file when the settings record is compatible). If (4), align current_settings with what gets written.
Scope
Covers the lockfile+node_modules row (next/astro/svelte/vue/large/babylon) and cache+lockfile+node_modules × {large, babylon} cells. Once it fires reliably, all eight should drop to 0.05–0.20× pnpm, matching the smaller fixtures.
Tracker: #11902
Written by an agent (Claude Code, claude-opus-4-7).
Problem
The 2026-05-27
benchmarks.vlt.shchart (pacquet 0.2.12vspnpm 11.3.0) shows thelockfile+node_modulesrow still 1.92–9.09× slower than pnpm acrossnext,astro,vue,large,babylon, and the same family hitscache+lockfile+node_modules × large = 1.57×and× babylon = 2.87×. Per the tracker comment,pacquet 0.2.12includes theoptimistic_repeat_installport (#11943) and the workspace-state-fix (#11946), so the fast path should fire here.Locally on the same fixture set,
optimistic_repeat_installdoes fire — post-#11946 local re-bench hadnext × lockfile+node_modules = 0.07×and thebabylon × *+node_modulescells at 0.07–0.17×. Something about vlt's exact scenario keeps the fast path from firing.What
lockfile+node_modules.shactually doesFrom
vltpkg/benchmarks/scripts/variations/lockfile+node_modules.sh:--setup="bash …/clean-helpers.sh clean_all"— full wipe once, before all pkg managers--prepare="sleep 1; bash …/clean-helpers.sh clean_all_cache clean_package_manager_files"— wipes caches + transient pkg-manager files between each iteration;node_modulesandpnpm-lock.yamlcarry over--cleanup="bash …/clean-helpers.sh clean_all"— full wipe after all pkg managersclean_pacquet_cacheremoves~/.cache/pnpmand~/.local/share/pnpm/store. The workspace state file lives atnode_modules/.pnpm-workspace-state-v1.json, which is not in the cache, so it should survive apreparecycle.Hypotheses
clean_pacquet_cachewipes something the optimistic check depends on. The check itself readsnode_modules/.pnpm-workspace-state-v1.jsonandpackage.jsonmtimes — neither lives under~/.cache/pnpm. Butpacquet_store_dir::register_projectwrites into the store registry, which lives at~/.local/share/pnpm/store/<version>/registry.json(or similar) — wiped between iterations. If the optimistic check transitively touches that, it might fail.warmup+runscycle in sequence, so pacquet's first warmup iteration sees anode_moduleswritten by the previous pkg manager..pnpm-workspace-state-v1.jsonis either pnpm-format (potentially incompatible field set) or missing (bun/vlt didn't write it). Pacquet's first iteration falls through to full install, then writes its own state. Iteration 2+ should match. WithBENCH_WARMUP=1, BENCH_RUNS=3, the mean of 3 fast iterations should still be near pnpm.babylon × lockfile+node_modules = 9.09×is the worst cell; the workspace state file has 87 importers. If any importer'spackage.jsonmtime is touched byclean_package_manager_files/clean_all_cachebetween iterations, the optimistic check rejects.current_settings(inpacquet/crates/package-manager/src/optimistic_repeat_install.rs) builds the settings record fromconfig+node_linker+included. If vlt's invocation environment differs from what was recorded in the state file (e.g. a default that changed between pacquet versions inside the iteration), the comparison fails every time.Reproduction
Clone
vltpkg/benchmarks, installpacquet@0.2.12andpnpm@11.3.0, then run only the cell that's worst (babylon × lockfile+node_modules):Grep the captured
pacquet-output-*.logfiles foroptimistic_repeat_installdecisions. Each measured iteration should log eitherUpToDate(fast path) or aSkipped { reason: ... }with the rejection cause.Fix shape
Falls out of the diagnosis. If (1), narrow
clean_pacquet_cacheupstream in vlt's bench. If (2)/(3), the fix is in pacquet (mtime comparison tolerance, or accept a foreign-written state file when the settings record is compatible). If (4), aligncurrent_settingswith what gets written.Scope
Covers the
lockfile+node_modulesrow (next/astro/svelte/vue/large/babylon) andcache+lockfile+node_modules × {large, babylon}cells. Once it fires reliably, all eight should drop to 0.05–0.20× pnpm, matching the smaller fixtures.Tracker: #11902
Written by an agent (Claude Code, claude-opus-4-7).