Skip to content

feat(install): warn when an override matches no dependency#12741

Open
aqeelat wants to merge 9 commits into
pnpm:mainfrom
aqeelat:feat/warn-unused-overrides
Open

feat(install): warn when an override matches no dependency#12741
aqeelat wants to merge 9 commits into
pnpm:mainfrom
aqeelat:feat/warn-unused-overrides

Conversation

@aqeelat

@aqeelat aqeelat commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Warn during pnpm install when an entry in overrides matches no dependency in the resolved tree. The warning is buffered until the resolution_done stage and rendered as a single grouped line by the default reporter:

[WARN] 2 overrides matched no dependency: foo, parent>child

Implemented in both the TypeScript CLI and the Rust pacquet/ port.

Closes #10315.

How it works

  • Tracking: createVersionsOverrider accepts an optional onApplied callback that fires whenever an override selector matches a manifest's dependency. The installer collects applied selectors into a Set<string>.
  • Diffing: After resolution, the installer diffs the parsed override selectors against the applied set. Unmatched selectors emit a pnpm:unused-override log event.
  • Gating: The diff only runs when the full lockfile was reanalyzed (forceFullResolution || empty packages && all importers present), matching the same gate verifyPatches uses. This avoids false positives on frozen/partial installs where the applied set would be incomplete.
  • Reporting: A new reportUnusedOverrides reporter buffers events until pnpm:stage { stage: 'resolution_done' }, then renders one sorted, grouped WARN line (singular/plural aware).
  • pnpr server: The pnpr path is always used when configured (no fallback). The unused-override warning is computed by scanning the resolved lockfile after pnpr returns, since the pnpr protocol resolves with overrides but does not report which selectors matched.
  • Direct add: parseWantedDependencies calls onOverrideApplied when an override applies to a directly-added dependency, so pnpm add foo with an overrides: { foo: ... } entry is not falsely warned about.

Public API additions

  • @pnpm/core-loggers — new pnpm:unused-override channel (unusedOverrideLogger, UnusedOverrideLog, UnusedOverrideMessage).
  • @pnpm/hooks.read-package-hookcreateVersionsOverrider accepts onApplied; createReadPackageHook threads it as onOverrideApplied. VersionOverrideWithoutRawSelector kept as deprecated alias for backward compatibility.
  • @pnpm/installing.deps-installerProcessedInstallOptions exposes appliedOverrides: Set<string>.
  • @pnpm/cli.default-reporter — new reportUnusedOverrides wired into the client reporter pipeline.

Pacquet parity

  • VersionsOverrider records applied selectors via Arc<Mutex<HashSet<String>>>.
  • install_with_fresh_lockfile diffs parsed overrides against applied selectors after resolution, emits LogEvent::UnusedOverride per unmatched selector, then Stage::ResolutionDone.
  • Default reporter buffers unused overrides until ResolutionDone.

Squash Commit Body

Emit a pnpm:unused-override log for each override selector that matched no
resolved package during a fresh install. The default reporter buffers these
until the resolution_done stage and renders a single grouped WARN line.

The diff is gated to runs where the full lockfile was reanalyzed, matching
verifyPatches' gate, to avoid false positives on frozen/partial installs.

Tracking hooks into both the read-package hook (transitive deps) and
parseWantedDependencies (direct adds). When a pnpr server is configured,
the resolved lockfile is scanned to determine which override selectors
matched, since the pnpr protocol does not report applied selectors.

Mirrored in pacquet: VersionsOverrider records applied selectors, the
fresh-lockfile install path diffs and emits UnusedOverride events before
ResolutionDone, and the default reporter buffers and renders them.

Closes pnpm/pnpm#10315.

Checklist

  • The change is implemented in both the TypeScript CLI and the Rust
    pacquet/ port, or the description notes what still needs porting.
  • Added a changeset (pnpm changeset) if this PR changes any published
    package. Keep it short and written for pnpm users — it becomes a release note.
  • Added or updated tests.
  • Updated the documentation if needed.

Written by an agent (opencode, glm-5.2).

Summary by CodeRabbit

  • New Features
    • Added a new install-time [WARN] when an overrides selector matches no dependency.
    • The warning is buffered and emitted once after resolution, as a single grouped line with sorted selectors and correct singular/plural wording.
    • Selector text is sanitized to prevent control/escape characters from affecting output.
  • Bug Fixes
    • Improved unused-override detection consistency between standard installs and pnpr-server resolution.
  • Tests
    • Added coverage for warning buffering/flush timing, formatting, sanitization, and lockfile-based unused-override scanning.

@aqeelat aqeelat requested a review from zkochan as a code owner June 30, 2026 09:30
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Warn on unused pnpm overrides during install (TS + pacquet parity)

✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Track which override selectors are actually applied during dependency resolution.
• Emit pnpm:unusedOverride for selectors that matched nothing (gated to full resolution).
• Buffer and print one grouped WARN line at resolution_done in TS and pacquet.
Diagram

graph TD
I["Installer (pnpm install)"] -->|"no overrides"| S{{"pnpr server"}}
I --> H["Versions overrider hook"] --> A[("Applied selectors set")] --> D["Post-resolution diff"] --> E(("pnpm:unusedOverride")) --> R["Default reporter buffer"] --> W["Grouped WARN line"]
subgraph Legend
direction LR
_mod["Module"] ~~~ _db[("State/Set")] ~~~ _evt(("Log event")) ~~~ _ext{{"External"}}
end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Resolver-level reporting of matched overrides
  • ➕ More accurate than hook-based tracking (fewer incidental “applied” signals).
  • ➕ Would avoid gating logic tied to full lockfile reanalysis.
  • ➖ Requires deeper resolver protocol/API changes (including pnpr server), larger scope.
  • ➖ Harder to keep TS and pacquet implementations aligned.
2. Warn immediately per unused override (no buffering)
  • ➕ Simpler reporter logic; warnings appear as soon as known.
  • ➖ Noisier output and worse UX for many overrides.
  • ➖ Harder to avoid interleaving with progress output.
3. Lockfile-only detection (compare overrides vs lockfile contents)
  • ➕ Avoids hook plumbing and applied-selector tracking.
  • ➖ Unreliable: overrides may affect resolution without obvious lockfile fingerprints.
  • ➖ Does not naturally handle parent-scoped selectors or direct-add flows.

Recommendation: Keep the PR’s approach: track selector application during manifest processing, then diff post-resolution and buffer output until resolution_done. It minimizes user-facing noise, keeps correctness via the full-resolution gate, and is implementable with close TS/pacquet parity. The main alternative (resolver-level reporting) is attractive long-term, but substantially larger in scope and would require pnpr protocol work.

Files changed (24) +787 / -24

Enhancement (14) +254 / -19
state.rsBuffer unused override selectors and flush as grouped warning +36/-0

Buffer unused override selectors and flush as grouped warning

• Adds reporter state to collect 'pnpm:unusedOverride' selectors. Flushes them on 'Stage::ResolutionDone' into a single sorted warning line with correct singular/plural handling.

pacquet/crates/default-reporter/src/state.rs

install_with_fresh_lockfile.rsEmit UnusedOverride events after resolution and before ResolutionDone +35/-1

Emit UnusedOverride events after resolution and before ResolutionDone

• Computes the set difference between parsed override selectors and the overrider’s applied selectors. Emits one 'LogEvent::UnusedOverride' per unmatched selector, then emits 'Stage::ResolutionDone' to trigger reporter flush.

pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs

overrides.rsTrack which override selectors matched in VersionsOverrider +33/-2

Track which override selectors matched in VersionsOverrider

• Extends 'VersionsOverrider' with a mutex-protected 'HashSet' recording applied selectors. Records hits when overrides are chosen and exposes 'applied_selectors()' for post-resolution verification.

pacquet/crates/package-manager/src/overrides.rs

lib.rsAdd 'pnpm:unusedOverride' log event and payload type +21/-0

Add 'pnpm:unusedOverride' log event and payload type

• Introduces 'LogEvent::UnusedOverride' and 'UnusedOverrideLog' with 'prefix' and raw 'selector'. Documents intended buffering behavior in the default reporter.

pacquet/crates/reporter/src/lib.rs

index.tsPlumb 'pnpm:unusedOverride' into default reporter streams +5/-0

Plumb 'pnpm:unusedOverride' into default reporter streams

• Adds an RxJS subject for 'pnpm:unusedOverride' and routes parsed logs into it. Exposes the observable to downstream reporter composition.

pnpm11/cli/default-reporter/src/index.ts

index.tsWire unused override reporter into client reporter pipeline +6/-0

Wire unused override reporter into client reporter pipeline

• Adds 'reportUnusedOverrides' to the composed output pipeline and passes both the unusedOverride and stage streams needed for buffering until 'resolution_done'.

pnpm11/cli/default-reporter/src/reporterForClient/index.ts

reportUnusedOverrides.tsImplement grouped warning rendering for unused overrides +31/-0

Implement grouped warning rendering for unused overrides

• Buffers 'UnusedOverrideLog' events until the 'resolution_done' stage, then emits one WARN line listing sorted selectors. Handles pluralization and emits nothing when the buffer is empty.

pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts

all.tsExport unusedOverrideLogger from core-loggers barrel +1/-0

Export unusedOverrideLogger from core-loggers barrel

• Adds the new unused override logger module to the package’s public export surface.

pnpm11/core/core-loggers/src/all.ts

index.tsInclude UnusedOverrideLog in the union of known log types +2/-0

Include UnusedOverrideLog in the union of known log types

• Extends the 'Log' discriminated union to include 'UnusedOverrideLog' so consumers can handle the new 'pnpm:unusedOverride' channel.

pnpm11/core/core-loggers/src/index.ts

unusedOverrideLogger.tsIntroduce 'unusedOverrideLogger' and log payload types +14/-0

Introduce 'unusedOverrideLogger' and log payload types

• Adds a dedicated logger for 'pnpm:unusedOverride' events with a minimal payload of 'prefix' and raw override 'selector'.

pnpm11/core/core-loggers/src/unusedOverrideLogger.ts

createReadPackageHook.tsThread 'onOverrideApplied' callback into versions overrider hook +5/-2

Thread 'onOverrideApplied' callback into versions overrider hook

• Updates 'createReadPackageHook' to accept an optional 'onOverrideApplied' callback and passes it to 'createVersionsOverrider'. Broadens override input typing to preserve raw selectors when available.

pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts

createVersionsOverrider.tsAdd 'onApplied' callback and preserve raw selector typing +29/-11

Add 'onApplied' callback and preserve raw selector typing

• Extends 'createVersionsOverrider' with an optional 'onApplied' callback invoked when an override with a raw 'selector' matches a dependency entry. Keeps the older selector-stripped type as a deprecated alias for backward compatibility.

pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts

extendInstallOptions.tsExpose 'appliedOverrides' Set and record matches via read-package hook +4/-0

Expose 'appliedOverrides' Set and record matches via read-package hook

• Adds 'appliedOverrides: Set<string>' to 'ProcessedInstallOptions'. Initializes the set and wires 'createReadPackageHook' to record 'override.selector' when applied.

pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts

index.tsEmit unused override logs post-resolution; skip pnpr server when overrides exist +32/-3

Emit unused override logs post-resolution; skip pnpr server when overrides exist

• Falls back to local resolution when a pnpr server is configured but overrides are present, because the pnpr protocol cannot report matched selectors. After resolution (and only under a full-reanalysis gate), emits 'pnpm:unusedOverride' for selectors not in 'appliedOverrides', before the 'resolution_done' stage.

pnpm11/installing/deps-installer/src/install/index.ts

Bug fix (1) +2 / -0
parseWantedDependencies.tsMark override as applied for direct adds when override rewrites spec +2/-0

Mark override as applied for direct adds when override rewrites spec

• Adds an optional 'onOverrideApplied' callback and calls it when a directly-added dependency alias is overridden. Prevents false unused-override warnings for 'pnpm add' flows.

pnpm11/installing/deps-installer/src/parseWantedDependencies.ts

Tests (8) +513 / -5
render.rsTest pacquet reporter buffering/formatting for unused overrides +68/-1

Test pacquet reporter buffering/formatting for unused overrides

• Adds tests asserting unused overrides are buffered until 'ResolutionDone', sorted, grouped into one WARN line, singularized for one item, and omitted when empty.

pacquet/crates/default-reporter/tests/render.rs

tests.rsTest applied selector tracking in VersionsOverrider +66/-0

Test applied selector tracking in VersionsOverrider

• Adds coverage ensuring applied selectors include matched overrides (including deletions), remain empty when no matches occur, and dedupe across multiple apply calls.

pacquet/crates/package-manager/src/overrides/tests.rs

tests.rsVerify 'pnpm:unusedOverride' wire shape matches pnpm +24/-1

Verify 'pnpm:unusedOverride' wire shape matches pnpm

• Adds a serialization test confirming 'pnpm:unusedOverride' JSON envelope includes 'level', 'prefix', and 'selector' at the top level with the correct event name.

pacquet/crates/reporter/src/tests.rs

reportingUnusedOverrides.tsAdd unit tests for TS default reporter unused-override output +102/-0

Add unit tests for TS default reporter unused-override output

• Verifies the reporter prints a single grouped line at 'resolution_done', uses singular form for a single selector, and emits nothing when no unused-override events exist.

pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts

createVersionOverrider.test.tsTest 'onApplied' callback behavior and call frequency contract +63/-0

Test 'onApplied' callback behavior and call frequency contract

• Adds tests ensuring 'onApplied' is called for each matched override and documents that the callback fires per (manifest × dependency-group) pass, with downstream deduping handled by a Set.

pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts

overrides.tsAdd integration tests for emitting/avoiding 'pnpm:unusedOverride' +50/-2

Add integration tests for emitting/avoiding 'pnpm:unusedOverride'

• Introduces tests asserting unused override logs are emitted for unmatched selectors and omitted when overrides match (including ensuring direct-add override usage is not falsely flagged).

pnpm11/installing/deps-installer/test/install/overrides.ts

pnpmRegistry.tsTest pnpr server is bypassed when overrides are configured +31/-1

Test pnpr server is bypassed when overrides are configured

• Adds a registry harness test verifying pnpm does not hit the pnpr server when overrides exist, and that a grouped unused-override warning is printed for unmatched selectors only.

pnpm11/pnpm/test/install/pnpmRegistry.ts

unusedOverrides.tsAdd end-to-end tests for unused override warning output +109/-0

Add end-to-end tests for unused override warning output

• Adds CLI-level tests verifying warnings appear only for unused overrides, remain absent when all overrides match, and work with per-project overrides when 'sharedWorkspaceLockfile' is disabled.

pnpm11/pnpm/test/install/unusedOverrides.ts

Documentation (1) +18 / -0
warn-unused-overrides.mdAdd release note and version bumps for unused override warnings +18/-0

Add release note and version bumps for unused override warnings

• Introduces a changeset announcing install-time warnings for overrides that match no dependency. Documents the new logger channel, hook callback, installer state exposure, and reporter behavior (including pacquet parity).

.changeset/warn-unused-overrides.md

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds install-time detection for override selectors that match no dependency, emits a dedicated unused-override log at resolution completion, and renders it as a grouped warning in the default reporters. The change also threads applied-selector tracking through override application and adds coverage for install, reporter, and lockfile-scanning paths.

Changes

Unused overrides warning

Layer / File(s) Summary
Log contracts and stream plumbing
pacquet/crates/reporter/src/lib.rs, pnpm11/core/core-loggers/src/*, pnpm11/cli/default-reporter/src/*
Defines the unused-override log shape and exposes it through the logger exports and default-reporter log stream.
Applied override tracking
pnpm11/hooks/read-package-hook/src/*, pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts, pnpm11/installing/deps-installer/src/parseWantedDependencies.ts, pnpm11/installing/deps-installer/test/install/overrides.ts, pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
Threads an override-applied callback through hook wiring, records applied selectors, and validates the callback behavior.
Unused override detection in install
pnpm11/installing/deps-installer/src/install/*, pnpm11/installing/deps-installer/test/install/*, .changeset/warn-unused-overrides.md
Compares parsed overrides with applied selectors, emits unused-override debug logs in install flows, and adds scan and integration coverage for workspace and pnpr-server cases.
Buffered warning rendering
pnpm11/cli/default-reporter/src/reporterForClient/*, pacquet/crates/default-reporter/src/state.rs, pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts, pacquet/crates/default-reporter/tests/render.rs, pacquet/crates/package-manager/src/*, pacquet/crates/package-manager/src/overrides/tests.rs
Buffers unused-override events until resolution_done, sanitizes selectors, and renders a grouped warning with matching Rust-side selector tracking tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
Warn during pnpm i when an override selector matches no dependency [#10315]

Out-of-scope changes

No out-of-scope code changes identified.

Possibly related PRs

  • pnpm/pnpm#12283: Overlaps in pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs around lockfile reuse and resolution-path behavior.
  • pnpm/pnpm#12345: Also changes pacquet/crates/package-manager/src/overrides.rs override application behavior.

Suggested labels: product: pacquet, product: pnpm@11

Suggested reviewers: zkochan

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: warning when an override matches nothing.
Description check ✅ Passed The PR description follows the template with Summary, Squash Commit Body, and a completed checklist.
Linked Issues check ✅ Passed The implementation matches issue #10315 by warning on unmatched overrides and includes the requested install-time behavior.
Out of Scope Changes check ✅ Passed The changes shown are all tied to unused-override detection, reporter plumbing, or parity tests, with no clear unrelated additions.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jun 30, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (17) 📘 Rule violations (0) 📎 Requirement gaps (2) 📜 Skill insights (0)

Context used

Grey Divider


Action required

1. Unused overrides buffer ignores prefix 📎 Requirement gap ≡ Correctness ⭐ New
Description
reportUnusedOverrides() buffers all pnpm:unused-override events globally and flushes them on the
first resolution_done stage event without partitioning by log.prefix. In recursive/multi-prefix
runs this can mix selectors across workspaces/lockfileDirs or flush too early, leading to missing,
incorrect, or ambiguous warnings that fail to clearly identify which override selectors matched
nothing.
Code

pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[R25-41]

+  const resolutionDone$ = log$.stage.pipe(
+    filter((log) => log.stage === 'resolution_done')
+  )
+  return log$.unusedOverride.pipe(
+    buffer(resolutionDone$),
+    map((unusedOverrides) => {
+      if (unusedOverrides.length === 0) return Rx.EMPTY
+      const selectors = unusedOverrides
+        .map((log) => sanitizeSelector(log.selector))
+        .sort()
+      const head = selectors.length === 1
+        ? '1 override matched no dependency'
+        : `${selectors.length} overrides matched no dependency`
+      return Rx.of({
+        msg: formatWarn(`${head}: ${selectors.join(', ')}`),
+      })
+    })
Evidence
PR Compliance ID 1 requires pnpm install to emit a clear warning identifying which override
selector(s) matched nothing, but the reporter implementation buffers unusedOverride logs and emits
them on resolution_done without ever scoping by or reading log.prefix. This is problematic
because both pnpm:unused-override and pnpm:stage events include prefix: ctx.lockfileDir, so in
multi-prefix installs a resolution_done from one prefix can flush buffered selectors from another,
and selectors from different lockfileDirs can be merged into a single warning; other reporters use
log.prefix to disambiguate output, underscoring that prefix is intended to separate and
contextualize per-project reporting.

Warn when a pnpm override selector matches no packages
pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[25-41]
pnpm11/cli/default-reporter/src/reporterForClient/index.ts[111-119]
pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[19-43]
pnpm11/core/core-loggers/src/unusedOverrideLogger.ts[7-14]
pnpm11/installing/deps-installer/src/install/index.ts[1662-1685]
pnpm11/cli/default-reporter/src/reporterForClient/reportDeprecations.ts[19-34]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`reportUnusedOverrides()` currently ignores `UnusedOverrideLog.prefix`/`StageLog.prefix`, buffering all `pnpm:unused-override` events together and flushing them on any `resolution_done` stage event. In multi-prefix (recursive) installs this can merge selectors from different workspaces/lockfileDirs or flush before all selectors for a given prefix have arrived, producing missing, incorrect, or context-free warnings.

## Issue Context
- PR Compliance ID 1 requires `pnpm install` to emit a clear warning identifying which override selector(s) matched nothing.
- Each `pnpm:unused-override` (`UnusedOverrideLog`) and `pnpm:stage` (`StageLog`) event includes a `prefix` (workspace root / lockfileDir, typically `ctx.lockfileDir`).
- The warning needs to be accurate per-prefix; other reporters use `log.prefix` to disambiguate output (e.g., via zoom-out/prefix formatting).

## Fix Focus Areas
- pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[19-43]
- pnpm11/cli/default-reporter/src/reporterForClient/index.ts[111-119]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Pacquet gate skips updates 🐞 Bug ≡ Correctness ⭐ New
Description
pacquet emits unused-override events only when lockfile_for_reuse.is_none(), but
UpdateReuseScope::None disables reuse (full re-resolve) while lockfile_for_reuse can still be
Some. This suppresses unused-override warnings in full re-resolution flows like pacquet update,
undermining the feature.
Code

pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[R1216-1225]

+        if lockfile_for_reuse.is_none()
+            && let Some(overrider) = versions_overrider.as_ref()
+            && let Some(parsed) = parsed_overrides.as_ref()
+        {
+            let applied = overrider.applied_selectors();
+            let mut unused: Vec<&str> = parsed
+                .iter()
+                .map(|override_entry| override_entry.selector.as_str())
+                .filter(|selector| !applied.contains(*selector))
+                .collect();
Evidence
The emission site gates on lockfile_for_reuse.is_none(). However, update_reuse_scope can be set
to None (e.g. update flows / force resolve), and the resolver will not reuse any subtree when that
scope is None, meaning applied selectors would be complete but the warning is still skipped.

pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1202-1234]
pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1048-1109]
pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs[48-63]
pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs[2089-2097]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The unused-override diff is gated by `lockfile_for_reuse.is_none()`, but pacquet can still perform a full re-resolve (no subtree reuse) when `update_reuse_scope` is `UpdateReuseScope::None` even if a prior lockfile exists. In that case `applied_selectors()` should be complete and the warning should run, but currently it is skipped.

### Issue Context
`UpdateReuseScope::None` explicitly means “reuse nothing — the whole graph re-resolves”, and the resolver’s reuse path short-circuits when this scope is set.

### Fix Focus Areas
- pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1048-1110]
- pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1202-1234]
- pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs[48-63]
- pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs[2089-2097]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Workspace peer overrides missed 🐞 Bug ≡ Correctness
Description
findAppliedOverrideSelectorsFromLockfile() checks only importer dependencies/dev/optional when
matching workspace-project parents, so overrides that apply only to a workspace project’s
peerDependencies can be incorrectly reported as unused in pnpr-server mode.
Code

pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[R44-60]

+      for (const { importerId, manifest: projectManifest } of projectManifests) {
+        if (projectManifest.name !== parentName) continue
+        if (parentRange != null) {
+          const projectVersion = projectManifest.version
+          if (projectVersion == null) continue
+          if (!parentRangeValid || !semver.satisfies(projectVersion, parentRange)) continue
+        }
+        const importer = lockfile.importers[importerId as ProjectId]
+        if (importer == null) continue
+        if (
+          depEntryMatches(importer.dependencies, targetName) ||
+          depEntryMatches(importer.devDependencies, targetName) ||
+          depEntryMatches(importer.optionalDependencies, targetName)
+        ) {
+          applied.add(override.selector)
+          break
+        }
Evidence
Overrides are applied to peerDependencies in the read-package hook and count as ‘applied’ hits
there, but the pnpr-server lockfile scan only inspects importer dependency maps (which omit peers)
when using project manifests to match a workspace parent, so peer-only hits won’t be recognized.

pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[39-61]
pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[85-105]
pnpm11/core/types/src/package.ts[90-106]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The pnpr-server unused-override detector determines “applied” selectors by scanning lockfile importer/package snapshots. For workspace projects it uses `projectManifests` to match the parent name/version, but then only checks the lockfile importer’s `dependencies/devDependencies/optionalDependencies` maps.
However, the override application hook (`createVersionsOverrider`) also applies overrides to `peerDependencies` and reports hits via `onApplied`. Because lockfile importers do not represent `peerDependencies`, an override that only matches a workspace project’s peerDependencies can be treated as unused by the pnpr-server scan.
### Issue Context
This affects pnpr-server mode specifically, where applied selectors are reconstructed from the resolved lockfile instead of being collected during manifest hook execution.
### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[39-61]
- pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[85-105]
### Suggested fix
When evaluating workspace project matches (and potentially for the generic/non-parent path too), also consult `projectManifest.peerDependencies` (and, for completeness, `projectManifest.dependencies/devDependencies/optionalDependencies`) for `targetName`.
Concretely:
- In the `projectManifests` loop, add checks like `depEntryMatches(projectManifest.peerDependencies, targetName)`.
- Consider checking the project manifest’s dependency fields before/without requiring a corresponding lockfile importer entry, since the manifest is the authoritative source for peerDependencies.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (6)
4. Non-semver parent crash 🐞 Bug ⛨ Security
Description
createVersionsOverrider() calls semver.satisfies(manifest.version, parentPkg.bareSpecifier)
without validating that bareSpecifier is a semver range, but parseOverrides() can produce
non-semver values like latest. A malicious or misconfigured override selector (e.g.
parent@latest>child) can throw and abort pnpm install (repo-controlled DoS).
Code

pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[R38-40]

(!parentPkg.bareSpecifier || semver.satisfies(manifest.version, parentPkg.bareSpecifier))
)
})
-    overrideDepsOfPkg({ manifest, dir }, versionOverridesWithParent, genericVersionOverrides)
Evidence
parseOverrides() passes through bareSpecifier from parseWantedDependency() without
semver-range validation, and createVersionsOverrider() uses that value directly in
semver.satisfies(), which can throw on invalid ranges like latest.

pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[34-40]
pnpm11/config/parse-overrides/src/index.ts[62-70]
pnpm11/resolving/parse-wanted-dependency/src/index.ts[15-23]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`createVersionsOverrider()` filters parent-scoped overrides using `semver.satisfies()` on `parentPkg.bareSpecifier` without checking that the range is valid. Because override selectors are parsed via `parseWantedDependency()`, non-semver specifiers like `latest` can reach this code and trigger an exception.
### Issue Context
- Override selectors are repo-controlled input (workspace/package config).
- `parseWantedDependency()` treats anything after `@` as `bareSpecifier` (including dist-tags).
### Fix Focus Areas
- pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[35-40]
### Suggested fix
- Before calling `semver.satisfies(manifest.version, parentPkg.bareSpecifier)`, guard with `semver.validRange(parentPkg.bareSpecifier) != null`.
- If the range is invalid, treat it as **non-matching** (so the override is ignored / can be warned as unused later) or throw a typed `PnpmError('INVALID_SELECTOR', ...)` with a clear message.
- Also guard `manifest.version` (only call `satisfies` when `manifest.version` is present and semver-valid). Add a unit test for `parent@latest>child` (and another invalid range) to prevent regressions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Unused overrides ignore prefix 🐞 Bug ≡ Correctness
Description
pacquet’s default reporter buffers pnpm:unusedOverride selectors without tracking the event
prefix, then flushes the whole buffer on any Stage::ResolutionDone. In multi-prefix runs this
can mix selectors across prefixes or flush too early, producing incorrect/missing warnings.
Code

pacquet/crates/default-reporter/src/state.rs[R329-331]

+            LogEvent::UnusedOverride(log) => {
+                self.pending_unused_overrides.push(log.selector.clone());
+            }
Evidence
The handler receives Stage events with a prefix and maintains other state keyed by prefix, but
unused overrides discard the prefix and flush globally, so the buffering/flush logic cannot be
correct when multiple prefixes are active.

pacquet/crates/default-reporter/src/state.rs[295-335]
pacquet/crates/default-reporter/src/state.rs[429-444]
pacquet/crates/default-reporter/src/state.rs[390-408]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ReporterState` buffers unused override selectors in a single `Vec<String>` and ignores `log.prefix` when receiving `LogEvent::UnusedOverride`. It then flushes the entire buffer on any `Stage::ResolutionDone`, even though stage events are prefix-scoped and the reporter already maintains prefix-scoped state elsewhere.
This can misattribute warnings (selectors from prefix A printed when prefix B hits `resolution_done`) or drop warnings (late selectors after the first `resolution_done` may never be flushed).
## Issue Context
- `LogEvent::UnusedOverride` currently only stores `selector`, discarding `prefix`.
- `on_stage(prefix, stage)` flushes on `ResolutionDone` without using the passed `prefix`.
- The reporter already manages prefix-scoped progress, so multi-prefix support is real.
## Fix Focus Areas
- pacquet/crates/default-reporter/src/state.rs[326-333]
- pacquet/crates/default-reporter/src/state.rs[429-433]
## Suggested fix
- Change `pending_unused_overrides` to be prefix-scoped, e.g. `HashMap<String, Vec<String>>` or `Vec<(String, String)>`.
- On `LogEvent::UnusedOverride`, store `(prefix, selector)`.
- On `Stage::ResolutionDone` for a given prefix, flush only that prefix’s buffered selectors and clear just that bucket.
- Keep the current “single grouped line per prefix” behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. pnpr parent override false warnings 🐞 Bug ≡ Correctness
Description
In pnpr-server mode, findAppliedOverrideSelectorsFromLockfile() considers parent-scoped overrides
matched only when the parent name is found in package snapshots, so parent-scoped overrides that
apply to workspace project/importer manifests (e.g. my-app>dep) can be incorrectly logged as
unused.
Code

pnpm11/installing/deps-installer/src/install/index.ts[R2637-2653]

+    if (override.parentPkg != null) {
+      const parentName = override.parentPkg.name
+      const parentRange = override.parentPkg.bareSpecifier
+      for (const [depPath, snapshot] of Object.entries(lockfile.packages ?? {}) as Array<[DepPath, PackageSnapshot]>) {
+        const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot)
+        if (name !== parentName) continue
+        if (parentRange != null && version != null && !semver.satisfies(version, parentRange)) continue
+        if (
+          depEntryMatches(snapshot.dependencies, targetName, targetRange) ||
+          depEntryMatches(snapshot.optionalDependencies, targetName, targetRange) ||
+          depEntryMatches(snapshot.peerDependencies, targetName, targetRange)
+        ) {
+          applied.add(override.selector)
+          break
+        }
+      }
+    } else {
Evidence
The pnpr-server scan explicitly limits parent-scoped checks to lockfile.packages entries. However,
a parent-scoped override is matched upstream by comparing parentPkg.name to manifest.name, which
includes workspace project manifests; lockfile importer snapshots contain only dependency maps and
do not store name/version, so the scan has no way to recognize importer parents unless it is
explicitly given the project manifests/importer IDs.

pnpm11/installing/deps-installer/src/install/index.ts[2616-2653]
pnpm11/lockfile/types/src/index.ts[68-78]
pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[34-45]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`findAppliedOverrideSelectorsFromLockfile()` checks `lockfile.packages` for parent-scoped overrides, but does not account for the case where the parent package is a workspace project (an importer manifest). Since lockfile importer snapshots do not include package `name`/`version`, the current scan cannot detect that `parentPkg` matches a project manifest, and may emit false `pnpm:unusedOverride` logs.
### Issue Context
- Parent-scoped overrides in the local resolver path match against `manifest.name`/`manifest.version` (including project manifests).
- The pnpr-server path tries to reconstruct “applied overrides” by scanning the resolved lockfile.
### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[2616-2676]
- pnpm11/lockfile/types/src/index.ts[68-78]
- pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[34-45]
### Suggested fix
- Extend the pnpr-server scan to also treat workspace project manifests as possible `parentPkg` matches:
- In `installViaPnprServer()`, you already have `manifest` and optionally `allInstallProjects`.
- For each project whose `manifest.name` matches `override.parentPkg.name` (and version satisfies `parentPkg.bareSpecifier` when present), look up that project’s importer snapshot (`lockfile.importers[importerId]`) and check whether it contains the target dependency key (and range logic as appropriate).
- Keep the existing `lockfile.packages` scan for parent packages that are real resolved packages.
- Consider adjusting the helper signature to accept `{ importerId, manifest }[]` so parent-scoped overrides can be validated against importers without guessing parent identity from the lockfile.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Range match false negatives 🐞 Bug ≡ Correctness
Description
In pnpr-server mode, depEntryMatches() treats any non-semver lockfile version string as a match when
an override selector has a version range, so version-scoped overrides (e.g. foo@^1) can be
considered applied even when the resolved version does not satisfy the range, suppressing the
unused-override warning. This is common because lockfile versions can include peer suffixes like
"3.4.1(ajv@6.10.2)" which semver.valid() rejects.
Code

pnpm11/installing/deps-installer/src/install/index.ts[R2689-2699]

+function depEntryMatches (
+  deps: Record<string, string> | undefined,
+  targetName: string,
+  targetRange: string | undefined
+): boolean {
+  if (deps == null) return false
+  const version = deps[targetName]
+  if (version == null) return false
+  if (targetRange == null) return true
+  if (!semver.valid(version)) return true
+  return semver.satisfies(version, targetRange)
Evidence
The new scan logic explicitly treats non-semver resolved versions as matches for ranged selectors,
and peer-suffixed versions are present in pnpm lockfiles, so ranged selectors can be incorrectly
marked applied.

pnpm11/installing/deps-installer/src/install/index.ts[2689-2699]
pnpm11/fixtures/with-peer/pnpm-lock.yaml[9-17]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`depEntryMatches()` currently returns `true` for any non-semver `version` string when `targetRange` is set. In pnpm lockfiles, resolved versions frequently include peer suffixes (e.g. `3.4.1(ajv@6.10.2)`), plus other non-semver forms (`link:`, `npm:` aliases). This causes version-scoped override selectors to be treated as “applied” just because the dependency key exists, which suppresses the new unused-override warning.
### Issue Context
The pnpr-server path relies on `findAppliedOverrideSelectorsFromLockfile()` to infer which override selectors matched since server-side resolution does not report selectors.
### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[2689-2700]
### Suggested fix
- When `targetRange` is set:
- Extract a comparable semver from the lockfile value rather than treating non-semver as a match.
- For peer suffixes, a simple and accurate approach is `const base = version.split('(')[0]` and then `semver.valid(base)`.
- Return `false` (not a match) for non-semver protocols like `link:`, `file:`, `npm:` unless you have a deliberate, proven mapping that matches pnpm’s override-selector semantics.
- Keep the existing fast-path `targetRange == null => true` for name-only selectors.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Unhandled invalid selector ranges 🐞 Bug ☼ Reliability
Description
The pnpr-server lockfile scan calls semver.satisfies() with selector bareSpecifiers that are not
validated as semver ranges; selectors like foo@latest can reach this code and may throw, crashing
installs (repo-controlled DoS). The local override matcher guards semver operations with
semver.validRange(), but this scan does not.
Code

pnpm11/installing/deps-installer/src/install/index.ts[R2640-2644]

+      for (const [depPath, snapshot] of Object.entries(lockfile.packages ?? {}) as Array<[DepPath, PackageSnapshot]>) {
+        const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot)
+        if (name !== parentName) continue
+        if (parentRange != null && version != null && !semver.satisfies(version, parentRange)) continue
+        if (
Evidence
Override selector parsing does not ensure semver ranges, yet the new scan calls semver.satisfies
without validity checks; other parts of the codebase show the intended pattern is to guard with
semver.validRange first.

pnpm11/installing/deps-installer/src/install/index.ts[2640-2644]
pnpm11/resolving/parse-wanted-dependency/src/index.ts[15-37]
pnpm11/config/parse-overrides/src/index.ts[62-70]
pnpm11/hooks/read-package-hook/src/isIntersectingRange.ts[3-9]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`findAppliedOverrideSelectorsFromLockfile()` and `depEntryMatches()` call `semver.satisfies(version, range)` on `range` values derived from override selectors. Override selector parsing does not semver-validate `bareSpecifier`, so non-semver strings (e.g. `latest`) can reach this code and may crash the install.
### Issue Context
- `parseWantedDependency()` returns the raw substring after `@` as `bareSpecifier` without semver validation.
- The normal override-application logic (`isIntersectingRange`) explicitly checks `semver.validRange()` before using semver range logic.
### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[2640-2644]
- pnpm11/installing/deps-installer/src/install/index.ts[2689-2700]
### Suggested fix
- Before calling `semver.satisfies(...)`:
- If `range` is not a valid semver range (`semver.validRange(range) == null`), treat it as non-matching (return `false` / skip) to align with `isIntersectingRange()` behavior.
- Optionally wrap `semver.satisfies` in a try/catch as a belt-and-suspenders guard, logging debug if needed.
- Apply this guard for both:
- `parentRange` check in the parent-scoped branch, and
- `targetRange` checks in `depEntryMatches()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. pnprServer skips unused-override warning 📎 Requirement gap ≡ Correctness
Description
When pnprServer is configured, pnpm install returns via the pnpr-server path and the new
unused-override warning is explicitly skipped. This violates the requirement to warn on unused
overrides during pnpm i, allowing silent misconfiguration in this mode.
Code

pnpm11/installing/deps-installer/src/install/index.ts[R186-193]

// When a pnpr server is configured, use server-side resolution
-  // instead of the normal resolution flow.
+  // instead of the normal resolution flow. The pnpr protocol resolves
+  // with overrides but does not report which selectors matched, so
+  // the unused-override warning is silently skipped on this path —
+  // an acceptable tradeoff to preserve pnpr's performance benefit.
if (opts.pnprServer) {
return installViaPnprServer(manifest, rootDir, opts)
}
Evidence
PR Compliance ID 1 requires emitting a warning when an overrides entry matches no dependency
during pnpm i. The updated install path documents and enforces that when pnprServer is
configured the unused-override warning is skipped, and a new test explicitly asserts this skip,
meaning an unused override can produce no warning in this configuration.

Warn when a pnpm override key matches no packages during installation
pnpm11/installing/deps-installer/src/install/index.ts[186-193]
pnpm11/pnpm/test/install/pnpmRegistry.ts[97-122]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The unused-override warning is skipped when `opts.pnprServer` is set, so `pnpm install` can run with unused `overrides` without emitting any warning.
## Issue Context
The PR introduces unused override detection and reporting, but the pnpr-server install path currently bypasses it (and a test asserts this behavior).
## Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[186-193]
- pnpm11/pnpm/test/install/pnpmRegistry.ts[97-122]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

10. Workspace peerDeps scan missed 🐞 Bug ≡ Correctness ⭐ New
Description
In pnpr-server mode, findAppliedOverrideSelectorsFromLockfile() only consults workspace project
manifests (for peerDependencies) when the override is parent-scoped; generic overrides never check
projectManifests and therefore can’t match a workspace project’s peerDependencies. This can
incorrectly warn that a generic override is unused even though it matched a workspace manifest
peerDependency.
Code

pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[R39-89]

+    if (override.parentPkg != null) {
+      const parentName = override.parentPkg.name
+      const parentRange = override.parentPkg.bareSpecifier
+      const parentRangeValid = parentRange == null || semver.validRange(parentRange) != null
+
+      for (const { importerId, manifest: projectManifest } of projectManifests) {
+        if (projectManifest.name !== parentName) continue
+        if (parentRange != null) {
+          const projectVersion = projectManifest.version
+          if (projectVersion == null) continue
+          if (!parentRangeValid || !semver.satisfies(projectVersion, parentRange)) continue
+        }
+        // Importer snapshots don't carry peerDependencies, so check the
+        // manifest directly for that field. The other three groups are
+        // covered by the importer entry (resolved deps share the same
+        // names as the manifest).
+        const importer = lockfile.importers[importerId as ProjectId]
+        if (
+          (importer != null && targetInImporter(importer, targetName)) ||
+          depEntryMatches(projectManifest.peerDependencies, targetName)
+        ) {
+          applied.add(override.selector)
+          break
+        }
+      }
+      if (applied.has(override.selector)) continue
+
+      for (const [depPath, snapshot] of packageEntries) {
+        const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot)
+        if (name !== parentName) continue
+        if (parentRange != null && (version == null || !parentRangeValid || !semver.satisfies(version, parentRange))) continue
+        if (targetInSnapshot(snapshot, targetName)) {
+          applied.add(override.selector)
+          break
+        }
+      }
+    } else {
+      for (const importer of importerSnapshots) {
+        if (targetInImporter(importer, targetName)) {
+          applied.add(override.selector)
+          break
+        }
+      }
+      if (applied.has(override.selector)) continue
+      for (const snapshot of packageSnapshots) {
+        if (targetInSnapshot(snapshot, targetName)) {
+          applied.add(override.selector)
+          break
+        }
+      }
+    }
Evidence
The function explicitly notes importers don’t carry peerDependencies and checks
projectManifest.peerDependencies only for parent-scoped overrides. For generic overrides, it scans
only importer snapshots (no peerDeps) and package snapshots, so a workspace project
peerDependency-only match is invisible and will be treated as unused.

pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[39-63]
pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[75-89]
pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[95-104]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`findAppliedOverrideSelectorsFromLockfile()` has special handling for importer peerDependencies via `projectManifests`, but only in the parent-scoped override branch. Generic overrides (no `parentPkg`) can apply to workspace project `peerDependencies` too, yet the scan never checks them, leading to false `pnpm:unused-override` warnings in pnpr-server installs.

### Issue Context
Importer snapshots do not contain peerDependencies, so the scan already relies on `projectManifests` to see workspace peers in the parent-scoped path. The same limitation applies to the generic path.

### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[39-90]
- pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[95-104]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Unused override warning collapses 🐞 Bug ◔ Observability
Description
In pacquet’s default reporter, the grouped unused-override summary is emitted via push_warning(),
so once more than MAX_SHOWN_WARNINGS warnings have already been shown, this message can be
replaced by the generic “X other warnings” line and users won’t see which overrides were unused.
Code

pacquet/crates/default-reporter/src/state.rs[R466-472]

+        let head = if sanitized.len() == 1 {
+            "1 override matched no dependency".to_string()
+        } else {
+            format!("{} overrides matched no dependency", sanitized.len())
+        };
+        self.push_warning(&format!("{}: {}", head, sanitized.join(", ")));
+    }
Evidence
flush_pending_unused_overrides() emits the grouped message with self.push_warning(...).
push_warning() increments warnings_counter and, after MAX_SHOWN_WARNINGS, replaces subsequent
warnings with a collapsed “X other warnings” message—so the unused-override summary can be
suppressed.

pacquet/crates/default-reporter/src/state.rs[446-472]
pacquet/crates/default-reporter/src/state.rs[240-241]
pacquet/crates/default-reporter/src/state.rs[1012-1025]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The unused-override grouped warning is currently emitted through `push_warning()`. That function enforces pnpm’s “show first N warnings then collapse the rest” behavior, meaning the unused-override summary can be hidden behind a generic “X other warnings” line when many warnings occur.
### Issue Context
This is a new warn surface intended to be actionable; hiding it makes the feature unreliable in real-world installs that already produce many warnings (e.g. deprecations).
### Fix Focus Areas
- pacquet/crates/default-reporter/src/state.rs[458-472]
- pacquet/crates/default-reporter/src/state.rs[1012-1025]
- pacquet/crates/default-reporter/src/state.rs[240-241]
### Suggested change
Emit the grouped unused-override summary using a non-collapsing path (e.g. `push_block(format!("{} {message}", warn_label))`) or otherwise ensure it is always rendered even after `MAX_SHOWN_WARNINGS` is exceeded (e.g. a dedicated method that prints with `[WARN]` styling but does not increment/collapse the global warnings counter).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Unbounded WARN line size 🐞 Bug ➹ Performance
Description
reportUnusedOverrides buffers all pnpm:unused-override events until resolution_done and then
concatenates every selector into one WARN line with no cap. A repo with many/very-long override keys
can cause large temporary allocations and huge log output during install, degrading performance and
potentially destabilizing the process.
Code

pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[R25-41]

+  const resolutionDone$ = log$.stage.pipe(
+    filter((log) => log.stage === 'resolution_done')
+  )
+  return log$.unusedOverride.pipe(
+    buffer(resolutionDone$),
+    map((unusedOverrides) => {
+      if (unusedOverrides.length === 0) return Rx.EMPTY
+      const selectors = unusedOverrides
+        .map((log) => sanitizeSelector(log.selector))
+        .sort()
+      const head = selectors.length === 1
+        ? '1 override matched no dependency'
+        : `${selectors.length} overrides matched no dependency`
+      return Rx.of({
+        msg: formatWarn(`${head}: ${selectors.join(', ')}`),
+      })
+    })
Evidence
The reporter buffers every unused override event until resolution_done and then joins all
selectors into a single string, while the installer emits one event per unused selector from the
parsed overrides list (repo-controlled config).

pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[25-41]
pnpm11/installing/deps-installer/src/install/index.ts[1662-1680]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`reportUnusedOverrides()` buffers all unused override selectors until `resolution_done` and then builds one giant warning line via `selectors.join(', ')` with no cap. This can create very large allocations and extremely long terminal/CI output when a workspace config contains many or very large override selectors.
### Issue Context
The unused-override events are emitted once per unmatched override selector during install, so the buffered list size scales directly with the configured overrides size.
### Fix Focus Areas
- pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[25-41]
- pnpm11/installing/deps-installer/src/install/index.ts[1662-1680]
### Suggested fix direction
- Impose a maximum number of selectors rendered (e.g. first N after sort), and append `… (+X more)`.
- Impose a maximum total message length and/or per-selector length (truncate long selectors).
- Consider deduping identical sanitized selectors before rendering to reduce output volume.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (7)
13. Unbounded pacquet WARN size 🐞 Bug ➹ Performance
Description
pacquet’s default reporter stores all unused override selectors in memory and renders them as one
concatenated warning on ResolutionDone with no cap. A workspace with many/very-long override
selectors can significantly increase memory use and produce extremely large terminal output at the
end of resolution.
Code

pacquet/crates/default-reporter/src/state.rs[R460-473]

+    fn flush_pending_unused_overrides(&mut self) {
+        if self.pending_unused_overrides.is_empty() {
+            return;
+        }
+        let selectors = std::mem::take(&mut self.pending_unused_overrides);
+        let sanitized: Vec<String> =
+            selectors.iter().map(|s| sanitize_override_selector(s)).collect();
+        let head = if sanitized.len() == 1 {
+            "1 override matched no dependency".to_string()
+        } else {
+            format!("{} overrides matched no dependency", sanitized.len())
+        };
+        self.push_warning(&format!("{}: {}", head, sanitized.join(", ")));
+    }
Evidence
pacquet buffers selectors in pending_unused_overrides and concatenates them at ResolutionDone,
while the installer emits one event per unused selector after resolution.

pacquet/crates/default-reporter/src/state.rs[429-473]
pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1202-1239]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The pacquet default reporter buffers unused override selectors and flushes them into a single warning line by joining all selectors. There is no cap on how many selectors are buffered or how long the resulting rendered line can be.
### Issue Context
`install_with_fresh_lockfile` emits one `LogEvent::UnusedOverride` per unused selector, so the reporter’s buffered vector scales linearly with the number/size of override keys.
### Fix Focus Areas
- pacquet/crates/default-reporter/src/state.rs[460-473]
- pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1202-1239]
### Suggested fix direction
- Cap the number of buffered selectors rendered (first N) and append a suffix like `… (+X more)`.
- Cap per-selector length and/or total rendered warning length.
- Optionally dedupe selectors before rendering to reduce output volume.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. Prototype-key false matches 🐞 Bug ⛨ Security
Description
findAppliedOverrideSelectorsFromLockfile() uses deps[targetName] != null, which also returns
truthy for inherited prototype keys (e.g. constructor), so an override like constructor: ... can
be incorrectly treated as applied and never warned as unused on the pnpr-server scan path.
Code

pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[R117-123]

+function depEntryMatches (
+  deps: Record<string, string> | undefined,
+  targetName: string
+): boolean {
+  if (deps == null) return false
+  return deps[targetName] != null
+}
Evidence
The new lockfile-scan matcher uses direct bracket lookup (deps[targetName]) to decide whether a
dependency key exists. The lockfile is parsed via yaml.load(...) into ordinary JS objects, so
inherited properties can be observed via bracket access and mistakenly treated as present dependency
keys.

pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[117-123]
pnpm11/lockfile/fs/src/read.ts[135-141]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`depEntryMatches()` checks dependency presence via `deps[targetName] != null`. Because `deps` is a normal JS object, this lookup can hit the prototype chain (e.g. `deps['constructor']`), producing false positives and suppressing the new unused-override warning.
### Issue Context
This function is used to infer which override selectors matched when scanning a resolved lockfile (pnpr-server path). Lockfiles are parsed from YAML into plain JS objects.
### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[117-123]
- pnpm11/lockfile/fs/src/read.ts[135-141]
### Suggested fix
Change `depEntryMatches()` to check own-properties only, e.g.:
- `return Object.prototype.hasOwnProperty.call(deps, targetName)`
- or `return Object.hasOwn(deps, targetName)` (if supported by your TS/Node target)
This avoids matching inherited keys and keeps the unused-override signal trustworthy.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. Unicode spoof in WARN 🐞 Bug ⛨ Security
Description
pacquet’s sanitize_override_selector() only removes Unicode General Category Cc (“control”)
characters, so bidi formatting chars (Cf) and line/paragraph separators (Zl/Zp, e.g. U+2028/U+2029)
can still be embedded in override keys and visually spoof/split the grouped [WARN] ... line. This
weakens the trustworthiness of the new warning signal in terminals/CI because the rendered output
can be made misleading without changing the structured log payload.
Code

pacquet/crates/default-reporter/src/state.rs[R1034-1039]

+/// Strip ASCII control characters (C0 range 0x00–0x1F and DEL 0x7F)
+/// from an override selector before rendering, so a crafted key
+/// cannot inject/spoof terminal output.
+fn sanitize_override_selector(selector: &str) -> String {
+    selector.chars().filter(|ch| !ch.is_control()).collect()
+}
Evidence
The sanitizer only filters !ch.is_control(), and the sanitized strings are concatenated into the
emitted warning without further escaping, so any non-control Unicode formatting/separator characters
in selectors will be rendered verbatim in the WARN line.

pacquet/crates/default-reporter/src/state.rs[446-473]
pacquet/crates/default-reporter/src/state.rs[1034-1039]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`sanitize_override_selector()` currently filters only `char::is_control()`, which does not remove Unicode formatting characters (bidi controls, general category Cf) or line/paragraph separators (e.g. U+2028/U+2029). Those characters can be used in repo-controlled override selectors to visually spoof the grouped warning line in terminal/CI output.
## Issue Context
The sanitized selector is directly interpolated into a single `[WARN] ...` line during `flush_pending_unused_overrides()`. Even if ASCII control chars are stripped, bidi controls can reorder text and separators can create apparent line breaks in some renderers.
## Fix Focus Areas
- pacquet/crates/default-reporter/src/state.rs[1034-1039]
- pacquet/crates/default-reporter/src/state.rs[446-473]
## Suggested fix approach
- Extend sanitization to also remove/replace:
- Unicode bidi control characters (e.g. U+200E/U+200F/U+061C, U+202A–U+202E, U+2066–U+2069).
- Line/paragraph separators (U+2028, U+2029) and optionally other whitespace that can render as line breaks.
- Consider replacing removed characters with a visible placeholder (or a single space) to preserve readability while preventing spoofing.
- Add a targeted test case similar to the existing control-character test, but using e.g. `"foo\u202Ebar"` and/or `"foo\u2028bar"` to ensure the rendered warning stays single-line and non-spoofable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. Quadratic override lockfile scan 🐞 Bug ➹ Performance
Description
findAppliedOverrideSelectorsFromLockfile() scans all importers and packages for every override
selector, yielding O(#overrides × (importers+packages)) work in pnpr-server installs. A repo with a
large overrides object can significantly increase install CPU time on this path.
Code

pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts[R32-106]

+  const packageEntries = Object.entries(lockfile.packages ?? {}) as Array<[DepPath, PackageSnapshot]>
+  const packageSnapshots = packageEntries.map(([, snapshot]) => snapshot)
+  const importerSnapshots = Object.values(lockfile.importers)
+
+  for (const override of parsedOverrides) {
+    const targetName = override.targetPkg.name
+
+    if (override.parentPkg != null) {
+      const parentName = override.parentPkg.name
+      const parentRange = override.parentPkg.bareSpecifier
+      const parentRangeValid = parentRange == null || semver.validRange(parentRange) != null
+
+      for (const { importerId, manifest: projectManifest } of projectManifests) {
+        if (projectManifest.name !== parentName) continue
+        if (parentRange != null) {
+          const projectVersion = projectManifest.version
+          if (projectVersion == null) continue
+          if (!parentRangeValid || !semver.satisfies(projectVersion, parentRange)) continue
+        }
+        // Importer snapshots don't carry peerDependencies, so check the
+        // manifest directly for that field. The other three groups are
+        // covered by the importer entry (resolved deps share the same
+        // names as the manifest).
+        const importer = lockfile.importers[importerId as ProjectId]
+        const matched =
+          (importer != null && (
+            depEntryMatches(importer.dependencies, targetName) ||
+            depEntryMatches(importer.devDependencies, targetName) ||
+            depEntryMatches(importer.optionalDependencies, targetName)
+          )) ||
+          depEntryMatches(projectManifest.peerDependencies, targetName)
+        if (matched) {
+          applied.add(override.selector)
+          break
+        }
+      }
+      if (applied.has(override.selector)) continue
+
+      for (const [depPath, snapshot] of packageEntries) {
+        const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot)
+        if (name !== parentName) continue
+        if (parentRange != null && (version == null || !parentRangeValid || !semver.satisfies(version, parentRange))) continue
+        if (
+          depEntryMatches(snapshot.dependencies, targetName) ||
+          depEntryMatches(snapshot.optionalDependencies, targetName) ||
+          depEntryMatches(snapshot.peerDependencies, targetName)
+        ) {
+          applied.add(override.selector)
+          break
+        }
+      }
+    } else {
+      for (const importer of importerSnapshots) {
+        if (
+          depEntryMatches(importer.dependencies, targetName) ||
+          depEntryMatches(importer.devDependencies, targetName) ||
+          depEntryMatches(importer.optionalDependencies, targetName)
+        ) {
+          applied.add(override.selector)
+          break
+        }
+      }
+      if (applied.has(override.selector)) continue
+      for (const snapshot of packageSnapshots) {
+        if (
+          depEntryMatches(snapshot.dependencies, targetName) ||
+          depEntryMatches(snapshot.optionalDependencies, targetName) ||
+          depEntryMatches(snapshot.peerDependencies, targetName)
+        ) {
+          applied.add(override.selector)
+          break
+        }
+      }
+    }
+  }
Evidence
...

@codecov-commenter

codecov-commenter commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.58%. Comparing base (991405e) to head (1aeb576).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12741      +/-   ##
==========================================
+ Coverage   85.55%   85.58%   +0.02%     
==========================================
  Files         413      413              
  Lines       63908    64053     +145     
==========================================
+ Hits        54679    54821     +142     
- Misses       9229     9232       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts (1)

41-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep overrideDepsOfPkg within the argument-count guideline.

Adding onApplied makes this helper a four-argument function; fold it into the existing options object.

Proposed refactor
-    overrideDepsOfPkg({ manifest, dir }, versionOverridesWithParent, genericVersionOverrides, onApplied)
+    overrideDepsOfPkg({ manifest, dir, onApplied }, versionOverridesWithParent, genericVersionOverrides)
 function overrideDepsOfPkg (
-  { manifest, dir }: { manifest: PackageManifest, dir: string | undefined },
+  { manifest, dir, onApplied }: {
+    manifest: PackageManifest
+    dir: string | undefined
+    onApplied?: (override: VersionOverrideBase) => void
+  },
   versionOverrides: VersionOverrideWithParent[],
-  genericVersionOverrides: VersionOverride[],
-  onApplied?: (override: VersionOverrideBase) => void
+  genericVersionOverrides: VersionOverride[]
 ): void {

As per coding guidelines, TypeScript functions should keep to no more than two or three arguments by using an options object when needed.

Also applies to: 78-83

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts` at line 41,
The helper call in createVersionsOverrider is passing too many arguments to
overrideDepsOfPkg, violating the argument-count guideline. Refactor
overrideDepsOfPkg to accept onApplied inside the existing options object instead
of as a separate fourth parameter, then update the call sites in
createVersionsOverrider and the related usage around the other referenced block
to match the new signature.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs`:
- Around line 1217-1244: Gate the unused-override reporting in
install_with_fresh_lockfile on full re-resolution only: the current use of
versions_overrider.applied_selectors() in the unused selector loop can
misclassify overrides when reused wanted_lockfile subtrees are present. Update
the conditional around the UnusedOverride emission so it only runs when the
install path truly re-resolves the tree, and keep the existing selector
comparison logic inside that guarded block.

---

Nitpick comments:
In `@pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts`:
- Line 41: The helper call in createVersionsOverrider is passing too many
arguments to overrideDepsOfPkg, violating the argument-count guideline. Refactor
overrideDepsOfPkg to accept onApplied inside the existing options object instead
of as a separate fourth parameter, then update the call sites in
createVersionsOverrider and the related usage around the other referenced block
to match the new signature.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: debad984-0556-45b2-91cc-1f1cb937e0f6

📥 Commits

Reviewing files that changed from the base of the PR and between a6f303c and 851747d.

📒 Files selected for processing (24)
  • .changeset/warn-unused-overrides.md
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pnpm11/cli/default-reporter/src/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/core/core-loggers/src/index.ts
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pnpm11/installing/deps-installer/src/install/index.ts
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (9)
  • GitHub Check: Rust CI / Test / macos
  • GitHub Check: Rust CI / Test / ubuntu
  • GitHub Check: Rust CI / Test / windows
  • GitHub Check: Rust CI / Dylint
  • GitHub Check: TS CI / Build pnpr / ubuntu-latest
  • GitHub Check: TS CI / Build pnpr / windows-latest
  • GitHub Check: Code Coverage
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Run benchmark on ubuntu-latest
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: In TypeScript code, prefer interface for defining object shapes.
In TypeScript code, use camelCase for variable names.
In TypeScript code, prefer async/await over promise chains, use Promise.all or Promise.any for independent work, and hoist invariant work out of loops.
In TypeScript code, prefer functions over classes, declare functions after use when relying on hoisting, and keep functions to no more than two or three arguments by using an options object when needed.
In TypeScript code, use the import order: standard libraries first, then external dependencies in alphabetical order, then relative imports.
In TypeScript code, throw PnpmError for user-reachable errors, use plain Error for programmer/type-guard/unreachable errors, never swallow errors, catch only the specific expected error code, and include contextual information such as the offending path in error messages.
In TypeScript code, keep configuration flowing through @pnpm/config and command options, avoid hardcoding configurable values, have command handlers return data for the CLI to print, and avoid wrapper functions that add no behavior.
In TypeScript code, use async filesystem APIs and util.types.isNativeError() in Jest instead of instanceof Error when checking caught errors across realms.
In TypeScript tests, do not use instanceof Error for caught-error checks; use util.types.isNativeError() instead because Jest can run tests across VM realms.

Files:

  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/core/core-loggers/src/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/cli/default-reporter/src/index.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts
  • pnpm11/installing/deps-installer/src/install/index.ts
pacquet/crates/**/*.rs

📄 CodeRabbit inference engine (pacquet/AGENTS.md)

pacquet/crates/**/*.rs: When porting a function that emits pnpm-style log events through globalLogger, logger.debug(...), or streamParser.write(...), mirror the upstream call site, payload, and ordering so the default reporter parses pacquet NDJSON the same way.
Prefer real fixtures; use the dependency-injection seam on Host/Sys only for branches that portable fixtures cannot reach, such as filesystem error kinds, deterministic time, shared process-global state, or external-service happy paths.
When porting a branded string type, declare a distinct Rust newtype wrapper instead of collapsing it to String or &str.
If upstream always validates a branded string before construction, make the Rust wrapper constructible only via TryFrom<String> and/or FromStr; do not provide an infallible public constructor.
If upstream never validates a branded string, expose infallible From<String> (and From<&str> when convenient) for the Rust wrapper.
If upstream sometimes constructs a branded string without validation, add a from_str_unchecked-style constructor alongside the validating constructor.
For branded types that cross JSON, YAML, or INI boundaries, wire serde through the validator with #[serde(try_from = "String")] on deserialization and #[serde(into = "String")] on serialization.
Use derive_more::From / derive_more::Into for mechanical wrapper conversions; hand-write conversion impls only when validation or normalization requires custom logic.
Model upstream string-literal unions as Rust enums rather than newtype wrappers.
Treat TypeScript template-literal types as branded strings and apply the same newtype/validation rules.
Do not use star imports inside module bodies; prefer explicit imports such as use super::{Foo, bar}.
Use doc comments for rustdoc-visible API contracts, and use regular // comments only for non-obvious implementation rationale.
Do not duplicate tests in prose: if a behavior is already covered by a test, keep the doc...

Files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides.rs
🧠 Learnings (14)
📚 Learning: 2026-05-14T09:04:00.133Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11622
File: resolving/npm-resolver/test/publishedBy.test.ts:350-354
Timestamp: 2026-05-14T09:04:00.133Z
Learning: In the pnpm/pnpm repository, ESLint is the authoritative style linter. Do not raise review findings for missing trailing commas in multiline function calls (e.g., `fs.writeFileSync(...)`) when this repo’s ESLint configuration does not report them and lint passes. Prefer deferring to the ESLint results for this specific trailing-comma rule rather than enforcing it manually in code review.

Applied to files:

  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/core/core-loggers/src/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/cli/default-reporter/src/index.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts
  • pnpm11/installing/deps-installer/src/install/index.ts
📚 Learning: 2026-06-05T13:47:26.046Z
Learnt from: vsumner
Repo: pnpm/pnpm PR: 12190
File: installing/deps-installer/src/install/index.ts:2337-2343
Timestamp: 2026-06-05T13:47:26.046Z
Learning: In the pnpm/pnpm codebase, `PnpmError` automatically prefixes `err.code` with `ERR_PNPM_` when you pass a code that does not already start with `ERR_PNPM_` (it normalizes `this.code` via `code.startsWith('ERR_PNPM_') ? code : `ERR_PNPM_${code}``). Therefore, during code review you should NOT flag `new PnpmError(...)` call sites for passing a bare error code (e.g., `new PnpmError('FROZEN_STORE_INCOMPATIBLE_WITH_PNPR', ...)`); the resulting `err.code` will still be `ERR_PNPM_FROZEN_STORE_INCOMPATIBLE_WITH_PNPR`.

Applied to files:

  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/core/core-loggers/src/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/cli/default-reporter/src/index.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts
  • pnpm11/installing/deps-installer/src/install/index.ts
📚 Learning: 2026-06-05T13:47:05.929Z
Learnt from: vsumner
Repo: pnpm/pnpm PR: 12190
File: installing/deps-installer/test/install/frozenStore.ts:2-17
Timestamp: 2026-06-05T13:47:05.929Z
Learning: In the pnpm/pnpm repository, the shared Jest preset keeps `injectGlobals` at its default (`true`), so `test` and `expect` are available as Jest globals. Therefore, reviewers should not flag (or treat as TypeScript/compilation errors) missing `import { test, expect } from 'jest/globals'` when a test file uses `test`/`expect` without importing them. Importing from `jest/globals` may still be used for consistency with sibling files, but it is not required for execution in this repo unless a Jest preset is explicitly configured with `injectGlobals: false`.

Applied to files:

  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
📚 Learning: 2026-05-26T21:01:06.666Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11966
File: .changeset/require-tarball-integrity.md:6-6
Timestamp: 2026-05-26T21:01:06.666Z
Learning: In pnpm lockfile-related release notes/docs (especially changeset markdown), preserve URL hostnames exactly as they appear in pnpm-lock.yaml tarball resolution entries—keep hosts like `codeload.github.com`, `bitbucket.org`, and `gitlab.com` in lowercase. Do not “correct” them to title-case/preserve brand capitalization (e.g., LanguageTool rules like `GITHUB` capitalization) because these are literal URL fragments, not platform brand names.

Applied to files:

  • .changeset/warn-unused-overrides.md
📚 Learning: 2026-05-20T19:40:55.051Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11774
File: pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs:0-0
Timestamp: 2026-05-20T19:40:55.051Z
Learning: In the pacquet Rust code, ensure the semver implementation uses the `node-semver` crate (not `nodejs-semver`). `node-semver`’s public API does not include a `satisfies_with_prerelease`-style method; prerelease-tolerant matching should be implemented inline by first calling `Range::satisfies`, and when it rejects a prerelease version, retry matching against a stripped `MAJOR.MINOR.PATCH` base of the prerelease version.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-05-22T00:08:44.646Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11837
File: pacquet/crates/resolving-npm-resolver/src/pick_package.rs:33-51
Timestamp: 2026-05-22T00:08:44.646Z
Learning: In the pnpm/pnpm repo’s pacquet Rust crates, do not flag Unicode ellipsis characters (U+2026, `…`) in Rust doc comments (`///` / `/** */`) as a lint violation. The pacquet crate’s `dylint.toml` only enables `perfectionist::derive_ordering`, and the Dylint `unicode-ellipsis` rule is not enabled for this project—so `…` in doc comments is an intentional, repo-consistent style.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-05-20T23:07:58.444Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11784
File: pacquet/crates/resolving-deps-resolver/src/hoist_peers.rs:120-133
Timestamp: 2026-05-20T23:07:58.444Z
Learning: When reviewing code in this pacquet Rust port, follow the upstream pnpm compatibility rule: only match pnpm’s behavior exactly. Do not propose review changes that intentionally deviate from pnpm’s documented/observed behavior, even if pnpm appears buggy. If you identify a real bug in pnpm behavior, the review should prioritize fixing it upstream in pnpm first, and avoid implementing a pnpm-behavior workaround here unless the same fix has already landed upstream.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-06-06T18:58:37.156Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12243
File: pacquet/crates/package-manager/src/install_package_by_snapshot.rs:319-322
Timestamp: 2026-06-06T18:58:37.156Z
Learning: When reviewing Rust code, do not assume `matches!(expr, Pattern(_))` will move out of `expr` if `Pattern(_)` contains no by-value bindings. `matches!` desugars to a `match` that auto-borrows the scrutinee for discrimination, so even if `expr` is a non-`Copy` value behind a shared reference (e.g., `&T`), the macro should not move-out of the borrowed data purely due to `matches!`. Treat `matches!(&expr, Pattern(_))` as a readability/clarity improvement, not a correctness requirement. Only flag potential move-out-of-borrow risks when the pattern includes by-value bindings that would require moving the matched value.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-06-12T20:41:57.558Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12364
File: pacquet/crates/package-manager/src/install/tests.rs:5717-5717
Timestamp: 2026-06-12T20:41:57.558Z
Learning: In the pnpm/pnpm Rust workspace (toolchain Rust 1.95.0), keep using `std::time::Duration::from_mins(...)` and `std::time::Duration::from_hours(...)` as-is. Do not flag these as invalid or suggest replacing them with `Duration::from_secs(...)`, because Clippy’s `clippy::duration_suboptimal_units` lint is denied by `-D warnings` in CI, and changing to seconds may trigger CI failures.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-06-29T10:07:32.128Z
Learnt from: KSXGitHub
Repo: pnpm/pnpm PR: 12719
File: pacquet/crates/cli/tests/update.rs:56-56
Timestamp: 2026-06-29T10:07:32.128Z
Learning: When reviewing Rust code, do not flag `format!`, `write!`, or `writeln!` calls as having “missing format arguments” if the format string is a raw string literal (e.g., `r#"...{name}..."#`, `br#"...{spec}..."#`) that uses Rust’s captured-format-argument syntax (`{name}`, `{spec}`, etc.). Raw string literals still support captured-format placeholders, so the code is valid as long as those captured names correspond to in-scope variables and compiles.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-06-12T07:04:03.703Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12227
File: pacquet/crates/package-manager/src/install.rs:708-719
Timestamp: 2026-06-12T07:04:03.703Z
Learning: In this pnpm-based repo’s package-manager Rust code, `ThrottledClient` uses a two-class semaphore scheduling policy (“reserved half” for tarball/download work and a higher-priority “latency class” for lockfile-verification metadata fetches). Therefore, when reviewing, do NOT flag reuse of the same `Arc<ThrottledClient>` for both downloads and verification as a budget/contention issue—this reuse is intentional and handled by the internal two-class “reserved permits” design. Creating a separate client instance would break the EMFILE guard behavior that relies on shared throttling.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-06-16T00:37:05.024Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12436
File: pacquet/crates/package-manager/src/install.rs:254-270
Timestamp: 2026-06-16T00:37:05.024Z
Learning: When reviewing the pacquet Rust port (package-manager crate), ensure any diagnostic `help`/message text included in error variants (e.g., `ERR_PNPM_*` codes) matches pnpm upstream error message strings verbatim. This includes user-facing strings and any pnpm-specific presentation (error code naming, `pnpm:*` log channels, pnpm user-agent expectations, etc.). If the help text references a command that is not yet implemented in pacquet (e.g., `approve-builds`), do not flag that as a review issue—porting/implementing the missing command is tracked separately; keep the user-facing message consistent with pnpm.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-06-30T00:46:30.632Z
Learnt from: KSXGitHub
Repo: pnpm/pnpm PR: 12737
File: pacquet/crates/package-manager/src/dependencies_graph_to_lockfile.rs:354-354
Timestamp: 2026-06-30T00:46:30.632Z
Learning: When implementing permalink-stability / reachability checks for GitHub commit SHAs in the pnpm codebase, do not determine whether a pinned SHA is reachable from `origin/main` by running `git merge-base --is-ancestor <sha> origin/main` on a shallow `--depth=1` clone. A shallow clone can omit older `origin/main` commits, causing false “unreachable” results. For ancestry/merge-base checks, fetch full history (or otherwise ensure the local commit graph contains the relevant `origin/main` history needed for the ancestry test) before concluding that a pinned SHA is off-`main`.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/package-manager/src/overrides.rs
📚 Learning: 2026-06-19T14:23:52.915Z
Learnt from: KSXGitHub
Repo: pnpm/pnpm PR: 12510
File: pacquet/crates/real-hoist/src/tests.rs:1098-1098
Timestamp: 2026-06-19T14:23:52.915Z
Learning: In the pnpm/pnpm Pacquet Rust codebase, treat `dbg!` calls that appear immediately before an `assert!` (but not `assert_eq!`)—especially when checking complex values like `HashMap<..., VecDeque<...>>`—as intentional, per `CODE_STYLE_GUIDE.md` ("When or when not to log during tests?"). Do not flag these `dbg!` statements as debugging noise or recommend removing them. This is meant to ensure that if the test fails, the actual logged value is visible; `just test` runs tests via `cargo nextest run`, which keeps output from passing tests and only surfaces it on failures.

Applied to files:

  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/tests.rs
🔇 Additional comments (24)
pnpm11/cli/default-reporter/src/reporterForClient/index.ts (1)

61-61: LGTM!

Also applies to: 116-119

pnpm11/pnpm/test/install/pnpmRegistry.ts (1)

97-125: LGTM!

.changeset/warn-unused-overrides.md (1)

1-19: LGTM!

pnpm11/pnpm/test/install/unusedOverrides.ts (1)

84-97: 🎯 Functional Correctness

No change needed: packageConfigs.<project>.overrides is supported in pnpm-workspace.yaml.

			> Likely an incorrect or invalid review comment.
pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts (1)

18-29: 🎯 Functional Correctness

No dedupe needed here. parseOverrides() starts from Record<string, string>, so the same selector cannot appear twice in opts.parsedOverrides or reach this reporter.

			> Likely an incorrect or invalid review comment.
pnpm11/cli/default-reporter/src/index.ts (1)

169-169: LGTM!

Also applies to: 245-247, 291-291

pacquet/crates/default-reporter/src/state.rs (1)

237-243: LGTM!

Also applies to: 297-297, 335-337, 436-439, 452-472

pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts (1)

15-102: LGTM!

pacquet/crates/default-reporter/tests/render.rs (1)

334-399: LGTM!

pnpm11/installing/deps-installer/test/install/overrides.ts (1)

315-317: 🎯 Functional Correctness

No duplicate const calls declaration here.

			> Likely an incorrect or invalid review comment.
pnpm11/core/core-loggers/src/unusedOverrideLogger.ts (1)

1-14: LGTM!

pnpm11/core/core-loggers/src/index.ts (1)

25-25: LGTM!

Also applies to: 55-55

pacquet/crates/reporter/src/lib.rs (1)

159-168: LGTM!

Also applies to: 660-669

pacquet/crates/reporter/src/tests.rs (1)

700-721: LGTM!

pacquet/crates/package-manager/src/overrides.rs (1)

40-46: LGTM!

Also applies to: 96-96, 105-113, 222-223, 261-262, 306-315

pacquet/crates/package-manager/src/overrides/tests.rs (1)

332-397: LGTM!

pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs (1)

1245-1249: LGTM!

pnpm11/core/core-loggers/src/all.ts (1)

25-25: LGTM!

pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts (1)

3-27: LGTM!

Also applies to: 55-76, 97-124, 154-157

pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts (1)

1-1: LGTM!

Also applies to: 48-56, 76-76

pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts (1)

770-805: LGTM!

Also applies to: 807-830

pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts (1)

397-397: LGTM!

Also applies to: 412-424

pnpm11/installing/deps-installer/src/parseWantedDependencies.ts (1)

17-17: LGTM!

Also applies to: 63-63

pnpm11/installing/deps-installer/src/install/index.ts (1)

22-22: LGTM!

Also applies to: 187-191, 332-332, 888-888, 1659-1678, 2079-2082

Comment thread pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs Outdated
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 851747d

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

Commit: 1aeb5760331d

Each scenario reports direct installs and pnpr installs. Bencher consumes pacquet@HEAD and pnpr@HEAD.

Scenario: Isolated linker: fresh restore, cold cache + cold store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.169 ± 0.134 3.952 4.405 2.00 ± 0.11
pacquet@main 4.119 ± 0.140 3.959 4.355 1.97 ± 0.11
pnpr@HEAD 2.156 ± 0.091 2.042 2.360 1.03 ± 0.06
pnpr@main 2.087 ± 0.092 1.972 2.311 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.16868080266,
      "stddev": 0.133943565602734,
      "median": 4.14392184696,
      "user": 3.89087612,
      "system": 3.5588280800000005,
      "min": 3.95207117096,
      "max": 4.4048922049599994,
      "times": [
        4.4048922049599994,
        4.020061140959999,
        3.95207117096,
        4.25095996796,
        4.310122177959999,
        4.1534007619599995,
        4.10490600896,
        4.131914504959999,
        4.22403715596,
        4.13444293196
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.11925980016,
      "stddev": 0.13983223972364447,
      "median": 4.06852027146,
      "user": 3.93612612,
      "system": 3.5214041799999998,
      "min": 3.9590824709600003,
      "max": 4.35538326896,
      "times": [
        4.35538326896,
        4.06803436196,
        4.281362608959999,
        4.06900618096,
        4.270561798959999,
        4.048864507959999,
        3.9590824709600003,
        4.16006653096,
        4.00176964996,
        3.9784666219600004
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.15567304506,
      "stddev": 0.09132443142811597,
      "median": 2.15660872496,
      "user": 2.65027262,
      "system": 3.07506358,
      "min": 2.04194707696,
      "max": 2.36035574896,
      "times": [
        2.10351079496,
        2.15588412496,
        2.15733332496,
        2.1125198539600003,
        2.06038045296,
        2.36035574896,
        2.16428964196,
        2.23572926296,
        2.16478016796,
        2.04194707696
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.08692160666,
      "stddev": 0.09174410591007412,
      "median": 2.07483364046,
      "user": 2.74851052,
      "system": 3.0520321800000003,
      "min": 1.97208841696,
      "max": 2.3108907269600003,
      "times": [
        2.10925918596,
        2.02003329396,
        2.11072013496,
        2.07139590496,
        2.3108907269600003,
        2.11799644796,
        2.06212439996,
        2.0164361789600003,
        1.97208841696,
        2.07827137596
      ]
    }
  ]
}

