From 50913ca20636506c9b80251d588d0874aa5dc342 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 28 Oct 2026 22:12:44 -0700 Subject: [PATCH 1/2] quest: plan CLI media modes and the resolve follow-ups CLI `--video`/`--audio` take on|demand|off, C routes carry their epoch, smoke clients wait on the binding release, moq-hls follows once, moq-bench pins epochs, plus Plan notes in migrate-audit, raw-audio and land. Co-Authored-By: Claude Opus 5.5 --- quest/m0/ci/land.md | 4 +++ quest/m1/c/README.md | 1 + quest/m1/c/route-epoch.md | 27 ++++++++++++++++++++ quest/m1/eager-encode/README.md | 1 + quest/m1/eager-encode/cli-modes.md | 30 +++++++++++++++++++++++ quest/m1/eager-encode/raw-audio.md | 4 +++ quest/m2/README.md | 2 ++ quest/m2/bench-epoch-pin.md | 16 ++++++++++++ quest/m2/hls-follow-once.md | 22 +++++++++++++++++ quest/m2/release/README.md | 1 + quest/m2/release/migrate-audit.md | 4 +++ quest/m2/release/smoke-bindings-rename.md | 19 ++++++++++++++ 12 files changed, 131 insertions(+) create mode 100644 quest/m1/c/route-epoch.md create mode 100644 quest/m1/eager-encode/cli-modes.md create mode 100644 quest/m2/bench-epoch-pin.md create mode 100644 quest/m2/hls-follow-once.md create mode 100644 quest/m2/release/smoke-bindings-rename.md diff --git a/quest/m0/ci/land.md b/quest/m0/ci/land.md index ba27e1d97e..e9201baf2c 100644 --- a/quest/m0/ci/land.md +++ b/quest/m0/ci/land.md @@ -82,6 +82,10 @@ Decided 2026-10-26 (maintainer): review, and moq-bot joins that bypass list here. Decide with the bypass list whether `main` keeps deploying to `publish`, or publishing narrows to `release` and release tags. Ask the maintainer; settings changes are theirs. +- The gate tests each PR on the latest `main`, not the PR's own base. On + 2026-10-29 [moq-dev/moq#7162](https://github.com/moq-dev/moq/pull/7162) + passed its own CI but broke in the queue on API renames that landed after + its last base merge; that is the case the gate must catch before `main`. Work in this repository: diff --git a/quest/m1/c/README.md b/quest/m1/c/README.md index a8a62969b3..ba886d6f5a 100644 --- a/quest/m1/c/README.md +++ b/quest/m1/c/README.md @@ -32,3 +32,4 @@ Public API: moq-c gains each m1 binding feature. Wire: none. - [moq-c decode start](/quest/m1/c/decode-start.md) - a moq-c decoder can read a finished track from its start - [JSON windows](/quest/m1/c/json-window.md) - moq-c publishes and reads moq-json windows, as moq-ffi does - [Announce route](/quest/m1/c/announce-route.md) - a C publisher announces with a cost and restart epoch through its own struct, and cannot claim relay hops +- [Route epochs](/quest/m1/c/route-epoch.md) - a received `moq_route` carries its epoch, so a C subscriber can pin what it saw announced diff --git a/quest/m1/c/route-epoch.md b/quest/m1/c/route-epoch.md new file mode 100644 index 0000000000..9f90384fa6 --- /dev/null +++ b/quest/m1/c/route-epoch.md @@ -0,0 +1,27 @@ +# [S] moq-c routes carry their epoch + +## Goal + +A received `moq_route` exposes its epoch, as moq-ffi's `MoqRoute` does, so a C +subscriber can pin `moq_origin_request` or `moq_origin_follow` to the +instance it saw announced. + +## Plan + +Decided 2026-10-29 (maintainer), a follow-up of +[moq-dev/moq#7193](https://github.com/moq-dev/moq/pull/7193), which gave the +C resolutions an optional epoch. Today a C caller can pin only an epoch it got +elsewhere: received routes carry none. In m1, since moq-c ships at the cut +with parity with moq-ffi. + +[Announce route](/quest/m1/c/announce-route.md) adds minting and announcing +an epoch. This quest covers the receiving side. Expose the epoch as UUIDv7 +text, as the resolutions take it, and test that a pinned request built from a +received route refuses another instance. + +Public API: additive in the C ABI, or breaking if `moq_route`'s layout +changes; record which. Wire: none. + +## Related + +- [Announce route](/quest/m1/c/announce-route.md) - the publishing side's epoch diff --git a/quest/m1/eager-encode/README.md b/quest/m1/eager-encode/README.md index 64a29d37dd..dd7228f7a5 100644 --- a/quest/m1/eager-encode/README.md +++ b/quest/m1/eager-encode/README.md @@ -50,6 +50,7 @@ The epic's own work, once the children land: ## Required - [@moq/publish encodes while enabled](/quest/m1/eager-encode/js.md) - audio and video encoders drop the demand gate, with an on-demand opt-in +- [The CLI picks each medium's mode](/quest/m1/eager-encode/cli-modes.md) - `--video`/`--audio` take `on|demand|off` in capture and `on|off` in export and play, replacing `--no-*` and `--on-demand` - [Raw audio on demand](/quest/m1/eager-encode/raw-audio.md) - audio encodes on demand again, from raw frames kept up to `maxAge` ## Related diff --git a/quest/m1/eager-encode/cli-modes.md b/quest/m1/eager-encode/cli-modes.md new file mode 100644 index 0000000000..1f8f8046b8 --- /dev/null +++ b/quest/m1/eager-encode/cli-modes.md @@ -0,0 +1,30 @@ +# [S] The CLI picks each medium's mode with --video and --audio + +## Goal + +`moq import capture` takes `--video ` and +`--audio `, default `on`, in place of `--no-video`, +`--no-audio`, and `--on-demand`. `export` and `play` take `--video ` +and `--audio ` in place of `--no-video` and `--no-audio`. One +vocabulary across the CLI. + +## Plan + +Decided 2026-10-29 (maintainer), right after +[moq-dev/moq#7188](https://github.com/moq-dev/moq/pull/7188) shipped +`--on-demand`, which reads vaguely and cannot say which medium it means. + +- `on` encodes for the whole publish, `demand` only while subscribed (each + library's `Capture::on_demand`), and `off` publishes no track of that + medium. Rejected names: `always`, `never`, `none`, `--video-enabled`, + `--video-encode`. +- [Raw audio on demand](/quest/m1/eager-encode/raw-audio.md) later adds + `buffered` to `--audio` and makes it audio's default, so per-medium flags + avoid a second rename. If raw audio lands first, include `buffered` here. +- In `export` and `play`, `off` keeps today's `--no-*` meaning: select no + rendition of that medium. Keep the existing refusals, such as an + elementary-stream export with no video. +- Update `doc/bin/cli.md`, `--help`, the tests, and every in-tree script or + doc that passes the old flags. + +Public API: breaking CLI flags, with an Impact migration note. Wire: none. diff --git a/quest/m1/eager-encode/raw-audio.md b/quest/m1/eager-encode/raw-audio.md index d82035b62d..7707b468fd 100644 --- a/quest/m1/eager-encode/raw-audio.md +++ b/quest/m1/eager-encode/raw-audio.md @@ -24,6 +24,10 @@ on-demand saved, without losing the past. - JS (`js/publish/src/audio/encoder.ts`) and Rust (`rs/moq-audio` capture) both switch. The always-on default from their sibling quests becomes the opt-out. +- The CLI's audio mode gains `buffered` as its default (decided + 2026-10-29). If [The CLI picks each medium's mode](/quest/m1/eager-encode/cli-modes.md) + has landed, add it to `--audio`; otherwise that quest adds it. Update + `--help` and `doc/bin/cli.md`. Tests: no subscriber for a few seconds, then a subscriber with `maxDelay` covering the last second receives that second, timestamps matching capture diff --git a/quest/m2/README.md b/quest/m2/README.md index 1751b2c37d..44e9ebb50c 100644 --- a/quest/m2/README.md +++ b/quest/m2/README.md @@ -248,3 +248,5 @@ lite-07; bitrate enforcement is not part of this release. - [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 - [Open-GOP MPEG-2 export](/quest/m2/mpeg2-open-gop-export.md) - a TS export resuming in an open GOP trims the B-pictures that reference the previous one +- [The HLS server follows each path once](/quest/m2/hls-follow-once.md) - `Following` reports synced absence, so moq-hls resolves with one follow +- [moq-bench pins the instances it measures](/quest/m2/bench-epoch-pin.md) - pooled requests pin their announced epoch, so a takeover is not counted as the same broadcast diff --git a/quest/m2/bench-epoch-pin.md b/quest/m2/bench-epoch-pin.md new file mode 100644 index 0000000000..c7ac12d321 --- /dev/null +++ b/quest/m2/bench-epoch-pin.md @@ -0,0 +1,16 @@ +# [XS] moq-bench pins the instances it measures + +## Goal + +moq-bench requests each pooled broadcast pinned to the epoch it saw +announced, so a takeover between gathering and requesting is not counted as +the same broadcast. + +## Plan + +Decided 2026-10-29 (maintainer), a follow-up of +[moq-dev/moq#7192](https://github.com/moq-dev/moq/pull/7192). Pass the +announced epoch to `request`. A pinned request that finds another instance is +refused; count that as a takeover, not a failure. + +Public API: none. Wire: none. diff --git a/quest/m2/hls-follow-once.md b/quest/m2/hls-follow-once.md new file mode 100644 index 0000000000..88992d2b0f --- /dev/null +++ b/quest/m2/hls-follow-once.md @@ -0,0 +1,22 @@ +# [S] The HLS server follows each path once + +## Goal + +The moq-hls server resolves a path once, with one `follow`, instead of a +`request` for the first answer and a separate follower for takeovers. It +still reports a path nothing serves once discovery has synced. + +## Plan + +Decided 2026-10-29 (maintainer), a follow-up of +[moq-dev/moq#7192](https://github.com/moq-dev/moq/pull/7192). The server needs +`request` today only because `Following` cannot say "discovery has synced and +nothing serves this path". Add that report to `Following`, the synced absence +`request` already answers with `Unroutable`, without making a follower give up. +Then move the server onto it. After the cut, since the double resolve works. + +Tests: an unserved path is reported once discovery syncs, a takeover is +followed without a second resolution, and the hand-written resolve timeout +stays only a limit on a handler that never answers. + +Public API: additive in moq-net. Wire: none. diff --git a/quest/m2/release/README.md b/quest/m2/release/README.md index 2ad1e5bd63..106836c1cd 100644 --- a/quest/m2/release/README.md +++ b/quest/m2/release/README.md @@ -43,5 +43,6 @@ production stability proven merely because upstream artifacts published. - [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 +- [Smoke clients use request and follow](/quest/m2/release/smoke-bindings-rename.md) - condition: a binding release ships the renames; then the native smoke clients move to them - [Relay loader adoption](/quest/m2/release/relay-loader-adoption.md) - once their pins carry it, embedding consumers load relay config through `Config::merge` and refuse obsolete spellings - [Release provenance](/quest/m2/release/provenance.md) - attached binary archives carry build provenance attestations diff --git a/quest/m2/release/migrate-audit.md b/quest/m2/release/migrate-audit.md index 0b977ffa70..7ee5d432c3 100644 --- a/quest/m2/release/migrate-audit.md +++ b/quest/m2/release/migrate-audit.md @@ -18,6 +18,10 @@ m1 quest on 2026-10-22. for its migration note, since squash commits drop the PR body. Write each note into its package's guide. The API-diff report below catches breaks a PR left unmarked; a behavior break with no `!` stays with PR review. +- Correct Unreleased entries that a later PR overturned. Known: `js/net/MIGRATE.md` + still describes `request(path, { announced: true })`, which + [moq-dev/moq#7173](https://github.com/moq-dev/moq/pull/7173) replaced with + `follow(path)` (decided 2026-10-29). - Run the API-diff report on the cut PR and read the diff of the hand-written binding wrappers (`py/moq-rs`, `kt/moq`, `dart/moq`, `go/wrapper`, `swift`, `cpp/moq`, `cpp/obs`) and of each binary's flags, diff --git a/quest/m2/release/smoke-bindings-rename.md b/quest/m2/release/smoke-bindings-rename.md new file mode 100644 index 0000000000..ed19a6df13 --- /dev/null +++ b/quest/m2/release/smoke-bindings-rename.md @@ -0,0 +1,19 @@ +# [XS] Smoke clients use request and follow + +## Goal + +Condition: a binding release ships the `request` and `follow` names from +[moq-dev/moq#7193](https://github.com/moq-dev/moq/pull/7193). Check each +registry's latest moq-ffi-based package (Go, Python, Kotlin, Swift, C) for +`request`/`follow`. Then move `test/smoke/clients/{go,python,kotlin,swift,c}` +off `request_broadcast` and `announced_broadcast`, and delete this quest. + +## Plan + +Decided 2026-10-29 (maintainer). The smoke clients install published packages +(see `test/smoke/AGENTS.md`), so they cannot move until the rename ships. +[moq-dev/moq#7173](https://github.com/moq-dev/moq/pull/7173) handled the JS +smoke client the same way. If a client must run against both old and new +releases for a while, detect the method, as the JS compat client does. + +Public API: none. Wire: none. From fef89a6d8ad77f11021ad7cdf438dd37a36702d3 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Thu, 29 Oct 2026 08:25:17 -0700 Subject: [PATCH 2/2] quest: drop route-epoch, delivered by #7151 moq-dev/moq#7151 landed on main and already fills moq_route's epoch for every received announcement, so the planned receiving-side quest has no work left. Co-Authored-By: Claude Opus 5.5 --- quest/m1/c/README.md | 1 - quest/m1/c/route-epoch.md | 27 --------------------------- 2 files changed, 28 deletions(-) delete mode 100644 quest/m1/c/route-epoch.md diff --git a/quest/m1/c/README.md b/quest/m1/c/README.md index c08dec0e34..af4cbf2d37 100644 --- a/quest/m1/c/README.md +++ b/quest/m1/c/README.md @@ -31,4 +31,3 @@ Public API: moq-c gains each m1 binding feature. Wire: none. - [moq-c decode start](/quest/m1/c/decode-start.md) - a moq-c decoder can read a finished track from its start - [JSON windows](/quest/m1/c/json-window.md) - moq-c publishes and reads moq-json windows, as moq-ffi does -- [Route epochs](/quest/m1/c/route-epoch.md) - a received `moq_route` carries its epoch, so a C subscriber can pin what it saw announced diff --git a/quest/m1/c/route-epoch.md b/quest/m1/c/route-epoch.md deleted file mode 100644 index 9f90384fa6..0000000000 --- a/quest/m1/c/route-epoch.md +++ /dev/null @@ -1,27 +0,0 @@ -# [S] moq-c routes carry their epoch - -## Goal - -A received `moq_route` exposes its epoch, as moq-ffi's `MoqRoute` does, so a C -subscriber can pin `moq_origin_request` or `moq_origin_follow` to the -instance it saw announced. - -## Plan - -Decided 2026-10-29 (maintainer), a follow-up of -[moq-dev/moq#7193](https://github.com/moq-dev/moq/pull/7193), which gave the -C resolutions an optional epoch. Today a C caller can pin only an epoch it got -elsewhere: received routes carry none. In m1, since moq-c ships at the cut -with parity with moq-ffi. - -[Announce route](/quest/m1/c/announce-route.md) adds minting and announcing -an epoch. This quest covers the receiving side. Expose the epoch as UUIDv7 -text, as the resolutions take it, and test that a pinned request built from a -received route refuses another instance. - -Public API: additive in the C ABI, or breaking if `moq_route`'s layout -changes; record which. Wire: none. - -## Related - -- [Announce route](/quest/m1/c/announce-route.md) - the publishing side's epoch