Skip to content

Fix pnpm env settings read across majors (#1460) - #1461

Merged
Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
agent/fix-pnpm-env-setting-major
Oct 13, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
agent/fix-pnpm-env-setting-major

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1460

Summary

Hosted pnpm mode refused to pin a lock over environment settings the project's pnpm never reads. The common trigger is npx socket-patch scan --mode hosted in a pnpm 11/12 project whose .npmrc still has an npm-era package-lock=false. npx exports npm_config_package_lock=, and pnpm 12 ignores it and installs from the lock. The scan still warned redirect_pnpm_lockfile_disabled, pinned nothing, and exited 0 with status: success.

Root cause

env_setting (crates/socket-patch-core/src/utils/pnpm_workspace.rs) looked up pnpm_config_<key> and then npm_config_<key> on every pnpm major. Real pnpm reads one family per major: npm_config_* on pnpm 10 and older, pnpm_config_* on pnpm 11 and newer (empirical table in #1460). This affected three settings:

  • lockfile / package-lock (lockfile_disabled): false redirect_pnpm_lockfile_disabled
  • git-branch-lockfile (view_setting via git_branch_locks, used by both hosted and vendored): false redirect_pnpm_git_branch_lockfile / vendor_pnpm_git_branch_lockfile
  • shared-workspace-lockfile (view_setting via workspace_members): member locks routed by a variable pnpm ignores

Fix

env_setting takes the pnpm major, the same pnpm_major that already chooses pnpm-workspace.yaml vs .npmrc. It reads pnpm_config_* for 11+, npm_config_* for 10 and older, and both when the major is unknown (the safe side, same as the file rule). view_setting is now async and passes the major down. The major is only computed when a candidate variable is actually set, so scans with no such variable don't re-read the lock. CLI_CONTRACT.md now describes the per-major family for all three settings.

Tests (red → green)

Issue Test Without fix With fix
#1460 (issue repro: pnpm 12 + npm_config_package_lock=, plus npm_config_lockfile on 11/12, pnpm_config_lockfile on 9/10, npm_config_git_branch_lockfile on 12, pnpm_config_git_branch_lockfile on 10; controls refuse in the family the major reads) in_process_redirect_pnpm::hosted_scan_reads_pnpm_env_settings_for_the_project_pnpm_major (spawns the CLI with the env set) FAILED: pnpm@12.11.2 npm_config_package_lock=: pin count 0, expected 1 ok
#1460 (lock setting per major, every cell of the issue's table) pnpm_workspace::tests::the_environment_disables_the_lockfile_only_for_its_pnpm_major n/a (new seam) ok
#1460 (family selection, incl. git-branch on pnpm 10) pnpm_workspace::tests::the_environment_family_follows_the_pnpm_major n/a (new signature) ok

Local runs:

  • cargo fmt --all -- --check: ok
  • cargo clippy --workspace --all-features -- -D warnings: ok
  • cargo test -p socket-patch-core --all-features --lib: 6409 passed. The 4 failures (copy_tree symlink relax, vlt_heal unremovable lock, pypi_poetry/pypi_requirements write-failure) depend on chmod and fail only because the sandbox runs as root. None touch pnpm.
  • cargo test -p socket-patch-cli --all-features --test in_process_redirect_pnpm --test in_process_vendor_pnpm_takeover --test hosted_memory_parity: 33 + 15 + 42 passed
  • The full cargo test --workspace ran out of sandbox disk while linking ~100 CLI test binaries, so CI is the full run.

No wrapper (npm/, pypi/, gem/) changes are needed: this logic lives only in the Rust core.

/code-review high: findings not fixed

🤖 Generated with Claude Code

https://claude.ai/code/session_01E552fKgtx93unKJDowBuF4


Note

Medium Risk
Changes when hosted/vendored pnpm runs refuse vs pin based on CI/npx-injected env vars; behavior now matches real pnpm but could differ from prior overly conservative refusals.

Overview
Fixes #1460: hosted pnpm mode no longer treats npm-era environment variables (npm_config_*) as disabling the lockfile or enabling git-branch locks on pnpm 11+, which only honor pnpm_config_* (pnpm ≤10 still use npm_config_*).

env_setting in pnpm_workspace.rs now picks the env var family from the project’s pnpm major (same sources as existing file-based rules). That affects lockfile_disabled, git_branch_locks, and sharedWorkspaceLockfile env fallbacks via async view_setting. The major is resolved only when a relevant env var is set. CLI_CONTRACT.md documents the per-major behavior.

Adds integration test hosted_scan_reads_pnpm_env_settings_for_the_project_pnpm_major (e.g. npm_config_package_lock= from npx on pnpm 12 no longer blocks pinning) and unit tests for the env-family matrix.

Reviewed by Cursor Bugbot for commit c782837. Configure here.


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
Hosted pnpm refused to pin a lock over environment settings the
project's pnpm never reads. pnpm 10 and older read only npm_config_*
variables and pnpm 11 and newer only pnpm_config_*, but socket-patch
accepted both families on every major.

The common trigger: `npx socket-patch scan --mode hosted` in a pnpm
11/12 project whose .npmrc still has an npm-era package-lock=false.
npx exports npm_config_package_lock=, pnpm 12 ignores it and installs
from the lock, yet the scan warned redirect_pnpm_lockfile_disabled
and pinned nothing. The same blindness made gitBranchLockfile and
sharedWorkspaceLockfile env lookups refuse or mis-route.

The environment is now read in the family the project's pnpm major
reads (the same major that already picks pnpm-workspace.yaml vs
.npmrc), and in both families only when the major is unknown.

Fixes #1460

Assisted-by: Claude Code:claude-opus-5-5
Hosted pnpm scans now look the pnpm major up for the environment
fallback only when one of the candidate variables is actually set, so
a project with no such variable does not re-read its lock. Also
documents the per-major family for sharedWorkspaceLockfile and folds
the duplicated test helpers.

Refs #1460

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 13, 2026 02:01
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit c782837. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 13, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Ready for review at c782837d531ea7f72923dc0616220b13357c81f6.

  • CI: all green on this head (36 pass + 50 skipped), no failures.
  • Bugbot: reviewed c782837, no new issues; no unresolved review threads.
  • Mergeable, no CHANGELOG.md changes.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Final review brief

What it does: pnpm reads one family of environment variables per major: npm_config_* on 10 and older, pnpm_config_* on 11 and newer. Until now socket-patch honoured both on every major. So npx socket-patch scan --mode hosted in a pnpm 11/12 project with an npm-era package-lock=false falsely refused to pin, because npx exports npm_config_package_lock= and pnpm 11+ ignores it. env_setting now picks the family from the project's pnpm major, and reads both when the major is unknown. This covers lockfile/package-lock, git-branch-lockfile and shared-workspace-lockfile. Fixes #1460.

Risk: low to medium. The code is small and correct. For a known major, though, it moves from refusing to pinning, so it relies on the per-major claim. That claim is backed by the measured table in #1460 for pnpm 9.15.9, 10.34.6, 11.28.3 and 12.11.2, and the tests encode every cell of it. It also trusts pnpm_major, the same major the settings-file path already trusts.

Look here:

  • pnpm_workspace.rs:134: env_setting chooses the family by major.
  • pnpm_workspace.rs:162: view_setting is now async and resolves the major only when some candidate variable is set.
  • pnpm_workspace.rs:636: lockfile_disabled_in. The file verdict still wins and env is the fallback.
  • in_process_redirect_pnpm.rs:2474:`` CLI-spawning matrix, including the issue repro (pnpm 12 + npm_config_package_lock=).

Verified:

  • Read the full diff and CLI_CONTRACT.md.
  • Unknown major falls back to the old read-both behaviour. Memory views still skip env. File-vs-env precedence is unchanged.
  • The new test helper strips inherited npm_config_*/pnpm_config_* lock variables.
  • Ran cargo test -p socket-patch-core --lib pnpm_workspace locally on c782837: 20/20 pass.
  • CI on c782837: 36 success, 50 skipped of 86; ci-ok and clippy green. Cursor Bugbot passed. No unresolved review threads. CHANGELOG.md untouched.

Changes I made: none.

Open questions (non-blocking):

  • Workspace members. pnpm_major reads the member's own files, but packageManager and .modules.yaml usually live at the workspace root. So a member scanned alone usually has an unknown major and keeps the old read-both refusal. That errs on the safe side, and the PR body names it as a follow-up.
  • Upper-case names. On Unix, upper-case NPM_CONFIG_* is still missed, though npm/pnpm 10 match the prefix case-insensitively. This predates the PR and is worth a follow-up issue.
  • Stale comment. The lockfile_disabled doc comment ("withholding a pin is the safe side") now holds only for an unknown major.

Auto-merge (squash) is armed, so approving sends it straight to the merge queue.


Generated by Claude Code

Merged via the queue into main with commit 6ce0939 Oct 13, 2026
86 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/fix-pnpm-env-setting-major branch October 13, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

3 participants