Scenario: Isolated linker: fresh restore, hot cache + hot store

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 640.8 ± 13.4 627.4 665.1 1.00
pacquet@main 655.6 ± 14.8 637.3 674.9 1.02 ± 0.03
pnpr@HEAD 709.7 ± 47.2 679.2 839.3 1.11 ± 0.08
pnpr@main 705.4 ± 19.5 679.3 735.4 1.10 ± 0.04
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.6407822328,
      "stddev": 0.013381232246980856,
      "median": 0.6329463115,
      "user": 0.37099956,
      "system": 1.3295766199999999,
      "min": 0.6274353570000001,
      "max": 0.665098917,
      "times": [
        0.631167932,
        0.658114378,
        0.649763799,
        0.6482422600000001,
        0.633330876,
        0.632561747,
        0.6315650030000001,
        0.630542059,
        0.665098917,
        0.6274353570000001
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.6556018987999999,
      "stddev": 0.014799383581493991,
      "median": 0.6570514645000001,
      "user": 0.39643766,
      "system": 1.32741652,
      "min": 0.63728965,
      "max": 0.6749176990000001,
      "times": [
        0.661780008,
        0.6630476790000001,
        0.652322921,
        0.6683535650000001,
        0.674685725,
        0.638867563,
        0.6433178940000001,
        0.63728965,
        0.6414362840000001,
        0.6749176990000001
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.7097334686000002,
      "stddev": 0.047175419793648914,
      "median": 0.6967262275,
      "user": 0.38887205999999996,
      "system": 1.36557152,
      "min": 0.6792370910000001,
      "max": 0.839312218,
      "times": [
        0.7165084610000001,
        0.7072100250000001,
        0.696402403,
        0.681596602,
        0.697050052,
        0.6792370910000001,
        0.707542627,
        0.689200009,
        0.839312218,
        0.683275198
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.7053561844,
      "stddev": 0.019509896808298365,
      "median": 0.6962420840000001,
      "user": 0.40601376,
      "system": 1.35054092,
      "min": 0.6792978540000001,
      "max": 0.735370717,
      "times": [
        0.728808293,
        0.6939755470000001,
        0.696104107,
        0.7107639530000001,
        0.6928485400000001,
        0.690369813,
        0.6792978540000001,
        0.696380061,
        0.7296429590000001,
        0.735370717
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, cold cache + cold store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.294 ± 0.049 4.233 4.404 1.95 ± 0.13
pacquet@main 4.270 ± 0.054 4.171 4.329 1.94 ± 0.13
pnpr@HEAD 2.198 ± 0.142 2.038 2.433 1.00
pnpr@main 2.262 ± 0.157 2.033 2.507 1.03 ± 0.10
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.293949263780001,
      "stddev": 0.04871058718646163,
      "median": 4.28951135298,
      "user": 3.77709756,
      "system": 3.4390345399999993,
      "min": 4.23259565498,
      "max": 4.40375629998,
      "times": [
        4.40375629998,
        4.29642900698,
        4.23259565498,
        4.275451980980001,
        4.29226605498,
        4.29390791398,
        4.33580834998,
        4.28616480398,
        4.28675665098,
        4.23635592098
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.27026965258,
      "stddev": 0.054380512164978224,
      "median": 4.28322527348,
      "user": 3.8345341599999996,
      "system": 3.41553754,
      "min": 4.17094705298,
      "max": 4.32904667998,
      "times": [
        4.27620621298,
        4.2902443339800005,
        4.2507426529800005,
        4.32134936298,
        4.32904667998,
        4.31428060998,
        4.17094705298,
        4.30620226898,
        4.25307595798,
        4.190601392980001
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.19836771718,
      "stddev": 0.14210232023070543,
      "median": 2.15935166648,
      "user": 2.5026945599999992,
      "system": 2.9390676399999998,
      "min": 2.0376892519800003,
      "max": 2.43284071398,
      "times": [
        2.0376892519800003,
        2.1201758069800003,
        2.13463997798,
        2.18406335498,
        2.08696491998,
        2.2193128529800004,
        2.3759569329800003,
        2.04408842598,
        2.34794493398,
        2.43284071398
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.26235772468,
      "stddev": 0.1565452637247315,
      "median": 2.2593846619800004,
      "user": 2.5396353599999997,
      "system": 2.9491378399999997,
      "min": 2.0328211779800003,
      "max": 2.50657754698,
      "times": [
        2.50657754698,
        2.2961625269800003,
        2.22260679698,
        2.40025212798,
        2.41805125098,
        2.1249908159800004,
        2.0328211779800003,
        2.35703498098,
        2.11369247898,
        2.1513875429800002
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, hot cache + hot store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 1.385 ± 0.022 1.360 1.419 2.01 ± 0.12
pacquet@main 1.445 ± 0.093 1.404 1.707 2.09 ± 0.18
pnpr@HEAD 0.690 ± 0.041 0.661 0.803 1.00
pnpr@main 0.701 ± 0.007 0.693 0.714 1.02 ± 0.06
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 1.38528570524,
      "stddev": 0.02195531174656638,
      "median": 1.38187767364,
      "user": 1.3471852599999998,
      "system": 1.7385469000000005,
      "min": 1.36041071014,
      "max": 1.41883803114,
      "times": [
        1.3816396481400002,
        1.37999506614,
        1.39977273914,
        1.39051428714,
        1.41830015514,
        1.38211569914,
        1.41883803114,
        1.36041071014,
        1.36053894514,
        1.36073177114
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 1.44497100424,
      "stddev": 0.09266218047578534,
      "median": 1.41449759514,
      "user": 1.4306212600000001,
      "system": 1.7396957,
      "min": 1.40436367414,
      "max": 1.7072796221400002,
      "times": [
        1.40611205414,
        1.7072796221400002,
        1.40436367414,
        1.43221762214,
        1.43154982014,
        1.4087846881400001,
        1.41488428114,
        1.4190613811400001,
        1.41134599014,
        1.4141109091400001
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6902997656400001,
      "stddev": 0.04104560865170669,
      "median": 0.68008793314,
      "user": 0.36034675999999993,
      "system": 1.3146198999999998,
      "min": 0.6612679921400001,
      "max": 0.80288716114,
      "times": [
        0.6642187111400001,
        0.6612679921400001,
        0.67706763114,
        0.80288716114,
        0.67122325514,
        0.7004626021400001,
        0.67915441214,
        0.6827517201400001,
        0.6829427171400001,
        0.68102145414
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.70105155054,
      "stddev": 0.006636792097374372,
      "median": 0.6993794561400001,
      "user": 0.37132405999999996,
      "system": 1.3195823,
      "min": 0.69270388114,
      "max": 0.71357842814,
      "times": [
        0.69876388314,
        0.7057012231400001,
        0.7080430901400001,
        0.6983465761400001,
        0.6949546001400001,
        0.6999950291400001,
        0.71357842814,
        0.70378200814,
        0.69270388114,
        0.6946467861400001
      ]
    }
  ]
}

Scenario: Isolated linker: fresh install, cold cache + hot store

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 3.104 ± 0.032 3.039 3.150 4.64 ± 0.06
pacquet@main 3.100 ± 0.053 3.060 3.235 4.63 ± 0.09
pnpr@HEAD 0.673 ± 0.008 0.656 0.682 1.01 ± 0.01
pnpr@main 0.669 ± 0.006 0.661 0.682 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 3.1038544881600005,
      "stddev": 0.032276522575814495,
      "median": 3.1118689120600003,
      "user": 1.8802692,
      "system": 2.0068132599999995,
      "min": 3.03916239006,
      "max": 3.14995106906,
      "times": [
        3.10857239106,
        3.12146997906,
        3.12683108006,
        3.08954554606,
        3.11516543306,
        3.06740234506,
        3.12543702506,
        3.09500762306,
        3.14995106906,
        3.03916239006
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 3.09958016736,
      "stddev": 0.05251111006294535,
      "median": 3.08400828656,
      "user": 1.8782501999999996,
      "system": 2.00457676,
      "min": 3.05970867206,
      "max": 3.23546876806,
      "times": [
        3.06026981706,
        3.12758561806,
        3.09565704806,
        3.08775788706,
        3.08025868606,
        3.05970867206,
        3.0764305100600002,
        3.10887451206,
        3.23546876806,
        3.06379015506
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6726700583599999,
      "stddev": 0.007933273368760124,
      "median": 0.67528988606,
      "user": 0.3503283,
      "system": 1.2967594599999999,
      "min": 0.65560933706,
      "max": 0.68209884806,
      "times": [
        0.67833154706,
        0.67782088906,
        0.67734619806,
        0.6757666530599999,
        0.67089609206,
        0.65560933706,
        0.67481311906,
        0.68209884806,
        0.67051512306,
        0.66350277706
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.66877106296,
      "stddev": 0.005888958424990845,
      "median": 0.66834904856,
      "user": 0.35915909999999995,
      "system": 1.2909376599999998,
      "min": 0.66051598206,
      "max": 0.68188730506,
      "times": [
        0.66943100806,
        0.66051598206,
        0.66801943306,
        0.67371862206,
        0.66806688206,
        0.66601623706,
        0.66257852906,
        0.66884541606,
        0.66863121506,
        0.68188730506
      ]
    }
  ]
}

Scenario: Isolated linker: fresh restore, cold cache + cold store + cold pnpr

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 7.009 ± 0.211 6.656 7.359 1.42 ± 0.05
pacquet@main 6.962 ± 0.192 6.669 7.354 1.41 ± 0.05
pnpr@HEAD 4.928 ± 0.081 4.793 5.077 1.00
pnpr@main 5.019 ± 0.122 4.875 5.189 1.02 ± 0.03
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 7.009224038779999,
      "stddev": 0.21106622753079357,
      "median": 7.010334437379999,
      "user": 4.05151686,
      "system": 3.81722786,
      "min": 6.65607629188,
      "max": 7.35875186688,
      "times": [
        7.35875186688,
        6.89827836088,
        6.89331987788,
        7.0435282708799996,
        7.0077820078799995,
        6.65607629188,
        7.26543028588,
        7.1506369758799995,
        6.8055495828799994,
        7.01288686688
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 6.9621410808799995,
      "stddev": 0.19151735348320487,
      "median": 6.93441826388,
      "user": 4.104301659999999,
      "system": 3.8288200599999995,
      "min": 6.66861324988,
      "max": 7.35378279388,
      "times": [
        6.95489732188,
        6.66861324988,
        6.91393920588,
        7.06675405688,
        7.1014373618799995,
        6.86491808388,
        7.0548835168799995,
        6.8221452958799995,
        7.35378279388,
        6.820039921879999
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 4.92817907598,
      "stddev": 0.08055977294949718,
      "median": 4.91522161038,
      "user": 2.76667846,
      "system": 3.2878508600000003,
      "min": 4.79281696188,
      "max": 5.07694778788,
      "times": [
        4.91972589488,
        5.00341662488,
        4.91071732588,
        4.94521095488,
        4.79281696188,
        4.99243625088,
        4.89979580688,
        5.07694778788,
        4.87215012388,
        4.86857302788
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 5.019213050179999,
      "stddev": 0.1220644989563262,
      "median": 5.016426818879999,
      "user": 2.83147276,
      "system": 3.29032646,
      "min": 4.87483077588,
      "max": 5.189391307879999,
      "times": [
        4.87483077588,
        5.09439130888,
        4.98003972488,
        4.92919502988,
        5.16889305388,
        4.90057788788,
        4.87704253188,
        5.189391307879999,
        5.12495496788,
        5.05281391288
      ]
    }
  ]
}

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12741
Testbedpacquet
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
milliseconds (ms)
(Result Δ%)
Upper Boundary
milliseconds (ms)
(Limit %)
isolated-linker.fresh-install.cold-cache.cold-store📈 view plot
🚷 view threshold
4,293.95 ms
(-4.88%)Baseline: 4,514.01 ms
5,416.81 ms
(79.27%)
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
🚷 view threshold
3,103.85 ms
(+1.42%)Baseline: 3,060.42 ms
3,672.50 ms
(84.52%)
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
🚷 view threshold
1,385.29 ms
(+1.54%)Baseline: 1,364.23 ms
1,637.07 ms
(84.62%)
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
🚷 view threshold
4,168.68 ms
(-5.22%)Baseline: 4,398.33 ms
5,278.00 ms
(78.98%)
isolated-linker.fresh-restore.cold-cache.cold-store.cold-pnpr📈 view plot
🚷 view threshold
7,009.22 ms
(-1.31%)Baseline: 7,102.28 ms
8,522.73 ms
(82.24%)
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
🚷 view threshold
640.78 ms
(+1.86%)Baseline: 629.10 ms
754.92 ms
(84.88%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12741
Testbedpnpr

⚠️ WARNING: No Threshold found!

Without a Threshold, no Alerts will ever be generated.

Click here to create a new Threshold
For more information, see the Threshold documentation.
To only post results if a Threshold exists, set the --ci-only-thresholds flag.

Click to view all benchmark results
BenchmarkLatencymilliseconds (ms)
isolated-linker.fresh-install.cold-cache.cold-store📈 view plot
⚠️ NO THRESHOLD
2,198.37 ms
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
672.67 ms
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
690.30 ms
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
⚠️ NO THRESHOLD
2,155.67 ms
isolated-linker.fresh-restore.cold-cache.cold-store.cold-pnpr📈 view plot
⚠️ NO THRESHOLD
4,928.18 ms
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
709.73 ms
🐰 View full continuous benchmarking report in Bencher

@aqeelat aqeelat force-pushed the feat/warn-unused-overrides branch from 851747d to 0436da5 Compare June 30, 2026 12:13
Comment on lines 186 to 193
// When a pnpr server is configured, use server-side resolution
// instead of the normal resolution flow.
// instead of the normal resolution flow. The pnpr protocol resolves
// with overrides but does not report which selectors matched, so
// the unused-override warning is silently skipped on this path —
// an acceptable tradeoff to preserve pnpr's performance benefit.
if (opts.pnprServer) {
return installViaPnprServer(manifest, rootDir, opts)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Pnprserver skips unused-override warning 📎 Requirement gap ≡ Correctness

When pnprServer is configured, pnpm install returns via the pnpr-server path and the new
unused-override warning is explicitly skipped. This violates the requirement to warn on unused
overrides during pnpm i, allowing silent misconfiguration in this mode.
Agent Prompt
## Issue description
The unused-override warning is skipped when `opts.pnprServer` is set, so `pnpm install` can run with unused `overrides` without emitting any warning.

## Issue Context
The PR introduces unused override detection and reporting, but the pnpr-server install path currently bypasses it (and a test asserts this behavior).

## Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[186-193]
- pnpm11/pnpm/test/install/pnpmRegistry.ts[97-122]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 0436da5

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Looking for bugs?

Check back in a few minutes. Qodo's review agents are on it.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpm11/installing/deps-installer/src/install/index.ts`:
- Around line 187-190: The pnpr install path in install/index.ts is skipping
unusedOverride reporting entirely, so the new warning is never emitted when
pnprServer handles resolution. Update the pnpr flow used by the install logic
(the branches around the pnprServer resolution path) so matched selectors are
available for unusedOverride, either by propagating the selector matches back
from pnpr or by falling back to the client-side resolver when warning
correctness is required. Make sure the same fix covers the other pnpr-related
branch referenced in the diff as well.

In `@pnpm11/pnpm/test/install/pnpmRegistry.ts`:
- Around line 97-122: The test in pnpmRegistry.ts does not actually cover an
unused override, so it cannot verify the skipped warning behavior. Update the
setup in test('pnpm install with overrides uses pnpr server and skips
unused-override warning', ...) so the overrides entry does not match any
installed dependency, then keep the execPnpm call with pnprServer and assert the
install still succeeds without emitting the unused-override warning. Use the
existing helpers prepareProject, writeYamlFileSync, and execPnpm to keep the
test focused on the pnpr server path and the warning behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: aad27078-6c1d-41b7-b5d6-057d030c1627

📥 Commits

Reviewing files that changed from the base of the PR and between 851747d and 0436da5.

📒 Files selected for processing (25)
  • .changeset/warn-unused-overrides.md
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pnpm11/cli/default-reporter/src/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/core/core-loggers/src/index.ts
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pnpm11/installing/deps-installer/src/install/index.ts
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pnpm11/pnpm/test/utils/execPnpm.ts
✅ Files skipped from review due to trivial changes (3)
  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/core/core-loggers/src/index.ts
  • .changeset/warn-unused-overrides.md
🚧 Files skipped from review as they are similar to previous changes (19)
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pnpm11/cli/default-reporter/src/index.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pacquet/crates/reporter/src/tests.rs
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts

Comment thread pnpm11/installing/deps-installer/src/install/index.ts Outdated
Comment thread pnpm11/pnpm/test/install/pnpmRegistry.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpm11/installing/deps-installer/src/install/index.ts`:
- Around line 2697-2699: Update depEntryMatches() so selector matching does not
compare the post-override resolved version against the selector range for
pnpr-style scoped selectors like foo@^1: 2.0.0; instead use the matched selector
metadata from pnpr, the original requested range, or a fallback that recognizes
range-scoped selectors before deciding whether the override is unused. Make the
fix in the selector/range handling around depEntryMatches() and the related
override warning path it feeds, then add a regression test covering foo@^1
resolving to 2.0.0 so the warning fails without the fix.
- Around line 2640-2644: The parent-version filtering in the install flow is too
permissive: in the package scan inside the install logic, an entry from
nameVerFromPkgSnapshot() with no version is currently allowed through even when
parentRange is set, which can hide an unused-override warning. Update the
conditional around the parentName/parentRange checks so unknown versions are not
treated as matching a range; only continue past the selector when the version is
present and semver.satisfies() returns true, and otherwise let the warning path
run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1879f977-4967-4ada-bc91-46e1acf88c73

📥 Commits

Reviewing files that changed from the base of the PR and between 0436da5 and c9c467f.

📒 Files selected for processing (2)
  • pnpm11/installing/deps-installer/src/install/index.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts

Comment thread pnpm11/installing/deps-installer/src/install/index.ts Outdated
Comment thread pnpm11/installing/deps-installer/src/install/index.ts Outdated
Comment on lines +2689 to +2699
function depEntryMatches (
deps: Record<string, string> | undefined,
targetName: string,
targetRange: string | undefined
): boolean {
if (deps == null) return false
const version = deps[targetName]
if (version == null) return false
if (targetRange == null) return true
if (!semver.valid(version)) return true
return semver.satisfies(version, targetRange)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Range match false negatives 🐞 Bug ≡ Correctness

In pnpr-server mode, depEntryMatches() treats any non-semver lockfile version string as a match when
an override selector has a version range, so version-scoped overrides (e.g. foo@^1) can be
considered applied even when the resolved version does not satisfy the range, suppressing the
unused-override warning. This is common because lockfile versions can include peer suffixes like
"3.4.1(ajv@6.10.2)" which semver.valid() rejects.
Agent Prompt
### Issue description
`depEntryMatches()` currently returns `true` for any non-semver `version` string when `targetRange` is set. In pnpm lockfiles, resolved versions frequently include peer suffixes (e.g. `3.4.1(ajv@6.10.2)`), plus other non-semver forms (`link:`, `npm:` aliases). This causes version-scoped override selectors to be treated as “applied” just because the dependency key exists, which suppresses the new unused-override warning.

### Issue Context
The pnpr-server path relies on `findAppliedOverrideSelectorsFromLockfile()` to infer which override selectors matched since server-side resolution does not report selectors.

### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[2689-2700]

### Suggested fix
- When `targetRange` is set:
  - Extract a comparable semver from the lockfile value rather than treating non-semver as a match.
    - For peer suffixes, a simple and accurate approach is `const base = version.split('(')[0]` and then `semver.valid(base)`.
  - Return `false` (not a match) for non-semver protocols like `link:`, `file:`, `npm:` unless you have a deliberate, proven mapping that matches pnpm’s override-selector semantics.
- Keep the existing fast-path `targetRange == null => true` for name-only selectors.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +2640 to +2644
for (const [depPath, snapshot] of Object.entries(lockfile.packages ?? {}) as Array<[DepPath, PackageSnapshot]>) {
const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot)
if (name !== parentName) continue
if (parentRange != null && version != null && !semver.satisfies(version, parentRange)) continue
if (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Unhandled invalid selector ranges 🐞 Bug ☼ Reliability

The pnpr-server lockfile scan calls semver.satisfies() with selector bareSpecifiers that are not
validated as semver ranges; selectors like foo@latest can reach this code and may throw, crashing
installs (repo-controlled DoS). The local override matcher guards semver operations with
semver.validRange(), but this scan does not.
Agent Prompt
### Issue description
`findAppliedOverrideSelectorsFromLockfile()` and `depEntryMatches()` call `semver.satisfies(version, range)` on `range` values derived from override selectors. Override selector parsing does not semver-validate `bareSpecifier`, so non-semver strings (e.g. `latest`) can reach this code and may crash the install.

### Issue Context
- `parseWantedDependency()` returns the raw substring after `@` as `bareSpecifier` without semver validation.
- The normal override-application logic (`isIntersectingRange`) explicitly checks `semver.validRange()` before using semver range logic.

### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[2640-2644]
- pnpm11/installing/deps-installer/src/install/index.ts[2689-2700]

### Suggested fix
- Before calling `semver.satisfies(...)`:
  - If `range` is not a valid semver range (`semver.validRange(range) == null`), treat it as non-matching (return `false` / skip) to align with `isIntersectingRange()` behavior.
  - Optionally wrap `semver.satisfies` in a try/catch as a belt-and-suspenders guard, logging debug if needed.
- Apply this guard for both:
  - `parentRange` check in the parent-scoped branch, and
  - `targetRange` checks in `depEntryMatches()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit c9c467f

Comment on lines +2637 to +2653
if (override.parentPkg != null) {
const parentName = override.parentPkg.name
const parentRange = override.parentPkg.bareSpecifier
for (const [depPath, snapshot] of Object.entries(lockfile.packages ?? {}) as Array<[DepPath, PackageSnapshot]>) {
const { name, version } = nameVerFromPkgSnapshot(depPath, snapshot)
if (name !== parentName) continue
if (parentRange != null && version != null && !semver.satisfies(version, parentRange)) continue
if (
depEntryMatches(snapshot.dependencies, targetName, targetRange) ||
depEntryMatches(snapshot.optionalDependencies, targetName, targetRange) ||
depEntryMatches(snapshot.peerDependencies, targetName, targetRange)
) {
applied.add(override.selector)
break
}
}
} else {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Pnpr parent override false warnings 🐞 Bug ≡ Correctness

In pnpr-server mode, findAppliedOverrideSelectorsFromLockfile() considers parent-scoped overrides
matched only when the parent name is found in package snapshots, so parent-scoped overrides that
apply to workspace project/importer manifests (e.g. my-app>dep) can be incorrectly logged as
unused.
Agent Prompt
### Issue description
`findAppliedOverrideSelectorsFromLockfile()` checks `lockfile.packages` for parent-scoped overrides, but does not account for the case where the parent package is a workspace project (an importer manifest). Since lockfile importer snapshots do not include package `name`/`version`, the current scan cannot detect that `parentPkg` matches a project manifest, and may emit false `pnpm:unusedOverride` logs.

### Issue Context
- Parent-scoped overrides in the local resolver path match against `manifest.name`/`manifest.version` (including project manifests).
- The pnpr-server path tries to reconstruct “applied overrides” by scanning the resolved lockfile.

### Fix Focus Areas
- pnpm11/installing/deps-installer/src/install/index.ts[2616-2676]
- pnpm11/lockfile/types/src/index.ts[68-78]
- pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts[34-45]

### Suggested fix
- Extend the pnpr-server scan to also treat workspace project manifests as possible `parentPkg` matches:
  - In `installViaPnprServer()`, you already have `manifest` and optionally `allInstallProjects`.
  - For each project whose `manifest.name` matches `override.parentPkg.name` (and version satisfies `parentPkg.bareSpecifier` when present), look up that project’s importer snapshot (`lockfile.importers[importerId]`) and check whether it contains the target dependency key (and range logic as appropriate).
  - Keep the existing `lockfile.packages` scan for parent packages that are real resolved packages.
- Consider adjusting the helper signature to accept `{ importerId, manifest }[]` so parent-scoped overrides can be validated against importers without guessing parent identity from the lockfile.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit c9c467f

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpm11/installing/deps-installer/test/install/unusedOverrideScan.ts`:
- Around line 7-156: The current tests only cover the lockfile helper and miss
the install-time warning flow, so add an install e2e regression test around the
unused override warning path. Exercise the install command and verify that
pnpm:unusedOverride is emitted only for truly unused overrides, is buffered
until resolution_done, and appears in the grouped WARN output. Use the existing
unusedOverrideScan-related behavior as a guide, and place the test where it
covers the user-visible install logging rather than just the helper internals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e9f66f3-0666-4cef-9890-b40d01270cf8

📥 Commits

Reviewing files that changed from the base of the PR and between c9c467f and 2779a89.

📒 Files selected for processing (2)
  • pnpm11/installing/deps-installer/src/install/index.ts
  • pnpm11/installing/deps-installer/test/install/unusedOverrideScan.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • pnpm11/installing/deps-installer/src/install/index.ts

Comment thread pnpm11/installing/deps-installer/test/install/unusedOverrideScan.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 2779a89

1 similar comment
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 2779a89

Copilot AI review requested due to automatic review settings July 1, 2026 11:25
@aqeelat aqeelat force-pushed the feat/warn-unused-overrides branch from 2779a89 to 1b5e4b0 Compare July 1, 2026 11:25
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 1b5e4b0

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 1b5e4b0

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit b744003

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Comment on lines +464 to +472
let selectors = std::mem::take(&mut self.pending_unused_overrides);
let sanitized: Vec<String> =
selectors.iter().map(|s| sanitize_override_selector(s)).collect();
let head = if sanitized.len() == 1 {
"1 override matched no dependency".to_string()
} else {
format!("{} overrides matched no dependency", sanitized.len())
};
self.push_warning(&format!("{}: {}", head, sanitized.join(", ")));

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts (1)

39-105: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated dependency-group scanning between parent-scoped and generic branches.

The parent-scoped branch (importer/package loops at Lines 44-67 and 70-82) and the generic branch (Lines 84-93, 95-104) repeat nearly identical depEntryMatches checks across dependencies/devDependencies/optionalDependencies/peerDependencies. Extracting a small shared helper (e.g. matchesAnyGroup(entry, targetName, groups)) would reduce duplication and lower the risk of the two branches silently diverging on a future edit.

♻️ Sketch of a shared helper
+function matchesDependencyGroups (
+  groups: Array<Record<string, string> | undefined>,
+  targetName: string
+): boolean {
+  return groups.some((deps) => depEntryMatches(deps, targetName))
+}

Then both branches can call matchesDependencyGroups([importer.dependencies, importer.devDependencies, importer.optionalDependencies], targetName) etc., instead of repeating the three-way || chain.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts` around
lines 39 - 105, The parent-scoped and generic paths in findAppliedOverrides
duplicate the same depEntryMatches logic across dependency groups, making the
two branches easy to drift apart. Extract a small shared helper near
findAppliedOverrides (for example, one that checks a list of dependency maps
against targetName) and use it in both the importer/package snapshot loops and
the generic importer/package snapshot loops so the matching rules stay identical
and easier to maintain.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpm11/installing/deps-installer/src/install/index.ts`:
- Around line 1662-1681: The unused-override check in the install flow is
comparing the lockfile importer count against the mutated projects list, which
can misidentify partial installs as full reanalysis. Update the condition in the
`index.ts` install logic to use `ctx.projects` instead of `projects`, matching
the `tryFrozenInstall` gate and the selected workspace set after
`pruneLockfileImporters` has trimmed `ctx.wantedLockfile.importers`.

---

Nitpick comments:
In `@pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts`:
- Around line 39-105: The parent-scoped and generic paths in
findAppliedOverrides duplicate the same depEntryMatches logic across dependency
groups, making the two branches easy to drift apart. Extract a small shared
helper near findAppliedOverrides (for example, one that checks a list of
dependency maps against targetName) and use it in both the importer/package
snapshot loops and the generic importer/package snapshot loops so the matching
rules stay identical and easier to maintain.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3de42aa5-2f6d-4bc2-a811-e342068ff9bd

📥 Commits

Reviewing files that changed from the base of the PR and between 093c536 and b744003.

📒 Files selected for processing (27)
  • .changeset/warn-unused-overrides.md
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/default-reporter/tests/render.rs
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/reporter/src/lib.rs
  • pacquet/crates/reporter/src/tests.rs
  • pnpm11/cli/default-reporter/src/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/core/core-loggers/src/index.ts
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts
  • pnpm11/hooks/read-package-hook/test/createVersionOverrider.test.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pnpm11/installing/deps-installer/src/install/findAppliedOverrides.ts
  • pnpm11/installing/deps-installer/src/install/index.ts
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pnpm11/installing/deps-installer/test/install/unusedOverrideScan.ts
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pnpm11/pnpm/test/utils/execPnpm.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/warn-unused-overrides.md
🚧 Files skipped from review as they are similar to previous changes (22)
  • pnpm11/installing/deps-installer/src/parseWantedDependencies.ts
  • pnpm11/core/core-loggers/src/index.ts
  • pnpm11/core/core-loggers/src/all.ts
  • pnpm11/pnpm/test/install/unusedOverrides.ts
  • pacquet/crates/reporter/src/lib.rs
  • pnpm11/cli/default-reporter/src/reporterForClient/index.ts
  • pnpm11/installing/deps-installer/src/install/extendInstallOptions.ts
  • pnpm11/core/core-loggers/src/unusedOverrideLogger.ts
  • pnpm11/installing/deps-installer/test/install/overrides.ts
  • pacquet/crates/default-reporter/tests/render.rs
  • pnpm11/cli/default-reporter/src/index.ts
  • pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs
  • pnpm11/pnpm/test/install/pnpmRegistry.ts
  • pnpm11/cli/default-reporter/test/reportingUnusedOverrides.ts
  • pnpm11/installing/deps-installer/test/install/unusedOverrideScan.ts
  • pnpm11/hooks/read-package-hook/src/createReadPackageHook.ts
  • pacquet/crates/default-reporter/src/state.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts
  • pacquet/crates/reporter/src/tests.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pnpm11/hooks/read-package-hook/src/createVersionsOverrider.ts

Comment thread pnpm11/installing/deps-installer/src/install/index.ts
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit b744003

aqeelat added 7 commits July 3, 2026 01:01
Emits a pnpm:unusedOverride log for each override selector that matched
no resolved package during a fresh install. The default reporter buffers
these until the resolution_done stage and renders a single grouped WARN
line (e.g. '[WARN] 2 overrides matched no dependency: foo, parent>child').

Closes pnpm#10315.

TypeScript (pnpm):
- New pnpm:unusedOverride logger channel (core-loggers).
- createVersionsOverrider accepts onApplied callback; createReadPackageHook
  threads it as onOverrideApplied. Backward-compat VersionOverrideWithoutRawSelector
  alias kept for external consumers.
- Installer diffs parsed overrides against applied set after full resolution;
  gate mirrors verifyPatches (forceFullResolution || empty lockfile).
- Direct-add path (parseWantedDependencies) records applied overrides too.
- Default reporter sanitizes control characters from selectors at render time;
  raw selectors stay intact in structured events.
- pnpr-server path preserved with overrides (warning silently skipped since
  pnpr doesn't report matched selectors).
- ramda isEmpty used for emptiness gate instead of Object.keys().length.

Pacquet (Rust port):
- VersionsOverrider records applied selectors via Arc<Mutex<HashSet>>;
  record_applied checks contains before cloning.
- install_with_fresh_lockfile gates the diff on lockfile_for_reuse.is_none()
  (subtree reuse bypasses manifest_hook, so applied_selectors is incomplete).
- UnusedOverride events emitted sorted before ResolutionDone.
- Default reporter buffers and renders at resolution_done; control characters
  stripped at render; sort at emission only (no double sort).
- Wire-shape test and render tests for the new event channel.
…ckfile scan

The pnpr protocol resolves with overrides but does not report which
selectors matched. After pnpr resolves, scan the lockfile to determine
which override selectors matched at least one dependency, then emit
unused-override events for unmatched selectors — same behavior as the
local-resolver path.

Also fix the e2e test to include an actual unused override and verify
the warning is emitted. Use spawnPnpm (async) to capture stdout without
deadlocking the counting proxy's event loop.
…g, and project manifests

Don't compare post-override resolved versions against selector ranges —
the lockfile stores post-override values, so comparing them against the
old selector range produces false positives (e.g. foo@^1: 2.0.0 resolves
to 2.0.0, which doesn't satisfy ^1). depEntryMatches now checks name
presence only; the selector range was already applied during resolution.

Guard semver.satisfies with semver.validRange for parentPkg.bareSpecifier
— non-semver strings like 'latest' can reach this code via override
selectors and produce unexpected results, matching isIntersectingRange's
guard in the local resolver path.

Fix parent-version filtering: an absent version with a parent range set
must NOT pass through (previously version == null short-circuited the
AND chain, letting unknown-version packages through).

Extend parent-scoped override matching to also check workspace project
manifests (importers), not just resolved packages. Importer snapshots
don't carry name/version, so the scan now accepts a projectManifests
list mapping importer IDs to manifests, letting parent-scoped overrides
match project names like my-app>foo.

Adds unit tests covering cross-version scoped overrides, genuinely
unused overrides, absent parent versions, workspace-project parents,
and non-semver parent ranges.
… assertion

Collect chars directly into String instead of mapping to String per
char. Check HashSet size and membership directly instead of collecting
into a Vec of references to temporaries.
…ing, hoist enumerations

Rename pnpm:unusedOverride to pnpm:unused-override to match the
kebab-case convention used by every other multi-word pnpm log channel
(e.g. fetching-progress, package-manifest, lockfile-verification).
Updated across TS logger, reporter, tests, and pacquet serde mapping.

Add C1 control range (0x80-0x9F) to the TS sanitizeSelector regex;
Rust is already covered by char::is_control().

Add proc.on('error', reject) to the test spawnPnpm wrapper so spawn
failures fail fast instead of timing out.

Hoist Object.values/entries(lockfile.importers/packages) out of the
override loop in findAppliedOverrideSelectorsFromLockfile — they are
invariant across iterations.
…parent range

Fix stale pnpm:unusedOverride reference in the changeset — the actual
channel name is pnpm:unused-override (kebab-case).

Move findAppliedOverrideSelectorsFromLockfile to a new internal module
(src/install/findAppliedOverrides.ts) so api.ts's export * from
install/index.js no longer exposes it as public API. The unit test
imports from the new module directly.

Guard semver.satisfies with semver.validRange and manifest.version !=
null in createVersionsOverrider's parent-scoped filter. Non-semver
bareSpecifiers like 'latest' are treated as non-matching instead of
potentially throwing. Adds a regression test for parent@latest>child.
Lockfile importer snapshots don't carry peerDependencies, so the
pnpr-server scan missed parent-scoped overrides whose target only
appears in a workspace project's peerDependencies. Check the project
manifest's peerDependencies directly alongside the importer's
dependencies/devDependencies/optionalDependencies.

Adds unit test for the peer-dependency case.
@aqeelat aqeelat force-pushed the feat/warn-unused-overrides branch from b744003 to cae43bd Compare July 2, 2026 22:04
…check helpers

The unused-override gate compared lockfile importer count against
projects.length (the mutation batch), but tryFrozenInstall uses
Object.keys(ctx.projects).length (the full workspace set). In a
partial install (--filter, pnpm add in one project) the batch is a
subset, so the gate could misidentify a partial install as full
reanalysis and emit false warnings. Use ctx.projects to match.

Extract targetInImporter and targetInSnapshot helpers in
findAppliedOverrides to deduplicate the depEntryMatches chains and
keep the importer (deps/devDeps/optionalDeps) vs snapshot
(deps/optionalDeps/peerDeps) group lists explicit and drift-proof.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit cae43bd

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jul 2, 2026

Copy link
Copy Markdown

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

Qodo Logo

Copilot AI review requested due to automatic review settings July 2, 2026 22:08
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit af82991

@github-actions github-actions Bot added the reviewed: coderabbit CodeRabbit submitted an approving review label Jul 2, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit af82991

@aqeelat

aqeelat commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@zkochan Can you please review the PR? It helps keep pnpm-workspace.yaml tidy as it help remove unused overrides. I usually delete the overrides one by one and run install to see if it they were actually changing anything.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 10 comments.

Comment on lines +36 to +39
for (const override of parsedOverrides) {
const targetName = override.targetPkg.name

if (override.parentPkg != null) {
const parentRange = override.parentPkg.bareSpecifier
const parentRangeValid = parentRange == null || semver.validRange(parentRange) != null

for (const { importerId, manifest: projectManifest } of projectManifests) {
}
if (applied.has(override.selector)) continue

for (const [depPath, snapshot] of packageEntries) {
Comment on lines +75 to +76
} else {
for (const importer of importerSnapshots) {
}
}
if (applied.has(override.selector)) continue
for (const snapshot of packageSnapshots) {
Comment on lines +11 to +17
* A selector is considered matched if its target name appears as a
* dependency key in any importer or package snapshot. The target's
* version range (bareSpecifier) is NOT checked against the resolved
* version because the lockfile stores post-override values — the
* override already changed the version, so comparing the new version
* against the old selector range would produce false positives (e.g.
* `foo@^1: 2.0.0` resolves to 2.0.0, which doesn't satisfy ^1).
Comment on lines +458 to +460
/// Selectors arrive pre-sorted from the emission site
/// (`install_with_fresh_lockfile`), so no re-sort is needed here.
fn flush_pending_unused_overrides(&mut self) {
Comment on lines +464 to +466
let selectors = std::mem::take(&mut self.pending_unused_overrides);
let sanitized: Vec<String> =
selectors.iter().map(|s| sanitize_override_selector(s)).collect();
} else {
format!("{} overrides matched no dependency", sanitized.len())
};
self.push_warning(&format!("{}: {}", head, sanitized.join(", ")));
Comment on lines +1034 to +1039
/// Strip ASCII control characters (C0 range 0x00–0x1F and DEL 0x7F)
/// from an override selector before rendering, so a crafted key
/// cannot inject/spoof terminal output.
fn sanitize_override_selector(selector: &str) -> String {
selector.chars().filter(|ch| !ch.is_control()).collect()
}
…c comment

Restore sort_unstable in flush_pending_unused_overrides so the reporter
is resilient to unsorted event order — mirrors the TS reporter which
sorts, and removes the fragile coupling to emission-site ordering.

Fix sanitize_override_selector doc comment: char::is_control() strips
all Unicode control characters (C0, DEL, C1, and other control code
points), not just ASCII C0 + DEL.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 1aeb576

Comment on lines +25 to +41
const resolutionDone$ = log$.stage.pipe(
filter((log) => log.stage === 'resolution_done')
)
return log$.unusedOverride.pipe(
buffer(resolutionDone$),
map((unusedOverrides) => {
if (unusedOverrides.length === 0) return Rx.EMPTY
const selectors = unusedOverrides
.map((log) => sanitizeSelector(log.selector))
.sort()
const head = selectors.length === 1
? '1 override matched no dependency'
: `${selectors.length} overrides matched no dependency`
return Rx.of({
msg: formatWarn(`${head}: ${selectors.join(', ')}`),
})
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Unused overrides buffer ignores prefix 📎 Requirement gap ≡ Correctness

reportUnusedOverrides() buffers all pnpm:unused-override events globally and flushes them on the
first resolution_done stage event without partitioning by log.prefix. In recursive/multi-prefix
runs this can mix selectors across workspaces/lockfileDirs or flush too early, leading to missing,
incorrect, or ambiguous warnings that fail to clearly identify which override selectors matched
nothing.
Agent Prompt
## Issue description
`reportUnusedOverrides()` currently ignores `UnusedOverrideLog.prefix`/`StageLog.prefix`, buffering all `pnpm:unused-override` events together and flushing them on any `resolution_done` stage event. In multi-prefix (recursive) installs this can merge selectors from different workspaces/lockfileDirs or flush before all selectors for a given prefix have arrived, producing missing, incorrect, or context-free warnings.

## Issue Context
- PR Compliance ID 1 requires `pnpm install` to emit a clear warning identifying which override selector(s) matched nothing.
- Each `pnpm:unused-override` (`UnusedOverrideLog`) and `pnpm:stage` (`StageLog`) event includes a `prefix` (workspace root / lockfileDir, typically `ctx.lockfileDir`).
- The warning needs to be accurate per-prefix; other reporters use `log.prefix` to disambiguate output (e.g., via zoom-out/prefix formatting).

## Fix Focus Areas
- pnpm11/cli/default-reporter/src/reporterForClient/reportUnusedOverrides.ts[19-43]
- pnpm11/cli/default-reporter/src/reporterForClient/index.ts[111-119]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +1216 to +1225
if lockfile_for_reuse.is_none()
&& let Some(overrider) = versions_overrider.as_ref()
&& let Some(parsed) = parsed_overrides.as_ref()
{
let applied = overrider.applied_selectors();
let mut unused: Vec<&str> = parsed
.iter()
.map(|override_entry| override_entry.selector.as_str())
.filter(|selector| !applied.contains(*selector))
.collect();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Pacquet gate skips updates 🐞 Bug ≡ Correctness

pacquet emits unused-override events only when lockfile_for_reuse.is_none(), but
UpdateReuseScope::None disables reuse (full re-resolve) while lockfile_for_reuse can still be
Some. This suppresses unused-override warnings in full re-resolution flows like pacquet update,
undermining the feature.
Agent Prompt
### Issue description
The unused-override diff is gated by `lockfile_for_reuse.is_none()`, but pacquet can still perform a full re-resolve (no subtree reuse) when `update_reuse_scope` is `UpdateReuseScope::None` even if a prior lockfile exists. In that case `applied_selectors()` should be complete and the warning should run, but currently it is skipped.

### Issue Context
`UpdateReuseScope::None` explicitly means “reuse nothing — the whole graph re-resolves”, and the resolver’s reuse path short-circuits when this scope is set.

### Fix Focus Areas
- pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1048-1110]
- pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs[1202-1234]
- pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs[48-63]
- pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs[2089-2097]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 1aeb576

@zkochan zkochan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it is a good idea. On one hand it could be a problem if the override didn't work. On the other hand, maybe there is a big shared set of overrides shared across the org and it is not a problem if some repositories don't match all of them.

@aqeelat

aqeelat commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

I don't know if it is a good idea. On one hand it could be a problem if the override didn't work. On the other hand, maybe there is a big shared set of overrides shared across the org and it is not a problem if some repositories don't match all of them.

@zkochan do you want it as a pnpm check-overrides command? Or maybe add a config that disables it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

product: pacquet product: pnpm@11 reviewed: coderabbit CodeRabbit submitted an approving review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Warn when override doesn't match anything

4 participants