Skip to content

fix(pacquet): refresh lockfile when catalogs change#12382

Merged
zkochan merged 1 commit into
mainfrom
fix-pacquet
Jun 13, 2026
Merged

fix(pacquet): refresh lockfile when catalogs change#12382
zkochan merged 1 commit into
mainfrom
fix-pacquet

Conversation

@zkochan

@zkochan zkochan commented Jun 13, 2026

Copy link
Copy Markdown
Member

Summary

  • detect catalog drift between pnpm-workspace.yaml and the lockfile catalogs: snapshot
  • record and compare catalogs in pacquet's workspace-state fast path so plain pacquet install does not skip after catalog edits
  • add lockfile, repeat-install, and CLI regression coverage for catalog changes

Tests

  • cargo test -p pacquet-lockfile check_settings_
  • cargo test -p pacquet-package-manager returns_outdated_when_workspace_catalog_cache_changes
  • cargo test -p pacquet-cli --test catalog install_reruns_when_catalog_entry_changes
  • cargo test -p pacquet-package-manager returns_up_to_date_when_state_carries_unported_pnpm_settings
  • cargo test -p pacquet-package-manager build_workspace_state_tests
  • cargo check --locked -p pacquet-lockfile -p pacquet-package-manager -p pacquet-cli --all-targets
  • pre-push hook: TypeScript compile/lint/spellcheck/meta checks, Rust fmt/doc/dylint, taplo format check

No changeset: pacquet Rust-only change.


Written by an agent (Codex, GPT-5).

Summary by CodeRabbit

  • Tests

    • Added end-to-end and unit tests covering catalog-aware install behavior and cache drift.
  • Bug Fixes

    • Lockfile freshness now considers workspace catalog configuration.
    • Repeat/optimistic reinstall paths detect catalog cache changes and trigger accurate re-resolution.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR extends lockfile and optimistic repeat-install freshness checks to detect when workspace catalog configurations change. It adds a new StalenessReason::CatalogsChanged variant, threads catalog snapshots through the install dispatcher, and implements catalog-cache matching in the repeat-install fast path to skip the UpToDate decision when catalogs drift.

Changes

Catalog Freshness in Lockfile and Repeat Install

Layer / File(s) Summary
Lockfile catalog freshness contract and helpers
pacquet/crates/lockfile/Cargo.toml, pacquet/crates/lockfile/src/freshness.rs
Introduces StalenessReason::CatalogsChanged, extends LockfileSettingsCheck<'a> to carry pub catalogs: &'a Catalogs, refactors check_lockfile_settings to delegate to new check_lockfile_settings_with_catalogs, and implements all_catalogs_are_up_to_date helper to compare current workspace catalogs against the lockfile's recorded snapshot.
Lockfile catalog freshness tests
pacquet/crates/lockfile/src/freshness/tests.rs
Adds settings_check(catalogs: &Catalogs) helper and new test cases verifying check_lockfile_settings_with_catalogs passes when snapshots match or config entries are absent from snapshot, and reports CatalogsChanged when specifiers change or config entries are removed.
Install dispatcher: catalog wiring through freshness checks
pacquet/crates/package-manager/src/install.rs
Updates check_lockfile_settings_drift and build_workspace_state signatures to accept catalogs: &Catalogs, threads catalogs into the freshness flow at all call sites (early up-to-date check, fresh-resolve, and final workspace-state persistence), and switches lockfile freshness from check_lockfile_settings to check_lockfile_settings_with_catalogs via LockfileSettingsCheck struct.
Install tests: signature updates
pacquet/crates/package-manager/src/install/tests.rs
Updates three existing build_workspace_state invocations to pass new &BTreeMap::default() catalogs argument.
Optimistic repeat install: catalog cache freshness
pacquet/crates/package-manager/src/optimistic_repeat_install.rs
Adds catalogs input destructuring, implements early-exit guard for workspace installs when recorded catalog snapshot doesn't match current catalogs, threads catalogs into workspace-state refresh calls, and introduces current_settings_with_catalogs helper (with JSON-based cache-comparison logic) to serialize catalogs into workspace-state settings.
Optimistic repeat install tests: catalog cache changes
pacquet/crates/package-manager/src/optimistic_repeat_install/tests.rs
Adds check_workspace(catalogs: &Catalogs) test helper that forwards catalogs into the fast-path check, removes explicit settings.catalogs assignment from existing test, and introduces returns_outdated_when_workspace_catalog_cache_changes to verify the fast path skips when workspace catalogs change between invocations.
End-to-end catalog freshness test
pacquet/crates/cli/tests/catalog.rs
Adds catalog_snapshot(workspace, name) helper to extract catalog entries from pnpm-lock.yaml and install_reruns_when_catalog_entry_changes test that runs install, verifies the catalog snapshot, edits the workspace catalog entry, runs install again, and asserts the snapshot updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • pnpm/pnpm#12005: Modifies optimistic repeat-install settings_match comparison behavior in the same file to narrow pacquet-written fields and normalize allow_builds.
  • pnpm/pnpm#11943: Touches optimistic-repeat-install fast-path implementation and settings construction similarly to this PR.
  • pnpm/pnpm#11946: Refactors build_workspace_state and related plumbing that this PR builds upon.

Suggested reviewers

  • anonrig

Poem

🐰 Catalogs dance through lockfiles, whispering changes—
Each snapshot a promise, each drift a rediscovery.
Fast paths yield to fresh starts when the catalogs call,
And reinstalls spring forth like clover after rain. 🌱

🚥 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 'fix(pacquet): refresh lockfile when catalogs change' directly summarizes the main objective: detecting catalog drift and refreshing the lockfile when catalog entries change, which is the core focus across all modified files.
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 fix-pacquet

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 Jun 13, 2026

Copy link
Copy Markdown
Contributor

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.01      7.5±0.12ms   575.1 KB/sec    1.00      7.5±0.24ms   581.3 KB/sec

@codecov-commenter

codecov-commenter commented Jun 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.29%. Comparing base (4819fb4) to head (86f5df4).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12382      +/-   ##
==========================================
+ Coverage   88.26%   88.29%   +0.03%     
==========================================
  Files         297      297              
  Lines       38705    38796      +91     
==========================================
+ Hits        34164    34256      +92     
+ Misses       4541     4540       -1     

☔ 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.

@zkochan zkochan marked this pull request as ready for review June 13, 2026 14:20
@qodo-free-for-open-source-projects

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

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0)

Grey Divider


Action required

1. Catalog drift not checked 🐞 Bug ≡ Correctness
Description
check_optimistic_repeat_install only checks catalogs-cache drift when is_workspace_install is
true, so non-workspace installs can still short-circuit even if Config::catalogs changed. Since
catalogs influence catalog: override resolution, this can skip an install that should rerun and
leave node_modules inconsistent with current config.
Code

pacquet/crates/package-manager/src/optimistic_repeat_install.rs[R158-160]

+    if is_workspace_install && !catalogs_cache_matches(state.settings.catalogs.as_ref(), catalogs) {
+        return Decision::Skipped { reason: "catalogs cache outdated" };
+    }
Evidence
The fast path only checks catalogs drift under is_workspace_install, but catalogs can come from
Config::catalogs (pnpmfile hook output) and are used by the install pipeline to resolve catalog:
overrides; therefore gating the drift check on workspace detection can incorrectly skip installs in
non-workspace runs where catalogs still matter.

pacquet/crates/package-manager/src/optimistic_repeat_install.rs[130-161]
pacquet/crates/config/src/lib.rs[1331-1339]
pacquet/crates/package-manager/src/install.rs[503-580]
pacquet/crates/package-manager/src/install.rs[1392-1409]

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

## Issue description
`check_optimistic_repeat_install` only invalidates the optimistic repeat-install fast path on catalog drift when `is_workspace_install` is true. However, `Config::catalogs` can be populated by pnpmfile `updateConfig` hooks even when there is no `pnpm-workspace.yaml`, and catalogs affect `catalog:` override resolution; the fast path can therefore return `UpToDate` when it should fall through to a real install.
## Issue Context
- Catalogs are threaded into the install path even when there is no workspace manifest (via `config.catalogs`).
- The optimistic fast path can exit before any lockfile/settings drift checks that would otherwise observe catalog-driven changes.
## Fix Focus Areas
- pacquet/crates/package-manager/src/optimistic_repeat_install.rs[154-161]
- pacquet/crates/config/src/lib.rs[1331-1339]
- pacquet/crates/package-manager/src/install.rs[503-580]
## Suggested change
Remove the `is_workspace_install` gate and compare catalogs cache unconditionally (or at least whenever `catalogs` is non-empty / `state.settings.catalogs` is present). `catalogs_cache_matches` already handles `None` by treating it as `{}`, so unconditional checking should be safe for legacy state files.

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



Remediation recommended

2. Catalog cache order drift 🐞 Bug ➹ Performance ⭐ New
Description
catalogs_cache_matches compares serde_json::Value objects directly, but this workspace enables
serde_json/preserve_order (IndexMap-backed maps), so differing key insertion order between a
pnpm-written workspace-state file and pacquet’s BTreeMap-derived JSON can be treated as inequality.
This can incorrectly skip the optimistic repeat-install fast path even when catalogs are
semantically unchanged, causing needless full installs.
Code

pacquet/crates/package-manager/src/optimistic_repeat_install.rs[R904-908]

