Skip to content

Commit 33cd86e

Browse files
committed
pnpm bug-hunt run 2026-10-01
1 parent 5d39b6c commit 33cd86e

2 files changed

Lines changed: 59 additions & 21 deletions

File tree

‎entries/pnpm/20261001T003559Z.md‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[agent] 2026-10-01: pnpm bug-hunt run
2+
3+
**Tested:** main `f6b7fb9` (unchanged since run 1), latest release 4.0.0 (npm `@socketsecurity/socket-patch@4.0.0`, used for the regression checks). pnpm 7.33.7, 8.15.9, 9.15.9, 10.34.5, 11.27.0 and 12.8.1, on Node 22 in the Linux sandbox. Hosted mode ran against a local Python mock of the patch API and tarball routes, modelled on `e2e_redirect_pnpm_build.rs`. Vendored mode ran from a hand-staged `.socket/manifest.json` plus blobs. The oracle is a marker on `left-pad/index.js` after a fresh `--frozen-lockfile` install against a dead registry.
4+
5+
### Re-triage
6+
- #360, #361 and #362 are still open. Main hasn't moved, so there's no fix to verify. #362 has draft PR #365 (the custom `virtualStoreDir` half; the global-virtual-store half stays open per the maintainer note). Nothing to close.
7+
8+
### Cells
9+
- **fail #400**: a whole-document flow `pnpm-workspace.yaml` (`{packages: [.]}`), or one ending in `...`. The hosted `trustLockfile: true` append and the vendored `overrides:` append both write YAML pnpm can't load, and both report success. Hosted fails on 10.34.5, 11.27.0 and 12.8.1; vendored fails on 11.27.0 and 12.8.1. Release 4.0.0 behaves the same.
10+
- **fail #401**: hosted → vendored takeover (`vendor` and `scan --mode vendored`) on pnpm 11.27.0 and 12.8.1 leaves `trustLockfile: true` plus an orphan `redirect_pnpm_workspace_trust` ledger edit with no records. `vendor --revert` doesn't remove it either. npm's `.npmrc` gets a last-one-out unwind in the same situation. Release 4.0.0 behaves the same.
11+
- **fail #402**: a quoted or space-before-colon top-level `"trustLockfile": false`, `'trustLockfile': true`, `trustLockfile : false`, or a quoted `"overrides":`, is not recognised, so a duplicate key is appended (`duplicated mapping key`). Hosted fails on 10.34.5, 11.27.0 and 12.8.1; vendored fails on 11.27.0 and 12.8.1. Release 4.0.0 behaves the same.
12+
- pass: hosted baseline (no workspace file) on pnpm 7.33.7 (lock 5.4), 8.15.9 (lock 6.0) and 9.15.9 (lock 9.0, trust file created). The fresh frozen install is patched.
13+
- pass: hosted with a `catalog:` dependency on pnpm 9.15.9, 10.34.5, 11.27.0 and 12.8.1.
14+
- pass: the full cycle vendor → hosted takeover → vendored takeover → bare `rollback` on pnpm 11.27.0. Every fresh frozen install is patched, and the lock, `pnpm-workspace.yaml` and a tab-indented `package.json` come back byte-identical.
15+
- pass: scoped `rollback <purl>` after hosted only on pnpm 11.27.0 and 12.8.1 (2 runs each). The trust line is removed through whole-ledger replay.
16+
17+
### Issues
18+
- Filed #400, #401 and #402.
19+
20+
### False positives ruled out
21+
- A compact single-line `package.json` comes back 2-space-indented after vendor + rollback. A one-line file has no indent to detect, and an indented file round-trips byte-exactly, so this wasn't filed. It's cosmetic, and `JsonLayout` work in PR #357 is nearby.
22+
- A `scan --mode vendored` re-run that returned `status: error` after a bare `rollback` came from the fixture: rollback garbage-collected the staged blobs, and the mock doesn't serve blob content.
23+
24+
### Probe
25+
- No new probe branches. `git push --delete` of the stale `bughunt/pnpm/20260930-virtual-store` was denied by the session's permission policy, so new probe branches couldn't be cleaned up either. **A maintainer needs to delete `bughunt/pnpm/20260930-virtual-store`.**
26+
27+
### Next
28+
1. Hosted: Rush / subspace locks (`common/config/rush/pnpm-lock.yaml`) and peer-suffixed instances in a workspace with the mock harness.
29+
2. Hosted `--frozen-lockfile --offline` with a warm store that holds the upstream tarball, on pnpm 9–12. Confirm the documented warm-cache caveat and that `vex` doesn't attest unpatched bytes.
30+
3. Agent: `dependenciesMeta.injected` and `package-import-method=clone|copy`, and pnpm 1–6 legacy layouts on Node 16.
31+
4. Vendored on Windows / macOS autocrlf checkouts (needs a probe branch; blocked until probe-branch deletion is allowed).
32+
5. Re-check #400–#402 once fixes land, including both modes and pnpm 12.

‎state/pnpm.md‎

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,36 @@
11
[agent] Progress ledger for the scheduled pnpm bug-hunt routine (label pm:pnpm).
22

3-
Last updated: 2026-09-30 (run 1), main `f6b7fb9`, latest release 4.0.0 (previous 3.3.0).
3+
Last updated: 2026-10-01 (run 2), main `f6b7fb9`, latest release 4.0.0 (previous 3.3.0).
44

5-
Method: real pnpm installs with a hand-staged `.socket/manifest.json` plus blobs (agent and vendored), and a local Python mock of the patch API and hosted tarball route (hosted). The oracle is a marker prepended to `index.js`, checked through Node resolution. The repo's pinned matrix (`.github/workflows/pnpm-compatibility.yml`) already covers plain hosted and vendored installs on pnpm 1–12. This ledger tracks what it doesn't.
5+
Method: real pnpm installs. Agent and vendored modes use a hand-staged `.socket/manifest.json` plus both blobs. Hosted mode uses a local Python mock of the patch API (batch, by-package, package grant, view) and the hosted tarball route. The oracle is a marker prepended to `left-pad/index.js` after a fresh `--frozen-lockfile` install against a dead registry. The repo's pinned matrix (`.github/workflows/pnpm-compatibility.yml`) already covers plain hosted and vendored installs on pnpm 1–12. This ledger tracks what it doesn't.
66

77
## Coverage matrix
88

9-
| OS | pnpm | Agent: default `.pnpm` | Agent: global virtual store | Agent: custom virtualStoreDir | Agent: hoisted | Vendored: plain / hoisted | Vendored: user overrides in pnpm-workspace.yaml | Hosted: trustLockfile variants |
10-
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
11-
| Linux | 7.33.7 | untested | n/a | untested | untested | untested | n/a | untested |
12-
| Linux | 8.15.9 / 9.15.9 | pass | n/a | fail #362 | untested | untested | n/a | untested |
13-
| Linux | 10.0.0 | untested | n/a | untested | untested | untested | pass (10.0 ignores them) | untested |
14-
| Linux | 10.5.2 / 10.12.1 | untested | fail #361 #362 (10.12.1) | untested | untested | untested | fail #360 | untested |
15-
| Linux | 10.34.5 | pass | fail #361 #362 | fail #362 | untested | pass | fail #360 | untested |
16-
| Linux | 11.27.0 | pass | fail #361 #362 | fail #362 | pass | pass | pass | pass (CRLF, no-EOL, comment); fail on whole-flow / `...` files (unfiled, backlog 1) |
17-
| Linux | 12.8.1 | pass | fail #361 #362 | fail #362 | untested | untested | pass | untested |
18-
| macOS | 10.34.5 | pass | n/a on CI (pnpm 10 disables it) | fail #362 | untested | untested | untested | untested |
19-
| macOS | 11.27.0 / 12.8.1 | pass | fail #361 #362 | fail #362 | untested | untested | untested | untested |
20-
| Windows | 10.34.5 | pass | n/a on CI | fail #362 | untested | untested | untested | untested |
21-
| Windows | 11.27.0 / 12.8.1 | pass | fail #361 #362 | fail #362 | untested | untested | untested | untested |
9+
| OS | pnpm | Agent: default `.pnpm` | Agent: global virtual store | Agent: custom virtualStoreDir | Agent: hoisted | Vendored: plain / hoisted | Vendored: workspace-file edge shapes | Hosted: plain / catalog | Hosted: trustLockfile edge shapes | Takeover vendored ⇄ hosted |
10+
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
11+
| Linux | 7.33.7 | untested | n/a | untested | untested | untested | n/a | pass (lock 5.4) | n/a (no trust) | untested |
12+
| Linux | 8.15.9 | pass | n/a | fail #362 | untested | untested | n/a | pass (lock 6.0) | n/a (no trust) | untested |
13+
| Linux | 9.15.9 | pass | n/a | fail #362 | untested | untested | untested | pass / pass | untested | untested |
14+
| Linux | 10.0.0 | untested | n/a | untested | untested | untested | pass (10.0 ignores user overrides) | untested | untested | untested |
15+
| Linux | 10.5.2 / 10.12.1 | untested | fail #361 #362 (10.12.1) | untested | untested | untested | fail #360 | untested | untested | untested |
16+
| Linux | 10.34.5 | pass | fail #361 #362 | fail #362 | untested | pass | fail #360 | pass / pass | fail #400 #402 | untested |
17+
| Linux | 11.27.0 | pass | fail #361 #362 | fail #362 | pass | pass | fail #400 #402 | pass / pass | fail #400 #402; pass CRLF, no-EOL, comment | fail #401 (trust left); otherwise pass, byte-exact rollback |
18+
| Linux | 12.8.1 | pass | fail #361 #362 | fail #362 | untested | pass | fail #400 #402 | pass / pass | fail #400 #402 | fail #401 |
19+
| macOS | 10.34.5 | pass | n/a on CI (pnpm 10 disables it) | fail #362 | untested | untested | untested | untested | untested | untested |
20+
| macOS | 11.27.0 / 12.8.1 | pass | fail #361 #362 | fail #362 | untested | untested | untested | untested | untested | untested |
21+
| Windows | 10.34.5 | pass | n/a on CI | fail #362 | untested | untested | untested | untested | untested | untested |
22+
| Windows | 11.27.0 / 12.8.1 | pass | fail #361 #362 | fail #362 | untested | untested | untested | untested | untested | untested |
23+
24+
"Edge shapes" means a whole-document flow mapping, a `...` document end, and quoted or `key :` top-level keys.
2225

2326
## Backlog
2427

25-
0. Delete the stale probe branch `bughunt/pnpm/20260930-virtual-store`. The git proxy refused `git push --delete` in run 1, so a maintainer needs to do it.
26-
1. Whole-document flow `pnpm-workspace.yaml` (`{packages: [.]}`), or one ending in `...`: the hosted `trustLockfile: true` append (`plan_workspace_trust`, crates/socket-patch-cli/src/commands/scan/hosted.rs:386) and the vendored `overrides:` append both produce YAML pnpm can't parse, while reporting success. Reproduced on pnpm 11.27.0. Confirm on 10 and 12, then file.
27-
2. Hosted: pnpm 7/8 workspaces with catalogs, peer-suffixed instances, Rush/subspace locks, `--frozen-lockfile --offline` with a warm store (mock harness: `mock.py` in the run-1 entry's method).
28-
3. Vendored ⇄ hosted takeover on pnpm 11/12, and byte-exact rollback of `pnpm-workspace.yaml` after both edits.
29-
4. Agent: `dependenciesMeta.injected`, `package-import-method=clone|copy`, pnpm 1–6 legacy layouts (Node 16).
30-
5. Vendored on Windows and macOS (autocrlf checkouts: expect the documented `vendor_lockfile_crlf_unsupported` refusal; check that it fires and that hosted handles the same checkout).
28+
0. Delete the stale probe branch `bughunt/pnpm/20260930-virtual-store`. Run 1 failed through the git proxy, and run 2 was denied by the session permission policy, so a maintainer needs to do it. Until deletion works, new probe branches can't be cleaned up, so macOS and Windows cells are on hold.
29+
1. Hosted: Rush / subspace locks and peer-suffixed workspace instances, using the mock harness.
30+
2. Hosted `--frozen-lockfile --offline` with a warm store holding the upstream tarball, on pnpm 9–12. Check that `vex` doesn't attest unpatched installed bytes.
31+
3. Agent: `dependenciesMeta.injected`, `package-import-method=clone|copy`, and pnpm 1–6 legacy layouts (Node 16).
32+
4. Vendored on Windows and macOS (autocrlf: expect the `vendor_lockfile_crlf_unsupported` refusal; check that hosted handles the same checkout). Needs a probe branch.
33+
5. Re-verify #360–#362 (PR #365) and #400–#402 when fixes land.
3134

3235
## Known non-bugs
3336

@@ -37,4 +40,7 @@ Method: real pnpm installs with a hand-staged `.socket/manifest.json` plus blobs
3740
- Vendored refusals that are intended, loud and fail-closed: a CRLF `pnpm-lock.yaml` or `pnpm-workspace.yaml` (`vendor_lockfile_crlf_unsupported`), a BOM package.json (`vendor_pkg_json_unsupported`), an inline / flow `overrides:` mapping (`vendor_override_conflict`, unit-tested), and `patchedDependencies` on the target (`vendor_lock_entry_unsupported`; the detail wrongly says "peer-suffixed snapshot key", which is cosmetic).
3841
- Vendored `vex` attests from the committed artifact plus lock wiring even when the tree isn't installed. That's by design (CLI_CONTRACT "Manifest-less VEX").
3942
- Agent rollback needs the *before* blob in `.socket/blobs`, so fixtures must stage both blobs (`missing_blob` otherwise). VEX needs `setup.manual: ["npm"]` or a setup hook (`ecosystem_not_setup`).
43+
- A bare `rollback` garbage-collects `.socket/blobs`. A later vendored run in a mock harness that serves no blob content then fails, and that's a fixture artifact.
44+
- A compact single-line `package.json` comes back 2-space-indented after vendor + rollback. There's no indent to detect, and indented files round-trip byte-exactly, so it's cosmetic.
45+
- Scoped `rollback <purl>` of the only hosted purl removes `trustLockfile` correctly (whole-ledger replay). The leftover in #401 is specific to the vendored takeover.
4046
- A `vex --output /dev/stdout` hang when stdout is a pipe is not pnpm-specific.

0 commit comments

Comments
 (0)