Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions quest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ grouped into milestones ordered by priority.
## Plan

m0 is everything in flight now: relay hardening and the last known IETF
interop fix ahead of Seattle, wildcard routing, broadcast epochs, and audio playout (jitter target
and quality harness). m1 is the next wave across reliability, features, performance, and
interop fix ahead of Seattle, wildcard routing, broadcast epochs, and audio playout (the jitter target). m1 is the next wave across reliability, features, performance, and
planning. m2 holds later features, design studies, and experiments. m3 is
gated on the outside world (hardware, a partner, a consumer, or a provider's
offer) or is speculative work with no named consumer yet. m4 waits on an upstream release.
Expand Down
7 changes: 3 additions & 4 deletions quest/m0/wildcard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,9 @@ path, not with a route identity or a generation field.
advertised prefix MUST overlap the sender's granted patterns or it is
refused. A prefix wider than the grant is accepted, but it only routes
requests for paths the grant covers. Fleet-wide services use the cluster
identity; a customer service serves only what its own v1 grant contains.
Until [Advertise-only authorization](/quest/m3/processor/advertise-auth.md)
lands, the publish scope stands in for advertising; a credential with its own
advertise scope is checked against that instead.
identity; a customer service serves only what its own grant contains.
The publish scope authorizes advertising; there is no separate advertise
scope (dropped with the processor questline in the 2026-10-06 audit).
- **Claims are visible to subscribers.** A claim is an ordinary prefix
announcement, so it tells a client it may subscribe beneath it, and its
withdrawal tells the client the capability is gone. The browser player's
Expand Down
9 changes: 4 additions & 5 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ transport, benchmark tooling); worktrees isolate commits, not semantics.
A line with no named consumer waits in m3 until one appears; the 2026-10-05
audit moved P2P, ladder, processor, and timed metadata there from m2.

Decided in the 2026-10-05 audit: the clock chain ranks first (import at the
first frame, the HLS first catalog, typed timedness, the untimed models,
Decided in the 2026-10-05 audit: the clock chain ranks first (the untimed models,
CMAF frame timestamp, the shared clock, and the two publish-timestamp
quests), with FFI shape pulled up inside it because publishing never invents
a timestamp requires its JSON pilot. The hard fork follows, ahead of transport-seam and perf, and the rest
Expand Down Expand Up @@ -47,9 +46,10 @@ blocks. The quests that gated m0 lines moved under them.
- [main merges through a squash queue](/quest/m1/merge-queue-settings.md) - condition: once `release` carries the new back-merge script, the maintainer enables the squash merge queue and moq-bot's pull_request bypass together
- [Binding audio delay](/quest/m1/binding-surface.md) - moq-ffi and every wrapper configure and observe audio playout delay
- [moq-net owns its transport seam](/quest/m1/transport-seam.md) - moq-net names only its own transport traits, so a web-transport-trait or qmux major bump is a patch for it
- [Bump mp4-atom for avc3](/quest/m1/mp4-atom-avc3-bump.md) - this repository depends on mp4-atom 0.16.2, which reads and writes an `avc3` sample entry
- [fMP4 init from the catalog](/quest/m1/fmp4-catalog-init.md) - fMP4 export writes avc3/hev1 entries from the catalog, so an Annex-B H.264 or H.265 init no longer waits for the first keyframe
- [Delete the live marker](/quest/m1/announce-live-removal.md) - announce streams yield only route events; the `Live` marker and its hold machinery are gone
- [WebTransport close backends](/quest/m1/wt-close-backends.md) - web-transport-noq and -quinn keep the session alive while closing, and iroh's client reads a capsule close
- [WebTransport close backends](/quest/m1/wt-close-backends.md) - iroh's client reads a peer's capsule close, and moq-uring's HTTP/3 close task keeps the session alive until the capsule is sent
- [Enabled flag](/quest/m1/catalog-enabled.md) - one `enabled` rendition flag replaces `stalled` and pausing, and the flapping encoder-lag detector is deleted
- [Hang changelog](/quest/m1/hang-changelog-04.md) - the hang draft lists under -03 only what -03 published
- [SUBSCRIBE_DROP](/quest/m1/subscribe-drop.md) - every stream group in a lite subscription arrives or is dropped by name, and lite-07 drops its stream count for it
Expand Down Expand Up @@ -117,7 +117,6 @@ blocks. The quests that gated m0 lines moved under them.
- [TS AAC PCE joins](/quest/m1/ts-aac-pce-join.md) - PCE-described AAC over TS plays after a mid-stream join or resume, and a missing PCE silences only its track
- [FFI frame duration default](/quest/m1/ffi-frame-duration-default.md) - the binding audio encoder takes the codec's own frame by default, so `aac()` needs no explicit 0
- [mp4-atom dOps mapping](/quest/m1/mp4-atom-dops-mapping.md) - a released mp4-atom reads and writes any `dOps` channel mapping family and table
- [Bump mp4-atom for avc3](/quest/m1/mp4-atom-avc3-bump.md) - this repository depends on mp4-atom 0.16.2, which reads and writes an `avc3` sample entry
- [CMAF surround Opus](/quest/m1/cmaf-opus-surround.md) - fMP4 import and export carry an Opus channel mapping table
- [A self-hosted NVIDIA runner is registered](/quest/m1/gpu-runner.md) - the maintainer registers the host that runs the NVIDIA tests
- [GPU CI](/quest/m1/gpu-ci.md) - NVIDIA tests run nightly on a self-hosted GPU runner, and `just rs nvidia` runs them locally instead of skipping
Expand All @@ -129,7 +128,7 @@ blocks. The quests that gated m0 lines moved under them.
- [io_uring flow control](/quest/m1/uring-flow-control-windows.md) - the relay's io_uring workers honor the QUIC flow-control windows instead of refusing them
- [Own the QUIC stack](/quest/m1/quic/README.md) - quinn hard-forked in-tree as `moq-quic`, carrying BBR, reliable reset, hierarchical scheduling, peer limits, and endpoint sharding
- [QoS](/quest/m1/qos/README.md) - broadcast health: relay starvation and timeliness histograms
- [Catalog track alias](/quest/m1/catalog-track-alias.md) - catalog rendition keys become aliases with an optional `track` name, so one catalog lists renditions from several broadcasts
- [Catalog rendition IDs](/quest/m1/catalog-track-alias.md) - catalog rendition keys become IDs unique across video and audio, with an optional `track` name, so one catalog lists renditions from several broadcasts
- [Media stats](/quest/m1/stats/README.md) - publishers announce a stats track in the catalog, viewers answer a soliciting catalog through a per-catalog `.echo` broadcast, and one model turns both into a health verdict and a preflight report
- [JS track handover](/quest/m1/js-group-handover.md) - a JS track subscription resumes across a route swap from the first frame it lacks, so `test/drain` passes at zero latency budget
- [JS GOAWAY requests](/quest/m1/js-goaway-requests.md) - after GOAWAY the JS client opens no new request on the old session, like Rust
Expand Down
44 changes: 42 additions & 2 deletions quest/m1/archive/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,47 @@ follows by listing each timeline's keys after its cursor; `Reader::finish`
applies out-of-band finality. `rs/moq-archive/src/proof.rs` records one
multi-rendition broadcast end to end.

### Decisions

Moved from the deleted per-track timelines quest (2026-10-06 audit: its Rust
work landed in #4034 and its children are this line's own):

- One timeline track per track, live and recorded. `moq-mux` publishes them for
every broadcast; an unsubscribed track costs nothing.
- The catalog's root `archive` entry maps each track to its timeline, including
the catalog track itself. `replay`, `store`, and `version` stay beside it.
- Each track cuts on its own by one rule: at a group boundary between a
minimum and maximum duration (a 2s minimum today; 4s and a multiple of the
declared duration once
[declared duration](/quest/m1/archive/declared-duration.md) lands; a zero
minimum only for sparse data such as the catalog), splitting a long-lived
group by frame at the maximum. Manual cuts stay as an optimization, such as
a video keyframe cutting audio so derived segments need fewer objects.
- A stored object may hold a frame range of a group, not only whole groups.
- HLS and DASH segments are derived at the edge from group timestamps, not
from storage objects. Fetching extra objects is fine when they land in the
reader's cache for the next request.
- `moq-hls` never retries a failed timeline, because the origin already reconnects
transient source failures. A replacement publisher that restarts group
numbering is a publisher bug: a broadcast, track, or group name always means
the same content, and MoQ has no ETag-style invalidation
([#4556](https://github.com/moq-dev/moq/pull/4556)). A failed timeline
fails loud instead: the reference ends every playlist with `EXT-X-ENDLIST`,
and another rendition's playlist ends at its last covered segment rather than
listing gaps.
- HLS `EXT-X-TARGETDURATION` is fixed for the run, not the observed maximum
#4280 shipped. This reverses that PR's decision 4 (09-28 merged-PR audit).
The target comes from each timeline's declared duration, which replaces the
broadcast-wide `durationMax` (09-29 planning).

For triage, not blocking: two Codex P2s arrived after #4280 merged and are
unanswered. A timeline record whose `sequence` differs from its window index
is passed through unvalidated
([review](https://github.com/moq-dev/moq/pull/4280#pullrequestreview-5332725290)),
and `Timelines::track` re-enrolling a name while its old `Recorder` is alive
leaves two handles on one segmenter
([r4117516035](https://github.com/moq-dev/moq/pull/4280#discussion_r4117516035)).

### Format

The format is the draft's
Expand Down Expand Up @@ -118,8 +159,7 @@ owned by that prerequisite, not duplicated in archive storage.
- [Timelines declare their segment duration](/quest/m1/archive/declared-duration.md) - each timeline entry declares its segment duration (reported or estimated by the publisher), replacing the root `durationMax`
- [JS per-track timelines](/quest/m1/archive/js-timelines.md) - `@moq/hang` publishes the same per-track timelines as Rust (it already reads them)
- [Fixed HLS target duration](/quest/m1/archive/hls-target.md) - one `EXT-X-TARGETDURATION` for the run, from the reference timeline's declared duration; an overrun is listed with a warning
- [Per-track timelines](/quest/m1/archive/track-timeline.md) - every track segments and expires on its own timeline, and HLS is derived from group timestamps at the edge
- [Replay catalog](/quest/m1/archive/replay-catalog.md) - `moq import archive` publishes the recorded catalog live with `store` set, so stock `moq export hls` serves the whole replay
- [Replay catalog](/quest/m1/archive/replay-catalog.md) - `moq_archive::Reader` republishes the recorded catalog live with `store` set, so stock `moq export hls` serves the whole replay of `moq import archive`
- [Idle flush](/quest/m1/archive/flush.md) - idle tracks are recorded within a bounded wall-clock delay, and `flush()` forces a track's pending record out
- [Backward timestamps](/quest/m1/archive/backward-timestamps.md) - a resumed recording refuses a restarted source instead of dropping its groups or overlapping media time
- [HLS media sequence](/quest/m1/archive/hls-media-sequence.md) - `EXT-X-MEDIA-SEQUENCE` never decreases when the reference rendition switches
Expand Down
4 changes: 0 additions & 4 deletions quest/m1/archive/backward-timestamps.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,3 @@ The 2026-09-30 audit folded this into the recording writer, which landed
without it; the [#4034 review](https://github.com/moq-dev/moq/pull/4034#issuecomment-6005694031)
found the silent group drop. The archive format may break in place since it
is unreleased.

## Related

- [Per-track timelines](/quest/m1/archive/track-timeline.md) - reshapes the recovery this check reads
10 changes: 6 additions & 4 deletions quest/m1/archive/dvr.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ playlists keep serving for rewind and for players finishing the last
segments. The fall-through needs the recording to publish its catalog live,
since `moq-hls` subscribes to it rather than FETCHing it. Decided (09-29):
that republishing moves into `moq-archive`, so any host of the archive
behind the root claim does it, not only `moq-cli`; update [Replay
catalog](/quest/m1/archive/replay-catalog.md) to match.
behind the root claim does it, not only `moq-cli`, as [Replay
catalog](/quest/m1/archive/replay-catalog.md) now plans.

During live, rewind needs no handover: a recorded broadcast's live timeline
is durable, and every group it lists is promised available, so a seek past
Expand All @@ -51,10 +51,12 @@ numbers when the name moves from the live publisher to the archive.

## Required

- [Per-track timelines](/quest/m1/archive/track-timeline.md) - seeks through per-track timelines
- [Replay catalog](/quest/m1/archive/replay-catalog.md) - the recording publishes its catalog live, so `moq-hls` finds it after the handover
- [Wildcard](/quest/m0/wildcard/README.md) - the archive's root claim serves the source path once the live announcement ends

## Closes

- [#2275](https://github.com/moq-dev/moq/issues/2275) - close this issue when the quest finishes

## Related

- [Wildcard](/quest/m0/wildcard/README.md) - landed (#4403) the root claim that serves the source path once the live announcement ends
6 changes: 3 additions & 3 deletions quest/m1/archive/flush.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ Decided:
- The segmenter stays pure: it takes `now` as an input and exposes the next
wall-clock deadline at which a record must close. Callers arm the timer. The
moq-archive writer uses tokio time; moq-mux's `Recorder` must stay wasm-safe
(moq-mux builds for wasm32), so it uses moq-net's runtime `Timer` or
`web_async` time, never `tokio::time`.
(moq-mux builds for wasm32), so it uses `web_async` time, never
`tokio::time` (moq-net's runtime `Timer` went away in #4437).
- Manual flush is per track: `Control::flush(name)` on the writer, beside the
broadcast-wide `cut`, and `Recorder::flush()` on a timeline.
- JS mirrors it: `@moq/hang`'s `Timeline.Recorder` gets the same idle
Expand All @@ -39,4 +39,4 @@ Decided:

## Required

- [Per-track timelines](/quest/m1/archive/track-timeline.md) - the per-track segmenter, writer, and JS recorder this extends, so the flush lands on the per-track shape rather than the aligned one it replaces
- [JS per-track timelines](/quest/m1/archive/js-timelines.md) - the JS `Timeline.Recorder` this extends; the Rust per-track segmenter and writer are already on `main` (#4034)
4 changes: 0 additions & 4 deletions quest/m1/archive/hls-target.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,3 @@ keeps the original target.
## Required

- [Timelines declare their segment duration](/quest/m1/archive/declared-duration.md) - the declared value the target is taken from

## Related

- [Per-track timelines](/quest/m1/archive/track-timeline.md) - the quest this blocks
9 changes: 6 additions & 3 deletions quest/m1/archive/replay-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ this by hand-building a catalog.
recording format. Refuse a URL carrying userinfo and strip its query so
credentials never land in a catalog, and let the importer opt out of
advertising the URL at all. `replay` stays unset: the timelines live on this broadcast.
- Keep the logic in `moq-cli`; `moq-archive` stays catalog-agnostic. Select the
catalog track with the CLI's catalog format as `export archive` does: hang
and hang.z are stamped, MSF is refused.
- The logic lives in `moq-archive` (`moq_archive::Reader`), so any host of
the archive behind the root claim republishes and stamps the catalog, not
only `moq-cli` (decided 09-29 in [DVR rewind](/quest/m1/archive/dvr.md)).
`moq-cli` only passes the URL and the opt-out. Select the catalog track by
catalog format as `export archive` does: hang and hang.z are stamped, MSF
is refused.
- The recorded catalog's `archive` entry describes the source's live
timelines, not the recording's, so replace it with the timelines the reader
replays rather than trusting the recorded ones.
Expand Down
71 changes: 0 additions & 71 deletions quest/m1/archive/track-timeline.md

This file was deleted.

Loading
Loading