+fn catalogs_cache_matches(recorded: Option<&serde_json::Value>, current: &Catalogs) -> bool {
+    let recorded = recorded.cloned().map_or_else(empty_json_object, filter_null_object_values);
+    let current = filter_null_object_values(catalogs_to_json(current));
+    recorded == current
+}
Evidence
The repo enables serde_json's preserve_order feature, and another module documents that
serde_json::Map is IndexMap-backed under that feature, so insertion order is retained and must
often be normalized for stable behavior. The new catalogs cache check performs direct
serde_json::Value equality without canonicalization, so equivalent objects with different key
orders can fail the comparison and skip the fast path.

Cargo.toml[121-139]
pacquet/crates/package-manager/src/optimistic_repeat_install.rs[155-165]
pacquet/crates/package-manager/src/optimistic_repeat_install.rs[893-922]
pacquet/crates/lockfile-verification/src/hash_lockfile.rs[40-62]

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

## Issue description
`catalogs_cache_matches` compares `serde_json::Value` objects directly (`recorded == current`). Because the workspace enables `serde_json/preserve_order`, JSON object maps preserve insertion order; if the recorded workspace-state file was written by pnpm (likely preserving YAML/user insertion order) while pacquet serializes catalogs from a `BTreeMap` (sorted iteration order), the values can compare unequal despite representing the same catalogs.

This defeats the optimistic repeat-install fast path and makes installs rerun unnecessarily.

## Issue Context
- The workspace explicitly builds `serde_json` with `preserve_order`.
- Other code in this repo already normalizes/sorts JSON object keys specifically because `preserve_order` retains insertion order.

## Fix Focus Areas
Implement an order-insensitive comparison for catalogs by canonicalizing both sides before comparing. Two reasonable approaches:
1) **Typed compare (preferred):** deserialize the recorded JSON into `pacquet_catalogs_types::Catalogs` and compare `BTreeMap` values (order-insensitive by construction). Treat deserialize failures as mismatch (skip fast path).
2) **JSON canonicalization:** recursively sort object keys (deep) on both `recorded` and `current` values before comparing.

- pacquet/crates/package-manager/src/optimistic_repeat_install.rs[904-922]

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


Grey Divider

Previous review results

Review updated until commit 86f5df4

Results up to commit 187c903


🐞 Bugs (1) 📘 Rule violations (0)


Action required
1. Catalog drift not checked 🐞 Bug ≡ Correctness
Description
check_optimistic_repeat_install only checks catalogs-cache drift when is_workspace_install is
true, so non-workspace installs can still short-circuit even if Config::catalogs changed. Since
catalogs influence catalog: override resolution, this can skip an install that should rerun and
leave node_modules inconsistent with current config.
Code

pacquet/crates/package-manager/src/optimistic_repeat_install.rs[R158-160]

+    if is_workspace_install && !catalogs_cache_matches(state.settings.catalogs.as_ref(), catalogs) {
+        return Decision::Skipped { reason: "catalogs cache outdated" };
+    }
Evidence
The fast path only checks catalogs drift under is_workspace_install, but catalogs can come from
Config::catalogs (pnpmfile hook output) and are used by the install pipeline to resolve catalog:
overrides; therefore gating the drift check on workspace detection can incorrectly skip installs in
non-workspace runs where catalogs still matter.

pacquet/crates/package-manager/src/optimistic_repeat_install.rs[130-161]
pacquet/crates/config/src/lib.rs[1331-1339]
pacquet/crates/package-manager/src/install.rs[503-580]
pacquet/crates/package-manager/src/install.rs[1392-1409]

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

## Issue description
`check_optimistic_repeat_install` only invalidates the optimistic repeat-install fast path on catalog drift when `is_workspace_install` is true. However, `Config::catalogs` can be populated by pnpmfile `updateConfig` hooks even when there is no `pnpm-workspace.yaml`, and catalogs affect `catalog:` override resolution; the fast path can therefore return `UpToDate` when it should fall through to a real install.

## Issue Context
- Catalogs are threaded into the install path even when there is no workspace manifest (via `config.catalogs`).
- The optimistic fast path can exit before any lockfile/settings drift checks that would otherwise observe catalog-driven changes.

## Fix Focus Areas
- pacquet/crates/package-manager/src/optimistic_repeat_install.rs[154-161]
- pacquet/crates/config/src/lib.rs[1331-1339]
- pacquet/crates/package-manager/src/install.rs[503-580]

## Suggested change
Remove the `is_workspace_install` gate and compare catalogs cache unconditionally (or at least whenever `catalogs` is non-empty / `state.settings.catalogs` is present). `catalogs_cache_matches` already handles `None` by treating it as `{}`, so unconditional checking should be safe for legacy state files.

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


Qodo Logo

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

Copy link
Copy Markdown

PR Summary by Qodo

Fix pacquet lockfile freshness when workspace catalogs change
🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

Walkthroughs

Description
• Detect catalog drift between pnpm-workspace.yaml and pnpm-lock.yaml snapshots.
• Persist catalogs in workspace-state to avoid skipping installs after catalog edits.
• Add regression tests covering lockfile, repeat-install, and CLI behavior.
Diagram
graph TD
  W["pnpm-workspace.yaml"] --> R["Repeat-install check"] --> D{"Skip install?"}
  S["workspace-state.json"] --> R
  D -->|"UpToDate"| U["Exit early"]
  D -->|"Run install"| F["Full install"] --> L["pnpm-lock.yaml"] --> C["Lockfile settings check"]
  W --> C
  F --> S

  subgraph Legend
    direction LR
    _file["File"] ~~~ _proc["Process"] ~~~ _dec{"Decision"}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Invalidate repeat-install on `pnpm-workspace.yaml` mtime change
  • ➕ Very simple implementation; no schema changes to workspace-state
  • ➕ Covers any workspace-config edits, not just catalogs
  • ➖ Over-invalidates (any unrelated YAML edit forces install)
  • ➖ Doesn’t address lockfile-level catalogs: snapshot drift checks as precisely
  • ➖ Less parity with pnpm’s targeted behavior around catalogs
2. Store a catalogs checksum instead of full JSON in workspace-state
  • ➕ Smaller state payload; cheaper equality comparison
  • ➕ Avoids potential serialization-shape mismatches
  • ➖ Harder to debug (no visibility into what changed)
  • ➖ Requires stable canonicalization to avoid false positives
  • ➖ Still needs catalog-aware lockfile settings checking for correctness

Recommendation: The PR’s approach is the best fit: it mirrors pnpm’s split behavior (catalogs ignored in generic settings loop but checked explicitly for workspace installs), while also extending the lockfile settings drift check to include the lockfile’s catalogs: snapshot. This keeps invalidation targeted (only when catalogs that matter to the lockfile/state change) and is well-covered by focused regression tests.

Grey Divider

File Changes

Bug fix (3)
freshness.rs Detect catalog drift in lockfile settings freshness checks +75/-7

Detect catalog drift in lockfile settings freshness checks

• Adds 'LockfileSettingsCheck' to bundle settings inputs (including catalogs) and introduces 'check_lockfile_settings_with_catalogs'. Implements 'CatalogsChanged' staleness reason and catalog snapshot comparison, and wires the default 'check_lockfile_settings' through the new API.

pacquet/crates/lockfile/src/freshness.rs


install.rs Thread catalogs through lockfile settings drift and workspace-state construction +22/-10

Thread catalogs through lockfile settings drift and workspace-state construction

• Extends lockfile freshness checks to pass the loaded catalogs into the lockfile settings drift gate. Updates workspace-state building to record catalog data via a catalogs-aware settings constructor, ensuring later installs detect catalog edits.

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


optimistic_repeat_install.rs Invalidate optimistic repeat-install when workspace catalogs cache changes +49/-6

Invalidate optimistic repeat-install when workspace catalogs cache changes

• Adds explicit catalogs cache comparison for workspace installs, mirroring pnpm’s separate catalogs handling from generic settings drift. Introduces 'current_settings_with_catalogs' to store catalogs in workspace-state settings and helpers to normalize/compare serialized catalogs while filtering nulls.

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


Tests (4)
catalog.rs Add CLI regression test ensuring install reruns after catalog edits +37/-0

Add CLI regression test ensuring install reruns after catalog edits

• Introduces a helper to parse 'pnpm-lock.yaml' and extract the 'catalogs.default' snapshot entry for a dependency. Adds a test that edits 'pnpm-workspace.yaml' catalog versions and asserts a subsequent 'pacquet install' refreshes the lockfile snapshot.

pacquet/crates/cli/tests/catalog.rs


tests.rs Add unit tests for catalog snapshot drift detection +105/-1

Add unit tests for catalog snapshot drift detection

• Adds fixtures and assertions validating that catalog snapshots matching config pass, missing snapshots are tolerated, and changed/removed snapshot entries produce 'StalenessReason::CatalogsChanged'. Provides helper to construct 'LockfileSettingsCheck' for tests.

pacquet/crates/lockfile/src/freshness/tests.rs


tests.rs Update workspace-state builder tests for new catalogs parameter +3/-0

Update workspace-state builder tests for new catalogs parameter

• Adjusts 'build_workspace_state' tests to pass an empty catalogs map now required by the function signature.

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


tests.rs Add repeat-install regression test for catalogs cache invalidation +66/-2

Add repeat-install regression test for catalogs cache invalidation

• Adds a workspace-only check helper that passes catalogs into the repeat-install gate. Introduces a test that writes workspace-state with one catalogs set and asserts the fast path is skipped when the current catalogs differ.

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


Other (1)
Cargo.toml Add catalogs types dependency to lockfile crate +1/-0

Add catalogs types dependency to lockfile crate

• Adds 'pacquet-catalogs-types' as a workspace dependency so lockfile freshness logic can compare config catalogs against the lockfile snapshot.

pacquet/crates/lockfile/Cargo.toml


Grey Divider

Qodo Logo

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

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 86f5df4

