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/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ session outcomes, and embedder refusals inside session outcomes.
- [Per-frame arrivals in @moq/watch](/quest/m1/watch-arrivals.md) - the audio and video decoders expose a window of recent frame arrivals, late and skipped marks included, as a signal
- [Bump web-transport-iroh for the capsule close](/quest/m1/iroh-capsule-bump.md) - condition: moq-dev/web-transport#419 ships in a release, then moq's iroh HTTP/3 client reports a peer's close capsule
- [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
- [lite-07 Live flag](/quest/m1/lite-live.md) - a separate `Live` field on lite-07 SUBSCRIBE, so merged floors never starve a subscriber; late lower groups build on it
- [Subscribe ranges](/quest/m1/subscribe-ranges/README.md) - a lite-07 SUBSCRIBE asks for past and live ranges in either order and replaces FETCH; relays fill misses by range, including over moq-transport
- [Subscribe ranges](/quest/m1/subscribe-ranges/README.md) - a lite-07 SUBSCRIBE asks for past and live ranges with absolute or relative ends, in either order, and replaces FETCH; merged ranges never starve a subscriber; relays fill misses by range, including over moq-transport
- [Reproduce cross-node announce flapping](/quest/m1/cross-node-flapping.md) - a clean close reaches a client on another node as one retraction, checked by a 3+ relay drill on main
- [Untimed lite-07](/quest/m1/lite-untimed.md) - lite-07 carries an untimed track in both languages; lite-05/06 write send time
- [A watch and publish release ships assets()](/quest/m1/assets-release.md) - the release that lets the sites host the worklets
Expand Down
2 changes: 1 addition & 1 deletion quest/m1/cache-max-age.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ encoding change; Max Age semantics in the lite draft change.

## Related

- [lite-07 Live flag](/quest/m1/lite-live.md) - its untimed `Live` start (the latest group) follows this rule instead: replay what is not stale
- [Model ranges](/quest/m1/subscribe-ranges/model.md) - an untimed `Absolute(0)..` range follows this rule: replay what is not stale
- [JS track handover](/quest/m1/js-group-handover.md) - mirrors the failover rule in JS
- [Generated @moq/net](/quest/m1/rs2ts/README.md) - retires js/net's hand-written model
- [FETCH max-delay](/quest/m1/fetch-max-delay.md) - applies the shared rule to historical requests and reconciles native IETF retention clocks
93 changes: 0 additions & 93 deletions quest/m1/lite-live.md

This file was deleted.

1 change: 0 additions & 1 deletion quest/m1/lite07-finalize.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ is published; older versions are unchanged.

## Required

- [lite-07 Live flag](/quest/m1/lite-live.md) - SUBSCRIBE carries `Live` apart from its floor
- [In-band auth](/quest/m1/auth/README.md) - lite-07 carries the Auth Stream and UNAUTHORIZED (0x3B)
- [Routes and announces](/quest/m1/cluster-routing/routes.md) - lite-07 carries the route layer: ROUTE per origin node and path-less ANNOUNCE, with the hop list gone
- [SUBSCRIBE_DROP](/quest/m1/subscribe-drop.md) - lite-07 restores SUBSCRIBE_DROP in place of `Stream Count`
Expand Down
1 change: 0 additions & 1 deletion quest/m1/pipeline-requests/subscribe.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,5 @@ blocks the Related quests below; whichever lands second rebases.
## Related

- [Pipelined first FETCH](/quest/m1/pipeline-requests/fetch.md) - the same change for fetch-only readers
- [lite-07 Live flag](/quest/m1/lite-live.md) - reshapes the same SUBSCRIBE fields
- [One max_age meaning](/quest/m1/cache-max-age.md) - the staleness rule that makes the wire clamp redundant
- [Lite-07 ranges](/quest/m1/subscribe-ranges/lite.md) - replaces the SUBSCRIBE floor with ranges
23 changes: 17 additions & 6 deletions quest/m1/subscribe-ranges/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Decided in planning (09-29), after the fetch-span agent (#4558) found that a
relay bounds a sparse FETCH only if the model can request ranges:

- **Wire (lite-07, unpublished).** SUBSCRIBE carries a list of group ranges
(an open end means live) in place of Group Start/End, plus
(an open end means live; ends may be relative, below) in place of Group Start/End, plus
`order: asc | desc` (desc, newest first, is today's rule and the default).
Subscriber Max Age (the model's `max_delay`) stays as a cap alongside the
ranges, since a group's timestamp isn't always known. Decided 2026-10-10:
Expand All @@ -43,10 +43,22 @@ relay bounds a sparse FETCH only if the model can request ranges:
group's existing prefix but never wait for its future objects. Downstream,
an IETF FETCH is served from the model's ranges, capped at the Largest
Object.
- The `Live` flag from [lite-07 Live flag](/quest/m1/lite-live.md)
stays a separate field beside the range list (maintainer, 10-07): a range
starting above the live edge must not hide the latest group from a
subscriber merged with it.
- **Relative ends** (maintainer, 2026-10-11, superseding the 10-07 `Live`
flag and closing #5085). Each range end is `Absolute(group, frame)` or
`Relative(n)`, naming the group n before the latest; either end may be
relative, and an omitted end is live. An offset past the track's start
clamps to group 0. Before any group exists, relative ends resolve when the
first one arrives, so `Relative(0)..` starts at it. The cross-language and
bridge tests cover both edges. Ends are inclusive of whole groups:
a relative start resolves to frame 0 of that group, and a relative end to
just after its last frame (the model's exclusive `Position::after_group`),
so `Absolute(0)..Relative(0)` includes the latest group. Live is `Relative(0)..`, so no separate `Live` field exists.
Merging subscribers is the union of their ranges, so a range above the
live edge never hides the latest group from a merged live subscriber,
which is the starvation the flag existed to prevent. Subscriber Max Age
still caps every range, so `Absolute(0)..` means everything not stale.
A relay that cannot resolve a relative end locally forwards it upstream as
relative.
- Ranges are frame-precise (`Position`), not whole groups. The IETF joining
FETCH for a mid-group SUBSCRIBE's uncached prefix stays, because today's
bridge relies on it (maintainer, 09-29).
Expand All @@ -59,7 +71,6 @@ every sequence delivered or dropped.

## Required

- [lite-07 Live flag](/quest/m1/lite-live.md) - the `Live` field the range list sits beside
- [Model ranges](/quest/m1/subscribe-ranges/model.md) - `Subscription` carries ranges and order, and `Dynamic` fills misses by range
- [SUBSCRIBE_DROP](/quest/m1/subscribe-drop.md) - publishers name every group they won't deliver
- [Lite-07 ranges](/quest/m1/subscribe-ranges/lite.md) - the lite-07 wire, Rust publisher and subscriber, and the draft
Expand Down
25 changes: 24 additions & 1 deletion quest/m1/subscribe-ranges/lite.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,30 @@ lite upstream by subscribing to the missing ranges.

## Plan

Each range end encodes `Absolute(group, frame)`, `Relative(n)`, or open, and
a SUBSCRIBE with no ranges is refused. Older wires map at the codec only, with
no change to a published version: lite-06 `Group Start` 0 with `Frame Start`
0, and pre-06 absent, are `Absolute(0)..` capped by max age (the oldest group
not yet stale); any other lite-06 pair is an absolute start. When merged
ranges can't be expressed on an older upstream wire, subscribe from group 0
and filter locally; lite-03 to 05 must send an explicit group 0, since the
codec folds 0 to absent (`encode_start_group`), which they read as the latest
group. moq-transport's relative offsets differ by one: draft-20
`Relative(0)` is the next group and `Relative(1)` the current one, so an
open-ended `Relative(n)..` maps to draft-20 `Relative(n + 1)`, saturating
(an offset past the track's start clamps to group 0 either way). Older
drafts only encode a relative 0, so there it is SUBSCRIBE plus a relative
joining FETCH n groups back, as the live join already does. That filter
has no end, so a range with a bounded end resolves both bounds against the
Largest Object and goes upstream as an absolute range. Live keeps today's
Comment on lines +26 to +27

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 Define the empty-track bounded-end bridge

When an empty upstream track receives Absolute(0)..Relative(0), these bounds cannot be resolved against Largest Object because none exists, while ietf::Filter cannot encode a relative upper bound (rs/moq-net/src/ietf/filter.rs:13-15). The README fallback of forwarding the endpoint as relative therefore cannot preserve the cap. Unlike the earlier empty-track live-start comment, the fresh case here is a bounded relative upper endpoint: define a temporary live join that is canceled after resolution, or explicitly refuse the request, so implementations do not widen it into a permanent live subscription. (Written by GPT-5.6 Sol)

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.

This is already covered by the general fallback in this file: when merged ranges can't be expressed upstream, the relay subscribes and filters locally. With an empty upstream, the relay holds an upstream subscription and resolves Relative(0) locally once the first group arrives. It ends the downstream range there and drops the upstream subscription when no other range needs it. Nothing becomes a permanent live subscription for that subscriber, and the implementation PR's bridge tests pin it.

(Written by Claude Opus 5.5)

join, `NextObject` plus a `Relative(1)` fill on draft-20+ or a relative
Comment on lines +20 to +28

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 Preserve latest-group semantics across the transport bridge

When a subscription arrives after group N is created but before its first frame, this mapping does not preserve the new lite semantics: rs/moq-net/src/ietf/publisher.rs::live_edge walks back to the previous group for Largest Object, and filter_range anchors both Relative(1) and the NextObject plus fill join there, while lite Relative(0) is defined against the publisher's latest group N. The fresh evidence beyond the earlier offset review is this explicitly handled empty-newest-group state, where the bridge can deliver group N-1 even though the lite range begins at N. Define an exact translation for this state or refuse it rather than silently widening the range.

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.

Defined rather than refused. A relative end resolves against the latest group the answering hop knows. Behind an IETF upstream, that's the Largest Object's group, so a relay that hasn't seen an object in N yet treats N-1 as latest. Nothing is widened from that hop's view, and N arrives through the NextObject join once its first object does. Refusing would fail every live join at a group boundary, and waiting for the peer breaks the rule that relays report current state.

(Written by Claude Opus 5.5)

joining FETCH on older drafts (`ietf::subscriber::subscribe_join`), so the
current group's existing prefix still arrives. A relative end resolves
against the latest group the answering hop knows. Behind an IETF upstream
that is the Largest Object's group, so a newest group with no objects yet is
not counted until its first object arrives; the relay reports what it has
rather than waiting for the peer.

Update `drafts/draft-lcurley-moq-lite.md` in the same PR: the SUBSCRIBE and
SUBSCRIBE_UPDATE fields, the Group Order section (the order is now a field),
the removal of FETCH, and the lite-07 changelog. Fix the stale "offset by 1"
Expand All @@ -20,6 +44,5 @@ FETCH, answered through the model's ranges. Run `just drafts check` and

## Required

- [lite-07 Live flag](/quest/m1/lite-live.md) - reshapes the same SUBSCRIBE first
- [Model ranges](/quest/m1/subscribe-ranges/model.md) - the model this serves
- [SUBSCRIBE_DROP](/quest/m1/subscribe-drop.md) - lite-07's DROP for holes
24 changes: 17 additions & 7 deletions quest/m1/subscribe-ranges/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,23 @@ requests for misses instead of one request per group.
See the [line](/quest/m1/subscribe-ranges/README.md) for the decisions.
Guidance:

- Aggregating several subscribers' ranges and orders onto one upstream
request needs a rule. For example, the union of ranges, and desc wins when
orders conflict. Decide it and write it down.
- Ranges have `Absolute` or `Relative` ends (see the line). Aggregating
subscribers onto one upstream request is the union of their ranges; a
relative end resolves against the track's latest group when the publisher
serves it. Decide and document the order rule when orders conflict (for
example, desc wins).
- This absorbs the deleted lite-07 Live flag quest, so the model mirrors the
wire with no `live` field, and its tests move here, on mock time and both
in-process and through a relay: a subscriber from `Absolute(4)` merged with
a `Relative(0)..` subscriber on a quiet track whose newest group is 3 (the
live one still gets group 3); a buffering `Relative(k)..` merged with a
range above the live edge; a frame-precise start merged with live; an
untimed `Absolute(0)..` (it follows
[One max_age meaning](/quest/m1/cache-max-age.md)); and the lite-05 relay
case #5000 left out: a live subscriber already reading group 1, then one
from `Absolute(0)`, and a fresh group 0 reaches only the second. The closed
#5085 branch has reusable pieces (older-wire codec mappings, the JS fix
keeping groups below a floor buffered, mocked-time tests).
- Replace `requested_group` and `fetch_group` rather than keep both. Update
every caller (relay, moq-archive, hls, the ladder) in the same PR, plus the
published surfaces built on them, per the cross-package table: moq-ffi
Expand All @@ -32,10 +46,6 @@ Guidance:
enforcement; reuse its contract rather than restoring a historical exemption.
- Benchmark range count and span as separate axes (AGENTS.md fan-out rule).

## Required

- [lite-07 Live flag](/quest/m1/lite-live.md) - reshapes the same `Subscription` first

## Related

- [FETCH max-delay](/quest/m1/fetch-max-delay.md) - historical request budgets and per-caller enforcement
Loading