Skip to content

feat!: generate async wrappers behind default-off async features - #7607

Merged
kixelated merged 74 commits into
mainfrom
quest/m1/poll-first/async-feature
Nov 5, 2026
Merged

kixelated merged 74 commits into
mainfrom
quest/m1/poll-first/async-feature

Conversation

@kixelated

@kixelated kixelated commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Finishes the async-feature quest. moq's library crates hand-wrote an async fn x() { kio::wait(|w| self.poll_x(w)).await } beside each poll and compiled coroutines into every build, even for callers that only poll. moq-net's async feature was on by default, and its sessions (the moq-transport layer above all) were written as async fn bodies with no poll form, which accept policy in moq-net waits on.

Approach

  • Generated wrappers. Every one-poll wrapper is #[cfg_attr(feature = "async", kio::wrapper)] on its poll: 48 in moq-net, and those in moq-json, hang, moq-mux, moq-room, moq-stats, moq-crypto, and moq-auth. Each poll's doc now reads for both forms. Runtime glue and bindings that are always async (moq-tokio, moq-uring, moq-c, moq-audio, moq-transcode) use an unconditional #[kio::wrapper].
  • Default-off async everywhere. moq-net's async is no longer a default. hang, moq-mux, moq-hls, moq-room, moq-stats, moq-crypto, and moq-auth gain a default-off async feature. Binaries, bindings, tests (self dev-dependencies, as moq-json does), and tokio glue enable them: moq-tokio's net, moq-uring, moq-archive, and moq-mux's async forward moq-net/async. A plain cargo check -p moq-net now builds the poll model alone.
  • No coroutine left in a poll-only build. just rs coroutines scans kio, moq-net, moq-json, hang, moq-mux, moq-hls, moq-room, moq-stats, moq-crypto, and moq-auth, with no allowance left, so coroutines.sh drops --allow.
  • Every multi-await body is a poll machine (decided 2026-11-05, see Decisions). Hand-written state machines where a wait sits in a loop or branch, #[kio::machine] where straight-line; progress lives in named fields, and each machine drops what the old future held at the same points.
    • moq-net's IETF layer: the publisher (SUBSCRIBE, FETCH, TRACK_STATUS, SUBSCRIBE_NAMESPACE serves, fills, the namespace advertisement loops), the subscriber (routes, broadcasts, subscribes, joining FETCH, group, fill, and fetch ingest), SUBSCRIBE_TRACKS and PUBLISH (subscriber/tracks.rs), SUBSCRIBE_NAMESPACE requests (subscriber/namespaces.rs), MoQ Auth presenting and answering, and request-stream refusals. Both handle_streams return a poll task.
    • The IETF session driver (ietf::Driver) is a poll machine racing its halves (SETUP, unis, bidi dispatch, datagrams, GOAWAY, auth, grant enforcement, namespace loops, the task set) in the old order with the old "only an error ends it" rule, and crate::driver::Driver polls it directly.
    • moq-net core: Client::connect (Connect), the server handshake reply (Answer) under Server::accept, Session's and the auth handles' waits, and time::run (now kio::clock::drive directly). util::TaskSet/Tasks::push take kio::Tasks; util::{err_only, sendable}, TaskSet::drive, auth::until, and the guard combinators are gone, and the coding layer's Writer::{encode, varint, close, encode_message} and Stream::open remain for tests only.
    • The origin front driver (run_front/serve_front) is a hand-written poll machine (FrontServeRun, FrontServe), submitted to the task set as a poll task. It keeps a fresh waiter per wait, as kio::wait gave it (see Follow-ups).
    • Server handshake poll form. Server::accept_request keeps its signature over a private Accept machine; ietf::accept_setup becomes ietf::SetupAccept, lite's SetupAccept is reused, PausedNegotiated::ok becomes a buffered reply plus NegotiatedReply::poll, and Writer::close splits into closing plus a Closing poll so a dropped wait never resets the reply. Error codes, close-on-refusal, the 32-stream accept budget, and what a cancelled handshake releases are unchanged; an_abandoned_accept_closes_nothing covers the cancel.
    • Siblings: moq-mux's catalog subscription, Source::{catalog, resolve, subscribe_track}, the JSON entry's subscribe, ts::Release::new, and fmp4::Muxer::read (poll_read); hang Catalog::subscribe; moq-room chat::Subscriber::subscribe; moq-auth's lease (Producer::due and Consumer::reported, no more tokio Notify/select!); moq-stats' Publisher::poll_run and readers; moq-hls's export drivers (catalog and instance following, renditions, segments, init builds, media watching).
    • Left async, as edges or one-wait wrappers: HTTP code (moq-auth's client, server, and mesh; moq-hls's import driver and axum routes; see Waiting), and thin wrappers over private polls such as Server::close, Handshake::ok, Session::{close, closed, peer_implementation}, and moq-hls's Rendition::{playlist, init, segment}.
  • Quest: the quest and the poll-first epic are deleted; the epic's last item, moq-hls's import driver, stays async (see Decisions).