@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.

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

600-685: 💤 Low value

Optional: Consider adding a test for the "config adds new catalog entry" scenario.

The current tests cover the core scenarios well. To make the asymmetric ignore behavior more explicit, consider adding a test where:

  • Lockfile has catalogs.default.react: ^18.2.0
  • Config has both react: ^18.2.0 AND vue: ^3.0.0 (new entry)
  • Assert: check passes (new config entries not in snapshot are ignored)

This would document the behavior that removing snapshot entries triggers drift (test at line 670) but adding new config entries does not.

🤖 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/lockfile/src/freshness/tests.rs` around lines 600 - 685, Add a
new unit test to document that new catalog entries present in the config but
absent from the lockfile snapshot are ignored: create a test (e.g.,
check_settings_ignores_new_catalog_entries_in_config) that parses a Lockfile
containing catalogs.default.react specifier ^18.2.0, builds a Catalogs via
Catalogs::from with both "react": "^18.2.0" and a new "vue": "^3.0.0", and
assert that check_lockfile_settings_with_catalogs(&lockfile,
settings_check(&catalogs)).is_ok(); use the same helper functions and types
shown (Lockfile parsing, Catalogs::from, settings_check,
check_lockfile_settings_with_catalogs) so the test mirrors the existing
patterns.
🤖 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.

Nitpick comments:
In `@pacquet/crates/lockfile/src/freshness/tests.rs`:
- Around line 600-685: Add a new unit test to document that new catalog entries
present in the config but absent from the lockfile snapshot are ignored: create
a test (e.g., check_settings_ignores_new_catalog_entries_in_config) that parses
a Lockfile containing catalogs.default.react specifier ^18.2.0, builds a
Catalogs via Catalogs::from with both "react": "^18.2.0" and a new "vue":
"^3.0.0", and assert that check_lockfile_settings_with_catalogs(&lockfile,
settings_check(&catalogs)).is_ok(); use the same helper functions and types
shown (Lockfile parsing, Catalogs::from, settings_check,
check_lockfile_settings_with_catalogs) so the test mirrors the existing
patterns.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0fa8ceb8-c912-404b-947c-69b376dea99b

📥 Commits

Reviewing files that changed from the base of the PR and between 187c903 and 86f5df4.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • pacquet/crates/cli/tests/catalog.rs
  • pacquet/crates/lockfile/Cargo.toml
  • pacquet/crates/lockfile/src/freshness.rs
  • pacquet/crates/lockfile/src/freshness/tests.rs
  • pacquet/crates/package-manager/src/install.rs
  • pacquet/crates/package-manager/src/install/tests.rs
  • pacquet/crates/package-manager/src/optimistic_repeat_install.rs
  • pacquet/crates/package-manager/src/optimistic_repeat_install/tests.rs
✅ Files skipped from review due to trivial changes (1)
  • pacquet/crates/lockfile/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (6)
  • pacquet/crates/package-manager/src/install/tests.rs
  • pacquet/crates/cli/tests/catalog.rs
  • pacquet/crates/lockfile/src/freshness.rs
  • pacquet/crates/package-manager/src/optimistic_repeat_install.rs
  • pacquet/crates/package-manager/src/install.rs
  • pacquet/crates/package-manager/src/optimistic_repeat_install/tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
pacquet/**/*.rs

📄 CodeRabbit inference engine (pacquet/AGENTS.md)

pacquet/**/*.rs: Log emissions are part of matching pnpm — when porting a function that fires pnpm:<channel> events through globalLogger, logger.debug(...), or streamParser.write(...), mirror the call site, payload, and ordering so @pnpm/cli.default-reporter parses pacquet's NDJSON the same way
Declare a newtype wrapper for branded string types instead of collapsing the brand into a plain String or &str in Rust
If upstream TypeScript always validates before construction of a branded string, validate in the Rust wrapper too via TryFrom<String> and/or FromStr and do not provide an infallible public constructor
If upstream TypeScript never validates a branded string, just brand for type-safety in Rust by exposing an infallible From<String> constructor
If upstream TypeScript occasionally constructs a branded string without validation, expose from_str_unchecked in Rust as an escape hatch alongside the validating constructor
Match upstream serde behavior for branded strings crossing JSON, YAML, or INI boundaries by using #[serde(try_from = "String")] for deserialization and #[serde(into = "String")] for serialization
Derive simple conversions for branded strings using #[derive(derive_more::From)] and #[derive(derive_more::Into)] instead of handwriting impl blocks; use manual impl only when conversion needs custom logic
Model TypeScript string literal unions (like 'auto' | 'always' | 'never') as Rust enums instead of newtype wrappers, since the set of valid values is closed
Treat TypeScript string template literal types (like `${string}@${string}`) the same as branded string types in Rust, using a newtype wrapper with validation
Follow the code style guide in CODE_STYLE_GUIDE.md — imports, modules, naming, ownership and borrowing, parameter type selection, trait bounds, pattern matching, pipe-trait, error handling, test layout, and cloning of Arc and Rc
Choose owned vs. borrowed parameters to minimize copies; widen to t...

Files:

  • pacquet/crates/lockfile/src/freshness/tests.rs
🧠 Learnings (6)
📚 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/lockfile/src/freshness/tests.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/lockfile/src/freshness/tests.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/lockfile/src/freshness/tests.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/tests.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/lockfile/src/freshness/tests.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/lockfile/src/freshness/tests.rs
🔇 Additional comments (6)
pacquet/crates/lockfile/src/freshness/tests.rs (6)

1-11: LGTM!


25-35: LGTM!


605-621: LGTM!


623-634: LGTM!


636-668: LGTM!


670-685: LGTM!

@github-actions

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

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 3.966 ± 0.103 3.805 4.098 1.89 ± 0.14
pacquet@main 3.935 ± 0.117 3.818 4.199 1.88 ± 0.14
pnpr@HEAD 2.153 ± 0.130 1.975 2.336 1.03 ± 0.09
pnpr@main 2.096 ± 0.145 1.922 2.371 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 3.9657185697800004,
      "stddev": 0.10346409625851508,
      "median": 3.9615679901800003,
      "user": 3.8502562399999993,
      "system": 3.3206070399999996,
      "min": 3.80513191218,
      "max": 4.09805198018,
      "times": [
        4.001287645180001,
        3.87244465018,
        4.09805198018,
        4.06736636818,
        4.06765935418,
        3.90919503718,
        4.04952781618,
        3.86467259918,
        3.92184833518,
        3.80513191218
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 3.9350989522799997,
      "stddev": 0.11687072020525434,
      "median": 3.89110322368,
      "user": 3.8548601399999995,
      "system": 3.32639574,
      "min": 3.8181279511799997,
      "max": 4.19870979918,
      "times": [
        3.95469144018,
        3.8451905051799997,
        3.88349559418,
        3.8181279511799997,
        3.87419312218,
        4.0598056191800005,
        3.89871085318,
        3.85123358618,
        3.96683105218,
        4.19870979918
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.15323049838,
      "stddev": 0.1300570446960446,
      "median": 2.11803487568,
      "user": 2.69140654,
      "system": 2.8389105399999996,
      "min": 1.9753972191800002,
      "max": 2.3363762541799997,
      "times": [
        2.04275734818,
        2.29023387218,
        2.08665364318,
        2.3363762541799997,
        2.1494161081799996,
        2.07349376618,
        2.33387510118,
        2.04887146518,
        2.1952302061799998,
        1.9753972191800002
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.09635932008,
      "stddev": 0.14501334313705147,
      "median": 2.07147621668,
      "user": 2.6997371400000003,
      "system": 2.85464654,
      "min": 1.9223052611800002,
      "max": 2.37142347518,
      "times": [
        1.9780548631800001,
        1.99425576118,
        2.0654982601799996,
        2.37142347518,
        2.07745417318,
        1.9624107001800002,
        1.9223052611800002,
        2.1199442341799997,
        2.23419372118,
        2.2380527511799997
      ]
    }
  ]
}

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

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 611.5 ± 11.3 595.4 627.4 1.01 ± 0.02
pacquet@main 606.1 ± 6.1 593.4 614.0 1.00
pnpr@HEAD 670.6 ± 16.6 646.1 710.8 1.11 ± 0.03
pnpr@main 665.3 ± 29.6 631.4 739.9 1.10 ± 0.05
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.61148069272,
      "stddev": 0.01132089162990104,
      "median": 0.6088791797200002,
      "user": 0.35889622,
      "system": 1.28113324,
      "min": 0.5953892412200001,
      "max": 0.62742775122,
      "times": [
        0.6110896262200001,
        0.6066687332200001,
        0.6231385992200001,
        0.6273518812200001,
        0.6020147402200001,
        0.5953892412200001,
        0.61406552422,
        0.6010222662200001,
        0.62742775122,
        0.6066385642200001
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.60606739532,
      "stddev": 0.006144617325348355,
      "median": 0.6066993412200001,
      "user": 0.36455782000000003,
      "system": 1.27665754,
      "min": 0.5933516132200001,
      "max": 0.61396769922,
      "times": [
        0.60535623522,
        0.6023680252200001,
        0.6111672972200001,
        0.6118132072200001,
        0.6080424472200001,
        0.5933516132200001,
        0.6023616822200001,
        0.6025981572200001,
        0.6096475892200001,
        0.61396769922
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6706269073200002,
      "stddev": 0.016629044193292742,
      "median": 0.6692184697200001,
      "user": 0.37930402,
      "system": 1.3222870400000002,
      "min": 0.64608426222,
      "max": 0.7108020572200001,
      "times": [
        0.7108020572200001,
        0.6606802962200001,
        0.6706987002200001,
        0.64608426222,
        0.6716513882200001,
        0.66090667422,
        0.66701394022,
        0.67778778922,
        0.6677382392200001,
        0.6729057262200001
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.6652952737200001,
      "stddev": 0.02957553679851492,
      "median": 0.6638885687200001,
      "user": 0.3771773199999999,
      "system": 1.30921054,
      "min": 0.6314390232200001,
      "max": 0.7398829682200001,
      "times": [
        0.6627697562200001,
        0.6712388022200001,
        0.6712301702200001,
        0.6314390232200001,
        0.6650073812200001,
        0.6479569422200001,
        0.6459192302200001,
        0.6460221342200001,
        0.6714863292200001,
        0.7398829682200001
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.169 ± 0.051 4.091 4.218 1.92 ± 0.12
pacquet@main 4.176 ± 0.037 4.114 4.238 1.93 ± 0.12
pnpr@HEAD 2.184 ± 0.123 1.990 2.338 1.01 ± 0.08
pnpr@main 2.169 ± 0.131 2.005 2.411 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.16861883246,
      "stddev": 0.05144368238332586,
      "median": 4.18457853446,
      "user": 3.7775097200000003,
      "system": 3.247822899999999,
      "min": 4.09097077496,
      "max": 4.21763142796,
      "times": [
        4.09576459296,
        4.20827347096,
        4.20682037096,
        4.10308435996,
        4.1817878769600005,
        4.09097077496,
        4.18008852096,
        4.21763142796,
        4.2143977369600005,
        4.18736919196
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.176426306160001,
      "stddev": 0.037006365430495916,
      "median": 4.18275748146,
      "user": 3.79602852,
      "system": 3.2577073,
      "min": 4.1137147699600005,
      "max": 4.23778386796,
      "times": [
        4.1793137949600005,
        4.23778386796,
        4.18674585696,
        4.16197423096,
        4.18620116796,
        4.15761263396,
        4.1137147699600005,
        4.12991496996,
        4.20495747196,
        4.20604429696
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.18388616886,
      "stddev": 0.12259543863925924,
      "median": 2.19728011846,
      "user": 2.53801542,
      "system": 2.7644962,
      "min": 1.98995014896,
      "max": 2.33824630296,
      "times": [
        2.01246834196,
        2.2722193009600002,
        2.2583632059600003,
        2.1187744039600003,
        2.33824630296,
        2.27586478696,
        2.1355032079600003,
        2.13619703096,
        2.30127495796,
        1.98995014896
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.16924271416,
      "stddev": 0.13054323744733323,
      "median": 2.14679437396,
      "user": 2.5686706200000002,
      "system": 2.7669571,
      "min": 2.00460984396,
      "max": 2.4112114899600003,
      "times": [
        2.2113565469600003,
        2.03433235596,
        2.23048847096,
        2.4112114899600003,
        2.00460984396,
        2.04700323996,
        2.3314899329600003,
        2.15172055396,
        2.14186819396,
        2.1283465129600003
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 1.348 ± 0.036 1.311 1.436 2.11 ± 0.06
pacquet@main 1.387 ± 0.054 1.346 1.529 2.17 ± 0.09
pnpr@HEAD 0.640 ± 0.009 0.628 0.659 1.00
pnpr@main 0.642 ± 0.010 0.628 0.666 1.00 ± 0.02
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 1.3484204780000002,
      "stddev": 0.036140543457678774,
      "median": 1.3356384697,
      "user": 1.33344036,
      "system": 1.6922674200000003,
      "min": 1.3108149712000001,
      "max": 1.4357113642000001,
      "times": [
        1.3241721362,
        1.3282551302,
        1.3387417152,
        1.4357113642000001,
        1.3743433812,
        1.3444380282000001,
        1.3325352242000001,
        1.3661910232,
        1.3290018062000002,
        1.3108149712000001
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 1.3870855763,
      "stddev": 0.053704544946753,
      "median": 1.3662539262000002,
      "user": 1.35642546,
      "system": 1.7238543199999998,
      "min": 1.3460368412000001,
      "max": 1.5288942602000002,
      "times": [
        1.3460368412000001,
        1.5288942602000002,
        1.4117613002,
        1.3630933522000002,
        1.3624715272,
        1.3694145002000002,
        1.3939085752,
        1.3838288652000001,
        1.3599610432,
        1.3514854982000002
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6399357395,
      "stddev": 0.008519082020001737,
      "median": 0.6378907572000001,
      "user": 0.32239455999999994,
      "system": 1.25342702,
      "min": 0.6281491902,
      "max": 0.6585410372,
      "times": [
        0.6281491902,
        0.6382460612,
        0.6375354532,
        0.6367786062,
        0.6463704612000001,
        0.6402347422,
        0.6457802042,
        0.6340140952000001,
        0.6337075442,
        0.6585410372
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.6416583,
      "stddev": 0.010329244588443254,
      "median": 0.6423891397000001,
      "user": 0.33183216,
      "system": 1.2502074200000002,
      "min": 0.6284170572000001,
      "max": 0.6655115222,
      "times": [
        0.6412195612,
        0.6423272962000001,
        0.6432532872000001,
        0.6424509832,
        0.6655115222,
        0.6358940712000001,
        0.6288553162,
        0.6437209812,
        0.6284170572000001,
        0.6449329242
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 3.038 ± 0.038 2.985 3.118 4.71 ± 0.08
pacquet@main 3.068 ± 0.033 3.021 3.127 4.76 ± 0.08
pnpr@HEAD 0.645 ± 0.008 0.632 0.661 1.00
pnpr@main 0.658 ± 0.024 0.638 0.724 1.02 ± 0.04
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 3.0383262291,
      "stddev": 0.03753261558143003,
      "median": 3.0315685708,
      "user": 1.7823595399999999,
      "system": 1.9688726200000002,
      "min": 2.9846095283,
      "max": 3.1182121403000003,
      "times": [
        3.0293352963,
        2.9846095283,
        2.9988832693000003,
        3.0562256003,
        3.0243706863,
        3.0201515533000003,
        3.1182121403000003,
        3.0530397133,
        3.0338018453,
        3.0646326583000003
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 3.0682329483,
      "stddev": 0.03349267088811908,
      "median": 3.0633140718,
      "user": 1.78204174,
      "system": 2.04864462,
      "min": 3.0209045733,
      "max": 3.1269539233,
      "times": [
        3.0447651713,
        3.0562034683,
        3.0595460303,
        3.0209045733,
        3.0670821133,
        3.0356787293000003,
        3.0859779773000002,
        3.1269539233,
        3.0694522303,
        3.1157652663
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.64493435,
      "stddev": 0.008298119291685602,
      "median": 0.6444765093,
      "user": 0.32713133999999994,
      "system": 1.26726082,
      "min": 0.6320179553,
      "max": 0.6612066513,
      "times": [
        0.6438473193,
        0.6612066513,
        0.6320179553,
        0.6485067023,
        0.6387423823,
        0.6452030103,
        0.6372251723,
        0.6446893493,
        0.6442636693,
        0.6536412883
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.6578822008,
      "stddev": 0.024167365784456437,
      "median": 0.6545143693,
      "user": 0.32859604,
      "system": 1.27033242,
      "min": 0.6383614623,
      "max": 0.7238320613,
      "times": [
        0.6436459043,
        0.6544258723,
        0.6454185513,
        0.6582933213,
        0.6554007853,
        0.6461193593,
        0.6383614623,
        0.6546028663,
        0.7238320613,
        0.6587218243
      ]
    }
  ]
}

@github-actions

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12382
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,168.62 ms
(-13.03%)Baseline: 4,792.91 ms
5,751.49 ms
(72.48%)
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
🚷 view threshold
3,038.33 ms
(-1.32%)Baseline: 3,078.83 ms
3,694.60 ms
(82.24%)
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
🚷 view threshold
1,348.42 ms
(+13.74%)Baseline: 1,185.51 ms
1,422.61 ms
(94.78%)
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
🚷 view threshold
3,965.72 ms
(-23.66%)Baseline: 5,194.56 ms
6,233.48 ms
(63.62%)
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
🚷 view threshold
611.48 ms
(-6.46%)Baseline: 653.68 ms
784.41 ms
(77.95%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12382
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,183.89 ms
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
644.93 ms
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
639.94 ms
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
⚠️ NO THRESHOLD
2,153.23 ms
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
670.63 ms
🐰 View full continuous benchmarking report in Bencher

@zkochan zkochan merged commit 29981f6 into main Jun 13, 2026
28 checks passed
@zkochan zkochan deleted the fix-pacquet branch June 13, 2026 16:44
truffle-dev added a commit to truffle-dev/pnpm that referenced this pull request Jun 16, 2026
The catalog-registry-range test reaches catalogs_cache_matches now that
the workspace state records catalogs (pnpm#12382). Stamp the state
with the test's catalogs so the cache comparison passes and the spec
deref is what gets exercised, not the catalogs-outdated bail.
zkochan pushed a commit to truffle-dev/pnpm that referenced this pull request Jun 16, 2026
The catalog-registry-range test reaches catalogs_cache_matches now that
the workspace state records catalogs (pnpm#12382). Stamp the state
with the test's catalogs so the cache comparison passes and the spec
deref is what gets exercised, not the catalogs-outdated bail.
zkochan pushed a commit to truffle-dev/pnpm that referenced this pull request Jun 16, 2026
The catalog-registry-range test reaches catalogs_cache_matches now that
the workspace state records catalogs (pnpm#12382). Stamp the state
with the test's catalogs so the cache comparison passes and the spec
deref is what gets exercised, not the catalogs-outdated bail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants