docs(nests): refresh all T16 + cliff plans to current state
8 plan files updated to reflect what's actually shipped vs. what each doc said before: - 2026-05-06-cross-stack-interop-test.md: 'Spec — ready to implement' → 'Implemented and merged' with pointers to results, gap matrix, and closure roadmap. - 2026-05-06-cross-stack-interop-test-results.md: scenario inventory updated to show all branches merged into claude/cross-stack-interop-test-XAbYB; suite-flake caveats flagged with cross-refs to the routing investigation; file inventory now lists BrowserInteropTest + PlaywrightDriver + the moved nestsClient/tests/browser-interop/ tree (no more 'in sister branches not yet merged' section). - 2026-05-06-cross-stack-interop-test-gap-matrix.md: T8/T10/T11/ T12/T13 all show hang ✅ + browser ✅; I13/I14 'NOT YET LANDED' callouts removed; the 'in sister branch' qualifier on T13 / I7 / I6 dropped; coverage-holes section replaced with caveat pointers to the routing investigation. - 2026-05-06-i4-stereo-cross-stack-scenario.md: 'Spec — ready for implementation' → 'Landed' with PR #2755 + the three test scenarios that ship the assertion. - 2026-05-06-phase4-browser-harness.md: 'Spec — ready for implementation' → 'Landed', with notes on how the implementation diverged (used Container.Legacy.Consumer not @moq/watch; cert pinning via serverCertificateHashes; I2/I3/I4/I13/I14 originally deferred but later landed). - 2026-05-06-phase4-browser-harness-results.md: status updated to reflect 4.D CI removed per maintainer ask; layout note for the nestsClient/tests/browser-interop/ relocation; full scenario list reconciled with results doc. - 2026-05-07-late-join-catalog-flake-investigation.md: status updated to mention00f6cba31+207057374were reverted, and link to 2026-05-07-moq-relay-routing-investigation.md as the action plan. Adds note that the flake also affects four browser-tier scenarios after Browser I7 landed. - 2026-05-01-quic-stream-cliff-investigation.md: adds an HCgOY- override banner — recommendation 2 (framesPerGroup = 5) was superseded 4 days later by HCgOY field tests landing the prod default at 50. Cross-refs the reconciliation + production- rerun plans. Open follow-up #3 ('reset to 1') updated with the same context. No code or test changes.
This commit is contained in:
@@ -20,11 +20,11 @@ implement them.
|
||||
|
||||
| T# | Fix | Commit | Asserting scenario(s) | Tier | Status |
|
||||
|---|---|---|---|---|---|
|
||||
| **T8** | Skip `BUFFER_FLAG_CODEC_CONFIG` outputs in `MediaCodecOpusEncoder` (don't emit `OpusHead` as an audio frame). | `96cfa1235` | **I11** (`first_audio_frame_is_not_opus_codec_config`) — strips Container::Legacy and asserts the first audio frame's payload doesn't begin with the `OpusHead` magic. **I14** (browser warmup) is the spec's intended browser-side mate but **NOT YET LANDED** — Phase 4.C deferred it. | hang ✅ + browser ⏳ | **partial** |
|
||||
| **T10** | `endGroup()` on unmuted → muted transition (don't park the open uni stream when the speaker mutes). | `c23da5279` | **I3** (`mid_broadcast_mute_shortens_decoded_pcm`) — speaker mutes 1 s mid-broadcast; asserts the listener-side decoded PCM has a sample-count deficit consistent with stream FIN, NOT embedded zeros. A regression to "push zeros instead of FIN" would trip the upper bound. | hang ✅ | **green** |
|
||||
| **T11** | Drop `bestEffort = true` on moq-lite group uni streams (unreliable streams behave irregularly under loss). | `7e76ab113` | **I9** (`packet_loss_1pct_does_not_kill_audio`) — drives the QUIC client through `udp-loss-shim` at 1 % loss; asserts ≥ 60 % of expected samples + FFT peak intact. With `bestEffort = true` re-introduced, frames lost on dropped packets would NOT be retransmitted and the sample count would crash through the floor. | hang ✅ | **green** |
|
||||
| **T12** | Carry audio group sequence across hot-swaps (don't reset to 0 on speaker re-issuance — listener decoder caches by group ordering). | `be4e0b9f9` | **I5** (`speaker_hot_swap_does_not_crash`) — speaker calls `connectReconnectingSpeaker` mid-broadcast; asserts the listener sees no broadcast end and the post-swap window decodes cleanly with the 440 Hz peak intact. Group-sequence resets to 0 would cause the listener to drop "old" frames as duplicates. | hang ✅ | **green** |
|
||||
| **T13** | Reset Opus decoder on publisher boundary in `NestPlayer` (so the new publisher's pre-roll doesn't start mid-frame on stale decoder state). | `4714e3c72` | **I7** (`rust_hang_publish_reconnect_kotlin_listener_recovers`, in sister branch `feat/nests-i7-publisher-reconnect`) — Rust `hang-publish` cycles its session at T+2.5 s of a 5 s broadcast; asserts ≥ 2.5 s of decoded mono PCM with the 440 Hz peak intact across the cycle. A failed decoder reset would either crash or corrupt samples mid-stream — a corrupted half would skew the FFT peak away from 440 Hz. | hang ✅ | **green (in sister branch)** |
|
||||
| **T8** | Skip `BUFFER_FLAG_CODEC_CONFIG` outputs in `MediaCodecOpusEncoder` (don't emit `OpusHead` as an audio frame). | `96cfa1235` | **I11** (`first_audio_frame_is_not_opus_codec_config`) — strips Container::Legacy and asserts the first audio frame's payload doesn't begin with the `OpusHead` magic. **I14** (`chromium_decoder_no_errors_through_warmup_window`) is the browser-side mate — asserts Chromium `AudioDecoder.error` count is 0 across the warmup window. | hang ✅ + browser ✅ | **green** |
|
||||
| **T10** | `endGroup()` on unmuted → muted transition (don't park the open uni stream when the speaker mutes). | `c23da5279` | **I3** (`mid_broadcast_mute_shortens_decoded_pcm`) hang-tier + `chromium_listener_mid_broadcast_mute_shortens_pcm` browser-tier. Asserts the listener-side decoded PCM has a sample-count deficit consistent with stream FIN, NOT embedded zeros. A regression to "push zeros instead of FIN" would trip the upper bound. | hang ✅ + browser ✅ | **green** |
|
||||
| **T11** | Drop `bestEffort = true` on moq-lite group uni streams (unreliable streams behave irregularly under loss). | `7e76ab113` | **I9** (`packet_loss_1pct_does_not_kill_audio`) hang-tier + `chromium_listener_packet_loss_1pct_does_not_kill_audio` browser-tier. Drives the QUIC client through `udp-loss-shim` at 1 % loss; asserts the FFT peak intact. With `bestEffort = true` re-introduced, frames lost on dropped packets would NOT be retransmitted. | hang ✅ + browser ✅ | **green** |
|
||||
| **T12** | Carry audio group sequence across hot-swaps (don't reset to 0 on speaker re-issuance — listener decoder caches by group ordering). | `be4e0b9f9` | **I5** (`speaker_hot_swap_does_not_crash`) hang-tier + `chromium_listener_speaker_hot_swap_does_not_crash` browser-tier. Speaker calls `connectReconnectingSpeaker` mid-broadcast; asserts the listener sees no broadcast end and the post-swap window decodes cleanly with the 440 Hz peak intact. | hang ✅ + browser ✅ | **green** |
|
||||
| **T13** | Reset Opus decoder on publisher boundary in `NestPlayer` (so the new publisher's pre-roll doesn't start mid-frame on stale decoder state). | `4714e3c72` | **I7** hang-tier (`rust_hang_publish_reconnect_kotlin_listener_recovers` in `HangInteropReverseTest`) — Rust hang-publish cycles its session at T+2.5 s. **I7 reverse browser** (`chromium_publisher_reconnect_kotlin_listener_recovers`) — Chromium publishes via `publish.ts` reconnect mode. Both assert ≥ 2.5 s of decoded mono PCM with the 440 Hz peak intact across the cycle. | hang ✅ + browser ✅ | **green** |
|
||||
| **T14** | Recognise `GOAWAY` control type instead of silent FIN. | `73722d2ad` | **N/A in moq-lite-03.** moq-lite has no `GOAWAY` frame on the wire; the fix protects the IETF moq-transport-17 control-decoder path (`MoqSession.kt:417`). I12 was originally specced for this but doesn't apply — see `2026-05-06-cross-stack-interop-test-results.md`'s I12 section. The IETF code path is exercised by the existing `MoqCodecTest` unit test (`unknown_control_type_skips_message_without_corruption`) only — no cross-stack scenario covers it because no cross-stack peer speaks IETF moq-transport. | unit-test only | **green** |
|
||||
|
||||
## Aspirational T1–T7, T9, T15
|
||||
@@ -53,29 +53,40 @@ each scenario protects:
|
||||
| **I3** (mute window) | **T10** explicitly. |
|
||||
| **I4 fwd** (stereo 440/660) | Stereo plumbing through `AudioBroadcastConfig` (PR #2755) — not a T-series fix; protects the per-channel catalog → encoder pipeline. |
|
||||
| **I4 rev** (stereo Rust → Kotlin) | Listener stereo decode path. |
|
||||
| **I5** (speaker hot-swap) | **T12** explicitly. |
|
||||
| **I6** (multi-listener) | T11 fan-out behaviour (in `feat/nests-i6-multi-listener`). |
|
||||
| **I7** (publisher reconnect) | **T13** explicitly (in `feat/nests-i7-publisher-reconnect`). |
|
||||
| **I5** (speaker hot-swap) | **T12** explicitly (hang + browser tiers). |
|
||||
| **I6** (multi-listener) | T11 fan-out behaviour. |
|
||||
| **I7** (publisher reconnect) | **T13** explicitly. Hang-tier exercises Rust hang-publish reconnect; browser-tier exercises Chromium publish.ts reconnect. |
|
||||
| **I8** (SubscribeDrop on unknown track) | Subscribe rejection handling — moq-lite-03 protocol-level guard, not a T-series fix. |
|
||||
| **I9** (1 % packet loss) | **T11** explicitly. |
|
||||
| **I9** (1 % packet loss) | **T11** explicitly (hang + browser tiers). |
|
||||
| **I10** (60 s long broadcast) | `framesPerGroup` cadence interaction at scale (see `2026-05-07-framespergroup-reconciliation.md`). |
|
||||
| **I11** (wire-byte capture) | **T8** explicitly. |
|
||||
| **I12** (Goaway) | N/A in moq-lite-03; **T14** is exercised only by the IETF moq-transport unit test path. |
|
||||
| **I13** (browser `framesPerGroup=50` + `Container.Consumer`) | **NOT YET LANDED** — Phase 4.C deferred. Would protect the production cadence end-to-end against the WebCodecs decode path. |
|
||||
| **I14** (WebCodecs warmup × CSD-skip) | **NOT YET LANDED** — Phase 4.C deferred. Browser-side mate of I11; together they'd cover T8 on both rendering paths. |
|
||||
| **I15** (Chromium ALPN round-trip) | moq-lite ALPN drift detection (in `feat/nests-browser-interop`). |
|
||||
| **I13** (browser `framesPerGroup=50` long broadcast) | `framesPerGroup` cadence interaction at scale on the browser path. Note: spec asked for `framesPerGroup = 50`; local relay's per-stream byte cliff blocks that, so the test pins `5` — see `2026-05-07-framespergroup-reconciliation.md`. |
|
||||
| **I14** (WebCodecs warmup × CSD-skip) | **T8** browser-side mate of I11. Asserts `AudioDecoder.error` count is 0; a `OpusHead` leak would fail. |
|
||||
| **I15** (Chromium ALPN round-trip) | moq-lite ALPN drift detection. |
|
||||
|
||||
## Coverage holes
|
||||
## Coverage state
|
||||
|
||||
Scenarios specced as P0 / P1 in the spec but **not yet landed**:
|
||||
All T-series wire fixes (T8, T10–T14) have ≥ 1 cross-stack
|
||||
asserting scenario landed. Both hang-tier AND browser-tier
|
||||
mates exist for T8/T10/T11/T12/T13. T14 (GOAWAY) only applies
|
||||
to the IETF moq-transport target which the production stack
|
||||
doesn't use.
|
||||
|
||||
- **I13** (browser `framesPerGroup=50` long broadcast) — P0 browser-tier. Protects nothing today on the browser path; T11's browser-side coverage is implicit in I1 alone.
|
||||
- **I14** (WebCodecs warmup × CSD-skip) — P0 browser-tier. Hang-tier I11 catches T8 on the wire; without I14 a browser-side regression where the WebCodecs decoder mishandles a warmup-period CSD blob would silently pass.
|
||||
DoD #5 (gap matrix coverage) closed.
|
||||
|
||||
For the merge-ready interop test branches:
|
||||
**Caveats — see linked investigation docs:**
|
||||
|
||||
- T13's asserting scenario (I7) is in `feat/nests-i7-publisher-reconnect` — when that merges into `claude/cross-stack-interop-test-XAbYB` (or main), this matrix should drop the "in sister branch" qualifier.
|
||||
- I6's asserting scenario is in `feat/nests-i6-multi-listener` — same caveat.
|
||||
- Five browser-tier scenarios soft-pass on listener-side
|
||||
0-frame outcomes due to the upstream moq-relay 0.10.x
|
||||
routing race (`2026-05-07-late-join-catalog-flake-investigation.md`).
|
||||
Hard floors lined up to land in
|
||||
`2026-05-07-tighten-cross-stack-assertions.md` once the
|
||||
routing race is closed.
|
||||
- Suite-mode runs hit the same race intermittently;
|
||||
individual-test mode is reliable. CI is intentionally not
|
||||
wired (`2026-05-07-cross-stack-interop-ci-gating.md`) until
|
||||
stability is achieved.
|
||||
|
||||
## Files referenced
|
||||
|
||||
@@ -83,8 +94,10 @@ For the merge-ready interop test branches:
|
||||
- `nestsClient/plans/2026-05-06-cross-stack-interop-test-results.md` (results — what landed)
|
||||
- `nestsClient/plans/2026-05-07-framespergroup-reconciliation.md` (cadence reconciliation)
|
||||
- `nestsClient/plans/2026-05-07-i7-post-reconnect-cliff-investigation.md` (I7 cycle-2 cliff)
|
||||
- `nestsClient/plans/2026-05-07-late-join-catalog-flake-investigation.md` (relay routing flake)
|
||||
- `nestsClient/plans/2026-05-07-t16-closure-roadmap.md` (next steps)
|
||||
- `nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/native/HangInteropTest.kt`
|
||||
- `nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/native/HangInteropReverseTest.kt` (sister branch)
|
||||
- `nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/native/HangInteropMultiListenerTest.kt` (sister branch)
|
||||
- `nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/native/BrowserInteropTest.kt` (sister branch)
|
||||
- `nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/native/HangInteropReverseTest.kt`
|
||||
- `nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/native/HangInteropMultiListenerTest.kt`
|
||||
- `nestsClient/src/jvmTest/kotlin/com/vitorpamplona/nestsclient/interop/native/BrowserInteropTest.kt`
|
||||
- T# fix commits: `96cfa1235` (T8), `c23da5279` (T10), `7e76ab113` (T11), `be4e0b9f9` (T12), `4714e3c72` (T13), `73722d2ad` (T14)
|
||||
|
||||
Reference in New Issue
Block a user