[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: register comment.
Kind: bug (one pnpm layout question answered two ways, proven by execution against a real pnpm install). Source: new finding; register E92 (related to E40 and E48).
Problem
"Where does pnpm keep this project's install?" has two answers:
pnpm's node-linker=pnp writes a .pnp.cjs. When modulesDir is also set, the store is <modulesDir>/.pnpm, so the carve-out fails and the tree is classified YarnBerryPnP. Three consumers act on that classification:
- agent
apply refuses with yarn_pnp_unsupported and "Use yarn patch <pkg>" (apply.rs#L1332-L1341, and apply --check at #L604-L612);
- the vendored router skips its
vendor_pnpm_pnp_unsupported diagnosis and refuses with vendor_yarn_berry_unsupported and the yarn remedy instead (npm_flavor.rs#L181-L210);``
- VEX reads pnpm's
.pnp.cjs as a yarn loader (YarnPnpLoader::detect).``
Meanwhile the crawler finds every copy under deps/.pnpm, and agent mode could patch them.
Proof, run twice on e2d9633 with a real pnpm 10.28.0 install: package.json depends on left-pad@1.3.0, .npmrc = node-linker=pnp + modules-dir=deps, then pnpm install. The install wrote .pnp.cjs, deps/.modules.yaml, deps/.pnpm/ and deps/left-pad; node_modules/ holds only .pnpm-workspace-state-v1.json.
| Probe (throwaway tests) |
modules-dir=deps |
control: same project without modules-dir |
pnpm_modules_dirs (crawler roots) |
[<root>/deps, <root>/deps] |
n/a |
detect_npm_pkg_manager |
YarnBerryPnP |
Pnpm |
pnpm_pnp_layout |
false |
true |
YarnPnpLoader::detect(..).is_some() |
true |
false |
socket-patch apply --json --offline with a one-patch npm manifest |
exit 1, yarn_pnp_unsupported, "packages live inside .yarn/cache zips… Use yarn patch <pkg>" |
n/a |
Smaller detail: the crawler lists the deps root twice.
Symptoms
None filed. #698 fixed the crawler half (#661, #696), and #859 is the same pattern for yarn's pnpmStoreFolder. This is one more place where the package-manager layout is spelled outside the crawler (E40/#855, E48).
Impact: a pnpm project using its Plug'n'Play linker with a custom modulesDir can't use agent mode, gets the wrong refusal and remedy in vendored mode, and has VEX consult the wrong loader. This combination is uncommon. Plain pnpm with modulesDir only loses the pnpm notice, because detect falls through to Npm/Unknown.
Proposed change
- Move the modules-dir resolution (
pnpm_modules_dir_setting, resolve_modules_folder and the YAML unquote) out of npm_crawler.rs into one pnpm layout helper, for example crawlers/pnpm_layout.rs or formats::pnpm::workspace. Have it answer "the project's pnpm modules dirs" for both a disk root and a ProjectView.
detect_npm_pkg_manager step 4 and pnpm_pnp_layout_in look for .modules.yaml / .pnpm under those dirs instead of the literal node_modules.
- The crawler's
pnpm_modules_dirs calls the same helper and deduplicates its roots.
- Delete the hard-coded
node_modules/.modules.yaml / node_modules/.pnpm probes in pkg_managers.rs.
Size and scope
Acceptance criteria
Dependencies
Backlog review — 2026-10-08
Priority: unassigned → P2. Keep the reproduced pnpm PnP/custom-modulesDir layout defect. It blocks agent apply and gives the wrong package-manager diagnosis in a specific supported layout. The report does not demonstrate a successful false attestation; P2 fits the conditional compatibility failure.
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: register comment.
Kind: bug (one pnpm layout question answered two ways, proven by execution against a real pnpm install). Source: new finding; register E92 (related to E40 and E48).
Problem
"Where does pnpm keep this project's install?" has two answers:
modulesDir:modulesDir:inpnpm-workspace.yaml, ormodules-dirin.npmrcup to pnpm 10. Seepnpm_modules_dirs/pnpm_modules_dir_setting,`` added by Fix pnpm modulesDir store being skipped (#661, #696) #698 for Agent mode ignores pnpm'smodulesDir: on pnpm 10.12+ every installed package is "not installed", and apply exits 0 leaving it unpatched #661 and Hosted pnpm vex attests not_affected over an unpatched install when pnpm'smodulesDiris set (pnpm 10.12+), because the missed install is treated as "nothing installed" #696.crawlers/pkg_managers.rshard-codesnode_modules. This affects bothdetect_npm_pkg_managerstep 4 and the pnpm Plug'n'Play carve-outpnpm_pnp_layout_in:``pnpm's
node-linker=pnpwrites a.pnp.cjs. WhenmodulesDiris also set, the store is<modulesDir>/.pnpm, so the carve-out fails and the tree is classifiedYarnBerryPnP. Three consumers act on that classification:applyrefuses withyarn_pnp_unsupportedand "Useyarn patch <pkg>" (apply.rs#L1332-L1341, andapply --checkat#L604-L612);vendor_pnpm_pnp_unsupporteddiagnosis and refuses withvendor_yarn_berry_unsupportedand the yarn remedy instead (npm_flavor.rs#L181-L210);``.pnp.cjsas a yarn loader (YarnPnpLoader::detect).``Meanwhile the crawler finds every copy under
deps/.pnpm, and agent mode could patch them.Proof, run twice on
e2d9633with a real pnpm 10.28.0 install:package.jsondepends onleft-pad@1.3.0,.npmrc=node-linker=pnp+modules-dir=deps, thenpnpm install. The install wrote.pnp.cjs,deps/.modules.yaml,deps/.pnpm/anddeps/left-pad;node_modules/holds only.pnpm-workspace-state-v1.json.modules-dir=depsmodules-dirpnpm_modules_dirs(crawler roots)[<root>/deps, <root>/deps]detect_npm_pkg_managerYarnBerryPnPPnpmpnpm_pnp_layoutYarnPnpLoader::detect(..).is_some()socket-patch apply --json --offlinewith a one-patch npm manifestyarn_pnp_unsupported, "packages live inside .yarn/cache zips… Useyarn patch <pkg>"Smaller detail: the crawler lists the
depsroot twice.Symptoms
None filed. #698 fixed the crawler half (#661, #696), and #859 is the same pattern for yarn's
pnpmStoreFolder. This is one more place where the package-manager layout is spelled outside the crawler (E40/#855, E48).Impact: a pnpm project using its Plug'n'Play linker with a custom
modulesDircan't use agent mode, gets the wrong refusal and remedy in vendored mode, and has VEX consult the wrong loader. This combination is uncommon. Plain pnpm withmodulesDironly loses the pnpm notice, becausedetectfalls through toNpm/Unknown.Proposed change
pnpm_modules_dir_setting,resolve_modules_folderand the YAML unquote) out ofnpm_crawler.rsinto one pnpm layout helper, for examplecrawlers/pnpm_layout.rsorformats::pnpm::workspace. Have it answer "the project's pnpm modules dirs" for both a disk root and aProjectView.detect_npm_pkg_managerstep 4 andpnpm_pnp_layout_inlook for.modules.yaml/.pnpmunder those dirs instead of the literalnode_modules.pnpm_modules_dirscalls the same helper and deduplicates its roots.node_modules/.modules.yaml/node_modules/.pnpmprobes inpkg_managers.rs.Size and scope
crawlers/pkg_managers.rs,crawlers/npm_crawler.rs, possiblyvendor/lock_inventory/view.rs(a memory-view read ofpnpm-workspace.yaml/.npmrc).virtualStoreDirset separately frommodulesDir, and yarn'spnpmStoreFolder(Agent mode misses transitive packages in Yarn's pnpm-linker store whenpnpmStoreFoldermoves it out ofnode_modules: skipped aspackage_not_installed, or refused as "first-party source" #859).Acceptance criteria
pkg_managers.node-linker=pnp+modulesDir: depslayout (.pnp.cjs,pnpm-lock.yaml,deps/.modules.yaml,deps/.pnpm/) is detected asPnpm,YarnPnpLoader::detectreturnsNone, and the vendored router returnsvendor_pnpm_pnp_unsupported. Cover both the.npmrcand thepnpm-workspace.yamlspelling.apply --jsonin that layout is not refused withyarn_pnp_unsupported.e2e_safety_yarn_pnp, the Yarn 4 node-modules / pnpm-linker projects migrated from Yarn 2 PnP keep a stale.pnp.js, and socket-patch refuses them as Plug'n'Play: agent and vendored exit 1, hosted warns "npm dependencies were NOT scanned" (regression since 3.3.0) #975 stale-loader tests andtest_pnpm_modules_dir_is_a_crawl_rootstay green.Dependencies
pnpmStoreFoldermoves it out ofnode_modules: skipped aspackage_not_installed, or refused as "first-party source" #859.Backlog review — 2026-10-08
Priority: unassigned → P2. Keep the reproduced pnpm PnP/custom-modulesDir layout defect. It blocks agent apply and gives the wrong package-manager diagnosis in a specific supported layout. The report does not demonstrate a successful false attestation; P2 fits the conditional compatibility failure.