GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Fix pnpm brace and class workspace globs (#1846) by mikolalysenko · Pull Request #1863 · SocketDev/socket-patch Conversation
|
| glob | pnpm lists | here |
|---|---|---|
packages/{a,b} |
a b | read |
packages/[ab]* |
a ab b | read |
packages/{a..c} |
a b c | read |
packages/[a-b] |
a b | read |
packages/*, !packages/[ab] |
ab c x | read |
packages/[!a]* |
a ab (pnpm reads [!a] as [a]) |
refused |
packages/[^a]* |
.h b c x (matches a leading dot) | refused |
packages/[.]h |
.h | refused |
packages/[[:alpha:]] |
a b c x | refused |
| `packages/@(a | b), packages/(a |
b)` |
A class is read only when it is closed, not negated, and holds just letters, digits, _ and - ranges. Such a class can never match . or /. A glob with more brace alternatives than the matcher expands is also refused, so the answer is never partial.
member_dirs walks each brace alternative, with its classes widened to ? (a superset), and then lists_member narrows the result exactly.
hosted::governing_root::pnpm_lists_unmodeled and its unwrap_or_else fallback are deleted. Hosted now reads through lists_member. Syntax that is still unmodeled lists nothing there, which matches that function's documented "errs toward not a member" rule.
There is now one detector for "the lock lists member importers": formats::pnpm::workspace, with a new lock_text_has_member_importers(&str) entry point. It replaces pnpm_workspace::root_lock_lists_members. It now skips # comment lines: an indented commented importer was counted as a member, and a column-0 comment ended the section early. It also treats tab-led lines as continuation, as the deleted copy did.
Brace shapes that pnpm reads as picomatch does, not as brace expansion, are refused (a7ee393, from the final review). These are stepped or multi-character sequences (p{1..10} lists p0 p1 under pnpm), * or ? inside braces (these match a leading .), and an empty alternative (packages/{a,} must not list packages).
member_dirs walks at most 64 brace alternatives across all globs and returns Err beyond that (2161606, from the final review). Globs without braces are not counted against that cap (d52f3b6, from Bugbot). Each alternative is one walk of the tree, and an alternative that matches nothing never reaches MAX_MANIFESTS. In the reviewer's measurement, **/{a..z}{a..z}{a..e} took 519 s on about 4,200 directories.
A {x..y} sequence must have both ends digits, both lowercase or both uppercase (5ca5e0e, from the final review's open question): {-..0} stepped through . and /, and {0..Z} through ?.
A .. beside a comma in a brace set ({a,b..c}) and braces inside a class ([a{b,c}]) are refused (032b960, from the final review): pnpm reads the first as a sequence and the second as class members.
Merged main after the merge queue dropped this PR for a conflict (6dc33e2). main's "pnpm lock importers list a non-root member" is written twice and drifted on comment lines: keep formats::pnpm::workspace, delete the utils::pnpm_workspace copy #1952 had already merged the two lock-importer detectors, so this PR now uses main's lock_has_member_importers / lock_text_has_member_importers and no longer touches formats/pnpm/workspace.rs.
Behaviour notes: the merged lock-importer reader skips # comments, no longer ends importers: at a column-0 comment, and treats tab-indented lines as indented. The member walk's MAX_MANIFESTS bound now counts the union of every glob's candidates.
I did not add WorkspacesDialect::PNPM, which the issue suggested. With the second reader gone, lists_member (via glob_matches_no_dot) is the only pnpm reader, so the constant would have no caller.
Red before the fix (cargo test -p socket-patch-core --lib, new tests on 78ccde1 plus the test commit): 4 failed: member_dirs_read_braces_and_classes_as_pnpm_does, a_project_outside_the_packages_globs_is_not_governed, member_importers_mark_a_pre_10_5_workspace (commented importer), lock_text_member_importers_read_every_lock_shape.
Green after:
cargo fmt --all -- --check: okcargo clippy --workspace --all-features -- -D warnings: okcargo test -p socket-patch-core --all-features: 6992 passed. 4 failed only because this container runs as root, so chmod-based "write fails" tests cannot fail: copy_tree::relax_loop_must_not_traverse_symlinked_root, vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry, pypi_poetry::wire_write_failure_…, pypi_requirements::wire_failure_rolls_back_…. This PR doesn't touch those files.hosted_memory_parity (42), in_process_redirect_pnpm (41), in_process_vendor_pnpm_parent_child (8), in_process_vendor_pnpm_takeover (15), scan_pnpm_relocated_store_cwd_e2e (23): all pass.e2e_redirect_pnpm_build -- --ignored --skip pnpm_pinned_matrix (CI's leg, local pnpm 10.28): 11 passed.cargo test --workspace run ran out of container disk while linking CLI test binaries, so CI is the full run.Per-issue checklist (#1846 acceptance criteria):
member_dirs: governing_root::tests::pnpm_brace_and_class_globs_list_what_member_dirs_lists, pnpm_workspace::tests::member_dirs_read_braces_and_classes_as_pnpm_does (disk and in-memory trees).#-commented importer line is not a member: member_importers_mark_a_pre_10_5_workspace, lock_text_member_importers_read_every_lock_shape.governing_root tests pass. hosted_memory_parity::an_unconfirmed_pnpm_member_keeps_its_lock now uses an extglob as its unmodeled glob, because braces are read now.Fixed in acf9d23:
+ and \ beside a class or brace set: pnpm reads them as a quantifier and an escape. I confirmed this on pnpm 10.28: packages/[ab]+ lists a, ab, b; packages/\[a] lists only [a]. These globs are refused again, checked on the raw glob and on each brace alternative (so {Z..a} is refused too).member_dirs_refuse_a_glob_the_bounded_walk_cannot_finish).member_dirs no longer re-runs modeled for each candidate (lists_modeled_member).Err from member_dirs instead of relying on unwrap_or_default.scan --mode vendored still exits 1 forever and drops its in-run VEX when a nested npm project has no lockfile (package-lock=false); the #1534 fix only covers nested projects with their own lock #1554 doc comment is back on its own test.Bugbot (acf9d23): a class range starting at - ([--9]) spans . and /. Fixed in f9b15ba: a class body containing -- is refused.
Not fixed, by choice:
cargo_workspace::expand_glob_bounded braces and classes for every caller. That is Cargo workspace member globs ignore [...] character classes, so members = ["crates/[ab]*"] expands to no members #1833 (Cargo classes, p2), a separate root cause. Here the widen-then-narrow walk stays local to pnpm and stays exact, because lists_member decides every candidate.modeled's class check on workspace_globs::char_class. The check here deliberately accepts only a strict subset: closed, non-negated classes of [A-Za-z0-9_-] with no range starting at -. Anything else, []a] included, is refused. So when it disagrees with the matcher's grammar, the result is a refusal, never a wrong answer.https://claude.ai/code/session_011f9aeQPdgsuof1CE3TcTC5
Generated by Claude Code
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Assisted-by: Claude Code:claude-opus-5-5
The check for "does this pnpm lock list workspace members" counted a `#`-commented importer line as a member, and a column-0 comment ended the importers section early. It now skips comments, accepts tab-led lines, and gains a whole-text entry point so the second, hand-split copy in pnpm_workspace can go (#1846). Assisted-by: Claude Code:claude-opus-5-5
A pnpm-workspace.yaml listing members as `packages/{a,b}` or
`packages/[ab]*` was refused by every non-hosted membership check,
or (when deciding which workspace file governs a project) treated as
listing every directory, even though pnpm installs exactly those
members and the shared glob matcher already reads that syntax. Hosted
mode kept its own second reader to work around the refusal.
Now one reader answers for all callers: brace sets and plain classes
of letters, digits, `_` and `-` match as pnpm 10.28 reads them, and
the member walk expands braces and widens classes before narrowing.
Syntax pnpm reads its own way stays refused: `[!a]` (pnpm reads it
as `[a]`), `[^a]` and `[.]` (they match a leading dot), POSIX classes
and extglob groups. The hosted fallback reader and the duplicate
lock-importer detector are gone (#1846).
Assisted-by: Claude Code:claude-opus-5-5
The hosted/in-memory parity test used `packages/{a,b}` as its example
of a pnpm glob socket-patch cannot read. Brace sets are now read
(#1846), so the case uses an extglob group, which is still refused.
Assisted-by: Claude Code:claude-opus-5-5
Review on #1846: beside a class or brace set, pnpm reads `+` as a quantifier (`packages/[ab]+` lists `packages/ab`) and `\` as an escape (`packages/\[a]` lists only a directory named `[a]`), while the shared matcher reads `+` literally and `\` as a separator. Those globs are refused again, in each brace alternative too, instead of answering "not a member". Globs without classes or braces read as before. The member walk now applies one directory bound across every brace alternative, so a brace glob can no longer collect many times more candidates than the limit. Each candidate also skips the repeated syntax check. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
A class range from `-` (as in `packages/[--9]h`) spans `.` and `/`, so pnpm can match a hidden directory that the shared matcher never does. Such classes are refused now. A literal `-` (`[-a]`) and ranges between letters, digits and `_` stay readable. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Burn-down agent: labeled Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Burn-down agent: labeled Ready for review at
Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
pnpm 10.28.0 reads braces as picomatch does, not as brace-expansion
does. So modeled() accepted three shapes whose members differ from
what pnpm lists:
- a stepped or multi-character sequence: `p{1..10}` lists p0 and p1
under pnpm, not p10;
- a `*` or `?` inside braces: `{a,*}` lists dot directories under pnpm;
- an empty alternative: `packages/{a,}` listed `packages` itself.
Refuse these shapes, as the rest of modeled() already does for syntax
pnpm reads its own way, instead of guessing a member set that would
reach member_dirs and the hosted governing root.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
|
Final review of I compared against a real pnpm 10.28.0 (
The fix adds Ran: Non-blocking, for the PR description:
I removed bugbot run Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Burn-down agent: labeled Ready for review at
Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
member_dirs walks the tree once for each brace alternative, and the
directory bound only counts matches, so an alternative that matches
nothing walks the whole tree without ever reaching it. A scanned repo's
pnpm-workspace.yaml could list up to 4095 alternatives (for example
**/{a..z}{a..z}{a..e}) and stall the scan for minutes on a modest tree.
Allow at most 64 alternatives over all globs and answer Err beyond
that, which callers already treat as no answer.
Refs #1846
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011f9aeRR24V93EPLyuXR8tp
|
Final review of The problem: an untrusted The fix: Verified:
Non-blocking, for the description: two changes go beyond the brace/class fix, and the description doesn't mention them. Both are tested and look right.
I removed bugbot run Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
A brace sequence with single-character ends that are not the same
kind stepped through punctuation: `packages/{-..0}` expanded through
`.` and `/`, listing `packages` itself as a member, and `{0..Z}`
through `?`, which the walk then read as a wildcard. A sequence now
needs both ends to be digits, both lowercase or both uppercase.
Found in the final review of #1863.
Assisted-by: Claude Code:claude-opus-5-5
|
[agent] Fixed the final review's open question in 5ca5e0e instead of leaving it as a follow-up. This PR introduced it, and Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
pnpm 10.28 expands a `..` inside a comma brace set as a sequence
(`packages/{a,b..c}` lists `,` `0` `A` `[` ...), and reads braces inside a
class as class members (`packages/[a{b,c}]` lists `,` `{` `}`). modeled()
accepted both and listed a different member set, where the rule is to
refuse syntax we don't read the way pnpm does. Refuse any alternative
holding `..` beside a comma, and check classes on the raw glob too.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_011f9aeRocMg7S8GHB43bJsX
|
Final review found two globs where
All four globs are added to the refusal table. Local results: I removed bugbot run Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Ready for review (burn-down agent) at
Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Final review brief (replaces the brief for d52f3b6)What it does: pnpm Risk: low to medium. Glob semantics are subtle, and pnpm's behavior was probed on 10.28 only. Every gap fails closed: a refusal becomes Look here
Verified: I read the full diff and traced Changes I made: none. Open questions (non-blocking):
Auto-merge is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
[agent] Reviewed 032b9603af30ace16dd89c6bc8d8c977e9786ce8. Checked bounded brace/class workspace expansion, membership/importer agreement, range syntax and large plain workspace sets; existing inline findings are addressed at this head. No major correctness issues found. Validation: source and regression-test review plus the available exact-head CI checks; no local test pass is claimed.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
main (#1952) already merged the two pnpm lock-importer detectors this PR also merged. Keep main's generic lock_has_member_importers and lock_text_has_member_importers, and drop this PR's duplicate copy and its overlapping tests. The brace and class glob changes are unchanged. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
pnpm 10.28 keeps a brace group with no top-level comma or `..`
literal, also around a nested set: `packages/{app-{web,api}}` lists
only a directory named `{app-web}`, never `app-web`. The shared
matcher reads it the same way; this pins that.
Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem 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 8a311af. Configure here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
[final reviewer] Re-enqueued: approved, Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
pnpm workspace membership refuses brace and class globs the shared matcher already reads, and hosted keeps a second reader for them
There was an error while loading. Please reload this page.