wai merge train E: twenty-five PRs onto main, the relay's upstream window bounded, and three fixes the merged tree needed #499
Loading…
Reference in a new issue
No description provided.
Delete branch "train/wai-e"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
WAI merge train E: twenty-five open PRs merged onto
mainbygit merge --no-ff, one merge commit each, every conflict resolved with both sides kept, the generated files regenerated, and the one open item settled (#475's upstream links held to #483's connection window). What the merged tree exposed is fixed in commits of their own, each with its test: two pairs of room modes the service accepted together, a race in the page's SUBSCRIBE, a test count #463 left behind, and the five failures of this PR's first CI run (CI's first run, below).Branch
train/wai-e. Base:origin/main, withmainmerged in seven more times as it moved: #465, #486 and #485; then #477; then #492; then #494; then #495; then #497; then #498. The head is current withmainatf1a34c06.What it holds, and the SHA merged
ad283d92main, so the train's second merge ofmainbrought only its merge commit069b551cwai-ops/1-npuon a neural processor (G2)6064a35cda3c09c59804962cwai.avatar.face(AVTR)4863036d986edfea2a99c78fdf8c7f4913964c94, replayed4623548d9cea6b5ce60c7dbed56916da05fb22cccf93ad7a43c87c8cc90c4d54b54dc94c545892086745bf6cb41b566bd1e8965fe8c747ec01f3aac1wai.live.message,wai.live.call), merged last59bfbbfd, its next headwai/wai-sink-swift/), merged on top after #493850eeefe, its head nowwai/wai-sink-swift/andwai-sink-swift.yml), merged on top of59bfbbfdLeft out: #458 (below).
Order
main, and #463 merges as the "re-merge main after pack-stack" its own notes planned. #465 then landed onmainwhile the train was being built; the later merge ofmainis clean.59bfbbfdis merged on top of it, then850eeefeon top of that (a fast-forward of the same branch, so the train holds #480 at850eeefe). They touch onlywai/wai-sink-swift/and its workflow. #488 changes nothing the later merges change but #480's CHANGELOG entry; #489 and #490 come after #481 and #482, as asked. The [remote]+[world] refusal (below) was made after #489 and before #490 arrived; #490 merged over it cleanly.How #463 was merged
#463's head contains #452's commits, and with them #438's first research note (
docs/research/wai-cross-fabric.md), which names fleet hosts and their addresses. #465 replaced that history with one squash precisely so that the note never entersmain's history. Merging #463's head would have brought it back.So #463's own commits are replayed with
cherry-pick -xonto the train's #465 merge (branchtraine/enc-replay), and that branch is merged as #463's merge commit:6ad92e2e8,8695bc75f,fed8694f4;df5ea962f11b255682ff069acc2244a715b32a8d45aa0a203eae239b6e4bada1ffceb5086c03ba72cce38948da1ca593124507f4cd9ec9533773913964c944.#463's three merge commits (of
main, and of #452) are not replayed: their conflict resolutions (SPEC §7.1 step 2, the CHANGELOG) are what the later commits reach anyway.Checked:
main1a465f23as the base. The two exceptions are the files that merge conflicts on:int_kernels_vectors.rs(#465'swgsl-conformanceline and EN-C'splatform-decode-conformanceline, both kept), and the CHANGELOG.docs/research/wai-cross-fabric.mdis not in the tree.Conflicts, and how each was resolved
Every conflict below kept both sides. A conflict here was almost always two additions at one place.
main's.codecs/mod.rs,codecs/registry.rs,glossary_check.rs),lib.rsmodules, Cargo[features],[[bin]]and[[test]], the live-conformance README, workflowpaths:and steps. These are unions.codecs/mod.rs:main's gain-map, ST 2094-50 and DRED strings sit beside #445's tensor-file priors, #446's projection descriptor, JPEG XS, MV-HEVC and IEEE 1857.11, and #448's face generator. This holds in every class list, the companion-only and video-companion rules, the one-file parameter sets, the ops members and the registry tests' expected lists.WireKind::all()is now 17. #445 (glTF extension) and #446 (telemetry key) each raised it from 15 to 16, so neither side compiled after the merge.main's co-watch and origin):app.jsimports and snapshot fields from both sides;room.e2e.mjskeeps every scenario (ageco,cowatch,origin,termination,remote,world,privateworld) in the default list, the--onlyusage and the runner's table, plus both sides' imports (writeWav,rawBrowser,spawn);lib.mjskeepswriteWavandrawBrowser;run.shruns all the page's module tests (cowatch,remote,markup,endpoint,termination);waifeatures arestream_terminationandlive_worldboth.main's DRED and splat). #448's build line goes into the build step's run block. Placed aftermain's DRED step instead, it would have broken the YAML.platform_encodeand #465's optionalwai-pack-gpu;lib.rs: the module account;--test=encode_rung 3beside #465's counts.metering.rs(#463 with #475): the self-metered relay and the hop links, in one text.moq-relay-energyjob, and #479's account of the ingest job.frame.rs:Codecwith HEVC, VVC, AAC and FLAC (ALLis nine);WEBRTCandOption-returningto_str0m, and #483'swebrtc()andaac_header;Header, whose audio rate is #479'srate(#483'ssamplerateis renamed at its uses);unframekeeps #483's whole-ADTS check.package.rs, one packager:catalog.rs: #479's entry carries its layer name, and #483'scontrib.rsnow names one.config.rs,gateway.rs(routes, fields, methods, listeners,srt_task, shutdown),rtc.rs,lib.rs, the example config, the README and live-ingest's header, status table and test account: both sides.tests/common:watch_kinds→watch_layers(#479) →watch_tracks(#483), one subscriber.Watched.layeris the track name where it is a number.tests/ertmp.rsimportscommon::rtmp::adtsby name, sincecommonnow has #483'sadtstoo.mainmid-train). Its independent-verifiers job builds wai-rs once per feature list. The train had added fifteen steps there, each with a feature list of its own, and each switch between a list and #477's union rebuilds the library and relinks every test. They now follow #477's rule:WAI_FEATURESgains the fifteen steps' features (WAI_RELEASE_FEATURESgainsavatar_face).cfg(not(feature))gates arepq_signatures,neural_int,stagedand the integer media features, already in or out of the union as before.cargo run, and builds their test targets.features-alonechecks each of the train's lists alone.int_videobuild.Changes the merges forced, each its own commit
include/wai.h, regenerated bybuild.rs. #467's head already left a build dirty: its new publicint_kernels::Isareaches the C surface, which adds an opaque typedef. Rebuilt with no features and with the HTTP falsify shards' features, the header stays unchanged.check-lockfiles.shfound three stale; each was refreshed withcargo metadata(resolve only).joule-moq-remote(#481) now resolves #475's relay dependencies,tokio-rustls0.26.6 andrustls-native-certs.wai-key-proxy(#471) andwai-ledger(#473) now resolvemain'swai-quantum0.6.15.joule-moq-remoteagain aftermain's #492, which moved every other lock to zstd 0.14.3 for its advisories.every_decoded_output_states_a_sha256gains entries forformat-probe-conformance(#446) andencode-conformance(#484). Neither corpus decodes a payload.encode-conformance's README gains the**Provenance.**line thattests/corpus_provenance.rsrequires.The open item: #475's upstream links and #483's connection window
The relay's links to its upstreams set no receive windows:
On both, the connection-level window was unbounded. One transport configuration (
server::transport_config) now serves the listener and both kinds of link, andwebtransport::connect_draft_tls_withtakes it.tests/upstream_window.rsputs an upstream of the test's own on each transport. It opens 16 data streams before its SETUP, which the relay parks after each header, and writes until flow control stops it.git apply -R, then targeted edits, each restored through git):The late additions: #488, #489, #490, #493
main, so #489's version is taken whole. Conflicts:waifeatures take #482'slive_worldand #489'sremote_desktop;room.e2e.mjs's usage:remoteruns by default when both the host agent and the room service are given.telemetry_aggregatenow sits on the newhpkefeature, beside #446'sformat_probe. Every build withtelemetry_aggregateorremote_desktopgetshpkethrough the feature, #477's union among them;hpke::test filter;ConfigandServicefields, the epoch (remote::epoch) with the conversation and calls opened beside it, the refusals of #482 and #493, and the README;app.js: a remote room's grant request, and #493's given grant;run.sh, which runsroom.e2e.mjs(with--remote) andmessaging.e2e.mjs, each with its own--only;live_messagingjoins #477's union and the first step's test build;lib.rs,registry.rsand REGISTRY.md;capabilities.jsonandv2.ttl, regenerated.Modes a room service cannot keep together
Each refusal below is its own commit, with a test, and falsified.
[remote]with[world](once #482 and #489 were both in):remote::servicerefuses the pair when the configuration is read.a_remote_room_is_not_also_a_world_room.[messaging]or[call]with[world]or[remote](#493).settings()refused a conversation beside a watch room, co-performance, admission by age,[room] e2eeor a call, and a call beside the first three. It accepted either beside a shared world or a remote desktop room. Both refusals now count those two modes.a_conversation_or_a_call_is_not_also_a_world_or_a_remote_room.live_messagingalone, under #477's rule.A verifier the train's tree caught
claim-conformance/differential.py --random 2000 --seed 1drew31135_session_roles_companion_wai.meta.projectionon the train's registry: wai-rs accepted it andclaim_verify.pyrefused it (session_layer_not_applicable).staged_verify.py's_companion_applies_to, the independent reading thatclaim_verify.pyandhttp_verify.pyshare.wai.meta.projectionwith the HDR descriptors.A race the train's Studio run caught
The full browser run on the Studio failed one check of #482's
worldscenario:The other 336 checks passed.
world.jsfollows a departed actor on that refusal. Under the Studio's load the page's timer won, so the refusal was never read.joule-moq-web: a SUBSCRIBE that asks for a rendezvous waits past it for the relay's answer).request()takes how long to wait for its answer, andsubscribe()waits a step past the rendezvous it asks for. Nothing else waits on that error.web/moq/session.test.mjsuses a transport and a codec of its own, with the clock mocked. It runs inrun.sh's page-module step, so the e2e job runs it:session.js's change reverted, the first two cases fail, the first with the e2e's own error. Restored, all three pass.A count #463 left behind
wai-web-wasm.ymlrequires wai-web's native unit tests to report exactly35 passed. #463 addedworld::tests::the_pages_figure_is_sealed_as_an_estimatorand left the count at 35. #463's own run of that job was cancelled, so this never showed. On the train's tree the Studio read36 passedand the step failed.CI's first run: five failures, each fixed
The first run, on
5b79d155, had 115 checks green and 5 failed. Each failure is fixed in its own commit, tested where its job runs, and falsified:wai-neural-gates, model-free refusals.several_file_capabilities_need_the_set_formmet #446'swai.image.ieee1857_11and got "no model registered" instead ofform_required.codecs::is_dispatchable, and checks that a several-file capability it does not dispatch is a candidate the sink refuses to decode.wai-ledger, service · linux.smoke.shends withreceipt_ledger_verify.py, which importspack_verify.pyand so needstomllib; the runner image's Python is 3.10.wai-key-proxy's does, and the step fails first with an::error::if itspython3has notomllib.catthehacker/ubuntu:act-22.04: with the image's Python, the early error; with 3.11 first on the path, every check holds, the independent verifier among them.wai-sink-android, macos. "the AAR has no jni/arm64-v8a/libwai.so", though the native step built all three ABIs and Gradle packed them.pipefail,unzip -l | grep -qfails whenevergrepstops at its first match beforeunziphas finished writing (SIGPIPE). On the AAR the Studio built, that pipeline fails 7 times in 300; with the listing read first, 0 in 300. The toolchain, the NDK and the targets were all found.build-native.shnow readsnmandreadelfoutput whole: the same race there could report an export or aNEEDEDentry missing, or let a misaligned LOAD segment through.wai-web-reach, the package of record. Every build on the record leg (shipped, L1, L2, J) failed itsmenuworkload. The fallback path did not regress.248846f1. The registry the workload reads is this tree's, and it gains #446's candidatewai.image.ieee1857_11, which that package does not know, so the package'sisCandidatedisagreed with the registry.newer.neweris empty and nothing is let through. Moving the package of record itself is the site's step, and is not made here.joule-moq-webe2e, privateworld. "carol replays the world from its start: not within 120000 ms". This was a real catch-up race, not load and not a timeout.E2ee.readToEnd), follows every actor it records, waits for each subscription's answer (WorldClient.followActors), and only then publishes.privateworldpasses twice in a row, and the whole run passes: room 342 of 342, messaging and call 17 of 17, page tests 74.The merge of
main's #498 movedwai-quantumto 0.6.16. The locks of three train crates,wai-audit(#474),wai-key-proxy(#471) andwai-ledger(#473), are refreshed by resolution only, one version line each. On the final head,joule-moq-room(33 tests), the generated files, andwai-web-wasm(engine 13, native 36) pass, with all 53 lockfiles current.Left out: #458
#458 (delivery bindings, head
aca6c347) was to come in only if its four failing checks were real failures that a small, clearly right change in the train could fix. They are not. Its job logs on the forge show:main's at #458's base, since cleared there (the train's advisories pass). #458 changes none of those locksjouleclaw-loader-ggufdoes not compile under-D warnings(a deprecated quick-xml method)main's at the time. #458 does not touch the cratecli_http::origin_refuses_an_oversized_headread an empty answer instead of 431sealed_objects::a_changed_identity_is_refused_at_the_door_over_quic: "group 1's object is refused at the door, the others pass"The only failure that is #458's sits in the relay's door and session code, which #475 rewrites in this train. Fixing it is a change to #458's design, not a small one. Three more reasons point the same way:
main.It stays open as it is.
Generated files
capabilities.json,capabilities.schema.json,v2.ttl,v2.shapes.ttland REGISTRY.md's table.wai registry exportat every merge that touched the registry, and committed in that merge.registry export --checkreports it up to date.include/wai.h: regenerated bybuild.rs(see above). At the head, it is unchanged after a build with no features and after a build with the HTTP falsify shards' features.cargo metadata(resolve only):joule-moq-remotetwice (#475's relay dependencies; then #492's zstd),wai-key-proxyandwai-ledger.scripts/check-lockfiles.shreports 53 lockfiles, all current.main, for the shared corpora the train changes (train-prefix.py, not committed):live-conformance/browser/vectors.json: every list ofmain's is an unchanged prefix of the train's (routes 11, constraints 23, bindings 15, frame_tiers 24, frames 13, tables 10), andchoices(14) is new.http-conformance/cases.json: #463 edits five ofmain's cases in place (an explicitorder, a png-only case's skips) and inserts two (select_O2_default,fetch_O2_default). Its energy order changes whatselectandfetchpick by default, and that corpus states no append-only rule. This is #463's own change, as reviewed in #463, not a merge's.Checks
Hosts:
wfrun.py, which runs a workflow job'srun:steps as the runner would: env, working directory, shell,$GITHUB_PATH/$GITHUB_ENV. It skipsuses:steps and the steps that install a toolchain or a system package.waistand in for another's and failed builds that CI never sees.Each row's tree:
5b79d1550, or3a3bbfc16.3a3bbfc16differs from it only bymain's #497 (wai-quantum, quantum-studio and wai-web's quantum engine). The checks of the fixes since, on8ab46dfb0and the headf004aa4f9, are under CI's first run.de7fe1b91: before #480's last head, the test-count fix, #495 and #497.63cf067e3: #493 and the refusals in, beforemain's #492.wai-conformancecargo-classes (linux leg), all 20 stepswai-conformancefeatures-alone (every list,live_messagingamong them; wai-live-web withoutint_video)wai-conformanceint-kernels-amd (every x86_64 kernel set, both profiles)--check;include/wai.hafter builds;check-lockfiles.shjoule-moq-room, every target (messaging_room,call_room,remote_room,world_roomamong them)joule-moq-remote, every target, and clippy-D warnings(linux leg)joule-code-conformancemoq-ingest (with and withoutrist, the corpora) and moq-relaystandards-buildjoule-code-rs:cargo check --workspace --all-targets,cargo test --workspaceage_rising, a flakemainhas too (below)joule-code-conformanceconformancejoule-code-remediate's two formal-tier tests. The job installs z3 withsudo apt-get, which this shared box does not run, so they fail with "JOULE_FIX_EXPECT_Z3=1, but there is no working z3". The workspace run above passes them, since it does not require z3wai-packlegs (linux: clippy, release tests, the test-count floors, the corpus recomputed)wai-conformanceindependent verifiers (#477's union with the train's features), all 67 stepsnode --testran on the Studio (next row)nodesteps (28, 29, 54, 55)wai-conformancevocab-shapes (RDF tools at the workflow's versions, in a venv)wai-conformancebyte-exact (linux), c2pa-emitter, quantum and avatar-face under wasip2;wai-opsnative, wasip2, checker;wai-httpcache-conformance;wai-ops-gpuchecks;wai-ops-npucheckswai-ops-npunpu-hw, on the device, requiredmismatches=0 errors=0, 12 of 12 mutants killed, width)wai-auditcollector-linux,wai-key-proxyproxy-linux,wai-ledgerservice-linux (with their clippy lines);wai-packindependent, licencesindependent's pip step aside)joule-moq-webbrowser e2e: the wholerun.sh, every room scenario andmessaging.e2e.mjssession.test.mjsamong themd2ae29c52wai-sink-swiftpackage-macos: every slice, desktop tests, both simulators hosted in TestHost, device slices850eeefe)wai-conformancecodec-wrappers (the VideoToolbox platform encode among them)joule-moq-remotemacos leg;wai-ledgerservice-macos;wai-auditkit-macos;joule-code-conformancemoq-relay-energywai-ops-gpumetal (the probe, the corpus at both widths, the mutants, on the GPU)wai-sink-androidandroid-macos: the ABIs, the AAR, instrumented tests in a headless emulatorwai-sink-androidJVM unit tests (thejvm-linux-arm64job, run on macOS here)nm -D), which a macOS dylib does not have.nm -gUshows all 16Java_wai_sink_WaiNative_*symbols andJNI_OnLoadexported. CI runs the job on linux-arm64wai-conformancedelivery telemetry differentialwai-web-wasmwasm32, every step5b79d1550, and again atf004aa4f9wai-quantumstudio · browser (studio.test.mjs)main(ea2a6defd), run there, is also 110 of 111, with a different check failing. The train changes nothing the failing check exercises. CI runs this job onlinux, wheremainpassescheck-advisories.py)d2ae29c52wai/, the 286 commit messages, this bodywfsteps.py HEAD origin/main <every merged head>and a YAML parse of every workflowFlakes that
mainhas toojoule-moq-relay'sage_rising::a_rating_that_rises_ends_what_waits_at_the_relayfails now and then with "groups that waited at the relay when the rise was held were sent no more: [0, …, 9]". The train does not change that test.main: 17 of 20 runs pass, with the same message.The workflow steps that match no single source
wfsteps.py HEAD origin/main <every merged head>reports 22 steps whose bodies match no source's. Each one is a union or a fix the train made on purpose:wai-conformance.ymlindependent-verifiers, 16 steps. The first step builds #477's union once, and now also the four corpus programs and test targets the train's steps need. Fifteen train steps run on$WAI_FEATURESand those built tools instead of feature lists of their own: determinism cost, sink energy, key release, stitched presentation, prior forms, scene carriage, faces from keypoints, receipt ledger, stream audit, native sink, platform-encode, remote desktop, stream termination, live worlds and header probes.wai-conformance.ymlfeatures-alone, 1 step:main's lists and every train PR's lists,live_messagingamong them.wai-ops-gpu.ymlchecks, 1 step:main'ssplat_exactline and #448'savatar_faceline in one run block.wai-pack.ymllegs, 1 step: #465's test-count floors and #484's--test=encode_rung 3.wai-web-wasm.ymlwasm32, 1 step: wai-web's native test count, 36 (see A count #463 left behind).wai-ledger.ymlservice-linux, 1 step: the smoke checks, which first require the Python 3.11 the job now sets up (CI's first run, 2).wai-sink-android.ymlandroid-macos, 1 step: the AAR check, reading the listing whole (CI's first run, 3).No step is duplicated or lacks a
run/uses, and every workflow parses (ruby YAML).Open items
main.main, moving them in is a follow-up.248846f1's. Moving it to a commit with this train's registry is the site's step (build-wasm-pkg.sh, thenWAI_REACH_RECORD=1). Until then the record leg lists the newer capabilities instead of holding them against the package.age_risingflakes onmainand here alike (above).mainand here alike. CI runs it onlinux.joule-code-remediate's formal tier;independent's Ed25519 step;joule-moq-ingest(whip.rs,whep.rs,tests/common/mod.rs) andjoule-moq-web.ymlmatch the denylist. They are the same lines onmain, and they sit outside the check'swai/scope.🤖 Generated with Claude Code
b1681667) into wai/energy-wastewai/wai-ledger: tariffs, sources and invoices kept in a directory the service owns (one process holds its lock; every file written whole; the state read back and verified again on start); POST /v1/tariffs, /v1/sources, /v1/invoices and /v1/verify, GET /v1/invoices/{digest} with the invoice's verification document. Its tests issue the corpus's invoices byte for byte and recover the chain after a restart; smoke.sh checks it over HTTP, the document checked by receipt_ledger_verify.py --document. wai.delivery.ledger registered with WLT1 and WLI1 (registry export regenerated); unit tests of the module; the CI step beside settlement's and .github/workflows/wai-ledger.yml. Co-Authored-By: Claude Opus 5.5 <[email protected]>96117c570) into wai/audit-kit 2a33aaa7e0d56916dac) into wai/sdk-native-apple 78a05d9ccdcd35b8ff9) into wai/sdk-native-apple 3836144637cd35b8ff9: train C, wai-quantum 0.6.15) into wai/encode-avc-hevc 6d35ddf5c9ad283d92): the packaging train, before the PRs that build on it 767d2aa7a6069b551c): wai-ops/1-npu on a neural processor 4afeaefe346064a35c): scene and prior carriage 65cc9f5eadda3c09c5): JPEG XS, MV-HEVC, the projection descriptor, IEEE 1857.11, format probes, CMSD read, LOC carriage 084bfda7839804962c): wai.avatar.face 70c3b2fca34863036d): DET1, what exactness costs int_hyper 6fe1521524986edfea): PERF1, int_hyper's integer decode on NEON, AVX2 and AVX-512 narrow kernels add759840d2a99c78f): EN-B, what nobody watches is ended with a receipt 372b51534edf8c7f49): EN-A, sink energy 73a1a0c95413964c94, replayed): EN-C, the energy order of dispatch, a self-metered relay, HwShunt closed to new profiles bfa44f4c1d4623548d): stitched presentation 9dc78f9dee9cea6b5c): the receipt ledger 9bc2cc9611e60c7dbe): key release, the proxy form of wai.video.keys 9a39b479abd56916da): stream audit, an audit kit for streams another service delivers 7c6353911105fb22cc): the native sink, its C interface and the Swift package 601b3cfe4143c87c8c): relay-to-relay cascading e56cad3047c90c4d54): Enhanced RTMP v2 ingest and SCTE 104 into signed cues a0e8a27b93b54dc94c): SRT and RIST contribution ingest, with a signed link record 29594e8ea954589208): wai.live.remote, remote desktop in a WAI room d87432e39c6745bf6c): wai.live.world, a shared world in a live room 20a37c22fbb41b566b): wai.video.encode, AVC and HEVC through the encoders a device already has 43bd5e66e134df55a5e): #465 landed, #486, #485 b1964e0844cd708e120): #477, the independent verifiers build wai-rs once per profile 22df0336c3cf93ad7a): the native sink as a Kotlin library over the C interface 8089acf226d1e8965f): remote desktop rooms in the room service 63d4042224web/room/messages.html: a member of a conversation in a page. It joins with a proof of its own key, keys through the service's log with joule_moq_web_e2ee's member (any member commits), seals each message before it is signed into its receipt chain and posted, opens and verifies every message (wai_live_web's Messages, live-messaging §11), shows threads, reactions, edits and retractions, and acknowledges what it read. web/room/call.html: a page's inbox, each invitation checked with its call before it rings (callCheck); placing a call, ringing, accepting, declining and cancelling; the call's media through the room page in a frame, which now takes a grant handed to it (enter(role, { seed, answer })). wai-live-web: the messaging records, receipts, acknowledgements, invitations and answers a page signs, and Messages, verified against the corpus in its tests. joule-moq-web: keyProofHttp, a proof naming no grant. e2e/messaging.e2e.mjs (run by e2e/run.sh): the messaging scenario and the call scenario. Co-Authored-By: Claude Opus 5.5 <[email protected]>e8c747ec): sealed input in remote rooms 8e8e067f6a01f3aac1): wai.live.message and wai.live.call, conversations and calls on live rooms beb4679dc60855f00d1): #492, zstd 0.14.3 and the avx2 leg on the framework runner d3be3fec5aThe platform now refuses to launch an application without the scene life cycle ("UIScene life cycle is required"), so the test host quit before its tests connected. It is a scene-based application now: an App with one WindowGroup, and the generated Info.plist carries its scene manifest. Co-Authored-By: Claude Opus 5.5 <[email protected]>59bfbbfd): the Swift tests on a device 7933772adbThe page asked the relay for a 10 s rendezvous on each world and room track and waited 10 s for the answer. With no publisher, the relay answers when the rendezvous ends, so the two timers raced: on a loaded host the page gave up ("SUBSCRIBE: no answer in 10000 ms") as the refusal was sent, and world.js, which follows a departed actor's track on that refusal, never saw it. The world scenario's "dave catches up after alice left" failed so on the train's Studio run. request() takes how long to wait for its answer; subscribe() waits a step past the rendezvous it asks for. session.test.mjs holds the three cases with the clock mocked; without the change its first case fails with the e2e's error. Co-Authored-By: Claude Opus 5.5 <[email protected]>99fd7d1e3): #494, the person's rules for wai-quantum proposals de7fe1b91b850eeefe): simulator tests hosted in TestHost, every step bounded 7086a59a5fea2a6defd): #495, what is new in a wai-quantum proposal 8cbbea2b69907c46889): #497, a person's taste in wai-quantumf1a34c068): #498, wai-quantum 0.6.16 and wai-quantum-cli 0.1.4 27c38a8b08