Skip to content
This repository was archived by the owner on May 14, 2026. It is now read-only.

feat(cmd-shim,package-manager): hoisted-bin precedence + post-build top-level bin re-link (#342)#523

Merged
zkochan merged 1 commit into
mainfrom
fix/342-hoisted-bin-precedence-and-lifecycle
May 14, 2026
Merged

feat(cmd-shim,package-manager): hoisted-bin precedence + post-build top-level bin re-link (#342)#523
zkochan merged 1 commit into
mainfrom
fix/342-hoisted-bin-precedence-and-lifecycle

Conversation

@zkochan

@zkochan zkochan commented May 14, 2026

Copy link
Copy Markdown
Member

Summary

Closes the two bin-linking behaviors deferred from #333:

Behavior 1 — Hoisted-bin precedence

Direct dependencies' bins must win over publicly-hoisted (transitive) bins with the same name, so a project never gets its own tooling silently shadowed by a transitive's bin. Mirrors upstream's preferDirectCmds partition.

  • New BinOrigin { Direct, Hoisted } discriminator on PackageBinSource.
  • pick_winner gains a top tier: Direct wins outright over Hoisted regardless of ownership / lexical order. Existing tiers (ownership, then lexical fallback) still apply within each origin bucket.
  • New link_top_level_bins(modules_dir, direct_names, hoisted_names) helper in pacquet-package-manager mixes both candidate lists into one link_bins_of_packages call so the new tier resolves conflicts in a single pass. Previously the two passes (SymlinkDirectDependencies for direct + hoist pass for publicly-hoisted) wrote shims independently and a hoisted bin could shadow a direct one when its package name was lexically smaller.

Behavior 2 — Lifecycle-script-created bins

Some packages generate their bin files via postinstall (the @pnpm.e2e/generated-bins fixture upstream uses to test this). The earlier per-importer bin link runs before lifecycle scripts, so generated bins were missed.

  • Add a post-BuildModules per-importer top-level bin link pass. Re-reading each direct dep's package.json after lifecycle scripts run picks up newly-found bin entries that point at now-existing files.
  • Idempotent for unchanged shims via is_shim_pointing_at, so the second pass is essentially free for installs without generated bins or precedence conflicts.
  • Mirrors upstream's linkBinsOfImporter pass that runs after buildModules.

Supporting changes

  • PackageBinSource::new(location, manifest) constructor + with_origin builder so existing call sites don't have to spell out the new field.
  • Public direct_dep_names_for_importer helper extracted from SymlinkDirectDependencies so the post-build pass uses the same filter (skipped / first-wins / link_only) as the symlink phase.
  • InstallFrozenLockfileError::TopLevelBinLink for the new failure surface (distinct from HoistLinkBins which targets the virtual store's private hoist dir).

Test plan

  • just ready (all tests pass; lint, fmt, typos clean)
  • just dylint (perfectionist) clean
  • taplo format --check clean
  • RUSTDOCFLAGS=\"-D warnings\" cargo doc -p pacquet-cmd-shim -p pacquet-package-manager --no-deps clean
  • direct_origin_wins_over_hoisted_regardless_of_lexical — pins the new tier overrides lexical ordering.
  • hoisted_origin_loses_to_existing_direct — pins both arms of the new tier (Direct incumbent vs Hoisted candidate).

End-to-end fixture coverage against upstream's @pnpm.e2e/generated-bins is left to a follow-up — adding the fixture to the registry-mock is its own task. The unit tests pin the precedence and the post-build pass's idempotency contract.


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

Summary by CodeRabbit

  • New Features

    • Direct dependency executables now take precedence over hoisted executables when names conflict, ensuring more predictable behavior.
  • Bug Fixes

    • Improved executable linking process to properly capture binaries created during package lifecycle scripts.

Review Change Stack

…op-level bin re-link (#342)

Two related bin-linking behaviors deferred from #333.

Behavior 1 — hoisted-bin precedence:
- Add `BinOrigin { Direct, Hoisted }` discriminator to `PackageBinSource`.
- New top tier in `pick_winner`: Direct wins outright over Hoisted
  regardless of ownership / lexical order. Mirrors upstream's
  `preferDirectCmds` partition at
  https://github.com/pnpm/pnpm/blob/4750fd370c/bins/linker/src/index.ts#L92.
- New `link_top_level_bins(modules_dir, direct, hoisted)` helper in
  `pacquet-package-manager` mixes both candidate lists into one
  `link_bins_of_packages` call so the new tier resolves conflicts in
  a single pass — previously the two passes (SymlinkDirectDependencies
  for direct + hoist pass for publicly-hoisted) wrote shims
  independently and a hoisted bin could shadow a direct one when its
  package name was lexically smaller.

Behavior 2 — lifecycle-script-created bins:
- Add a post-`BuildModules` per-importer top-level bin link pass.
  Re-reading each direct dep's `package.json` after lifecycle
  scripts run picks up bins generated by `postinstall` (the
  `@pnpm.e2e/generated-bins` upstream fixture). Idempotent for
  unchanged shims via `is_shim_pointing_at`.
- Mirrors upstream's `linkBinsOfImporter` pass that runs after
  `buildModules` at
  https://github.com/pnpm/pnpm/blob/4750fd370c/installing/deps-installer/src/install/index.ts#L1539.

Supporting changes:
- `PackageBinSource::new(location, manifest)` constructor + `with_origin`
  builder so existing call sites don't have to spell out the new field.
- Public `direct_dep_names_for_importer` helper extracted from
  `SymlinkDirectDependencies` so the post-build pass uses the same
  filter (skipped / first-wins / link_only) as the symlink phase.
- `InstallFrozenLockfileError::TopLevelBinLink` for the new failure
  surface.

Tests:
- `direct_origin_wins_over_hoisted_regardless_of_lexical` — pins the
  new tier overrides lexical ordering.
- `hoisted_origin_loses_to_existing_direct` — pins both arms of the
  new tier (Direct incumbent vs Hoisted candidate).
Copilot AI review requested due to automatic review settings May 14, 2026 09:37
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1077c396-e8ee-4712-b692-66d1813e6c29

📥 Commits

Reviewing files that changed from the base of the PR and between 0439707 and 05ca5ba.

📒 Files selected for processing (5)
  • crates/cmd-shim/src/link_bins.rs
  • crates/cmd-shim/src/link_bins/tests.rs
  • crates/package-manager/src/install_frozen_lockfile.rs
  • crates/package-manager/src/link_bins.rs
  • crates/package-manager/src/symlink_direct_dependencies.rs
📜 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). (8)
  • GitHub Check: copilot-pull-request-reviewer
  • GitHub Check: Code Coverage
  • 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: Dylint
  • GitHub Check: Run benchmark on ubuntu-latest
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Preserve existing method chains and pipe-trait chains; do not break them into intermediate let bindings unless there is a concrete justification such as a compilation failure, borrow checker rejection, meaningful performance improvement, or other technical necessity. Refactoring for style alone is not sufficient justification.
Choose owned vs. borrowed parameters to minimize copies; prefer borrowed types (&Path over &PathBuf, &str over &String) when it does not force extra copies.
Prefer Arc::clone(&x) and Rc::clone(&x) over x.clone() for reference-counted types to make the cost visible at the call site.
Do not use star imports inside module bodies. Write use super::{Foo, bar} instead of use super::*; for any glob whose target is a module you control. External-crate preludes (e.g., use rayon::prelude::*;) and root-of-module re-exports (e.g., pub use submodule::*; in lib.rs) are exceptions.
Follow Rust API Guidelines for naming, as documented in https://rust-lang.github.io/api-guidelines/naming.html.
Declare a newtype wrapper for any branded string type being ported from TypeScript pnpm. Do not collapse the brand into a plain String or &str; give the type its own struct so misuse is a type error.
When porting branded string types where upstream TypeScript always validates before construction, validate in the Rust port too. Construct the wrapper only via TryFrom<String> and/or FromStr; do not provide an infallible public constructor that takes an arbitrary string.
For branded string types where upstream TypeScript never validates (used purely for type-safety to prevent confusion between string slots), expose an infallible From<String> and From<&str> constructor in the Rust wrapper.
When upstream TypeScript occasionally constructs a branded type without validation (via bare as assertion), add a from_str_unchecked (or similarly named) constructor on the Rust side. Keep the validating constructor as well; `from_str_u...

Files:

  • crates/package-manager/src/symlink_direct_dependencies.rs
  • crates/package-manager/src/install_frozen_lockfile.rs
  • crates/package-manager/src/link_bins.rs
  • crates/cmd-shim/src/link_bins/tests.rs
  • crates/cmd-shim/src/link_bins.rs
🧠 Learnings (5)
📚 Learning: 2026-05-07T23:19:08.272Z
Learnt from: KSXGitHub
Repo: pnpm/pacquet PR: 401
File: tasks/integrated-benchmark/src/work_env.rs:343-344
Timestamp: 2026-05-07T23:19:08.272Z
Learning: When reviewing Rust code in pnpm/pacquet for deprecated API usage, do not automatically treat `serde_saphyr::to_string` as deprecated. In `serde-saphyr` v0.0.25, `serde_saphyr::to_string` has no `#[deprecated]` attribute (the `#[deprecated]` later in `serde-saphyr-0.0.25/src/lib.rs` applies to a different function). Only flag `serde_saphyr::to_string` as deprecated if the resolved dependency version’s source shows `#[deprecated]` on that specific function.

Applied to files:

  • crates/package-manager/src/symlink_direct_dependencies.rs
  • crates/package-manager/src/install_frozen_lockfile.rs
  • crates/package-manager/src/link_bins.rs
  • crates/cmd-shim/src/link_bins/tests.rs
  • crates/cmd-shim/src/link_bins.rs
📚 Learning: 2026-05-13T22:52:32.579Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 506
File: crates/package-manager/src/link_bins.rs:238-241
Timestamp: 2026-05-13T22:52:32.579Z
Learning: In Rust code using `matches!` (or `match`) on a borrowed value (e.g., `meta: &PackageMetadata` and a field access like `meta.resolution`), it is safe to use wildcard/OR patterns such as `LockfileResolution::Binary(_) | LockfileResolution::Variations(_)` when the pattern does not bind the inner payload by value. `_` wildcard patterns (and similar discriminant-only patterns) should not move non-`Copy` data; they only test the variant and avoid ownership transfer. Do not flag these patterns as move-out-of-borrow/ownership compile errors. Only patterns that bind the inner value by value (e.g., `LockfileResolution::Binary(b)`) would require ownership and may trigger move errors when matching on data behind a borrow.

Applied to files:

  • crates/package-manager/src/symlink_direct_dependencies.rs
  • crates/package-manager/src/install_frozen_lockfile.rs
  • crates/package-manager/src/link_bins.rs
  • crates/cmd-shim/src/link_bins/tests.rs
  • crates/cmd-shim/src/link_bins.rs
📚 Learning: 2026-05-13T19:22:48.951Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 478
File: crates/package-manager/src/hoisted_dep_graph.rs:51-55
Timestamp: 2026-05-13T19:22:48.951Z
Learning: When reviewing this Rust codebase, avoid introducing/using a newtype like `PkgIdWithPatchHash` in only one module (e.g., `hoisted_dep_graph.rs`) if other related pacquet modules still represent the upstream pnpm “pkg id with patch hash” as a plain `String` (e.g., `virtual_store_layout`). For type consistency, either keep `pkg_id_with_patch_hash` as `String` here, or require a workspace-wide sweep that defines/extracts the `PkgIdWithPatchHash` newtype once and updates all call sites together (otherwise defer the refactor to a coordinated follow-up PR).

Applied to files:

  • crates/package-manager/src/symlink_direct_dependencies.rs
  • crates/package-manager/src/install_frozen_lockfile.rs
  • crates/package-manager/src/link_bins.rs
📚 Learning: 2026-05-13T20:09:22.171Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 486
File: crates/package-manager/src/hoisted_dep_graph.rs:472-476
Timestamp: 2026-05-13T20:09:22.171Z
Learning: In pnpm/pacquet, when generating serialized `hoisted_locations` strings (used for `.modules.yaml`), normalize path separators to forward slashes (e.g., replace `\\` with `/`). This preserves cross-platform portability: the output must not use OS-native separators because upstream pnpm’s `path.relative` can return platform-specific separators, which would break consistency with pnpm/pacquet’s other serialized formats on Windows.

Applied to files:

  • crates/package-manager/src/symlink_direct_dependencies.rs
  • crates/package-manager/src/install_frozen_lockfile.rs
  • crates/package-manager/src/link_bins.rs
📚 Learning: 2026-05-01T10:01:33.766Z
Learnt from: zkochan
Repo: pnpm/pacquet PR: 349
File: crates/reporter/src/tests.rs:121-121
Timestamp: 2026-05-01T10:01:33.766Z
Learning: In Rust test code, follow the repo’s CODE_STYLE_GUIDE test-logging rule: add logging (e.g., `eprintln!`/`eprintln!(...)`) so that useful diagnostic values are printed when a test fails, unless the assertion is `assert_eq!` (where the differing values are already included). Concretely, if you use assertions like `assert!`, `assert_ne!`, etc., ensure the test logs the relevant actual/expected values (or context) before/around the assertion so failures can be diagnosed without rerunning.

Applied to files:

  • crates/cmd-shim/src/link_bins/tests.rs
🔇 Additional comments (34)
crates/package-manager/src/symlink_direct_dependencies.rs (1)

257-300: LGTM!

crates/cmd-shim/src/link_bins.rs (7)

34-52: LGTM!


54-72: LGTM!


74-98: LGTM!


256-256: LGTM!


336-367: LGTM!


304-310: LGTM!


263-277: LGTM!

crates/cmd-shim/src/link_bins/tests.rs (15)

1-1: LGTM!


41-41: LGTM!


81-81: LGTM!


162-163: LGTM!


200-201: LGTM!


352-352: LGTM!


422-422: LGTM!


489-489: LGTM!


564-564: LGTM!


635-635: LGTM!


704-704: LGTM!


809-810: LGTM!


915-916: LGTM!


929-983: LGTM!


985-1036: LGTM!

crates/package-manager/src/link_bins.rs (6)

5-6: LGTM!


58-58: LGTM!


67-124: LGTM!


126-156: LGTM!


436-436: LGTM!


672-672: LGTM!

crates/package-manager/src/install_frozen_lockfile.rs (5)

9-11: LGTM!

Also applies to: 29-29


176-185: LGTM!


809-822: LGTM!


947-961: LGTM!


1110-1169: LGTM!


📝 Walkthrough

Walkthrough

This PR introduces origin-based precedence to bin conflict resolution: PackageBinSource now tracks whether a bin comes from a direct dependency or hoisted candidate. Direct bins always win, then ownership, then lexical order. A post-BuildModules bin-linking pass integrates unified conflict resolution into the install pipeline.

Changes

Bin Origin Tracking and Conflict Resolution

Layer / File(s) Summary
PackageBinSource origin field and pick_winner precedence
crates/cmd-shim/src/link_bins.rs
PackageBinSource gains origin: BinOrigin (Direct/Hoisted) with constructors new() and with_origin(). pick_winner() updated to prefer Direct over Hoisted origins before ownership and lexical tiebreaking.
cmd-shim test refactoring and precedence tests
crates/cmd-shim/src/link_bins/tests.rs
All existing tests refactored to use PackageBinSource::new() constructors. Two new tests verify direct-wins-over-hoisted and hoisted-loses-to-direct precedence rules.
Direct dependency names helper
crates/package-manager/src/symlink_direct_dependencies.rs
New public direct_dep_names_for_importer() extracts deduplicated direct-dependency names with skip filtering for reuse by bin-linking phases.
Top-level bin-linking API
crates/package-manager/src/link_bins.rs
New link_top_level_bins() entry point with private read_bin_sources() helper reads direct and hoisted candidates, tags origins, filters hoisted by direct name set, and performs unified conflict resolution.
Post-BuildModules bin-linking in install pipeline
crates/package-manager/src/install_frozen_lockfile.rs
Defers public-bin shimming from hoist pass to new post-BuildModules phase; collects direct and hoisted candidates per importer and calls link_top_level_bins(). Added InstallFrozenLockfileError::TopLevelBinLink error variant.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • pnpm/pacquet#342: Directly implements the requested BinOrigin discriminator on PackageBinSource and updates pick_winner to enforce Direct-over-Hoisted precedence.
  • pnpm/pacquet#438: Shares the same bin-linking and hoisted-vs-direct resolution logic that this PR extends.

Possibly related PRs

  • pnpm/pacquet#333: Extends the bin-linking implementation introduced there by adding BinOrigin discrimination and updating pick_winner conflict resolution.
  • pnpm/pacquet#520: Both PRs modify the post-BuildModules pipeline in install_frozen_lockfile.rs; #520 changes how BuildModules runs, while this PR adds dedicated direct-vs-hoisted bin resolution after it.

Suggested reviewers

  • anonrig

Poem

🐰 Hops through bin candidates with glee,
Direct bins rise above the hoisted spree,
BinOrigin tracks where each comes from true,
Post-build linking ties it all anew!
A cleaner path through the package maze,
Pacquet hops onward in grateful daze! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the two main features: hoisted-bin precedence and post-build top-level bin re-linking, matching the PR's core changes.
Description check ✅ Passed The description comprehensively covers the summary, mirrors upstream pnpm behavior, references an issue, includes test plans, and provides sufficient detail on both behaviors and supporting changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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/342-hoisted-bin-precedence-and-lifecycle

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

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions

Copy link
Copy Markdown

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.03      5.3±0.20ms   820.7 KB/sec    1.00      5.1±0.12ms   845.8 KB/sec

@codecov

codecov Bot commented May 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.95798% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.15%. Comparing base (0439707) to head (05ca5ba).

Files with missing lines Patch % Lines
crates/package-manager/src/link_bins.rs 89.58% 5 Missing ⚠️
...package-manager/src/symlink_direct_dependencies.rs 96.29% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #523      +/-   ##
==========================================
+ Coverage   89.09%   89.15%   +0.06%     
==========================================
  Files         125      125              
  Lines       14114    14220     +106     
==========================================
+ Hits        12575    12678     +103     
- Misses       1539     1542       +3     

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

@github-actions

Copy link
Copy Markdown

Integrated-Benchmark Report (Linux)

Scenario: Frozen Lockfile

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 2.557 ± 0.106 2.456 2.783 1.03 ± 0.05
pacquet@main 2.489 ± 0.045 2.418 2.542 1.00
pnpm 5.757 ± 0.094 5.657 5.942 2.31 ± 0.06
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 2.5571314427200003,
      "stddev": 0.10575257351901567,
      "median": 2.5250070007200005,
      "user": 2.6016254799999996,
      "system": 3.55396104,
      "min": 2.45645085622,
      "max": 2.7832007422200005,
      "times": [
        2.63340076922,
        2.4748258672200003,
        2.58425646022,
        2.45645085622,
        2.63900439322,
        2.7832007422200005,
        2.4807273442200004,
        2.4814983832200004,
        2.56851561822,
        2.4694339932200005
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 2.48912010652,
      "stddev": 0.04529722748045105,
      "median": 2.50069008722,
      "user": 2.59338798,
      "system": 3.5077166399999995,
      "min": 2.41800490522,
      "max": 2.5419946072200004,
      "times": [
        2.5419946072200004,
        2.53278972922,
        2.51242031122,
        2.4723078542200003,
        2.46246218922,
        2.4889598632200003,
        2.41800490522,
        2.41846177122,
        2.51812004922,
        2.5256797852200004
      ]
    },
    {
      "command": "pnpm",
      "mean": 5.75673943652,
      "stddev": 0.09362874310307445,
      "median": 5.71631575722,
      "user": 8.31341888,
      "system": 4.24166814,
      "min": 5.656685631219999,
      "max": 5.94215824322,
      "times": [
        5.79468007722,
        5.656685631219999,
        5.71673722622,
        5.7158942882199995,
        5.69579782022,
        5.87200059322,
        5.80189870022,
        5.94215824322,
        5.66724066822,
        5.70430111722
      ]
    }
  ]
}

Scenario: Frozen Lockfile (Hot Cache)

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 732.2 ± 17.9 709.6 770.9 1.00
pacquet@main 819.6 ± 63.2 744.1 947.3 1.12 ± 0.09
pnpm 2416.9 ± 154.4 2275.2 2795.4 3.30 ± 0.23
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.73224684468,
      "stddev": 0.017930788855753135,
      "median": 0.72466200378,
      "user": 0.36271014,
      "system": 1.62247766,
      "min": 0.7095673892800001,
      "max": 0.7709113662800001,
      "times": [
        0.7709113662800001,
        0.7221272012800001,
        0.7485218242800001,
        0.7240391432800001,
        0.7095673892800001,
        0.7337604682800001,
        0.7451693922800001,
        0.7227239272800001,
        0.72528486428,
        0.7203628702800001
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.81961317558,
      "stddev": 0.0631607831573082,
      "median": 0.79127773178,
      "user": 0.36684083999999995,
      "system": 1.6390974599999997,
      "min": 0.7441211822800001,
      "max": 0.94730259528,
      "times": [
        0.8610388392800001,
        0.8498539632800001,
        0.7702147132800001,
        0.7776181402800001,
        0.7441211822800001,
        0.94730259528,
        0.79556891228,
        0.7869865512800001,
        0.7810671342800001,
        0.8823597242800001
      ]
    },
    {
      "command": "pnpm",
      "mean": 2.4168941028799997,
      "stddev": 0.15437208679301562,
      "median": 2.3745173132799997,
      "user": 2.80340564,
      "system": 2.1725686600000005,
      "min": 2.27515265428,
      "max": 2.79536933228,
      "times": [
        2.46905985828,
        2.3723921772799996,
        2.79536933228,
        2.37664244928,
        2.36563762028,
        2.2794311212799996,
        2.3875328582799997,
        2.27515265428,
        2.31817756228,
        2.52954539528
      ]
    }
  ]
}

@zkochan zkochan merged commit 110df76 into main May 14, 2026
16 of 17 checks passed
@zkochan zkochan deleted the fix/342-hoisted-bin-precedence-and-lifecycle branch May 14, 2026 10:40
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants