fix(config): default enableGlobalVirtualStore to false#489
Conversation
There was a problem hiding this comment.
Pull request overview
This PR corrects Pacquet’s enableGlobalVirtualStore default to match the non-global install behavior and updates related tests/benchmark comments to reflect that GVS is now explicit opt-in.
Changes:
- Changes
default_enable_global_virtual_store()fromtruetofalse. - Updates config tests to assert default-off behavior and explicitly opt into GVS where needed.
- Revises benchmark fixture/docs to explain why the fixture pins
enableGlobalVirtualStore: false.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
crates/config/src/defaults.rs |
Flips the GVS default and expands rationale. |
crates/config/src/lib.rs |
Updates GVS derivation tests and fixture setup. |
crates/package-manager/src/install/tests.rs |
Updates GVS-on install test documentation and explicit opt-in comment. |
tasks/integrated-benchmark/src/workspace_manifest.rs |
Updates manifest field documentation for benchmark GVS behavior. |
tasks/integrated-benchmark/src/fixtures/pnpm-workspace.yaml |
Updates fixture comments while keeping the explicit GVS-off pin. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughThe PR flips the effective default of ChangesGlobal Virtual Store Default Value Flip
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #489 +/- ##
==========================================
- Coverage 88.90% 88.81% -0.09%
==========================================
Files 121 121
Lines 12625 12643 +18
==========================================
+ Hits 11224 11229 +5
- Misses 1401 1414 +13 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Micro-Benchmark ResultsLinux |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/config/src/lib.rs (1)
208-214:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUpdate stale GVS default docs to
falseeverywhere.Line 208-214 and the leading part of the test docblock still state
enableGlobalVirtualStoredefaults totrue, which now contradicts the actual default and the updated test intent.Suggested doc fix
- /// `<project>/node_modules/.pnpm`. Default `true`, mirroring upstream's - /// [`config/reader/src/index.ts:392-394`](https://github.com/pnpm/pnpm/blob/94240bc046/config/reader/src/index.ts#L392-L394). + /// `<project>/node_modules/.pnpm`. Default `false` for regular installs + /// (the upstream `true` assignment is in the `--global` path only).- /// `enableGlobalVirtualStore` defaults to `true`. The derivation + /// `enableGlobalVirtualStore` defaults to `false`. The derivationAlso applies to: 1003-1019
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/config/src/lib.rs` around lines 208 - 214, The docblock for the configuration option enableGlobalVirtualStore incorrectly states the default is `true`; update the documentation text in the lib.rs doc comment for enableGlobalVirtualStore (and the corresponding test docblock referenced later) to reflect the current default `false` so docs match behavior and test intent; search for the symbol enableGlobalVirtualStore and any docblocks or comments that mention "default `true`" (including the test docblock near the later tests) and change them to "default `false`" while preserving the explanatory text and upstream link.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/config/src/lib.rs`:
- Around line 208-214: The docblock for the configuration option
enableGlobalVirtualStore incorrectly states the default is `true`; update the
documentation text in the lib.rs doc comment for enableGlobalVirtualStore (and
the corresponding test docblock referenced later) to reflect the current default
`false` so docs match behavior and test intent; search for the symbol
enableGlobalVirtualStore and any docblocks or comments that mention "default
`true`" (including the test docblock near the later tests) and change them to
"default `false`" while preserving the explanatory text and upstream link.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 1449e3e4-65d9-4c60-a289-2d45473bd522
📒 Files selected for processing (5)
crates/config/src/defaults.rscrates/config/src/lib.rscrates/package-manager/src/install/tests.rstasks/integrated-benchmark/src/fixtures/pnpm-workspace.yamltasks/integrated-benchmark/src/workspace_manifest.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Preserve existing method chains andpipe-traitchains; do not break them into intermediateletbindings unless there is a concrete justification such as a compilation failure, borrow checker rejection, meaningful performance improvement, or other technical necessity. Refactoring for style alone is not sufficient justification.
Choose owned vs. borrowed parameters to minimize copies; prefer borrowed types (&Pathover&PathBuf,&strover&String) when it does not force extra copies.
PreferArc::clone(&x)andRc::clone(&x)overx.clone()for reference-counted types to make the cost visible at the call site.
Do not use star imports inside module bodies. Writeuse super::{Foo, bar}instead ofuse super::*;for any glob whose target is a module you control. External-crate preludes (e.g.,use rayon::prelude::*;) and root-of-module re-exports (e.g.,pub use submodule::*;inlib.rs) are exceptions.
Follow Rust API Guidelines for naming, as documented in https://rust-lang.github.io/api-guidelines/naming.html.
Declare a newtype wrapper for any branded string type being ported from TypeScript pnpm. Do not collapse the brand into a plainStringor&str; give the type its own struct so misuse is a type error.
When porting branded string types where upstream TypeScript always validates before construction, validate in the Rust port too. Construct the wrapper only viaTryFrom<String>and/orFromStr; do not provide an infallible public constructor that takes an arbitrary string.
For branded string types where upstream TypeScript never validates (used purely for type-safety to prevent confusion between string slots), expose an infallibleFrom<String>andFrom<&str>constructor in the Rust wrapper.
When upstream TypeScript occasionally constructs a branded type without validation (via bareasassertion), add afrom_str_unchecked(or similarly named) constructor on the Rust side. Keep the validating constructor as well; `from_str_u...
Files:
crates/package-manager/src/install/tests.rscrates/config/src/defaults.rstasks/integrated-benchmark/src/workspace_manifest.rscrates/config/src/lib.rs
🧠 Learnings (4)
📚 Learning: 2026-05-01T10:01:33.766Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 349
File: crates/reporter/src/tests.rs:121-121
Timestamp: 2026-05-01T10:01:33.766Z
Learning: In Rust test code, follow the repo’s CODE_STYLE_GUIDE test-logging rule: add logging (e.g., `eprintln!`/`eprintln!(...)`) so that useful diagnostic values are printed when a test fails, unless the assertion is `assert_eq!` (where the differing values are already included). Concretely, if you use assertions like `assert!`, `assert_ne!`, etc., ensure the test logs the relevant actual/expected values (or context) before/around the assertion so failures can be diagnosed without rerunning.
Applied to files:
crates/package-manager/src/install/tests.rs
📚 Learning: 2026-05-07T23:19:08.272Z
Learnt from: KSXGitHub
Repo: pnpm/pacquet PR: 401
File: tasks/integrated-benchmark/src/work_env.rs:343-344
Timestamp: 2026-05-07T23:19:08.272Z
Learning: When reviewing Rust code in pnpm/pacquet for deprecated API usage, do not automatically treat `serde_saphyr::to_string` as deprecated. In `serde-saphyr` v0.0.25, `serde_saphyr::to_string` has no `#[deprecated]` attribute (the `#[deprecated]` later in `serde-saphyr-0.0.25/src/lib.rs` applies to a different function). Only flag `serde_saphyr::to_string` as deprecated if the resolved dependency version’s source shows `#[deprecated]` on that specific function.
Applied to files:
crates/package-manager/src/install/tests.rscrates/config/src/defaults.rstasks/integrated-benchmark/src/workspace_manifest.rscrates/config/src/lib.rs
📚 Learning: 2026-05-13T19:22:48.951Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 478
File: crates/package-manager/src/hoisted_dep_graph.rs:51-55
Timestamp: 2026-05-13T19:22:48.951Z
Learning: When reviewing this Rust codebase, avoid introducing/using a newtype like `PkgIdWithPatchHash` in only one module (e.g., `hoisted_dep_graph.rs`) if other related pacquet modules still represent the upstream pnpm “pkg id with patch hash” as a plain `String` (e.g., `virtual_store_layout`). For type consistency, either keep `pkg_id_with_patch_hash` as `String` here, or require a workspace-wide sweep that defines/extracts the `PkgIdWithPatchHash` newtype once and updates all call sites together (otherwise defer the refactor to a coordinated follow-up PR).
Applied to files:
crates/package-manager/src/install/tests.rs
📚 Learning: 2026-05-13T20:09:22.171Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 486
File: crates/package-manager/src/hoisted_dep_graph.rs:472-476
Timestamp: 2026-05-13T20:09:22.171Z
Learning: In pnpm/pacquet, when generating serialized `hoisted_locations` strings (used for `.modules.yaml`), normalize path separators to forward slashes (e.g., replace `\\` with `/`). This preserves cross-platform portability: the output must not use OS-native separators because upstream pnpm’s `path.relative` can return platform-specific separators, which would break consistency with pnpm/pacquet’s other serialized formats on Windows.
Applied to files:
crates/package-manager/src/install/tests.rs
🔇 Additional comments (5)
crates/config/src/defaults.rs (1)
98-117: LGTM!crates/package-manager/src/install/tests.rs (1)
1294-1297: LGTM!Also applies to: 1327-1328
tasks/integrated-benchmark/src/fixtures/pnpm-workspace.yaml (1)
3-16: LGTM!tasks/integrated-benchmark/src/workspace_manifest.rs (1)
29-39: LGTM!crates/config/src/lib.rs (1)
1021-1032: LGTM!Also applies to: 1062-1073, 1097-1120
Pacquet's `default_enable_global_virtual_store()` returned `true` and cited upstream's [`config/reader/src/index.ts:392-394`](https://github.com/pnpm/pnpm/blob/94240bc046/config/reader/src/index.ts#L392-L394) as the authority for that default. But that range lives entirely inside the [`if (cliOptions['global']) { ... }`](https://github.com/pnpm/pnpm/blob/94240bc046/config/reader/src/index.ts#L348-L395) block — surrounded by `CONFIG_CONFLICT_*_WITH_GLOBAL` errors and closed by `} else if (!pnpmConfig.bin) { ... }`. So in pnpm v11: - `pnpm install --global foo`: `enableGlobalVirtualStore` defaults to `true`. - `pnpm install` (regular): stays `null`/unset → effectively `false`. Pacquet doesn't have a `--global` CLI flag at all (only `install --frozen-lockfile`), so the applicable upstream default is the `false` one. Pre-fix, every pacquet install silently wrote slots to `<store>/links/...` and registered projects, even when the user never asked for GVS — and a project alternating between `pnpm install` and `pacquet install --frozen-lockfile` would see two different layouts. The default introduced by #444 cited the same `L392-L394` range but read it as an unconditional default. Corrected here. Test changes: - `gvs_default_writes_links_into_global_virtual_store_dir` renamed and inverted — now asserts the default-off behaviour. The path derivation still populates both fields cleanly so downstream code can read either without first checking the toggle. - `gvs_user_pinned_virtual_store_routes_into_global_virtual_store_dir` and `yaml_global_virtual_store_dir_wins_over_derivation`: yaml now opts into GVS explicitly (`enableGlobalVirtualStore: true`) so the GVS-on derivation path is still exercised. - `install/tests.rs` comments updated to reflect the new default. Benchmark fixture's explicit `enableGlobalVirtualStore: false` pin is kept (it's now redundant but future-proofs the bench against a default flip), with an updated comment explaining the design intent. Same for `MinimalWorkspaceManifest.enable_global_virtual_store` doc.
Two doc sites still claimed the default was `true` after the behaviour flipped: - `Config::enable_global_virtual_store` field doc (lib.rs:208-213): the trailing "Default `true`, mirroring upstream's L392-L394" was the same misreading the function itself had. Replaced with the correct framing — `false`, with the link kept but reframed as "applies only inside upstream's `--global` branch". - `WorkspaceSettings::enable_global_virtual_store` (workspace_yaml.rs): same fix, same reasoning. - `gvs_default_is_off_and_paths_derive_cleanly` test doc (lib.rs): the opening sentence still said `enableGlobalVirtualStore` defaults to `true`. Restructured so the "default false" line leads and the derivation-still-fires note follows. CI auto-detect bullet dropped from the field doc — it was always a follow-up bullet (pacquet#432) and reads as noise next to the corrected default. The original tracking still exists on the issue.
The [`default_enable_global_virtual_store`] intra-doc link in `Config::enable_global_virtual_store`'s doc resolved locally with `--document-private-items` but tripped `rustdoc::private-intra-doc-links` (a pub item linking to a private- module symbol) on CI's `RUSTDOCFLAGS="-D warnings"` build. Two sites: - Field doc: replaced the intra-doc link with a plain backticks reference + a "see `crates/config/src/defaults.rs` for the full reasoning" pointer. - Test doc: changed the link target to the public field `Config::enable_global_virtual_store`, which lives in the same module and is fine.
Copilot caught a regression introduced by flipping the `enableGlobalVirtualStore` default to `false`. The `node --version` detection in `InstallFrozenLockfile::run` was hoisted *before* `CreateVirtualStore::run` in #444 because the GVS-aware layout needed `engine_name` upfront. With GVS now off by default, that hoist costs ~tens of ms of synchronous spawn on the install critical path — the value just gets passed into a `VirtualStoreLayout::new` that immediately returns without using it. `engine_name` is still used by `BuildModules` for the side-effects- cache key prefix (cache defaults to on), so dropping the spawn entirely isn't right. Instead, split the detection by GVS state: - **GVS on**: spawn synchronously, same as today — layout needs it. - **GVS off, no host yet**: spawn into `tokio::task::spawn_blocking` and keep the `JoinHandle`. The blocking pool runs the spawn concurrently with `CreateVirtualStore::run`'s I/O. Await right before `BuildModules`, so the `node` startup cost is hidden under the install rather than serialised before it. `VirtualStoreLayout::new` is built with `None` on the deferred path, which is fine because GVS is off and the layout ignores the field in that path. Pre-GVS pacquet had this same overlap; this restores it for the default config.
1b166f4 to
fa5d541
Compare
Summary
Pacquet's
default_enable_global_virtual_store()returnedtrueand cited upstream'sconfig/reader/src/index.ts:392-394as the authority. But that range lives entirely inside theif (cliOptions['global']) { ... }block — surrounded byCONFIG_CONFLICT_*_WITH_GLOBALerrors and closed by} else if (!pnpmConfig.bin) { ... }. So in pnpm v11:pnpm install --global foo→enableGlobalVirtualStoredefaults totruepnpm install(regular) → staysnull/unset → effectivelyfalsePacquet doesn't have a
--globalCLI flag (onlyinstall --frozen-lockfile), so the applicable upstream default is thefalseone. Pre-fix, every pacquet install silently wrote slots to<store>/links/...and registered projects, even when the user never asked for GVS — and a project alternating betweenpnpm installandpacquet install --frozen-lockfilewould see two different on-disk layouts.The default introduced by #444 cited the same
L392-L394range but read it as an unconditional default. Corrected here.Test changes
gvs_default_writes_links_into_global_virtual_store_dirrenamed togvs_default_is_off_and_paths_derive_cleanlyand inverted — now asserts the default-off behaviour. The path derivation still populates bothvirtual_store_dirandglobal_virtual_store_dircleanly so downstream code can read either field without first checking the toggle.gvs_user_pinned_virtual_store_routes_into_global_virtual_store_dirandyaml_global_virtual_store_dir_wins_over_derivation: yaml now opts into GVS explicitly (enableGlobalVirtualStore: true) so the GVS-on derivation path is still exercised.install/tests.rsdoc + inline comments updated to reflect that GVS-on tests need to pin the flag explicitly now.Benchmark
The bench fixture's explicit
enableGlobalVirtualStore: falsepin is kept (it's now redundant but future-proofs the bench against a default flip), with an updated comment explaining the design intent. Same forMinimalWorkspaceManifest.enable_global_virtual_storedoc.Test plan
just ready(1078 tests pass, 2 skipped)taplo format --checkjust dylintWritten by an agent (Claude Code, claude-opus-4-7).
Summary by CodeRabbit
Changes
Documentation
Tests