diff --git a/quest/m0/ci/README.md b/quest/m0/ci/README.md index 83dfc3b376a..881b908829a 100644 --- a/quest/m0/ci/README.md +++ b/quest/m0/ci/README.md @@ -112,6 +112,7 @@ The historical samples locate candidates; they are not controlled benchmarks. ## Required - [Require the release gate](/quest/m0/ci/release-gates.md) - condition: the next cut carries `release-gate.yml`; then release PRs require it +- [Seed release with API reports](/quest/m0/ci/release-api-seed.md) - the first cut's API diff has a baseline on `release` - [Build queue entries concurrently](/quest/m0/ci/queue-concurrency.md) - the queue builds two or more entries at once instead of one - [Measure nightly compiler levers](/quest/m0/ci/nightly-levers.md) - the parallel frontend and Cranelift, adopted only if the numbers beat their risks - [Bump to the manifest fix](/quest/m0/ci/mbx-bump.md) - condition: an mbx release contains jdx/mr-boxington#798; then bump the Rust cache's pin diff --git a/quest/m0/ci/release-api-seed.md b/quest/m0/ci/release-api-seed.md new file mode 100644 index 00000000000..b2270f68bbe --- /dev/null +++ b/quest/m0/ci/release-api-seed.md @@ -0,0 +1,15 @@ +# [S] Seed release with API reports + +## Goal + +`release` carries its own committed API reports and the per-PR report check, +so the first cut's API diff compares against a baseline instead of nothing. + +## Plan + +- Decided by the maintainer on [moq-dev/moq#6477](https://github.com/moq-dev/moq/pull/6477): + seed `release` once with a small backport. Today main has 36 `.api.md` + reports and release has none, and `sh/api-diff/run.sh` reads them from + `origin/release`. +- Backport `js/common/api.ts` and the report check, and commit the reports + generated from release's own sources. diff --git a/quest/m0/nightly/README.md b/quest/m0/nightly/README.md index 42a09a3cad7..7e0d9638066 100644 --- a/quest/m0/nightly/README.md +++ b/quest/m0/nightly/README.md @@ -35,4 +35,5 @@ Public API: none. Wire: none. - [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 +- [moq-net builds without async](/quest/m0/nightly/net-async-free.md) - the no-default-features lane stops pulling `async` back in - [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 diff --git a/quest/m0/nightly/net-async-free.md b/quest/m0/nightly/net-async-free.md new file mode 100644 index 00000000000..c04a0ce757a --- /dev/null +++ b/quest/m0/nightly/net-async-free.md @@ -0,0 +1,22 @@ +# [S] moq-net builds without async + +## Goal + +The `moq-net --no-default-features` lane compiles and lints moq-net without +the `async` feature, so async-only code can't leak into the sync build. + +## Plan + +- Today the lane's `cargo clippy --all-targets` and `cargo nextest run --tests` + steps (`sh/rs/net-features.sh`) build dev-dependencies, which pull `async` + back in: moq-net dev-depends on itself with `fuzz`, which implies `async`, + and on moq-json, whose `moq-net = { workspace = true }` may enable the + default features (confirm with `cargo tree -e features`). +- Replace the `--all-targets` clippy with `--lib`, which skips + dev-dependencies. For tests, move every test target that needs those + dev-dependencies into its own test crate, so the lane's nextest builds + moq-net without `async`. + +## Related + +- [Generated async wrappers](/quest/m1/poll-first/async-feature.md) - reshapes the `async` feature this lane keeps out diff --git a/quest/m1/README.md b/quest/m1/README.md index ce7dc211bbd..475de954039 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -156,6 +156,11 @@ whose surface its QUIC adapter plugs into. - [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 +- [App-limited BBR3 estimate ages](/quest/m1/bbr-app-limited.md) - an app-limited BBR3 estimate falls within seconds after the path drops +- [Seeded BBR3 in tests](/quest/m1/bbr-test-seed.md) - unseeded `Bbr3Config::default()` tests replay the same randomness +- [Aborted epoch reads keep their cause](/quest/m1/epoch-abort-cause.md) - an aborted read through an epoch route ends with its own error, not NotFound +- [Bindings name every session code](/quest/m1/ffi-malformed-auth-kind.md) - MALFORMED_AUTH_TOKEN and its siblings reach moq-ffi, moq-c, and the wrappers +- [A profiling host](/quest/m1/perf-host.md) - condition: a quiet host with `perf_event_paranoid=-1`, recorded in `bench/README.md` - [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 diff --git a/quest/m1/auth/README.md b/quest/m1/auth/README.md index 65bb8c2ee58..ab78c08796b 100644 --- a/quest/m1/auth/README.md +++ b/quest/m1/auth/README.md @@ -148,6 +148,8 @@ because `main` assigned 0x3A to NOT_FETCHABLE first. AUTH streams: a session starts on the token its SETUP or URL carried and its AUTH streams add the rest - [Binding auth polish](/quest/m1/auth/bindings-polish.md) - OBS reconnects with the presented token, Swift grant sequences +- [Expiry before SETUP](/quest/m1/auth/expire-before-setup.md) - a mocked-clock test proves a grant expiring before SETUP closes as Expired +- [Tokens through a drain](/quest/m1/auth/drain-token.md) - a closing Rust connection keeps a draining publication's token grant ## Related diff --git a/quest/m1/auth/drain-token.md b/quest/m1/auth/drain-token.md new file mode 100644 index 00000000000..db50e368c07 --- /dev/null +++ b/quest/m1/auth/drain-token.md @@ -0,0 +1,16 @@ +# [S] Rust keeps tokens through a drain + +## Goal + +A Rust `Connection` closed while a token-only publication drains keeps that +token's grant until the drain ends, as JS does since +[moq-dev/moq#6630](https://github.com/moq-dev/moq/pull/6630). + +## Plan + +- Suspected gap: `Connection::close` (`rs/moq-tokio/src/connection.rs`) drains + the session, but `Shared::end` aborts the shared `auth::Handle` when the + loop task ends. Write the test first; fix only if it fails, and delete this + quest if it passes. +- Carrying tokens across reconnects already works (one handle shared across + sessions). diff --git a/quest/m1/auth/expire-before-setup.md b/quest/m1/auth/expire-before-setup.md new file mode 100644 index 00000000000..f374e955a08 --- /dev/null +++ b/quest/m1/auth/expire-before-setup.md @@ -0,0 +1,14 @@ +# [XS] A grant that expires before SETUP + +## Goal + +A test on `moq_clock::Manual` proves that a grant expiring between admission +and SETUP closes the session as `Expired` (session code 0x18 at the client), +not `Unauthorized`. + +## Plan + +- The branch exists in `rs/moq-relay/src/auth/refresh.rs` (from + [moq-dev/moq#6612](https://github.com/moq-dev/moq/pull/6612)) but nothing + asserts it. Parameterize `refused_before_setup` with the expected error and + advance the clock past `expires` before `preparing`. diff --git a/quest/m1/bbr-app-limited.md b/quest/m1/bbr-app-limited.md new file mode 100644 index 00000000000..5b0b8a721dc --- /dev/null +++ b/quest/m1/bbr-app-limited.md @@ -0,0 +1,29 @@ +# [M] App-limited BBR3 estimate ages + +## Goal + +After a path's capacity drops, an application-limited BBR3 sender's bandwidth +estimate falls within a few seconds instead of staying at the old peak for +20 s or more. Readers of the estimate, starting with the native simulcast rung +disable, stop funding rungs the path can no longer carry. + +## Plan + +- Cause: `update_max_bw` in `rs/moq-congestion/src/bbr3/mod.rs` admits an + app-limited sample only when it is at least `max_bw`, and the max filter is + keyed on `cycle_count`, which an app-limited sender never advances. The + bandwidth probe also stays idle while the estimate covers its target. + [moq-dev/moq#6635](https://github.com/moq-dev/moq/pull/6635) measured + neither run's estimate falling within 20 s. +- Fix it in the estimator, not in each reader (decided 2026-10-25, root-cause + rule): age `max_bw` while app-limited, by wall time or by delivery rounds, + whichever matches BBRv3 and QUICHE's behavior once compared. A reader-side + fallback to `bw_shortterm` is the rejected alternative. +- Turn the `stale_estimate` report in `rs/moq-quic/src/tests/probe.rs` into an + assertion on a mocked clock and a bufferbloat path (a rate limit below the + media bitrate behind a deep finite queue whose overflow drops packets). + +## Related + +- [Native rung disable](/quest/m1/simulcast-rung-disable.md) - reads this estimate +- [BBR media study](/quest/m2/quic-bbr-study.md) - broader BBR3 behavior under media diff --git a/quest/m1/bbr-test-seed.md b/quest/m1/bbr-test-seed.md new file mode 100644 index 00000000000..b75c4bde4ce --- /dev/null +++ b/quest/m1/bbr-test-seed.md @@ -0,0 +1,16 @@ +# [XS] Seeded BBR3 in tests + +## Goal + +Every moq-congestion test that builds `Bbr3Config::default()` without a seed +replays the same randomness on every run, as it did before +[moq-dev/moq#6602](https://github.com/moq-dev/moq/pull/6602). + +## Plan + +- `Bbr3::new` falls back to `Pcg32::from_rng(&mut rand::rng())` + (`rs/moq-congestion/src/bbr3/mod.rs`, about line 620); before the extraction + it used `crate::entropy::rng()`, which tests seeded per thread. +- Under `cfg(test)`, fall back to a fixed seed (moq-quic already reseeds its + own tests in `rs/moq-quic/src/config/transport.rs`). Production keeps OS + randomness. diff --git a/quest/m1/drop-set.md b/quest/m1/drop-set.md index 021a5ba5924..0d273d2d834 100644 --- a/quest/m1/drop-set.md +++ b/quest/m1/drop-set.md @@ -219,6 +219,11 @@ Mirror each case in `js/net`. Public API: none. Wire: lite-07 SUBSCRIBE_DROP (unpublished) gains `Max Age` and the widening and ordering rules above; published versions are unchanged. +- A local producer's declared end must settle over dropped groups, as the + doc on `TrackState::drop_groups` already claims (added 2026-10-25): let + `reaches(fin)` count a live edge whose gap `edge..fin` is wholly dropped, + then delete moq-archive's fake empty group at `fin - 1` + (`rs/moq-archive/src/consumer/track.rs`). ### CPU per drop (2026-10-24 pre-cut audit) diff --git a/quest/m1/epoch-abort-cause.md b/quest/m1/epoch-abort-cause.md new file mode 100644 index 00000000000..de04429c6de --- /dev/null +++ b/quest/m1/epoch-abort-cause.md @@ -0,0 +1,17 @@ +# [S] Aborted epoch reads keep their cause + +## Goal + +A track read through an epoch route that aborts after delivering ends with the +abort's own error (for example `FrameTooLarge`), not the `NotFound` a re-query +of the source returns. + +## Plan + +- Reproduced in [moq-dev/moq#6428](https://github.com/moq-dev/moq/pull/6428): + `rs/moq-net/src/model/front.rs` (about line 563) returns a failed epoch route + to Idle and redispatches it, and the re-query's refusal replaces the + original error. +- Redispatch only when the error is a route failure (the `route_failed` rule in + `rs/moq-net/src/model/resume.rs`); otherwise abort the read with that error. + Check JS for the same path. diff --git a/quest/m1/ffi-malformed-auth-kind.md b/quest/m1/ffi-malformed-auth-kind.md new file mode 100644 index 00000000000..133eaeccb48 --- /dev/null +++ b/quest/m1/ffi-malformed-auth-kind.md @@ -0,0 +1,14 @@ +# [S] Bindings name every session code + +## Goal + +A session closed with MALFORMED_AUTH_TOKEN (0x16) reports that kind through +moq-ffi's `MoqProtocolKind`, moq-c, and every hand-written wrapper, instead of +`Unknown`. Any other session code moq-net names but the bindings drop (check +0x13 and 0x17) gets the same treatment. + +## Plan + +- moq-net already has `SessionError::MalformedAuthToken` + ([moq-dev/moq#6612](https://github.com/moq-dev/moq/pull/6612) follow-up). +- Follow the root Cross-Package Sync table for moq-ffi. diff --git a/quest/m1/perf-host.md b/quest/m1/perf-host.md new file mode 100644 index 00000000000..f68a4f192c6 --- /dev/null +++ b/quest/m1/perf-host.md @@ -0,0 +1,16 @@ +# [XS] A profiling host + +## Goal + +Condition: a quiet Linux host has `kernel.perf_event_paranoid=-1` and +`bench/README.md` names it and how to reach it. Check with +`sysctl kernel.perf_event_paranoid` on that host. This is a maintainer action; +delete this quest once it holds. + +## Plan + +- `bench/profile.py` refuses `lock` and `cpu` captures without it (heap + captures need only `jeprof`). The + [log lock profile](/quest/m1/unbounded-groups/log-lock-profile.md) and + [moq-dev/moq#6680](https://github.com/moq-dev/moq/pull/6680) need CPU and lock + profiles from such a host. diff --git a/quest/m1/test-flakes-2/README.md b/quest/m1/test-flakes-2/README.md index 56635bcb105..a7cdb7669ac 100644 --- a/quest/m1/test-flakes-2/README.md +++ b/quest/m1/test-flakes-2/README.md @@ -41,5 +41,8 @@ Public API: none. Wire: none. ## Required - [Media resource instrumentation](/quest/m1/test-flakes-2/resource-instrumentation.md) - the media test stops seeing a playing player report nothing to release +- [moq-cli relay tests under load](/quest/m1/test-flakes-2/cli-relay-load.md) - the fetch and announced tests wait on events, not timing +- [FFI publisher audio gaps](/quest/m1/test-flakes-2/ffi-audio-gap.md) - interop tone checks stop finding gaps from FFI publishers +- [moq-uring allocations under load](/quest/m1/test-flakes-2/uring-alloc-load.md) - the steady-state send test and MEMLOCK users pass in a parallel check - [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 diff --git a/quest/m1/test-flakes-2/cli-relay-load.md b/quest/m1/test-flakes-2/cli-relay-load.md new file mode 100644 index 00000000000..28c2c2ff20a --- /dev/null +++ b/quest/m1/test-flakes-2/cli-relay-load.md @@ -0,0 +1,15 @@ +# [S] moq-cli relay tests under load + +## Goal + +`real_relay_matches_http_fetch` (`rs/moq-cli/src/fetch.rs`) and the moq-cli +`announced` network tests pass under a parallel `just check`. + +## Plan + +- Reproduce under load first; the failure mode is not yet captured. The fetch + test runs on the wall clock against a real relay and curls right after the + publisher connects, so a routing race is the leading suspect. +- Fix by waiting on the relay's announce or route event before fetching. Keep + the fetch test on the real relay, which is the HTTP routing and response + coverage it exists for. Never a sleep or retry. diff --git a/quest/m1/test-flakes-2/ffi-audio-gap.md b/quest/m1/test-flakes-2/ffi-audio-gap.md new file mode 100644 index 00000000000..1b90e9df505 --- /dev/null +++ b/quest/m1/test-flakes-2/ffi-audio-gap.md @@ -0,0 +1,15 @@ +# [S] FFI publisher audio gaps in interop + +## Goal + +The interop tone check (`test/interop/tone.py`, "timestamp gap") stops +failing for FFI publishers: `python -> c` and the `cpp ->` cells seen in +[moq-dev/moq#6464](https://github.com/moq-dev/moq/pull/6464) and +[moq-dev/moq#6648](https://github.com/moq-dev/moq/pull/6648). + +## Plan + +- [moq-dev/moq#6658](https://github.com/moq-dev/moq/pull/6658)'s max-age cause + does not apply: FFI publishers keep hang's 30 s max-age. +- Reproduce under load and find which group or frame jumps, then fix the + cause at its source. diff --git a/quest/m1/test-flakes-2/uring-alloc-load.md b/quest/m1/test-flakes-2/uring-alloc-load.md new file mode 100644 index 00000000000..06e8a974722 --- /dev/null +++ b/quest/m1/test-flakes-2/uring-alloc-load.md @@ -0,0 +1,16 @@ +# [S] moq-uring allocation test under load + +## Goal + +`steady_state_sends_do_not_allocate` (`rs/moq-uring/tests/allocations.rs`) +and the other moq-uring tests pass under a parallel `just check`. + +## Plan + +- Seen as 1001 allocations over 1000 sends in + [moq-dev/moq#6496](https://github.com/moq-dev/moq/pull/6496). Find the extra + acquire (likely a second pending acquire's waiter under load) and count what + the test means to bound, without loosening it. +- moq-uring tests also hit the shared `RLIMIT_MEMLOCK` under load + ([moq-dev/moq#6538](https://github.com/moq-dev/moq/pull/6538)); serialize + them with a nextest test group if that is the cause. diff --git a/quest/m1/unbounded-groups/log-lock-profile.md b/quest/m1/unbounded-groups/log-lock-profile.md index 28683eea496..eb88d17630b 100644 --- a/quest/m1/unbounded-groups/log-lock-profile.md +++ b/quest/m1/unbounded-groups/log-lock-profile.md @@ -10,12 +10,13 @@ or holds. ## Plan -- Blocked on the perf-host quest (`quest/m1/perf-host.md`, planned in - [moq-dev/moq#6796](https://github.com/moq-dev/moq/pull/6796)); add it under - Required once it lands. - Compare the commit before #6782 with the one that merged it, at each worker count, and post the wait-by-stack diff on the PR that finishes this. - #6782's body holds the criterion numbers, taken on an oversubscribed host: `group_contended` costs 13 to 61% less per reader across cores, and about 4 ns more per frame on one thread. A profile that contradicts them goes back to the maintainer. + +## Required + +- [A profiling host](/quest/m1/perf-host.md) - the `perf_event_paranoid=-1` host the lock profile runs on diff --git a/quest/m2/README.md b/quest/m2/README.md index 1cb2ffe7c93..de6c30c8018 100644 --- a/quest/m2/README.md +++ b/quest/m2/README.md @@ -231,4 +231,10 @@ lite-07; bitrate enforcement is not part of this release. - [Artifact size audit](/quest/m2/audit-size.md) - repeat the shipping, native, WASM and browser attribution after the release ships - [Compile time audit](/quest/m2/audit-compile-time.md) - build-time hotspots are measured against the m1 baselines, starting with the transport share now that moq-net compiles once, and the worst are fixed or planned - [Lint override and deprecation audit](/quest/m2/audit-lints.md) - repeat the suppression and deprecation audit after the release ships, starting with clippy on the macOS and Windows targets +- [Bound cmsg payload reads](/quest/m2/cmsg-decode-bound.md) - `CMsg::decode` refuses a short control message +- [One typed SETUP parse](/quest/m2/setup-parse-once.md) - one function replaces three SETUP parameter parses +- [Archive reads against a real store](/quest/m2/archive-store-bench.md) - LIST/GET counts and latency over track count +- [Quiet logs for clean ends](/quest/m2/quiet-clean-close-logs.md) - clean probe ends and unroutable requests log at debug +- [No MOQ_* knobs outside the binaries](/quest/m2/env-knobs.md) - test, bench, and library knobs leave the `MOQ_*` prefix +- [Clean ALSA playback onset](/quest/m2/audio-alsa-onset.md) - no onset restarts or clicks over PulseAudio - [Interop audit](/quest/m2/audit-interop.md) - our interop runner entries match what we ship, and every red interop cell with a moq.dev side is fixed, reported, or noted as down or unsupported diff --git a/quest/m2/archive-store-bench.md b/quest/m2/archive-store-bench.md new file mode 100644 index 00000000000..66fe1b73f57 --- /dev/null +++ b/quest/m2/archive-store-bench.md @@ -0,0 +1,16 @@ +# [M] Archive reads against a real object store + +## Goal + +A benchmark or nightly probe measures `moq_archive::Consumer` against a real +object store (S3, R2, or MinIO), counting LIST and GET calls and latency as +the track count grows, so a regression in archive reads shows up. + +## Plan + +- The cost is store round trips (per refresh, one LIST of the archive prefix + plus one per track; one GET per object), which an `InMemory` Criterion + bench would hide ([moq-dev/moq#6262](https://github.com/moq-dev/moq/pull/6262)). + `object_store`'s `aws` feature is already a dev feature. +- Sweep both axes, track count and objects per track, per the fan-out + benchmark rule. diff --git a/quest/m2/audio-alsa-onset.md b/quest/m2/audio-alsa-onset.md new file mode 100644 index 00000000000..0d883026372 --- /dev/null +++ b/quest/m2/audio-alsa-onset.md @@ -0,0 +1,17 @@ +# [M] Clean ALSA playback onset + +## Goal + +ALSA playback over PulseAudio starts without restarting output and without +audible clicks right after onset or after a switch. + +## Plan + +- From [moq-dev/moq#6676](https://github.com/moq-dev/moq/pull/6676): a + transient EIO from `snd_pcm_avail_delay` counts toward `ERROR_LIMIT` + (`rs/moq-audio/src/playback/driver.rs`) and restarts output; the first + callbacks then stall about 1.5 s. Don't count the first EIO before the sink's + first successful callback toward the limit; a repeat before then, and every + EIO after, still counts, so a sink that never starts still rebuilds. +- Size the sink prefill below the target so a fresh sink lands on it, which + should remove the onset clicks. Re-measure both before and after. diff --git a/quest/m2/audit-deps.md b/quest/m2/audit-deps.md index 4cf6348e81b..24a39d93725 100644 --- a/quest/m2/audit-deps.md +++ b/quest/m2/audit-deps.md @@ -132,6 +132,10 @@ deep-equal pair, and duplicated WebVTT stamps and `jwt=` lookups. near copies), which is duplication rather than a dependency question. The m1 run came a day after m0's and did not re-review it; check code added since. +- When TypeScript 7.1 is stable, delete `TransportStats` in + `js/net/src/connection/stats.ts` and type `getStats()` as the DOM's + `WebTransportConnectionStats` (from + [moq-dev/moq#6625](https://github.com/moq-dev/moq/pull/6625)). ## Required diff --git a/quest/m2/cmsg-decode-bound.md b/quest/m2/cmsg-decode-bound.md new file mode 100644 index 00000000000..6daff65e50b --- /dev/null +++ b/quest/m2/cmsg-decode-bound.md @@ -0,0 +1,18 @@ +# [XS] Bound cmsg payload reads + +## Goal + +`CMsg::decode` in `rs/moq-sock/src/udp/cmsg/mod.rs` refuses a control message +shorter than its type instead of reading `size_of::()` bytes past it in +release builds. + +## Plan + +- Today only a `debug_assert_eq!` checks the length; + [moq-dev/moq#6678](https://github.com/moq-dev/moq/pull/6678) bounded the + iterator but not `decode`. Return `None` when the payload is short and let + the Unix and Windows callers skip it. + +## Related + +- [Wire fuzz coverage](/quest/m2/wire-fuzz-coverage.md) - fuzzes the same cmsg walk diff --git a/quest/m2/env-knobs.md b/quest/m2/env-knobs.md new file mode 100644 index 00000000000..f98bb0c918b --- /dev/null +++ b/quest/m2/env-knobs.md @@ -0,0 +1,17 @@ +# [S] No MOQ_* knobs outside the binaries + +## Goal + +Only a binary's declared settings use the `MOQ_*` prefix, so a shell that sets +a test, bench, or library knob never trips a binary's unknown-variable refusal +from [moq-dev/moq#6633](https://github.com/moq-dev/moq/pull/6633). + +## Plan + +- Rename test and bench knobs out of `MOQ_*` (for example `MOQ_SHAPER_SEED`, + `MOQ_QUIC_SEED`, `MOQ_JSON_SEED`, `MOQ_AUDIO_DEVICE`, `MOQ_BENCH_*`, + `MOQ_X11_BENCH_LOG`), updating CI and docs that set them. +- moq-video reads `MOQ_VAAPI_DEVICE` and `MOQ_V4L2_*` from the environment as + a library. Decided 2026-10-25 (recommendation, maintainer delegated): a + library reads no environment; the binaries that link moq-video declare these + as settings and pass them in. diff --git a/quest/m2/p2p/README.md b/quest/m2/p2p/README.md index 0925b7dcd19..fcd23b43442 100644 --- a/quest/m2/p2p/README.md +++ b/quest/m2/p2p/README.md @@ -160,6 +160,7 @@ Backend choice does not change the policy that watching tabs never re-serve. - [Peer route policy](/quest/m2/p2p/cost-scopes.md) - application priorities and total cost choose eligible routes, with epoch-aware handover - [Watch opts in](/quest/m2/p2p/watch.md) - one attribute turns it on in the demo and the watcher migrates to the best eligible route - [Harness](/quest/m2/p2p/harness.md) - the Playwright harness and the numbers behind every mapping decision +- [Plan P2P identity](/quest/m2/p2p/identity-plan.md) - condition: the maintainer settles the roster key, exploring moq-e2ee signing first ## Related diff --git a/quest/m2/p2p/identity-plan.md b/quest/m2/p2p/identity-plan.md new file mode 100644 index 00000000000..ea677c10b72 --- /dev/null +++ b/quest/m2/p2p/identity-plan.md @@ -0,0 +1,23 @@ +# [S] Plan P2P identity + +## Goal + +Condition: the maintainer runs `/quest-plan` on P2P identity and the +[Signaling and policy](/quest/m2/p2p/signal.md) and +[Peer grants](/quest/m2/p2p/peer-grant.md) quests reflect the result. Delete +this quest then. + +## Plan + +- Parked 2026-10-25 (maintainer): the roster-key question that + [moq-dev/moq#6310](https://github.com/moq-dev/moq/pull/6310) left open in + `signal.md` (what names a roster entry and maps an announce to a peer, now + that each receiver stamps its own routing identity) needs a walkthrough + before any choice. +- Maintainer direction to explore first: when peers don't trust each other + and need proof, extend moq-e2ee to sign content (not only encrypt it), so + proof rides the media rather than a routing identity. + +## Related + +- [E2EE](/quest/m2/e2ee/README.md) - where signing would live diff --git a/quest/m2/probe/README.md b/quest/m2/probe/README.md index 71c46f67c44..f888a5ce549 100644 --- a/quest/m2/probe/README.md +++ b/quest/m2/probe/README.md @@ -88,6 +88,7 @@ This README's own work, once the children land: - [Viewer targets](/quest/m2/probe/viewer-target.md) - a session sends its viewer handles as its PROBE target, probes to the peer's, splits the receive estimate into viewer grants, and advertises `Increase` where a sender exists - [Players set viewer targets](/quest/m2/probe/players.md) - players hold a viewer handle per watched broadcast at its highest enabled rendition's bitrate - [Viewer up-switch](/quest/m2/probe/viewer-upswitch.md) - a viewer capped by its small rendition finds headroom through PROBE and moves up +- [Back off an unreachable target](/quest/m2/probe/target-backoff.md) - failed probe rises back the target off instead of wasting media ## Related diff --git a/quest/m2/probe/target-backoff.md b/quest/m2/probe/target-backoff.md new file mode 100644 index 00000000000..91d345b63fc --- /dev/null +++ b/quest/m2/probe/target-backoff.md @@ -0,0 +1,23 @@ +# [S] Back off an unreachable probe target + +## Goal + +A session whose probes keep failing to raise the estimate toward its target +backs the target off, instead of spending about 5% of its media on duplicate +probe bytes indefinitely. + +## Plan + +- Measured in [moq-dev/moq#6635](https://github.com/moq-dev/moq/pull/6635): + 4.6% redundant bytes for a 100 Mbit/s target on a 3 Mbit/s path. + `rs/moq-quic/src/connection/bandwidth_probe.rs` keeps no state about failed + rises. +- Keep the requested target (`set_probe_target`) apart from the effective one + the probe paces to. Back off the effective target exponentially after + ProbeBW_UP cycles with no estimate rise, reset it to the requested target + when the caller changes that, and retry the requested target on the same + backoff so returning capacity is found. Prove it on a bufferbloat path. + +## Related + +- [App-limited BBR3 estimate ages](/quest/m1/bbr-app-limited.md) - the estimate the probe compares against diff --git a/quest/m2/quiet-clean-close-logs.md b/quest/m2/quiet-clean-close-logs.md new file mode 100644 index 00000000000..25f51cc11a9 --- /dev/null +++ b/quest/m2/quiet-clean-close-logs.md @@ -0,0 +1,13 @@ +# [XS] Quiet logs for clean ends + +## Goal + +A probe stream that ends cleanly, or a track request that is unroutable, logs +at debug instead of warn; other errors stay at warn. + +## Plan + +- `probe stream error` in `rs/moq-net/src/lite/publisher.rs` and + `subscriber.rs` warns even for `no error`; `track info failed` in + `subscriber.rs` warns for Unroutable; also check the SRT server's + unroutable line. From [moq-dev/moq#6632](https://github.com/moq-dev/moq/pull/6632). diff --git a/quest/m2/release/migrate-audit.md b/quest/m2/release/migrate-audit.md index a008ca05c8f..b32ccf2792a 100644 --- a/quest/m2/release/migrate-audit.md +++ b/quest/m2/release/migrate-audit.md @@ -40,6 +40,10 @@ m1 quest on 2026-10-22. - Compile-check the code in every `MIGRATE.md` section the cut ships against the candidate. Nothing else builds it. - Required by the cut, after m1's breaking work has landed. +- Start from the candidates [moq-dev/moq#6477](https://github.com/moq-dev/moq/pull/6477) + listed as breaks matching no name in `MIGRATE.md` (about 15 Rust crates, + `@moq/hang`, `@moq/net`, `@moq/watch`, and moq-ffi): confirm each, and add + its migration note or record why none is needed. ## Required diff --git a/quest/m2/setup-parse-once.md b/quest/m2/setup-parse-once.md new file mode 100644 index 00000000000..6c28ba59380 --- /dev/null +++ b/quest/m2/setup-parse-once.md @@ -0,0 +1,13 @@ +# [S] One typed SETUP parse + +## Goal + +One function turns SETUP parameters into path, token, implementation, and +`Peer` for every caller, replacing the three copies in +`rs/moq-net/src/server.rs` (legacy CLIENT_SETUP) and +`rs/moq-net/src/ietf/session.rs` (`accept_setup`, `decode_peer_setup`). + +## Plan + +- The legacy copy builds `Peer` by hand without cluster, auth, or epoch; + check whether that difference is intended before unifying. diff --git a/quest/m2/stats/README.md b/quest/m2/stats/README.md index b4e6141adc2..dba62cd8c94 100644 --- a/quest/m2/stats/README.md +++ b/quest/m2/stats/README.md @@ -117,6 +117,7 @@ connection view and the dashboard flow. stats and `` publishes feedback - [Preflight](/quest/m2/stats/preflight.md) - a bounded test run over a broadcast reports which media layer is broken and why +- [Client health in use](/quest/m2/stats/health-consumers.md) - a per-connection media counter, consumers of the grade, and re-measured limits ## Related diff --git a/quest/m2/stats/health-consumers.md b/quest/m2/stats/health-consumers.md new file mode 100644 index 00000000000..dc247051e11 --- /dev/null +++ b/quest/m2/stats/health-consumers.md @@ -0,0 +1,23 @@ +# [M] Client health in use + +## Goal + +The client health grade from +[moq-dev/moq#6654](https://github.com/moq-dev/moq/pull/6654) is read by +something and holds for a connection carrying several broadcasts: stats carry +a per-connection media counter, at least one consumer shows the grade, and the +grade's limits are re-measured against browser reporters. + +## Plan + +- Add a media counter to the per-connection `Transport` stats + (`rs/hang/src/stats.rs` and the JS mirror). `health.rs` says the grade holds + only for a connection's sole broadcast until then. +- Consumers: preflight is planned in [Preflight](/quest/m2/stats/preflight.md); + add the demo dashboard and a `moq` CLI sink. +- Re-measure the thresholds in `rs/hang/src/health.rs` once + [Browser reporters](/quest/m2/stats/js.md) publish real numbers. + +## Required + +- [Browser reporters](/quest/m2/stats/js.md) - the browser numbers the limits are measured against diff --git a/quest/m2/stats/rust.md b/quest/m2/stats/rust.md index a629a837e98..a6105d56dc7 100644 --- a/quest/m2/stats/rust.md +++ b/quest/m2/stats/rust.md @@ -47,6 +47,10 @@ - Decided 2026-10-22 (maintainer): the publisher's solicit option moved here from [encoder feedback](/quest/m3/stats-encoder-feedback.md), which keeps only the adaptation loop and reuses `--echo-path`. +- `export --echo` counts no drops in `late`: `Received::report` + (`rs/moq-mux/src/stats.rs`) fills only frames, bytes, and arrival while the + TS release section holds the drops (from + [moq-dev/moq#6654](https://github.com/moq-dev/moq/pull/6654)). ## Related