Skip to content

feat(lite): TRACKS lists a broadcast's tracks on lite-07 - #6057

Merged
kixelated merged 15 commits into
mainfrom
quest/m1/archive/tracks
Oct 21, 2026
Merged

kixelated merged 15 commits into
mainfrom
quest/m1/archive/tracks

Conversation

@kixelated

@kixelated kixelated commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Implements the TRACKS quest in Rust: a moq-lite-07 Tracks Stream lists one broadcast's tracks with their TRACK_INFO, marks SYNCED, and names removed tracks. The subscriber then SUBSCRIBEs per track. The JS half is split into quest/m1/archive/tracks-js.md, which now gates the lite-07 cut in its place.

Summary

  • Model (rs/moq-net/src/model/listing.rs). A broadcast lists the tracks its producer creates (create_track, unique_track, and reserve_track once accepted) until they leave the track table. A Finish-held track stays listed. Request-served tracks are never listed, and listing never requests one.
    • Each reader keeps a queue keyed by name in insertion order. An unread add and its removal cancel, and a removal plus re-add of a seen name collapses in place. A stalled reader holds at most the names it saw plus the live set.
    • SYNCED comes at the first drain or after N events, where N is the snapshot size.
    • A handler answers through broadcast::Lister. While any lister exists, readers wait for it to sync.
  • Fronts. An origin front forwards its serving source's listing through its own lister. On a same-instance takeover it reconciles: readers see only what differs, at the new source's SYNCED. A front whose serving route covers the path by a shorter prefix fails the listing with NOT_FOUND, since a route is capability, not inventory.
  • Wire (rs/moq-net/src/lite/tracks.rs). Stream type 0x8. The request is TRACKS {Broadcast Path, Epoch}. Replies are typed like lite-06+ announce messages:
    • TRACKS_ADD 0x0: the name plus an embedded, length-prefixed TRACK_INFO.
    • TRACKS_REMOVE 0x1: the name.
    • SYNCED 0x4: empty.
    • An unknown type, a duplicate add, an unknown remove, or a second SYNCED is a protocol violation. FIN means the broadcast ended.
    • Versions before lite-07 reset the stream type.
  • Publisher. A TracksServe request takes a subscription slot, is gated by subscribe auth like TRACK, and flushes before pulling each event, so backpressure collapses in the reader's queue.
    • A session keeps one listing per broadcast, deduplicated in the model by a per-session owner token so aliases and paths cannot split it: a newer TRACKS cancels the older with CANCELLED instead of being refused, since a relisting subscriber can open the new stream before the old one's reset arrives. Without this, each listing queues the whole listed set for one slot, so memory and fanout grow as tracks × listings. Each listing keeps its own slot until it is gone, so a replacement must fit under the cap, like a repeated SUBSCRIBE.
  • Subscriber. A session source answers through a Lister.
    • When someone lists, it syncs at once ("synced with this hop") and opens one upstream TRACKS. The peer's tracks follow as live adds, each holding an announces slot. Past the cap the listing resets with TOO_MANY_REQUESTS and the session stays.
    • It decodes the peer's events under a cooperative budget (32 per poll), since each one fans out to every reader.
    • It drops the stream once nobody lists. On the peer's FIN it ends its listing (Lister::finish) and releases the slots, without waiting for the retraction. A front whose live source finishes its listing ends its own.
    • Pre-lite-07 sessions fail listings with Unsupported rather than answer empty.
  • Draft. Adds the Tracks Stream section, the TRACKS, TRACKS_ADD, TRACKS_REMOVE and SYNCED messages, a stream-table row, and a lite-07 changelog line. just drafts check passes.
  • Docs. One Discovery paragraph in doc/concept/moq-lite.md.
  • Bench (rs/moq-net/benches/tracks.rs). Sweeps listings × tracks per broadcast × idle broadcasts. A change costs O(listings of the touched broadcast) and is flat in tracks and broadcasts. A new listing costs O(tracks).
shape (listings, tracks, broadcasts) change list
1, 10, 1 2.2 µs 0.62 µs
1, 1000, 1 2.4 µs 68 µs
100, 10, 1 33.6 µs 0.63 µs
100, 1000, 1 42 µs 82 µs
10, 10, 1000 5.2 µs 0.75 µs
10, 10, 1 4.7 µs 0.73 µs

Merge with main

Merged origin/main after moq-dev/moq#6030 (refresh demand) and moq-dev/moq#6058 (the ietf extension):

  • TRACKS_ADD's embedded TRACK_INFO now carries Refresh both ways, with an integration test (a_listing_carries_track_info).
  • drafts/draft-lcurley-moq-ietf.md: a subscriber MUST NOT skip the Track Stream for a listed track when the extension is negotiated, since TRACKS_ADD has no TRACK_PROPERTIES. The Rust subscriber never skips it.
  • Owner and tracks_as carry // private: capability gap markers for main's model-marker lint.
  • Quests: announce-synced.md and subscribe-ok-start.md landed on main and tracks.md lands here, so all three are gone; lite07-finalize.md lists tracks-js.md and the ietf provenance quest.

