Commit Graph

10701 Commits

Author SHA1 Message Date
Zoltan Kochan
7a304b17c4 refactor: rename directories and unify command packages per domain (#10993)
- Rename `installing/core` → `installing/deps-installer` and `installing/headless` → `installing/deps-restorer` for clearer naming
- Rename all `plugin-commands-*` directories to use `-commands` suffix convention
- Merge multiple command packages per domain into a single `commands/` directory (one commands package per domain rule):
  - `building/{build-commands,policy-commands}` → `building/commands`
  - `deps/compliance/{audit-commands,licenses-commands,sbom-commands}` → `deps/compliance/commands`
  - `deps/inspection/{listing-commands,outdated-commands}` → `deps/inspection/commands`
  - `store/{store-commands,inspecting-commands}` → `store/commands`
  - `releasing/{publish-commands,deploy-commands}` → `releasing/commands`
  - `cli/{completion-commands,doctor-commands}` → `cli/commands`
  - `engine/pm/{self-updater-commands,setup-commands}` → `engine/pm/commands`
  - `engine/runtime/{runtime-commands,env-commands}` → `engine/runtime/commands`
  - `cache/cache-commands` → `cache/commands`
- Fix relative paths in merged test files (pnpmBin, __typings__ references)
- Update jest config to ignore `utils/` dirs at any nesting depth under `test/`
- Fix stale package names in changeset files
2026-03-17 17:42:20 +01:00
Zoltan Kochan
f47ef4b125 refactor: reorganize monorepo domain structure (#10987)
Reorganize the monorepo's top-level domain directories for clarity:

- pkg-manager/ split into:
  - installing/ (core, headless, client, resolve-dependencies, etc.)
  - installing/linking/ (hoist, direct-dep-linker, modules-cleaner, etc.)
  - bins/ (link-bins, package-bins, remove-bins)
- completion/ merged into cli/
- dedupe/ moved to installing/dedupe/
- env/ renamed to engine/ with subdomains:
  - engine/runtime/ (node.fetcher, node.resolver, plugin-commands-env, etc.)
  - engine/pm/ (plugin-commands-setup, plugin-commands-self-updater)
- env.path moved to shell/
- tools/ and runtime/ dissolved
- reviewing/ and lockfile audit packages moved to deps/:
  - deps/inspection/ (list, outdated, dependencies-hierarchy)
  - deps/compliance/ (audit, licenses, sbom)
- registry/ moved to resolving/registry/
- semver/peer-range moved to deps/
- network/fetching-types moved to fetching/
- packages/ slimmed down, moving packages to proper domains:
  - calc-dep-state, dependency-path -> deps/
  - parse-wanted-dependency -> resolving/
  - git-utils -> network/
  - naming-cases -> text/
  - make-dedicated-lockfile -> lockfile/
  - render-peer-issues -> installing/
  - plugin-commands-doctor -> cli/
  - plugin-commands-init -> workspace/

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:45:54 +01:00
zybo
5d130c3aed fix: fail incompatible lockfile in frozen CI mode (#10978)
* fix(lockfile): fail incompatible lockfile in frozen CI

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: zubeyralmaho <zubeyralmaho@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-17 01:47:13 +01:00
zybo
672e58c285 fix(core): improve no-TTY modules purge hint (#10973)
* fix(core): clarify non-interactive modules purge guidance

Add confirmModulesPurge=false workaround to the no-TTY error hint and
add a regression test for the non-interactive purge confirmation flow.

Refs #6778

* test(core): assert non-tty purge hint on error hint field

---------

Co-authored-by: zubeyralmaho <zubeyralmaho@users.noreply.github.com>
2026-03-17 00:14:05 +01:00
Jason Paulos
53c780bfc3 fix: pnpm audit fix update command in changelog (#10985) 2026-03-17 00:10:28 +01:00
Zoltan Kochan
a5e227cac6 revert: "chore: use devEngines.packageManager field"
action-setup doesn't work with devEngines.packageManager field yet.

This reverts commit 0fefd7ab17.
2026-03-16 01:15:54 +01:00
Zoltan Kochan
0fefd7ab17 chore: use devEngines.packageManager field 2026-03-15 23:17:47 +01:00
Zoltan Kochan
6e9cad3a47 fix: handle dangling symlink when linking node binary (#10972)
existsSync() follows symlinks and returns false for broken symlinks,
so a dangling symlink from a previous node install would not be removed
before creating the new symlink, causing an EEXIST error.

Use rimraf unconditionally instead, which handles both existing files
and non-existent paths gracefully.
2026-03-15 22:43:59 +01:00
Victor Sumner
09a999af04 feat: add virtualStoreOnly option to skip post-import linking (#10965)
* feat: add virtualStoreOnly option to skip post-import linking

Adds a new `virtualStoreOnly` config option that populates the virtual
store (standard or GVS) without creating importer symlinks, hoisting,
bin links, or running lifecycle scripts.

- Config: add virtual-store-only to types, Config interface, defaults
- extendInstallOptions: validate against enableModulesDir=false, force
  ignoreScripts=true and empty hoist patterns when enabled
- headless: add skipPostImportLinking flag guarding 7 post-import steps
- core install: guard buildModules, bin linking, and lifecycle hooks
- link.ts: skip hoisting and symlink creation
- fetch command: use virtualStoreOnly internally
- CLI: wire through rcOptionsTypes and installDeps Pick type

Closes #10840

* fix: address virtualStoreOnly review comments

- Remove ignoreScripts=true forcing (allow builds with virtualStoreOnly)
- Allow virtualStoreOnly + enableModulesDir=false when GVS is enabled
- Guard linkHoistedModules with skipPostImportLinking in hoisted branch
- Un-guard buildModules so lifecycle scripts can run with virtualStoreOnly
- Split metadata block so writeModulesManifest persists with virtualStoreOnly
- Add enableModulesDir=true to pnpm fetch to avoid config conflict
- Fix test bugs: dep version 100.0.0→100.1.0, globalVirtualStoreDir→virtualStoreDir
- Add test for virtualStoreOnly + enableModulesDir=false + GVS
- Relax headless import guard to allow GVS with enableModulesDir=false

* fix: pin dep-of-pkg-with-1-dep dist-tag in virtualStoreOnly tests

The tests hardcode dep-of-pkg-with-1-dep@100.1.0 in path assertions
but didn't call addDistTag to pin the latest version. Since test files
run concurrently, other tests can change the dist-tag to 100.0.0,
causing resolution to pick a different version and the path check to
fail.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 19:59:27 +01:00
Zoltan Kochan
a61617d517 fix: add package.json to linkExePlatformBinary test fixtures (#10976)
* fix: add package.json to linkExePlatformBinary test fixtures

On Windows, linkExePlatformBinary reads @pnpm/exe/package.json to
rewrite bin.pnpm from "pnpm" to "pnpm.exe". The tests didn't create
this file, causing ENOENT on Windows. Non-Windows platforms skip this
code path so the tests passed elsewhere.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update lockfile

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 19:27:01 +01:00
Zoltan Kochan
cae7a46ecd chore: update pnpm to v11 alpha 16 2026-03-15 15:41:44 +01:00
Zoltan Kochan
10000ecb6c chore(release): 11.0.0-alpha.16 v11.0.0-alpha.16 2026-03-15 15:21:02 +01:00
Zoltan Kochan
253858d6a7 fix: resolve @pnpm/exe platform binary in symlinked node_modules layout (#10971)
When running `pnpm self-update` with `@pnpm/exe`, `linkExePlatformBinary`
looked for the platform binary (e.g. `@pnpm/macos-arm64`) at the top level
of `node_modules`. In pnpm's symlinked layout, the platform package is not
hoisted — it only exists as a sibling of `@pnpm/exe` in the virtual store.

The fix resolves through the `@pnpm/exe` symlink to find the platform
binary as a sibling, which works for both symlinked and flat layouts.
2026-03-15 15:18:46 +01:00
Zoltan Kochan
57101e105c chore(release): 11.0.0-alpha.15 v11.0.0-alpha.15 2026-03-15 14:02:55 +01:00
Zoltan Kochan
58429f9ba0 fix: resolve config dependencies from pnpm-workspace.yaml during install (#10969)
Previously, config dependencies could only be installed via `pnpm add --config`.
If a user manually added config deps to pnpm-workspace.yaml or deleted
pnpm-lock.env.yaml, `pnpm install` would fail because the resolution step
(fetching integrity from the registry) was missing.

Add `resolveAndInstallConfigDeps` which checks the env lockfile for missing
entries and resolves them from the npm registry before installing. This enables
two new workflows:
1. Manually adding config deps to pnpm-workspace.yaml
2. Deleting pnpm-lock.env.yaml and having `pnpm install` recreate it
2026-03-15 12:31:37 +01:00
Zoltan Kochan
31858c544b refactor: merge env lockfile into pnpm-lock.yaml (#10964)
Instead of a separate pnpm-lock.env.yaml file, the env lockfile
(configDependencies and packageManagerDependencies) is now stored as
the first YAML document in pnpm-lock.yaml, separated by `---`.

The combined file starts with `---\n` when an env document is present,
allowing pnpm to check just the first 4 bytes to know whether
the file contains an env document. Reading uses streaming I/O that
stops as soon as the document separator is found, avoiding parsing
of the full lockfile.

Writing preserves both documents: when the env lockfile is updated
the main lockfile portion is kept, and vice versa.
2026-03-15 01:44:20 +01:00
Zoltan Kochan
da2429d354 fix: use devEngines.runtime node version for engine checks (#10954)
When devEngines.runtime (or engines.runtime) specifies a Node.js version
with onFail: "download", use that version for engine strictness checks
instead of the system Node.js version.

close #10033
2026-03-14 20:00:40 +01:00
Zoltan Kochan
784cdcd419 ci: only run Windows tests with lowest Node.js on branches (#10962)
On non-main branches, run Windows tests only with Node.js 22.13.0
(the lowest supported version). The full Windows matrix still runs
on main.
2026-03-13 22:42:39 +01:00
Zoltan Kochan
226376eff5 ci: update pnpm/action-setup to v4.4 2026-03-13 21:25:26 +01:00
Zoltan Kochan
9931621152 ci: run Linux/Node 24 tests first, then the rest of the matrix (#10960)
* ci: run Linux/Node 24 tests first, then the rest of the matrix

Run tests on ubuntu-latest / Node.js 24 as a smoke test first.
The remaining 5 matrix combinations only start if it passes,
saving CI resources on failing PRs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(ci): extract test steps into reusable workflow

Reduces duplication by moving all test steps into test.yml as a
reusable workflow. ci.yml now calls it twice: once for the smoke
test (Linux/Node 24) and once for the remaining matrix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(ci): remove redundant if conditions from dependent jobs

The if condition only needs to be on compile-and-lint. Downstream
jobs are automatically skipped when their needs are skipped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(ci): clean up check names for reusable workflow

Drop redundant "Test" prefix from caller job names since the
reusable workflow job key "test" is automatically appended by
GitHub, e.g. "CI / ubuntu-latest / Node.js 24 / test".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(ci): capitalize Test in reusable workflow job name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:18:24 +01:00
Ben Scholzen
2fc913969b fix: correctly identify workspace packages in all operations (#10575)
* fix: correctly identify workspace packages in all operations

* fix: use Set for workspacePackages lookup and add uninstallSome test

Use Set<string> instead of string[] for workspacePackages in
dedupeInjectedDeps for O(1) lookups. Add test covering pnpm rm
(uninstallSome) to directly reproduce the scenario from #9518.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: rename workspacePackages to workspaceProjectIds and add defensive guard

Address Copilot review comments:
- Rename `workspacePackages` to `workspaceProjectIds` to avoid confusion
  with the `WorkspacePackages` type used elsewhere in the codebase.
- Add a defensive guard in `getDedupeMap` to skip deps whose target
  project is not in `dependenciesByProjectId`, preventing a potential
  runtime error if the function is called with a partial project set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use allProjectIds from ctx.projects instead of wantedLockfile.importers

wantedLockfile.importers may not always contain all workspace projects
(e.g. when pruneLockfileImporters is true during subset operations).
Pass allProjectIds explicitly from ctx.projects, which is the
authoritative source for all workspace project IDs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: make allProjectIds a required field

All callers of resolveDependencies now explicitly pass allProjectIds
rather than falling back to wantedLockfile.importers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: rewrite test to actually reproduce the bug from #9518

The previous tests used mutateModules with all projects in allProjects,
which caused installInContext to expand the projects list — hiding the
bug. The real bug occurs when mutateModulesInSingleProject is used
(as pnpm rm does from a single package directory), where allProjects
contains only the operated-on package.

The new test uses mutateModulesInSingleProject for the removal step,
matching the actual pnpm rm code path. It correctly fails without the
fix (receives "file:b" instead of "link:../b") and passes with it.

Also fixes the workspaceProjectIds source to merge both allProjectIds
and wantedLockfile.importers, since in single-project operations
allProjectIds only has one project while the lockfile has all of them.

Refines the defensive guard in getDedupeMap to allow deduplication when
the target project has no children (empty set is always a subset).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: make workspaceProjectIds required in resolvePeers

Remove the optional marker and empty-set fallback. All callers now
provide this explicitly, and test call sites pass new Set().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 17:04:11 +01:00
Varun Chawla
3417386cb7 fix(outdated): handle NO_MATCHING_VERSION when minimumReleaseAge is set (#10618)
* fix(outdated): handle NO_MATCHING_VERSION when minimumReleaseAge is set

When minimumReleaseAge filters out all versions of a package (including
the one the "latest" dist-tag points to), the resolver throws
NO_MATCHING_VERSION instead of NO_MATURE_MATCHING_VERSION. The
getManifest function in outdated only caught the latter, causing
`pnpm outdated` to crash.

Now both error codes are caught when publishedBy is set, so outdated
gracefully skips packages with no mature versions.

Fixes #10605

* test(outdated): remove redundant getManifest test

The 'handles NO_MATCHING_VERSION error gracefully' test was misleadingly
named (it actually threw ERR_PNPM_NO_MATURE_MATCHING_VERSION) and
duplicated the existing 'with minimumReleaseAge filters latest when too
new' test. It also passed without the fix, so it wasn't verifying the
actual bug.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:41:24 +00:00
Ryan Johnson
353bc16b42 fix: pnpm list --only-projects regression (fixes #10651) (#10892)
- Fall back to wanted lockfile when current lockfile is missing so list works
  without node_modules (e.g. workspace-with-nested-workspace-deps fixture).
- Pass onlyProjects from CLI opts (cliOptions['only-projects']) into list render.
- In buildDependencyGraph, when onlyProjects is true only add edges to workspace
  importers so the graph is restricted to workspace projects.
- Normalize ref from lockfile (support inline { version, specifier } format).
2026-03-13 14:42:43 +00:00
Zoltan Kochan
76be86dcb5 chore: add script to clean up worktrees with merged PRs (#10953)
* chore: add script to clean up worktrees with merged PRs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use safe arithmetic to avoid set -e exit on zero increment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:48:35 +01:00
Zoltan Kochan
251f8a3cfc chore: set up remote tracking for fork PRs in worktree helper (#10952)
When creating a worktree from a PR number, use `gh pr view` to get the
fork owner/repo and branch name, add the fork as a remote, and set the
upstream tracking branch. This makes `git push` work out of the box for
PRs from forks, matching the behavior of `gh pr checkout`.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:13:35 +01:00
nozaq
d458ab318c fix: incorrect depPath format used in time pruning (#10907)
* fix: depPath format used in time pruning

The local `refToRelative` helper in `lockfileFormatConverters.ts` produced
dependency paths with a leading slash (e.g. `/foo@1.0.0`), while the keys
stored in the `time` field do not have one (e.g. `foo@1.0.0`).

Because of this mismatch, `rootDepPaths.has(depPath)` always returned false
inside `pruneTimeInLockfile`, so `pickBy` filtered out every entry and the
entire `time` field was cleared on every install.

Fix by replacing the local helper with `refToRelative` from
`@pnpm/dependency-path`, which produces the correct format.

* chore: add pnpm to changeset

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:01:08 +01:00
zybo
61f94906ea fix: handle verifyDepsBeforeRun prompt in non-TTY environments (#10903)
* fix: handle verifyDepsBeforeRun prompt in non-TTY environments

In non-interactive environments like CI, verifyDepsBeforeRun: 'prompt' would
silently exit with code 0 even when node_modules were out of sync. This could
cause tests to pass when they should fail.

Now, pnpm throws an error in non-TTY environments, alerting users that they
need to run 'pnpm install' first.

Also handles Ctrl+C gracefully during the prompt - exits cleanly without
showing a stack trace.

Fixes #10889
Fixes #10888

* fix: improve Ctrl+C handling and fix prompt TTY guard

- Replace brittle ERR_USE_AFTER_CLOSE check with generic catch for prompt
  cancellation (enquirer rejects with empty string on Ctrl+C, not that error)
- Fix prompt test to mock isTTY=true since Jest runs in non-TTY environment
- Fix test description "noTTY" → "non-TTY"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: narrow try/catch to only wrap enquirer.prompt

Avoid catching errors from install() which should propagate normally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: zubeyralmaho <zubeyralmaho@users.noreply.github.com>
Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:00:12 +01:00
Zoltan Kochan
5d5818e44f style: enforce node: protocol for builtin imports (#10951)
Add n/prefer-node-protocol rule and autofix all bare builtin imports
to use the node: prefix. Simplify the simple-import-sort builtins
pattern to just ^node: since all imports now use the prefix.
2026-03-13 07:59:51 +01:00
Zoltan Kochan
1c8c4e49f5 style: add eslint-plugin-simple-import-sort (#10947)
Add eslint-plugin-simple-import-sort to enforce consistent import ordering:
- Node.js builtins first
- External packages second
- Relative imports last
- Named imports sorted alphabetically within each statement
2026-03-13 02:02:38 +01:00
Dami Oyeniyi
61cad0cdbc fix: treat HTTP 400 responses as errors in npm resolver fetch (#10945) 2026-03-12 22:40:32 +01:00
Zoltan Kochan
0e7ef2bb6e fix: detect global bin conflicts between pnpm and @pnpm/exe (#10929)
Both `pnpm` and `@pnpm/exe` packages legitimately own the `pnpm` and
`pnpx` bins. Previously, installing one while the other was already
globally installed would silently skip the bin or allow an override.
Now both are recognized as owners via BIN_OWNER_OVERRIDES, and when
both the new and existing packages own a bin, a GLOBAL_BIN_CONFLICT
error is raised instead of silently proceeding.
2026-03-12 22:39:15 +01:00
Allan Kimmer Jensen
99b07f5237 fix(sbom): suppress reporter to prevent warnings from polluting stdout (#10924)
sbom always outputs JSON to stdout, but the pnpm log reporter could
write warnings (e.g. engine mismatch) to stdout before the JSON,
breaking parsers and piping to files.

Refs: #10592
close #10923
2026-03-12 22:18:26 +01:00
Jason Paulos
15549a9445 feat(audit): add fix update mode (#10341)
* feat(audit): add fix update mode

Add the ability to fix vulnerabilities by updating packages in the
lockfile instead of adding overrides.

* revert: remove audit-registry parameter

* fix: properly invoke audit command recursively on workspace

* fix: negative weight version priority & top-level pinned dep updating

* refactor: apply packageVulnerabilityAudit version preferences earlier

* chore: update changeset

* fix: vulnerability penalties are greater than direct dep weight

* test: use nock on mock registry directly

* fix: exit with 1 if it can't resolve all vulnerabilities to match npm

* fix: properly update workspace top-level pinned vulnerable dependencies

* fix: update lockfile

* fix: update vulnerabilities in catalogs

* chore: sync pnpm-lock.yaml with main
2026-03-12 21:42:49 +01:00
Jason Paulos
6fcf5bafbd test: fix another isRepoPublic flaky test (#10941) 2026-03-12 21:15:47 +01:00
Zoltan Kochan
62f760ec3d fix(dlx): fix race conditions in parallel dlx calls sharing Global Virtual Store (#10939)
## Summary

Fixes intermittent failures in the `parallel dlx calls of the same package` test, especially on Windows CI. Multiple race conditions were discovered when concurrent `pnpm dlx` processes share the same Global Virtual Store (GVS):

- **Content-verified skip in GVS mode**: When `safeToSkip` is true and a rename fails because the target already exists (ENOTEMPTY/EEXIST/EPERM), verify all files match (inode or content comparison) before skipping. Falls through to `renameOverwriteSync` if content doesn't match.
- **Tolerate EPERM during bin creation on Windows**: `cmd-shim`'s `chmod` can fail with EPERM when another process holds the `.bin` file. Warn instead of crashing.
- **Handle EPERM in DLX cache symlink**: Added EPERM to the list of tolerated errors when creating the DLX cache symlink, as Windows can throw this when another process has the symlink open.

## Test plan

- [x] `parallel dlx calls of the same package` test passes on Windows CI
- [x] Full test suite passes on both Ubuntu and Windows
2026-03-12 21:06:32 +01:00
Zoltan Kochan
39afb24ce6 chore: add worktree helper script and shell functions (#10938)
Adds a `pnpm worktree:new <branch>` script that creates a git worktree
as a sibling directory of the repo root, with branch slashes replaced by
dashes (e.g. `feat/foo` → `../feat-foo`). Shell helpers in `shell/wt.fish`
and `shell/wt.sh` wrap the script to also `cd` into the new worktree.
Documents setup and usage in CONTRIBUTING.md.
2026-03-11 22:59:42 +01:00
Zoltan Kochan
edbe1bcbf9 chore: add Husky hooks to prevent Claude Code from bad git practices (#10937)
- Adds two Husky hooks to prevent Claude Code from bad git practices:
  - \`prepare-commit-msg\`: blocks \`git commit --amend\` (detected via the \`commit\` source argument)
  - \`pre-commit\`: blocks committing directly to \`main\`
- Both hooks detect Claude Code sessions via the \`CLAUDECODE\` environment variable, so regular users are unaffected
- Error messages explicitly tell Claude what to do instead
2026-03-11 20:28:25 +01:00
Zoltan Kochan
178f2210e3 fix: don't run pnpm install in the fixture dir, use a temp copy instead (#10936) 2026-03-11 20:09:57 +01:00
Zoltan Kochan
0fda5eaf0b fix: skip entries that disappear between readdirSync and lstatSync on Windows CI
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 19:41:40 +01:00
Zoltan Kochan
bb177242df feat: support devEngines.packageManager for pnpm version management (#10932)
## Summary

- Support specifying the pnpm version via `devEngines.packageManager` in `package.json`, as an alternative to the `packageManager` field
- Unlike `packageManager`, `devEngines.packageManager` supports semver ranges — the resolved version is stored in `pnpm-lock.env.yaml` and reused if it still satisfies the range
- The `onFail` field determines behavior: `download` (auto-download), `error` (default), `warn`, or `ignore`
- `devEngines.packageManager` takes precedence over `packageManager` when both are present (with a warning)
- For array notation, default `onFail` is `ignore` for non-last elements and `error` for the last
- For the legacy `packageManager` field, `onFail` is derived from existing config settings (`managePackageManagerVersions`, `packageManagerStrict`, `packageManagerStrictVersion`), so `main.ts` uses `onFail` as the single source of truth
- Reuses `EngineDependency` type from `@pnpm/types` instead of a custom `WantedPackageManager` type

## Test plan

- [x] 10 tests in `switchingVersions.test.ts` — version switching with `packageManager` field, `devEngines.packageManager` with `onFail=download` (exact + range), env lockfile reuse, corrupt binary
- [x] 15 tests in `packageManagerCheck.test.ts` — version checks with `engines.pnpm`, `packageManager` field, `devEngines.packageManager` with all `onFail` values, array notation, range matching, precedence

close https://github.com/pnpm/pnpm/issues/8153
2026-03-11 18:49:09 +01:00
Zoltan Kochan
6d56db2aad feat(audit): audit dependencies from pnpm-lock.env.yaml (#10933)
The `pnpm audit` command now also audits dependencies from
`pnpm-lock.env.yaml`, including `configDependencies` and
`packageManagerDependencies` along with their transitive dependencies.

They appear as separate groups in the audit tree so that vulnerability
paths clearly indicate their origin (e.g. configDependencies>pkg>...).
2026-03-11 18:48:16 +01:00
Zoltan Kochan
3a5bfaa94f chore: update zkochan packages to latest versions (#10930)
Update all packages from zkochan/packages to their latest major versions
and exclude them from minimumReleaseAge requirement. This includes
updating catalog entries, adapting to breaking API changes (default
exports replaced with named exports, sync functions renamed with Sync
suffix), and updating type declarations.
2026-03-11 13:47:46 +01:00
Zoltan Kochan
56b065dd47 chore: update pnpm-lock.yaml (#10905) 2026-03-11 08:53:47 +01:00
Zoltan Kochan
6470c17172 chore: update pnpm to v11 alpha 14 2026-03-11 01:17:27 +01:00
Zoltan Kochan
4b4a7f5bce chore(release): 11.0.0-alpha.14 v11.0.0-alpha.14 2026-03-11 01:09:05 +01:00
Zoltan Kochan
a8f016ca59 feat: store config deps and package manager integrities in pnpm-lock.env.yaml (#10912)
## Summary

Store config dependency and package manager integrity info in a separate `pnpm-lock.env.yaml` lockfile instead of inlining it in `pnpm-workspace.yaml`. The workspace manifest now contains only clean version specifiers for `configDependencies`, while the resolved versions, integrity hashes, and tarball URLs are recorded in the new env lockfile.

### Key changes

- **New `pnpm-lock.env.yaml` lockfile**: Uses the standard lockfile format (`importers`, `packages`, `snapshots`) to store resolved config dependencies and package manager dependencies with integrity hashes and tarball URLs.
- **Automatic migration**: Projects using the old inline-hash format in `pnpm-workspace.yaml` are automatically migrated on install.
- **Global Virtual Store (GVS) for version switching**: When switching pnpm versions via the `packageManager` field, pnpm is installed to the global virtual store (`$STORE_DIR/links/`) instead of `globalPkgDir`, reusing the content-addressable store for deduplication.
- **Self-update uses headless install**: `pnpm self-update` performs frozen headless installs using integrity hashes from the env lockfile, then links bins to `PNPM_HOME`.
- **`packageManagerDependencies`**: The env lockfile also stores resolved `packageManagerDependencies` during version switching and self-update.
- **`@pnpm/exe` support**: Replicates `@pnpm/exe`'s postinstall script (linking platform-specific binaries) since install scripts are disabled.
- **`pnpm setup` refactored**: Uses `pnpm add -g` instead of copying the CLI binary directly.
- **Extracted `toLockfileResolution`** to `@pnpm/lockfile.utils` and **deduplicated `iteratePkgMeta`** into `@pnpm/calc-dep-state`.
- **Removed unused `@pnpm/tools.path` package**.
2026-03-11 00:39:37 +01:00
Zoltan Kochan
2b68ae123b chore: add --provenance to publish commands in release script 2026-03-09 23:12:12 +01:00
Rohan Santhosh
78c2faabec docs: fix after-install warning typo (#10919)
Co-authored-by: rohan436 <rohan.santhoshkumar@googlemail.com>
2026-03-09 10:56:33 +01:00
Zoltan Kochan
2fccb03fbe refactor: consolidate build-related packages into building/ domain (#10918)
* refactor: rename rebuildSelectedPkgs/rebuildProjects to buildSelectedPkgs/buildProjects

The "rebuild" prefix is redundant now that these functions live in
@pnpm/building.after-install.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename Rebuild option types to Build (RebuildOptions → BuildOptions, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename plugin-commands-rebuild and exec.build-commands to building domain

- @pnpm/plugin-commands-rebuild → @pnpm/building.build-commands
- @pnpm/exec.build-commands → @pnpm/building.policy-commands

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: move build-modules and pkg-requires-build to building domain

- @pnpm/build-modules → @pnpm/building.during-install
- @pnpm/exec.pkg-requires-build → @pnpm/building.pkg-requires-build

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: alphabetically sort imports after package renames

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add changeset

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:56:13 +01:00
Zoltan Kochan
7354e6bb19 refactor: extract rebuild implementation into @pnpm/building.after-install (#10916)
* refactor: extract rebuild implementation into @pnpm/building.after-install

Move the rebuild implementation (rebuildProjects, rebuildSelectedPkgs)
from @pnpm/plugin-commands-rebuild into a new @pnpm/building.after-install
package. This breaks the circular dependency chain:
config/deps-installer → core → plugin-commands-rebuild → cli-utils → config/deps-installer

The CLI command layer stays in plugin-commands-rebuild, while the core
rebuild logic now lives in building/after-install with no dependency
on cli-utils.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add README for @pnpm/building.after-install

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename @pnpm/builder.policy to @pnpm/building.policy

Move builder/policy to building/policy, consolidating all build-related
packages under the building/ domain. Update all consumers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add changeset

* refactor: remove old implementation files from plugin-commands-rebuild

These files were copied to @pnpm/building.after-install but not removed
from the original location.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: remove unused deps from plugin-commands-rebuild

Dependencies that were only needed by the implementation (now in
@pnpm/building.after-install) are removed. Deps used only in tests
are moved to devDependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:20:47 +01:00