Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix(arborist): don't load store packages' devDependencies as required edges by manzoorwanijk · Pull Request #9626 · npm/cli · GitHub
Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(arborist): don't load store packages' devDependencies as required edges by manzoorwanijk · Pull Request #9626 · npm/cli · GitHub
Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(arborist): don't load store packages' devDependencies as required edges by manzoorwanijk · Pull Request #9626 · npm/cli · GitHub
Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix(arborist): don't load store packages' devDependencies as required edges by manzoorwanijk · Pull Request #9626 · npm/cli · GitHub
Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(arborist): don't load store packages' devDependencies as required edges by manzoorwanijk · Pull Request #9626 · npm/cli · GitHub
Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix(arborist): don't load store packages' devDependencies as required edges by manzoorwanijk · Pull Request #9626 · npm/cli · GitHub
Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix(arborist): don't load store packages' devDependencies as required edges by manzoorwanijk · Pull Request #9626 · npm/cli · GitHub
Skip to content

fix(arborist): don't load store packages' devDependencies as required edges - #9626

Merged
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps
Jun 24, 2026
Merged

fix(arborist): don't load store packages' devDependencies as required edges#9626
owlstronaut merged 1 commit into
npm:latestfrom
manzoorwanijk:fix/linked-sbom-store-devdeps

Conversation

@manzoorwanijk

@manzoorwanijkmanzoorwanijk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Under install-strategy=linked, npm sbom exited non-zero with ESBOMPROBLEMS, reporting the devDependencies of transitive packages (e.g. matcha, tape) as missing: ... required by .... Those dev dependencies are correctly not installed (the same is true under hoisted), yet only the linked strategy treated them as missing-and-required. Hoisted produced a clean SBOM for the same dependency set.

Why

A package in the linked strategy's store lives at node_modules/.store/<key>/node_modules/<pkg>, which makes it a structural tree top (isTop, no parent). Node._loadDeps loads devDependencies for every top node, so each store package — a transitive dependency whose devDependencies are never installed — gained required dev edges. npm sbom reads the filesystem tree via loadActual, queries it, and flags every non-optional missing edge, so those spurious dev edges surfaced as ESBOMPROBLEMS. Standalone npm audit was unaffected because it audits the virtual tree from the lockfile. Hoisted was unaffected because its transitive packages have a real parent, so they are not tops and never load devDependencies.

How

load-actual.js now flags a node as isInStore when its realpath sits inside a node_modules/.store/ directory, matching the flag the isolated reifier already sets on ideal-tree store nodes. Node._loadDeps excludes store nodes from the devDependency load (isTop && !globalTop && path && !this.isInStore), so a store package — a transitive dependency by definition — never gains required dev edges. This makes the linked actual tree's edge semantics match hoisted.

References

Fixes#9610
Part of #9608

@manzoorwanijk
manzoorwanijk marked this pull request as ready for review June 24, 2026 08:44
@manzoorwanijk
manzoorwanijk requested review from a team as code ownersJune 24, 2026 08:44
@owlstronaut
owlstronaut merged commit 851558c into npm:latestJun 24, 2026
24 checks passed
@manzoorwanijk
manzoorwanijk deleted the fix/linked-sbom-store-devdeps branch June 24, 2026 14:40
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Backport to release/v11 failed.

This usually means the cherry-pick had conflicts. Please create a manual backport:

git fetch origin release/v11
git checkout -b backport/v11/9626 origin/release/v11
git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
# resolve any conflicts, then:
git push origin backport/v11/9626
Error details
Command failed: git cherry-pick -x 851558c02a9c79412aa454113973cab047a47f20
error: could not apply 851558c02... fix(arborist): don't load store packages' devDependencies as required edges (#9626)
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

@github-actionsgithub-actionsBot mentioned this pull request Jun 24, 2026
@owlstronaut

Copy link
Copy Markdown

@manzoorwanijk would you be able to create the manual backport of this?

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

@manzoorwanijk would you be able to create the manual backport of this?

Sure, I will try.

@manzoorwanijk

Copy link
Copy Markdown
ContributorAuthor

PR for backport to v11: #9633

owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
… edges (#9633)
Backport of #9626 to `release/v11`.
Under `install-strategy=linked`, `npm sbom` exited with `ESBOMPROBLEMS`,
reporting transitive packages' devDependencies as missing/required. A
store package lives at `node_modules/.store/<key>/node_modules/<pkg>`,
which makes it a structural tree top, so `Node._loadDeps` loaded its
devDependencies as required edges. `loadActual` now flags such nodes
`isInStore` and `_loadDeps` skips devDependencies for them, matching the
hoisted strategy.
Cherry-picked cleanly except for a test-file context conflict: the
unrelated `applies root packageExtensions to a linked actual tree` test
(not part of this PR and not present on `release/v11`) was dropped from
the resolution; only this fix's two regression tests are included.
## References
Backports #9626
owlstronaut pushed a commit that referenced this pull request Jun 24, 2026
Restores the global 100% coverage gate on `latest`, which broke after
#9626.
`filterLinkedStrategyEdges` in `lib/commands/ls.js` skips dev edges on
non-root packages — a guard added in #9095 to suppress false `UNMET
DEPENDENCY` output in the linked strategy. #9626 fixed the root cause
for store packages (they no longer load `devDependencies` as required
edges), so the store-based test no longer produces a dev edge, leaving
that branch unexercised.
Rather than ignore the line, this adds a regression test that genuinely
exercises the guard: arborist still loads dev edges for a `file:`-linked
transitive package, so listing one with `--all` under the linked
strategy reaches the guard at depth > 0 and confirms its devDependency
is suppressed instead of reported as `UNMET DEPENDENCY`. The full test
suite passes at 100%.
This is the `latest` counterpart of #9636, which restored coverage on
`release/v11` via an `istanbul ignore`.
## References
Follows up #9626
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] install-strategy=linked: npm sbom fails with ESBOMPROBLEMS (transitive devDependencies reported missing)

2 participants

@manzoorwanijk@owlstronaut