Choices I made without asking (from the agents' work, reviewed):

  • moq-stats Consumer::{totals, presence, prefix, group} return the reader at once; with moq-dev/moq#7736's self-subscribing snapshot consumer, a refused subscription fails the first read. Gating them instead would leave a poll-only build no way to make a reader.
  • track::Ordered gains poll_finished (generating finished), so a poll-only build can wait for an ordered reader's end as for a Subscriber's.
  • json::Consumer::from_track (made async by moq-dev/moq#7736) is gated with the other async wrappers, over a private Opening machine.
  • moq-hls's segments::Consumer::next keeps a fetch in progress in the cursor, so a next dropped mid-fetch is resumed by the next call (noted in its MIGRATE).
  • Races that were unbiased tokio::select!s in moq-hls now poll in a fixed order (closed before the backoff sleep; retirement before media readiness), and its init-build lock is a kio::Shared<bool> rather than a FIFO tokio Mutex.
  • The IETF AUTH reply and SUBSCRIBE_TRACKS loops spend a coop::Budget pass at the top of each poll, as lite's loops do, rather than once per message; SUBSCRIBE_NAMESPACE writes are buffered per event and flushed before the next read (same bytes and order on the wire).
  • Handshake::ok stays an async fn, so an ok() future dropped before its first poll still refuses the session with Cancel.
  • moq-auth's poll_revalidate is renamed poll_revalidate_requested, so revalidate_requested is generated.
  • moq-hls gates its import and export modules whole; its default server feature enables async. moq-mux and moq-hls allow rustdoc::broken_intra_doc_links only when async is off, so their docs keep linking the async-only functions on docs.rs.

Impact

Breaking for Rust users who .await these crates; each published crate's MIGRATE.md has an Unreleased note.

  • moq-net: enable features = ["async"] for sessions (Client, Server, Session), time::run, and the async wrappers. moq-tokio's net (a default) enables it. group::Producer::ready now needs it too. New public polls: frame::Consumer::poll_read_all, track::Demand::poll_closed, track::Ordered::poll_finished. Server::accept and time::run are fn -> impl Future with unchanged inputs and outputs.
  • moq-json, hang, moq-mux, moq-hls, moq-room, moq-stats, moq-crypto, moq-auth: enable async to keep awaiting their wrappers, including with default-features = false; every poll_* stays available without it. moq-auth's client and serve, and moq-hls's server, enable it.
  • moq-stats: Consumer::{totals, presence, prefix, group} drop their .await; new public poll_next on the eight readers and Publisher::poll_run.
  • moq-mux: fmp4::Muxer::poll_read is new; json::Consumer::from_track needs async; timeline::Resume::ready borrows instead of consuming; moq-mux no longer enables moq-json/async. hang's and moq-json's consumer wrappers drop a T: Unpin bound.
  • moq-hls: new public Broadcaster::{poll_closed, poll_ready}, Rendition::poll_playable, and poll_next on renditions::Consumer and segments::Consumer.
  • moq-auth: lease::Producer::poll_revalidate is poll_revalidate_requested.
  • moq-uring: poll_read_chunk and poll_received_reset are public, as the generated wrappers copy the poll's visibility.
  • JS, the bindings' APIs, and wire formats are unchanged (just test interop passes). No versions change.

Decisions

  • Decided 2026-11-05 (maintainer, /quest-unblock), for the earlier Waiting item on the remaining multi-await async fn bodies:

    • A: land this PR as is and split the rest into child quests.
    • ✅ B: convert them all in this PR before it lands.
  • Decided 2026-11-05 (maintainer, /quest-plan), for moq-hls's import driver (import.rs), which awaits only reqwest, tokio::fs, and retry sleeps, beside async axum handlers:

    • ✅ A: leave the import driver and routes async as HTTP edge glue, like moq-auth's client and server. It is gated behind async, so no poll-only build compiles it.
    • B: convert import.rs to poll machines over boxed reqwest futures.

    That was the poll-first epic's last open item, so this PR also deletes quest/m1/poll-first/README.md and its m1 link.

Follow-ups

  • Below-start FETCH race in the miss judgment. A reader on a lite-07 copy can judge its misses after SUBSCRIBE_START resolves its start but before any frame lands, so drifted() has no live edge to rule the groups below the start stale and it asks a fill that comes back empty: a wasted round trip, not wrong data (rs/moq-net/src/model/track/miss.rs:869, :934; track.rs:1706). The front's fresh-waiter-per-wait (FrontServe::park) keeps the old scheduling, which hides it in widened_max_age::a_fresh_reader_fills_nothing_below_its_start; dropping park reproduces it with MOQ_SIM_SEED=7084668493435518961. Recommended fix: hold the below-start asks on a timed copy until its first frame or the arrival grace.
  • moq-auth poll-only docs. cargo doc -p moq-auth --no-default-features fails on links to Client, serve::Server, and Coordinator, which exist only with client/serve. Pre-existing; once fixed, add its poll-only doc line to just rs coroutines.

Checks

Through quest gate:

  • just check origin/main on 9a3f2c2709 (after merging origin/main at f5764604f2): Rust 11777 tests, 11777 passed, 137 skipped. check drill failed because the subscriber-max-age-ignored mutation no longer applied to the rewritten publisher; fe0da30fcf retargets it and just test drill-sensitivity passes. check flake skipped: the local Nix builder cannot create user namespaces (moq-dev/moq#7763); hosted CI runs it strictly. Everything else passed.
  • just test interop on fe0da30fcf: all checks passed.
  • just rs features on fe0da30fcf: net-features failed on two breaks that reproduce on origin/main (cargo clippy -p moq-net --no-default-features --lib -- -D warnings on kio's clock::Timer large_enum_variant, and cargo test -p moq-net --no-default-features, where moq-dev/moq#7690's reused_encoders_start_independent_group_streams calls the async-only poll_read_object). 47c7a8b099 fixes both, and just rs net-features --all passes (1391 poll-only tests). Every later step passed on fe0da30fcf, run individually: just rs coroutines (all ten crates report no coroutines), quic-features --all, crypto-key, tokio-features --all, media-features --all, the workspace --no-default-features check, relay-minimal, the moq-cli, moq-bench, moq-boy, moq-auth, moq-hls/moq-rtmp/moq-rtc checks, the capture_window tests, and the all-features docs; the all-features clippy and tests are just check's.
  • moq-auth's suite by manifest path (-p moq-auth is ambiguous in the lockfile): 265 passed.
  • Each of the 48 non-fuzz workspace crates checked alone (cargo check --all-targets on 47c7a8b099, by manifest path for moq-auth and qmux), since feature unification hides a missing async in a workspace build: all pass.
  • After merging origin/main at 419b799c75 (f043156f59, hand-resolved around moq-dev/moq#7678): workspace clippy with all features clean, just rs coroutines and just rs net-features --all pass, and workspace nextest with all features passes (11915 passed, 141 skipped).
  • cargo fmt --all --check (dev shell) and quest check: ok.

Review

Codex gpt-6.1-sol, medium effort (quest review --base origin/main), session 01a1aae6-1cc4-73e1-bbd6-a723a927f898, restarted with --new for the design change (comment).

  • Round 1 on fe0da30fcf: no findings.
  • Round 2 on 47c7a8b099 (the two pre-existing fixes above): no findings.
  • Round 3 on f043156f59 (the hand-resolved merge of origin/main): no findings.
  • 1b399b927a (Claude Opus 5.5, skipped as trivial): since round 3's f043156f59, the head only deletes the finished poll-first epic (quest/m1/poll-first/README.md and its m1 link) for the maintainer's moq-hls decision, and merges origin/main at 2367707aea without conflicts (quest files only). No code changed; quest check --base origin/main passes.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 2 commits November 1, 2026 19:15
Keep poll methods canonical and enable the wrappers in their existing Rust consumers. Leave the overlapping origin conversion and remaining libraries in the quest.

Co-Authored-By: GPT-6.1 Sol <noreply@openai.com>
@kixelated kixelated changed the title Generated async wrappers behind a feature feat(json)!: generate async wrappers behind an opt-in feature Nov 2, 2026
kixelated and others added 18 commits November 4, 2026 13:36
Replace 48 hand-written `kio::wait(|waiter| self.poll_x(waiter)).await`
wrappers in moq-net with `#[cfg_attr(feature = "async", kio::wrapper)]` on
their polls, merging each wrapper's docs into its poll so one doc reads for
both forms. `group::Producer::ready` was compiled without `async`; it is
now generated behind the feature like the rest.

Gate `auth::until`, `RequestGrant::guard`, and `util::sendable` (their
only remaining caller) behind `async`, since only the async IETF session
uses them, and drop `--allow until` from `just rs coroutines`.

Point moq-json's module docs at `Producer::poll_refresh`, which the
poll-only doc build in `just rs coroutines` can resolve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The origin's per-broadcast front driver was the last pair of coroutines
(`run_front`, `serve_front`) moq-net compiled without its `async` feature.
It is now a hand-written `kio::Task`: `FrontServe` holds what the
coroutine's locals held and turns its one `kio::wait` into `poll_step`,
and `FrontServeRun` adds the lazy start and the in-flight phase. Each
wait still gets a fresh waiter, as `kio::wait` gave it, so a finished
wait's registrations cannot wake the front spuriously.

`TasksWeak::push` takes a poll task, and the submission queue holds
boxed poll tasks, so the front and the socket pump queue without a
future adapter; `Tasks::push` adapts its futures on submission.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in feature

Each poll-based sibling gains a default-off `async` feature, its one-poll
wrappers become `#[kio::wrapper]` on their polls, and its poll-only build
joins `just rs coroutines`.

- moq-room: `Room::next`, `chat::Publisher::expire`, and
  `chat::Subscriber::recv` are generated; `chat::Subscriber::subscribe` is
  gated.
- moq-stats: the readers gain public `poll_next` with generated `next`.
  `Consumer::{totals, presence, prefix, group}` return their reader at once
  and finish the subscription handshake on its first read, as the
  aggregate consumer already does. `Publisher::poll_run` drives the publish
  loop; `run(self)` stays a hand-written by-value wrapper behind `async`.
- moq-crypto: the `sign` and `e2ee` wrappers are generated.
- moq-auth: the lease wrappers are generated; `poll_revalidate` is
  `poll_revalidate_requested`, after its wrapper. `reported` is gated, and
  `client` and `serve` enable `async`.

The coroutine scan takes a manifest path for moq-auth, whose name its
published fixture shares. moq-relay enables the features it awaits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pers

The runtime glue and bindings are always async, so their one-poll wrappers
are an unconditional `#[kio::wrapper]` on the poll, which carries the
merged docs, and their kio dependency enables `async`. moq-uring's
`poll_read_chunk` and `poll_received_reset` become public beside their
generated wrappers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… moq-mux, and moq-hls

hang, moq-mux, and moq-hls gain a default-off `async` feature. Their hand-written
`kio::wait` wrappers become `#[cfg_attr(feature = "async", kio::wrapper)]` on the
polls, and the async functions with logic of their own compile only with the
feature. moq-mux's TS follower subscribes to a catalog through a crate-private
poll type instead of a boxed `async` block, so its poll-only build keeps it.
moq-hls gates its import and export gateways behind `async`, which `server`
enables. All three join `just rs coroutines`, and their consumers enable the
feature where they await.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moq-net builds its poll model alone unless a dependent enables `async`:
moq-tokio's `net`, moq-uring, moq-archive, and moq-mux's `async` forward it,
and test targets that await moq-net enable it through a dev-dependency.
Every coroutine scan now passes without an allowance, so drop `--allow`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Server::accept_request now waits on a hand-written Accept machine over the
transport's ALPN: moq-transport's SETUP (ietf::SetupAccept, now a poll), a
lite Setup Stream (lite::SetupAccept), or the negotiated bidi SETUP with its
hand-off reply. Handshake::ok's negotiated path flushes its server SETUP
through a NegotiatedReply poll. Writer::closing splits close into a FIN and
a Closing poll that, like close, never resets on drop.

The async accept_setup helpers and Stream::accept remain only as test
futures. accept_request keeps its signature, error codes, close on refusal,
accept budget, and what a dropped handshake releases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge from main added a hand-written wrapper; generate it like the rest,
and restore the blank lines the merge dropped between migration notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the boxed transport, which needs `async`, sizes a stream's window, so the
poll-only lint failed on main with `window` unused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title feat(json)!: generate async wrappers behind an opt-in feature feat!: generate async wrappers behind default-off async features Nov 5, 2026
kixelated and others added 4 commits November 4, 2026 21:47
Futures not yet written as polls go through a transitional future_task adapter.
Records the maintainer's decision to convert the remaining async bodies here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated and others added 6 commits November 5, 2026 00:30
…elpers for tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adapts the catalog, JSON entry, stats, and HLS catalog subscriptions to the
self-subscribing snapshot and hang consumers from #7736, and ports
#7789's errored-history splice into the origin front machine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hine

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Design change: per the maintainer's 2026-11-05 decision (option B), this PR now also converts every remaining multi-await async fn body in library code to poll form before it lands, rather than leaving them to child quests.

  • moq-net: the IETF publisher, subscriber, tracks, namespaces, auth, and request streams are poll machines; ietf::Driver is a poll machine that crate::driver::Driver polls directly; Client::connect, the server handshake reply, and the model readers have private or public polls. util::{err_only, sendable, future_task, BoxFuture}, TaskSet::drive, auth::until, and the guard combinators are gone; TaskSet/Tasks::push take kio::Tasks.
  • Siblings: moq-mux's catalog, source, JSON entry, ts::Release and fmp4::Muxer::read, hang Catalog::subscribe, moq-room chat::Subscriber::subscribe, moq-auth's lease, and moq-hls's export drivers wait on poll machines.
  • Left async: HTTP edges (moq-auth client/server/mesh, moq-hls import and routes), plus single-wait wrappers over private polls.

The review restarts with quest review --new.

(Written by Claude Opus 5.5)

kixelated and others added 2 commits November 5, 2026 01:02
kio's Timer lints as a large enum variant only in builds without its sim
clock, and a moq-net test from #7690 calls an async-only read;
both fail on main too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ports #7678's route listing and Following changes into the IETF
namespace machines and moq-hls's follow machines, takes its Activity::poll_close,
and links Following::poll_available so poll-only docs resolve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated and others added 2 commits November 5, 2026 08:19
Decided 2026-11-05 (maintainer): leave moq-hls's HTTP import driver and
routes async as HTTP edge glue, like moq-auth's client and server. That
was the epic's last open item, so the epic is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated
kixelated marked this pull request as ready for review November 5, 2026 16:20
@kixelated
kixelated added this pull request to the merge queue Nov 5, 2026

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

Reviewed the async-to-poll conversion against the async fn bodies it replaces, with the IETF data plane and the origin front read from git diff --merge-base origin/main because the exported diff renders publisher.rs and subscriber.rs as binary.

  • Generated wrappers — #[cfg_attr(feature = "async", kio::wrapper)] on the one-poll polls (48 in moq-net, plus moq-json, hang, moq-mux, moq-room, moq-stats, moq-crypto, moq-auth) and unconditional #[kio::wrapper] on the always-async edges; each removed async fn maps to the same poll and docs, and the renamed polls (poll_revalidate_requested, poll_read_all, poll_finished, poll_closed) keep the behavior of the wrappers they replace.
  • Default-off async — moq-net's default is removed and the eight sibling crates gain a default-off feature; binaries, tests, tokio glue, docs.rs metadata, and one ## Unreleased MIGRATE.md note per published crate all match the Impact section. No version or wire change.
  • IETF publisher/subscriber — the SUBSCRIBE/FETCH/TRACK_STATUS serves, PrepareFetch/ReadFetch, Serving/RunSubscription/Retain/WritePublishDone, SubscribeTrack, RecvFill/RunFill, joining FETCH, group ingest, SUBSCRIBE_TRACKS, PUBLISH, and the namespace machines keep their old ordering, coop budgets, guard/drop order (filling before counted, serve before PUBLISH_DONE), and withdraw/cancel paths. ReadFetch's retained ahead and RecvFill's explicit drop order are deliberate and harmless.
  • Session driver — Machine/Launch/Race/Running polls the halves in the old order, keeps the close → drain → abort sequence, and closing().is_local() reads the same shared Arc the old snapshot cloned. Client::connect owns its handshake once Connect is built, and Server::accept's Accept closes only on failure, leaving an abandoned accept to the caller (new test covers it). SendSetup, SetupAccept, Connect, and Answer reproduce the old hold/GOAWAY/linger and deadline semantics.
  • Origin front — FrontServeRun/FrontServe mirror run_front/serve_front step for step, including the fresh waiter per wait, the Action::End in-flight handoff, and the InFlight drain.
  • Siblings — moq-hls (WatchCatalog, WatchMedia, Fetch, LoadInit, Playlist, Idle, Building, Hold, Follow), moq-auth (DueTimers, Present, Answering), moq-mux (Subscribing, Opening, fmp4::poll_read, Source::subscribe), moq-stats poll_run with its span scope, and the moq-room/moq-crypto wrappers all resolve to their previous futures.
  • Build gates — coroutines.sh drops --allow, gains the manifest-path form, and covers the ten crates; the drill mutation is retargeted at the rewritten SUBSCRIBE serve.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash-1017 (free via Pullfrog for OSS) | 𝕏

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed commit 1b399b9. No actionable findings in the reviewed scope. The poll-first direction is coherent: generated wrappers suit single waits, while explicit machines preserve progress for branching operations; retaining async HTTP edge glue fits that boundary.

Verification: targeted GitHub-only static review of the higher-risk session, publisher/subscriber, authorization, teardown, origin-front, HLS, mux, lease and stats paths, not an exhaustive review of all 165 changed files. I did not run builds, tests, benchmarks, or generated code.

Merged via the queue into main with commit d0c73e3 Nov 5, 2026
10 of 11 checks passed
@kixelated
kixelated deleted the quest/m1/poll-first/async-feature branch November 5, 2026 16:36
kixelated added a commit that referenced this pull request Nov 5, 2026
Ports main's announcement listing and follow (#7678), split JS datagram
tracks (#7846) and generated async wrappers (#7607) onto the Route handle:
the ietf session layer takes main's poll machines with this branch's route
renames, main's new tests publish through routes, and re-price checks read a
fresh listing now that apps no longer see updates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant