Skip to content

feat(ws): stream the rig library to the client#1044

Open
gionnibgud wants to merge 1 commit into
mainfrom
feat/rigs-library-on-the-wire
Open

feat(ws): stream the rig library to the client#1044
gionnibgud wants to merge 1 commit into
mainfrom
feat/rigs-library-on-the-wire

Conversation

@gionnibgud

Copy link
Copy Markdown
Contributor

What

Completes the core reader for source rigs — board Keys Foundations #4, "Core reader for source rigs (spec 1.18.0)". Follows #1040, which landed the reading half.

#1040 shipped the references and not the thing they reference. base_rig and each change's rig reached the client, and LoadedSloppak.rigs — the library those ids point into — sat server-side with zero consumers. A client could learn that a change binds "grand-piano" and had no way to find out what that was. Same gap on the drum side: P3 resolved each part's tones binding in the loader, and the wire payload was still {id, name}.

Two additions:

  • New rigs WS message carrying rigs.json whole and verbatim.
  • song_info.drum_parts[].tones — each part's resolved binding (entry tones, or the drum_tones fallback), omitted when the part binds nothing.

Plus the client-side plumbing: getRigs() / getToneBaseRig(), bundle.rigs / bundle.toneBaseRig, and both reset paths clearing them between songs.

Two decisions worth reviewing

Not gated on tone changes. The library ships whenever the pack has one, rather than only when the active arrangement has tone_changes. A pack can bind sound to its drum parts alone via drum_tones and still need the library — gating on arrangement tones would strand exactly that case. Covered by test_rigs_stream_even_without_arrangement_tones.

Verbatim, whole. No per-rig filtering or resolution. Core selects no realization and applies no intent.gm floor, so the consumer that voices the part needs the entire block to make that choice — including the unknown role/engine/kind values and ext namespaces §7.9 obliges a Reader to preserve. Sending only "the rigs this arrangement references" would also break the drum case above.

Compatibility

Packs that bind no rig are byte-identical on the wire: no rigs message, no base_rig, no rig, no tones key on a drum part. test_unbound_pack_keeps_the_legacy_payload_shape asserts exactly that.

Verification

  • Python 2802 passed / 4 skipped (+6 new in tests/test_highway_ws_rigs.py, end-to-end through the real WS via TestClient).
  • JS 1343 passed / 0 failed.
  • tools/check_spec_conformance.py: OK.

The new tests cover the pairing that is the actual point — that the ids in tone_changes and in a drum part's tones resolve against ids present in the rigs frame.

feedpak surface

Checklist

  • CHANGELOG.md [Unreleased] updated
  • Tests added/updated for new behaviour
  • Commits are DCO signed off (git commit -s)

Note for whoever merges: CHANGELOG.md is CRLF in this repo — worth knowing before editing it with a tool that normalises line endings, which silently rewrites all ~660 lines.

Also open and independent: #1041 (routes _load_rigs_file through the shared path helper).

The core rig reader landed its reading half but not its exposing half:
the bindings shipped (`base_rig`, per-change `rig`) while the library
they are references INTO stayed server-side on LoadedSloppak.rigs with
no consumer at all. A client could see that a change binds
"grand-piano" and had no way to learn what that was.

Add a `rigs` WS message carrying the library whole and verbatim, and put
each drum part's resolved `tones` binding on its `song_info.drum_parts`
entry — the drum half had the same gap, since the loader resolved the
binding in P3 and the wire payload was still `{id, name}`.

Sent whenever the pack ships a library, deliberately NOT gated on this
arrangement having tone changes: a pack can bind sound to its drum parts
alone via `drum_tones` and still need the library.

Verbatim matters here. Core selects no realization and applies no
`intent.gm` floor, so the consumer that voices the part needs the whole
block to make that choice — including the unknown `role`/`engine`/`kind`
values and `ext` namespaces §7.9 requires a Reader to preserve.

Client side: `hwState.rigs` / `toneBaseRig`, `getRigs()` /
`getToneBaseRig()`, and `bundle.rigs` / `bundle.toneBaseRig` so
renderers reach them the same way they reach every other chart array,
with both reset paths clearing them between songs.

Packs that bind no rig are byte-identical on the wire — no `rigs`
message, no `base_rig`, no `rig`, no `tones` on a drum part.

Signed-off-by: gionnibgud <gionnibgud@gmail.com>
@gionnibgud gionnibgud added the keys-foundations Keys Foundations initiative — org project #4 label Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@gionnibgud, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 20 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 402d9f8a-564c-4215-b20a-fc84305903bf

📥 Commits

Reviewing files that changed from the base of the PR and between eef58c8 and b943589.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • CLAUDE.md
  • lib/routers/ws_highway.py
  • static/highway.js
  • tests/test_highway_ws_rigs.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rigs-library-on-the-wire

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Labels

keys-foundations Keys Foundations initiative — org project #4

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant