Skip to content

feat(pacquet): port pnpm-workspace.yaml overrides support to the install chain#11793

Merged
zkochan merged 4 commits into
mainfrom
overrides
May 21, 2026
Merged

feat(pacquet): port pnpm-workspace.yaml overrides support to the install chain#11793
zkochan merged 4 commits into
mainfrom
overrides

Conversation

@zkochan

@zkochan zkochan commented May 21, 2026

Copy link
Copy Markdown
Member

Summary

Ports pnpm's pnpm.overrides feature to pacquet:

  • New pacquet-config-parse-overrides crate — port of @pnpm/config.parse-overrides. Splits foo, foo@^1, bar>foo, bar@1>foo@^2, foo@3 || >=2 keys via the [^ |@]> disambiguation; catalog refs surface as ERR_PNPM_CATALOG_IN_OVERRIDES until catalogs are ported.
  • overrides plumbed through Config and WorkspaceSettings — read from pnpm-workspace.yaml, empty maps collapse to None (matches upstream's delete settings.overrides), kept out of global config.yaml via clear_workspace_only_fields, and accepts PNPM_CONFIG_OVERRIDES via env-overlay.
  • Lockfile-side drift surfaces as StalenessReason::OverridesChangedcheck_lockfile_settings checks overrides before ignoredOptionalDependencies, matching upstream's getOutdatedLockfileSetting.ts:50-56 ordering. Comparison is order-insensitive (normalizes to BTreeMap).
  • VersionsOverrider (in pacquet-package-manager) — port of createVersionsOverrider. Generic + parent-scoped buckets, range intersection via node-semver, - deletion, link: / file: local targets with re-relativization against the importing package's dir. The peer-arm promotion is intentionally deferred until peer install lands.
  • Install pipeline applies the overrider to a clone of the root manifest before satisfies_package_manifest, so post-override lockfile specifiers line up with the on-disk manifest. WorkspaceState.settings.overrides now records the resolved map.

Drafted because pacquet's resolver isn't ported yet, so this slice is install-side parity only — when the resolver lands, the overrider gets wired into every readPackageHook call site (transitive packuments, not just the root) and the peer arm gets ported alongside peer install.

Upstream references threaded into doc comments / commit-pinned at the first 10 hex chars per pacquet's link policy.

Test plan

  • cargo nextest run -p pacquet-config-parse-overrides — 10 tests, all pass.
  • cargo nextest run -p pacquet-config — 209 tests, all pass (3 new overrides cases).
  • cargo nextest run -p pacquet-lockfile — 154 tests, all pass (6 new overrides-drift cases).
  • cargo nextest run -p pacquet-package-manager — 276 tests, all pass (11 new overrider unit tests + 2 new integration tests covering drift error and post-override freshness).
  • cargo fmt --check
  • cargo clippy --workspace --all-targets -- --deny warnings

Written by an agent (Claude Code, claude-opus-4-7).

Summary by CodeRabbit

  • New Features

    • Full support for pnpm.overrides to rewrite dependency specifiers during install, including parent-scoped selectors, version-range constraints, and local link/file paths; overrides are applied to manifests before freshness checks.
  • Improvements

    • Lockfile freshness now detects overrides drift and causes frozen installs to fail when overrides mismatch.
    • Workspace and environment config now accept and persist overrides.
  • Bug Fixes

    • Better validation and clearer errors for invalid override selectors and unsupported catalog: values.

Review Change Stack

Adds a new `pacquet-config-parse-overrides` crate (port of
`@pnpm/config.parse-overrides`), threads `overrides` through
`Config`/`WorkspaceSettings`, surfaces lockfile-side drift as
`StalenessReason::OverridesChanged` (matching upstream's
`getOutdatedLockfileSetting` overrides branch), and applies the parsed
overrides to a cloned root manifest before the frozen-lockfile
freshness check so post-override lockfile specifiers line up with the
on-disk manifest. The read-package-hook port (`VersionsOverrider`)
mirrors upstream's `createVersionsOverrider` minus the peer-arm
promotion, which is deferred until peer install lands. Catalog refs in
override values surface as `INVALID_OVERRIDES` until catalogs are
ported.
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 516f1dc1-d84e-4e1a-becb-d90cf5a17ca5

📥 Commits

Reviewing files that changed from the base of the PR and between de1303f and 8d19cf3.

📒 Files selected for processing (4)
  • pacquet/crates/config-parse-overrides/src/lib.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/config/src/workspace_yaml/tests.rs
  • pacquet/crates/package-manager/src/overrides.rs
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (1)
pacquet/**/*.rs

📄 CodeRabbit inference engine (pacquet/AGENTS.md)

pacquet/**/*.rs: When porting a function that fires pnpm:<channel> events through globalLogger, logger.debug(), or streamParser.write(), mirror the call site, payload, and ordering so the reporter parses pacquet's NDJSON the same way it parses pnpm's.
Declare a newtype wrapper for branded string types. Do not collapse the brand into a plain String or &str.
If upstream always validates before construction, validate in pacquet's wrapper too. The wrapper must construct only via TryFrom<String> and/or FromStr. Do not provide an infallible public constructor.
If upstream never validates, just brand for type-safety. Expose an infallible From<String> (and From<&str> when convenient).
If upstream occasionally constructs without validation, expose from_str_unchecked as an escape hatch alongside the validating constructor.
Match upstream serde behavior for branded types that cross JSON, YAML, or INI boundaries. Use #[serde(try_from = "String")] for deserialization and #[serde(into = "String")] for serialization.
Use #[derive(derive_more::From)] and #[derive(derive_more::Into)] for mechanical conversion impls. Fall back to manual impl only when conversion needs custom logic.
String-literal unions should become enums, not newtype wrappers. Model closed sets of valid string values as enums.
Template literal types should be treated as branded strings with validation discipline from rules 2-5.
Choose owned vs. borrowed parameters to minimize copies. Widen to the most encompassing type (&Path over &PathBuf, &str over &String) when it doesn't force extra copies.
Prefer Arc::clone(&x) / Rc::clone(&x) over x.clone() for reference-counted types, so the cost is visible at the call site.
Follow Rust API Guidelines for naming conventions.
Do not use star imports inside module bodies. Write use super::{Foo, bar} instead of use super::*;. Two forms stay allowed: external-crate preludes like use rayon::prelude::*; and root-of-module re-...

Files:

  • pacquet/crates/config/src/workspace_yaml/tests.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/config-parse-overrides/src/lib.rs
  • pacquet/crates/package-manager/src/overrides.rs
🧠 Learnings (2)
📚 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/config/src/workspace_yaml/tests.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/config-parse-overrides/src/lib.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/config/src/workspace_yaml/tests.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/config-parse-overrides/src/lib.rs
  • pacquet/crates/package-manager/src/overrides.rs
🔇 Additional comments (6)
pacquet/crates/config/src/workspace_yaml/tests.rs (1)

756-772: LGTM!

pacquet/crates/config/src/workspace_yaml.rs (1)

580-590: LGTM!

pacquet/crates/config-parse-overrides/src/lib.rs (1)

99-105: LGTM!

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

232-249: LGTM!


310-321: LGTM!


328-331: LGTM!


📝 Walkthrough

Walkthrough

Adds pnpm.overrides end-to-end: parsing crate, config/workspace/env wiring, lockfile freshness drift detection, PackageManifest mutation support, an in-memory VersionsOverrider, and frozen-lockfile install integration with tests.

Changes

pnpm overrides implementation

Layer / File(s) Summary
Workspace & parse-crate manifest
Cargo.toml, pacquet/crates/config-parse-overrides/Cargo.toml
Registers pacquet-config-parse-overrides in workspace and adds the crate manifest.
Override parsing crate
pacquet/crates/config-parse-overrides/src/lib.rs, pacquet/crates/config-parse-overrides/src/tests.rs
New crate parses pnpm override selectors into VersionOverride entries (parent>child, ranges), rejects catalog: specs, exposes ordered/iterator parse APIs, and includes tests.
Config layer: overrides field and YAML/env loading
pacquet/crates/config/src/lib.rs, pacquet/crates/config/src/workspace_yaml.rs, pacquet/crates/config/src/env_overlay.rs, pacquet/crates/config/src/workspace_yaml/tests.rs
Adds Config::overrides and WorkspaceSettings::overrides; env-overlay reads OVERRIDES; empty maps collapse to None; apply/clear logic and tests updated.
Lockfile freshness: overrides drift detection
pacquet/crates/lockfile/src/freshness.rs, pacquet/crates/lockfile/src/freshness/tests.rs
Adds StalenessReason::OverridesChanged and updates check_lockfile_settings to compare lockfile vs config overrides (order-insensitive), returning OverridesChanged first; tests added/updated.
PackageManifest: Clone and value mutation support
pacquet/crates/package-manifest/src/lib.rs
PackageManifest derives Clone and exposes value_mut() for in-memory JSON mutation used when applying overrides.
Override applicator: in-memory manifest rewriting
pacquet/crates/package-manager/src/lib.rs, pacquet/crates/package-manager/src/overrides.rs, pacquet/crates/package-manager/src/overrides/tests.rs
VersionsOverrider applies parsed overrides across dependency groups, respects parent-scoped precedence, matches semver ranges, supports deletion via "-", rewrites link:/file: paths with normalization; tests cover precedence, path re-anchoring, and protocols.
Install: frozen-lockfile overrides validation and application
pacquet/crates/package-manager/Cargo.toml, pacquet/crates/package-manager/src/install.rs, pacquet/crates/package-manager/src/install/tests.rs, pacquet/crates/package-manager/src/install_package_from_registry/tests.rs
Frozen-lockfile install parses/validates overrides (errors as InvalidOverrides), includes overrides in freshness checks, applies overrides to cloned manifests for freshness/ignored-optional checks, persists overrides to workspace state, and adds tests for drift and applied scenarios.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • pnpm/pnpm#11755: Parsing crate calls into parse_wanted_dependency functionality introduced there.
  • pnpm/pnpm#11665: Related workspace-state writing and install workspace-state handling integration.
  • pnpm/pnpm#11752: Related env-overlay parsing changes for WorkspaceSettings.

Poem

🐰 I hop through selectors, > and @ in tow,
I re-anchor file paths where local links go,
I whisper to lockfiles when overrides change,
Manifests bend gently to the new version range,
Hooray for tidy installs — nibble a carrot, let's go!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: porting pnpm-workspace.yaml overrides support to pacquet's install chain. It is specific, concise, and directly reflects the changeset's primary objective.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch overrides

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 and usage tips.

@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.02      5.9±0.15ms   732.6 KB/sec    1.00      5.8±0.03ms   747.6 KB/sec

@codecov-commenter

codecov-commenter commented May 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.06897% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.44%. Comparing base (df990fd) to head (8d19cf3).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pacquet/crates/package-manager/src/overrides.rs 89.44% 17 Missing ⚠️
pacquet/crates/config-parse-overrides/src/lib.rs 92.10% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #11793      +/-   ##
==========================================
+ Coverage   87.20%   87.44%   +0.24%     
==========================================
  Files         190      200      +10     
  Lines       22525    23353     +828     
==========================================
+ Hits        19642    20421     +779     
- Misses       2883     2932      +49     

☔ View full report in Codecov by Sentry.
📢 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.

…link

Renames single-letter closure / function / generic params introduced
by the overrides port to descriptive names, fixes trailing-comma
policy in test macro invocations, swaps the Windows path literal to
a raw string, and removes a stale `[`Self::root_dir`]` rustdoc link
left behind when the `root_dir` field was dropped from
`VersionsOverrider`.
@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

Scenario: Frozen Lockfile

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 2.450 ± 0.077 2.370 2.597 1.02 ± 0.04
pacquet@main 2.397 ± 0.064 2.311 2.490 1.00
pnpm 4.673 ± 0.081 4.513 4.794 1.95 ± 0.06
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 2.4504267256600003,
      "stddev": 0.07739234092641506,
      "median": 2.41462364796,
      "user": 2.8441393400000003,
      "system": 3.65458204,
      "min": 2.37000642346,
      "max": 2.59701099746,
      "times": [
        2.39319641446,
        2.49401397546,
        2.53456509146,
        2.59701099746,
        2.50706827246,
        2.41144498246,
        2.37376191046,
        2.37000642346,
        2.40539687546,
        2.41780231346
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 2.3968989138600003,
      "stddev": 0.0640405012195271,
      "median": 2.38187658696,
      "user": 2.84290904,
      "system": 3.6504337399999995,
      "min": 2.31052835346,
      "max": 2.48956365046,
      "times": [
        2.34367617346,
        2.36707280146,
        2.36468797846,
        2.33795620646,
        2.48956365046,
        2.39668037246,
        2.40857162646,
        2.46383992046,
        2.48641205546,
        2.31052835346
      ]
    },
    {
      "command": "pnpm",
      "mean": 4.67321690116,
      "stddev": 0.0810941209438727,
      "median": 4.68521208746,
      "user": 8.002722239999999,
      "system": 4.074765640000001,
      "min": 4.51329278646,
      "max": 4.79361280246,
      "times": [
        4.74296800746,
        4.79361280246,
        4.70483135946,
        4.73461268846,
        4.69652511746,
        4.65480276046,
        4.59651316646,
        4.67389905746,
        4.51329278646,
        4.62111126546
      ]
    }
  ]
}

Scenario: Frozen Lockfile (Hot Cache)

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 716.2 ± 56.1 682.7 871.7 1.00
pacquet@main 722.8 ± 30.3 689.3 794.4 1.01 ± 0.09
pnpm 2582.6 ± 95.6 2432.9 2742.0 3.61 ± 0.31
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.71622058174,
      "stddev": 0.056111166659350474,
      "median": 0.69559237334,
      "user": 0.38880936,
      "system": 1.59700932,
      "min": 0.6827416193400001,
      "max": 0.8717333033400001,
      "times": [
        0.8717333033400001,
        0.71006844834,
        0.6918879723400001,
        0.69637229034,
        0.6882525673400001,
        0.6827416193400001,
        0.6948124563400001,
        0.69258336734,
        0.70669987934,
        0.72705391334
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.72283742154,
      "stddev": 0.030310954110029924,
      "median": 0.7145529453400001,
      "user": 0.39680796000000007,
      "system": 1.60627432,
      "min": 0.68925859134,
      "max": 0.79438161734,
      "times": [
        0.7401302763400001,
        0.69893216534,
        0.70070534334,
        0.79438161734,
        0.70836405134,
        0.68925859134,
        0.7098729583400001,
        0.72964283634,
        0.73785344334,
        0.7192329323400001
      ]
    },
    {
      "command": "pnpm",
      "mean": 2.58256645044,
      "stddev": 0.09561581393528298,
      "median": 2.5824811158400003,
      "user": 3.07060666,
      "system": 2.23032712,
      "min": 2.43288324134,
      "max": 2.7419570713400003,
      "times": [
        2.60580316434,
        2.44552527634,
        2.55915906734,
        2.6195921593400002,
        2.66229476534,
        2.55830024734,
        2.54681383934,
        2.43288324134,
        2.7419570713400003,
        2.65333567234
      ]
    }
  ]
}

