Skip to content

fix(net): backport an explicit group 0 floor on pre-06 wires (#5000) - #5300

Merged
kixelated merged 4 commits into
releasefrom
backport/lite05-start-group-zero
Oct 11, 2026
Merged

kixelated merged 4 commits into
releasefrom
backport/lite05-start-group-zero

Conversation

@kixelated

@kixelated kixelated commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Backport of #5000 (36f82ac) onto release.

What it fixes

On release, a moq-lite-05 (or older) SUBSCRIBE or SUBSCRIBE_UPDATE that names group 0 was folded to "latest" by the encoder in both languages, so a subscriber asking to replay from group 0 joined at the live edge instead. After this:

  • undefined / None means the latest group (wire 0 on pre-06).
  • An explicit group 0 means group 0 (wire 1 on pre-06, the sequence + 1).
  • Rust's Subscription::start: Option<Position> and codec start_group: Option<u64> encode exactly like JS groups.start undefined vs { included: 0 }.
  • Lite-06 still writes 0 for both, a published-wire limitation left as is.

The publisher no longer pins its cursor to the SUBSCRIBE_START group when the subscription named an explicit floor, so a fresh group created below the first served group is still delivered within the subscriber's max age. A pre-06 subscription with no floor still pins, since those drafts define an absent Group Start as the latest group.

Conflicts and resolutions

  • rs/moq-net/src/lite/subscribe.rs: kept release's BufMut codec (no refactor(net)!: plain u64 varint codec and simulated-time tests (rs2ts) #4437 varint refactor); the fix is start_group.encode(w, version) with no > 0 filter. Test ported to release's encode_msg/decode_msg.
  • rs/moq-net/src/lite/publisher.rs: kept release's SubscribeStart { group } (no largest); applied the conditional raise_start_to. Unit tests use #[tokio::test] and with_max_age.
  • rs/moq-net/tests/late_lower_group.rs (new): ported to release's tokio harness, request_broadcast(path), track.used(), and max_age.
  • rs/moq-net/tests/history_groups.rs: kept release's version (main's hunk only rewrote a comment on a sleep release does not have).
  • rs/moq-net/tests/quiet_catalog.rs: deleted on release, hunk dropped.
  • js/net/src/integration.test.ts, js/net/src/lite/subscriber.ts: maxAge instead of maxDelay; merged the resolvesStart import with release's.
  • drafts/draft-lcurley-moq-lite.md: kept the SUBSCRIBE / SUBSCRIBE_OK text and the two matching lite-07 changelog lines; dropped main-only changelog entries. No wire format change.
  • quest/m1: deleted lite-late-lower-group.md and its README line, as main did; dropped the lite-live.md edit (that quest is absent on release).

Added group_start_wire_values_match_js (Rust) and a matching JS test that pin the pre-06 wire values (absent 0, group 0 is 1) and lite-06 (both 0) on both sides.

Public API and wire impact

No public API change. Wire: a pre-06 SUBSCRIBE/SUBSCRIBE_UPDATE that names group 0 now sends Group Start = 1 instead of 0, as those drafts define. Lite-06 and lite-07-wip bytes are unchanged. SUBSCRIBE_OK Group is no longer a new floor (a semantic change documented in the lite-07 draft).

Tests

  • just check: pass.
  • cargo nextest run -p moq-net: 1545 passed, 4 skipped. With the release encoder and publisher restored, late_lower_group fails on lite-05/06/07-wip and group_start_wire_values_match_js fails.
  • bun test in js/net: 1119 pass, 2 skip. With the release encoder restored, the three Group Start tests fail.

Also: #5301

Codex found that a pre-06 SUBSCRIBE_UPDATE dropping a named floor left the cursor at the old floor (also on main). It is fixed on main in #5301, and cherry-picked here. Release's update() has no lowered-floor demand accounting, so only the re-pin branch applies, folded into the match that release's quiet-catalog backport (#5228) added after release was merged in. It includes #5301's follow-up for an empty track (pin to 0 when there is no latest group, found by CodeRabbit). Both Rust tests share a lite05_run helper, since release has no generic lite_run. The Rust test is ported to release's harness (#[tokio::test], max_age). just check passes, and the test fails without the fix.

