Skip to content

Fix vlt 1.3 brotli lock nodes being refused (#372) - #820

Merged
Mikola Lysenko (mikolalysenko) merged 7 commits into
mainfrom
agent/fix-vlt-brotli-node-flag
Oct 5, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 7 commits into
mainfrom
agent/fix-vlt-brotli-node-flag

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #372

Root cause

vlt 1.3 records a new node flag bit, brotli = 4, in slot [0] of a vlt-lock.json node when it resolved a .tar.br alternate. The shared vlt node-line grammar (vendor/vlt_lock_text.rs::parse_node_entry_text) whitelists slot [0] ∈ {0,1,2,3}, so every brotli node fails to parse. Hosted, vendored, heal and VEX discovery all read nodes through that parser, so hosted refuses the lock as "not canonical" (exit 0, nothing redirected), and vendored fails with vendor_lockfile_version_unsupported.

Changes (b3996a6)

  • Shared grammar: slot [0] is vlt's flag bitset 0–7 (node_flags); anything else is still refused.
  • render_tuple_with_slots now takes the brotli bit explicitly, because slots [2]/[3] name one artifact and its hash. vlt derives the bit from slot [3]'s extension (tarballFormat, checked against @vltpkg/graph / @vltpkg/types 1.3.6). If slot [3] is omitted, vlt uses the stored bit to rebuild the URL. Callers:
    • hosted pin → hosted .tgz: bit cleared, so vlt ci keeps the lock byte-stable, as the issue verified.
    • vendored wiring → local dir: bit cleared.
    • upstream restore → registry .tgz integrity: bit follows the written URL (cleared when omitted).
    • vendored revert and superseding-carried-pin restore → the recorded original's bit.
  • vlt_heal::reinstalls_after_removal: decided by the optional bit (flags <= 7 && flags & 1 == 0), so brotli prod/dev nodes (4, 6) are reinstalled.

Tests (red → green)

With only the old "0" | "1" | "2" | "3" grammar line restored, 3 of the 4 new tests fail. With the fix, all 4 pass:

  • vlt_lock_text::node_line_grammar_accepts_vlt_1_3_brotli_flags (flags 4–7 parse; 8, 07, -1 still refused)
  • vlt_lock_text::brotli_bit_follows_the_artifact_slot_three_names
  • redirect::vlt::a_vlt_1_3_brotli_lock_is_pinned_with_the_brotli_bit_cleared (hosted: no refusal, bits cleared with dev kept, idempotent re-run, carried-pin restore puts bit 4 back)
  • vendor::vlt_lock::a_vlt_1_3_brotli_lock_is_vendored_and_reverted_exactly (vendored wire + byte-exact revert)
  • updated vlt_heal::only_prod_and_dev_nodes_are_reinstalled_after_removal

cargo test -p socket-patch-core --lib -- vlt: 171 passed, 1 failed. The failure is vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry, which depends on a 0o555 directory blocking writes, and this sandbox runs as root. The change doesn't touch it.

Local gate

  • cargo fmt --all -- --check: clean
  • cargo clippy --workspace --all-features -- -D warnings: clean
  • cargo test --workspace --all-features --no-fail-fast: every vlt binary passes (e2e_redirect_vlt_build, e2e_vendor_vlt_build, e2e_vlt, e2e_safety_vlt, mode_migration_vlt). The only local failures don't involve vlt:
    • chmod-based tests (covgap_commands_vendor *_state_write_failure_*, vlt_heal::an_unremovable_hidden_lock_*). This sandbox runs as root, so a 0o555 directory doesn't block writes.
    • Go/PyPI e2e builds that hit ENOSPC because the sandbox disk filled up.
  • The ignored real-vlt-1.2.0 matrix (--include-ignored vlt_pinned_matrix) can't fetch npmjs from the Rust test client in this sandbox. CI runs it: 460/466 checks green on b3996a6, 3 still in progress, 0 failed.

Per-issue checklist

Follow-ups (not in this PR)

  • The CI vlt matrix pins vlt 1.2.0, and its e2e fixtures use npmjs bytes that advertise no .tar.br alternates. A real-vlt-1.3 e2e would need a mock registry that serves alternates.

Note

Medium Risk
Touches vlt lock parsing and rewrite paths (hosted, vendor, heal, upstream restore); behavior is narrow and heavily tested but incorrect flag handling could break installs on vlt 1.3 locks.

Overview
Fixes #372 by teaching the shared vlt-lock.json node grammar to accept vlt 1.3 slot [0] flags 0–7 (including the brotli bit 4 for .tar.br resolves), instead of refusing anything above 3 as non-canonical.

Brotli-aware tuple rendering: render_tuple_with_slots now takes an explicit brotli flag derived from slot [3]’s URL extension (brotli_for_slot3 / has_brotli_flag). Hosted redirect pins clear bit 4 when rewriting to a hosted .tgz; vendored wiring and upstream restore follow the same artifact rules; revert and carried-pin restore put the pristine brotli bit back. Heal treats brotli prod/dev nodes (4, 6) as reinstallable after removal (optional bit still excludes 1, 3, 5, 7).

Tests: New coverage for brotli lock parse, pin, vendor/revert, and flag behavior; vex hosted npm tests were adjusted so alias expansion is still exercised now that the name-keyed resolver (#605) discovers aliases on its own.

Reviewed by Cursor Bugbot for commit 95ecf33. Configure here.


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
vlt 1.3 marks a lock node that fetches the registry's Brotli
(.tar.br) tarball with a new flag bit, 4, in slot [0]. socket-patch
only accepted flags 0-3, so hosted mode refused such a lock as "not
canonical" and exited 0 with nothing redirected, and vendored mode
failed with a misleading lockfile-version error.

Accept flags 0-7. When a pin or vendored wiring points a node at a
.tgz or local directory, clear the brotli bit as vlt would save it;
reverts put the recorded bit back with the original slots. The vlt
heal now reinstalls brotli prod and dev nodes like any other.

Fixes #372

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 5, 2026 02:53
@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.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 5, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Labeled Ready for review.

  • Head: b3996a6e
  • CI: all checks green on head (491 runs, 0 failing)
  • Bugbot: reviewed b3996a6e, no issues found; 0 unresolved review threads
  • Mergeable against main; already approved by Tanmay Singla (@Tanmay182003).

Slack announcement not sent this run (no Slack send tool available), so the next run will retry.


Generated by Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NhRxWtzEYpLyrByBegiiRy
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

composer 2.5.8 / php 8.2 / ubuntu-latest failed on 7535c05, but the failure doesn't come from this PR. composer_hosted_v_tagged_fresh_checkout_install stopped inside composer update with curl error 28 while downloading https://repo.packagist.org/packages.json: SSL connection timeout. The PR doesn't touch Composer or packagist; its changes are vlt brotli node handling plus a merge of main. The job's other 10 composer e2e tests passed. There's nothing to port. I'll re-run the failed job once, after the rest of the workflow run finishes (GitHub refuses a re-run while the run is in progress).


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

coverage failed on 7535c05, in the -p socket-patch-cli --lib target. The evidence says the failure doesn't come from this PR:

The failing test's name falls outside the 5,000-line log tail I can read, so the root cause isn't known yet. I'll re-run the job once when its workflow run finishes. If it fails again, I'll treat it as real and dig in.


Generated by Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NhRxWtzEYpLyrByBegiiRy
main is red since 4646693 (#605): two commands::vex_consumed tests
assumed the name-keyed resolver never returns npm-aliased copies.
Same test-only change as #851; it no-ops once main carries it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NhRxWtzEYpLyrByBegiiRy
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Update on the coverage failure: I found the root cause. main has been red since 4646693 (#605). Two commands::vex_consumed tests in socket-patch-cli --lib fail there, and I reproduced that locally on origin/main. CI tests PRs merged into main, so every open PR picks up the failure. #851 fixes it with a test-only change.

I pushed fde5eef, which merges main (4646693) and ports #851's change. The port becomes a no-op once #851 lands. cargo test -p socket-patch-cli --lib now passes (840/840), and fmt and clippy are clean.

native (ubuntu-latest, 2.17.3) also failed on 7535c05, in the PDM backtest case multi-target agent (appliedExactlyOne). Agent apply is the area #605 changed, and this PR doesn't touch PDM. I'll check that job on fde5eef. The coverage re-run I promised is no longer needed, since fde5eef triggers a fresh run.


Generated by Claude Code

The fix commit b3996a6 also reformatted 123 files it does not otherwise
touch (the output of cargo fmt --all on a tree main has not formatted).
Every one of those files is byte-identical to rustfmt run over main's
version, so this restores them to main. The PR now only touches the vlt
lock, redirect and heal code plus the ported #851 test fix, which keeps
the review small and stops the churn from conflicting with every other
open PR.

Co-Authored-By: Claude <noreply@anthropic.com>
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Burn-down agent: pushed 95ecf33.

  • Merged main (clean).
  • Fix commit b3996a6 had also run cargo fmt --all, reformatting 123 files the fix doesn't otherwise touch. Each one matched rustfmt run over main's copy byte for byte, so I restored them to main. The diff is now 6 files: the vlt lock, redirect and heal code, plus the ported Fix vex alias tests broken by store-copy merge #851 test fix.
  • Locally: cargo clippy --workspace --all-features -D warnings is clean, and socket-patch-cli --lib vex_consumed passes 10/10. socket-patch-core --lib vlt passes 179/180. The one failure is vlt_heal::tests::an_unremovable_hidden_lock_keeps_every_store_entry, a chmod-based test that can't fail when the sandbox runs as root. This PR doesn't change that test, and it passes in CI.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


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 95ecf33. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 5, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Burn-down agent: labeled Ready for review.

  • Head: 95ecf33dc988c3462179d29c0d08eb2c02ea2675
  • CI: 488/488 check runs green (success/skipped) on this head; mergeable clean
  • Bugbot: reviewed 95ecf33, no new issues; no open threads
  • Reviewer focus: vlt 1.3 brotli lock node flag handling; diff is 6 files after dropping fmt churn

Generated by Claude Code

@mikolalysenko
Mikola Lysenko (mikolalysenko) merged commit 7fd88f5 into main Oct 5, 2026
489 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/fix-vlt-brotli-node-flag branch October 5, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hosted and vendored modes refuse vlt 1.3 locks whose nodes carry the new brotli flag (slot [0] = 4)

3 participants