Repository navigation
Fix Bun 1.3+ bun.lockb read as pre-1.3 (#1492) - #1496
Merged
Mikola Lysenko (mikolalysenko) merged 7 commits intoOct 13, 2026
Merged
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Bun 1.3+ writes a cNfGvRsN extension into bun.lockb, the binary twin of the text lock's configVersion. Expose it from the codec and add regression tests for #1492: a tagged lone bun.lockb root must honour "!" workspace patterns, so an excluded member's own lock is the one patched. WIP: lock_dialect does not read the tag yet. Assisted-by: Claude Code:claude-opus-5-5
A Bun 1.3+ project that keeps a binary bun.lockb (saveTextLockfile = false) and excludes a member with "!packages/b" could no longer patch that member in hosted or vendored mode: socket-patch read the lone bun.lockb as older Bun, which ignores "!", and refused with redirect_workspace_lockfile_elsewhere. Read the cNfGvRsN config-version tag Bun 1.3+ writes into bun.lockb, as configVersion is read from bun.lock. Fixes #1492. Assisted-by: Claude Code:claude-opus-5-5
The Bun 1.3+ check parsed the whole bun.lockb, so a tagged lock the codec rejects, or one with an extension it does not know before the tag, still read as older Bun and kept refusing an excluded member. Bun writes the cNfGvRsN extension last, right before the lock's total length, so read the header and those 16 bytes only. This also keeps the check cheap on large monorepo locks. Cover a workspace root's lock, whose tag follows its workspace and catalog extensions, and say in the docs that Bun 1.3.0 does not write the tag. Assisted-by: Claude Code:claude-opus-5-5
Mikola Lysenko (mikolalysenko)
marked this pull request as ready for review
October 13, 2026 19:25
Collaborator
Author
|
BugBot review Generated by Claude Code |
…ialect # Conflicts: # crates/socket-patch-cli/CLI_CONTRACT.md
Collaborator
Author
|
BugBot review Generated by Claude Code |
Bun writes the sCoPdOvR scoped-overrides extension after cNfGvRsN, so a lock with nested overrides has no tag at total - 16 and still read as older Bun, refusing a member excluded with "!". Walk the structure instead: the header, the six buffer descriptors and the extension tags, seeking past every array, so package records are never read and the tag is found wherever Bun puts it. Add a Bun 1.4.2 fixture with scoped overrides and a "!" workspace pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013g2AhipQxH9Q19uPZT6Aph
Every bun-lockb fixture is swept by the VEX discovery tests, which rewire minimist@1.2.2 at the root and compare against the golden corpus. Regenerate the scoped-overrides lock with the corpus's minimist@1.2.2 / is-number@7.0.0 dependencies and an override nothing installs (Bun still writes sCoPdOvR after cNfGvRsN), and add its golden entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013g2AhipQxH9Q19uPZT6Aph
Tanmay Singla (Tanmay182003)
approved these changes
Oct 13, 2026
Collaborator
Author
|
bugbot run Generated by Claude Code |
There was a problem hiding this comment.
✅ 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 e509c25. Configure here.
Collaborator
Author
|
Ready for review (burn-down agent)
Generated by Claude Code |
Mikola Lysenko (mikolalysenko)
deleted the
agent/fix-bun-lockb-dialect
branch
October 13, 2026 22:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1492
Summary
A Bun 1.3+ project that keeps a binary
bun.lockb(saveTextLockfile = false) and excludes a member with"!packages/b"can patch that member again in hosted and vendored mode. Since 5.0.1, socket-patch treated the excluded member as a workspace member. It refused withredirect_workspace_lockfile_elsewhere(hosted) orvendor_lockfile_missing(vendored) and named a root lock Bun never reads for that member.Root cause
lock_dialectincrates/socket-patch-core/src/hosted/governing_root.rs(#1097, #1480) picks how a root'sworkspacesglobs are read from the lock at that root. Every lonebun.lockbwas read with the pre-1.3 Bun rules, which ignore!. Bun 1.3+ applies!whichever lock format it writes. It marks abun.lockbwith acNfGvRsNextension that carriesconfigVersion, the binary twin of the text lock's top-level key, which thebun.lockbranch already checks.Fix
vendor/bun_lockb.rs:read_config_versionwalks only the lock's structure (header, the six buffer descriptors, the extension tags), seeking past every array, and returns the tag wherever Bun writes it. With nestedoverrides, Bun writessCoPdOvRafter it.lock_dialectcalls it through the FIFO-safe opener on the blocking pool. It never reads package records, so a lock the full codec rejects still gets its tag read, and a large monorepo lock costs a few small reads. A lock that is untagged, unreadable or not binary keeps the wider pre-1.3 reading, as before.CLI_CONTRACT.mdline forredirect_workspace_lockfile_elsewhereand the Hosted scan from a yarn classic workspace member still pins nothing and exits 0 when the root's workspaces use a!pattern (yarn 1 ignores it) or an extglob like packages/@(a|b) #1097 CLI test comment.Test evidence
hosted::governing_root::tests::bun_lockb_with_a_config_version_tag_honours_negated_workspacesuses real Bun 1.3.14, 1.4.2 workspace-root and 1.4.2 scoped-overrides locks (the last is the newbun-lockb/1.4.2-scoped-overridesfixture, written on Linux) (no refusal, member lock not a stray), plus 1.2.23 and a non-binary lock (still refused).assertion left == right failed: bun.lockb of 1646 bytes; left: Some("redirect_workspace_lockfile_elsewhere"), right: None.cargo test -p socket-patch-core --all-features --lib -- governing_root bun_lockb→ 67 passed.vendor::bun_lockb::tests::config_version_is_read_from_tagged_locks_onlychecks every historical fixture 0.1.1 to 1.4.2, plus workspace "late-dependent" locks.cargo fmt --all -- --check: clean.cargo clippy --workspace --all-features -- -D warnings: clean.cargo test -p socket-patch-core --all-features --lib: 6453 passed and 4 failed. All 4 are permission-denial tests (copy_treesymlinked root,vlt_healunremovable lock, poetry/requirements write failure) that cannot fail as intended when the sandbox runs as root. They are unrelated to this diff, and CI runs as non-root.cargo test --workspacelocally: the sandbox ran out of disk building every CLI test binary. CI runs the full suite.Per-issue checklist
refusal) and vendored (samelock_dialect→member_stray_lockpath), covered bybun_lockb_with_a_config_version_tag_honours_negated_workspaces.Notes / not changed
cNfGvRsNtag (fixturebun-lockb/1.3.0), so its binary lock still reads as older Bun. Its textbun.lockwithoutconfigVersionalready does the same today. This fails closed: a refusal, never a wrong pin./code-review highsuggested a different approach: decide membership from the lock's own workspace list (workspace_paths()) instead of the Bun version. I didn't take it. The text-lock branch decides byconfigVersiontoo, and the lock's list is stale for a member added since the last install. Moving both branches would be a separate change to the Hosted scan from a yarn classic workspace member still pins nothing and exits 0 when the root's workspaces use a!pattern (yarn 1 ignores it) or an extglob like packages/@(a|b) #1097 design. Every other finding (full-parse dependence, unknown-extension stop, unbounded read, 1.3.0 doc claim, stale CLI test comment, missing workspace-root fixture) is fixed in 7d05f17. A reviewer's finding on scoped overrides is fixed in 13f02d6 (fixture fitted to the VEX corpus in e509c25).🤖 Generated with Claude Code
Note
Medium Risk
Changes workspace membership and refusal logic for hosted/vendored npm flows when only
bun.lockbis present; mis-detection could refuse or allow runs from the wrong directory, but untagged or invalid locks still fall back to pre-1.3 behavior.Overview
Fixes #1492: lone binary
bun.lockblocks were always interpreted with pre–Bun 1.3 workspace rules (negated!patterns ignored), so excluded workspace members were wrongly refused withredirect_workspace_lockfile_elsewhere/ stray-lock handling when only a taggedbun.lockbexisted at the root.read_config_versioninbun_lockb.rsreads Bun’scNfGvRsNextension (binary twin of textconfigVersion) via a structural walk, including whensCoPdOvRfollows the tag.lock_dialectuses that for standalonebun.lockb(FIFO-safe sync read on the blocking pool) to pick Bun 1.3+ vs pre-1.3 glob semantics, matching the existingbun.lockpath.Docs (
CLI_CONTRACT.md), CLI test comments, a1.4.2-scoped-overridesfixture, VEX golden updates, and unit/integration tests cover tagged vs untagged locks and negated workspaces.Reviewed by Cursor Bugbot for commit e509c25. Configure here.
Generated by Claude Code