Skip to content

docs(drafts): spec the timeline track and compressed catalog in moq-hang - #2732

Merged
kixelated merged 2 commits into
mainfrom
hang-draft-catalog-sync
Aug 10, 2026
Merged

docs(drafts): spec the timeline track and compressed catalog in moq-hang#2732
kixelated merged 2 commits into
mainfrom
hang-draft-catalog-sync

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

The hang draft had drifted from the implementation. The catalog code (rs/hang/src/catalog, js/hang/src/catalog) carries a per-rendition timeline field pointing at a companion timeline track, and publishes a compressed catalog.json.z sibling, but draft-lcurley-moq-hang documented neither. This reconciles the draft with the implementation as the source of truth:

  • Timeline section: the per-rendition Timeline catalog schema (track, timescale defaulting to 1000, wall anchored to the 2020-01-01 moq epoch) and the timeline track format (a single never-rolled compressed group of {group, pts} JSON records, appended at group open, duration implicit, optional granularity throttling). Matches rs/hang/src/catalog/timeline.rs, rs/hang/src/timeline.rs, and the moq-mux timeline producer/consumer.
  • Compression section: the shared-window sync-flushed raw DEFLATE framing (RFC 1951 with the RFC 7692 trailing-marker trick) used by the .z tracks, matching moq-flate.
  • Common rendition fields: add timeline alongside broadcast/container/jitter.
  • Catalog: note the catalog.json.z sibling a publisher SHOULD also serve.

Notably not touched: the text root section, which was already cleanly reverted from both the draft and the implementation on main by #2571 (it lives on dev), so draft and code agree there.

Docs-only; no wire change (the draft catches up to what already ships). No changelog appendix exists in this draft, so none updated.

Testing

  • nix develop --command just drafts check (kramdown-rfc parses all drafts)
  • nix develop --command bun run --cwd doc check (VitePress renders the generated /draft/ pages; drafts.test.ts passes, only existing kramdown constructs used)

(written by Fable 5)

🤖 Generated with Claude Code

The hang implementation publishes a per-rendition timeline (the Timeline
catalog section on VideoConfig/AudioConfig plus the companion track of
{group, pts} records) and a compressed catalog.json.z sibling, but the
draft documented neither. Add a Timeline section (catalog schema, wall
clock anchor, track format), a Compression section (the shared-window
sync-flushed DEFLATE framing both .z tracks use), the timeline common
rendition field, and the compressed catalog sibling.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 40beb132-0d44-40d2-b812-b79e9f2a7f77

📥 Commits

Reviewing files that changed from the base of the PR and between 3b44f17 and a087bf9.

📒 Files selected for processing (1)
  • drafts/draft-lcurley-moq-hang.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • drafts/draft-lcurley-moq-hang.md

Walkthrough

The draft adds a recommended compressed catalog.json.z track and lets consumers select the compressed or uncompressed catalog track. Renditions can declare an optional companion timeline track. The draft defines the Timeline schema, timestamp mapping, wall-clock anchoring, live-edge updates, implicit durations, throttling, and raw-DEFLATE encoding for timeline records.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the timeline track and compressed catalog changes in the draft specification.
Description check ✅ Passed The description directly explains the documentation changes, implementation alignment, scope, and validation performed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch hang-draft-catalog-sync

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@drafts/draft-lcurley-moq-hang.md`:
- Around line 392-396: The timeline specification must reconcile throttled
record emission with its duration model: define how consumers determine or
interpolate omitted group boundaries when consecutive emitted records span
multiple groups, including lookup rules, and specify how the final record
without a following PTS represents the live edge. Update the surrounding
group-duration and sequence-number semantics accordingly.
- Around line 358-374: The Timeline contract must require timescale to be a
positive integer and define how legacy microsecond media timestamps are
converted to Timeline.pts using the declared timescale, including the required
rounding rule. Update the Timeline documentation near the timescale and pts
definitions, including the related section around the legacy container timestamp
handling, so publishers and consumers use identical conversion semantics.
- Around line 104-106: Update the catalog track description to explicitly define
that catalog.json.z contains the same group-ordered snapshot and RFC 7396 JSON
Merge Patch delta framing as catalog.json, with only compression differing.
Specify the consumer behavior when the compressed track is unavailable,
including fallback to catalog.json.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7140fb4c-67b6-404a-b143-6c1b3ee3502f

📥 Commits

Reviewing files that changed from the base of the PR and between 7de545f and 3b44f17.

📒 Files selected for processing (1)
  • drafts/draft-lcurley-moq-hang.md

Comment thread drafts/draft-lcurley-moq-hang.md Outdated
Comment thread drafts/draft-lcurley-moq-hang.md
Comment thread drafts/draft-lcurley-moq-hang.md Outdated

@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: 3b44f17f9e

ℹ️ 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 drafts/draft-lcurley-moq-hang.md Outdated
Comment thread drafts/draft-lcurley-moq-hang.md Outdated
Comment thread drafts/draft-lcurley-moq-hang.md Outdated
Fix the timeline track's placement (it follows the rendition's broadcast
field, matching the moq-hls consumer), require a positive timescale
(Timescale is NonZero and the consumer errors on 0), state the round-down
pts conversion (Timestamp::as_scale truncates), bound timeline integers
to 2^53-1 (the JS schema's u53), define record spans under throttling
plus the live-edge semantics of the last record, and note the compressed
catalog shares the plaintext track's group/frame rules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kixelated
kixelated enabled auto-merge (squash) August 10, 2026 22:38
@kixelated
kixelated merged commit 76754d6 into main Aug 10, 2026
1 check passed
@kixelated
kixelated deleted the hang-draft-catalog-sync branch August 10, 2026 22:39

@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: a087bf9097

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

Measuring from 2020 rather than 1970 keeps the values small.
A consumer derives the wall-clock time of any group as `wall + pts`.

Timeline integers (`timescale`, `wall`, and each record's `pts`) MUST NOT exceed 2^53 - 1, so they survive JSON consumers that parse numbers as IEEE 754 doubles.

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 Cap timescale at the supported Rust width

When a publisher chooses timescale = 2^32, the value is permitted by the new 2^53 - 1 ceiling and accepted by the JS TimelineSchema, but rs/hang/src/catalog/timeline.rs::Timeline.timescale is a u32, so Rust rejects the entire catalog during deserialization. Cap this field at 2^32 - 1, or widen the Rust field before standardizing larger values. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L178-L178

Useful? React with 👍 / 👎.


The `wall` field anchors the timeline to the wall clock, if known: the wall-clock time of timestamp 0, in `timescale` units since the moq epoch, 2020-01-01T00:00:00Z (1577836800 Unix seconds).
Measuring from 2020 rather than 1970 keeps the values small.
A consumer derives the wall-clock time of any group as `wall + pts`.

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 Bound the required wall-clock sum

When both operands approach the new ceiling, the required wall + pts calculation can leave JavaScript's safe-integer range even though each operand conforms; for example, (2^53 - 1) + 2 is rounded. The new individual-value bound is fresh evidence that the previously reported arithmetic issue remains, so constrain the sum rather than only its operands or consumers can derive an incorrect wall-clock time. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L178-L178

Useful? React with 👍 / 👎.


~~~
type Record = {
"group": number,

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 Include group IDs in the JSON-safe bound

When a Rust publisher uses an explicit group sequence above 2^53 - 1, which moq_net::track::Producer::create_group accepts, this JSON number loses precision in double-based consumers because group is omitted from the safe-integer rule. A rounded value identifies a different group for subscription or fetch, so constrain group alongside pts or encode it losslessly. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L178-L178

Useful? React with 👍 / 👎.

~~~

The `group` field is the sequence number of the media track's group, as used by subscriptions and fetches.
The `pts` field is the group's start, its first frame's presentation timestamp, re-expressed in the timeline's `timescale` (rounding down when the media clock is finer).

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 Require recorded PTS values to advance

When two recorded groups open within one tick of the chosen timeline timescale, rounding down gives both records the same pts. The span rule below then creates a zero-length boundary and cannot uniquely map a target time to a record. Require successive emitted records to have strictly increasing pts by choosing sufficient resolution or coalescing/skipping collisions. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L178-L178

Useful? React with 👍 / 👎.

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