Skip to content

Fix workspace member globs for yarn 1 and npm (#1097) - #1480

Merged
Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-workspace-glob-dialects
Oct 13, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-workspace-glob-dialects

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 #1097

Summary

A hosted scan / get from a workspace member must refuse with
redirect_workspace_lockfile_elsewhere, because the member installs from
the root's lock. The member check read every root's package.json
workspaces like npm does. It now reads them the way the package manager
that owns the root's lock does.

Root cause

workspaces_include (utils/workspace_globs.rs, called from
hosted/governing_root.rs) applied npm's last-match-wins ! negation
and had no extglobs, for every lock. I probed it on this box:

pattern npm 10.9 yarn 1.22.22 yarn 4.10 Bun 1.4.2 Bun 1.2.23
["packages/*","!packages/b"] a a,b a a a,b
["!packages/b","packages/*"] a,b a,b a a,b a,b
["packages/@(a|b)"] a,b a,b a,b install error install error
["!(internal)"] none none tools (extglob) — —

So under a yarn classic (or pre-1.3 Bun) root, a !-excluded member was
dropped. Under npm/yarn roots, an extglob matched nothing. Either way the
refusal never fired, and the run reported success with nothing pinned.

Fix

Bun < 1.3 (from the issue comments) is covered: a bun.lock without
configVersion, or a bun.lockb alone, ignores negation.

Changed test: package_json_workspace_non_members_are_left_alone
asserted that an empty yarn.lock root drops a !-negated directory.
That is the #1097 bug for yarn classic, so the test now uses a berry lock
for that assertion. Berry really does drop the directory.

Test evidence

  • New e2e in_process_redirect_pnpm::hosted_run_from_negated_or_extglob_workspace_member_refuses
    (scan and get; yarn classic / old Bun / bun.lockb negation, npm,
    shrinkwrap, classic and berry extglobs). Red on main 15c2c83: the
    first case reports "status":"success" with redirect_unconfirmed.
    Green on d7b844c.
  • New unit tests: workspace_globs::{extglob_dialects_match_like_npm_and_yarn, negation_is_per_dialect, ambiguous_extglobs_stay_fast} and
    governing_root::{package_json_workspaces_read_in_the_root_locks_dialect, lockless_intermediate_root_reads_the_widest_dialect, only_the_locks_whose_manager_lists_the_member_govern_it, bun_config_version_is_read_at_the_top_level_only}.
  • cargo fmt --all -- --check: clean. cargo clippy --workspace --all-features -- -D warnings: clean.
  • cargo test --workspace --all-features: 14345 passed, 13 failed. All
    13 are environmental. 12 are write-failure / unremovable-file tests
    that can't fail as root (this sandbox runs as uid 0), and
    e2e_bun_lockb::binary_shared_bundled_record_hosted_pin_is_managed
    needs network to patches-api.socket.dev. None of them touch the changed
    code. CI is the arbiter.
  • No wrapper changes are needed: the logic lives in core only.

Per-issue checklist

Bugbot (d7b844c) found 1 issue, the lock head read bypassing the FIFO-safe opener. Fixed in bfa67a3 with a test.

/code-review high ran on d9d05fd. All 9 findings were fixed in d7b844c:
lock filtering (3), berry negation order and !(, extglob blowup, head-only
lock reads, reuse of is_berry_lock, top-level configVersion, and a
?() simplification.

Follow-up, out of scope: npm_crawler's workspace directory expansion
still has no extglob support.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FkKQZyi8RSQAgn4DdJc2DP


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
A hosted scan or get run from a workspace member must refuse, since
the member installs from the root's lock. The member check read every
root's package.json "workspaces" like npm, so it disagreed with the
package manager in two ways:

- yarn classic (and Bun before 1.3) ignore "!" patterns, so a member
  excluded with "!packages/b" is still installed from the root lock.
- npm and yarn match extglobs like packages/@(a|b); the matcher matched
  nothing.

In both cases the run pinned nothing and reported success while the
next install brought in the unpatched package. The check now picks
the dialect from the root's lock: yarn classic vs berry by berry's
__metadata key, Bun 1.3+ by the configVersion it writes into bun.lock.
A root with several locks refuses when any manager lists the member;
a lockless root reads the widest set.

Fixes #1097

Assisted-by: Claude Code:claude-opus-5-5
Review follow-ups on the workspace dialect fix:

- A root with several locks now governs the member only through the
  locks whose package manager lists it. The refusal names just those,
  and a member's own npm, Bun or vlt lock is no longer called stray
  when its own manager excludes the member.
- yarn berry applies "!" patterns whatever their order and reads a
  leading "!(" as an extglob; yarn classic skips any "!" pattern.
- Ambiguous extglobs such as *(a|aa) no longer take exponential time.
- The lock sniff reads only the head of yarn.lock / bun.lock, reuses
  the shared berry check, and needs configVersion at the top level.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


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.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-core/src/hosted/governing_root.rs
The workspace dialect check sniffs the head of yarn.lock and bun.lock.
It opened them with a plain open, so a FIFO at that path could block
a hosted scan or get forever. It now uses the shared regular-file
opener, which fails fast on anything but a regular file.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


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 bfa67a3. Configure here.

Merged via the queue into main with commit 1b5d8d7 Oct 13, 2026
54 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/fix-workspace-glob-dialects branch October 13, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants