From 7460e021c9e187f40811732f89135df5fb4755d7 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 5 Oct 2026 15:24:51 -0700 Subject: [PATCH] quest: plan the merge-queue settings and today's loose ends A condition quest for switching main to the squash merge queue with moq-bot's pull_request bypass once release carries the new back-merge script; marks moq.sh's manual deploy done; plans the transcode fetch demand and JS broadcast demand follow-ups from #4708; folds the FFI group demand, the filtered-front leak, the auth tree reconciliation, and the archive window reconciliation into existing quests. Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 3 +++ quest/m1/ffi-shape/net.md | 5 ++++ quest/m1/hls-bounded.md | 5 +++- quest/m1/js-broadcast-demand.md | 20 ++++++++++++++++ quest/m1/merge-queue-settings.md | 37 ++++++++++++++++++++++++++++++ quest/m1/moq-sh-deploy.md | 9 ++++---- quest/m1/origin-front-parks.md | 7 ++++++ quest/m1/quest-flat-lines.md | 7 ++++++ quest/m1/transcode-fetch-demand.md | 23 +++++++++++++++++++ 9 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 quest/m1/js-broadcast-demand.md create mode 100644 quest/m1/merge-queue-settings.md create mode 100644 quest/m1/transcode-fetch-demand.md diff --git a/quest/m1/README.md b/quest/m1/README.md index d9df2dea1d..f1db18e192 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -44,8 +44,11 @@ blocks. The quests that gated m0 lines moved under them. - [Delete removed cluster flags](/quest/m1/cluster-shims.md) - `mesh` and `linger` leave `cluster::Config` and their flags become unknown - [Track tail interop](/quest/m1/track-tail-interop.md) - a Rust publisher ending a track with a group in flight is read to its end by the JS subscriber, and the reverse, in `just test interop` - [Request linger](/quest/m1/request-linger.md) - an upstream FETCH or SUBSCRIBE outlives its last reader by a short linger, so quick re-requests don't churn upstream +- [Transcode fetch demand](/quest/m1/transcode-fetch-demand.md) - the transcode fetch handler drops a request once nobody wants the group +- [JS broadcast demand](/quest/m1/js-broadcast-demand.md) - `@moq/net`'s `Broadcast.Demand` matches Rust in three edge cases - [Flat questlines](/quest/m1/quest-flat-lines.md) - moq pins the current quest CLI, lands its questline branches on main, and retires them - [moq-bot may push workflow changes](/quest/m1/bot-workflows-permission.md) - condition: the maintainer grants moq-bot's GitHub App the `workflows` permission, so back-merges carrying workflow changes go through +- [main merges through a squash queue](/quest/m1/merge-queue-settings.md) - condition: once `release` carries the new back-merge script, the maintainer enables the squash merge queue and moq-bot's pull_request bypass together - [Binding audio delay](/quest/m1/binding-surface.md) - moq-ffi and every wrapper configure and observe audio playout delay - [moq-net owns its transport seam](/quest/m1/transport-seam.md) - moq-net names only its own transport traits, so a web-transport-trait or qmux major bump is a patch for it - [moq announced](/quest/m1/cli-announced.md) - `moq ls` becomes a follow-only live view named `moq announced`, with local-only shell completion diff --git a/quest/m1/ffi-shape/net.md b/quest/m1/ffi-shape/net.md index f057703119..350c7e6196 100644 --- a/quest/m1/ffi-shape/net.md +++ b/quest/m1/ffi-shape/net.md @@ -30,6 +30,11 @@ are renamed. Kotlin, Dart, and Python, whatever the generated name. Swift keeps its generated `.` cases, since it cannot alias a case. - `TrackProducer` drops `name`/`is_used`/`used`/`unused` for `demand()`. +- `GroupRequest` gains `demand()` too, in moq-ffi, moq-c, and every wrapper, + so a binding's fetch handler can tell when every caller left and drop the + request (decided 2026-10-05, from #4708, which moved Rust's + `group::Request` onto `demand()` and withdraws an abandoned fetch on the + last caller's drop). - The renames no additive change could make: - `subscribe` to `consume` on Python `Client`/`connect`, Kotlin `Moq.connect`/`Server.listen`, Dart `ConnectOptions`/`ListenOptions`, and Go diff --git a/quest/m1/hls-bounded.md b/quest/m1/hls-bounded.md index 3cfb9de98b..15b44bbca1 100644 --- a/quest/m1/hls-bounded.md +++ b/quest/m1/hls-bounded.md @@ -50,7 +50,10 @@ writes `EXT-X-GAP`). Fix only what a test shows missing: window even when the store retains more. A full VOD or EVENT listing is a separate, explicit replay mode. This conflicts with #4155's durable listing on the archive line branch, which lists the whole durable timeline without - the live window; reconcile it there when that branch next merges `main`. + the live window. This quest owns the reconciliation (decided 2026-10-05): + when the archive line lands on `main`, its durable listing becomes this + capped window and the full listing becomes the explicit replay mode. It is + not a Required link, so the live rules land without waiting for the line. - **Stable sequence.** `EXT-X-MEDIA-SEQUENCE` is the window's first segment number, derived from the timeline, so two edges and a reload after a pop agree. diff --git a/quest/m1/js-broadcast-demand.md b/quest/m1/js-broadcast-demand.md new file mode 100644 index 0000000000..d4b8e18a75 --- /dev/null +++ b/quest/m1/js-broadcast-demand.md @@ -0,0 +1,20 @@ +# [XS] JS broadcast demand matches Rust + +## Goal + +`@moq/net`'s `Broadcast.Demand` (`js/net/src/broadcast.ts`) agrees with Rust's +broadcast demand in the three cases where it differs today, each with a test: + +- A pending `resolveTrackInfo` query counts as demand, as a pending track + request does in Rust. +- `removeTrack` stops counting the removed track at once, instead of until it + closes. +- Inserting an already-closed track leaves no cleanup entry behind. + +## Plan + +Found while landing #4708, which introduced `Broadcast.Demand` and per-level +`demand()` handles in both languages. Nothing outside the bench reads +`Broadcast.Demand` yet, so this is parity, not a live bug. + +Public API: none beyond the corrected behavior. Wire: none. diff --git a/quest/m1/merge-queue-settings.md b/quest/m1/merge-queue-settings.md new file mode 100644 index 0000000000..cba10e34a0 --- /dev/null +++ b/quest/m1/merge-queue-settings.md @@ -0,0 +1,37 @@ +# [XS] main merges through a squash queue + +## Goal + +Condition: once `release` carries #4619's `sh/gh/back-merge.sh`, the +maintainer switches `main` to the merge queue in ruleset 2420853, making both +changes at once: + +- Enable "Require merge queue" with method Squash, keeping Check and Test as + required checks. +- Add moq-bot as a bypass actor with mode `pull_request`, so the `land` job in + `.github/workflows/check.yml` can merge the release back-merge as a merge + commit outside the queue. + +Order matters. Until `release` carries the new script, a push to `release` +runs the old copy, which enables auto-merge on the back-merge PR; under a +squash queue that squashes it. With the queue on but no bypass, `land`'s merge +is refused. + +Check: `git show origin/release:sh/gh/back-merge.sh` no longer runs +`gh pr merge --auto`, and +`gh api repos/moq-dev/moq/rulesets/2420853` lists a `merge_queue` rule with +merge method `SQUASH` and a moq-bot bypass actor with `bypass_mode` +`pull_request`. Delete this quest once both hold. + +## Plan + +Decided in #4619 (2026-10-05): a squash queue with a pull_request-only bot +bypass for the back-merge, landed by the `land` job; the back-merge may land +against a `main` that moved during its CI run, accepted. + +Known risk: the Dependabot workflow mints the same moq-bot app token, so a +Dependabot merge could also skip the queue once moq-bot is a bypass actor. + +## Related + +- [moq-bot may push workflow changes](/quest/m1/bot-workflows-permission.md) - the other moq-bot permission the back-merge needs diff --git a/quest/m1/moq-sh-deploy.md b/quest/m1/moq-sh-deploy.md index 2661c52ac1..f8b8689715 100644 --- a/quest/m1/moq-sh-deploy.md +++ b/quest/m1/moq-sh-deploy.md @@ -4,11 +4,10 @@ `curl -fsSL https://moq.sh | sh` installs `moq`, and CI keeps it deployed. -1. Once the installer is on `main`, run `just infra moq-sh deploy` by hand - under the maintainer's `wrangler login`. This creates the worker and its - `moq.sh` custom domain, which the CI token cannot do. Then run - `curl -fsSL https://moq.sh | sh -s -- --dir "$(mktemp -d)"` and check the - installed `moq --version`. +1. Done 2026-10-05: `just infra moq-sh deploy` under the maintainer's + `wrangler login` created the worker and its `moq.sh` custom domain + (version 217dc477), and `curl -fsSL https://moq.sh | sh -s -- --dir + "$(mktemp -d)"` installed `moq 0.14.0`. 2. The first `moq.sh` workflow run on `release` deploys with the `CLOUDFLARE_API_TOKEN` secret. It runs once a release cut brings `.github/workflows/moq-sh.yml` to `release`, either from the push or from diff --git a/quest/m1/origin-front-parks.md b/quest/m1/origin-front-parks.md index 1df5ab14bb..36421c6e20 100644 --- a/quest/m1/origin-front-parks.md +++ b/quest/m1/origin-front-parks.md @@ -25,6 +25,13 @@ benchmark swept over requesters and route-table churn would show whether the re-mint is a real slope or noise, and it is the same benchmark that would show the replacement is cheaper. +Also reclaim a filtered front left behind for a hop that appears in a route +chain: one can outlive its peer session today, once per session (found while +landing #4832, which fixed the per-viewer case in +[shared fronts](/quest/m0/shared-fronts.md)). Test that the front count +returns to the plain fronts after the peer session closes. Folded in +2026-10-05. + Public API: no signature change expected. `routed_broadcast` and `request_broadcast` keep their contracts; only where the waiting happens changes. diff --git a/quest/m1/quest-flat-lines.md b/quest/m1/quest-flat-lines.md index 4cfbbd4e3b..f8597418ac 100644 --- a/quest/m1/quest-flat-lines.md +++ b/quest/m1/quest-flat-lines.md @@ -67,6 +67,13 @@ Remaining: PR still based on it, or GitHub closes it with the branch. As of the 2026-10-05 audit: #4645 (tstd/delay, retarget to `main` after #4640), #4732 (ffi-shape/request-accept), and #4675 (auth/request-token). +- Retiring the auth branch reconciles `quest/m1/auth/` with `main`'s copy + (decided 2026-10-05). Drop the children the branch finished or moved (lite, + interop, unauthorized, auth-ok-preflight, error-codes, narrowing, peer-grant, + moq-transport), keep the branch's new ones (not-supported, violations, + js-fetch-watch), fold violations' lite decode gap into + [malformed grant](/quest/m1/auth/malformed-grant.md), and retarget the + branch's lite-06 wire text at the current `-wip` lite version. Done when `flake.nix` pins the new quest, no `quest/*README` branch remains, and `quest check` passes. diff --git a/quest/m1/transcode-fetch-demand.md b/quest/m1/transcode-fetch-demand.md new file mode 100644 index 0000000000..18bad206fb --- /dev/null +++ b/quest/m1/transcode-fetch-demand.md @@ -0,0 +1,23 @@ +# [XS] A transcode fetch stops when nobody wants the group + +## Goal + +moq-transcode's fetch handler (`rs/moq-transcode/src/rung.rs`, the +`requested_group` path) watches `request.demand()` and drops the request once +it goes unused, so a group every caller abandoned is never encoded. +Test: an abandoned fetch encodes nothing, and a late retry after the last +caller left gets a fresh request rather than racing a stale encode. + +## Plan + +Found while landing #4708, which moved `group::Request` onto `demand()` and +withdraws an abandoned fetch when its last caller drops. The transcode handler +never watches demand, so a late retry still encodes the group and its +`accept` logs `Duplicate`. Wasted work, not a correctness bug. + +Public API: none. Wire: none. + +## Related + +- [Per-worker transcode epochs](/quest/m0/wildcard/transcode-group-start.md) - also edits `rung.rs` +- [Request linger](/quest/m1/request-linger.md) - its linger also delays the fetch withdrawal this relies on