You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Re-scoped 2026-07-26. The original report bundled five root causes. Three are fixed and one is now tracked separately, so this issue now covers only the peer-resolution divergence that remains. The original report is preserved verbatim below.
Root cause
Status
Scoped @scope/name@file: ids never dedupe back to link:
Measured against pnpm 11.17.0 on the same Astro checkout, the lockfile diff went from 306 lines (on main at the time of the report — not the 957 the original recorded on 12.0.0-alpha.21) to 157 lines, all of it now this one cause.
What remains
pacquet's peer resolution produces different peer-variant sets than pnpm on large workspaces. Two symptoms, one class:
1. Peers shadowed by a same-named dependency. When a package declares a name in both dependencies and peerDependencies, upstream drops it from dependencies — always under autoInstallPeers, and otherwise only when the name is already visible in the resolving parent's alias scope (options.parentPkgAliases in installing/deps-resolver/src/resolveDependencies.ts). pacquet models the first arm in omit_peer_shadowed_dependencies and documents the second as unmodeled. That is what drops the wrangler peer from @cloudflare/vite-plugin and the @atcute/lexicons peer from @atcute/identity, cascading into duplicate @cloudflare/vite-plugin variants and an extra @cloudflare/workers-types entry in @flue/cli's transitivePeerDependencies.
Upstream's effective behavior is "the first occurrence's parent scope decides", since both the resolved package and its children are memoized per package id. pacquet memoizes the same things but picks the owner deterministically rather than by arrival, so porting this means threading a parent-alias set through the walk without reintroducing order dependence — that is the design question.
2. Variants that should collapse but don't.@standard-community/[email protected] and @standard-community/[email protected] declare no dependencies at all, so this is not the shadowing bug. pacquet emits two extra variants whose children and resolved peers are strict subsets of the full variant, which upstream's dedupePeerDependents would collapse. pacquet's is_compatible_and_has_more_deps agrees they are collapsible; what blocks it is the collapsed_target_matches_parent guard in dedupe_peer_dependents.rs, which has no upstream counterpart and vetoes the child-edge rewrite that would orphan them.
That guard was added in #12372 to compensate for a peer-resolution divergence (#12330), so removing it in isolation would regress that. It is a symptom of the same underlying gap rather than an independent bug, which is why both symptoms belong in one issue.
Reproduction
Unchanged from the original report below, with pnpm 11.17.0 as the reference. The remaining 157-line diff is entirely @cloudflare/vite-plugin, @atcute/identity, @flue/cli and the two @standard-community packages.
Original report
Verify latest release
This reproduces with a release build of pacquet from pnpm main at 875073e596a2def295c7f68cb82e45c6bf0075bd (pnpm 12.0.0-alpha.21).
Temporarily remove trustPolicy: no-downgrade from pnpm-workspace.yaml. This is only to keep pnpm 11 from stopping on a newly published Netlify trust downgrade; make the same change for both runs.
Delete pnpm-lock.yaml.
Generate a lockfile with pnpm 11.13.1:
pnpm install --lockfile-only
Delete it and generate a lockfile with the release build of pacquet identified above:
pnpm install --lockfile-only
Compare the two lockfiles.
Describe the bug
The two resolvers produce materially different lockfiles from identical manifests. The diff is 957 lines (423 insertions and 534 deletions).
Examples:
pacquet adds an unrelated [email protected] peer context to many packages where pnpm 11 does not, including eslint, typescript-eslint, @flue/cli, @mdx-js/mdx, and several Vite plugins;
Note
Re-scoped 2026-07-26. The original report bundled five root causes. Three are fixed and one is now tracked separately, so this issue now covers only the peer-resolution divergence that remains. The original report is preserved verbatim below.
@scope/name@file:ids never dedupe back tolink:bundledDependenciesresolved as regular dependenciespeerDependenciesreaching its lockfile entry withoutautoInstallPeersfile:*.tgzdeps resolve without a manifestMeasured against pnpm 11.17.0 on the same Astro checkout, the lockfile diff went from 306 lines (on
mainat the time of the report — not the 957 the original recorded on12.0.0-alpha.21) to 157 lines, all of it now this one cause.What remains
pacquet's peer resolution produces different peer-variant sets than pnpm on large workspaces. Two symptoms, one class:
1. Peers shadowed by a same-named dependency. When a package declares a name in both
dependenciesandpeerDependencies, upstream drops it fromdependencies— always underautoInstallPeers, and otherwise only when the name is already visible in the resolving parent's alias scope (options.parentPkgAliasesininstalling/deps-resolver/src/resolveDependencies.ts). pacquet models the first arm inomit_peer_shadowed_dependenciesand documents the second as unmodeled. That is what drops thewranglerpeer from@cloudflare/vite-pluginand the@atcute/lexiconspeer from@atcute/identity, cascading into duplicate@cloudflare/vite-pluginvariants and an extra@cloudflare/workers-typesentry in@flue/cli'stransitivePeerDependencies.Upstream's effective behavior is "the first occurrence's parent scope decides", since both the resolved package and its children are memoized per package id. pacquet memoizes the same things but picks the owner deterministically rather than by arrival, so porting this means threading a parent-alias set through the walk without reintroducing order dependence — that is the design question.
2. Variants that should collapse but don't.
@standard-community/[email protected]and@standard-community/[email protected]declare no dependencies at all, so this is not the shadowing bug. pacquet emits two extra variants whose children and resolved peers are strict subsets of the full variant, which upstream'sdedupePeerDependentswould collapse. pacquet'sis_compatible_and_has_more_depsagrees they are collapsible; what blocks it is thecollapsed_target_matches_parentguard indedupe_peer_dependents.rs, which has no upstream counterpart and vetoes the child-edge rewrite that would orphan them.That guard was added in #12372 to compensate for a peer-resolution divergence (#12330), so removing it in isolation would regress that. It is a symptom of the same underlying gap rather than an independent bug, which is why both symptoms belong in one issue.
Reproduction
Unchanged from the original report below, with pnpm 11.17.0 as the reference. The remaining 157-line diff is entirely
@cloudflare/vite-plugin,@atcute/identity,@flue/cliand the two@standard-communitypackages.Original report
Verify latest release
This reproduces with a release build of pacquet from pnpm
mainat875073e596a2def295c7f68cb82e45c6bf0075bd(pnpm 12.0.0-alpha.21).pnpm version
12.0.0-alpha.21Which area(s) of pnpm are affected?
Dependencies resolver, Lockfile, Package manager compatibility
Link to the code that reproduces this issue
https://github.com/withastro/astro/tree/b01a6921cd8be574db2d82a6d2bbde7c7d319295
Reproduction steps
Check out the Astro commit above.
Temporarily remove
trustPolicy: no-downgradefrompnpm-workspace.yaml. This is only to keep pnpm 11 from stopping on a newly published Netlify trust downgrade; make the same change for both runs.Delete
pnpm-lock.yaml.Generate a lockfile with pnpm 11.13.1:
Delete it and generate a lockfile with the release build of pacquet identified above:
Compare the two lockfiles.
Describe the bug
The two resolvers produce materially different lockfiles from identical manifests. The diff is 957 lines (423 insertions and 534 deletions).
Examples:
pacquet adds an unrelated
[email protected]peer context to many packages where pnpm 11 does not, includingeslint,typescript-eslint,@flue/cli,@mdx-js/mdx, and several Vite plugins;pacquet resolves
[email protected]with@types/[email protected], while pnpm 11 resolves the workspace's@types/[email protected];pacquet resolves
@testing-library/[email protected]with[email protected], while pnpm 11 resolves[email protected];four nested workspace
file:dependencies are recorded as root-relativefile:snapshots by pacquet but as locallink:entries by pnpm 11. For example:The same difference occurs for Astro's local renderer and fixture packages.
Expected behavior
Pacquet and pnpm 11 should resolve the same manifests to equivalent peer contexts, peer versions, and local workspace dependency references.
Node.js version
25.9.0Operating system
macOS 26.5.2, arm64
Written by an agent (Codex, gpt-5).