From e413cf35522a6d882465c65f879647d784ce42eb Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Thu, 22 Oct 2026 10:04:17 -0700 Subject: [PATCH 1/4] quest: plan follow-ups from the 2026-10-22 quest spawn Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 5 +++ quest/m1/ffi-shutdown-sync.md | 40 +++++++++++++++++++ quest/m1/flake-interop-cpp-js.md | 19 +++++++++ quest/m1/flake-resource-instrumentation.md | 23 +++++++++++ quest/m1/interop-coverage/README.md | 2 + .../interop-coverage/js-namespace-withdraw.md | 22 ++++++++++ .../m1/interop-coverage/runner-client-bump.md | 22 ++++++++++ quest/m1/libav-polyfill-fork.md | 23 +++++++++++ quest/m1/obs-test-nightly.md | 17 ++++++++ quest/m2/README.md | 2 + quest/m2/js-imquic-objects.md | 20 ++++++++++ quest/m2/readers-range-live.md | 23 +++++++++++ 12 files changed, 218 insertions(+) create mode 100644 quest/m1/ffi-shutdown-sync.md create mode 100644 quest/m1/flake-interop-cpp-js.md create mode 100644 quest/m1/flake-resource-instrumentation.md create mode 100644 quest/m1/interop-coverage/js-namespace-withdraw.md create mode 100644 quest/m1/interop-coverage/runner-client-bump.md create mode 100644 quest/m1/libav-polyfill-fork.md create mode 100644 quest/m1/obs-test-nightly.md create mode 100644 quest/m2/js-imquic-objects.md create mode 100644 quest/m2/readers-range-live.md diff --git a/quest/m1/README.md b/quest/m1/README.md index e89770e38f3..f3d9decc9e1 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -68,6 +68,7 @@ lite-07 stream type here. - [Rust request credit](/quest/m1/rs-request-credit.md) - a moq-net request fails at once without stream credit instead of waiting - [Generated C bindings](/quest/m1/c/README.md) - C generated from moq-ffi ships as `moq-c` 0.8.0 and replaces the hand-written libmoq - [Exact timestamps in every binding](/quest/m1/binding-timestamps.md) - bindings carry `{value, scale}` timestamps instead of lossy microseconds +- [FFI shutdown requests the drain synchronously](/quest/m1/ffi-shutdown-sync.md) - `shutdown()` becomes a sync drain request awaited with `closed()`, so a dropped future can no longer cancel - [moq-transport passthrough](/quest/m1/ietf-extension/README.md) - object IDs, properties, end status, datagram objects, and unknown track properties survive moq-transport -> moq-relay (and a relay cluster) -> moq-transport; moxygen's moq-test sections 1-7 pass nightly, except cases that use a subgroup other than 0 - [Refresh](/quest/m1/refresh/README.md) - a join asks for a fresh group once the current group's deltas exceed a publisher-advertised byte ratio, at every hop; replaces `Demand::used`/`unused` and moq-json's `delta_ratio` - [Announcement takeover](/quest/m1/announce-takeover.md) - a new independent route explicitly continues instances served through its predecessor, with shared Rust/JS semantics and lite-07 wire @@ -80,6 +81,8 @@ lite-07 stream type here. - [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 - [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 +- [Media resource instrumentation flake](/quest/m1/flake-resource-instrumentation.md) - the media test stops seeing a playing player report nothing to release +- [Interop cpp to js budget](/quest/m1/flake-interop-cpp-js.md) - the cpp -> js cell finishes inside its 30 s budget, fixed at its cause - [A public model](/quest/m1/public-model/README.md) - every model item a built-in session reaches is public, unnecessary, or marked deliberately private, so a custom publisher, subscriber, or relay builds from the public model alone - [FETCH_OK whole group](/quest/m1/ietf-fetch-end-location.md) - on drafts 14 to 19, FETCH_OK End Object 0 means the whole group in both directions, and a FETCH ending at the maximum group is refused as unsupported - [Pause an IETF SUBSCRIBE](/quest/m1/ietf-subscribe-pause.md) - Forward=0 pauses a SUBSCRIBE without demand upstream and Forward=1 resumes it, instead of ending it @@ -107,7 +110,9 @@ lite-07 stream type here. - [moq-net compiles once](/quest/m1/net-erase-transport.md) - the session drivers stop monomorphizing per transport and per crate, saving several MiB of the relay, FFI library, `libmoq` and CLI - [Audio devices on ARM](/quest/m1/audio-devices-arm.md) - `just rs audio-devices` passes on the hosted ARM runner - [CI housekeeping](/quest/m1/ci-housekeeping.md) - validate queue nextest at 24 threads and remove the actionlint queue ignore after its release +- [Nightly OBS TSan suite](/quest/m1/obs-test-nightly.md) - Nightly runs `just obs test` so a broken suite is seen - [Interop audio delivery](/quest/m1/interop-audio.md) - every interop subscriber decodes and checks the publishers' 440 Hz tone, and the Rust publisher sends Opus and AAC +- [libav polyfill fork fix](/quest/m1/libav-polyfill-fork.md) - our polyfill fork copies planar audio correctly and `@moq/hang` drops its patch - [Native audio decode conformance](/quest/m1/audio-decode-conformance.md) - Opus and AAC decode through every moq-audio backend, moq-c, and moq-ffi is checked against known tones and clips, like moq-video's suite - [moq-net internals](/quest/m1/net-internals.md) - no per-group session clones, no transport type parameter in lite and IETF internals, and the `Local` check measured - [Main is no slower than release](/quest/m1/release-perf/README.md) - every benchmark where main is slower than release is fixed or accepted with a reason, checked by a final paired run before the cut diff --git a/quest/m1/ffi-shutdown-sync.md b/quest/m1/ffi-shutdown-sync.md new file mode 100644 index 00000000000..cb88523cf69 --- /dev/null +++ b/quest/m1/ffi-shutdown-sync.md @@ -0,0 +1,40 @@ +# [M] FFI shutdown requests the drain synchronously + +## Goal + +`MoqSession::shutdown()` in moq-ffi is a plain (non-async) call that requests +the draining close before it returns, like `cancel(code)`. A caller waits for +the drain with the existing async `closed()`. Dropping or never polling a +future can no longer turn a shutdown into a cancel. Every binding and wrapper +follows, with a `MIGRATE.md` entry in each affected package. + +## Plan + +Today `shutdown` is async and runs the close through `ffi::detached` +(`rs/moq-ffi/src/ffi.rs`), which aborts its task when the caller drops the +future. The async body only runs on first poll, so a caller that drops the +future early, as OBS's `MoQOutput::Stop` must avoid by holding it, gets a cancel +instead of a drain (found in [moq-dev/moq#6277](https://github.com/moq-dev/moq/pull/6277)). + +Decided 2026-10-22 (maintainer): a synchronous `shutdown()` that only requests +the drain, waited on with `closed()`. Rejected: keeping it async and never +aborting the close (no API change, but the request still waits for a poll), and +an extra `begin_shutdown()` beside the async one (two methods for one action). + +- Start the close on the FFI runtime before `shutdown()` returns, and report a + close that fails through `closed()`. +- Follow the Cross-Package Sync row for `rs/moq-ffi`: `rs/moq-c` (or the + generated C package, whichever ships first), the py, swift, kt, dart, and go + wrappers, `cpp/moq`, `cpp/obs/src` (drop the "keep the future" workaround in + `MoQOutput::Stop`), and `doc/lib/*`. +- Test: a shutdown whose result is never awaited still drains a finished track, + with mocked time, in moq-ffi and through the OBS output test. +- The `release` line's additive async `drain()` + ([FFI shutdown backport](/quest/m0/ffi-shutdown-backport.md)) maps onto this + at the next breaking cut; say so in each MIGRATE entry. + +Public API: breaking in moq-ffi and every binding. Wire: none. + +## Related + +- [FFI shutdown backport](/quest/m0/ffi-shutdown-backport.md) - the release line's async `drain()` diff --git a/quest/m1/flake-interop-cpp-js.md b/quest/m1/flake-interop-cpp-js.md new file mode 100644 index 00000000000..1bf671028a6 --- /dev/null +++ b/quest/m1/flake-interop-cpp-js.md @@ -0,0 +1,19 @@ +# [S] The interop matrix's cpp to js cell stays inside its budget + +## Goal + +The `cpp -> js` cell of `just test interop --all` finishes inside its 30 s +budget on CI, fixed at its cause rather than by raising the budget. + +## Plan + +It took 38 s once in a CI Interop dispatch while working +[moq-dev/moq#6302](https://github.com/moq-dev/moq/pull/6302) (run 39734065658). +Find which phase overran (C++ publisher start, the browser's first frame, or +teardown) from that run's log first, then reproduce under load. + +Public API: none expected. Wire: none. + +## Related + +- [More tests under load](/quest/m1/test-flakes-2/README.md) - the same load round diff --git a/quest/m1/flake-resource-instrumentation.md b/quest/m1/flake-resource-instrumentation.md new file mode 100644 index 00000000000..fe5940619a8 --- /dev/null +++ b/quest/m1/flake-resource-instrumentation.md @@ -0,0 +1,23 @@ +# [S] The media test's resource instrumentation reports what the player holds + +## Goal + +The media interop test's resource instrumentation check passes reliably under +a loaded `just check`, fixed at its cause. It sometimes fails with the player +reporting nothing to release while it is still playing. + +## Plan + +Seen twice locally while working +[moq-dev/moq#6302](https://github.com/moq-dev/moq/pull/6302), once with the +fixture's mono pin and once without, so the pin is unrelated. Reproduce under +load with the diagnostics #6302 added (a failed media window prints each page's +long animation frames and the host's busiest processes), then decide whether +the player drops its resource handles early or the check samples before they +exist. Never widen the check's wait to hide it. + +Public API: none expected. Wire: none. + +## Related + +- [More tests under load](/quest/m1/test-flakes-2/README.md) - the same load round diff --git a/quest/m1/interop-coverage/README.md b/quest/m1/interop-coverage/README.md index 4cda43b181f..b63de7f455d 100644 --- a/quest/m1/interop-coverage/README.md +++ b/quest/m1/interop-coverage/README.md @@ -41,6 +41,8 @@ coverage on `main` at `3ab6cbf81d`. ## Required - [Runner cases](/quest/m1/interop-coverage/runner-cases.md) - our runner clients run data-subgroup-basic and subscribe-namespace-lifecycle +- [JS namespace withdrawal in one process](/quest/m1/interop-coverage/js-namespace-withdraw.md) - moq-dev-js sees NAMESPACE_DONE when publisher and subscriber share a process +- [Runner client bump](/quest/m1/interop-coverage/runner-client-bump.md) - waiting on a moq-tokio release with #5083, then the runner's Rust client stops stamping every object - [Late join and FETCH](/quest/m1/interop-coverage/late-join.md) - a late subscriber gets the current group from object 0, and a standalone FETCH returns a past group exactly - [Control cases](/quest/m1/interop-coverage/control.md) - GOAWAY redirect, TRACK_STATUS, datagrams, and request-ID limits pass across implementations diff --git a/quest/m1/interop-coverage/js-namespace-withdraw.md b/quest/m1/interop-coverage/js-namespace-withdraw.md new file mode 100644 index 00000000000..f2ccc7954ce --- /dev/null +++ b/quest/m1/interop-coverage/js-namespace-withdraw.md @@ -0,0 +1,22 @@ +# [M] moq-dev-js sees a namespace withdrawal from its own process + +## Goal + +The moq-dev-js runner client passes `subscribe-namespace-lifecycle` against +Cloudflare draft-18 and aiomoqt when its publisher and subscriber share one Bun +process, as it already does in two processes or paired with a Rust counterpart. + +## Plan + +Found while working +[moq-dev/moq#6275](https://github.com/moq-dev/moq/pull/6275): in one process +the subscriber never sees NAMESPACE_DONE. Each half passes with a Rust +counterpart, so suspect state shared between the two sessions in js/net or the +WebTransport polyfill. Reproduce with a js/net test first, fix at the cause, and +add the regression test there. + +Public API: none expected. Wire: none. + +## Related + +- [Runner cases](/quest/m1/interop-coverage/runner-cases.md) - added the case to moq-dev-js diff --git a/quest/m1/interop-coverage/runner-client-bump.md b/quest/m1/interop-coverage/runner-client-bump.md new file mode 100644 index 00000000000..3e7a52c04d2 --- /dev/null +++ b/quest/m1/interop-coverage/runner-client-bump.md @@ -0,0 +1,22 @@ +# [XS] The runner's Rust client stops stamping every object + +## Goal + +Condition: a moq-tokio release carries +[moq-dev/moq#5083](https://github.com/moq-dev/moq/pull/5083). Check with +`cargo info moq-tokio` and that release's changelog. + +Then bump the moq-dev-rs client in +[englishm/moq-interop-runner](https://github.com/englishm/moq-interop-runner) +to it, so it stops attaching a Timestamp property to every object, and delete +this quest once that PR merges. + +## Plan + +The released client adds the property, which third-party subscribers count as +an unexpected extension in `data-subgroup-basic`. The interop audit's standing +approval covers PRs touching the `moq-dev-*` builds. + +## Related + +- [Runner cases](/quest/m1/interop-coverage/runner-cases.md) - the cases this keeps green diff --git a/quest/m1/libav-polyfill-fork.md b/quest/m1/libav-polyfill-fork.md new file mode 100644 index 00000000000..2508089dd4f --- /dev/null +++ b/quest/m1/libav-polyfill-fork.md @@ -0,0 +1,23 @@ +# [XS] Fix the libav polyfill's planar copy in our fork + +## Goal + +The `@kixelated` fork of libavjs-webcodecs-polyfill converts interleaved +samples to planar from the right offset, a release of it is published, and +`@moq/hang` drops the copy patch that works around it. + +## Plan + +Found by [moq-dev/moq#6284](https://github.com/moq-dev/moq/pull/6284): the +polyfill garbles every channel after the first, so stereo Opus under Node, Bun, +or a browser without `AudioDecoder` lost its right channel. #6284 patches the +conversion in `Util.Libav.polyfill()` with a regression test; keep that test +when the patch goes. + +Decided 2026-10-22 (maintainer): fix it in the fork only; post nothing upstream. + +Public API: none. Wire: none. + +## Related + +- [Interop audio delivery](/quest/m1/interop-audio.md) - found it and carries the interim patch diff --git a/quest/m1/obs-test-nightly.md b/quest/m1/obs-test-nightly.md new file mode 100644 index 00000000000..5fb18ee3ae7 --- /dev/null +++ b/quest/m1/obs-test-nightly.md @@ -0,0 +1,17 @@ +# [XS] Nightly runs the OBS TSan suite + +## Goal + +A Nightly job runs `just obs test` (the OBS plugin's ThreadSanitizer suite) +and its failure is visible like any other Nightly lane. + +## Plan + +Nothing ran it, so it failed every time on `main` unnoticed until +[moq-dev/moq#6277](https://github.com/moq-dev/moq/pull/6277) fixed its +suppression rule. Add it to the Nightly recipe matrix in +`.github/workflows/nightly.yml` with the `.#obs` shell it needs, and record its +runtime; a loaded TSan run of `moq-output-test` can take 60 to 90 s instead of +about 8. + +Public API: none. Wire: none. diff --git a/quest/m2/README.md b/quest/m2/README.md index c6dbabf0107..2ea7afd6d0a 100644 --- a/quest/m2/README.md +++ b/quest/m2/README.md @@ -87,6 +87,7 @@ ranked just below deterministic TS legs, which it requires. - [Android capture](/quest/m2/mobile-capture-android.md) - Rust captures through NDK/JNI on Android, reusing the existing codecs and setting the catalog rotation - [Time stretch](/quest/m2/watch-audio-time-stretch.md) - js/watch: the audio ring converges by time-stretching instead of skipping or going silent - [Audio join budget](/quest/m2/audio-join-budget.md) - `moq-audio` joining at the latest group loses no group a publisher bursts before its budget widens +- [Latest readers use Range::live()](/quest/m2/readers-range-live.md) - after #6278, readers start at the live edge without waiting on `largest()` - [Media QA audio cases](/quest/m2/media-qa-audio.md) - AAC, audio codec/rate/channel changes, rendition switches, output mute/volume, and a native publisher's A/V sync are graded like the video cases - [Audio outlives video](/quest/m2/audio-bufferbloat-av.md) - under bufferbloat audio stays within budget while video may skip, rendered frames stay in sync, and native audio rows are enforced - [ViSQOL grading](/quest/m2/audio-visqol.md) - the nightly scores played audio against a reference clip and fails below measured floors @@ -101,6 +102,7 @@ ranked just below deterministic TS legs, which it requires. - [Dart on iOS](/quest/m2/dart-ios.md) - prove the shipped iOS native asset actually loads on a device, which no CI can - [Mobile completion](/quest/m2/mobile-completion.md) - verify the Swift and Kotlin bindings over Rust-owned capture - [Bindings in the interop matrix](/quest/m2/interop-bindings.md) - Kotlin, Swift, and Dart publish and subscribe against every other interop client +- [moq-dev-js receives from imquic](/quest/m2/js-imquic-objects.md) - the JS runner client gets objects from imquic over draft-22 - [WebGPU HDR](/quest/m2/webgpu-hdr.md) - HDR renditions play as HDR where the browser and display can show it, and tone-map to SDR elsewhere - [One port](/quest/m2/one-port/README.md) - one UDP port carries QUIC, SRT, and WebRTC media through an embedder hook, and one TCP port carries HTTP, RTMP, and RTMPS - [QUIC caps](/quest/m2/rate-quic.md) - paced MAX_DATA credit in and a capped pacer out hold a QUIC session to its token's bitrate diff --git a/quest/m2/js-imquic-objects.md b/quest/m2/js-imquic-objects.md new file mode 100644 index 00000000000..38a69139db4 --- /dev/null +++ b/quest/m2/js-imquic-objects.md @@ -0,0 +1,20 @@ +# [S] moq-dev-js receives objects from imquic + +## Goal + +The moq-dev-js runner client passes `data-subgroup-basic` against imquic +(draft-22 over WebTransport), as moq-dev-rs already does. + +## Plan + +Found while working +[moq-dev/moq#6275](https://github.com/moq-dev/moq/pull/6275): the JS client +gets no objects at all. Capture what imquic sends (stream types, subgroup +headers) and compare against what js/net accepts on draft-22 before deciding +which side is wrong. + +Public API: none expected. Wire: none on our side unless js/net misreads draft-22. + +## Related + +- [Interop coverage](/quest/m1/interop-coverage/README.md) - the cases and clients diff --git a/quest/m2/readers-range-live.md b/quest/m2/readers-range-live.md new file mode 100644 index 00000000000..2f90f6d2944 --- /dev/null +++ b/quest/m2/readers-range-live.md @@ -0,0 +1,23 @@ +# [S] Latest readers subscribe with Range::live() + +## Goal + +Condition: [moq-dev/moq#6278](https://github.com/moq-dev/moq/pull/6278) has +merged, so `Range::live()` starts at the live edge on a warm relay copy too. + +Then the readers that wait for `largest()` and raise their floor to start at +the newest group (moq-audio, moq-video, `moq play`, moq-room chat) subscribe +with `Range::live()` instead, with no change in what they play. + +## Plan + +Inventory with `rg 'largest\(\)' rs/` first; keep any caller that needs the +position itself rather than a start. Each reader keeps its existing tests, +plus one against a warm relay copy. + +Public API: none expected. Wire: none. + +## Related + +- [Audio join budget](/quest/m2/audio-join-budget.md) - moq-audio's join at the latest group +- [Track live signal](/quest/m1/track-live.md) - the fix this builds on From 54c45bb10063ee79a41c082dde704987cf8025a2 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Thu, 22 Oct 2026 11:27:51 -0700 Subject: [PATCH 2/4] quest: move the runner client bump to release execution; readers keep lookbacks and cover JS chat Co-Authored-By: Claude Opus 5.5 --- quest/m1/interop-coverage/README.md | 2 +- quest/m2/readers-range-live.md | 21 +++++++++++++------ quest/m2/release/README.md | 1 + .../release}/runner-client-bump.md | 3 ++- 4 files changed, 19 insertions(+), 8 deletions(-) rename quest/{m1/interop-coverage => m2/release}/runner-client-bump.md (83%) diff --git a/quest/m1/interop-coverage/README.md b/quest/m1/interop-coverage/README.md index b63de7f455d..12004fd8aef 100644 --- a/quest/m1/interop-coverage/README.md +++ b/quest/m1/interop-coverage/README.md @@ -42,11 +42,11 @@ coverage on `main` at `3ab6cbf81d`. - [Runner cases](/quest/m1/interop-coverage/runner-cases.md) - our runner clients run data-subgroup-basic and subscribe-namespace-lifecycle - [JS namespace withdrawal in one process](/quest/m1/interop-coverage/js-namespace-withdraw.md) - moq-dev-js sees NAMESPACE_DONE when publisher and subscriber share a process -- [Runner client bump](/quest/m1/interop-coverage/runner-client-bump.md) - waiting on a moq-tokio release with #5083, then the runner's Rust client stops stamping every object - [Late join and FETCH](/quest/m1/interop-coverage/late-join.md) - a late subscriber gets the current group from object 0, and a standalone FETCH returns a past group exactly - [Control cases](/quest/m1/interop-coverage/control.md) - GOAWAY redirect, TRACK_STATUS, datagrams, and request-ID limits pass across implementations ## Related +- [Runner client bump](/quest/m2/release/runner-client-bump.md) - after the cut publishes #5083, the runner's Rust client stops stamping every object - [Interop audit](/quest/m0/audit-interop.md) - classifies the red cells these cases produce - [moq-transport passthrough](/quest/m1/ietf-extension/README.md) - Moxygen's moq-test conformance through moq-relay diff --git a/quest/m2/readers-range-live.md b/quest/m2/readers-range-live.md index 2f90f6d2944..46aedef9e38 100644 --- a/quest/m2/readers-range-live.md +++ b/quest/m2/readers-range-live.md @@ -1,22 +1,31 @@ -# [S] Latest readers subscribe with Range::live() +# [S] Latest readers subscribe with a relative range ## Goal Condition: [moq-dev/moq#6278](https://github.com/moq-dev/moq/pull/6278) has merged, so `Range::live()` starts at the live edge on a warm relay copy too. -Then the readers that wait for `largest()` and raise their floor to start at -the newest group (moq-audio, moq-video, `moq play`, moq-room chat) subscribe -with `Range::live()` instead, with no change in what they play. +Then the readers that wait for the largest group and raise their floor to +start near it (moq-audio, moq-video, `moq play`, and both moq-room and +`@moq/room` chat) subscribe with a relative range instead, with no change in +what they play: `Range::live()` for a start at the newest group, and a +relative start for a reader that looks back, such as moq-video's warmup lane, +which keeps its one-group lookback so the preceding intra-refresh group still +decodes. ## Plan -Inventory with `rg 'largest\(\)' rs/` first; keep any caller that needs the -position itself rather than a start. Each reader keeps its existing tests, +Inventory with `rg 'largest\(|poll_largest' rs/ js/` first, since Rust chat +polls rather than awaits; keep any caller that needs the position itself +rather than a start. Each reader keeps its existing tests, plus one against a warm relay copy. Public API: none expected. Wire: none. +## Required + +- [JS ranges](/quest/m1/subscribe-ranges/js.md) - `@moq/room` chat needs relative ranges in `@moq/net` + ## Related - [Audio join budget](/quest/m2/audio-join-budget.md) - moq-audio's join at the latest group diff --git a/quest/m2/release/README.md b/quest/m2/release/README.md index b7a3bb4a310..08025d660f7 100644 --- a/quest/m2/release/README.md +++ b/quest/m2/release/README.md @@ -40,3 +40,4 @@ production stability proven merely because upstream artifacts published. - [Retire hand-written C](/quest/m2/release/c-retire.md) - delete the hand-written crate once generated C publishes - [Retire the web-transport JS qmux](/quest/m2/release/qmux-js-retire.md) - once `@moq/qmux` publishes from `js/qmux`, deprecate `@moq/web-socket-stream` and stop the second publisher - [moq.sh deployment](/quest/m2/release/moq-sh-deploy.md) - verify its release-triggered publication +- [Runner client bump](/quest/m2/release/runner-client-bump.md) - the upstream interop runner's Rust client moves to the published moq-tokio, so it stops stamping every object diff --git a/quest/m1/interop-coverage/runner-client-bump.md b/quest/m2/release/runner-client-bump.md similarity index 83% rename from quest/m1/interop-coverage/runner-client-bump.md rename to quest/m2/release/runner-client-bump.md index 3e7a52c04d2..66649d4cc4a 100644 --- a/quest/m1/interop-coverage/runner-client-bump.md +++ b/quest/m2/release/runner-client-bump.md @@ -3,7 +3,8 @@ ## Goal Condition: a moq-tokio release carries -[moq-dev/moq#5083](https://github.com/moq-dev/moq/pull/5083). Check with +[moq-dev/moq#5083](https://github.com/moq-dev/moq/pull/5083), a breaking +change on `main` that publishes only with the next cut. Check with `cargo info moq-tokio` and that release's changelog. Then bump the moq-dev-rs client in From 7850271b13286d39accce863c9665a2955533b68 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Thu, 22 Oct 2026 13:20:47 -0700 Subject: [PATCH 3/4] quest: drop the link to the finished interop-audio quest Co-Authored-By: Claude Opus 5.5 --- quest/m1/libav-polyfill-fork.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/quest/m1/libav-polyfill-fork.md b/quest/m1/libav-polyfill-fork.md index 2508089dd4f..2f65d9dfeb6 100644 --- a/quest/m1/libav-polyfill-fork.md +++ b/quest/m1/libav-polyfill-fork.md @@ -17,7 +17,3 @@ when the patch goes. Decided 2026-10-22 (maintainer): fix it in the fork only; post nothing upstream. Public API: none. Wire: none. - -## Related - -- [Interop audio delivery](/quest/m1/interop-audio.md) - found it and carries the interim patch From 4c13c3a0e349774c3108e89432cd605f3c28000a Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Thu, 22 Oct 2026 13:38:54 -0700 Subject: [PATCH 4/4] quest: defer duplicates to #6275, nest flakes under test-flakes-2 Drop js-namespace-withdraw and js-imquic-objects, which #6275 owns. Move the two load flakes into test-flakes-2 as its children, and link ffi-shutdown-sync to the MIGRATE quest that must describe its final shape. Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 2 -- quest/m1/ffi-shutdown-sync.md | 1 + quest/m1/interop-coverage/README.md | 1 - .../interop-coverage/js-namespace-withdraw.md | 22 ------------------- quest/m1/test-flakes-2/README.md | 7 +++++- .../interop-cpp-js.md} | 4 ---- .../resource-instrumentation.md} | 4 ---- quest/m2/README.md | 1 - quest/m2/js-imquic-objects.md | 20 ----------------- 9 files changed, 7 insertions(+), 55 deletions(-) delete mode 100644 quest/m1/interop-coverage/js-namespace-withdraw.md rename quest/m1/{flake-interop-cpp-js.md => test-flakes-2/interop-cpp-js.md} (85%) rename quest/m1/{flake-resource-instrumentation.md => test-flakes-2/resource-instrumentation.md} (89%) delete mode 100644 quest/m2/js-imquic-objects.md diff --git a/quest/m1/README.md b/quest/m1/README.md index 175fa039aa7..ec097a5ebdd 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -91,8 +91,6 @@ tracks, so per-group stats stop costing cluster announces. - [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 - [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 -- [Media resource instrumentation flake](/quest/m1/flake-resource-instrumentation.md) - the media test stops seeing a playing player report nothing to release -- [Interop cpp to js budget](/quest/m1/flake-interop-cpp-js.md) - the cpp -> js cell finishes inside its 30 s budget, fixed at its cause - [A public model](/quest/m1/public-model/README.md) - every model item a built-in session reaches is public, unnecessary, or marked deliberately private, so a custom publisher, subscriber, or relay builds from the public model alone - [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 has its MIGRATE entry - [FETCH_OK whole group](/quest/m1/ietf-fetch-end-location.md) - on drafts 14 to 19, FETCH_OK End Object 0 means the whole group in both directions, and a FETCH ending at the maximum group is refused as unsupported diff --git a/quest/m1/ffi-shutdown-sync.md b/quest/m1/ffi-shutdown-sync.md index cb88523cf69..5671aa784a6 100644 --- a/quest/m1/ffi-shutdown-sync.md +++ b/quest/m1/ffi-shutdown-sync.md @@ -38,3 +38,4 @@ Public API: breaking in moq-ffi and every binding. Wire: none. ## Related - [FFI shutdown backport](/quest/m0/ffi-shutdown-backport.md) - the release line's async `drain()` +- [MIGRATE matches release](/quest/m1/api-audit/migrate.md) - plans entries saying `shutdown` became an async `Result`; they must describe the final sync shape instead diff --git a/quest/m1/interop-coverage/README.md b/quest/m1/interop-coverage/README.md index 12004fd8aef..9a5c09ce0a4 100644 --- a/quest/m1/interop-coverage/README.md +++ b/quest/m1/interop-coverage/README.md @@ -41,7 +41,6 @@ coverage on `main` at `3ab6cbf81d`. ## Required - [Runner cases](/quest/m1/interop-coverage/runner-cases.md) - our runner clients run data-subgroup-basic and subscribe-namespace-lifecycle -- [JS namespace withdrawal in one process](/quest/m1/interop-coverage/js-namespace-withdraw.md) - moq-dev-js sees NAMESPACE_DONE when publisher and subscriber share a process - [Late join and FETCH](/quest/m1/interop-coverage/late-join.md) - a late subscriber gets the current group from object 0, and a standalone FETCH returns a past group exactly - [Control cases](/quest/m1/interop-coverage/control.md) - GOAWAY redirect, TRACK_STATUS, datagrams, and request-ID limits pass across implementations diff --git a/quest/m1/interop-coverage/js-namespace-withdraw.md b/quest/m1/interop-coverage/js-namespace-withdraw.md deleted file mode 100644 index f2ccc7954ce..00000000000 --- a/quest/m1/interop-coverage/js-namespace-withdraw.md +++ /dev/null @@ -1,22 +0,0 @@ -# [M] moq-dev-js sees a namespace withdrawal from its own process - -## Goal - -The moq-dev-js runner client passes `subscribe-namespace-lifecycle` against -Cloudflare draft-18 and aiomoqt when its publisher and subscriber share one Bun -process, as it already does in two processes or paired with a Rust counterpart. - -## Plan - -Found while working -[moq-dev/moq#6275](https://github.com/moq-dev/moq/pull/6275): in one process -the subscriber never sees NAMESPACE_DONE. Each half passes with a Rust -counterpart, so suspect state shared between the two sessions in js/net or the -WebTransport polyfill. Reproduce with a js/net test first, fix at the cause, and -add the regression test there. - -Public API: none expected. Wire: none. - -## Related - -- [Runner cases](/quest/m1/interop-coverage/runner-cases.md) - added the case to moq-dev-js diff --git a/quest/m1/test-flakes-2/README.md b/quest/m1/test-flakes-2/README.md index 4a756d41ddf..fd5086a45a0 100644 --- a/quest/m1/test-flakes-2/README.md +++ b/quest/m1/test-flakes-2/README.md @@ -1,4 +1,4 @@ -# [S] More tests hold up under load +# More tests hold up under load ## Goal @@ -37,6 +37,11 @@ in one child. 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 +- [Interop cpp to js budget](/quest/m1/test-flakes-2/interop-cpp-js.md) - the cpp -> js cell finishes inside its 30 s budget, fixed at its cause + ## Related - [Controlled time](/quest/m1/time/README.md) - the systemic fix these rules ask for: every crate on a controlled clock diff --git a/quest/m1/flake-interop-cpp-js.md b/quest/m1/test-flakes-2/interop-cpp-js.md similarity index 85% rename from quest/m1/flake-interop-cpp-js.md rename to quest/m1/test-flakes-2/interop-cpp-js.md index 1bf671028a6..d1fb9ccd257 100644 --- a/quest/m1/flake-interop-cpp-js.md +++ b/quest/m1/test-flakes-2/interop-cpp-js.md @@ -13,7 +13,3 @@ Find which phase overran (C++ publisher start, the browser's first frame, or teardown) from that run's log first, then reproduce under load. Public API: none expected. Wire: none. - -## Related - -- [More tests under load](/quest/m1/test-flakes-2/README.md) - the same load round diff --git a/quest/m1/flake-resource-instrumentation.md b/quest/m1/test-flakes-2/resource-instrumentation.md similarity index 89% rename from quest/m1/flake-resource-instrumentation.md rename to quest/m1/test-flakes-2/resource-instrumentation.md index fe5940619a8..f374199391b 100644 --- a/quest/m1/flake-resource-instrumentation.md +++ b/quest/m1/test-flakes-2/resource-instrumentation.md @@ -17,7 +17,3 @@ the player drops its resource handles early or the check samples before they exist. Never widen the check's wait to hide it. Public API: none expected. Wire: none. - -## Related - -- [More tests under load](/quest/m1/test-flakes-2/README.md) - the same load round diff --git a/quest/m2/README.md b/quest/m2/README.md index f21bc12c6ac..c0c5242a44f 100644 --- a/quest/m2/README.md +++ b/quest/m2/README.md @@ -105,7 +105,6 @@ ranked just below deterministic TS legs, which it requires. - [Dart on iOS](/quest/m2/dart-ios.md) - prove the shipped iOS native asset actually loads on a device, which no CI can - [Mobile completion](/quest/m2/mobile-completion.md) - verify the Swift and Kotlin bindings over Rust-owned capture - [Bindings in the interop matrix](/quest/m2/interop-bindings.md) - Kotlin, Swift, and Dart publish and subscribe against every other interop client -- [moq-dev-js receives from imquic](/quest/m2/js-imquic-objects.md) - the JS runner client gets objects from imquic over draft-22 - [WebGPU HDR](/quest/m2/webgpu-hdr.md) - HDR renditions play as HDR where the browser and display can show it, and tone-map to SDR elsewhere - [One port](/quest/m2/one-port/README.md) - one UDP port carries QUIC, SRT, and WebRTC media through an embedder hook, and one TCP port carries HTTP, RTMP, and RTMPS - [qmux receive leases](/quest/m2/qmux-receive-lease.md) - WebSocket, TCP, and WebRTC sessions bound incomplete messages by their receive window, at a per-session cost the maintainer picks diff --git a/quest/m2/js-imquic-objects.md b/quest/m2/js-imquic-objects.md deleted file mode 100644 index 38a69139db4..00000000000 --- a/quest/m2/js-imquic-objects.md +++ /dev/null @@ -1,20 +0,0 @@ -# [S] moq-dev-js receives objects from imquic - -## Goal - -The moq-dev-js runner client passes `data-subgroup-basic` against imquic -(draft-22 over WebTransport), as moq-dev-rs already does. - -## Plan - -Found while working -[moq-dev/moq#6275](https://github.com/moq-dev/moq/pull/6275): the JS client -gets no objects at all. Capture what imquic sends (stream types, subgroup -headers) and compare against what js/net accepts on draft-22 before deciding -which side is wrong. - -Public API: none expected. Wire: none on our side unless js/net misreads draft-22. - -## Related - -- [Interop coverage](/quest/m1/interop-coverage/README.md) - the cases and clients