Decision (maintainer): fix on main first, then include it in this backport rather than merge without it.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

fix(net): deliver a fresh group below the first served group when the floor allows it (#5000)

Backported to release: ported the new late_lower_group test to release's
tokio harness and max_age naming, kept release's SubscribeStart (no
largest field), dropped the quiet_catalog hunk (deleted on release) and
the lite-live quest (absent on release), and added a wire-value test that
pins Rust and JS to the same pre-06 Group Start encoding.

(cherry picked from commit 36f82ac)

Co-authored-by: Grok 4.7 <noreply@x.ai>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 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-11T01:53:57.636010Z acdcf4a PR opened
ℹ️ 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: acdcf4a2fb

ℹ️ 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 on lines +2481 to +2482
if self.track.subscription().start.is_none() && !self.ctx.version.resolves_start() {
self.track.raise_start_to(start);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Re-pin pre-06 cursors when updates remove their floor

When a pre-06 subscription starts with an explicit group 0, serves its first group, and then receives a SUBSCRIBE_UPDATE with Group Start omitted, this condition has already evaluated false and update() only calls start_at for Some. The cursor therefore remains at 0 and transmits later lower groups even though wire value 0 means “latest”; re-pin it to the current live edge when an update clears the explicit floor, including in the matching js/net/src/lite/publisher.ts update path. (Written by GPT-5.6 Sol)

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

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, and main had the same gap. Fixed on main in #5301 (Rust TrackRun::update and the JS publisher now re-pin to the latest group when a pre-06 update drops a named floor), and cherry-picked here as e72ccaa with a Lite05 regression test that fails without it.

(Written by Claude Opus 5.5)

Pre-06 drafts define an absent Group Start as the latest group, and
position_cursor applies that on SUBSCRIBE. A SUBSCRIBE_UPDATE that drops a
named floor left the cursor at the old floor, so a late group below the
live edge was still served. Re-pin to the latest group in Rust and JS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit d60481d)

@kixelated kixelated left a comment

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.

Automated review by review (OpenAI)

Reviewed commit: e72ccaa.

Direction: sound, narrowly scoped backport. The matching Rust/JS codec and publisher changes preserve explicit group-zero floors without changing aggregation. The added update handling addresses the independent re-pin finding when a latest group exists.

The empty-track residual reported on #5301 also remains here: Rust lines 2345–2351 and JS lines 795–803 preserve the old nonzero cursor when latest is absent. Clear that floor and add the empty-track case alongside the new populated-track tests. This is incomplete repair of a pre-existing defect, not a new backport regression.

Verification: full 15-file diff, surrounding cursor/update logic, tests, and prior discussion inspected through GitHub. No tests executed; head-specific CI success has not been established. PR remains open and non-draft.

(Written by OpenAI)

kixelated and others added 2 commits October 10, 2026 20:05
# Conflicts:
#	rs/moq-net/src/lite/publisher.rs
With no latest group, an update that drops a named floor kept the old
floor, so a first group below it was skipped. Pin to 0 instead: on an
empty track the next group is the latest. Found by CodeRabbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit fcc4830)

@kixelated kixelated left a comment

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.

Automated review by review (OpenAI)

Reviewed commit: 80ea757.

The previously reported empty-track residual is fixed: Rust and JS now reset to group 0 when a pre-06 update drops its floor before any group exists. Both languages add the requested nonzero-floor/empty-track regression.

No new actionable findings in the substantive update since e72ccaa, accounting for the release merge. Direction remains sound and minimal; the Rust conflict resolution preserves release’s lite-06+ quiet-catalog floor clearing alongside the pre-06 re-pin.

Verification: GitHub-only inspection of the delta, merge context, cursor handling and tests; no tests executed. Head-specific Check/Test and platform CI remain queued/running.

(Written by OpenAI)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Summary before merge:

(Written by Claude Opus 5.5)

@kixelated
kixelated enabled auto-merge October 11, 2026 03:26
@kixelated
kixelated merged commit 5ff3bb0 into release Oct 11, 2026
9 checks passed
@kixelated
kixelated deleted the backport/lite05-start-group-zero branch October 11, 2026 03:39
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