Public API impact

All additive, so there is no MIGRATE entry:

  • broadcast::Consumer::tracks() -> Result<Tracks, Error>
  • broadcast::Tracks with poll_next, next (async), and broadcast
  • broadcast::TracksEvent::{Added { name, info }, Synced, Removed { name }}
  • broadcast::Dynamic::lister() -> Result<Lister, Error>, failing with Duplicate while the broadcast has another lister (one answer per broadcast)
  • broadcast::Lister with poll_used, poll_unused, add, remove, synced, clear, finish, and abort

Wire impact

New lite-07-wip stream type 0x8 with four messages. No published version changes; older versions reset the stream type, as they already do for unknown types.
A publisher resets an older Tracks Stream for the same Broadcast on a session with CANCELLED.

Decisions (confirmed)

The maintainer confirmed each decision below, taking its recommendation; the alternatives stay listed.

  1. Names. tracks() / Tracks / TracksEvent / Lister, mirroring the wire's TRACKS. Alternative: listing() / Listing / ListingEvent. Chosen and confirmed: keep Tracks, since it matches the wire and the quest.
  2. End clients sync with their hop too. A client listing over a session sees SYNCED at once with zero tracks, then the upstream's tracks as live adds, so it cannot tell "no tracks" from "not arrived yet". This follows the 2026-10-19 decision that relays never wait on peers, and the session code does not know whether it is a relay.
    • Alternative: the session source syncs at the upstream's SYNCED. That makes every relay hop wait on its upstream.
    • Chosen and confirmed: hop-local sync.
  3. Peers that cannot list. A lite-01..06 session fails a listing with Unsupported. A moq-transport session has no lister yet, so it lists nothing (synced, empty) until SUBSCRIBE_TRACKS lands.
    • Chosen and confirmed: Unsupported for lite: fail loud, and the archive reports it as that broadcast's error rather than recording nothing.
    • Alternative: list nothing on both.
  4. SYNCED 0x4 shared with the announce stream. moq-dev/moq#6029 defines the same empty SYNCED for announces. Chosen and confirmed: whichever PR lands second merges the two into one section covering both streams. Done in the main merge: one ## SYNCED {#synced} section, where an Announce Stream ending before SYNCED is a protocol violation and a Tracks Stream FIN before SYNCED means the Broadcast ended. Alternative: give each stream its own SYNCED section.
  5. Cap overflow resets the listing, not the session. Announcements past announces close the session with TOO_MANY_REQUESTS. A listing past it only resets its stream with TOO_MANY_REQUESTS, per the quest ("reset the listing rather than holding more"). Chosen and confirmed: keep it. Alternative: close the session, matching announcements.
  6. JS split. @moq/net already resets type 8 on lite-07 (malformed.test.ts), so a Rust relay with a JS upstream fails just that listing with Unsupported. quest/m1/archive/tracks-js.md now gates the lite-07 cut. Chosen and confirmed: split. Alternative: land the JS half in this PR.

Follow-ups

  • TRACKS in js/net: created in this PR.
  • Seed TRACK_INFO from the listing. TRACKS_ADD carries TRACK_INFO, so a subscriber could skip the Track Stream for a listed track. Not done here: the TRACK stream's open stream doubles as held interest before SUBSCRIBE. Recommend a small quest once the archive producer shows the RTT matters. With the ietf extension negotiated it must not: TRACKS_ADD carries no TRACK_PROPERTIES, which the ietf draft now says.
  • Announces slot accounting. In the cap test, a lite-07 server session with one announced broadcast admitted no listed track under announces = 3. Something holds more than one slot per announced broadcast, perhaps the visible and hidden announce streams. Worth a look.

Checks

  • Passed:
    • After merging origin/main at eecb86c: just test interop --all, just drafts check, quest check. On the final head (with the TRACKS decode budget): just check.
    • cargo nextest run -p moq-net --all-features: listing unit tests, front tests (listing, takeover reconcile, covering-prefix NOT_FOUND), lite codec tests, and integration tests (direct, through a relay with two downstream listings, a listed track served from cache, lite-06 refusal, and the announces cap).
    • just drafts check, quest check, cargo bench --bench tracks.
  • Not tested here: datagrams arriving only from the SUBSCRIBE on (unchanged behavior: datagrams are never cached).

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 6 commits October 19, 2026 21:39
Consumer::tracks reports each listed track with its info, then Synced,
then live changes. A front forwards its serving source's listing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A subscriber opens stream type 0x8 naming a broadcast path and epoch.
The publisher answers with TRACKS_ADD (name plus TRACK_INFO),
TRACKS_REMOVE, and one SYNCED, then FINs when the broadcast ends. A
session syncs its readers at once and forwards the peer's tracks as live
adds, each holding an announces slot. Fronts reached through a covering
prefix refuse the listing with NOT_FOUND.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the Tracks Stream, TRACKS, TRACKS_ADD, TRACKS_REMOVE, and SYNCED to
the moq-lite draft, a listing paragraph to the moq-lite concept page, and
a bench sweeping listings, tracks, and broadcasts. Splits the JS half
into quest/m1/archive/tracks-js.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title feat(lite)!: TRACKS lists a broadcast's tracks on lite-07 feat(lite): TRACKS lists a broadcast's tracks on lite-07 Oct 20, 2026
@kixelated
kixelated marked this pull request as ready for review October 20, 2026 06:19
@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 36 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 83cbbecf-128f-4ddd-b2e4-dc54f52750b6
📥 Commits

Reviewing files that changed from the base of the PR and between eecb86c and 3546a6f.

📒 Files selected for processing: 24
  • doc/.vitepress/drafts.test.ts
  • doc/concept/moq-lite.md
  • drafts/draft-lcurley-moq-ietf.md
  • drafts/draft-lcurley-moq-lite.md
  • quest/m1/archive/README.md
  • quest/m1/archive/producer.md
  • quest/m1/archive/subscribe-tracks.md
  • quest/m1/archive/tracks-js.md
  • quest/m1/archive/tracks.md
  • quest/m1/lite07-finalize.md
  • rs/moq-net/Cargo.toml
  • rs/moq-net/benches/tracks.rs
  • rs/moq-net/src/lite/mod.rs
  • rs/moq-net/src/lite/publisher.rs
  • rs/moq-net/src/lite/stream.rs
  • rs/moq-net/src/lite/subscriber.rs
  • rs/moq-net/src/lite/tracks.rs
  • rs/moq-net/src/lite/version.rs
  • rs/moq-net/src/model/broadcast.rs
  • rs/moq-net/src/model/listing.rs
  • rs/moq-net/src/model/origin.rs
  • rs/moq-net/src/model/track.rs
  • rs/moq-net/tests/integration/main.rs
  • rs/moq-net/tests/integration/tracks.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T22:41:55.101908Z 3546a6f New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ab7b3a363

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-net/src/lite/stream.rs
Comment thread rs/moq-net/src/lite/publisher.rs
Each listing queues the broadcast's whole listed set but took one
subscription slot, so a peer could list one large broadcast up to the
cap and grow memory and fanout as tracks times listings. A newer listing
of the same broadcast instance now cancels the older one, rather than
being refused, since a subscriber that stops and relists can open the
new stream before the old one's reset arrives.

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d7dc3be90f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-net/src/lite/publisher.rs
Comment thread rs/moq-net/src/model/listing.rs Outdated
Comment thread rs/moq-net/src/lite/subscriber.rs Outdated
- A replacement TRACKS listing shares the older one's subscription slot,
  so relisting at the cap no longer closes the session.
- `Dynamic::lister` refuses a second lister with `Duplicate`: the model
  holds one answer and one sync flag, which two handlers would share.
- A peer's FIN on the Tracks Stream ends the source's listing through the
  new `Lister::finish` and releases the slots it held, even before the
  retraction arrives. A front whose live source finishes its listing ends
  its own, so the end reaches downstream readers.

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d2a9a6690a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-net/src/lite/publisher.rs Outdated
Sharing one slot across a broadcast's listings left unresolved duplicates
and other instances at the same path uncharged. Which listing a newer one
replaces is known only after resolution, so each listing is charged, and a
replacement must fit under the cap like a repeated SUBSCRIBE.

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8c5109b95f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-net/src/lite/publisher.rs Outdated
Comment thread rs/moq-net/src/model/listing.rs Outdated
kixelated and others added 4 commits October 20, 2026 00:12
The session registry was keyed by path, so aliases of one broadcast each
held a full queue. The broadcast's listing state now keeps at most one
reader per owner (a session), ending the older with Cancel, so identity
is the broadcast itself and the publisher-side registry is gone.

