Skip to content

ci(pnpr): benchmark the install accelerator (new Bencher pnpr testbed)#12154

Merged
zkochan merged 4 commits into
mainfrom
bench/pnpr-integrated-benchmark
Jun 3, 2026
Merged

ci(pnpr): benchmark the install accelerator (new Bencher pnpr testbed)#12154
zkochan merged 4 commits into
mainfrom
bench/pnpr-integrated-benchmark

Conversation

@zkochan

@zkochan zkochan commented Jun 2, 2026

Copy link
Copy Markdown
Member

What

Benchmarks the pnpr install-accelerator path end to end and tracks it in a new Bencher pnpr testbed, folded into the existing pacquet integrated-benchmark so the two co-run.

Orchestrator: a new pnpr@<rev> target

pacquet/tasks/integrated-benchmark gains a pnpr@<rev> target kind. It builds both the pacquet client and the pnpr server from the revision's monorepo clone, boots a per-target pnpr server with an isolated --storage, and points the client at it via PNPR_SERVER (sourced from a generated .pnpr-env). The server is killed on drop; its store is wiped once before the run so the hyperfine warmup primes a warm long-running server.

One workflow, two testbeds

The pnpr server is built from the pacquet-* resolver/store/tarball crates, so a pacquet change can move the pnpr-accelerated numbers as much as the direct ones. They share a trigger surface and should co-run — so rather than a second workflow posting a second comment on every pacquet PR, the existing pacquet-integrated-benchmark workflow now measures both in one run:

  • Every scenario runs pacquet@<rev> (direct) and pnpr@<rev> (accelerated), so pnpr@HEAD vs pacquet@HEAD is the pnpr-vs-direct ratio in one hyperfine table.
  • One combined comment; two separate Bencher testbedspacquet and pnpr — so each keeps its own HEAD-vs-main regression gate.
  • Trigger gains pnpr/**.

Cache axes

Both tools run all four scenarios. The cold-store scenarios wipe the client store between iterations while the per-target pnpr server stays warm — i.e. pnpr's cold-client-vs-warm-server shape, the realistic CI case (empty local store hitting a warm shared server). The hot-store scenarios keep the client store warm. A cold-server axis (server restarted per iteration) is a deliberate follow-up — it needs per-iteration server restart machinery.

Validation

  • cargo check, clippy --deny warnings, cargo fmt --check, and the orchestrator's unit tests pass; the pre-push Rust hook passed.
  • actionlint is at parity with the prior workflow (only the pre-existing intentional SC2086 word-split notes on \$BENCHMARK_TARGETS).
  • Not yet run end to end — the first CI run is where any pacquet-via-pnpr integration wrinkle would surface. Draft for that reason.

Manual step before merge

The Bencher pnpr testbed must be created in the pnpm Bencher project; --testbed pnpr does not auto-create it.


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

Summary by CodeRabbit

  • New Features

    • Added pnpr install-accelerator support to integrated benchmarks alongside pacquet, including running pnpr servers and per-target accelerator wiring.
    • Benchmark outputs now produce separate results for pacquet and pnpr and upload both testbeds.
  • CI / Tests

    • CI matrix and workflows expanded to cover pacquet and pnpr scenarios; increased precompile and benchmark timeouts for the larger target set.

…elerator

Measures the pnpr-accelerated install path end to end. A new `pnpr@<rev>`
target in the integrated-benchmark orchestrator builds both the `pacquet`
client and the `pnpr` server from the revision's monorepo clone, boots a
per-target pnpr server with an isolated `--storage`, and points the client
at it via `PNPR_SERVER`.

Reusing the existing multi-target hyperfine model gives both comparisons:

- `pnpr@HEAD pacquet@HEAD` -> pnpr-vs-direct ratio in one run (same client,
  with and without the accelerator).
- `pnpr@HEAD pnpr@main` -> regression delta tracked in a new Bencher `pnpr`
  testbed.

Two CI workflows mirror the fork-safe two-stage pacquet pattern, triggered
on pnpr/**, pacquet/crates/pnpr-client/**, and pacquet/crates/config/**
(the pnprServer plumbing), running the hot-cache/hot-store restore and
fresh-install scenarios that model a warm long-running server.
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

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: 31f2f926-e75f-459c-be3d-c64ad7617048

📥 Commits

Reviewing files that changed from the base of the PR and between 4c3f7c4 and f752b03.

📒 Files selected for processing (4)
  • .github/workflows/pacquet-integrated-benchmark-comment.yml
  • .github/workflows/pacquet-integrated-benchmark.yml
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • .github/workflows/pacquet-integrated-benchmark-comment.yml
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📜 Recent 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). (10)
  • GitHub Check: Lint and Test (ubuntu-latest)
  • GitHub Check: Code Coverage
  • GitHub Check: Doc
  • GitHub Check: Lint and Test (windows-latest)
  • GitHub Check: Dylint
  • GitHub Check: Lint and Test (macos-latest)
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Compile & Lint

📝 Walkthrough

Walkthrough

Adds pnpr as a benchmark target and measures pacquet both directly and via pnpr: CLI parsing, unified repo/build dispatch, pnpr server lifecycle with readiness and env provisioning, conditional install script sourcing, expanded workflow matrix/timeouts, and generation/upload of two Bencher JSONs.

Changes

Pnpr Install-Accelerator Benchmarking

Layer / File(s) Summary
CLI argument parsing for pnpr targets
pacquet/tasks/integrated-benchmark/src/cli_args.rs, pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
TargetKind adds Pnpr; TargetSpec::from_str accepts pnpr@<rev> and validates non-empty <rev>; tests added/updated for parsing and errors.
Benchmark identifiers and path resolvers
pacquet/tasks/integrated-benchmark/src/work_env.rs
Adds BenchId::PnprRevision, pnpr_source_dir, maps TargetKind::Pnpr to BenchId::PnprRevision, and ensures pnpr installs use the pacquet client binary.
Workflow CI triggers and benchmark matrix
.github/workflows/pacquet-integrated-benchmark.yml
Adds pnpr/** filters; expands BENCHMARK_TARGETS to include pacquet@<rev> and pnpr@<rev> comparisons; increases precompile/timeouts for the expanded target superset.
Build dispatch and repo gating
pacquet/tasks/integrated-benchmark/src/main.rs, pacquet/tasks/integrated-benchmark/src/work_env.rs
Introduce needs_pacquet_repo (true for pacquet or pnpr targets); build() routes pnpr targets to build_pnpr() which syncs revision and builds both pacquet and pnpr binaries; init passes pnpr flag into script creation.
Pnpr server orchestration and benchmark runtime
pacquet/tasks/integrated-benchmark/src/work_env.rs
Pre-benchmark cleanup wipes per-target pnpr-storage; start_pnpr_servers()/start_pnpr_server() spawn isolated pnpr processes, select free ports, poll TCP readiness, write .pnpr-env with PNPR_SERVER, and maintain lifecycle via a PnprServer guard.
Conditional install script sourcing
pacquet/tasks/integrated-benchmark/src/work_env.rs
create_install_script(needs_pnpr_env) now sources ./.pnpr-env when needs_pnpr_env is true before executing the install command.
Bencher result shaping and dual uploads
.github/workflows/pacquet-integrated-benchmark.yml, .github/workflows/pacquet-integrated-benchmark-comment.yml
Produce bencher-results.json (pacquet) and bencher-results-pnpr.json (pnpr) by filtering scenario commands and renaming; stage both artifacts; upload both via an upload(testbed,file) helper that skips missing files.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • pnpm/pnpm#11741: Overlaps on integrated-benchmark target infrastructure and orchestration where pnpr support was introduced/reshaped.
  • pnpm/pnpm#11913: Modifies BENCHMARK_TARGETS and workflow target-selection logic that this PR also changes.
  • pnpm/pnpm#11883: Touches Bencher upload/invocation paths that overlap with this PR’s dual-upload adjustments.

Suggested reviewers

  • KSXGitHub

"🐰 Two testbeds now hop together through the benchmark,
One direct, one swift via pnpr's gateway light;
Carrots of data line up in neat arrays—
Ratios measured, hops counted, quiet delight. 🥕"

🚥 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 clearly and specifically describes the main change: adding benchmarking for the pnpr install-accelerator with a new Bencher testbed, which is directly reflected in the PR's core objective and 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 bench/pnpr-integrated-benchmark

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 2, 2026

Copy link
Copy Markdown
Contributor

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.03      9.1±0.41ms   478.8 KB/sec    1.00      8.8±0.14ms   495.5 KB/sec

@codecov-commenter

codecov-commenter commented Jun 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.57%. Comparing base (8bc25f3) to head (f752b03).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12154      +/-   ##
==========================================
- Coverage   87.61%   87.57%   -0.05%     
==========================================
  Files         268      268              
  Lines       30712    30761      +49     
==========================================
+ Hits        26909    26939      +30     
- Misses       3803     3822      +19     

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

zkochan added 2 commits June 3, 2026 01:34
The pnpr server is built from the pacquet resolver/store/tarball crates,
so any pacquet change can move the pnpr-accelerated numbers as much as the
direct ones. That means the two benchmarks share a trigger surface and
should co-run — so rather than a separate pnpr workflow posting a second
comment on every pacquet PR, measure both in one run.

The pacquet integrated-benchmark workflow now also runs `pnpr@<rev>`
targets in the two hot-cache/hot-store scenarios (a warm long-running
server is pnpr's realistic shape), emits one combined report/comment, and
uploads to two Bencher testbeds: `pacquet` (direct, all scenarios) and
`pnpr` (accelerated, hot scenarios). The trigger gains `pnpr/**`.

Deletes the standalone pnpr-integrated-benchmark{,-comment}.yml added
earlier in this branch.
Run the pnpr targets in the cold-cache/cold-store scenarios too, not just
the hot ones. Those scenarios already wipe the client store between
iterations while the per-target pnpr server store stays warm, so this
measures pnpr's cold-client-vs-warm-server shape — the realistic CI case
(empty local store hitting a warm shared server) — alongside the existing
hot-client numbers.

Both tools now run all four scenarios, so the report tables and both
Bencher testbeds (pacquet, pnpr) cover cold and hot. Collapses the two
target-list env vars into one and bumps the cold-step timeouts for the
extra commands. Table rendering is unchanged.
@zkochan zkochan marked this pull request as ready for review June 2, 2026 23:49
Copilot AI review requested due to automatic review settings June 2, 2026 23:49
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Review Summary by Qodo

Integrate pnpr install-accelerator benchmarking into pacquet workflow

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Add pnpr@ target kind to benchmark install-accelerator end-to-end
  - Builds both pacquet client and pnpr server from revision's monorepo
  - Boots per-target pnpr server with isolated storage, kills on drop
  - Points client at server via PNPR_SERVER env var from .pnpr-env
• Fold pnpr benchmark into existing pacquet integrated-benchmark workflow
  - One run measures both direct install and accelerated path in same hyperfine
  - Uploads to two separate Bencher testbeds: pacquet and pnpr
  - Trigger gains pnpr/** paths alongside pacquet paths
• Expand benchmark scenarios to include pnpr targets
  - Cold-store scenarios wipe client store while server stays warm (realistic CI)
  - Hot-store scenarios keep client store warm across iterations
  - Increases timeouts to accommodate additional benchmark commands
• Add TCP readiness polling and server lifecycle management
  - Wait for pnpr server to accept connections before benchmarking
  - Guards ensure servers killed on drop at end of benchmark run
Diagram
flowchart LR
  A["Target Spec Parser"] -->|"Add pnpr@rev"| B["TargetKind::Pnpr"]
  B -->|"build_pnpr"| C["Build pacquet + pnpr"]
  C -->|"start_pnpr_servers"| D["Boot per-target server"]
  D -->|"TCP poll"| E["Wait for readiness"]
  E -->|"write .pnpr-env"| F["install.bash sources env"]
  F -->|"PNPR_SERVER set"| G["Client routes through server"]
  G -->|"hyperfine runs"| H["Benchmark both tools"]
  H -->|"split results"| I["bencher-results.json"]
  H -->|"split results"| J["bencher-results-pnpr.json"]
  I -->|"upload"| K["pacquet testbed"]
  J -->|"upload"| L["pnpr testbed"]

Loading

Grey Divider

File Changes

1. pacquet/tasks/integrated-benchmark/src/cli_args.rs ✨ Enhancement +11/-4

Add pnpr target kind parsing support

• Add TargetKind::Pnpr enum variant with documentation
• Update FromStr impl to parse pnpr@ target specs
• Update error messages to include pnpr in expected formats

pacquet/tasks/integrated-benchmark/src/cli_args.rs


2. pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs 🧪 Tests +10/-1

Add pnpr target parsing tests

• Add test for parsing pnpr@main target spec
• Update error message assertions to include pnpr format
• Add empty-rev validation test for pnpr targets

pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs


3. pacquet/tasks/integrated-benchmark/src/main.rs ✨ Enhancement +7/-2

Add pnpr target dependency verification

• Add has_pnpr_target check alongside pacquet/pnpm checks
• Consolidate pacquet repo requirement for both pacquet and pnpr targets
• Update cargo requirement check to include pnpr targets

pacquet/tasks/integrated-benchmark/src/main.rs


View more (3)
4. pacquet/tasks/integrated-benchmark/src/work_env.rs ✨ Enhancement +170/-5

Implement pnpr server spawning and lifecycle management

• Add pnpr_source_dir() method mirroring pacquet layout
• Add BenchId::PnprRevision variant and is_pnpr() helper method
• Add build_pnpr() to build both pacquet and pnpr binaries
• Add start_pnpr_servers() and start_pnpr_server() to spawn servers
• Add PnprServer struct with Drop impl to kill servers on cleanup
• Add wait_for_pnpr_ready() TCP polling function with retries
• Update install_command() to handle pnpr targets same as pacquet
• Update create_install_script() to source .pnpr-env for pnpr targets
• Update benchmark() to wipe pnpr-storage and start servers before runs
• Import pick_unused_port, TcpStream, Child, thread, Duration

pacquet/tasks/integrated-benchmark/src/work_env.rs


5. .github/workflows/pacquet-integrated-benchmark-comment.yml ✨ Enhancement +21/-12

Split Bencher uploads to two testbeds

• Add comment explaining two-testbed upload strategy
• Refactor bencher upload into upload() function accepting testbed and file
• Upload to both pacquet and pnpr testbeds from separate result files

.github/workflows/pacquet-integrated-benchmark-comment.yml


6. .github/workflows/pacquet-integrated-benchmark.yml ✨ Enhancement +113/-62

Integrate pnpr into workflow with dual-testbed reporting

• Add pnpr/** to push and pull_request path filters
• Update BENCHMARK_TARGETS to include pnpr@HEAD and pnpr@main
• Expand precompile timeout from 15 to 25 minutes for additional builds
• Increase scenario timeouts to accommodate pnpr commands (10→15, 20→35, 20→25 min)
• Update scenario comments to explain cold-client-vs-warm-server model
• Refactor "Build Bencher-shaped report" into build_bencher_file() function
• Generate separate bencher-results.json and bencher-results-pnpr.json files
• Add summary comment explaining pnpr vs pacquet rows and testbed separation
• Refactor Bencher upload into upload() function for both testbeds
• Stage both bencher result files in artifact

.github/workflows/pacquet-integrated-benchmark.yml


Grey Divider

Qodo Logo

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

Adds end-to-end benchmarking for the pnpr install-accelerator path by introducing a new pnpr@<rev> benchmark target that runs the existing pacquet client against a per-target, long-running pnpr server, and publishes results to a separate Bencher pnpr testbed alongside the existing pacquet testbed.

Changes:

  • Extend the integrated-benchmark orchestrator with a pnpr@<rev> target that builds pacquet + pnpr, boots a per-target pnpr server, and injects PNPR_SERVER via a generated .pnpr-env.
  • Update CLI target parsing/tests to accept pnpr@<rev> and adjust environment validation to treat pnpr like pacquet (needs pacquet repo + cargo).
  • Update GitHub Actions workflows to co-run pacquet and pnpr benchmarks, generate two Bencher-shaped result files, and upload to two Bencher testbeds.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pacquet/tasks/integrated-benchmark/src/work_env.rs Adds pnpr target build + server lifecycle management and wires .pnpr-env sourcing into install.bash.
pacquet/tasks/integrated-benchmark/src/main.rs Ensures pacquet repo/cargo prerequisites are enforced when pnpr targets are present.
pacquet/tasks/integrated-benchmark/src/cli_args.rs Adds TargetKind::Pnpr and updates parsing/error messages.
pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs Adds pnpr target parsing tests and updates error expectations.
.github/workflows/pacquet-integrated-benchmark.yml Runs both pacquet and pnpr targets per scenario, produces two bencher-results JSONs, and uploads both testbeds.
.github/workflows/pacquet-integrated-benchmark-comment.yml Extends PR-side Bencher uploads to include the pnpr testbed from the artifact outputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pacquet/tasks/integrated-benchmark/src/work_env.rs
Comment thread .github/workflows/pacquet-integrated-benchmark-comment.yml
Comment thread .github/workflows/pacquet-integrated-benchmark.yml

@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 `@pacquet/tasks/integrated-benchmark/src/cli_args.rs`:
- Around line 65-69: Update the CLI help text to include the new pnpr target
kind: change the description for CliArgs.targets so it documents that targets
can be "pacquet@<rev>", "pnpm@<rev>" or the new "pnpr@<rev>" (this corresponds
to TargetSpec::from_str now accepting pnpr@<rev>). Locate the help string on the
CliArgs struct (the targets field) and add "pnpr@<rev>" to the examples and any
explanatory text so --help reflects the new supported target kind.

In `@pacquet/tasks/integrated-benchmark/src/work_env.rs`:
- Around line 401-423: Don't use pick_unused_port() (TOCTOU); instead start the
pnpr process asking it to bind an ephemeral port (use "--listen 127.0.0.1:0"
when constructing Command in the Command::new(&binary) block) and then
read/parse the child process output (captured via the stdout/stderr files or a
pipe created when spawning) to obtain the actual bound address/port reported by
pnpr; update the code around pick_unused_port(), the Command::new(&binary)
invocation, and the process handling logic to wait for and extract the reported
listening address from the child's output before proceeding.
🪄 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: 42598102-70aa-4dd1-bc12-335faa897745

📥 Commits

Reviewing files that changed from the base of the PR and between 2b788d5 and 4c3f7c4.

📒 Files selected for processing (6)
  • .github/workflows/pacquet-integrated-benchmark-comment.yml
  • .github/workflows/pacquet-integrated-benchmark.yml
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.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). (8)
  • GitHub Check: Agent
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Lint and Test (ubuntu-latest)
  • GitHub Check: Lint and Test (windows-latest)
  • GitHub Check: Lint and Test (macos-latest)
  • GitHub Check: Run benchmark on ubuntu-latest
  • GitHub Check: Code Coverage
  • GitHub Check: Compile & Lint
🧰 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/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
🧠 Learnings (41)
📓 Common learnings
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-25T12:36:42.202Z
Learning: User-visible changes (CLI flags, defaults, environment variables, lockfile/manifest/state-file formats, error codes/messages, log emissions, store layout, hook semantics) in pnpm must be mirrored to pacquet in the same PR
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11784
File: pacquet/crates/resolving-deps-resolver/src/hoist_peers.rs:120-133
Timestamp: 2026-05-20T23:08:06.093Z
Learning: Pacquet (pnpm's Rust port) has a cardinal rule: "match pnpm exactly — do not fix pnpm quirks unless the same fix has landed in pnpm first." Review comments should not suggest behavioral deviations from upstream pnpm, even when the upstream behavior appears buggy. If a real bug is identified, it must be fixed upstream first.
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Use Conventional Commits with 'pnpr' as the scope in commit messages (e.g., feat(pnpr): ..., fix(pnpr): ...)
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11915
File: pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs:553-617
Timestamp: 2026-05-24T21:11:04.272Z
Learning: In the pacquet Rust port (pnpm/pnpm repo), the `ResolvedPackage.optional` AND-folding on revisit intentionally mirrors pnpm's `resolveDependencies.ts:1627-1648` behavior: only the directly-revisited package's `optional` flag is updated; transitive descendants are not re-walked. pnpm CLI corrects stale optional flags downstream via `copyDependencySubGraph` BFS in `lockfile/pruner/src/index.ts:160-205`, which tracks a `nonOptional` set and re-stamps any package reachable by an all-non-optional path. Pacquet does not yet have this pruner equivalent, so the stale flags flow directly through `dependencies_graph_to_lockfile.rs:409` → `create_virtual_store.rs:762` → `installability.rs:394`. A follow-up to port `copyDependencySubGraph` is planned; until then, do not flag the resolver-layer optional propagation gap as a bug in pacquet PRs — it is intentional parity with pnpm's resolver layer.
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Reference the upstream pnpm commit/PR when porting code from pnpm in commit messages
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Use snapshot tests with `insta` and carefully review diffs when intentional changes alter snapshots; accept with `cargo insta review` only after careful review
Learnt from: KSXGitHub
Repo: pnpm/pnpm PR: 12093
File: pacquet/crates/cli/src/cli_args/run/recursive.rs:290-315
Timestamp: 2026-06-01T08:59:42.161Z
Learning: In pacquet's recursive run implementation (`pacquet/crates/cli/src/cli_args/run/recursive.rs`), the `pnpm-exec-summary.json` format for failed package entries correctly includes `prefix` and `message` fields in addition to `status` and `duration`. This matches pnpm's `ActionFailure` variant in `cli/utils/src/recursiveSummary.ts` and the direct serialization in `exec/commands/src/exec.ts`. There is no `ExecutionStatusInSummary` type in pnpm. The only intentional divergence is omitting the JS `error` field, whose `JSON.stringify` output is non-deterministic due to non-enumerable `Error` properties.
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Port relevant pnpm tests to Rust tests whenever they translate when porting behavior from pnpm
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Tests that need the mocked registry should start `pnpr` through `pacquet-testing-utils`; `cargo test` / `cargo nextest run` should not require a separate `just registry-mock launch` step
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Applies to pnpr/**/pnpr/**/*.rs : Follow the pacquet contributing guide (../pacquet/CONTRIBUTING.md) for test layout and Rust conventions
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Tests that need the mocked registry should start `pnpr` through `pacquet-testing-utils`; `cargo test` / `cargo nextest run` should not require a separate `just registry-mock launch` step

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Prefer `#[cfg_attr(target_os = "windows", ignore = "...")]` (or matching `#[cfg(unix)]` gates) over runtime probe-and-skip helpers for platform-locked tools

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-24T21:11:04.272Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11915
File: pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs:553-617
Timestamp: 2026-05-24T21:11:04.272Z
Learning: In the pacquet Rust port (pnpm/pnpm repo), the `ResolvedPackage.optional` AND-folding on revisit intentionally mirrors pnpm's `resolveDependencies.ts:1627-1648` behavior: only the directly-revisited package's `optional` flag is updated; transitive descendants are not re-walked. pnpm CLI corrects stale optional flags downstream via `copyDependencySubGraph` BFS in `lockfile/pruner/src/index.ts:160-205`, which tracks a `nonOptional` set and re-stamps any package reachable by an all-non-optional path. Pacquet does not yet have this pruner equivalent, so the stale flags flow directly through `dependencies_graph_to_lockfile.rs:409` → `create_virtual_store.rs:762` → `installability.rs:394`. A follow-up to port `copyDependencySubGraph` is planned; until then, do not flag the resolver-layer optional propagation gap as a bug in pacquet PRs — it is intentional parity with pnpm's resolver layer.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Use snapshot tests with `insta` and carefully review diffs when intentional changes alter snapshots; accept with `cargo insta review` only after careful review

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:24.760Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Prefer existing pacquet-* crates over writing new code; check pacquet-tarball, pacquet-crypto-hash, pacquet-crypto-shasums-file, pacquet-package-manifest, pacquet-network, pacquet-registry, pacquet-fs, and pacquet-diagnostics before implementing non-trivial functionality

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Tests must not be tolerant of missing build/runtime environment by silently returning early when a tool isn't found — let the test panic when a required tool is absent

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Port relevant pnpm tests to Rust tests whenever they translate when porting behavior from pnpm

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/*.rs : Search for existing shared helpers before writing new code; shared helpers tend to live in `crates/fs`, `crates/testing-utils`, and `crates/diagnostics`

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:24.760Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Applies to pnpr/**/pnpr/**/*.rs : Follow the pacquet contributing guide (../pacquet/CONTRIBUTING.md) for test layout and Rust conventions

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:24.760Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Applies to pnpr/**/pnpr/**/*.rs : Follow the pacquet code-style guide (../pacquet/CODE_STYLE_GUIDE.md) for Rust-level conventions including imports, naming, ownership, and error handling

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/Cargo.toml : Check whether the workspace already depends on something suitable in `[workspace.dependencies]` in the root `Cargo.toml` before adding a new dependency

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
📚 Learning: 2026-05-20T20:41:30.632Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11773
File: pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs:115-117
Timestamp: 2026-05-20T20:41:30.632Z
Learning: In the pacquet Rust port of pnpm, the `is_http_url` helper in `pacquet/crates/resolving-tarball-resolver/src/tarball_resolver.rs` intentionally uses `bare.starts_with("http:") || bare.starts_with("https:")` (not `"http://"` / `"https://"`) to match upstream pnpm's `startsWith('http:')` / `startsWith('https:')` check byte-for-byte. Pacquet's cardinal rule (pacquet/AGENTS.md) requires matching pnpm even on quirks; malformed non-URL inputs are rejected downstream by `reqwest::Url::parse` as a `ResolveError`.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
📚 Learning: 2026-06-02T13:18:26.437Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 12134
File: pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs:311-325
Timestamp: 2026-06-02T13:18:26.437Z
Learning: In pacquet's lockfile resolution verifier (`pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs`), URL-keyed tarball dependencies do NOT need a separate `non_semver_version` field in `VerifyCtx`. Unlike the TypeScript side (which derives `version` from `snapshot.version` and threads `nonSemverVersion` separately), pacquet's `collect_candidates` takes `version` from the lockfile key suffix. For a URL-keyed dep the key is `name@<url>`, so `ctx.version` is the URL string, which fails `node_semver::Version::parse(ctx.version)` and the existing guard `if node_semver::Version::parse(ctx.version).is_err() { return ResolutionVerification::Ok; }` already skips the registry lookup correctly. Adding a `non_semver_version` field to `VerifyCtx` for this purpose would be inert.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
📚 Learning: 2026-05-24T21:11:04.272Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11915
File: pacquet/crates/resolving-deps-resolver/src/resolve_dependency_tree.rs:553-617
Timestamp: 2026-05-24T21:11:04.272Z
Learning: In pacquet (pnpm/pnpm repo), `ResolvedPackage.optional` AND-folding intentionally mirrors pnpm's resolveDependencies.ts:1627-1648 revisit behavior: only the directly-visited package's `optional` flag is updated on revisit, not transitive descendants. pnpm CLI corrects stale optional flags via `copyDependencySubGraph` BFS in `lockfile/pruner/src/index.ts:160-205`. Pacquet does not yet have this pruner equivalent, so raw `node.optional` flows directly into snapshot/virtual-store via `dependencies_graph_to_lockfile.rs:409` → `create_virtual_store.rs:762` → `installability.rs:394`. A follow-up issue to port `copyDependencySubGraph` is planned.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
📚 Learning: 2026-05-25T14:58:11.105Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11931
File: pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs:560-589
Timestamp: 2026-05-25T14:58:11.105Z
Learning: In `pacquet/crates/resolving-npm-resolver/src/create_npm_resolution_verifier.rs`, all per-`(registry, name[, version])` caches in `NpmResolutionVerifier` (`published_at`, `full_meta`, `full_meta_for_trust`, `abbreviated_meta`, `local_meta`) intentionally use the same pattern: lock → miss-check → release lock → await fetch/load → re-acquire lock → insert. This uniform pattern is deliberate; do not flag individual caches for using it. The known follow-up improvement (replacing the pattern with `tokio::sync::OnceCell` per key inside a `Mutex<HashMap<…>>`) is tracked as a future structural change to cover all five caches simultaneously.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.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/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: The `pre-push` hook runs `pacquet/scripts/pre-push-rust.sh` which checks `rustfmt`, `taplo`, `cargo doc` with `-D warnings`, and `cargo dylint`

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Match how the same feature is implemented in the TypeScript pnpm CLI — any change in pacquet must match pnpm's behavior, logic, edge cases, config resolution, error messages, file/lockfile formats, and existing tests

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-20T20:41:50.322Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11773
File: pacquet/crates/package-manager/src/install_package_from_registry.rs:111-114
Timestamp: 2026-05-20T20:41:50.322Z
Learning: In pacquet (pnpm/pnpm repo, Rust codebase), `install_package_from_registry` is the npm-only install path. The npm resolver always stamps `ResolveResult.id` (a `PkgResolutionId`) as `nameversion`. Parsing it back through `PkgNameVer` with `.expect()` is intentional — a parse failure means a mis-dispatch bug, not malformed external input. Per pacquet's CLAUDE.md: "Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees." Do not suggest replacing such `.expect()` calls with graceful error handling.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/main.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/*.rs : Tests are documentation — do not duplicate test scenarios, edge cases, failure modes, or worked examples in prose when they are already captured by tests

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
📚 Learning: 2026-05-20T21:18:56.391Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11778
File: pacquet/crates/resolving-local-resolver/tests/resolve.rs:365-372
Timestamp: 2026-05-20T21:18:56.391Z
Learning: In `pacquet/crates/resolving-local-resolver/tests/resolve.rs`, the test `fail_when_resolving_from_not_existing_directory_an_injected_dependency` intentionally uses `injected: false`. The test is a verbatim port of the upstream pnpm TypeScript test (resolving/local-resolver/test/index.ts at ef87f3ccff). The `injected` flag only affects the file/link protocol choice for plain directory paths; when the `file:` scheme is explicit in the bare specifier, the flag has no effect on the resolution code path. The misleading test name is inherited from upstream.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Consult `plans/TEST_PORTING.md` before adding ported tests and update its checkboxes as items land; use `known_failures` modules and `pacquet_testing_utils::allow_known_failure!` at the not-yet-implemented boundary

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
📚 Learning: 2026-05-29T18:03:24.760Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Applies to pnpr/**/pnpr/crates/**/Cargo.toml : Cargo.toml files for new registry-only crates must use the pnpr- prefix for the package name

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-20T23:23:43.636Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11788
File: pacquet/crates/lockfile/src/snapshot_dep_ref.rs:52-56
Timestamp: 2026-05-20T23:23:43.636Z
Learning: In the pacquet lockfile crate, both `SnapshotDepRef::Link` and `ImporterDepVersion::Link` intentionally use raw `Link(String)` (not a newtype) for the link target. Upstream pnpm stores `link:` targets verbatim without validation (`refToRelative` only checks for the literal `link:` prefix). A `LinkTarget` newtype should not be suggested for either variant; if branding ever makes sense it should be applied to both sites together in a dedicated refactor PR, not in a bug-fix PR.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:24.760Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Applies to pnpr/**/pnpr/crates/**/Cargo.toml : New registry-only crates must be placed under pnpr/crates/<short-name>/ and named pnpr-<short-name> in Cargo.toml, never using the pacquet- prefix

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args/tests.rs
  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Use `bench` as a commit type for benchmark-only changes in addition to standard Conventional Commit types

Applied to files:

  • .github/workflows/pacquet-integrated-benchmark-comment.yml
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-25T12:36:42.202Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-25T12:36:42.202Z
Learning: User-visible changes (CLI flags, defaults, environment variables, lockfile/manifest/state-file formats, error codes/messages, log emissions, store layout, hook semantics) in pnpm must be mirrored to pacquet in the same PR

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/*.rs : Declare a newtype wrapper for branded string types instead of collapsing the brand into a plain `String` or `&str` in Rust

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-06-01T08:59:42.161Z
Learnt from: KSXGitHub
Repo: pnpm/pnpm PR: 12093
File: pacquet/crates/cli/src/cli_args/run/recursive.rs:290-315
Timestamp: 2026-06-01T08:59:42.161Z
Learning: In pacquet's recursive run implementation (`pacquet/crates/cli/src/cli_args/run/recursive.rs`), the `pnpm-exec-summary.json` format for failed package entries correctly includes `prefix` and `message` fields in addition to `status` and `duration`. This matches pnpm's `ActionFailure` variant in `cli/utils/src/recursiveSummary.ts` and the direct serialization in `exec/commands/src/exec.ts`. There is no `ExecutionStatusInSummary` type in pnpm. The only intentional divergence is omitting the JS `error` field, whose `JSON.stringify` output is non-deterministic due to non-enumerable `Error` properties.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/*.rs : Follow Rust API Guidelines for naming

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-20T10:06:55.749Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11760
File: pacquet/crates/resolving-deps-resolver/src/resolved_tree.rs:15-18
Timestamp: 2026-05-20T10:06:55.749Z
Learning: In `pacquet/crates/resolving-deps-resolver/src/resolved_tree.rs`, the `DirectDep.id`, `ResolvedPackage.id`, and `ResolvedTree.packages` HashMap keys are intentionally plain `String` for now. The natural branded type would be `pacquet_lockfile::PkgNameVer`, but it cannot be used as a HashMap key because `node_semver::Version` does not derive `Hash`. The upstream parity type is `PkgResolutionId` (which carries an optional peer-dep suffix), and the branded type should be introduced alongside peer-dep resolution and lockfile generation work to avoid locking the seam too early.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/cli_args.rs
  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:24.760Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pnpr/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:24.760Z
Learning: Applies to pnpr/**/pnpr/**/Cargo.toml : Declare new shared dependencies in the root [workspace.dependencies] and use { workspace = true } in pnpr crate's Cargo.toml

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-06-02T14:39:19.809Z
Learnt from: KSXGitHub
Repo: pnpm/pnpm PR: 11938
File: pacquet/crates/config/src/lib.rs:959-966
Timestamp: 2026-06-02T14:39:19.809Z
Learning: In the pnpm/pnpm pacquet Rust port (`pacquet/crates/config/src/lib.rs`), `Config.extra_bin_paths` is intentionally left empty (`Vec::new()`) until workspace fan-out support for `run`/`exec` is implemented. It mirrors pnpm's `Config.extraBinPaths` (the workspace-root `node_modules/.bin`), which is also empty outside a workspace. Populating it before the workspace-root is resolved would put a non-existent path on `PATH`, so it should only be derived once workspace support lands. Do not flag this as a bug or missing derivation in reviews.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/tests/**/*.rs : Prefer real fixtures over dependency-injection seams — use `tempfile::TempDir`, the mocked registry, or integration tests spawning the actual binary for happy paths and most error paths; use the DI seam only for filesystem error kinds, deterministic time, shared process-global state, or external-service happy paths

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-06-02T14:39:46.617Z
Learnt from: KSXGitHub
Repo: pnpm/pnpm PR: 11938
File: pacquet/crates/cli/src/cli_args/dlx.rs:281-288
Timestamp: 2026-06-02T14:39:46.617Z
Learning: In pacquet's `pacquet/crates/cli/src/cli_args/dlx.rs` (and the analogous exec path), the `shell_mode` branch intentionally uses `joined.join(" ")` (no per-token shell-escaping) when building the command string passed to the platform shell. This matches pnpm's observable behavior: pnpm passes the command to execa with `shell: true`, and execa explicitly does NOT escape arguments in shell mode — it joins them and delegates entirely to the shell. Applying any shell-escaping here would diverge from pnpm's behavior and violates the pnpm-compatibility rule for the pacquet Rust port.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-23T09:14:43.635Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11867
File: pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs:726-730
Timestamp: 2026-05-23T09:14:43.635Z
Learning: In `pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs`, the fresh-lockfile path intentionally does not run lifecycle scripts (`BuildModules` is not invoked, and `side_effects_maps_by_snapshot` from `CreateVirtualStoreOutput` is discarded). This is pre-existing behavior documented by an in-code comment mirroring upstream `link.ts:167-170`. The frozen-lockfile path wires `BuildModules` end-to-end as normal. Wiring lifecycle scripts into the fresh-lockfile path is tracked as future work, separate from this file's concern.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-23T09:14:43.635Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11867
File: pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs:726-730
Timestamp: 2026-05-23T09:14:43.635Z
Learning: In `pacquet/crates/package-manager/src/install_with_fresh_lockfile.rs`, the fresh-lockfile path intentionally does not invoke `BuildModules` and discards `side_effects_maps_by_snapshot` from `CreateVirtualStoreOutput`. This is pre-existing, documented behavior (mirroring upstream `link.ts:167-170`): `importing_done` fires once extraction and symlink linking are complete, and the fresh-lockfile path does not run lifecycle scripts. The frozen-lockfile path wires `BuildModules` end-to-end as normal. Do not flag this omission as a bug; wiring lifecycle scripts into the fresh-lockfile path is tracked as future work separate from perf refactors.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
📚 Learning: 2026-05-04T17:01:30.322Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11452
File: exec/commands/src/dlx.ts:298-305
Timestamp: 2026-05-04T17:01:30.322Z
Learning: In `exec/commands/src/dlx.ts`, when `promptApproveDlxBuilds` exits early (no `approve-builds` command or non-interactive stdin), the `cachedDir` is intentionally still linked into the shared dlx cache even if some build scripts were skipped. This is by design: (1) it mirrors `pnpm add -g` behavior which also commits the install with skipped builds in non-interactive mode; (2) the cache key already encodes `allowBuild`, so users can recover by re-invoking with `--allow-build=<pkg>` which generates a fresh cache entry; (3) re-installing on every non-interactive invocation would be a perf regression for CI. Do not suggest preventing the symlink in this code path.

Applied to files:

  • pacquet/tasks/integrated-benchmark/src/work_env.rs
  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-29T18:03:15.354Z
Learnt from: CR
Repo: pnpm/pnpm PR: 0
File: pacquet/AGENTS.md:0-0
Timestamp: 2026-05-29T18:03:15.354Z
Learning: Applies to pacquet/**/*.rs : 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`

Applied to files:

  • .github/workflows/pacquet-integrated-benchmark.yml
📚 Learning: 2026-05-24T08:18:06.019Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11895
File: pnpm/test/deploy.ts:91-95
Timestamp: 2026-05-24T08:18:06.019Z
Learning: In the pnpm/pnpm repository, integration tests that hit the real `registry.npmjs.org` (e.g., for `pacquet` or `pnpm/pacquet`) do NOT use a runtime env-var gate (such as `PNPM_RUN_PUBLIC_REGISTRY_TESTS`). They simply pass `--config.registry=https://registry.npmjs.org/` directly to `execPnpm` and set a higher timeout. This is the established pattern, as seen in `pnpm/test/install/pacquet.ts` and `pnpm/test/deploy.ts`. Do not suggest adding env-var guards for these tests.

Applied to files:

  • .github/workflows/pacquet-integrated-benchmark.yml

Comment thread pacquet/tasks/integrated-benchmark/src/cli_args.rs
Comment thread pacquet/tasks/integrated-benchmark/src/work_env.rs
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

