Skip to content

fix(npm): honor compatible automatic peer requirements - #37002

Draft
liuyinchu wants to merge 1 commit into
denoland:mainfrom
liuyinchu:fix-compatible-auto-peers
Draft

liuyinchu wants to merge 1 commit into
denoland:mainfrom
liuyinchu:fix-compatible-auto-peers

Conversation

@liuyinchu

Copy link
Copy Markdown

Problem

Automatic peer installation currently keeps only the first requirement for each package name. With two consumers requiring peer@* and peer@1, and registry versions 1.0.0 and 2.0.0, it can select 2.0.0 and report an avoidable mismatch. Renaming the consumers changes which requirement wins.

This standalone defect was found while investigating #36992. The minimal loopback-registry reproduction also fails with official Deno 2.9.7, for both static and dynamic imports. It does not establish the cause of the original static/dynamic discrepancy in that issue.

Change

  • Retain and deduplicate all required peer ranges before selecting an automatic fallback.
  • Check candidates against each requirement directly, preserving union and prerelease semantics rather than constructing a synthetic intersection.
  • Preserve linked-package precedence, dist-tags, the existing preference for latest, minimum dependency age, and trust-policy checks.
  • Reconsider a fallback when newly reachable packages change its constraints, within the existing ten-round bound.
  • Exclude abandoned fallback nodes from constraint collection and deduplication.

Explicit root and scoped dependency precedence is unchanged. Optional peers do not trigger automatic installation. For disjoint requirements with no common candidate, the existing first-requirement fallback and unmet-peer diagnostics remain. This is not a general SAT solver and does not rewrite snapshot provenance.

Tests and local validation

The diff contains only the resolver change and eight repository regression tests: compatible ranges in both consumer orders and with dedup on/off; newly discovered constraints; stale constraints after fallback replacement; and version-selection coverage for intersections, tags/latest, linked packages, minimum dependency age, and trust policy.

Validated against base a18ce33715e30cd2b0d99c7e322ef11a65490e4d, using the pinned Rust 1.95.0:

  • cargo +1.95.0 test -p deno_npm --all-features --locked: 256 passed.
  • cargo +1.95.0 test -p deno_npm --no-default-features --locked: 256 passed.
  • Scoped Clippy: cargo +1.95.0 clippy -p deno_npm --all-targets --all-features --locked --no-deps -- -D warnings --deny clippy::unused_async --deny clippy::print_stderr --deny clippy::print_stdout --deny clippy::large_futures --deny clippy::allow_attributes_without_reason: exit 0, with an unchanged Clippy configuration warning about unavailable chrono::Utc::now.
  • rustfmt +1.95.0 --check --config imports_granularity=item --config group_imports=StdExternalCrate libs/npm/resolution/common.rs libs/npm/resolution/graph.rs and git diff --check: passed.
  • A separate local finite-fixture harness passed 16 groups, including 48 compatible-range permutations, explicit/scoped versions, optional peers, incremental snapshots, replacement cascades, cycles, and bounded registry-cache queries. That harness and its logs are not part of this diff.
  • The original minimal regression fails on the unpatched resolver.

Draft / validation limits

A full patched Deno/V8 CLI build and runtime/spec integration suites have not been run. Full-workspace ./x lint and full-repository ./x fmt have not been run; the scoped checks above are not a full-repository pass. Clippy including dependencies is blocked by unchanged libs/maybe_sync/lib.rs:87, where #[allow(clippy::len_without_is_empty)] lacks a reason under the deny policy.

The commit includes [ci] to request the draft CI build checks described in the PR template.

AI assistance

The implementation, reproduction, tests, and this description were prepared with OpenAI AI assistance and checked locally.

Retain all required peer ranges for automatic fallback selection, recheck
newly reachable constraints, and exclude abandoned fallback requirements.
Preserve explicit-root precedence and the existing conflicting-range fallback.

Add eight resolver regression tests.

Prepared with AI assistance.
@CLAassistant

CLAassistant commented Oct 10, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@liuyinchu

Copy link
Copy Markdown
Author

Could a maintainer please approve the fork CI runs for this PR? The CLA check is passing, but the pr and ci workflows are still marked action_required. Thank you!

This branch has not been deployed

No deployments
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