Also keep an answered name listed without churn when its own track is
replaced before the earlier one unlists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve against refresh demand (#6030), announce SYNCED (#6029) and the
ietf extension (#6058): TRACKS_ADD now carries TRACK_INFO's Refresh, the
draft shares one SYNCED section between the Announce and Tracks streams,
and the ietf draft keeps the Track Stream for listed tracks since
TRACKS_ADD has no TRACK_PROPERTIES.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

@codex review

Merged main after #6030 and #6058 with conflict resolutions in the draft, quests and lite listing code; see "Merge with main" in the description.

(Written by Claude Opus 5.5)

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85ca0479d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// and `Consumer::track` answers `Unroutable` for one asked about after this
// point. Say the same to whoever asked earlier.
state.reject_unserved(Error::Unroutable);
state.listing.close();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Abort listings when their last route disappears

When an upstream announcement is retracted before its independently ordered TRACKS FIN, SourceServe calls self.source.close() in subscriber.rs:1917-1920, and this new call terminates every listing reader with Ok(()). The downstream publisher consequently FINs its TRACKS stream and reports a clean broadcast end even though only the route disappeared, suppressing the error and re-request path; route loss should abort these readers, while clean completion remains reserved for publisher FIN or local shutdown.

AGENTS.md reference: rs/moq-net/AGENTS.md:L7-L7

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disagree. In moq-lite a retraction means the broadcast went offline at that hop, and a Tracks Stream FIN is defined as the broadcast ending, so a clean end is the right signal; announcements, not errors, are what a subscriber restarts on. Route loss with other routes left does not reach readers either: the origin front treats Ok(None) from a closing source as "move to another source" (it only ends its listing when no source remains), and a_front_reconciles_a_takeover covers the switch. Aborting here would turn every ordinary unannounce into an error downstream.

(Written by Claude Opus 5.5)

Comment on lines +400 to +402
if !self.synced && (self.bound == Some(0) || (self.bound.is_some() && self.pending.is_empty())) {
self.synced = true;
return Ok(Some(TracksEvent::Synced));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fix the deterministic listing test failure

With initial tracks a,b, reading a leaves bound == 1; removing a appends its removal after b, and reading b decrements the bound to zero, so this condition emits Synced before the removal. The newly added a_removal_of_a_seen_track_may_precede_synced test instead asserts +b, -a, synced, so the moq-net unit suite deterministically fails on this path; either distinguish events belonging to the opening bound or align the assertion with the implemented ordering.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disagree: the test passes. It lists three tracks (a, b, c), so the opening bound is 3, not 2. After reading +a the bound is 2; dropping c cancels its unread add, leaving b, -a queued, and both are read before the bound hits 0, giving +b, -a, synced as asserted. The two-track trace in the finding is not what the test does. cargo nextest run -p moq-net --all-features listing passes a_removal_of_a_seen_track_may_precede_synced on this head.

(Written by Claude Opus 5.5)

Comment on lines +1768 to +1769
loop {
let Some(event) = ready!(stream.reader.poll_decode_maybe::<lite::TracksEvent>(&mut cx))? else {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Yield while draining buffered TRACKS events

When a peer continuously sends a valid alternating sequence of TRACKS_ADD and TRACKS_REMOVE events, poll_decode_maybe can remain ready for as long as bytes are supplied, but this loop has no cooperative budget and each event also locks and fans out through the listing model. A hostile session can therefore monopolize the executor thread and stall unrelated sessions without accumulating entries or exceeding the announcement cap; add a bounded kio::coop::Budget yield as used by the publisher request loops.

AGENTS.md reference: AGENTS.md:L17-L18

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed: fixed in 3546a6f. TracksRecv now spends a kio::coop::Budget::new(32) pass per decoded event, matching the publisher's request loops, so a churning peer yields the thread every 32 events.

(Written by Claude Opus 5.5)

kixelated and others added 2 commits October 20, 2026 15:04
Each event fans out to every reader of the listing, so a peer streaming
add/remove churn could hold the thread while its bytes keep arriving.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary for 3546a6f:

  • Merged origin/main (eecb86c, quest files only, no conflicts).
  • Addressed the Codex review of 85ca0479d5:
    • Fixed: the subscriber's TRACKS decode loop now yields on a kio::coop::Budget every 32 events (reply).
    • Declined: a_removal_of_a_seen_track_may_precede_synced passes; the finding traced two tracks where the test lists three (reply).
    • Declined: a retraction ends the broadcast at that hop, so a clean TRACKS end is correct, and the origin front already moves to another source when one remains (reply).
  • Checks: just test interop --all, just drafts check, quest check after the main merge; just check and the moq-net listing, TRACKS codec, front, and integration tests on the final head.
  • The delta since the Codex review is the 5-line budget the review asked for, mirroring the publisher's request loops, so no further review was requested.
  • Decisions in the description were confirmed by the maintainer earlier; nothing new is open.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit fecb571 Oct 21, 2026
13 checks passed
@kixelated
kixelated deleted the quest/m1/archive/tracks branch October 21, 2026 01:46
kixelated added a commit that referenced this pull request Oct 21, 2026
TRACKS (#6057) listed TRACK_INFO without the new Compression field: the
publisher now sends it (lite-07 only, as TRACK does) and the subscriber
keeps it on the listed track::Info. The listing tests cover it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant