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
10 changes: 8 additions & 2 deletions quest/m0/nightly/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# [S] Nightly passes on main
# Nightly passes on main

## Goal

Expand All @@ -16,7 +16,7 @@ Decided 2026-10-24 (maintainer), from a triage of run
child per distinct cause, each landing on its own. The PR gate keeps
skipping benches and examples; a green Nightly catches them within a day.

This README's own work:
This README's own work, after the children:

- Nightly's multi-step jobs (Features first) keep going past a failed step
and fail at the end, so one break never hides the steps after it.
Expand All @@ -30,3 +30,9 @@ This README's own work:
[moq-dev/moq#6656](https://github.com/moq-dev/moq/pull/6656).

Public API: none. Wire: none.

## Required

- [Windows builds moq-relay tests](/quest/m0/nightly/windows-relay-expect.md) - an unfulfilled lint expectation stops failing the Windows build
- [OBS audio-candidate test](/quest/m0/nightly/obs-audio-candidate.md) - the failed audio candidate check passes under TSan and load, fixed at its reproduced cause
- [Feature shapes per crate](/quest/m0/nightly/hls-poll-closed-gate.md) - moq-hls `Broadcaster::poll_closed` is gated on `server`, and the gate checks each crate's feature shapes in isolation
24 changes: 24 additions & 0 deletions quest/m0/nightly/hls-poll-closed-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# [XS] Feature shapes are checked per crate

## Goal

`cargo check -p moq-hls --no-default-features --all-targets` passes with
warnings denied, and the PR gate checks each selected crate's feature shapes
in isolation, so dead code behind a feature fails the PR that adds it.

## Plan

moq-hls `Broadcaster::poll_closed` (`rs/moq-hls/src/export/mod.rs:164`) is
dead under `--no-default-features`: its only caller is the `server` feature's
eviction loop. Gate it with `#[cfg(feature = "server")]`.

Neither the gate from
[moq-dev/moq#6703](https://github.com/moq-dev/moq/pull/6703) nor Nightly
catches it: workspace feature unification turns `server` on, because moq-cli
depends on moq-hls with it. Only an isolated moq-hls build shows the warning.
Make the gate build each selected crate's feature shapes on its own (`-p` per
crate, not one unified build), and measure the added cost in the PR.

Found 2026-10-25 for the feature-shapes quest, which #6703 finished first.

Public API: none. Wire: none.
27 changes: 27 additions & 0 deletions quest/m0/nightly/obs-audio-candidate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# [S] OBS audio-candidate test passes under TSan and load

## Goal

`cpp/obs/test/moq-source-test.cpp`'s "failed audio candidate preserves
playback" passes under OBS TSan every night and under load. On 2026-10-25 its check
`ctx->connection->audio && !ctx->connection->pending_audio` failed with no
TSan report. [moq-dev/moq#6711](https://github.com/moq-dev/moq/pull/6711) also
saw it fail intermittently under load, on its base commit too.

## Plan

The cause is not known yet. It is not the counter racing the clear: the
"Audio track error" log that bumps `g_candidate_failures` and the
`pending_audio` clear both run under `ctx->mutex`, which the check then takes.
But the counter is global, also bumped by any "Failed to resolve" or "Failed
to subscribe", and the check also needs the active `audio` to survive.
Reproduce first, under TSan or under CPU pressure or `SIGSTOP`/`SIGCONT`
pauses as [moq-dev/moq#6737](https://github.com/moq-dev/moq/pull/6737) did.
Find which conjunct fails and which track and error bumped the counter, then
fix that cause. If the wait is too broad, make it wait on the replacement's
own failure. Do not add a retry or a sleep.

Planned 2026-10-25 (maintainer) from the triage of Nightly run
[40192013303](https://github.com/moq-dev/moq/actions/runs/40192013303).

Public API: none. Wire: none.
23 changes: 23 additions & 0 deletions quest/m0/nightly/windows-relay-expect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# [XS] Windows builds moq-relay's tests

## Goal

Nightly's Windows job builds and runs the test suite again. Since 2026-10-25,
`cargo test --no-run` fails there with "this lint expectation is unfulfilled"
at `rs/moq-relay/src/relay.rs:871`.

## Plan

The module-level `#[expect(clippy::disallowed_methods)]` on moq-relay's
`mod tests` only hits on Unix, because the host-clock tests are `cfg(unix)`.
`build.warnings=deny` makes the unfulfilled expectation an error. Scope the
`expect` to the Unix-only tests, or use `cfg_attr(unix, expect(...))`.

In the same PR, gate or remove the two moq-video items that are dead on
Windows (`pump.rs` `Read::Idle` and `from_bgra`). They warn today and will
fail the build the same way.

Planned 2026-10-25 (maintainer) from the triage of Nightly run
[40192013303](https://github.com/moq-dev/moq/actions/runs/40192013303).

Public API: none. Wire: none.
2 changes: 2 additions & 0 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ divergences, under one epic; its redesign proposals went to m2.
- [Compressed tracks](/quest/m1/compress/README.md) - a track flagged `compress` is DEFLATEd per group by moq-net, forwarded compressed, and inflated once on the relay for peers that cannot signal it; `catalog.json.z` and moq-flate go away
- [Finalize moq-lite-07](/quest/m1/lite07-finalize.md) - when the maintainer cuts it, lite-07 negotiates as `moq-lite-07` and the next release ships it
- [Moxygen minimal interop](/quest/m1/smoke-moxygen.md) - waiting on Moxygen to send a registered filter type, then the smoke lane stops hiding its failure
- [Moxygen pin bump](/quest/m1/moxygen-pin-bump.md) - waiting on moxygen#264, then the TRACK_STATUS patch is dropped
- [More tests under load](/quest/m1/test-flakes-2/README.md) - the second round of load-only failures, one quest per flake, fixed at the cause
- [Broadcast lifecycle](/quest/m1/broadcast-lifecycle/README.md) - broadcasts are online or offline with no finished state in moq-net, finished-broadcast retention is a fixed moq-mux policy, and each linger timer has one meaning
- [A smaller, safer API than release](/quest/m1/api-audit/README.md) - every surface added since release has a consumer or is gone, overlapping operations are collapsed, names mirror across Rust, JS, and the bindings, and every break says how to migrate
Expand Down Expand Up @@ -151,6 +152,7 @@ divergences, under one epic; its redesign proposals went to m2.
- [Calibrate the paired nightly benchmarks](/quest/m1/bench-ci.md) - A/A and deliberately slowed Nightly runs set the paired comparison's threshold, so its regression alerts can be trusted
- [HLS takeover leak](/quest/m1/hls-takeover-leak.md) - a replaced instance's recording cursor never yields the replacement's media, and ends or fails instead of stalling
- [HLS and DASH segment conformance](/quest/m1/hls-conformance.md) - nightly ffprobe checks that advertised timing, sync flags, and bytes match the media served
- [HLS import log redaction](/quest/m1/hls-log-redaction.md) - no HLS import log line carries an unredacted playlist URL
- [Unbounded groups](/quest/m1/unbounded-groups/README.md) - groups and frames lose their size caps; the cache sheds parts of a group under pressure and refills the holes in place
- [Bindings decode media as media](/quest/m1/obs-data-decode.md) - moq-ffi decodes a media rendition with its kind, so OBS stops losing every other group
- [Relay demand gaps](/quest/m1/relay-demand-gaps.md) - pre-07 backlog, IETF warm-relay newcomer, and double upstream pulls are fixed or ruled out
Expand Down
1 change: 1 addition & 0 deletions quest/m1/api-audit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Rejected in planning:
- [Binding publications](/quest/m1/api-audit/binding-publication.md) - moq-ffi, the C ABI, and every wrapper hand out a publication handle that announces, replacing the private adapters
- [Bindings read gaps and ends](/quest/m1/api-audit/decode-read-bindings.md) - moq-ffi and every wrapper surface `Gap` and `End` instead of discarding them
- [Session-only items stay private](/quest/m1/api-audit/model-private.md) - model items only the built-in sessions use are private
- [Encoded consumers read gaps and ends](/quest/m1/api-audit/encoded-read-bindings.md) - moq-ffi, moq-c, and every wrapper read encoded media with the tagged-record shape the decoded consumers use
- [One lifecycle vocabulary](/quest/m1/api-audit/lifecycle.md) - finish, abort, closed, and close mean one thing on every handle, and Rust and JS observers fire alike
- [moq-net names say one thing](/quest/m1/api-audit/net-names.md) - demand says `wanted`, colliding stats and transport names are renamed, and Rust and JS info lookups mirror
- [Request handlers are named requests](/quest/m1/api-audit/requests.md) - `dynamic()` and `Dynamic` become `requests()` and `Requests` at every layer
Expand Down
19 changes: 19 additions & 0 deletions quest/m1/api-audit/encoded-read-bindings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# [M] Encoded consumers read gaps and ends

## Goal

The encoded media consumers in moq-ffi (`MoqMediaTrackConsumer`), moq-c's
`moq_consume_*` reads, and their wrappers surface `Gap` and `End` with the same
tagged-record read shape the decoded consumers got in
[moq-dev/moq#6745](https://github.com/moq-dev/moq/pull/6745), instead of
discarding them.

## Plan

Decided 2026-10-25 (maintainer, on #6745): the decoded consumers keep the
tagged-record shape as landed, and the encoded consumers follow in their own
quest. Mirror #6745 exactly: the same record names, the same end semantics,
and the same wrapper idioms in py, swift, kt, go, dart, cpp, and cpp/obs.
Update `doc/lib/*` and run `just test interop --all`.

Public API: breaking in moq-ffi, moq-c, and every wrapper. Wire: none.
19 changes: 19 additions & 0 deletions quest/m1/hls-log-redaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# [XS] HLS import logs redact URLs

## Goal

No HLS import log line carries an unredacted playlist or segment URL, so a
signed query string never reaches the logs.

## Plan

The "selected master playlist renditions" info line
(`rs/moq-hls/src/import.rs`) prints the audio playlist URL as given.
[moq-dev/moq#6767](https://github.com/moq-dev/moq/pull/6767) redacted the
error paths only.

Route every URL the import logs through the redaction #6767 added, and sweep
moq-hls for other `tracing` calls that format a URL. A test captures the log
line and asserts the query string is gone.

Public API: none. Wire: none.
26 changes: 26 additions & 0 deletions quest/m1/moxygen-pin-bump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# [XS] Moxygen pins without the TRACK_STATUS patch

## Goal

Waiting on upstream Moxygen. Once
[facebookexperimental/moxygen#264](https://github.com/facebookexperimental/moxygen/pull/264)
merges, `nix/moxygen.nix` pins a Moxygen that includes it,
`nix/moxygen-track-status.patch` is deleted, and the Moxygen interop and
conformance lanes still pass.

Check moxygen#264's state. Delete this quest once the patch is gone, or if
moxygen#264 lands before the patch reaches `main`.

## Plan

The patch is not on `main` yet:
[moq-dev/moq#6729](https://github.com/moq-dev/moq/pull/6729), still open, adds
it to `nix/moxygen.nix`'s `patches` and carries it until upstream lands it. Upstream's client has moved to draft-20 Location
Filters, so the profile patch the pin also applies needs rebasing in the same
bump. Run `just test interop --all` and the Moxygen smoke lane.

Public API: none. Wire: none.

## Related

- [Moxygen minimal interop](/quest/m1/smoke-moxygen.md) - the other upstream Moxygen fix the smoke lane waits on
1 change: 0 additions & 1 deletion quest/m1/test-flakes-2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,3 @@ Public API: none. Wire: none.
- [Media resource instrumentation](/quest/m1/test-flakes-2/resource-instrumentation.md) - the media test stops seeing a playing player report nothing to release
- [IETF22 fallback](/quest/m1/test-flakes-2/ietf22-fallback.md) - an IETF22 browser viewer follows a fallback within the media lane's bound, keeping its session and its audio
- [Echo report test on mocked time](/quest/m1/test-flakes-2/export-echo-time.md) - the moq-cli echo report test stops taking 35 s of wall time
- [OBS failed audio candidate](/quest/m1/test-flakes-2/obs-audio-candidate.md) - the OBS failed-audio-candidate test passes under load
16 changes: 0 additions & 16 deletions quest/m1/test-flakes-2/obs-audio-candidate.md

This file was deleted.

1 change: 1 addition & 0 deletions quest/m1/ts-reliability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ catalog linger (#5305).
- [PAT changes](/quest/m1/ts-reliability/pat-lifecycle.md) - a revised PAT never leaves a broadcast meaning another program
- [Stream routes](/quest/m1/ts-reliability/stream-routes.md) - every PID gets a declared route, and what is not carried is counted
- [TS workflow passes](/quest/m1/ts-reliability/validation-green.md) - the scheduled TS lanes pass on main again, with no lane loosened
- [Export SI order](/quest/m1/ts-reliability/export-si-order.md) - a TS export sends SI after its PMT and a PCR interval, so a hop keeps first emissions

## Related

Expand Down
23 changes: 23 additions & 0 deletions quest/m1/ts-reliability/export-si-order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# [S] TS export sends SI after its PMT and PCR

## Goal

A TS export holds its first SI tables until the PMT and one PCR interval are
out, so an export-to-import hop keeps each table's first emission instead of
dropping it until the table repeats.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

## Plan

Since [moq-dev/moq#6757](https://github.com/moq-dev/moq/pull/6757), TS import
admits SI only once a valid program-clock interval exists. The export writes
its first SI ahead of its PMT and PCRs, so the importer drops it. Order the
export's first output as PAT, PMT, a PCR interval, then SI. A PCR interval
here is what `si.rs` needs to place a section: one forward PCR step of at most
`MAX_INTERVAL`, not the importer's two-second catalog window. Test it with an
export-to-import round trip that sees every SI table's first emission.

Not planned (2026-10-25, maintainer): bounding SI aging against a source that
claims a huge mux rate through valid PCR steps. That needs a program-clock
floor per input byte, a new contract.

Public API: none. Wire: none.
2 changes: 2 additions & 0 deletions quest/m2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ lite-07; bitrate enforcement is not part of this release.
- [QoS](/quest/m2/qos/README.md) - the relay's egress `lag` histogram and `dropped` counters on the stats totals and prefix tracks
- [Lazy retained HLS instances](/quest/m2/hls-lazy-instances.md) - a replaced HLS instance starts its watchers only when a request reaches it
- [HLS and DASH browser playback](/quest/m2/hls-player-test.md) - hls.js and dash.js play, reload, switch, and survive reconfiguration nightly
- [moq-hls export on kio](/quest/m2/hls-export-kio.md) - export watchers and the init build are owned kio tasks instead of tokio::spawn
- [Re-init retires timelines](/quest/m2/reinit-retire.md) - fMP4 and MKV re-inits retire the old timeline, so import state stays bounded
- [Broadcast fairness](/quest/m2/broadcast-fairness.md) - broadcasts share a cluster link fairly, so one tenant's priority never starves another's
- [Peer grant bound](/quest/m2/peer-grant-bound.md) - a peer's AUTH_OK costs near-linear time in its bytes on every input shape, in Rust and in a browser
- [Plan: watch worker](/quest/m2/plan-watch-worker.md) - prototype an invisible page worker against app-spawned workers, and land the jank harness that decides
Expand Down
21 changes: 21 additions & 0 deletions quest/m2/hls-export-kio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# [M] moq-hls export runs on kio

## Goal

moq-hls export's background work (the catalog, timeline, and spans watchers in
`rs/moq-hls/src/export/{mod,rendition}.rs`, and the init build) runs as
poll-driven `kio` tasks the export owns, not on `tokio::spawn`, as
`rs/AGENTS.md` prefers.

## Plan

Do it crate-wide in one PR. Tasks end with their owner instead of being
detached, which also removes the abort handles kept for them today. Keep the
timeline watcher's two lifetime rules: a new reference timeline replaces the
old watcher, and a recording cursor that outlives the `Broadcaster` keeps the
watcher running until the timeline ends (see `Broadcaster`'s `Drop`). Test
both. Tests
keep their own spawns where they drive a runtime. Measure export throughput
before and after with the existing moq-hls benchmarks.

Public API: none expected. Wire: none.
18 changes: 18 additions & 0 deletions quest/m2/reinit-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# [S] fMP4 and MKV re-init retire old timelines

## Goal

When an fMP4 or MKV import re-initializes (a new init segment or EBML header
mid-stream), the old timeline is retired the way
[moq-dev/moq#6757](https://github.com/moq-dev/moq/pull/6757) retires an ended
TS route, so import state stays bounded across repeated re-inits.

## Plan

Reuse the retirement #6757 added to `rs/moq-mux/src/timeline.rs`.
`Timelines::retire` refuses a timeline whose recorder is still live, so each
re-init finishes and drops the old recorder before retiring, as the TS route
end does. Test a stream that re-inits many times and assert the import's state
does not grow.

Public API: none. Wire: none.
5 changes: 5 additions & 0 deletions quest/m2/uniffi-fork.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ which publishes `rust2-uniffi`, `rust2-uniffi-core`, `rust2-uniffi-macros`, and
Delete `rs/uniffi-bindgen`, the "five places" comments in `flake.nix`, and the
`nix/uniffi-dart-*` lockfile and patch. The `sh/{kt,swift,dart,cpp}`
packaging scripts stay: they package moq.
- Negative durations (2026-10-25, maintainer): the Dart negative-duration
patch moq carries goes upstream into the fork's Dart generator, and the Go
generator stops panicking on a negative `time.Duration` (the Go wrapper
guards it today; delete the guard in the PR that pins a generator with the
fix, with a test passing a negative duration through the Go binding).
- Update the quests that name a `kixelated/uniffi-*` fork
([Generated C bindings](/quest/m1/c/README.md)) to point at rust2, then
archive the three forks.
Expand Down
Loading