@zkochan zkochan changed the title feat(pacquet): port pnpm.overrides support to the install chain feat(pacquet): port pnpm-workspace.yaml overrides support to the install chain May 21, 2026
@zkochan zkochan marked this pull request as ready for review May 21, 2026 00:41
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@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: 4

🧹 Nitpick comments (1)
pacquet/crates/package-manager/src/install/tests.rs (1)

1424-1428: ⚡ Quick win

Trim test doc-comments to intent-only.

These doc blocks mostly restate the test flow and assertions. Keep only non-obvious rationale and upstream parity links; let the test body carry behavior details.

As per coding guidelines: "Tests are documentation. Do not duplicate them in prose." and "Doc comments (///, //!) document the contract... They are not a re-narration of the body."

Also applies to: 1487-1494

🤖 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 `@pacquet/crates/package-manager/src/install/tests.rs` around lines 1424 -
1428, The long doc-comments above the pnpm.overrides test should be trimmed to
an intent-only summary: remove prose that restates the test flow and assertions
and keep only the non-obvious rationale or upstream parity links; edit the
triple-slash comment block that begins with "`pnpm.overrides` drift..." (and the
similar block at the later range around lines 1487-1494) to a single short
sentence stating the intent (e.g., "Verify OutdatedLockfile is raised with
StalenessReason::OverridesChanged when pnpm.overrides differ") and preserve any
upstream link or required rationale only.
🤖 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/config-parse-overrides/src/lib.rs`:
- Around line 99-105: The doc for parse_overrides is incorrect: it claims
insertion-order behavior but the function takes &HashMap<String,String> and
iterates it, so output follows HashMap iteration order; update the documentation
on parse_overrides to state that HashMap iteration order is not guaranteed and
that callers who require stable/insertion order should use
parse_overrides_iter(map.iter()) (or pass a map type with defined ordering), and
keep the function signature and behavior unchanged; mention parse_overrides,
parse_overrides_iter, VersionOverride, and ParseOverridesError in the doc so
readers can find the alternatives.

In `@pacquet/crates/config/src/workspace_yaml.rs`:
- Around line 583-587: The current conditional for assigning overrides skips
when self.overrides is Some({}) so an explicit empty env overlay cannot clear
prior overrides; change the logic in the block handling self.overrides so that
whenever self.overrides is Some(v) you set config.overrides = Some(v) regardless
of v.is_empty() (i.e., remove the !v.is_empty() check) so an explicit empty map
from self.overrides clears earlier settings.

In `@pacquet/crates/package-manager/src/overrides.rs`:
- Around line 299-305: The branch logic in resolve_local_override_spec leaves
absolute paths un-normalized (it returns
target.absolute_path.display().to_string() in the diff_paths fallback and the
`_` arm), which yields backslashes on Windows; update both of those branches to
route the absolute path through normalize_path (i.e., call normalize_path on the
absolute path string or PathBuf from target.absolute_path) so both the
pathdiff::diff_paths success path and the fallback/non-relative branch produce
normalized forward-slash paths for link:/file: specs; ensure you keep the
existing behavior of using diff_paths when specified_via_relative_path is true
and pkg_dir is Some.
- Around line 228-239: The comparator in sort_by_specificity is not a total
order because it only returns Less/Greater and can disagree for cmp(a,b) vs
cmp(b,a); update sort_by_specificity to return Ordering::Equal in ambiguous
cases and add a deterministic tie-breaker: if lhs and rhs have identical
bare_specifier strings return Ordering::Equal; otherwise, if neither is more
specific according to is_intersecting_range return a stable ordering (e.g.,
compare lhs_spec.cmp(&rhs_spec) or another unique field such as a package
name/id) so the comparator can produce Equal for truly identical entries and a
consistent Less/Greater otherwise; reference function names:
sort_by_specificity, is_intersecting_range,
ResolvedOverride::inner.target_pkg.bare_specifier.

---

Nitpick comments:
In `@pacquet/crates/package-manager/src/install/tests.rs`:
- Around line 1424-1428: The long doc-comments above the pnpm.overrides test
should be trimmed to an intent-only summary: remove prose that restates the test
flow and assertions and keep only the non-obvious rationale or upstream parity
links; edit the triple-slash comment block that begins with "`pnpm.overrides`
drift..." (and the similar block at the later range around lines 1487-1494) to a
single short sentence stating the intent (e.g., "Verify OutdatedLockfile is
raised with StalenessReason::OverridesChanged when pnpm.overrides differ") and
preserve any upstream link or required rationale only.
🪄 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: 5222c266-113c-4d2a-b82c-ac9875e587bf

📥 Commits

Reviewing files that changed from the base of the PR and between b2a95fa and f2b9fee.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (18)
  • Cargo.toml
  • pacquet/crates/config-parse-overrides/Cargo.toml
  • pacquet/crates/config-parse-overrides/src/lib.rs
  • pacquet/crates/config-parse-overrides/src/tests.rs
  • pacquet/crates/config/src/env_overlay.rs
  • pacquet/crates/config/src/lib.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/config/src/workspace_yaml/tests.rs
  • pacquet/crates/lockfile/src/freshness.rs
  • pacquet/crates/lockfile/src/freshness/tests.rs
  • pacquet/crates/package-manager/Cargo.toml
  • pacquet/crates/package-manager/src/install.rs
  • pacquet/crates/package-manager/src/install/tests.rs
  • pacquet/crates/package-manager/src/install_package_from_registry/tests.rs
  • pacquet/crates/package-manager/src/lib.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/package-manifest/src/lib.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Lint and Test (macos-latest)
  • GitHub Check: Lint and Test (windows-latest)
  • GitHub Check: Dylint
  • GitHub Check: Code Coverage
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Compile & Lint
🧰 Additional context used
📓 Path-based instructions (1)
pacquet/**/*.rs

📄 CodeRabbit inference engine (pacquet/AGENTS.md)

pacquet/**/*.rs: When porting a function that fires pnpm:<channel> events through globalLogger, logger.debug(), or streamParser.write(), mirror the call site, payload, and ordering so the reporter parses pacquet's NDJSON the same way it parses pnpm's.
Declare a newtype wrapper for branded string types. Do not collapse the brand into a plain String or &str.
If upstream always validates before construction, validate in pacquet's wrapper too. The wrapper must construct only via TryFrom<String> and/or FromStr. Do not provide an infallible public constructor.
If upstream never validates, just brand for type-safety. Expose an infallible From<String> (and From<&str> when convenient).
If upstream occasionally constructs without validation, expose from_str_unchecked as an escape hatch alongside the validating constructor.
Match upstream serde behavior for branded types that cross JSON, YAML, or INI boundaries. Use #[serde(try_from = "String")] for deserialization and #[serde(into = "String")] for serialization.
Use #[derive(derive_more::From)] and #[derive(derive_more::Into)] for mechanical conversion impls. Fall back to manual impl only when conversion needs custom logic.
String-literal unions should become enums, not newtype wrappers. Model closed sets of valid string values as enums.
Template literal types should be treated as branded strings with validation discipline from rules 2-5.
Choose owned vs. borrowed parameters to minimize copies. Widen to the most encompassing type (&Path over &PathBuf, &str over &String) when it doesn't force extra copies.
Prefer Arc::clone(&x) / Rc::clone(&x) over x.clone() for reference-counted types, so the cost is visible at the call site.
Follow Rust API Guidelines for naming conventions.
Do not use star imports inside module bodies. Write use super::{Foo, bar} instead of use super::*;. Two forms stay allowed: external-crate preludes like use rayon::prelude::*; and root-of-module re-...

Files:

  • pacquet/crates/config/src/env_overlay.rs
  • pacquet/crates/package-manifest/src/lib.rs
  • pacquet/crates/package-manager/src/lib.rs
  • pacquet/crates/config/src/lib.rs
  • pacquet/crates/config-parse-overrides/src/tests.rs
  • pacquet/crates/config/src/workspace_yaml/tests.rs
  • pacquet/crates/lockfile/src/freshness.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/package-manager/src/install_package_from_registry/tests.rs
  • pacquet/crates/lockfile/src/freshness/tests.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/package-manager/src/install/tests.rs
  • pacquet/crates/config-parse-overrides/src/lib.rs
  • pacquet/crates/package-manager/src/install.rs
🧠 Learnings (3)
📚 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/config/src/env_overlay.rs
  • pacquet/crates/package-manifest/src/lib.rs
  • pacquet/crates/package-manager/src/lib.rs
  • pacquet/crates/config/src/lib.rs
  • pacquet/crates/config-parse-overrides/src/tests.rs
  • pacquet/crates/config/src/workspace_yaml/tests.rs
  • pacquet/crates/lockfile/src/freshness.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/package-manager/src/install_package_from_registry/tests.rs
  • pacquet/crates/lockfile/src/freshness/tests.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/package-manager/src/install/tests.rs
  • pacquet/crates/config-parse-overrides/src/lib.rs
  • pacquet/crates/package-manager/src/install.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/config/src/env_overlay.rs
  • pacquet/crates/package-manifest/src/lib.rs
  • pacquet/crates/package-manager/src/lib.rs
  • pacquet/crates/config/src/lib.rs
  • pacquet/crates/config-parse-overrides/src/tests.rs
  • pacquet/crates/config/src/workspace_yaml/tests.rs
  • pacquet/crates/lockfile/src/freshness.rs
  • pacquet/crates/config/src/workspace_yaml.rs
  • pacquet/crates/package-manager/src/overrides/tests.rs
  • pacquet/crates/package-manager/src/install_package_from_registry/tests.rs
  • pacquet/crates/lockfile/src/freshness/tests.rs
  • pacquet/crates/package-manager/src/overrides.rs
  • pacquet/crates/package-manager/src/install/tests.rs
  • pacquet/crates/config-parse-overrides/src/lib.rs
  • pacquet/crates/package-manager/src/install.rs
📚 Learning: 2026-05-20T23:23:40.606Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11788
File: pacquet/crates/lockfile/src/snapshot_dep_ref.rs:52-56
Timestamp: 2026-05-20T23:23:40.606Z
Learning: In the pacquet lockfile crate, the link target is intentionally represented as a raw `Link(String)` (not a `LinkTarget` newtype) for both `SnapshotDepRef::Link` and `ImporterDepVersion::Link`. pnpm upstream preserves `link:` targets verbatim with only a prefix check (e.g., `refToRelative`), so do not suggest introducing a `LinkTarget` newtype in a bug-fix/targeted PR. If type branding is ever desired, it should be done together for both variants in a separate dedicated refactor PR rather than as part of a small fix.

Applied to files:

  • pacquet/crates/lockfile/src/freshness.rs
  • pacquet/crates/lockfile/src/freshness/tests.rs
🔇 Additional comments (9)
pacquet/crates/lockfile/src/freshness.rs (1)

21-21: LGTM!

Also applies to: 89-102, 179-215

pacquet/crates/lockfile/src/freshness/tests.rs (1)

594-595: LGTM!

Also applies to: 611-611, 624-624, 644-644, 653-770

pacquet/crates/package-manifest/src/lib.rs (1)

65-65: LGTM!

Also applies to: 150-159

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

24-24: LGTM!

Also applies to: 55-55

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

1-274: LGTM!

pacquet/crates/package-manager/Cargo.toml (1)

30-30: LGTM!

Also applies to: 58-58

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

195-204: LGTM!

Also applies to: 403-452, 472-484, 840-842, 882-886

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

1430-1485: LGTM!

Also applies to: 1496-1573

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

68-68: LGTM!

Comment thread pacquet/crates/config-parse-overrides/src/lib.rs Outdated
Comment thread pacquet/crates/config/src/workspace_yaml.rs Outdated
Comment thread pacquet/crates/package-manager/src/overrides.rs
Comment thread pacquet/crates/package-manager/src/overrides.rs
- `parse_overrides` doc no longer claims insertion-order behavior; it
  accurately states that `HashMap` iteration is unordered and points
  ordered-output callers at `parse_overrides_iter`.
- `WorkspaceSettings::apply_to` now collapses `overrides: {}` from a
  later layer (env overlay, repeat `apply_to`) to `None` on `Config`,
  so an explicit empty map clears an earlier non-empty assignment
  instead of silently being skipped. Adds a regression test for the
  env-overlay-clears-yaml shape.
- `sort_by_specificity` widens its comparator to a 3-way result so
  Rust's `sort_by` total-order precondition holds. The strict
  Less/Greater arms keep the sort outcome identical to upstream's
  first-match choice; the `Equal` arm covers mutually-intersecting
  ranges.
- `resolve_local_override_spec` routes the absolute-path and
  diff-paths-fallback branches through `normalize_path` too, so
  Windows `\` separators get rewritten to `/` for every `link:` /
  `file:` shape (not just the diff-paths success branch).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants