Skip to content

fix(pacquet): persist the synthesized runtime package.json into the store index#12829

Merged
zkochan merged 3 commits into
mainfrom
fix-pacquet-runtime-dlx-warm-manifest
Jul 7, 2026
Merged

fix(pacquet): persist the synthesized runtime package.json into the store index#12829
zkochan merged 3 commits into
mainfrom
fix-pacquet-runtime-dlx-warm-manifest

Conversation

@zkochan

@zkochan zkochan commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the TS CI / Compile & Lint failure seen after bumping the repo to the
Rust pnpm alpha (Related to #12811). The compile-only script runs
pnpm dlx node@runtime:26.4.0 …, which died with:

Error: pacquet_cli::dlx_read_manifest
  × Failed to read the installed manifest at …/node_modules/node/package.json:
    No such file or directory (os error 2)

Root cause. Runtime archives (Node.js / Bun / Deno) ship no package.json,
so pacquet synthesizes one (name, version, bin). That synthesized
manifest was only added to the in-memory cas_paths in
fetch_binary_resolution_to_cas, after the download had already queued the
store-index row. The persisted PackageFilesIndex therefore recorded no
package.json and no bundled manifest.

A cold fetch masks this — the current install's slot still gets the
manifest from cas_paths. But a later warm install materializes the
runtime straight from the store-index row (via the warm-batch prefetch, which
never calls fetch_binary_resolution_to_cas), so the slot lands without a
package.json and the warm-batch bin linker finds no bin. That is exactly the
CI sequence: the root install cold-fetches node@runtime:26.4.0, then the
later pnpm dlx node@runtime:26.4.0 warm-reads the manifest-less row and dies
in getBinName.

Fix. Thread the synthesized manifest into the two binary download paths as
append_manifest, mirroring pnpm's appendManifest: fold it into the
extracted output's cas_paths, the row's files map, and its bundled
manifest before the row is persisted. Warm and cold installs now land the
same slot. This brings pacquet in line with the TypeScript stack, which already
bakes appendManifest into the files index via addManifestToCafs — no
TypeScript change is needed.

Verified end-to-end by reproducing the CI two-step (install then warm dlx node@runtime:26.4.0 --version) against an isolated store: it fails on the
pre-fix binary with dlx_read_manifest and succeeds (v26.4.0) on the fixed
binary.

Regression test. installing_a_runtime_persists_the_synthesized_manifest_into_the_store_index_row
(install_package_by_snapshot/tests.rs) ports the core of
installing/deps-installer/test/install/nodeRuntime.ts:209 (cold install →
rimraf node_modules → offline reinstall) network-free: it drives
InstallPackageBySnapshot on a Binary resolution pointing at a local file:
runtime-archive fixture, asserts the persisted store-index row carries the
synthesized package.json in both files and the bundled manifest, and that
a warm/offline reinstall (fixture deleted) re-materializes it. Confirmed to fail
when the fix is neutered. Plus unit tests for apply_append_manifest. The
real-download lockfile-shape / musl-variant assertions of nodeRuntime.ts
remain unported — tracked in pacquet/plans/TEST_PORTING.md.

Note: CI will only turn green once a new alpha built from this fix is
released and the repo's package-manager version is bumped to it.

Follow-up (out of scope): a store whose runtime row was written by a pre-fix
tool still lacks the manifest and won't be rewritten on a warm hit. Matching
pnpm's getBinName fallback (plus resolution-driven bin links) would harden
that case; it needs its own change.

Squash Commit Body

Runtime archives (Node.js / Bun / Deno) ship no package.json, so pacquet
synthesizes one carrying name, version, and bin. That synthesized manifest was
only added to the in-memory cas_paths in fetch_binary_resolution_to_cas, after
the download had already queued the store-index row, so the persisted
PackageFilesIndex recorded no package.json and no bundled manifest.

A cold fetch masks this — the current install's slot still gets the manifest
from cas_paths. But a warm install materializes the runtime straight from the
store-index row (via the warm-batch prefetch, which never calls
fetch_binary_resolution_to_cas), so the slot lands without a package.json and
the warm-batch bin linker finds no bin. That is the CI failure on
pnpm/pnpm#12811: the root install cold-fetches node@runtime:26.4.0 and the
later pnpm dlx node@runtime:26.4.0 warm-reads the manifest-less row and dies in
getBinName with dlx_read_manifest.

Thread the synthesized manifest into the two binary download paths as
append_manifest, mirroring pnpm's appendManifest: fold it into the extracted
output's cas_paths, the row's files map, and its bundled manifest before the
row is persisted, so warm and cold installs land the same slot. This brings
pacquet in line with the TypeScript stack, which already bakes appendManifest
into the files index via addManifestToCafs.

Checklist

  • The change is implemented in both the TypeScript CLI and the Rust
    pacquet/ port, or the description notes what still needs porting. (pacquet
    only — the TypeScript stack already has this behavior via appendManifest.)
  • Added or updated tests. (A network-free e2e regression test porting
    nodeRuntime.ts:209's cold→wipe→offline-reinstall core, plus unit tests for
    apply_append_manifest; verified against the pre-fix/fixed binaries and by
    neutering the fix.)

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

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of runtime archive installs (Node.js, Bun, Deno) when the archive omits package.json: pacquet now persists the synthesized package.json and bundled runtime manifest into the stored index during import, enabling correct warm reinstalls and offline use.
    • If the archive already includes a real package.json, existing behavior remains unchanged to avoid duplicate/incorrect metadata.
  • Tests

    • Added an end-to-end offline regression test covering synthesized manifest persistence and re-materialization on reinstall.
  • Documentation

    • Updated runtime installation test notes to match current coverage.

…tore index

Runtime archives (Node.js / Bun / Deno) ship no `package.json`, so pacquet
synthesizes one carrying `name`, `version`, and `bin`. That synthesized
manifest was only ever added to the *in-memory* `cas_paths` in
`fetch_binary_resolution_to_cas`, after the download had already queued the
store-index row. The persisted `PackageFilesIndex` therefore recorded no
`package.json` and no bundled `manifest`.

A cold fetch masks this — the current install's slot still gets the manifest
from `cas_paths`. But a later *warm* install materializes the runtime straight
from the store-index row (via the warm-batch prefetch, which never calls
`fetch_binary_resolution_to_cas`), so the slot lands without a `package.json`
and the warm-batch bin linker finds no bin. That is exactly the CI failure on
#12811, where the root install cold-fetches `node@runtime:26.4.0`
and the later `pnpm dlx node@runtime:26.4.0` warm-reads the manifest-less row
and dies in `getBinName` with `dlx_read_manifest`.

Thread the synthesized manifest into the two binary download paths as
`append_manifest`, mirroring pnpm's `appendManifest`: fold it into the
extracted output's `cas_paths`, the row's `files` map, and its bundled
`manifest` before the row is persisted, so warm and cold installs land the
same slot. This brings pacquet in line with the TypeScript stack, which
already bakes `appendManifest` into the files index via `addManifestToCafs`.
Copilot AI review requested due to automatic review settings July 6, 2026 22:53

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 was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ac067fb-71f2-43d3-9ca9-dc2b796f8f67

📥 Commits

Reviewing files that changed from the base of the PR and between 0a4b3fb and 8f354b9.

📒 Files selected for processing (1)
  • pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs

📝 Walkthrough

Walkthrough

Adds append_manifest to tarball and zip download flows, applies synthesized runtime package.json bytes during extraction when needed, and updates binary-resolution call sites, other download call sites, tests, and porting notes.

Changes

append_manifest feature

Layer / File(s) Summary
apply_append_manifest and extraction wiring
pacquet/crates/tarball/src/lib.rs
Adds append_manifest on both download structs, implements apply_append_manifest, and applies it in tarball and zip extraction paths before store-index queueing.
Runtime manifest synthesis
pacquet/crates/package-manager/src/install_package_by_snapshot.rs
Precomputes synthesized runtime package.json bytes and passes them as append_manifest for tarball and zip runtime archive handling.
Other download call sites set append_manifest to None
pacquet/crates/env-installer/src/install_config_deps.rs, pacquet/crates/package-manager/src/install_package_from_registry.rs, pacquet/crates/package-manager/src/patch.rs, pacquet/crates/package-manager/src/prefetching_resolver.rs, pacquet/crates/package-manager/src/tarball_prefetch.rs, pacquet/tasks/micro-benchmark/src/main.rs
Updates remaining DownloadTarballToStore initializations to pass append_manifest: None explicitly.
Tests and porting notes
pacquet/crates/tarball/src/tests.rs, pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs, pacquet/plans/TEST_PORTING.md
Updates tests for the new field, adds helper coverage, adds an end-to-end runtime regression test, and expands the runtime test-porting notes.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant InstallPackageBySnapshot
  participant DownloadTarballToStore
  participant apply_append_manifest
  participant CAS

  InstallPackageBySnapshot->>InstallPackageBySnapshot: synthesize_runtime_manifest_bytes()
  InstallPackageBySnapshot->>DownloadTarballToStore: run(append_manifest: Some(bytes))
  DownloadTarballToStore->>DownloadTarballToStore: extract archive
  alt package.json missing
    DownloadTarballToStore->>apply_append_manifest: apply(cas_paths, pkg_files_idx, bytes)
    apply_append_manifest->>CAS: write synthesized package.json
  end
  DownloadTarballToStore-->>InstallPackageBySnapshot: extraction result
Loading

Suggested labels: product: pacquet

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-pacquet-runtime-dlx-warm-manifest

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

❤️ Share

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

@qodo-code-review

qodo-code-review Bot commented Jul 6, 2026

Copy link
Copy Markdown

PR Summary by Qodo

Persist synthesized runtime package.json into the pacquet store index

🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Persist synthesized runtime package.json into the store-index row for warm installs.
• Thread append_manifest through tarball/zip fetchers so cold/warm materializations match.
• Add unit tests covering manifest folding and the no-op behavior for normal packages.
Diagram

graph TD
  A["Install snapshot"] --> B["Synthesize manifest"] --> C["Download + extract"] --> D{"Archive has package.json?"}
  D -->|"no"| E["apply_append_manifest"] --> F[("CAFS blobs")] --> G[("Store index row")]
  D -->|"yes"| G

  subgraph Legend
    direction LR
    _fn["Function"] ~~~ _dec{"Decision"} ~~~ _db[("Persistent store")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Post-write store-index patch-up
  • ➕ Avoids adding a new parameter to all download call sites
  • ➕ Could be implemented entirely in the store-index writer layer
  • ➖ More complex lifecycle: you must coordinate with queued/in-flight writes
  • ➖ Still needs to ensure CAS blob exists and is referenced consistently
  • ➖ Harder to guarantee correctness under retries/concurrency
2. Force warm path to re-run binary fetch/synthesis
  • ➕ Keeps store-index schema/rows unchanged
  • ➕ Moves responsibility to materialization layer
  • ➖ Defeats the purpose of warm materialization/prefetch
  • ➖ Adds network/compute to warm installs and hurts performance/offline behavior
3. Add `dlx`/bin-linker fallback when manifest is missing
  • ➕ Improves resilience for stores already containing pre-fix rows
  • ➕ Does not require rewriting existing store-index data
  • ➖ Paper-over fix: runtime slots can still be incomplete/missing package.json
  • ➖ More conditional behavior and potential divergence from pnpm semantics

Recommendation: Keep the PR’s approach: thread a synthesized manifest via append_manifest and fold it into both CAFS output and the persisted PackageFilesIndex row before it’s written. This aligns with pnpm’s appendManifest semantics and fixes the warm-materialization failure at the source (store-index correctness). Consider the bin-linker fallback only as a follow-up hardening measure for already-corrupted stores.

Files changed (9) +176 / -30

Bug fix (7) +101 / -26
install_config_deps.rsPlumb new 'append_manifest' field for installer tarball downloads +1/-0

Plumb new 'append_manifest' field for installer tarball downloads

• Updates the tarball download invocation to set 'append_manifest: None' to match the expanded downloader API. This keeps env-installer builds compiling while reserving manifest appending for runtime archives only.

pacquet/crates/env-installer/src/install_config_deps.rs

install_package_by_snapshot.rsPass synthesized runtime manifest into binary downloads +15/-24

Pass synthesized runtime manifest into binary downloads

• Moves runtime 'package.json' synthesis earlier and passes it to both tarball and zip binary download paths via 'append_manifest'. Removes the previous post-download in-memory-only insertion so the persisted store-index row includes the manifest for warm installs.

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

install_package_from_registry.rsUpdate registry tarball downloads for 'append_manifest' API +1/-0

Update registry tarball downloads for 'append_manifest' API

• Adds 'append_manifest: None' to registry package downloads, preserving existing behavior (registry packages already ship a 'package.json').

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

patch.rsUpdate patch write path for new download options +1/-0

Update patch write path for new download options

• Extends the download configuration used by patching to include 'append_manifest: None'. No behavior change intended; keeps compilation consistent with the new tarball API.

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

prefetching_resolver.rsExtend prefetching downloads with 'append_manifest: None' +1/-0

Extend prefetching downloads with 'append_manifest: None'

• Updates resolve-time prefetch downloads to set 'append_manifest' explicitly to 'None', ensuring only runtime binary fetches can inject synthesized manifests.

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

tarball_prefetch.rsAlign background tarball prefetch with new downloader API +1/-0

Align background tarball prefetch with new downloader API

• Adds 'append_manifest: None' to the spawned tarball downloads used for mem-cache prefetching. Keeps prefetch behavior unchanged while supporting the new manifest-folding capability.

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

lib.rsImplement 'append_manifest' folding into CAFS + store-index rows +81/-2

Implement 'append_manifest' folding into CAFS + store-index rows

• Introduces 'apply_append_manifest' to write a synthesized 'package.json' into the CAS and record it in both 'cas_paths' and the persisted 'PackageFilesIndex' ('files' map and bundled 'manifest'). Adds an 'append_manifest' option to both tarball and zip download structs and applies it before queueing the store-index row, fixing warm materialization for runtime archives.

pacquet/crates/tarball/src/lib.rs

Refactor (1) +1 / -0
main.rsUpdate micro-benchmark tarball download configuration +1/-0

Update micro-benchmark tarball download configuration

• Adds 'append_manifest: None' to the benchmark harness’s tarball download invocation to match the updated API. No benchmark semantics change intended.

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

Tests (1) +74 / -4
tests.rsAdd unit tests for 'apply_append_manifest' and update call sites +74/-4

Add unit tests for 'apply_append_manifest' and update call sites

• Adds tests verifying that a synthesized runtime manifest is persisted into both the files map and bundled manifest, and that the function is a no-op when an archive already includes 'package.json'. Updates existing tests to populate the new 'append_manifest' field with 'None'.

pacquet/crates/tarball/src/tests.rs

@qodo-code-review

qodo-code-review Bot commented Jul 6, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Historical pre-fix comments ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
New test comments use historical phrasing like Pre-fix / pre-fix gap to describe prior behavior
rather than the current contract. This increases drift risk and violates the requirement that
comments describe present behavior and invariants.
Code

pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[R612-734]

+/// End-to-end regression for the CI failure on pnpm/pnpm#12811, mirroring
+/// the core of `installing/deps-installer/test/install/nodeRuntime.ts:209`
+/// (`installing Node.js runtime`): a cold install, then `rimraf
+/// node_modules` + an offline reinstall. A runtime archive ships no
+/// `package.json`, so pacquet synthesizes one — and it must be baked into
+/// the persisted store-index row, not just this install's `cas_paths`.
+/// Pre-fix the row recorded neither the `package.json` file nor a bundled
+/// `manifest`, so a later *warm* install (which materializes straight from
+/// the row and never re-runs `fetch_binary_resolution_to_cas`) landed a
+/// manifest-less slot and `pnpm dlx node@runtime:<v>` died in `getBinName`
+/// with `dlx_read_manifest`.
+#[tokio::test]
+async fn installing_a_runtime_persists_the_synthesized_manifest_into_the_store_index_row() {
+    use pacquet_store_dir::{
+        SharedVerifiedFilesCache, StoreIndex, StoreIndexWriter, store_index_key,
+    };
+    use std::sync::atomic::AtomicU8;
+
+    let archive_tmp = tempfile::tempdir().expect("tempdir");
+    let tarball_path = archive_tmp.path().join("node-fixture.tar.gz");
+    let tarball_bytes = build_runtime_tarball_fixture();
+    std::fs::write(&tarball_path, &tarball_bytes).expect("write the fixture tarball");
+    let integrity = ssri::IntegrityOpts::new()
+        .algorithm(ssri::Algorithm::Sha512)
+        .chain(&tarball_bytes)
+        .result();
+
+    let store_tmp = tempfile::tempdir().expect("tempdir");
+    // `offline: true` is safe — a `file:` URL bypasses the offline gate,
+    // and it guarantees the install never reaches the network.
+    let config = leaked_offline_config("https://registry.test", store_tmp.path());
+    let (writer, writer_task) = StoreIndexWriter::spawn(&config.store_dir);
+
+    let package_key: PackageKey = "node@runtime:22.0.0".parse().expect("parse runtime key");
+    let metadata = pacquet_lockfile::PackageMetadata {
+        resolution: LockfileResolution::Binary(BinaryResolution {
+            url: format!("file:{}", tarball_path.display()),
+            integrity: integrity.clone(),
+            bin: BinarySpec::Map(std::collections::BTreeMap::from([(
+                "node".to_string(),
+                "bin/node".to_string(),
+            )])),
+            archive: BinaryArchive::Tarball,
+            prefix: None,
+        }),
+        version: Some("22.0.0".to_string()),
+        has_bin: Some(true),
+        engines: None,
+        cpu: None,
+        os: None,
+        libc: None,
+        deprecated: None,
+        prepare: None,
+        bundled_dependencies: None,
+        peer_dependencies: None,
+        peer_dependencies_meta: None,
+    };
+    let snapshot = pacquet_lockfile::SnapshotEntry::default();
+    let layout = crate::VirtualStoreLayout::legacy(store_tmp.path().join("vstore"), 120);
+    let allow_build_policy = crate::AllowBuildPolicy::new(
+        std::collections::HashSet::default(),
+        std::collections::HashSet::default(),
+        false,
+    );
+    let skipped = crate::SkippedSnapshots::new();
+    let logged_methods = AtomicU8::new(0);
+    let verified_files_cache = SharedVerifiedFilesCache::default();
+
+    // Cold install: fetch the fixture, synthesize the manifest, queue the row.
+    let cold_cas_paths = super::InstallPackageBySnapshot {
+        http_client: &pacquet_network::ThrottledClient::default(),
+        config,
+        layout: &layout,
+        store_index: None,
+        store_index_writer: Some(&writer),
+        prefetched_cas_paths: None,
+        progress_reported: None,
+        tarball_mem_cache: None,
+        verified_files_cache: &verified_files_cache,
+        logged_methods: &logged_methods,
+        requester: "/project",
+        package_key: &package_key,
+        metadata: &metadata,
+        snapshot: &snapshot,
+        allow_build_policy: &allow_build_policy,
+        skipped: &skipped,
+        workspace_root: store_tmp.path(),
+        node_linker: pacquet_config::NodeLinker::Hoisted,
+        defer_link: false,
+        link_concurrency_probe: None,
+    }
+    .run::<pacquet_reporter::SilentReporter>()
+    .await
+    .expect("cold runtime install");
+    assert!(cold_cas_paths.contains_key("package.json"), "the cold slot gets the manifest");
+
+    // Flush the store-index writer so the row is durable before read-back.
+    drop(writer);
+    writer_task.await.expect("join the writer task").expect("flush the store index");
+
+    // The persisted row must carry the synthesized `package.json` in both
+    // its `files` map and its bundled `manifest` — the pre-fix gap that a
+    // warm materialization would inherit.
+    let index_key =
+        store_index_key(&integrity.to_string(), &package_key.without_peer().to_string());
+    let row = StoreIndex::open_in(&config.store_dir)
+        .expect("open the store index")
+        .get(&index_key)
+        .expect("read the runtime row")
+        .expect("the runtime row was persisted");
+    assert!(row.files.contains_key("package.json"), "the row records the synthesized package.json");
+    let manifest = row.manifest.expect("the row records a bundled manifest");
+    assert_eq!(
+        manifest.get("bin").and_then(|bin| bin.get("node")).and_then(serde_json::Value::as_str),
+        Some("bin/node"),
+        "the bundled manifest carries the runtime bin",
+    );
+
+    // Warm reinstall — nodeRuntime.ts's `rimraf node_modules` + offline
+    // reinstall. Delete the archive so the store is the only possible
+    // source, then materialize straight from the persisted row. The slot
+    // must still get the `package.json`; pre-fix the row lacked it.
+    std::fs::remove_file(&tarball_path).expect("remove the fixture so only the store can serve");
Evidence
The checklist forbids historical/temporal phrasing in added/modified comments. The referenced
comment blocks explicitly use Pre-fix / pre-fix gap / pre-fix the row lacked it, which are
historical descriptions rather than current-contract wording.

Rule 772199: Comments must describe current behavior, not historical implementations
pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[612-622]
pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[712-734]

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

## Issue description
New comments in the runtime install regression test describe *past* behavior using phrases like `Pre-fix` and `pre-fix gap`. Per the checklist, comments should describe the current behavior/contract (or the invariant being protected) without historical narration.
## Issue Context
This is within a regression test and inline comments explaining why the persisted store-index row must contain the synthesized `package.json`/bundled `manifest`. The same intent can be expressed as a current invariant (e.g., "If the row omits `package.json`, a warm install will fail...") without referencing pre-fix history.
## Fix Focus Areas
- pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[612-622]
- pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[712-734]

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


2. Missing tar header checksum ✗ Dismissed 🐞 Bug ≡ Correctness
Description
build_runtime_tarball_fixture() writes a tar entry header without calling header.set_cksum(), which
can produce an invalid tar stream that archive readers reject, breaking the new regression test.
This repo’s other tar fixtures consistently recompute the checksum before appending entries.
Code

pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[R599-604]

+    let mut header = tar::Header::new_gnu();
+    header.set_size(script.len() as u64);
+    header.set_mode(0o755);
+    tar_builder
+        .append_data(&mut header, "node-v22.0.0-fixture/bin/node", &script[..])
+        .expect("append the fixture bin entry");
Evidence
The new fixture builds a tar header and appends it without recomputing the checksum. Elsewhere in
the repo, tar fixtures explicitly call set_cksum() before append, indicating this is the
expected/required pattern for producing valid tar bytes.

pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[597-605]
pacquet/crates/package-manager/src/prefetching_resolver/tests.rs[141-152]

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

## Issue description
The runtime tarball fixture builds a `tar::Header` but never calls `set_cksum()`. Many tar writers/readers expect the header checksum to be correct; without it, extraction may fail and the regression test won’t reliably validate the intended behavior.
## Issue Context
Other fixtures in this repo call `header.set_cksum()` after setting size/mode/path and before appending data.
## Fix Focus Areas
- pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[597-605]
## Suggested change
Add `header.set_cksum();` after `set_mode(...)` (and after setting path if you add that later) and before `append_data(...)`.

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



Remediation recommended

3. Case-colliding package.json 🐞 Bug ⛨ Security
Description
apply_append_manifest only checks for an exact "package.json" key, so an archive containing a
case-variant like "Package.json" will end up with two distinct entries in cas_paths/files. On
case-insensitive filesystems, materialization may keep the wrong bytes because imports are no-op on
AlreadyExists and the marker placement also treats an existing destination as success.
Code

pacquet/crates/tarball/src/lib.rs[R618-636]

+) -> Result<(), TarballError> {
+    if pkg_files_idx.files.contains_key("package.json") {
+        return Ok(());
+    }
+    let (cas_path, file_hash) =
+        store_dir.write_cas_file(manifest_bytes, false).map_err(TarballError::WriteCasFile)?;
+    let checked_at =
+        UNIX_EPOCH.elapsed().ok().and_then(|elapsed| u64::try_from(elapsed.as_millis()).ok());
+    let info = CafsFileInfo {
+        digest: format!("{file_hash:x}"),
+        // A synthesized manifest is a plain, non-executable data file;
+        // `0o644` is the same canonical mode `add_files_from_dir` reports
+        // for a non-executable entry (and pnpm's Windows-host default).
+        mode: 0o644,
+        size: manifest_bytes.len() as u64,
+        checked_at,
+    };
+    cas_paths.insert("package.json".to_string(), cas_path);
+    pkg_files_idx.files.insert("package.json".to_string(), info);
Evidence
The new helper inserts a canonical package.json purely based on an exact-case check, which allows
both Package.json and package.json to coexist in the index/maps. The materialization layer
treats existing targets as success (no overwrite), so a colliding preexisting casing can prevent the
synthesized bytes from being written as the completion marker on case-insensitive filesystems.

pacquet/crates/tarball/src/lib.rs[613-646]
pacquet/crates/package-manager/src/import_indexed_dir.rs[218-246]
pacquet/crates/package-manager/src/import_indexed_dir.rs[250-304]
pacquet/crates/package-manager/src/link_file.rs[155-190]

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

## Issue description
`apply_append_manifest` treats presence of `package.json` as a case-sensitive lookup (`files.contains_key("package.json")`). If an archive contains a case-variant filename (e.g. `Package.json`), `apply_append_manifest` will still add a synthesized lowercase `package.json` entry, creating two paths that collide on case-insensitive filesystems.
During import/materialization, file imports are no-ops when the destination already exists, and marker placement (`import_marker_atomic`) also treats an existing destination as success. This means the synthesized manifest can fail to land on disk (or the on-disk bytes can be inconsistent with the store-index row), undermining the goal of reliably materializing the runtime’s `package.json`.
## Issue Context
- `apply_append_manifest` inserts `"package.json"` without guarding against case-variants.
- Import/materialization treats `AlreadyExists` as success and does not overwrite.
## Fix Focus Areas
- pacquet/crates/tarball/src/lib.rs[613-646]
- pacquet/crates/tarball/src/tests.rs[3212-3261]
## Suggested fix approach
1. In `apply_append_manifest`, before deciding to early-return or insert, scan for any existing key in `pkg_files_idx.files` that matches `package.json` in a case-insensitive way (e.g. `eq_ignore_ascii_case`).
2. If an exact `package.json` exists: keep current behavior (`Ok(())`).
3. If only case-variants exist:
 - Remove those entries from both `pkg_files_idx.files` and `cas_paths` (and log a warning that the archive shipped an unexpected manifest casing), then proceed to write/insert the synthesized canonical `package.json`.
 - This avoids creating two colliding entries and guarantees the canonical marker file will be materialized.
4. Add a unit test covering the case-variant scenario (e.g. pre-populate `idx.files` with `"Package.json"` and ensure `apply_append_manifest` results in only canonical `"package.json"` being present).

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


4. Key omits appendManifest 🐞 Bug ⛨ Security
Description
append_manifest mutates the persisted PackageFilesIndex (adds package.json and possibly
manifest) before the row is queued, but the store-index key remains {integrity}\t{pkg_id}. If
two installs generate different synthesized manifests for the same (integrity, pkg_id), a warm
install can reuse a row with the wrong persisted manifest/bin mapping, making installs dependent on
prior store state.
Code

pacquet/crates/tarball/src/lib.rs[R2394-2398]

+        // Fold the synthesized runtime `package.json` into the row before
+        // it is persisted, so warm reinstalls (which read the row) get it.
+        if let Some(manifest_bytes) = append_manifest {
+            apply_append_manifest(store_dir, manifest_bytes, &mut cas_paths, &mut pkg_files_idx)?;
+        }
Evidence
The store-index row key is only {integrity}\t{pkg_id}, but this PR now mutates the queued row
based on append_manifest bytes (written into files["package.json"] and possibly manifest).
Those bytes are synthesized from BinaryResolution.bin, so if two installs ever synthesize
different bytes for the same key, the persisted row can be reused incorrectly.

pacquet/crates/tarball/src/lib.rs[2289-2419]
pacquet/crates/store-dir/src/store_index.rs[868-900]
pacquet/crates/package-manager/src/install_package_by_snapshot.rs[827-846]

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

## Issue description
This PR persists a synthesized runtime `package.json`/bundled `manifest` into the store-index row, but the row key stays `"{integrity}\t{pkg_id}"`. That means the cached row’s *value* can vary with `append_manifest` bytes (derived from lockfile `BinaryResolution.bin`), while the *key* does not—so store reuse can return a row whose synthesized manifest differs from what the current install would synthesize.
### Issue Context
- The tarball/zip download path now calls `apply_append_manifest(...)` before queueing the `PackageFilesIndex` row.
- The store-index key is still computed from integrity + pkg_id only.
- There is precedent in `git_hosted_store_index_key` that when cached content depends on an extra dimension (`built`), the key must account for it.
### How to fix
Pick one of these mitigation strategies (ordered by least invasive to pnpm interop):
1) **On store-hit / prefetched-row reuse when `append_manifest` is `Some`:**
- Compute the digest (sha512 hex) of `append_manifest` bytes.
- Verify the cached row’s `files["package.json"].digest` (and/or bundled `manifest`) matches what would be synthesized.
- If it’s missing/mismatched, treat as a cache miss and rebuild/overwrite the row (or at minimum, override the returned `cas_paths` with the synthesized `package.json` CAS entry so the current install is deterministic).
2) **Make synthesis deterministic per `(integrity, pkg_id)`** by deriving the runtime `bin` mapping from the extracted archive (or from a fixed runtime contract) rather than trusting arbitrary lockfile `bin` maps.
### Fix Focus Areas
- pacquet/crates/tarball/src/lib.rs[2289-2421]
- pacquet/crates/store-dir/src/store_index.rs[868-900]
- pacquet/crates/package-manager/src/install_package_by_snapshot.rs[827-852]

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


5. Non-portable file URL 🐞 Bug ☼ Reliability
Description
The regression test constructs a file URL via format!("file:{}", tarball_path.display()), which does
not guarantee a valid/encoded file URL (notably on Windows and for paths with reserved characters
like spaces/#). This can cause the test to fail to parse or resolve the archive path, masking the
real regression signal.
Code

pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[R648-649]

+            url: format!("file:{}", tarball_path.display()),
+            integrity: integrity.clone(),
Evidence
The test currently constructs a file: URL by string concatenation, while other parts of the repo
use Url::from_file_path() specifically to produce valid file URLs across platforms.

pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[630-656]
pacquet/crates/cli/src/cli_args/deploy.rs[1206-1211]

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

## Issue description
The test uses string formatting to create a `file:` URL from a filesystem path. This is not cross-platform and may produce an invalid URL (missing required slashes, wrong separators on Windows, and no percent-encoding).
## Issue Context
This repo already uses `url::Url::from_file_path()` when it needs a correct file URL.
## Fix Focus Areas
- pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs[645-656]
## Suggested change
Replace:

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


View more (1)
6. Duplicate runtime-archive scenario docs 📘 Rule violation ⚙ Maintainability
Description
The new Rust doc comments repeat the same concrete warm-install failure scenario already spelled out
in the new tests, increasing maintenance burden and risking drift. Per the checklist, scenario
narratives should live in either tests or docs, not both, unless the docs add new non-test context.
Code

pacquet/crates/tarball/src/tests.rs[R3213-3218]

+/// A runtime archive (Node.js / Bun / Deno) ships no `package.json`, so
+/// `apply_append_manifest` must bake the synthesized manifest into the
+/// persisted store-index row — both its `files` map and its bundled
+/// `manifest` — and into this install's `cas_paths`. Without the row
+/// entry, a later *warm* materialization reads a `package.json`-less row
+/// and `pnpm dlx node@runtime:<v>` fails with `dlx_read_manifest`.
Evidence
Rule 713470 requires avoiding duplicated test scenario explanations across docs and tests. The doc
comments on apply_append_manifest and DownloadTarballToStore::append_manifest describe the same
warm materialization / bin-linker scenario that the added tests also describe (including the `pnpm
dlx node@runtime:<v>` failure mention).

Rule 713470: Avoid duplicating test scenario explanations in both code and doc comments
pacquet/crates/tarball/src/lib.rs[600-612]
pacquet/crates/tarball/src/lib.rs[1508-1519]
pacquet/crates/tarball/src/tests.rs[3213-3218]

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

## Issue description
New/modified doc comments duplicate the same runtime-archive warm-install scenario that is already documented in the new tests (including the `pnpm dlx ...` failure narrative). This violates the guideline to avoid repeating test scenarios in doc comments.
## Issue Context
The new tests already clearly encode and explain the scenario; keeping parallel narratives in `///` docs (and struct field docs) makes future edits more error-prone.
## Fix Focus Areas
- pacquet/crates/tarball/src/lib.rs[600-612]
- pacquet/crates/tarball/src/lib.rs[1508-1519]
- pacquet/crates/tarball/src/tests.rs[3213-3218]

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


Grey Divider

Qodo Logo

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Micro-Benchmark Results

Linux

group                          main                                   pr
-----                          ----                                   --
tarball/download_dependency    1.00      6.6±0.14ms   660.4 KB/sec    1.02      6.7±0.07ms   649.1 KB/sec

Comment thread pacquet/crates/tarball/src/lib.rs
@qodo-code-review

qodo-code-review Bot commented Jul 6, 2026

Copy link
Copy Markdown

PR Code Suggestions ✨

Latest suggestions up to 8f354b9

Warning

/improve is deprecated. Use /agentic_review instead (removal date not yet scheduled).

CategorySuggestion                                                                                                                                    Impact
Possible issue
Avoid overwriting existing manifest

Check cas_paths for package.json before applying the appended manifest.

pacquet/crates/tarball/src/lib.rs [613-646]

 fn apply_append_manifest(
     store_dir: &StoreDir,
     manifest_bytes: &[u8],
     cas_paths: &mut HashMap<String, PathBuf>,
     pkg_files_idx: &mut PackageFilesIndex,
 ) -> Result<(), TarballError> {
-    if pkg_files_idx.files.contains_key("package.json") {
+    if pkg_files_idx.files.contains_key("package.json") || cas_paths.contains_key("package.json") {
         return Ok(());
     }
     let (cas_path, file_hash) =
         store_dir.write_cas_file(manifest_bytes, false).map_err(TarballError::WriteCasFile)?;
     let checked_at =
         UNIX_EPOCH.elapsed().ok().and_then(|elapsed| u64::try_from(elapsed.as_millis()).ok());
     let info = CafsFileInfo {
         digest: format!("{file_hash:x}"),
-        // A synthesized manifest is a plain, non-executable data file;
-        // `0o644` is the same canonical mode `add_files_from_dir` reports
-        // for a non-executable entry (and pnpm's Windows-host default).
         mode: 0o644,
         size: manifest_bytes.len() as u64,
         checked_at,
     };
     cas_paths.insert("package.json".to_string(), cas_path);
     pkg_files_idx.files.insert("package.json".to_string(), info);
-    // Surface the synthesized manifest as the row's bundled manifest so
-    // the warm-batch bin linker reads the bin here instead of stat-ing the
-    // slot. Only when the archive supplied none, mirroring pnpm's guard.
     if pkg_files_idx.manifest.is_none()
         && let Ok(parsed) = serde_json::from_slice::<serde_json::Value>(manifest_bytes)
     {
         pkg_files_idx.manifest = normalize_bundled_manifest(&parsed);
     }
     Ok(())
 }
  • Apply / Chat
Suggestion importance[1-10]: 3

__

Why: While it's a valid defensive programming measure to check cas_paths, both collections are populated synchronously during extraction so a desync is highly unlikely.

Low
  • More

Previous suggestions

Suggestions up to commit 301e8fb
CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix type mismatch by explicitly slicing manifest_bytes

Explicitly slice manifest_bytes to prevent a type mismatch compiler error.

pacquet/crates/package-manager/src/install_package_by_snapshot.rs [788-816]

             progress_reported: None,
-            append_manifest: Some(&manifest_bytes),
+            append_manifest: Some(&manifest_bytes[..]),
         }
         .run_without_mem_cache::<Reporter>()
         .await
         .map_err(InstallPackageBySnapshotError::DownloadTarball)?,
         BinaryArchive::Zip => DownloadZipArchiveToStore {
 ...
             ignore_file_pattern,
             offline: config.offline,
-            append_manifest: Some(&manifest_bytes),
+            append_manifest: Some(&manifest_bytes[..]),
         }
         .run_without_mem_cache::<Reporter>()
         .await
         .map_err(InstallPackageBySnapshotError::DownloadTarball)?,
     };
Suggestion importance[1-10]: 10

__

Why: This catches a critical compiler error, as Option<&Vec<u8>> cannot be implicitly coerced to Option<&[u8]> in struct initialization.

High
Replace unstable && let syntax with nested if

Replace the unstable && let syntax with nested if statements to ensure
compilation on stable Rust.

pacquet/crates/tarball/src/lib.rs [640-644]

     // Surface the synthesized manifest as the row's bundled manifest so
     // the warm-batch bin linker reads the bin here instead of stat-ing the
     // slot. Only when the archive supplied none, mirroring pnpm's guard.
-    if pkg_files_idx.manifest.is_none()
-        && let Ok(parsed) = serde_json::from_slice::<serde_json::Value>(manifest_bytes)
-    {
-        pkg_files_idx.manifest = normalize_bundled_manifest(&parsed);
+    if pkg_files_idx.manifest.is_none() {
+        if let Ok(parsed) = serde_json::from_slice::<serde_json::Value>(manifest_bytes) {
+            pkg_files_idx.manifest = normalize_bundled_manifest(&parsed);
+        }
     }
Suggestion importance[1-10]: 10

__

Why: This addresses a compilation error on stable Rust, as let chains inside if conditions are currently an unstable feature.

High

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 301e8fb

@github-actions github-actions Bot added the reviewed: coderabbit CodeRabbit submitted an approving review label Jul 6, 2026
@codecov-commenter

codecov-commenter commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.23529% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.42%. Comparing base (d1da02e) to head (8f354b9).

Files with missing lines Patch % Lines
pacquet/crates/tarball/src/lib.rs 87.80% 5 Missing ⚠️
...package-manager/src/install_package_by_snapshot.rs 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12829      +/-   ##
==========================================
+ Coverage   86.33%   86.42%   +0.09%     
==========================================
  Files         438      438              
  Lines       68355    68395      +40     
==========================================
+ Hits        59013    59110      +97     
+ Misses       9342     9285      -57     

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

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

Port the core of `installing/deps-installer/test/install/nodeRuntime.ts:209`
(`installing Node.js runtime` — cold install, then rimraf `node_modules` +
offline reinstall) as a network-free integration test.

`installing_a_runtime_persists_the_synthesized_manifest_into_the_store_index_row`
drives `InstallPackageBySnapshot` on a `Binary` resolution pointing at a
local `file:` runtime-archive fixture (a tarball with a `bin/node` and no
`package.json`), backed by a real `StoreIndexWriter`. It asserts the cold
install's `cas_paths` carries the synthesized `package.json`, the persisted
store-index row records it in both `files` and the bundled `manifest`, and a
warm/offline reinstall — with the fixture deleted so only the store can
serve — re-materializes it from that row. Verified to fail when the
`apply_append_manifest` fold is neutered.

The real-download lockfile-shape / musl-variant / npm+corepack-filter
assertions of nodeRuntime.ts remain unported; TEST_PORTING.md notes the split.
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 0a4b3fb

@qodo-code-review

Copy link
Copy Markdown

PR Code Suggestions ✨

Warning

/improve is deprecated. Use /agentic_review instead (removal date not yet scheduled).

No code suggestions found for the PR.

Auto-approved notes - no code suggestions found
- 'approve_pr_on_self_review' flag enabled

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

763-769: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Strengthen the warm-reinstall assertion to check manifest content, not just key presence.

The regression this test guards against (dlx_read_manifest failing to resolve bin) is specifically about manifest content, not just a package.json key existing in cas_paths. The cold-path/row checks (lines 722-728) verify the bin field content, but the final warm assertion only checks contains_key. Reading the file at warm_cas_paths.get("package.json") and asserting its bin.node value would tie the test more directly to the actual failure mode being fixed.

Based on path instructions ("Test expectation: add a regression test that ... asserts persisted results (warm reinstall) rather than only executing nearby code paths"), this closes the loop on end-to-end proof.

♻️ Suggested strengthening
     assert!(
         warm_cas_paths.contains_key("package.json"),
         "the warm reinstall re-materializes the manifest from the persisted row",
     );
+    let warm_manifest_path = warm_cas_paths.get("package.json").expect("warm package.json slot");
+    let warm_manifest_bytes =
+        std::fs::read(warm_manifest_path).expect("read the warm-materialized package.json");
+    let warm_manifest: serde_json::Value =
+        serde_json::from_slice(&warm_manifest_bytes).expect("parse the warm manifest");
+    assert_eq!(
+        warm_manifest.get("bin").and_then(|bin| bin.get("node")).and_then(serde_json::Value::as_str),
+        Some("bin/node"),
+        "the warm-materialized manifest carries the runtime bin",
+    );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs`
around lines 763 - 769, The warm-reinstall check in
install_package_by_snapshot/tests.rs only verifies that warm_cas_paths contains
the "package.json" key, which is too weak for the regression being guarded.
Update the final assertion in the warm reinstall test to read the manifest from
the path returned by warm_cas_paths.get("package.json") and assert its persisted
content, especially the bin.node value, using the existing test setup around
warm_cas_paths and the manifest checks already used earlier in the test.

Source: Path instructions

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

Nitpick comments:
In `@pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs`:
- Around line 763-769: The warm-reinstall check in
install_package_by_snapshot/tests.rs only verifies that warm_cas_paths contains
the "package.json" key, which is too weak for the regression being guarded.
Update the final assertion in the warm reinstall test to read the manifest from
the path returned by warm_cas_paths.get("package.json") and assert its persisted
content, especially the bin.node value, using the existing test setup around
warm_cas_paths and the manifest checks already used earlier in the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c8874f3c-6f6f-468e-b135-1071e7c00a16

📥 Commits

Reviewing files that changed from the base of the PR and between 301e8fb and 0a4b3fb.

📒 Files selected for processing (2)
  • pacquet/crates/package-manager/src/install_package_by_snapshot/tests.rs
  • pacquet/plans/TEST_PORTING.md
✅ Files skipped from review due to trivial changes (1)
  • pacquet/plans/TEST_PORTING.md

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 0a4b3fb

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 0a4b3fb

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Integrated-Benchmark Report (Linux)

Commit: 0a4b3fb15b8f

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

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.174 ± 0.099 4.047 4.369 1.91 ± 0.13
pacquet@main 4.186 ± 0.189 3.945 4.531 1.91 ± 0.15
pnpr@HEAD 2.200 ± 0.133 2.030 2.370 1.00 ± 0.09
pnpr@main 2.191 ± 0.139 1.999 2.393 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.173935280259999,
      "stddev": 0.09894761655879349,
      "median": 4.148459878060001,
      "user": 3.9257931799999994,
      "system": 3.5129288800000005,
      "min": 4.04716913406,
      "max": 4.36894455806,
      "times": [
        4.18638028606,
        4.16510428606,
        4.04716913406,
        4.10665670606,
        4.30872109006,
        4.10902718006,
        4.10990811806,
        4.13181547006,
        4.36894455806,
        4.20562597406
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.1858937448599995,
      "stddev": 0.18908684613689147,
      "median": 4.11542221256,
      "user": 4.009833179999999,
      "system": 3.4952954800000002,
      "min": 3.94485242306,
      "max": 4.53074795606,
      "times": [
        4.47007072506,
        4.12658826006,
        4.53074795606,
        4.18992386306,
        4.08733223306,
        4.10345901506,
        4.10425616506,
        4.01887038906,
        3.94485242306,
        4.28283641906
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.2000479337599996,
      "stddev": 0.13299909429167123,
      "median": 2.18821468006,
      "user": 2.67983268,
      "system": 2.99306288,
      "min": 2.03044966006,
      "max": 2.36988872606,
      "times": [
        2.20535418706,
        2.36988872606,
        2.36455656306,
        2.17107517306,
        2.03234770806,
        2.30483448406,
        2.03044966006,
        2.10810769906,
        2.32096613006,
        2.0928990070599998
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.19097449736,
      "stddev": 0.13919796285879676,
      "median": 2.20224733506,
      "user": 2.70270958,
      "system": 2.9960678799999996,
      "min": 1.99917724706,
      "max": 2.39325740806,
      "times": [
        2.39325740806,
        2.05852217906,
        2.19035710506,
        2.01020977206,
        2.3296133600599997,
        1.99917724706,
        2.33899323006,
        2.13888949506,
        2.23658761206,
        2.21413756506
      ]
    }
  ]
}

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

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 629.6 ± 15.6 612.4 656.5 1.00
pacquet@main 641.2 ± 34.0 616.2 734.2 1.02 ± 0.06
pnpr@HEAD 722.7 ± 85.4 671.7 959.8 1.15 ± 0.14
pnpr@main 688.6 ± 22.3 663.6 716.8 1.09 ± 0.04
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.62958809812,
      "stddev": 0.015559793481111785,
      "median": 0.62321097372,
      "user": 0.3753712,
      "system": 1.31446828,
      "min": 0.61244227472,
      "max": 0.65648563772,
      "times": [
        0.65259464572,
        0.6233674207200001,
        0.6230545267200001,
        0.61450749472,
        0.61244227472,
        0.6402938797200001,
        0.6329468957200001,
        0.65648563772,
        0.6230292577200001,
        0.61715894772
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.6412436668200001,
      "stddev": 0.03404476802622841,
      "median": 0.63010650622,
      "user": 0.38286619999999993,
      "system": 1.30848498,
      "min": 0.61624433372,
      "max": 0.7342318267200001,
      "times": [
        0.6371178687200001,
        0.64368483172,
        0.61812445772,
        0.62757207072,
        0.62926973172,
        0.63094103572,
        0.62927197672,
        0.61624433372,
        0.64597853472,
        0.7342318267200001
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.72270306012,
      "stddev": 0.08538198032723325,
      "median": 0.6941586177200001,
      "user": 0.4022145999999999,
      "system": 1.35515098,
      "min": 0.6716637977200001,
      "max": 0.9598287737200001,
      "times": [
        0.6885827307200001,
        0.6885371237200001,
        0.70604258872,
        0.6919536967200001,
        0.69739149272,
        0.6840716437200001,
        0.6716637977200001,
        0.69636353872,
        0.9598287737200001,
        0.74259521472
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.68864831692,
      "stddev": 0.022315034912533963,
      "median": 0.68940236272,
      "user": 0.393498,
      "system": 1.33862518,
      "min": 0.66359455272,
      "max": 0.71677238672,
      "times": [
        0.71677238672,
        0.69350132972,
        0.66359455272,
        0.6664922077200001,
        0.71210046072,
        0.66525207172,
        0.68530339572,
        0.70953969072,
        0.70930011472,
        0.66462695872
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 4.302 ± 0.032 4.247 4.352 2.00 ± 0.08
pacquet@main 4.330 ± 0.025 4.292 4.372 2.01 ± 0.08
pnpr@HEAD 2.218 ± 0.102 2.077 2.431 1.03 ± 0.06
pnpr@main 2.152 ± 0.083 2.045 2.321 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 4.3021786766800005,
      "stddev": 0.03204609886918103,
      "median": 4.30247912638,
      "user": 3.80175232,
      "system": 3.3792206800000004,
      "min": 4.24699210388,
      "max": 4.35220199888,
      "times": [
        4.29224277188,
        4.32367427288,
        4.3143695088800005,
        4.28354990488,
        4.24699210388,
        4.308669123880001,
        4.29628912888,
        4.35220199888,
        4.33768502088,
        4.26611293188
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 4.330174649480001,
      "stddev": 0.024664189826323343,
      "median": 4.33478822338,
      "user": 3.8606682199999995,
      "system": 3.3785789800000003,
      "min": 4.2922285458800005,
      "max": 4.37161517888,
      "times": [
        4.31703763388,
        4.3422901318800005,
        4.350350675880001,
        4.32728631488,
        4.34415692788,
        4.37161517888,
        4.2922285458800005,
        4.31032622088,
        4.34440411288,
        4.30205075188
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 2.21849782738,
      "stddev": 0.10247230462494226,
      "median": 2.21076678588,
      "user": 2.47464662,
      "system": 2.91602348,
      "min": 2.0770734328800002,
      "max": 2.4309955958800002,
      "times": [
        2.29556629688,
        2.2516857648800004,
        2.0770734328800002,
        2.12200578888,
        2.16277534488,
        2.4309955958800002,
        2.17207284988,
        2.15385637388,
        2.2494607218800002,
        2.2694861038800003
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 2.15180636908,
      "stddev": 0.08251844632885226,
      "median": 2.13100990138,
      "user": 2.5508194200000003,
      "system": 2.90647198,
      "min": 2.04472352888,
      "max": 2.32119135688,
      "times": [
        2.07798417588,
        2.12288867588,
        2.04472352888,
        2.18186692688,
        2.32119135688,
        2.11808966288,
        2.15048350088,
        2.25484386288,
        2.13913112688,
        2.10686087288
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 1.391 ± 0.031 1.352 1.451 2.14 ± 0.06
pacquet@main 1.454 ± 0.031 1.421 1.529 2.23 ± 0.06
pnpr@HEAD 0.690 ± 0.009 0.678 0.708 1.06 ± 0.02
pnpr@main 0.651 ± 0.010 0.637 0.671 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 1.3914230145400004,
      "stddev": 0.03139862735862692,
      "median": 1.38231866974,
      "user": 1.3819592600000001,
      "system": 1.6899987600000004,
      "min": 1.3520253212400002,
      "max": 1.45064904424,
      "times": [
        1.3520253212400002,
        1.36414322224,
        1.3652866972400002,
        1.37760987724,
        1.38646390724,
        1.3961950252400002,
        1.45064904424,
        1.37817343224,
        1.41405258424,
        1.42963103424
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 1.45415458544,
      "stddev": 0.03112258488877874,
      "median": 1.44943978274,
      "user": 1.4030273600000003,
      "system": 1.74878046,
      "min": 1.42086434324,
      "max": 1.52947684524,
      "times": [
        1.4630600332400001,
        1.52947684524,
        1.46681096724,
        1.45352630424,
        1.43483275324,
        1.4453532612400002,
        1.42086434324,
        1.4660804872400002,
        1.4329277092400001,
        1.4286131502400001
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6904455739400001,
      "stddev": 0.009259955300931167,
      "median": 0.6885430272399999,
      "user": 0.3529992599999999,
      "system": 1.30561536,
      "min": 0.67802888724,
      "max": 0.70817020524,
      "times": [
        0.68579873924,
        0.68512531224,
        0.67802888724,
        0.68448961724,
        0.6978778302399999,
        0.69994422024,
        0.69167441524,
        0.69128731524,
        0.68205919724,
        0.70817020524
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.65149413614,
      "stddev": 0.010110676623414376,
      "median": 0.64985430474,
      "user": 0.34277546,
      "system": 1.26874726,
      "min": 0.63698661024,
      "max": 0.6706468182399999,
      "times": [
        0.64263518324,
        0.65086596324,
        0.63698661024,
        0.65857203924,
        0.64884264624,
        0.6422107432399999,
        0.64778498024,
        0.66110575424,
        0.6706468182399999,
        0.65529062324
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 3.078 ± 0.024 3.027 3.111 4.54 ± 0.42
pacquet@main 3.094 ± 0.057 3.034 3.232 4.56 ± 0.43
pnpr@HEAD 0.681 ± 0.022 0.651 0.708 1.00 ± 0.10
pnpr@main 0.679 ± 0.062 0.648 0.853 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 3.0783491412000004,
      "stddev": 0.024409643189211974,
      "median": 3.0777611548,
      "user": 1.82576598,
      "system": 1.96220258,
      "min": 3.0270212223,
      "max": 3.1107102653000003,
      "times": [
        3.0615962553,
        3.0994440143000004,
        3.1037903963000004,
        3.0649783623,
        3.0780386263,
        3.0270212223,
        3.0724300963,
        3.1107102653000003,
        3.0774836833,
        3.0879984903000004
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 3.0938588105,
      "stddev": 0.05736638448600275,
      "median": 3.0793888198,
      "user": 1.8120485800000001,
      "system": 1.9813251800000002,
      "min": 3.0337160693,
      "max": 3.2318721683000002,
      "times": [
        3.0802294063000004,
        3.0951661283000003,
        3.0645919313000003,
        3.0568147023,
        3.0558012653000004,
        3.0945693463,
        3.0785482333000003,
        3.2318721683000002,
        3.1472788543,
        3.0337160693
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.6807052692,
      "stddev": 0.02185712790728542,
      "median": 0.6844368053000001,
      "user": 0.35568137999999994,
      "system": 1.31312158,
      "min": 0.6511292183,
      "max": 0.7082645353,
      "times": [
        0.7082645353,
        0.6965842283,
        0.6549160513,
        0.6581504983,
        0.6511292183,
        0.6661308193000001,
        0.7014063793,
        0.6926261053,
        0.6762475053,
        0.7015973513
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.6785474401999999,
      "stddev": 0.06206193510144619,
      "median": 0.6596263173,
      "user": 0.34857678000000003,
      "system": 1.27948388,
      "min": 0.6481863093,
      "max": 0.8534806323,
      "times": [
        0.6631950273,
        0.6619058863,
        0.6789321073,
        0.6565138483,
        0.6547570733,
        0.6583650673,
        0.6492508833,
        0.8534806323,
        0.6481863093,
        0.6608875673
      ]
    }
  ]
}

Scenario: Isolated linker: fresh resolve, hot cache, offline

Command Mean [ms] Min [ms] Max [ms] Relative
pacquet@HEAD 643.2 ± 13.8 620.4 660.8 5.99 ± 0.16
pacquet@main 651.5 ± 19.2 630.3 690.6 6.07 ± 0.20
pnpr@HEAD 107.3 ± 1.8 103.1 110.4 1.00
pnpr@main 107.7 ± 1.6 103.4 111.2 1.00 ± 0.02
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 0.6432087567,
      "stddev": 0.013803467473562684,
      "median": 0.6427539226000001,
      "user": 0.61673108,
      "system": 0.14296468,
      "min": 0.6203966066000001,
      "max": 0.6608094086,
      "times": [
        0.6460172436000001,
        0.6589421526000001,
        0.6503488146,
        0.6350483316000001,
        0.6394906016,
        0.6353529356000001,
        0.6203966066000001,
        0.6280787156000001,
        0.6576027566000001,
        0.6608094086
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 0.6515351220000001,
      "stddev": 0.019165730171763276,
      "median": 0.6445344351,
      "user": 0.61691198,
      "system": 0.15079798000000003,
      "min": 0.6302664366,
      "max": 0.6906403466000001,
      "times": [
        0.6683116346000001,
        0.6722952466000001,
        0.6906403466000001,
        0.6367022406,
        0.6485898066000001,
        0.6388049556000001,
        0.6429317406,
        0.6302664366,
        0.6461371296,
        0.6406716826000001
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 0.10734784498461539,
      "stddev": 0.0017581356303845524,
      "median": 0.10764191560000001,
      "user": 0.02825574153846154,
      "system": 0.017632949230769225,
      "min": 0.10310700260000001,
      "max": 0.11039210160000001,
      "times": [
        0.10549400860000001,
        0.10858093660000001,
        0.11039210160000001,
        0.10448921260000002,
        0.10821970260000001,
        0.10761365760000001,
        0.10310700260000001,
        0.10836973660000002,
        0.10734223460000002,
        0.10875039460000001,
        0.10754830560000002,
        0.10859229760000001,
        0.10767017360000002,
        0.10400812760000001,
        0.10774475260000001,
        0.1086208356,
        0.10776012860000002,
        0.10705877160000002,
        0.10509048060000001,
        0.10663070660000001,
        0.10863874360000002,
        0.10895507960000002,
        0.10659530760000001,
        0.10998179260000002,
        0.10644735660000001,
        0.1073421216
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 0.10767193504,
      "stddev": 0.0015712166711778926,
      "median": 0.10781522260000001,
      "user": 0.027233039999999997,
      "system": 0.018387140000000003,
      "min": 0.10341579060000002,
      "max": 0.11122959360000001,
      "times": [
        0.10727469260000001,
        0.10341579060000002,
        0.10808400560000002,
        0.10819892560000001,
        0.10884346360000001,
        0.10779934460000001,
        0.10717525860000002,
        0.10922588860000002,
        0.10781105360000001,
        0.10844196260000001,
        0.10781522260000001,
        0.10758921760000001,
        0.10817483060000001,
        0.11122959360000001,
        0.10599937260000002,
        0.10871174260000001,
        0.10636376960000002,
        0.10858840360000001,
        0.10650571360000001,
        0.10441087560000001,
        0.10800003460000002,
        0.10734082660000001,
        0.10838335560000001,
        0.10947400760000002,
        0.10694102360000002
      ]
    }
  ]
}

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

Command Mean [s] Min [s] Max [s] Relative
pacquet@HEAD 7.118 ± 0.165 6.906 7.376 1.43 ± 0.05
pacquet@main 6.933 ± 0.166 6.797 7.364 1.39 ± 0.05
pnpr@HEAD 5.028 ± 0.085 4.942 5.235 1.01 ± 0.03
pnpr@main 4.975 ± 0.128 4.783 5.236 1.00
BENCHMARK_REPORT.json
{
  "results": [
    {
      "command": "pacquet@HEAD",
      "mean": 7.11789809446,
      "stddev": 0.1646630452021146,
      "median": 7.08629922906,
      "user": 4.034726579999999,
      "system": 3.7680026,
      "min": 6.90643040256,
      "max": 7.3756622925599995,
      "times": [
        7.16018167156,
        7.09441777056,
        6.96993181856,
        6.97134111256,
        7.00593848856,
        7.29394180456,
        6.90643040256,
        7.3756622925599995,
        7.32295489556,
        7.07818068756
      ]
    },
    {
      "command": "pacquet@main",
      "mean": 6.932774202659999,
      "stddev": 0.1657298364231341,
      "median": 6.89252501306,
      "user": 4.134476179999999,
      "system": 3.7663245000000005,
      "min": 6.79658032456,
      "max": 7.36415234256,
      "times": [
        7.36415234256,
        6.9496213955599995,
        6.79797111856,
        6.9761669265599995,
        6.88611269556,
        6.8723906455599995,
        6.79658032456,
        6.89893733056,
        6.81520218656,
        6.97060706056
      ]
    },
    {
      "command": "pnpr@HEAD",
      "mean": 5.028276466459999,
      "stddev": 0.08522231013630473,
      "median": 5.0036208780599996,
      "user": 2.78660838,
      "system": 3.212686,
      "min": 4.94153486656,
      "max": 5.23542521256,
      "times": [
        4.94153486656,
        5.04648567556,
        5.037335522559999,
        4.97762397456,
        4.98915734856,
        5.23542521256,
        4.9825403035599996,
        5.09141208456,
        5.01808440756,
        4.96316526856
      ]
    },
    {
      "command": "pnpr@main",
      "mean": 4.97496787456,
      "stddev": 0.12847601659055446,
      "median": 4.93579070806,
      "user": 2.8197990799999997,
      "system": 3.1793126999999997,
      "min": 4.78337353356,
      "max": 5.23593133556,
      "times": [
        4.95860358656,
        5.15625170756,
        4.94029366856,
        4.78337353356,
        4.92090482256,
        4.93128774756,
        4.93096292856,
        5.23593133556,
        4.92402238356,
        4.968047031559999
      ]
    }
  ]
}

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12829
Testbedpacquet
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
milliseconds (ms)
(Result Δ%)
Upper Boundary
milliseconds (ms)
(Limit %)
isolated-linker.fresh-install.cold-cache.cold-store📈 view plot
🚷 view threshold
4,302.18 ms
(+1.99%)Baseline: 4,218.19 ms
5,061.83 ms
(84.99%)
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
🚷 view threshold
3,078.35 ms
(+2.32%)Baseline: 3,008.68 ms
3,610.41 ms
(85.26%)
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
🚷 view threshold
1,391.42 ms
(+4.50%)Baseline: 1,331.45 ms
1,597.74 ms
(87.09%)
isolated-linker.fresh-resolve.hot-cache.offline📈 view plot
🚷 view threshold
643.21 ms
(+2.25%)Baseline: 629.03 ms
754.84 ms
(85.21%)
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
🚷 view threshold
4,173.94 ms
(+5.05%)Baseline: 3,973.38 ms
4,768.05 ms
(87.54%)
isolated-linker.fresh-restore.cold-cache.cold-store.cold-pnpr📈 view plot
🚷 view threshold
7,117.90 ms
(+4.65%)Baseline: 6,801.61 ms
8,161.93 ms
(87.21%)
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
🚷 view threshold
629.59 ms
(-0.16%)Baseline: 630.57 ms
756.69 ms
(83.20%)
🐰 View full continuous benchmarking report in Bencher

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

Branchpr/12829
Testbedpnpr

⚠️ WARNING: No Threshold found!

Without a Threshold, no Alerts will ever be generated.

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

Click to view all benchmark results
BenchmarkLatencymilliseconds (ms)
isolated-linker.fresh-install.cold-cache.cold-store📈 view plot
⚠️ NO THRESHOLD
2,218.50 ms
isolated-linker.fresh-install.cold-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
680.71 ms
isolated-linker.fresh-install.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
690.45 ms
isolated-linker.fresh-resolve.hot-cache.offline📈 view plot
⚠️ NO THRESHOLD
107.35 ms
isolated-linker.fresh-restore.cold-cache.cold-store📈 view plot
⚠️ NO THRESHOLD
2,200.05 ms
isolated-linker.fresh-restore.cold-cache.cold-store.cold-pnpr📈 view plot
⚠️ NO THRESHOLD
5,028.28 ms
isolated-linker.fresh-restore.hot-cache.hot-store📈 view plot
⚠️ NO THRESHOLD
722.70 ms
🐰 View full continuous benchmarking report in Bencher

…riant

Rephrase the store-index-row test's comments to state the current contract —
a warm install materializes straight from the persisted row, so the row must
carry the synthesized package.json and bundled manifest — instead of narrating
pre-fix behavior in source, per the repo's comment convention.
Copilot AI review requested due to automatic review settings July 7, 2026 07:40

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 was unable to review this pull request because the user who requested the review has reached their quota limit.

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 8f354b9

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 8f354b9

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

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 8f354b9

@zkochan
zkochan merged commit 1219c99 into main Jul 7, 2026
33 checks passed
@zkochan
zkochan deleted the fix-pacquet-runtime-dlx-warm-manifest branch July 7, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

product: pacquet reviewed: coderabbit CodeRabbit submitted an approving review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants