Skip to content

Agent-mode apply in a pnpm workspace reports each member-linked package twice, inflating the --json skipped count with duplicate already_patched events #633

Description

[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).

Summary

In a pnpm workspace on the default isolated linker, agent-mode apply reports every package that a workspace member links (packages/a/node_modules/<pkg> → node_modules/.pnpm/<pkg>@<ver>/node_modules/<pkg>) twice. The first run applies the patch once, then emits a second skipped / already_patched event for the same purl and the same physical copy. A re-run reports more skips than there are patches. The bytes on disk are correct. Only the event stream and the summary counts are wrong.

The Bun routine first noticed this (handover on ledger #303), and Bun's isolated linker has the same shape. I've reproduced it on pnpm.

Impact

Low severity, but it breaks the machine contract. summary.skipped and events[] overcount, so a CI gate or dashboard that reads apply --json sees phantom skips on every workspace run. The first run reports applied: 3, skipped: 2 for 3 patches, and a second run reports skipped: 5 for the same 3. A consumer can't tell a real skip (such as a version mismatch) from these duplicates without de-duplicating by purl itself.

Repro (main 045d7ec, Linux, Node 22)

mkdir -p ws/packages/a && cd ws
echo '{"name":"root","version":"1.0.0","private":true,"dependencies":{"is-odd":"3.0.1"}}' > package.json
echo '{"name":"a","version":"1.0.0","dependencies":{"is-number":"6.0.0","left-pad":"1.3.0"}}' > packages/a/package.json
printf "packages:\n  - 'packages/*'\n" > pnpm-workspace.yaml
pnpm install
# stage .socket/manifest.json + blobs with one patch each for
# pkg:npm/is-odd@3.0.1, pkg:npm/is-number@6.0.0, pkg:npm/left-pad@1.3.0
socket-patch apply --json   # summary: applied 3, skipped 2
socket-patch apply --json   # summary: applied 0, skipped 5

Events from the second run:

{"action": "skipped", "purl": "pkg:npm/is-number@6.0.0", "reason": "All files already match afterHash", "errorCode": "already_patched"}
{"action": "skipped", "purl": "pkg:npm/is-number@6.0.0", "reason": "All files already match afterHash", "errorCode": "already_patched"}
{"action": "skipped", "purl": "pkg:npm/is-odd@3.0.1", "reason": "All files already match afterHash", "errorCode": "already_patched"}
{"action": "skipped", "purl": "pkg:npm/left-pad@1.3.0", "reason": "All files already match afterHash", "errorCode": "already_patched"}
{"action": "skipped", "purl": "pkg:npm/left-pad@1.3.0", "reason": "All files already match afterHash", "errorCode": "already_patched"}

is-odd, which only the root depends on, appears once. The two packages that the member packages/a links appear twice. Each pair of events is identical and carries no path, and only one physical copy of each exists, under node_modules/.pnpm/.

Expected vs actual

  • Expected: one event per physical copy. Copies are de-duplicated by their real location (the crawler doc for find_by_purls says it returns "every physical copy", and npm-family copy sets elsewhere are deduped by canonical path). The run should report applied: 3, skipped: 0, then skipped: 3.
  • Actual: one extra already_patched skip per member-linked package, on every run.
OS pnpm 9.15.9 pnpm 10.28.0 pnpm 12.8.1
Linux reproduces (2/2) reproduces (Bun routine) reproduces (2/2)
macOS / Windows untested (probe branches blocked) untested untested

The root-only package (is-odd) and the hoisted linker (node-linker=hoisted, which has no member symlinks) don't show the duplicate.

Suspect code

crates/socket-patch-cli/src/ecosystem_dispatch.rs:88 runs find_by_purls once per node_modules root: the workspace root and packages/a/node_modules. push_path (ecosystem_dispatch.rs:128) then dedupes the resulting copies by literal path (paths.contains(&path)). The member root yields the copy through its symlinked node_modules/<pkg> spelling, and the workspace root yields the .pnpm path. Both resolve to the same directory but compare unequal, so apply visits the copy twice and the second visit reports already_patched.

Not bisected.


Backlog review — 2026-10-08

Priority: P1 → P3. Bytes are patched correctly; duplicate events inflate skipped counts. Keep the active fix in #1007.

Activity

  1. mikolalysenko commented on Oct 3, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged as priority:p1 (pnpm). Not a duplicate. No open PR covers it. Root cause per the report: ecosystem_dispatch.rs push_path dedupes copies across node_modules roots by literal path, not canonical path. Related to #626 (agent-mode handling of node_modules links), but that is a different code path (crawler link acceptance), so they're not clustered.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 7, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Claiming this issue as part of the pnpm open-issue sweep in draft PR #1007. Branch: agent/fix-pnpm-open-issues. Claim-ID: 2026-10-07T12:44:29Z-pnpm07

  3. mikolalysenko commented on Oct 7, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] PR #1007 fixes this issue. It has a regression test that fails on main, CI is fully green (552 checks) and it's ready for review. The issue will close when #1007 merges. The PR description's table gives the root cause, the fix and the test for each issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions