Skip to content

fix(arborist): surface undeclared workspaces under the linked strategy (backport release/v11)#9669

Merged
owlstronaut merged 1 commit into
npm:release/v11from
manzoorwanijk:backport/9618-linked-undeclared-workspaces-v11
Jun 26, 2026
Merged

fix(arborist): surface undeclared workspaces under the linked strategy (backport release/v11)#9669
owlstronaut merged 1 commit into
npm:release/v11from
manzoorwanijk:backport/9618-linked-undeclared-workspaces-v11

Conversation

@manzoorwanijk

Copy link
Copy Markdown
Contributor

Backport of #9657 to release/v11.

Under install-strategy=linked, a workspace the root does not depend on is installed on disk but was invisible to npm ls --all, npm ls --workspaces, and npm query ':root > *', all of which reported an empty tree. The hoisted strategy lists every workspace.

loadActual now synthesizes the missing root-to-workspace links for undeclared workspaces in both the filesystem-scan and hidden-lockfile paths (via a shared #linkActualWorkspaces() helper), so the root's workspace edges resolve. A declared workspace whose root link is genuinely missing is left unsynthesized so it still reports UNMET, and a name already present as a root child is never replaced. With the edges resolving, the workspace-skip branch npm ls used to suppress them is removed.

Backport notes: the .npm-extension calls from the original commit are omitted (that feature is not on release/v11), and the filterLinkedStrategyEdges dev-edge guard keeps the v11 istanbul ignore since v11 has no test exercising it.

References

Fixes #9618
Backport of #9657

npm#9657)

In continuation of our exploration of using `install-strategy=linked` in
the [Gutenberg
monorepo](WordPress/gutenberg#75814), which
powers the WordPress Block Editor.

Under `install-strategy=linked`, a declared workspace that the root does
not depend on is installed on disk but was invisible to `npm ls --all`,
`npm ls --workspaces`, and `npm query ':root > *'`, all of which
reported an empty tree. The hoisted strategy lists every workspace.

Undeclared workspaces are intentionally not symlinked into the root
`node_modules` under the linked strategy, so when `loadActual` rebuilds
the actual tree (from the filesystem scan or the hidden lockfile,
neither of which records a `node_modules/<ws>` entry) the root's
`workspace` edges resolve to nothing and the workspaces drop out of the
tree that `ls` and `query` traverse. `npm ls` then hid those missing
edges entirely to avoid a false `UNMET DEPENDENCY`.

The fix adds `loadActual` post-processing that, for the linked strategy,
synthesizes an in-memory `Link` at `node_modules/<ws>` for each
undeclared workspace so its root edge resolves, matching the logical
layout the regular `package-lock.json` already records. This is
introspection-only and writes nothing to disk. A declared workspace
whose root link is genuinely missing is left alone so it still reports
`UNMET`, an existing root child of the same name is never replaced, and
a workspace that was not loaded is skipped. With the edges now
resolving, the workspace-skip branch that `npm ls` used to suppress them
is removed.

Fixes npm#9618
@owlstronaut owlstronaut merged commit cd57139 into npm:release/v11 Jun 26, 2026
33 checks passed
@manzoorwanijk manzoorwanijk deleted the backport/9618-linked-undeclared-workspaces-v11 branch June 26, 2026 13:17
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