Each scenario has pacquet rows (direct install) and pnpr rows (the same client through the pnpr install accelerator), so pnpr@HEAD vs pacquet@HEAD is the pnpr-vs-direct ratio. Cold-store scenarios wipe the client store between runs (warm server); hot-store scenarios keep it warm. The pacquet@HEAD rows feed the pacquet Bencher testbed; the pnpr@HEAD rows feed the pnpr testbed.

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 2.086 ± 0.129 1.987 2.373 1.04 ± 0.07
pacquet@main 2.030 ± 0.067 1.906 2.107 1.01 ± 0.04
pnpr@HEAD 2.018 ± 0.078 1.933 2.188 1.01 ± 0.05
pnpr@main 2.002 ± 0.050 1.956 2.099 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 2.0861554052000004,
      "stddev": 0.12925520876560043,
      "median": 2.0288604063,
      "user": 2.5435962799999996,
      "system": 3.2980932600000004,
      "min": 1.9869582653000002,
      "max": 2.3732088473000004,
      "times": [
        1.9884014223000002,
        2.0077769633,
        2.0291247163,
        2.2558754073,
        2.0496852883,
        1.9869582653000002,
        2.3732088473000004,
        2.1222533843,
        2.0285960963000003,
        2.0196736613
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 2.0299339596999997,
      "stddev": 0.06708796402913302,
      "median": 2.0337242308,
      "user": 2.5406828799999994,
      "system": 3.2817418600000003,
      "min": 1.9059394443000002,
      "max": 2.1073763143,
      "times": [
        2.0036902093,
        2.0933590923,
        2.1073763143,
        1.9962874723000001,
        2.0697342233000002,
        2.0637582523,
        1.9059394443000002,
        1.9688778913,
        1.9887133453000003,
        2.1016033523
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.0175024352,
      "stddev": 0.07791484682321347,
      "median": 1.9981918093000002,
      "user": 2.54448208,
      "system": 3.29467826,
      "min": 1.9327927433000003,
      "max": 2.1881747513,
      "times": [
        1.9927742313000003,
        2.0036093873,
        1.9716969163000002,
        1.9454365373000002,
        1.9327927433000003,
        2.0225519873,
        2.1881747513,
        2.0477413583,
        2.1009818723,
        1.9692645673000002
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.0019971756,
      "stddev": 0.04967089924243278,
      "median": 1.9855038288000002,
      "user": 2.5615398799999993,
      "system": 3.30721146,
      "min": 1.9562590933000001,
      "max": 2.0986291153,
      "times": [
        1.9996319203000001,
        1.9653064303,
        2.0986291153,
        1.9713757373000003,
        2.0062494893,
        1.9562590933000001,
        2.0239286703,
        2.0723461473,
        1.9658687593000002,
        1.9603763933000002
      ]
    }
  ]
}

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

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 636.9 ± 15.8 621.6 679.8 1.00
pacquet@main 651.2 ± 44.4 629.1 776.3 1.02 ± 0.07
pnpr@HEAD 687.6 ± 105.4 630.5 978.9 1.08 ± 0.17
pnpr@main 721.1 ± 57.8 636.4 831.4 1.13 ± 0.10
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.6369365807000001,
      "stddev": 0.015778823600057047,
      "median": 0.6330426294,
      "user": 0.3504649,
      "system": 1.2996630200000001,
      "min": 0.6215896604000001,
      "max": 0.6798281994,
      "times": [
        0.6798281994,
        0.6304626444,
        0.6358275044,
        0.6215896604000001,
        0.6292434174,
        0.6321474074,
        0.6339378514,
        0.6315902054,
        0.6362950204000001,
        0.6384438964
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.6511617211999999,
      "stddev": 0.04437032991311834,
      "median": 0.6371889694,
      "user": 0.35265040000000003,
      "system": 1.31253262,
      "min": 0.6291449804,
      "max": 0.7762677334,
      "times": [
        0.7762677334,
        0.6366917694,
        0.6390219594000001,
        0.6504025434,
        0.6317980254000001,
        0.6359531544,
        0.6425324334,
        0.6321184434,
        0.6291449804,
        0.6376861694
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6875611163,
      "stddev": 0.10544614400144374,
      "median": 0.6519109519,
      "user": 0.3539667,
      "system": 1.2982522199999997,
      "min": 0.6304772494,
      "max": 0.9789412694,
      "times": [
        0.7126744344,
        0.6526992204000001,
        0.9789412694,
        0.6511226834,
        0.6724860324,
        0.6719062124,
        0.6304772494,
        0.6341378294000001,
        0.6339330624,
        0.6372331694000001
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.7211107651,
      "stddev": 0.05781711294641612,
      "median": 0.7234326839,
      "user": 0.3466363,
      "system": 1.31503682,
      "min": 0.6363625644,
      "max": 0.8313554144,
      "times": [
        0.8313554144,
        0.6865132874000001,
        0.6708674054,
        0.7786030404000001,
        0.7233144234000001,
        0.7235509444,
        0.6363625644,
        0.6750252954,
        0.7247211604,
        0.7607941154000001
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 2.290 ± 0.017 2.268 2.320 1.00 ± 0.01
pacquet@main 2.298 ± 0.025 2.259 2.341 1.01 ± 0.01
pnpr@HEAD 2.302 ± 0.044 2.238 2.369 1.01 ± 0.02
pnpr@main 2.282 ± 0.018 2.262 2.315 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 2.28988288714,
      "stddev": 0.0171159143278725,
      "median": 2.28879967814,
      "user": 3.6896820200000002,
      "system": 3.0997950199999997,
      "min": 2.26793653264,
      "max": 2.31975152464,
      "times": [
        2.29143065264,
        2.30475407764,
        2.26793653264,
        2.27583457464,
        2.31975152464,
        2.30919427064,
        2.27383335664,
        2.27632606864,
        2.28616870364,
        2.2935991096399997
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 2.29759498494,
      "stddev": 0.025077737403242723,
      "median": 2.2960424011400002,
      "user": 3.7169062199999994,
      "system": 3.084124319999999,
      "min": 2.25929663164,
      "max": 2.34077993064,
      "times": [
        2.3256298536399997,
        2.29567080264,
        2.26677408364,
        2.25929663164,
        2.28019928864,
        2.29385530764,
        2.31224750064,
        2.34077993064,
        2.30508245064,
        2.29641399964
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.30209557664,
      "stddev": 0.04406301469605407,
      "median": 2.30031841464,
      "user": 3.6995176199999995,
      "system": 3.0888319199999996,
      "min": 2.23820226864,
      "max": 2.36932517464,
      "times": [
        2.34475898564,
        2.32072721364,
        2.34697071064,
        2.32120339564,
        2.36932517464,
        2.26477183064,
        2.23820226864,
        2.27990961564,
        2.27267058764,
        2.26241598364
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.28172563434,
      "stddev": 0.01826467606648467,
      "median": 2.27929243664,
      "user": 3.6906895200000003,
      "system": 3.06558522,
      "min": 2.26241219264,
      "max": 2.31455338664,
      "times": [
        2.31455338664,
        2.28170709164,
        2.31029657964,
        2.2735464846399998,
        2.26241219264,
        2.28162662164,
        2.26449645864,
        2.2876493176399997,
        2.27695825164,
        2.26400995864
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 1.460 ± 0.025 1.432 1.501 1.00
pacquet@main 1.485 ± 0.074 1.433 1.688 1.02 ± 0.05
pnpr@HEAD 1.461 ± 0.038 1.432 1.544 1.00 ± 0.03
pnpr@main 1.482 ± 0.046 1.441 1.590 1.02 ± 0.04
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 1.46024397508,
      "stddev": 0.024606781803267995,
      "median": 1.45258086798,
      "user": 1.64208264,
      "system": 1.8124288599999996,
      "min": 1.43237795048,
      "max": 1.50077750148,
      "times": [
        1.43237795048,
        1.47067056848,
        1.44689160148,
        1.50077750148,
        1.4506888254799999,
        1.43359873948,
        1.45447291048,
        1.4992827924799998,
        1.44340113048,
        1.4702777304799999
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 1.4853076224800001,
      "stddev": 0.07435164418902246,
      "median": 1.46418768898,
      "user": 1.66085654,
      "system": 1.8221989600000001,
      "min": 1.43280297848,
      "max": 1.68818242548,
      "times": [
        1.44822395748,
        1.43280297848,
        1.68818242548,
        1.4784057234799999,
        1.4735941664799999,
        1.50344318648,
        1.48028647548,
        1.44466807148,
        1.45478121148,
        1.44868802848
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 1.46130182928,
      "stddev": 0.038060809838510026,
      "median": 1.4450608319799998,
      "user": 1.63489854,
      "system": 1.8182050599999997,
      "min": 1.43214944848,
      "max": 1.5438753804799998,
      "times": [
        1.44878722948,
        1.43975124748,
        1.4413344344799999,
        1.45414370248,
        1.5438753804799998,
        1.45530786348,
        1.43921428448,
        1.43214944848,
        1.43965488448,
        1.5187998174800001
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 1.48244680488,
      "stddev": 0.04613213460391995,
      "median": 1.46875333548,
      "user": 1.6524617400000001,
      "system": 1.8402756599999996,
      "min": 1.44103347648,
      "max": 1.59039193648,
      "times": [
        1.5285854644799999,
        1.49610435148,
        1.4679589984799999,
        1.59039193648,
        1.4448732254799999,
        1.46802419048,
        1.47268973548,
        1.44532418948,
        1.44103347648,
        1.46948248048
      ]
    }
  ]
}

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12154
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
2,289.88 ms
(-2.19%)Baseline: 2,341.15 ms
2,809.38 ms
(81.51%)
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
🚷 view threshold
1,460.24 ms
(-3.73%)Baseline: 1,516.86 ms
1,820.23 ms
(80.22%)
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
🚷 view threshold
2,086.16 ms
(+1.67%)Baseline: 2,051.91 ms
2,462.29 ms
(84.72%)
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
🚷 view threshold
636.94 ms
(-2.01%)Baseline: 650.03 ms
780.03 ms
(81.66%)
🐰 View full continuous benchmarking report in Bencher

- work_env: wrap the spawned pnpr child in its PnprServer guard before the
  readiness wait and .pnpr-env write, so an early panic kills the process
  on unwind instead of leaking an orphaned server (Copilot).
- cli_args: document pnpr@<rev> in the `targets` --help text (CodeRabbit).
- workflows: guard each bencher upload on its file existing, so a missing
  optional results file logs a notice instead of failing the step (Copilot).
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.

3 participants