Skip to content

feat(lite): lite-07 carries an untimed track untimed - #5461

Merged
kixelated merged 3 commits into
mainfrom
quest/m1/lite-untimed
Oct 14, 2026
Merged

kixelated merged 3 commits into
mainfrom
quest/m1/lite-untimed

Conversation

@kixelated

@kixelated kixelated commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Quest: quest/m1/lite-untimed.md (deleted here, references removed).

Summary

On moq-lite-07-wip an untimed track now crosses the wire untimed in Rust and JS, so absence survives a lite relay hop:

  • TRACK_INFO Timescale is 0 for an untimed track. 0 was already invalid, so no shift or new field is needed.
  • FRAME omits Timestamp Delta and the DATAGRAM body omits Timestamp on an untimed track. The datagram body does not say which, so the decoder asks the subscription named by Subscribe ID, the same way FRAME already relies on TRACK_INFO.
  • lite-05/06 keep the documented downgrade: they declare 1000 and stamp each payload with its send time. A 0 there is still refused.

Rust (lite::Version::wire_timescale) and JS (wireTimescale) share one rule for the timescale a version carries. TRACK_INFO, SUBSCRIBE serving, FETCH serving, and datagrams all go through it, replacing the scattered unwrap_or(MILLI) fallbacks.

Draft: draft-lcurley-moq-lite.md describes the untimed encoding and the lite-05/06 downgrade, marks [Timestamp Delta] and [Timestamp] optional, drops "any varint value (including 0) is valid" and the "every frame carries a presentation timestamp" text, says an untimed group never expires, and adds lite-07 changelog entries. doc/concept/moq-lite.md is updated to match.

Public API and wire impact

  • Public API: none. lite::TrackInfo, lite::Datagram, and the JS lite wire classes are crate/package-internal.
  • Wire: lite-07-wip only, which is unpublished. lite-05/06 bytes are unchanged (checked by the existing cross-language TRACK_INFO byte test).

Tests

  • Regression tests that fail without the change: rs/moq-net/tests/untimed.rs now expects lite-07 to be faithful for frames, datagrams, and FETCH, plus a lite-07 to lite-07 relay chain. js/net/src/untimed.test.ts flips lite-07 to unstamped and adds an untimed datagram round trip on lite-06 and lite-07.
  • Codec unit tests in both languages: an untimed TRACK_INFO is 0 on lite-07 and milliseconds on lite-05/06, 0 is refused on lite-05/06, and an untimed datagram has no timestamp bytes.
  • Rust/JS byte interop (lite_varint_interop) now also round-trips an untimed datagram, an untimed GROUP with its frames, and an untimed TRACK_INFO on lite-06 and lite-07, in both directions.
  • Both encoders refuse an untimed datagram on lite-05/06, which have no untimed body (unit test in each language).
  • just check passes. just drafts check passes. just test interop --all passes on 8703633: 63 cells, 0 failures.

Decisions

  1. ✅ Timescale = 0 in TRACK_INFO is the untimed signal (maintainer accepted). It was already an invalid value and costs no bytes; no separate flag.
  2. ✅ The datagram body is not self-describing (maintainer accepted). The receiver learns timed or untimed from the subscription named by Subscribe ID, matching FRAME, rather than spending a flag byte on every datagram.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Local results on b7c477e:

  • just check: pass.
  • just drafts check: pass.
  • just test interop --all: 63 cells pass, including 24 moq-lite-07-wip sessions crossing lite-06 through the relay, so untimed catalog tracks went lite-07 to lite-06 and back. The byte-level lite_varint_interop (now with untimed datagram, GROUP, and TRACK_INFO) passes.
  • The 5 failures are the known main failure tracked by quest/m0/upgrade-unroutable.md: rust -> go and rust -> cpp and cpp -> python exit unroutable, rust -> c reports session status: 1 then times out, and the round then fails with a subscriber connection idling out. None of them involve a timestamp.

Open decisions for the maintainer (both kept as recommended in the PR body): Timescale = 0 as the untimed signal, and a datagram body that is not self-describing.

(Written by Claude Opus 5.5)

@kixelated
kixelated marked this pull request as ready for review October 13, 2026 22:49
kixelated and others added 2 commits October 13, 2026 15:49
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On moq-lite-07 an untimed track declares a Timescale of 0 in TRACK_INFO,
and its FRAME messages and datagrams omit the timestamp, so absence
survives a lite relay hop. lite-05/06 keep declaring milliseconds and
stamping send times, the documented downgrade for old peers.

Rust and JS share one rule, `wire_timescale` / `wireTimescale`, for the
timescale a version carries. The datagram decoder asks the subscription
whether a timestamp follows, since the body does not say.

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

coderabbitai Bot commented Oct 13, 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 3 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: 1cfba824-459e-41ee-9646-4db9adc6d365
📥 Commits

Reviewing files that changed from the base of the PR and between fb7310b and 8703633.

📒 Files selected for processing: 26
  • doc/concept/moq-lite.md
  • drafts/draft-lcurley-moq-lite.md
  • js/net/src/lite/datagram.test.ts
  • js/net/src/lite/datagram.ts
  • js/net/src/lite/publisher.ts
  • js/net/src/lite/subscriber.ts
  • js/net/src/lite/tail.test.ts
  • js/net/src/lite/track.test.ts
  • js/net/src/lite/track.ts
  • js/net/src/lite/version.ts
  • js/net/src/untimed.test.ts
  • quest/m1/README.md
  • quest/m1/lite-untimed.md
  • quest/m1/lite07-finalize.md
  • quest/m1/publish-timestamp.md
  • rs/moq-net/src/fuzz.rs
  • rs/moq-net/src/lite/datagram.rs
  • rs/moq-net/src/lite/publisher.rs
  • rs/moq-net/src/lite/subscriber.rs
  • rs/moq-net/src/lite/track.rs
  • rs/moq-net/src/lite/version.rs
  • rs/moq-net/src/model/frame.rs
  • rs/moq-net/src/model/track.rs
  • rs/moq-net/src/test_interop.rs
  • rs/moq-net/tests/untimed.rs
  • test/interop/lite-varint.ts
  • 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.

@kixelated
kixelated force-pushed the quest/m1/lite-untimed branch from 66546fa to e5dadbc Compare October 13, 2026 22:49
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 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-14T00:25:16.799072Z 8703633 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: 66546fac7b

ℹ️ 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".

w.varint(self.subscribe)?;
w.varint(self.sequence)?;
w.varint(self.timestamp)?;
if let Some(timestamp) = self.timestamp {

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 Reject untimed datagrams on lite-05/06

When timestamp is None with Lite05 or Lite06, this encoder silently omits a field that those versions require, so a compliant receiver consumes the first payload bytes as the timestamp and corrupts the payload or rejects it. The new lite_varint_interop test exercises exactly this invalid Lite06 encoding, and the mirrored JS encoder accepts it too, so the round trip hides the malformed wire data. Reject None before Lite07 rather than serializing it.

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

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.

Fixed in 8703633. Both encoders (Rust lite::Datagram and JS Datagram) now refuse a missing timestamp on lite-05/06, with a unit test each, and lite_varint_interop only exchanges untimed datagram and GROUP bytes on lite-07, asserting the lite-06 encode is refused.

(Written by Claude Opus 5.5)

Comment thread js/net/src/untimed.test.ts Outdated
Comment on lines +209 to +212
while (!stop) {
producer.appendDatagram(undefined, new Uint8Array([7]));
await new Promise((resolve) => setTimeout(resolve, 2));
}

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 Replace the wall-clock datagram pump

On a slow or loaded CI worker, this test repeatedly sleeps for 2 ms until subscription setup happens and has no bound if no datagram arrives. A regression can therefore leave the pump running indefinitely instead of producing a deterministic failure, and scheduler timing can make the test unnecessarily flaky. Synchronize subscription establishment or use mocked scheduling instead of polling wall-clock time.

AGENTS.md reference: AGENTS.md:L19-L19

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.

Fixed in 8703633. The test now writes one group and waits for the subscriber to read it, which proves the subscription is live end to end, then sends a single datagram. No timer or loop remains.

(Written by Claude Opus 5.5)

lite-05/06 always carry a datagram timestamp, so encoding one without it
produced bytes a receiver would misread. Both encoders now refuse it, and
the byte interop only exchanges untimed bytes on lite-07.

The JS untimed datagram test now waits for a group to prove the
subscription is live instead of pumping datagrams on a wall-clock timer.

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

Copy link
Copy Markdown
Collaborator Author

Merge summary for 8703633:

  • Decisions recorded in the body, both accepted by the maintainer: ✅ Timescale = 0 is the untimed signal, ✅ the datagram body is not self-describing.
  • Rebased onto main with fix(net): retire epochless handles only once their Restart is deliverable #5443. The draft (draft-lcurley-moq-lite.md) matches the encoding, and just drafts check passes.
  • Codex findings fixed in 8703633: both encoders now refuse an untimed datagram on lite-05/06, and the JS untimed datagram test no longer pumps on a wall-clock timer. Codex re-reviewed 8703633 with no findings.
  • Local: just check passes apart from moq-relay auth::refresh::tests::an_outage_refuses_transiently_and_never_extends_the_expiry, a known flake tracked by quest/m1/test-flakes-2/auth-refresh-expiry.md; a full rerun passed 6278/6278 Rust tests, plus 1805 js/net tests.
  • just test interop --all: 63 pass, 0 fail, including rust -> cpp and cpp -> c, which failed intermittently on the earlier rebased run. CI is green, including Interop.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit f2f0429 Oct 14, 2026
11 checks passed
@kixelated
kixelated deleted the quest/m1/lite-untimed branch October 14, 2026 02:44
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