[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
With Rush subspaces enabled, the pnpm locks and the repo-state files that carry pnpmShrinkwrapHash both live per subspace, at common/config/subspaces/<name>/{pnpm-lock.yaml,repo-state.json}. scan --mode hosted correctly rewrites the subspace locks (docs: "subspaces included"). But the redirect_rush_repo_state_stale warning only checks for common/config/rush/repo-state.json (RUSH_REPO_STATE_REL), which doesn't exist in a subspace repo. So the warning never fires. With preventManualShrinkwrapChanges: true, the next rush install fails with "The shrinkwrap file hash does not match the expected hash", and the scan output gave no hint.
The non-subspace layout with the same setting emits the warning (control below). The documented recovery works in the subspace layout too: after rush update the hosted pins survive, and rush install installs the patched bytes. Only the warning is missing.
Impact
Low/medium. Nothing is mis-patched and nothing silently reverts. But in a Rush monorepo that uses subspaces and the (commonly enabled) preventManualShrinkwrapChanges, the hosted rewrite breaks CI's rush install, and the one warning meant to explain why is missing.
Repro (Linux, Node 22, Rush 5.180.0, local patch-API mock serving left-pad@1.3.0 / is-number@7.0.0 patches)
rush init
# rush.json: pnpmVersion 10.34.5; projects app (default subspace) -> left-pad@1.3.0, tool (subspaceName "tools") -> is-number@7.0.0
# subspaces.json: subspacesEnabled true, subspaceNames ["default","tools"]; mkdir common/config/subspaces/{default,tools}; rm common/config/rush/.pnpmfile.cjs
# pnpm-config.json: "preventManualShrinkwrapChanges": true
rush update && git add -A && git commit -qm init
socket-patch scan --mode hosted $API --json
# status success, redirected 2, rewrittenFiles [common/config/subspaces/default/pnpm-lock.yaml, common/config/subspaces/tools/pnpm-lock.yaml]
# warnings: ['redirect_pnpm_trust_lockfile'] <- no redirect_rush_repo_state_stale
git commit -qam pin && git clone -q . ../fresh && cd ../fresh && rush install
# "The shrinkwrap file hash does not match the expected hash. Please run "rush update" ..." (exit 1)
Expected vs actual
- Expected (docs/ecosystems.md, "npm: Rush monorepos"): editing a Rush lock outside
rush update desyncs pnpmShrinkwrapHash, and "a redirect_rush_repo_state_stale warning flags this". The engine comment at crates/socket-patch-core/src/hosted/engine.rs:922-928 says to warn "when the rewrite actually landed in a Rush lock and the repo-state file that carries the hash is present". In a subspace repo that file is common/config/subspaces/<name>/repo-state.json, and it is present.
- Actual: no warning. The scan reports a clean success.
Matrix (Linux, main 045d7ec, each run twice from scratch)
| Layout |
pnpm |
redirect_rush_repo_state_stale |
rush install (clean clone) |
| subspaces (default + tools) |
9.15.9 |
missing |
fails: shrinkwrap hash mismatch |
| subspaces (default + tools) |
10.34.5 |
missing |
fails: shrinkwrap hash mismatch |
| no subspaces (control) |
10.34.5 |
emitted |
(expected failure, warned) |
subspaces, after rush update |
10.34.5 |
n/a |
pass, both packages patched |
macOS / Windows not tested (path logic only).
Suspect code
crates/socket-patch-core/src/hosted/engine.rs:761-769: rush_repo_state_present checks only RUSH_REPO_STATE_REL (common/config/rush/repo-state.json). It should also check the repo-state.json next to each rewritten subspace lock (common/config/subspaces/<name>/repo-state.json).
crates/socket-patch-core/src/hosted/engine.rs:930-944: the warning gate.
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
With Rush subspaces enabled, the pnpm locks and the repo-state files that carry
pnpmShrinkwrapHashboth live per subspace, atcommon/config/subspaces/<name>/{pnpm-lock.yaml,repo-state.json}.scan --mode hostedcorrectly rewrites the subspace locks (docs: "subspaces included"). But theredirect_rush_repo_state_stalewarning only checks forcommon/config/rush/repo-state.json(RUSH_REPO_STATE_REL), which doesn't exist in a subspace repo. So the warning never fires. WithpreventManualShrinkwrapChanges: true, the nextrush installfails with "The shrinkwrap file hash does not match the expected hash", and the scan output gave no hint.The non-subspace layout with the same setting emits the warning (control below). The documented recovery works in the subspace layout too: after
rush updatethe hosted pins survive, andrush installinstalls the patched bytes. Only the warning is missing.Impact
Low/medium. Nothing is mis-patched and nothing silently reverts. But in a Rush monorepo that uses subspaces and the (commonly enabled)
preventManualShrinkwrapChanges, the hosted rewrite breaks CI'srush install, and the one warning meant to explain why is missing.Repro (Linux, Node 22, Rush 5.180.0, local patch-API mock serving
left-pad@1.3.0/is-number@7.0.0patches)Expected vs actual
rush updatedesyncspnpmShrinkwrapHash, and "aredirect_rush_repo_state_stalewarning flags this". The engine comment atcrates/socket-patch-core/src/hosted/engine.rs:922-928says to warn "when the rewrite actually landed in a Rush lock and the repo-state file that carries the hash is present". In a subspace repo that file iscommon/config/subspaces/<name>/repo-state.json, and it is present.Matrix (Linux, main
045d7ec, each run twice from scratch)redirect_rush_repo_state_stalerush install(clean clone)rush updatemacOS / Windows not tested (path logic only).
Suspect code
crates/socket-patch-core/src/hosted/engine.rs:761-769:rush_repo_state_presentchecks onlyRUSH_REPO_STATE_REL(common/config/rush/repo-state.json). It should also check therepo-state.jsonnext to each rewritten subspace lock (common/config/subspaces/<name>/repo-state.json).crates/socket-patch-core/src/hosted/engine.rs:930-944: the warning gate.