Skip to content

chore: use global virtual store - #10587

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

zkochan wants to merge 16 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 (15) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Later installs break loaded environments 🐞 Bug ☼ Reliability
Description
snapshotLoadedVirtualStoreDirs() only scans /node_modules/.pnpm, even when the installer has
moved loaded package directories into the configured global store. When a subsequent install removes
or re-keys one of those package slots, deferred imports from an already-loaded environment can fail
because the restore phase captured nothing.
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The package manager explicitly snapshots loaded package directories before installation and restores
removed directories afterward, because re-keying can otherwise make deferred environment imports
throw. However, the snapshot function hard-codes the project-local virtual store while this PR
activates and forwards the global-store option, so no global package slot is captured.

workspace.jsonc[13-21]
scopes/dependencies/pnpm/pnpm.package-manager.ts[207-216]
scopes/dependencies/pnpm/pnpm.package-manager.ts[250-253]
scopes/dependencies/pnpm/pnpm.package-manager.ts[276-284]
scopes/dependencies/pnpm/preserve-loaded-virtual-store-dirs.ts[5-17]
scopes/dependencies/pnpm/preserve-loaded-virtual-store-dirs.ts[103-130]

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

## Issue description
Enabling the global virtual store moves package slots outside the only directory inspected by the loaded-module preservation mechanism. Subsequent installs can remove or re-key a package backing an already-loaded environment, leaving deferred imports pointed at deleted files.
## Fix Focus Areas
- workspace.jsonc[14-14]
- scopes/dependencies/pnpm/pnpm.package-manager.ts[207-283]
- scopes/dependencies/pnpm/preserve-loaded-virtual-store-dirs.ts[62-130]
## Recommended Fix
Pass the effective virtual-store location into the snapshot operation and extend the snapshot/restore implementation to identify loaded package slots under both project-local and global virtual-store layouts. Preserve and restore removed global-store slots using the same loaded-module and compatible-donor safeguards currently applied to `node_modules/.pnpm`.

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


2. Preview builds fail on host imports 🐞 Bug ≡ Correctness
Description
EnvBundlingStrategy.computeTargets() adds PHANTOM_HOST_CORE_ASPECTS to aliased host dependencies
but leaves the target's hostRootDir undefined. When an environment preview contains the undeclared
core-aspect import this change is intended to bridge, alias resolution falls back to the process or
package location rather than the environment aspect directory, which is unreachable from a
global-store slot.
Code

scopes/preview/preview/strategies/env-strategy.ts[R53-54]

+        hostDependencies: [...peers, ...PHANTOM_HOST_CORE_ASPECTS],
      aliasHostDependencies: true,
Evidence
The changed target enables host-dependency aliasing without a host root. The bundler contract
explicitly defines hostRootDir as the resolution root for aliases and specifies its fallback
order; the comparable environment preview template resolves and supplies the environment aspect path
before adding the same phantom dependency.

scopes/preview/preview/strategies/env-strategy.ts[32-55]
scopes/compilation/bundler/bundler-context.ts[97-123]
scopes/preview/preview/env-preview-template.task.ts[160-182]
scopes/compilation/bundler/bundler-context.ts[201-220]

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

The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
Issue description
`EnvBundlingStrategy` now aliases `@teambit/component` through `PHANTOM_HOST_CORE_ASPECTS`, but its target has no `hostRootDir`. The bundler's host-dependency alias resolution requires that path to resolve the dependency from the environment host instead of the global pnpm-store location.
Fix Focus Areas
- scopes/preview/preview/strategies/env-strategy.ts[32-55]
- scopes/preview/preview/env-preview-template.task.ts[160-182]
Recommended Fix
Resolve the environment aspect path while computing the env-strategy target and set it as `hostRootDir`, following the resolution approach used by `EnvPreviewTemplateTask`. Preserve the existing peer and phantom host-dependency aliases.

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


3. Registry-backed suites time out 🐞 Bug ≡ Correctness
Description
_establishRegistry() calls data.includes(REGISTRY_MOCK_PORT) on the child process's stdout
buffer, passing the numeric port rather than its textual representation. Buffer.includes() treats
that argument as a byte value instead of searching Verdaccio's emitted port text, so the readiness
fetch is never attempted and every registry-backed suite rejects after the new 60-second timeout.
Code

components/legacy/e2e-helper/npm-ci-registry.ts[109]

+        if (!settled && data.includes(REGISTRY_MOCK_PORT)) {
Evidence
The changed handler receives child-process stdout, appends its textual conversion to diagnostic
output, but performs the readiness test on the original buffer with the numeric port. The only code
that probes /is-odd is inside that condition, while the new timer rejects when it is not reached.

components/legacy/e2e-helper/npm-ci-registry.ts[101-105]
components/legacy/e2e-helper/npm-ci-registry.ts[107-119]
components/legacy/e2e-helper/npm-ci-registry.ts[124-128]

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

## Issue description
The registry readiness condition searches a stdout `Buffer` with the numeric `REGISTRY_MOCK_PORT`, which does not match the port text printed by Verdaccio. As a result, the startup probe is skipped and the new timeout fails otherwise healthy registry-backed test setup.
## Fix Focus Areas
- components/legacy/e2e-helper/npm-ci-registry.ts[107-109]
## Recommended Fix
Convert stdout to text before evaluating readiness and compare it with `String(REGISTRY_MOCK_PORT)`, for example by storing `const stdout = data.toString()` and using `stdout.includes(String(REGISTRY_MOCK_PORT))` while pushing that same value into `output`.

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


View high (6)
4. Aspect tests fail before commands run 🐞 Bug ≡ Correctness
Description
The new appendFile() call targets my-scope/my-aspect/my-aspect.aspect.ts, while createAspect()
creates the component beneath the dynamically generated remote-scope directory. Because
appendFile() does not create parent directories, the suite's before hook throws ENOENT and
none of its status or list assertions execute.
Code

e2e/harmony/aspect.e2e.ts[53]

+      helper.fs.appendFile(path.join('my-scope', 'my-aspect', 'my-aspect.aspect.ts'), `\nimport '${missingPkg}';\n`);
Evidence
createAspect() derives its directory from the current default or remote scope, and the remote
scope is randomly generated unless explicitly supplied. The filesystem helper delegates directly to
appendFileSync(), so the hard-coded nonexistent parent path is not created automatically.

e2e/harmony/aspect.e2e.ts[49-59]
components/legacy/e2e-helper/e2e-fixtures-helper.ts[242-265]
components/legacy/e2e-helper/e2e-scope-helper.ts[142-146]
components/legacy/e2e-helper/e2e-scopes.ts[35-43]
components/legacy/e2e-helper/e2e-fs-helper.ts[122-127]

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

## Issue description
The injected missing-package import targets a hard-coded `my-scope` directory, but `createAspect()` places the fixture under the dynamically generated remote-scope directory. This causes the setup hook to fail before the assertions run.
## Fix Focus Areas
- e2e/harmony/aspect.e2e.ts[53-53]
## Recommended Fix
Construct the aspect source path from `helper.scopes.remoteWithoutOwner`, or pass an explicit `path` to `createAspect()` and reuse that same path when appending the import.

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


5. Local previews fail under global store 🐞 Bug ≡ Correctness
Description
PHANTOM_HOST_CORE_ASPECTS is added to the other non-externalized preview targets, but
PreviewService still passes only peers to both its bundler context and target despite enabling
aliasHostDependencies. When local preview bundles a package with the documented undeclared
@teambit/component import, no host alias is generated and module resolution escapes into the
global store instead of finding the host copy.
Code

scopes/compilation/bundler/bundler-context.ts[216]

+export const PHANTOM_HOST_CORE_ASPECTS = ['@teambit/component'];
Evidence
The new constant's documentation says these phantom imports must be listed wherever host
dependencies are aliased and not externalized. PreviewService has two such local-preview
configurations, but both still use only resolver-provided peers; the alias generator can therefore
never create the new @teambit/component alias for this path.

scopes/compilation/bundler/bundler-context.ts[201-216]
scopes/preview/preview/preview.service.tsx[91-117]
scopes/preview/preview/preview.service.tsx[229-238]
scopes/dependencies/dependency-resolver/dependency-resolver.main.runtime.ts[1354-1359]
scopes/webpack/webpack/webpack.main.runtime.ts[202-207]

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

## Issue description
The new phantom host dependency is applied to dev-server and environment-preview targets but omitted from `PreviewService`, whose local-preview targets also alias non-externalized host dependencies. Local previews can therefore still fail to resolve `@teambit/component` under the global virtual store.
## Fix Focus Areas
- scopes/preview/preview/preview.service.tsx[1-12]
- scopes/preview/preview/preview.service.tsx[91-107]
- scopes/preview/preview/preview.service.tsx[229-237]
## Recommended Fix
Import `PHANTOM_HOST_CORE_ASPECTS` from `@teambit/bundler` as a runtime value and append it to `peers` for both the local-preview bundler context and generated target, matching the other non-externalized preview paths.

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


6. CI test suites cannot start reporters 🐞 Bug ≡ Correctness
Description
mocha-multi-reporters-config.json changes the JUnit reporter to a relative
./node_modules/mocha-junit-reporter specifier, which mocha-multi-reporters resolves relative to
its own package directory rather than the repository root. Each CircleCI Mocha script passes this
config, while the JUnit reporter is installed as a sibling workspace dependency, so reporter
initialization fails before the selected tests run.
Code

mocha-multi-reporters-config.json[2]

+    "reporterEnabled": "spec, ./node_modules/mocha-junit-reporter",
Evidence
The changed config supplies the relative reporter path, and all four CI scripts load that config
through mocha-multi-reporters. The workspace declares mocha-junit-reporter and
mocha-multi-reporters as separate dependencies, so the former is not available at the relative
child path under the latter.

mocha-multi-reporters-config.json[1-5]
package.json[35-42]
workspace.jsonc[572-574]

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

## Issue description
The reporter configured in `mocha-multi-reporters-config.json` must be resolvable from the `mocha-multi-reporters` module. A relative `./node_modules/...` reporter path is interpreted from that module rather than the repository root.
### Fix Focus Areas
- mocha-multi-reporters-config.json[2-2]
### Recommended Fix
Restore `mocha-junit-reporter` as the configured reporter package name. Keep the explicit repository-root path for the top-level `--reporter ./node_modules/mocha-multi-reporters` invocation if it is required by the global virtual-store layout.

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


7. Linked packages use the wrong source 🐞 Bug ≡ Correctness
Description
getDistDirForDevEnv() passes store-backed resolution results to resolveModuleDirFromFile(),
whose fallback parses an @-delimited virtual-store path as though it were a package-version
directory. When a package resolves under /links////, scoped packages can resolve to the scope
directory and additional or legacy package links are then skipped or created from the wrong
location.
Code

scopes/dependencies/dependency-resolver/dependency-linker.ts[R925-928]

+    const resolvedModulePath = resolveModuleFromDir(fromDir, packageName);
+    if (!resolvedModulePath) continue;
+    const dirPath = resolveModuleDirFromFile(resolvedModulePath, packageName);
+    if (fs.existsSync(dirPath)) return dirPath;
Evidence
The linker documents global-store package roots as /links////, while resolveModuleDirFromFile()
splits the resolved path at @ and retains only the first following segment. The newly added call
accepts that computed directory when it merely exists, so a scoped package can select the existing
scope directory rather than its package root before the value is used as a link source.

scopes/dependencies/dependency-resolver/dependency-linker.ts[196-202]
scopes/dependencies/dependency-resolver/dependency-linker.ts[923-930]
scopes/dependencies/dependency-resolver/dependency-linker.ts[955-964]
scopes/dependencies/dependency-resolver/dependency-linker.ts[865-895]

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

## Issue description
Store-backed module paths are passed through a helper whose fallback cannot derive package roots from the global virtual store layout, producing missing or incorrect link sources.
## Fix Focus Areas
- scopes/dependencies/dependency-resolver/dependency-linker.ts[923-930]
- scopes/dependencies/dependency-resolver/dependency-linker.ts[955-964]
## Recommended Fix
Replace the path-string parsing fallback with package-root discovery that walks upward from the resolved module file until it finds a package.json whose name matches the requested package. Return undefined when no matching package root exists, and update callers to handle that result without constructing a link from an invalid directory.

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


8. Store-backed bundles still fail 🐞 Bug ≡ Correctness
Description
resolveModules builds absolute search paths only by walking upward from the compiled config
module's __dirname, even though that directory is a dead-end store slot under the enabled layout.
When browser, development, or server rendering bundles encounter the phantom dependencies this
change targets, their resolver still cannot reach the installation's private hoist or root modules
directories.
Code

scopes/ui-foundation/ui/rspack/rspack.common.ts[R44-47]

+  let dir = __dirname;
+  for (;;) {
+    const candidate = path.join(dir, 'node_modules');
+    if (existsSync(candidate)) hostModulesDirs.push(candidate);
Evidence
The repository's resolution bridge explicitly states that __dirname is a dead end when the module
is loaded from a global-store slot and instead locates the installation from process.argv[1]. It
also establishes that both the private hoist and root node_modules directories are required,
whereas the new Rspack list only considers node_modules directories found above __dirname and is
installed directly into all three resolver configurations.

scopes/ui-foundation/ui/rspack/rspack.common.ts[42-53]
scopes/dependencies/dependency-resolver/hoisted-resolution-bridge.ts[184-208]
scopes/dependencies/dependency-resolver/hoisted-resolution-bridge.ts[226-239]
scopes/ui-foundation/ui/rspack/rspack.browser.config.ts[93-98]
scopes/ui-foundation/ui/rspack/rspack.dev.config.ts[152-157]
scopes/ui-foundation/ui/rspack/rspack.ssr.config.ts[66-71]

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

## Issue description
Rspack derives host module search paths from a global-store slot, which has no physical ancestor path back to the installation containing the required hoisted and direct dependencies.
## Fix Focus Areas
- scopes/ui-foundation/ui/rspack/rspack.common.ts[42-53]
- scopes/dependencies/dependency-resolver/hoisted-resolution-bridge.ts[184-239]
## Recommended Fix
Locate the actual installation root using an unresolved invocation path or equivalent installation metadata, then append both `<root>/node_modules/.pnpm/node_modules` and `<root>/node_modules` when they exist. Keep `node_modules` first so normal importer-relative dependency resolution retains precedence.

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


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

10. Fresh installs rewrite the lockfile 🐞 Bug ≡ Correctness ⭐ New
Description
The new packageExtensions change pnpm's dependency graph, but the committed snapshots still omit
@verdaccio/config from @verdaccio/signature and express from @verdaccio/auth. A normal `bit
install` forwards these extensions to pnpm with a non-frozen lockfile, so fresh checkouts rewrite
the tracked lockfile and lose reproducibility until those generated changes are committed.
Code

workspace.jsonc[R21-24]

+    "packageExtensions": {
+      "@verdaccio/signature": {
+        "dependencies": {
+          "@verdaccio/config": "8.0.0-next-8.1"
Evidence
Bit passes workspace package extensions through the dependency installer and pnpm wrapper, while
ordinary installs prefer rather than require a frozen lockfile. The checked-in snapshots currently
lack both newly injected edges, proving that the committed dependency graph does not match the new
configuration.

workspace.jsonc[21-31]
scopes/dependencies/dependency-resolver/dependency-installer.ts[370-379]
scopes/dependencies/pnpm/lynx.ts[394-395]
scopes/dependencies/pnpm/lynx.ts[427-445]
pnpm-lock.yaml[86016-86028]
pnpm-lock.yaml[86132-86137]

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

## Issue description
The configured Verdaccio package extensions are absent from the committed pnpm lockfile, causing the next install to rewrite tracked dependency data.

## Fix Focus Areas
- workspace.jsonc[21-31]
- pnpm-lock.yaml[86016-86028]
- pnpm-lock.yaml[86132-86137]

## Recommended Fix
Run the repository's supported Bit/pnpm install after applying the package extensions, then commit the resulting pnpm-lock.yaml changes, including the injected dependency edges and any package-extension metadata.

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


11. Healthy registries can fail startup 🐞 Bug ☼ Reliability ⭐ New
Description
The stdout callback checks only settled, which remains false throughout the asynchronous readiness
fetch and therefore allows another matching output event to start a competing fetch. If Verdaccio
emits its port more than once while a probe is pending, an errored or non-200 probe can reject
startup before another successful probe completes, failing every registry-backed suite.
Code

components/legacy/e2e-helper/npm-ci-registry.ts[R108-110]

+        output.push(data.toString());
+        if (!settled && data.includes(REGISTRY_MOCK_PORT)) {
          let fetchResults;
Evidence
The listener may execute again while the first asynchronous fetch is pending because settled
changes only inside settle() after that fetch completes. Every competing callback can call the
same rejection path, and the first result permanently determines startup through the settlement
guard.

components/legacy/e2e-helper/npm-ci-registry.ts[86-96]
components/legacy/e2e-helper/npm-ci-registry.ts[107-129]
components/legacy/e2e-helper/npm-ci-registry.ts[137-143]

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

## Issue description
Registry stdout can initiate multiple concurrent readiness requests before the startup promise settles, allowing a failed probe to win over a successful one.

## Fix Focus Areas
- components/legacy/e2e-helper/npm-ci-registry.ts[86-129]

## Recommended Fix
Add a separate readiness-probe-started flag and set it synchronously before awaiting the fetch. Keep `settled` for final promise settlement so only one probe runs while error, close, and timeout handlers remain idempotent.

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


12. Existing checkouts cannot run setup 🐞 Bug ≡ Correctness
Description
enableGlobalVirtualStore makes npm run setup invoke the transition through npm's workspace-local
node_modules/.bin/bit, which assertSafeVirtualStoreTransition() explicitly rejects while
.modules.yaml still records the project-local layout. Any existing checkout with the old layout
therefore aborts the documented setup and install commands until the contributor independently runs
one installation using an external Bit binary.
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
The PR enables the new layout in workspace.jsonc, while package.json defines the basic setup as
bit install and npm prepends the workspace's node_modules/.bin to that command. The installer
classifies the old .pnpm layout as local and throws whenever the running Bit code is inside the
workspace's node_modules; its error confirms that an external installation is required for this
one transition, but the contributor documentation still directs users to the failing commands.

workspace.jsonc[13-16]
package.json[43-48]
scopes/dependencies/dependency-resolver/dependency-installer.ts[224-257]
scopes/dependencies/dependency-resolver/exceptions/self-hosted-virtual-store-transition.ts[15-24]
CLAUDE.md[19-24]
CONTRIBUTING.md[14-17]

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

## Issue description
Enabling the global virtual store requires a one-time layout transition, but the documented `npm run setup` command resolves `bit` from the existing workspace's `node_modules` and is deliberately rejected by the transition guard.
## Fix Focus Areas
- workspace.jsonc[14-14]
- package.json[43-48]
- CLAUDE.md[19-24]
- CONTRIBUTING.md[14-17]
## Recommended Fix
Update the setup scripts so the first layout-changing install runs through a Bit installation outside the workspace, following the existing external-binary setup variant, and update contributor instructions to document the one-time migration path. Keep subsequent installs able to use the workspace-local binary after the global layout has been established.

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


View medium (3)
13. Peer variants disappear from diagnostics 🐞 Bug ≡ Correctness
Description
With the global virtual store enabled, readVirtualStoreEntries() falls back to lock.yaml but
reads packages, whose keys omit peer-specific installation variants; both bit deps diagnose and
bit deps diagnose --package therefore undercount copies and report incorrect peer combinations.
This repository's lockfile demonstrably stores the corresponding peer-suffixed variants under
snapshots.
Code

workspace.jsonc[14]

+    "enableGlobalVirtualStore": true,
Evidence
GVS is activated by this PR. The diagnostic fallback explicitly reads lockfile.packages, while the
repository's pruning code documents that .pnpm directory names correspond to peer-suffixed
snapshots keys; the actual lockfile shows a suffix-free packages key for @apollo/client and a
peer-suffixed snapshots key, and the command presents these entries as installed-copy counts and
peer combinations.

workspace.jsonc[13-15]
scopes/dependencies/dependencies/dependencies.main.runtime.ts[604-623]
scopes/dependencies/pnpm/pnpm-prune-modules.ts[21-25]
pnpm-lock.yaml[26667-26667]
pnpm-lock.yaml[46399-46406]
scopes/dependencies/dependencies/dependencies-cmd.ts[439-466]

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

## Issue description
When the global virtual store leaves no package directories in `node_modules/.pnpm`, dependency diagnostics reconstruct installed copies from the current lockfile. Reading `packages` loses peer-specific variants, causing incorrect copy counts and drill-down output.
## Issue Context
Use the peer-suffixed dependency paths from `lockfile.snapshots` and convert those paths with `depPathToDirName`, matching the representation of materialized `.pnpm` directories. Add coverage for multiple snapshots of the same package/version with different peer combinations while the virtual-store directory contains only `lock.yaml`/metadata.
## Fix Focus Areas
- scopes/dependencies/dependencies/dependencies.main.runtime.ts[613-623]
- scopes/dependencies/dependencies/dependencies.main.runtime.ts[627-658]

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


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


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



Informational

16. Hard-coded storeDir path 🐞 Bug ⚙ Maintainability
Description
CircleCI hard-codes the pnpm store location to /home/circleci/bit/.pnpm-store, coupling the
install output to the current executor user/home + working_directory layout. If the executor
image/user or working_directory ever changes, the global virtual store can end up outside the
persisted workspace root and downstream jobs may get dangling node_modules symlinks.
Code

.circleci/config.yml[R678-679]

+            echo "storeDir: /home/circleci/bit/.pnpm-store" > pnpm-workspace.yaml &&
+            echo "pnpm-workspace.yaml" >> .git/info/exclude &&
Evidence
The CI config defines the job working directory via ~/bit, but the new store configuration and
verification step use a fixed /home/circleci/bit path, introducing coupling to the executor’s home
directory resolution.

.circleci/config.yml[15-20]
.circleci/config.yml[674-702]

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

## Issue description
The CircleCI setup writes `pnpm-workspace.yaml` with an absolute `storeDir` under `/home/circleci/bit`, which is brittle if the job’s working directory or executor home ever changes.
### Issue Context
- The job working directory is configured as `~/bit`.
- `storeDir` and its verification step repeat `/home/circleci/bit` explicitly.
### Fix Focus Areas
- .circleci/config.yml[15-20]
- .circleci/config.yml[674-702]
### Suggested fix
In the `bbit install` step, compute the store path from the actual runtime directory (e.g., the outer workspace root) and use that variable consistently for:
- the `storeDir:` written into `pnpm-workspace.yaml`
- the verification step
For example, set `STORE_DIR="$(cd .. && pwd)/.pnpm-store"` (or similar, depending on where you want the store relative to the persisted root) and write `storeDir: ${STORE_DIR}`.

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


Grey Divider

Context sources
Review mode: 🧠 Deep: This broad, behavior-changing PR spans CI, dependency resolution, bundling, previews, and test infrastructure, with many independent logic sites and a high density of plausible subtle defects.

Grey Divider

Tip of the day
💡 Did you know, you can turn these tips off under Display preferences

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread workspace.jsonc
Comment thread .circleci/config.yml
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

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

Comment thread workspace.jsonc
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

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

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

Copy link
Copy Markdown

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

zkochan and others added 4 commits August 18, 2026 14:34
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>
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>
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>
Comment thread .circleci/config.yml
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 82d9421

Comment thread workspace.jsonc
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 4ece4d2

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 3523e61

Comment thread workspace.jsonc
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

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

zkochan and others added 2 commits September 10, 2026 15:04
…out of reach

Under the project-local layout the workspace root is an ancestor of every
package's real directory, so node's walk up from any package reaches the root
node_modules and a phantom import - a package requiring something it never
declared - lands there. With a global virtual store a package's realpath is
inside the pnpm store, the root is never an ancestor, and every such import
fails. Three consumers hit this:

- dependency-linker resolved @teambit/legacy and @teambit/harmony with a bare
  require.resolve, searching from its own realpath, and threw when it missed -
  taking down every bit link and bit install. It now searches the installation
  that holds @teambit/bit and the target workspace, and skips the link when the
  package is nowhere on disk: linking it is a backward-compatibility convenience
  for workspaces that still import it, not a reason to fail the command.

- verdaccio, the e2e mock registry, died on @verdaccio/signature -> @verdaccio/config
  and @verdaccio/auth -> express. Both are declared through packageExtensions,
  pinned to versions already resolved elsewhere in the tree.

- the rspack ui bundle lost @teambit/component, @teambit/docs and the node
  polyfills memfs and isbinaryfile import. resolve.modules now lists the host
  installation's node_modules chain, which also keeps a core aspect a single
  copy - a packageExtensions entry would have installed a second one.

Also make _establishRegistry settle on every path. A verdaccio that dies without
printing a port left the promise pending, and the suites run with timeout(0), so
25 of 40 e2e shards spent CircleCI's full 50-minute no-output timeout on what is
now a sub-second failure carrying verdaccio's own output.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
destroy runs from an `after` hook, which mocha still runs when the matching
`before` failed. Without the guard a TypeError here replaces the startup error
the report needs to show.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
Comment thread scopes/dependencies/dependency-resolver/dependency-linker.ts
Comment thread scopes/ui-foundation/ui/rspack/rspack.common.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 1861a45

`@teambit/semantics.entities.semantic-schema` requires `@teambit/component`
without declaring it - it is written against the instance the host provides.
That import used to resolve on its own: the package's real directory sat inside
the workspace or capsule, so the bundler's walk up from it reached a root whose
node_modules holds bit's linked core aspects. Under a global virtual store the
real directory is in the pnpm store, the walk leaves for the store, and three
build paths fail with `Can't resolve '@teambit/component'` - the env preview
template (bit_pr and custom-env-operations), the env preview strategy, and the
dev server (bit start).

hostDependencies is the mechanism already built for this: the alias transformer
resolves each entry against [hostRootDir, cwd, __dirname] and points the bundle
at the host's own copy. PHANTOM_HOST_CORE_ASPECTS is added only where those
dependencies are aliased and not externalized - a component preview externalizes
them, and nothing supplies a core aspect to an external at runtime.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
Comment thread mocha-multi-reporters-config.json
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

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

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

qodo-free-for-open-source-projects Bot commented Sep 10, 2026

Copy link
Copy Markdown

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

Qodo Logo

…e lockfile

readVirtualStoreEntries falls back to the private lockfile when no package
directories are materialized, and read `packages` - the section keyed without the
peer suffix. The virtual-store directory names it is comparing against come from
the peer-suffixed dep paths, which is what `snapshots` is keyed by, so every peer
variant of a package collapsed into one entry and `bit deps diagnose` undercounted
exactly the copies it exists to report.

Under the global virtual store this stopped being academic: nothing is
materialized under the project's own .pnpm, so the lockfile is the only source.
`packages` stays as the fallback for a lockfile written before `snapshots`.

Also declare enableGlobalVirtualStore and packageExtensions in the workspace.jsonc
schema, so the keys this branch adds validate and autocomplete.

Both found by the Qodo review on teambit#10587.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
Comment thread scopes/compilation/bundler/bundler-context.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

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

…ot supply

The suite proved that a command with loaders reports a descriptive load error by
creating an aspect and never installing it, then asserting on the resulting
"Cannot find module '@teambit/harmony'". Under the global virtual store bit puts
its own installation on NODE_PATH so that every phantom @teambit/* import
resolves to the host's copy - that is what hoisted-resolution-bridge exists to
do - so the aspect loads, and the suite silently stops testing anything.

Give the aspect an import of a package that exists nowhere instead. The failure
is then independent of the layout and of anything the host provides, and the
suite keeps asserting what it was written to assert. Verified passing under both
layouts: 3 passing project-local, 3 passing global-virtual-store.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
Comment thread e2e/harmony/aspect.e2e.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 4870fe4

…l store

The suite proved that an env which cannot be loaded is reported as "(not loaded)"
by emptying node_modules, so the env's @teambit/envs and @teambit/node imports
would not resolve. Under the global virtual store bit puts its own installation
on NODE_PATH, so those imports resolve to the host's copies by design
(hoisted-resolution-bridge): the env loads, isEnvRegistered returns true, and
both the marker and the NonLoadedEnv issue disappear.

Give the env an import of a package that exists nowhere, on top of the empty
node_modules. The env then stays unloadable for a reason no installation can
repair, and the suite keeps asserting what it was written to assert. Verified
passing under both layouts, and with the rest of the file: 3 passing
project-local, 3 passing global-virtual-store.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
Comment thread components/legacy/e2e-helper/npm-ci-registry.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 507d8ab

PreviewService builds two more targets that alias their host dependencies
without externalizing them - the local-preview bundler context and the target it
generates - and both were left out, so `bit start`'s local preview could still
fail to resolve `@teambit/component` out of the global store. The file is .tsx,
which is how it escaped the original sweep.

Also state the boundary the constant is applied on: the bundle has to carry
bit's own UI packages, which is where these phantom imports come from. That
excludes a user's application build (react.application.ts aliases host
dependencies too, but bundles user code).

Found by the Qodo review on teambit#10587.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
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. Later installs break loaded environments 🐞 Bug ☼ Reliability

snapshotLoadedVirtualStoreDirs() only scans <workspace>/node_modules/.pnpm, even when the
installer has moved loaded package directories into the configured global store. When a subsequent
install removes or re-keys one of those package slots, deferred imports from an already-loaded
environment can fail because the restore phase captured nothing.
Agent Prompt
## Issue description
Enabling the global virtual store moves package slots outside the only directory inspected by the loaded-module preservation mechanism. Subsequent installs can remove or re-key a package backing an already-loaded environment, leaving deferred imports pointed at deleted files.

## Fix Focus Areas
- workspace.jsonc[14-14]
- scopes/dependencies/pnpm/pnpm.package-manager.ts[207-283]
- scopes/dependencies/pnpm/preserve-loaded-virtual-store-dirs.ts[62-130]

## Recommended Fix
Pass the effective virtual-store location into the snapshot operation and extend the snapshot/restore implementation to identify loaded package slots under both project-local and global virtual-store layouts. Preserve and restore removed global-store slots using the same loaded-module and compatible-donor safeguards currently applied to `node_modules/.pnpm`.

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Accurate, and I'm deliberately not fixing it blind — leaving this thread open.

Confirmed: snapshotLoadedVirtualStoreDirs() hard-codes path.join(rootDir, 'node_modules', '.pnpm'), so under the global virtual store, where loaded slots live in <storeDir>/<version>/links, it captures nothing.

Two things narrow the impact, which is why I'd rather this were a separate change with its own reasoning than a rushed one here:

  • pnpmPruneModules() early-returns under this layout (readPackageDirsFromVirtualStore finds only lock.yaml and node_modules), so the pruning path this mechanism guards against is inert.
  • The global store is content-addressed, so re-keying a package creates a new hash directory rather than removing the loaded one in place; the engine prunes the store on its own schedule.

So the failure window is narrower than in the project-local layout, but it is not closed, and the recommendation — pass the effective virtual-store location through and handle both layouts — looks right to me. Filing it as follow-up work rather than resolving it.

Comment thread scopes/preview/preview/strategies/env-strategy.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 875913c

The alias transformer resolves each host dependency from
[hostRootDir, process.cwd(), __dirname]. This target never set the first, so the
aliases - now including the phantom core aspects - were resolved from the
directory the command happened to run in. That holds bit's linked core aspects,
which is why preview builds pass, but it is not the env the bundle belongs to.

Its sibling, ComponentBundlingStrategy, already takes the path from
context.envRuntime.envAspectDefinition, and the same context is available here;
the "hostRootDir, handle this" note has been open since teambit#5839.

Found by the Qodo review on teambit#10587.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnieZnVXAAyoDs5Rom9XKj
Comment thread workspace.jsonc
Comment on lines +21 to +24
"packageExtensions": {
"@verdaccio/signature": {
"dependencies": {
"@verdaccio/config": "8.0.0-next-8.1"

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

10. Fresh installs rewrite the lockfile 🐞 Bug ≡ Correctness

The new packageExtensions change pnpm's dependency graph, but the committed snapshots still omit
@verdaccio/config from @verdaccio/signature and express from @verdaccio/auth. A normal `bit
install` forwards these extensions to pnpm with a non-frozen lockfile, so fresh checkouts rewrite
the tracked lockfile and lose reproducibility until those generated changes are committed.
Agent Prompt
## Issue description
The configured Verdaccio package extensions are absent from the committed pnpm lockfile, causing the next install to rewrite tracked dependency data.

## Fix Focus Areas
- workspace.jsonc[21-31]
- pnpm-lock.yaml[86016-86028]
- pnpm-lock.yaml[86132-86137]

## Recommended Fix
Run the repository's supported Bit/pnpm install after applying the package extensions, then commit the resulting pnpm-lock.yaml changes, including the injected dependency edges and any package-extension metadata.

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

Comment on lines +108 to 110
output.push(data.toString());
if (!settled && data.includes(REGISTRY_MOCK_PORT)) {
let fetchResults;

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

11. Healthy registries can fail startup 🐞 Bug ☼ Reliability

The stdout callback checks only settled, which remains false throughout the asynchronous readiness
fetch and therefore allows another matching output event to start a competing fetch. If Verdaccio
emits its port more than once while a probe is pending, an errored or non-200 probe can reject
startup before another successful probe completes, failing every registry-backed suite.
Agent Prompt
## Issue description
Registry stdout can initiate multiple concurrent readiness requests before the startup promise settles, allowing a failed probe to win over a successful one.

## Fix Focus Areas
- components/legacy/e2e-helper/npm-ci-registry.ts[86-129]

## Recommended Fix
Add a separate readiness-probe-started flag and set it synchronously before awaiting the fetch. Keep `settled` for final promise settlement so only one probe runs while error, close, and timeout handlers remain idempotent.

ⓘ 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 533748c

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.

2 participants