* fix(git-fetcher): bundle transitive deps of bundled dependencies The packlist `bundleDependencies` pass only spliced in each directly-bundled package's own files; it never followed that package's own dependencies, so a bundled dep's transitive (and hoisted) dependencies were dropped from the published file set. Replace the per-dependency recursion with npm-bundled's reachability walk: seed from the root manifest's `bundleDependencies`, then transitively pull in every reachable package's `dependencies` and `optionalDependencies`, resolving each via the node module-resolution walk-up (nested `node_modules/` first, then ancestor `node_modules/`). The walk-up is what lets a hoisted transitive dep at the root `node_modules/` be found and spliced in under its real path. A visited-set keyed on the canonicalised resolved directory keeps a diamond from being processed twice and stops dependency cycles. Ports the upstream pnpm test "bundles transitive dependencies of bundled dependencies (hoisted)" from releasing/commands/test/publish/pack.ts, plus nested-wins-over-hoisted and optionalDependencies/devDependencies coverage. Resolves https://github.com/pnpm/pnpm/issues/12602 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga * docs(git-fetcher): fix stale bundling comment and pin test citation Address review nits on the transitive-bundling change: - The comment in `collect_own_files` referred to a `bundleDependencies` pass "below", but bundling now lives in the separate `collect_bundled_files`; describe the current structure instead. - Pin the ported-test citation to a commit permalink, per pacquet/AGENTS.md's rule that code citations link to a specific SHA. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga * fix(git-fetcher): refuse bundled deps whose real path escapes the package A `node_modules/<name>` entry can be a symlink pointing outside the package (a sibling directory or an absolute host path). The name still passes `is_safe_bundle_name` because it is a single safe segment, so the walk-up resolves it and `collect_own_files` walks the symlink target — splicing host files into the published set. The git/directory fetchers import untrusted packages, making this an information-disclosure path. Check each resolved dependency's canonical (symlink-resolved) path against the canonical package root and refuse anything that escapes, falling back to a lexical comparison when canonicalization is unavailable. Reuses the canonicalize call already used for cycle dedup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga * fix(git-fetcher): fail closed when a bundled dep's real path is unverifiable The symlink-escape guard fell back to a lexical path check whenever `fs::canonicalize` returned `None` for the dependency. A symlink under `node_modules/` is lexically inside the package even when its target escapes, so that fallback was fail-open. When the root canonicalizes but the dependency does not, refuse the dependency instead: a genuine dependency always canonicalizes here, since `resolve_bundled_dependency` already stat'd its `package.json` through the same path. The lexical fallback now applies only when the root itself cannot be canonicalized. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga * fix(git-fetcher): correct the upstream test citation to a real commit The previous citation pinned SHA cab1c11c69, which does not exist — it was taken from the issue body without verification. Point instead at the in-repo copy of the test at pnpm11/releasing/commands/test/publish/pack.ts, pinned to a commit that actually contains it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XXHGos5SaEKKr7pUW4FXga --------- Co-authored-by: Claude <noreply@anthropic.com>
pacquet
Warning
pacquet is under active development and not yet ready for production use.
The official pnpm rewrite in Rust.
pacquet is a port of the pnpm CLI from TypeScript to Rust. It is not a new package manager and not a reimagining of pnpm. Its behavior, flags, defaults, error codes, file formats, and directory layout will match pnpm exactly.
Roadmap
pacquet will become the installation engine of pnpm. The transition will happen in two phases.
Phase 1: fetching and linking
pacquet replaces fetching and linking only. pnpm continues to create the lockfile, and pacquet does the rest. We expect this alone to make pnpm at least twice as fast in most scenarios. Shipping this phase is the current focus.
Phase 2: resolution
pacquet also takes over dependency resolution.
See CONTRIBUTING.md for development setup, debugging, testing, and benchmarking.