Skip to content

chore: use global virtual store - #10587

Open
zkochan wants to merge 4 commits into
teambit:masterfrom
zkochan:enable-gvs
Open

chore: use global virtual store#10587
zkochan wants to merge 4 commits into
teambit:masterfrom
zkochan:enable-gvs

Conversation

@zkochan

@zkochan zkochan commented Aug 9, 2026

Copy link
Copy Markdown
Member

Proposed Changes

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Enable Bit global virtual store for pnpm installs

⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Enable Bit dependency resolver global virtual store for shared pnpm install layout.
• Regenerate pnpm lockfile to reflect the updated dependency installation strategy.
Diagram

graph TD
  cfg["workspace.jsonc"] --> resolver["Bit dependency resolver"] --> install["pnpm install"] --> lock["pnpm-lock.yaml"]
  install --> vstore["Virtual store links"] --> gvs[("Global virtual store")]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep per-workspace virtual store (default)
  • ➕ Maximum isolation between workspaces; fewer surprises if pnpm/Bit settings differ per repo
  • ➕ Less risk of cross-repo contamination if global store is corrupted
  • ➖ More disk usage and slower cold installs across multiple clones
  • ➖ Less effective caching on developer machines/CI runners
2. Configure pnpm virtual store globally via pnpm/.npmrc settings
  • ➕ Centralizes pnpm behavior across projects without Bit-specific configuration
  • ➕ Can be aligned with CI cache strategy in a single place
  • ➖ Doesn’t capture Bit-specific expectations; may diverge from Bit’s dependency resolver behavior
  • ➖ Harder to reason about when different tools manage install settings

Recommendation: Using Bit’s enableGlobalVirtualStore is a good fit when Bit owns installation/linking, because the behavior is explicit and scoped to the workspace config. Ensure CI caches and contributor docs (if any) assume the new store behavior, and watch for platform/path-related issues when developers share a global store across branches.

Files changed (2) +8889 / -13628

Other (2) +8889 / -13628
pnpm-lock.yamlRegenerate lockfile after enabling global virtual store +8888/-13628

Regenerate lockfile after enabling global virtual store

• Updates the pnpm lockfile to match the dependency installation/linking behavior when using a global virtual store. This is expected churn from changing pnpm/Bit install strategy and should be treated as an atomic lockfile refresh.

pnpm-lock.yaml

workspace.jsoncEnable global virtual store in Bit dependency resolver +1/-0

Enable global virtual store in Bit dependency resolver

• Adds 'enableGlobalVirtualStore: true' under 'teambit.dependencies/dependency-resolver' to make pnpm use a shared global virtual store for this workspace.

workspace.jsonc

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Aug 9, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Prune deletes pnpm internals 🐞 Bug ☼ Reliability
Description
With enableGlobalVirtualStore enabled, pnpm keeps pnpm-owned dot entries under
node_modules/.pnpm, but pnpmPruneModules() does not exclude dot entries and will remove them
when they don’t appear in the lockfile’s package list. This can break or destabilize subsequent
installs by deleting pnpm-managed virtual-store state (or forcing it to be recreated unpredictably).
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The PR turns on the global virtual store, and the install flow always runs pnpm prune afterward. In
the global virtual store layout, repo tests/helpers document that node_modules/.pnpm contains
pnpm-owned dot entries; however, the prune implementation only excludes lock.yaml and
node_modules, so dot entries are eligible for deletion even though they are pnpm internals.

workspace.jsonc[13-16]
scopes/workspace/install/install.main.runtime.ts[516-527]
scopes/dependencies/pnpm/pnpm.package-manager.ts[447-449]
scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]
e2e/harmony/global-virtual-store.e2e.ts[28-36]
components/legacy/e2e-helper/e2e-fs-helper.ts[62-77]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
After this PR enables `enableGlobalVirtualStore` in `workspace.jsonc`, installs run in the global virtual store layout where `node_modules/.pnpm` contains pnpm-owned entries (including dot-prefixed directories). The post-install prune step (`pnpmPruneModules`) currently treats *all* entries except `lock.yaml` and `node_modules` as prune candidates, so it may delete pnpm-owned dot entries.
### Issue Context
- The workspace runs a prune step after installs.
- Repo e2e/helper code explicitly treats dot entries under `node_modules/.pnpm` as pnpm-owned internals that should not be considered dependency directories.
### Fix Focus Areas
- scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]
### Suggested fix
- Change `readPackageDirsFromVirtualStore()` to:
- use `readdir(..., { withFileTypes: true })`
- include **directories only**
- exclude entries that start with `.`
- keep excluding `node_modules` and `lock.yaml`
- Add/adjust an e2e or unit test for the global virtual store path to ensure prune does not remove dot-prefixed pnpm entries under `node_modules/.pnpm`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Schema missing GVS key 🐞 Bug ⚙ Maintainability
Description
workspace.jsonc now sets enableGlobalVirtualStore, but the repo’s workspace-jsonc-schema.json
does not define this property under teambit.dependencies/dependency-resolver, so schema-driven
validation/autocomplete cannot surface/validate the new config key.
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The PR adds enableGlobalVirtualStore to the dependency-resolver config, but the schema’s
dependency-resolver properties section enumerates many fields (e.g., nodeLinker,
packageImportMethod, etc.) and does not include enableGlobalVirtualStore anywhere in that
definition.

workspace.jsonc[13-16]
workspace-jsonc-schema.json[111-137]
workspace-jsonc-schema.json[251-308]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`workspace.jsonc` enables `enableGlobalVirtualStore`, but `workspace-jsonc-schema.json` does not declare this option in the `teambit.dependencies/dependency-resolver` schema. This creates schema/config drift: editors and any schema validation tooling won’t recognize the new key.
### Issue Context
The config key is a real, supported option in code (`DependencyResolverWorkspaceConfig.enableGlobalVirtualStore?: boolean`), so the schema should be updated to match.
### Fix Focus Areas
- workspace-jsonc-schema.json[51-320]
- workspace.jsonc[13-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Persisted links path mismatch ✓ Resolved 🐞 Bug ☼ Reliability
Description
The CircleCI workspace persists .pnpm-store/*/links, but Bit resolves the global virtual store at
/links; if the resolved storeDir is /home/circleci/bit/.pnpm-store (as configured), downstream
jobs that only attach the workspace may miss the actual links directory and end up with broken
node_modules symlinks.
Code

.circleci/config.yml[R685-688]

+            # only the global virtual store, not the content-addressable files/ it hardlinks from:
+            # the consumers of this workspace read node_modules, they never fetch packages, and
+            # carrying files/ too would duplicate every package in the archive.
+            - .pnpm-store/*/links
Evidence
CI sets pnpm store-dir to /home/circleci/bit/.pnpm-store and persists .pnpm-store/*/links,
while Bit’s pnpm package manager computes the global virtual store directory as /links; downstream
jobs like lint only attach the workspace and then run without reinstalling, so missing the real
links directory would make node_modules symlinks non-resolvable.

.circleci/config.yml[651-710]
scopes/dependencies/pnpm/pnpm.package-manager.ts[426-445]
.circleci/config.yml[11-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
CircleCI persists `.pnpm-store/*/links`, but Bit/pnpm’s global virtual store directory is computed as `<storeDir>/links`. If pnpm resolves `storeDir` to the configured `/home/circleci/bit/.pnpm-store`, the actual required directory would be `.pnpm-store/links`, which is not matched by `.pnpm-store/*/links`.
This can break downstream jobs that rely on the attached workspace (without reinstalling) because `node_modules` entries may symlink into the missing global virtual store.
## Issue Context
- CI explicitly sets `store-dir=/home/circleci/bit/.pnpm-store`.
- Bit’s pnpm adapter computes the global virtual store as `join(config.storeDir, 'links')`.
- Downstream jobs (e.g. `lint`) attach the workspace and run commands without reinstalling.
## Fix Focus Areas
- .circleci/config.yml[665-710]
## Suggested fix
Update `persist_to_workspace.paths` to persist the exact `links` directory that Bit/pnpm uses.
A pragmatic, layout-tolerant option that still avoids persisting `files/` is to include both possible layouts:
- `.pnpm-store/links`
- `.pnpm-store/*/links`
(If you want to be stricter/cleaner, ensure the persisted path exactly matches the resolved `<storeDir>/links` layout you expect in CI.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Previous review results

Review updated until commit 23abbf3 ⚖️ Balanced

Results up to commit ebfb668


🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)


Action required
1. Prune deletes pnpm internals 🐞 Bug ☼ Reliability
Description
With enableGlobalVirtualStore enabled, pnpm keeps pnpm-owned dot entries under
node_modules/.pnpm, but pnpmPruneModules() does not exclude dot entries and will remove them
when they don’t appear in the lockfile’s package list. This can break or destabilize subsequent
installs by deleting pnpm-managed virtual-store state (or forcing it to be recreated unpredictably).
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The PR turns on the global virtual store, and the install flow always runs pnpm prune afterward. In
the global virtual store layout, repo tests/helpers document that node_modules/.pnpm contains
pnpm-owned dot entries; however, the prune implementation only excludes lock.yaml and
node_modules, so dot entries are eligible for deletion even though they are pnpm internals.

workspace.jsonc[13-16]
scopes/workspace/install/install.main.runtime.ts[516-527]
scopes/dependencies/pnpm/pnpm.package-manager.ts[447-449]
scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]
e2e/harmony/global-virtual-store.e2e.ts[28-36]
components/legacy/e2e-helper/e2e-fs-helper.ts[62-77]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
After this PR enables `enableGlobalVirtualStore` in `workspace.jsonc`, installs run in the global virtual store layout where `node_modules/.pnpm` contains pnpm-owned entries (including dot-prefixed directories). The post-install prune step (`pnpmPruneModules`) currently treats *all* entries except `lock.yaml` and `node_modules` as prune candidates, so it may delete pnpm-owned dot entries.
### Issue Context
- The workspace runs a prune step after installs.
- Repo e2e/helper code explicitly treats dot entries under `node_modules/.pnpm` as pnpm-owned internals that should not be considered dependency directories.
### Fix Focus Areas
- scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]
### Suggested fix
- Change `readPackageDirsFromVirtualStore()` to:
- use `readdir(..., { withFileTypes: true })`
- include **directories only**
- exclude entries that start with `.`
- keep excluding `node_modules` and `lock.yaml`
- Add/adjust an e2e or unit test for the global virtual store path to ensure prune does not remove dot-prefixed pnpm entries under `node_modules/.pnpm`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. Schema missing GVS key 🐞 Bug ⚙ Maintainability ⭐ New
Description
workspace.jsonc now sets enableGlobalVirtualStore, but the repo’s workspace-jsonc-schema.json
does not define this property under teambit.dependencies/dependency-resolver, so schema-driven
validation/autocomplete cannot surface/validate the new config key.
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The PR adds enableGlobalVirtualStore to the dependency-resolver config, but the schema’s
dependency-resolver properties section enumerates many fields (e.g., nodeLinker,
packageImportMethod, etc.) and does not include enableGlobalVirtualStore anywhere in that
definition.

workspace.jsonc[13-16]
workspace-jsonc-schema.json[111-137]
workspace-jsonc-schema.json[251-308]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`workspace.jsonc` enables `enableGlobalVirtualStore`, but `workspace-jsonc-schema.json` does not declare this option in the `teambit.dependencies/dependency-resolver` schema. This creates schema/config drift: editors and any schema validation tooling won’t recognize the new key.

### Issue Context
The config key is a real, supported option in code (`DependencyResolverWorkspaceConfig.enableGlobalVirtualStore?: boolean`), so the schema should be updated to match.

### Fix Focus Areas
- workspace-jsonc-schema.json[51-320]
- workspace.jsonc[13-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Persisted links path mismatch ✓ Resolved 🐞 Bug ☼ Reliability
Description
The CircleCI workspace persists .pnpm-store/*/links, but Bit resolves the global virtual store at
/links; if the resolved storeDir is /home/circleci/bit/.pnpm-store (as configured), downstream
jobs that only attach the workspace may miss the actual links directory and end up with broken
node_modules symlinks.
Code

.circleci/config.yml[R685-688]

+            # only the global virtual store, not the content-addressable files/ it hardlinks from:
+            # the consumers of this workspace read node_modules, they never fetch packages, and
+            # carrying files/ too would duplicate every package in the archive.
+            - .pnpm-store/*/links
Evidence
CI sets pnpm store-dir to /home/circleci/bit/.pnpm-store and persists .pnpm-store/*/links,
while Bit’s pnpm package manager computes the global virtual store directory as /links; downstream
jobs like lint only attach the workspace and then run without reinstalling, so missing the real
links directory would make node_modules symlinks non-resolvable.

.circleci/config.yml[651-710]
scopes/dependencies/pnpm/pnpm.package-manager.ts[426-445]
.circleci/config.yml[11-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
CircleCI persists `.pnpm-store/*/links`, but Bit/pnpm’s global virtual store directory is computed as `<storeDir>/links`. If pnpm resolves `storeDir` to the configured `/home/circleci/bit/.pnpm-store`, the actual required directory would be `.pnpm-store/links`, which is not matched by `.pnpm-store/*/links`.
This can break downstream jobs that rely on the attached workspace (without reinstalling) because `node_modules` entries may symlink into the missing global virtual store.
## Issue Context
- CI explicitly sets `store-dir=/home/circleci/bit/.pnpm-store`.
- Bit’s pnpm adapter computes the global virtual store as `join(config.storeDir, 'links')`.
- Downstream jobs (e.g. `lint`) attach the workspace and run commands without reinstalling.
## Fix Focus Areas
- .circleci/config.yml[665-710]
## Suggested fix
Update `persist_to_workspace.paths` to persist the exact `links` directory that Bit/pnpm uses.
A pragmatic, layout-tolerant option that still avoids persisting `files/` is to include both possible layouts:
- `.pnpm-store/links`
- `.pnpm-store/*/links`
(If you want to be stricter/cleaner, ensure the persisted path exactly matches the resolved `<storeDir>/links` layout you expect in CI.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 9424647


🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)


Action required
1. Prune deletes pnpm internals 🐞 Bug ☼ Reliability
Description
With enableGlobalVirtualStore enabled, pnpm keeps pnpm-owned dot entries under
node_modules/.pnpm, but pnpmPruneModules() does not exclude dot entries and will remove them
when they don’t appear in the lockfile’s package list. This can break or destabilize subsequent
installs by deleting pnpm-managed virtual-store state (or forcing it to be recreated unpredictably).
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The PR turns on the global virtual store, and the install flow always runs pnpm prune afterward. In
the global virtual store layout, repo tests/helpers document that node_modules/.pnpm contains
pnpm-owned dot entries; however, the prune implementation only excludes lock.yaml and
node_modules, so dot entries are eligible for deletion even though they are pnpm internals.

workspace.jsonc[13-16]
scopes/workspace/install/install.main.runtime.ts[516-527]
scopes/dependencies/pnpm/pnpm.package-manager.ts[447-449]
scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]
e2e/harmony/global-virtual-store.e2e.ts[28-36]
components/legacy/e2e-helper/e2e-fs-helper.ts[62-77]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
After this PR enables `enableGlobalVirtualStore` in `workspace.jsonc`, installs run in the global virtual store layout where `node_modules/.pnpm` contains pnpm-owned entries (including dot-prefixed directories). The post-install prune step (`pnpmPruneModules`) currently treats *all* entries except `lock.yaml` and `node_modules` as prune candidates, so it may delete pnpm-owned dot entries.
### Issue Context
- The workspace runs a prune step after installs.
- Repo e2e/helper code explicitly treats dot entries under `node_modules/.pnpm` as pnpm-owned internals that should not be considered dependency directories.
### Fix Focus Areas
- scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]
### Suggested fix
- Change `readPackageDirsFromVirtualStore()` to:
- use `readdir(..., { withFileTypes: true })`
- include **directories only**
- exclude entries that start with `.`
- keep excluding `node_modules` and `lock.yaml`
- Add/adjust an e2e or unit test for the global virtual store path to ensure prune does not remove dot-prefixed pnpm entries under `node_modules/.pnpm`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. Persisted links path mismatch 🐞 Bug ☼ Reliability ⭐ New
Description
The CircleCI workspace persists .pnpm-store/*/links, but Bit resolves the global virtual store at
<storeDir>/links; if the resolved storeDir is /home/circleci/bit/.pnpm-store (as configured),
downstream jobs that only attach the workspace may miss the actual links directory and end up with
broken node_modules symlinks.
Code

.circleci/config.yml[R685-688]

+            # only the global virtual store, not the content-addressable files/ it hardlinks from:
+            # the consumers of this workspace read node_modules, they never fetch packages, and
+            # carrying files/ too would duplicate every package in the archive.
+            - .pnpm-store/*/links
Evidence
CI sets pnpm store-dir to /home/circleci/bit/.pnpm-store and persists .pnpm-store/*/links,
while Bit’s pnpm package manager computes the global virtual store directory as <storeDir>/links;
downstream jobs like lint only attach the workspace and then run without reinstalling, so missing
the real links directory would make node_modules symlinks non-resolvable.

.circleci/config.yml[651-710]
scopes/dependencies/pnpm/pnpm.package-manager.ts[426-445]
.circleci/config.yml[11-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
CircleCI persists `.pnpm-store/*/links`, but Bit/pnpm’s global virtual store directory is computed as `<storeDir>/links`. If pnpm resolves `storeDir` to the configured `/home/circleci/bit/.pnpm-store`, the actual required directory would be `.pnpm-store/links`, which is not matched by `.pnpm-store/*/links`.

This can break downstream jobs that rely on the attached workspace (without reinstalling) because `node_modules` entries may symlink into the missing global virtual store.

## Issue Context
- CI explicitly sets `store-dir=/home/circleci/bit/.pnpm-store`.
- Bit’s pnpm adapter computes the global virtual store as `join(config.storeDir, 'links')`.
- Downstream jobs (e.g. `lint`) attach the workspace and run commands without reinstalling.

## Fix Focus Areas
- .circleci/config.yml[665-710]

## Suggested fix
Update `persist_to_workspace.paths` to persist the exact `links` directory that Bit/pnpm uses.

A pragmatic, layout-tolerant option that still avoids persisting `files/` is to include both possible layouts:
- `.pnpm-store/links`
- `.pnpm-store/*/links`

(If you want to be stricter/cleaner, ensure the persisted path exactly matches the resolved `<storeDir>/links` layout you expect in CI.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit c445ba1


🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)


Action required
1. Prune deletes pnpm internals 🐞 Bug ☼ Reliability
Description
With enableGlobalVirtualStore enabled, pnpm keeps pnpm-owned dot entries under
node_modules/.pnpm, but pnpmPruneModules() does not exclude dot entries and will remove them
when they don’t appear in the lockfile’s package list. This can break or destabilize subsequent
installs by deleting pnpm-managed virtual-store state (or forcing it to be recreated unpredictably).
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The PR turns on the global virtual store, and the install flow always runs pnpm prune afterward. In
the global virtual store layout, repo tests/helpers document that node_modules/.pnpm contains
pnpm-owned dot entries; however, the prune implementation only excludes lock.yaml and
node_modules, so dot entries are eligible for deletion even though they are pnpm internals.

workspace.jsonc[13-16]
scopes/workspace/install/install.main.runtime.ts[516-527]
scopes/dependencies/pnpm/pnpm.package-manager.ts[447-449]
scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]
e2e/harmony/global-virtual-store.e2e.ts[28-36]
components/legacy/e2e-helper/e2e-fs-helper.ts[62-77]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
After this PR enables `enableGlobalVirtualStore` in `workspace.jsonc`, installs run in the global virtual store layout where `node_modules/.pnpm` contains pnpm-owned entries (including dot-prefixed directories). The post-install prune step (`pnpmPruneModules`) currently treats *all* entries except `lock.yaml` and `node_modules` as prune candidates, so it may delete pnpm-owned dot entries.

### Issue Context
- The workspace runs a prune step after installs.
- Repo e2e/helper code explicitly treats dot entries under `node_modules/.pnpm` as pnpm-owned internals that should not be considered dependency directories.

### Fix Focus Areas
- scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]

### Suggested fix
- Change `readPackageDirsFromVirtualStore()` to:
 - use `readdir(..., { withFileTypes: true })`
 - include **directories only**
 - exclude entries that start with `.`
 - keep excluding `node_modules` and `lock.yaml`
- Add/adjust an e2e or unit test for the global virtual store path to ensure prune does not remove dot-prefixed pnpm entries under `node_modules/.pnpm`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread workspace.jsonc
"resolveEnvsFromRoots": true
},
"teambit.dependencies/dependency-resolver": {
"enableGlobalVirtualStore": true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Prune deletes pnpm internals 🐞 Bug ☼ Reliability

With enableGlobalVirtualStore enabled, pnpm keeps pnpm-owned dot entries under
node_modules/.pnpm, but pnpmPruneModules() does not exclude dot entries and will remove them
when they don’t appear in the lockfile’s package list. This can break or destabilize subsequent
installs by deleting pnpm-managed virtual-store state (or forcing it to be recreated unpredictably).
Agent Prompt
### Issue description
After this PR enables `enableGlobalVirtualStore` in `workspace.jsonc`, installs run in the global virtual store layout where `node_modules/.pnpm` contains pnpm-owned entries (including dot-prefixed directories). The post-install prune step (`pnpmPruneModules`) currently treats *all* entries except `lock.yaml` and `node_modules` as prune candidates, so it may delete pnpm-owned dot entries.

### Issue Context
- The workspace runs a prune step after installs.
- Repo e2e/helper code explicitly treats dot entries under `node_modules/.pnpm` as pnpm-owned internals that should not be considered dependency directories.

### Fix Focus Areas
- scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-50]

### Suggested fix
- Change `readPackageDirsFromVirtualStore()` to:
  - use `readdir(..., { withFileTypes: true })`
  - include **directories only**
  - exclude entries that start with `.`
  - keep excluding `node_modules` and `lock.yaml`
- Add/adjust an e2e or unit test for the global virtual store path to ensure prune does not remove dot-prefixed pnpm entries under `node_modules/.pnpm`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

With enableGlobalVirtualStore, node_modules holds only symlinks into
<store-dir>/links. pnpm's default store is ~/.local/share/pnpm, outside
setup_harmony's persist_to_workspace root, so every job that merely
attaches the workspace received dangling symlinks (lint died on a
missing node_modules/oxlint/bin/oxlint).

Point store-dir under ~/bit and persist the links directory. files/ is
left out: the consumers of this workspace read node_modules, they never
fetch packages, and carrying the content-addressable store too would
duplicate every package in the archive.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread .circleci/config.yml
Comment on lines +685 to +688
# only the global virtual store, not the content-addressable files/ it hardlinks from:
# the consumers of this workspace read node_modules, they never fetch packages, and
# carrying files/ too would duplicate every package in the archive.
- .pnpm-store/*/links

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Persisted links path mismatch 🐞 Bug ☼ Reliability

The CircleCI workspace persists .pnpm-store/*/links, but Bit resolves the global virtual store at
<storeDir>/links; if the resolved storeDir is /home/circleci/bit/.pnpm-store (as configured),
downstream jobs that only attach the workspace may miss the actual links directory and end up with
broken node_modules symlinks.
Agent Prompt
## Issue description
CircleCI persists `.pnpm-store/*/links`, but Bit/pnpm’s global virtual store directory is computed as `<storeDir>/links`. If pnpm resolves `storeDir` to the configured `/home/circleci/bit/.pnpm-store`, the actual required directory would be `.pnpm-store/links`, which is not matched by `.pnpm-store/*/links`.

This can break downstream jobs that rely on the attached workspace (without reinstalling) because `node_modules` entries may symlink into the missing global virtual store.

## Issue Context
- CI explicitly sets `store-dir=/home/circleci/bit/.pnpm-store`.
- Bit’s pnpm adapter computes the global virtual store as `join(config.storeDir, 'links')`.
- Downstream jobs (e.g. `lint`) attach the workspace and run commands without reinstalling.

## Fix Focus Areas
- .circleci/config.yml[665-710]

## Suggested fix
Update `persist_to_workspace.paths` to persist the exact `links` directory that Bit/pnpm uses.

A pragmatic, layout-tolerant option that still avoids persisting `files/` is to include both possible layouts:
- `.pnpm-store/links`
- `.pnpm-store/*/links`

(If you want to be stricter/cleaner, ensure the persisted path exactly matches the resolved `<storeDir>/links` layout you expect in CI.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 9424647

store-dir in .npmrc is ignored: pnpm keeps only npm-compatible settings
there, and bit installs through @pnpm/napi's config reader, which takes
storeDir from the pnpm-workspace.yaml cascade. The store stayed in
~/.local/share/pnpm, outside the persist_to_workspace root, so the
node_modules symlinks reaching into <storeDir>/links still dangled in
every job that only attaches the workspace.

Write a CI-only pnpm-workspace.yaml instead, and check the store landed
inside the workspace before persisting it — a persist path that matches
nothing is not an error, so the previous attempt failed as a
MODULE_NOT_FOUND in lint rather than in the job that got it wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread workspace.jsonc
"resolveEnvsFromRoots": true
},
"teambit.dependencies/dependency-resolver": {
"enableGlobalVirtualStore": true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Schema missing gvs key 🐞 Bug ⚙ Maintainability

workspace.jsonc now sets enableGlobalVirtualStore, but the repo’s workspace-jsonc-schema.json
does not define this property under teambit.dependencies/dependency-resolver, so schema-driven
validation/autocomplete cannot surface/validate the new config key.
Agent Prompt
### Issue description
`workspace.jsonc` enables `enableGlobalVirtualStore`, but `workspace-jsonc-schema.json` does not declare this option in the `teambit.dependencies/dependency-resolver` schema. This creates schema/config drift: editors and any schema validation tooling won’t recognize the new key.

### Issue Context
The config key is a real, supported option in code (`DependencyResolverWorkspaceConfig.enableGlobalVirtualStore?: boolean`), so the schema should be updated to match.

### Fix Focus Areas
- workspace-jsonc-schema.json[51-320]
- workspace.jsonc[13-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit ebfb668

The global virtual store puts every package's real directory outside the
project, so a package that requires an undeclared dependency by bare name
no longer finds it: node resolves from the realpath, and the ancestor walk
out of <store>/links/@/mocha/... never reaches the project's node_modules
the way the walk out of node_modules/.pnpm/mocha@11.1.0/ did.

mocha requires the reporter, and mocha-multi-reporters requires each
reporter it composes, so both hops died — taking down every e2e job before
a single test ran. Both accept a path resolved against cwd, which is the
repo root for these scripts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 23abbf3

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant