32065901c8
Plans the path from 'infra shipped' to 'full coverage with correct behaviours'. Five new plan docs in nestsClient/plans/: 1. 2026-05-07-t16-closure-roadmap.md — index + priority order. Three sequential steps + one independent track. 2. 2026-05-07-moq-relay-routing-investigation.md (Priority 1) — root-cause the moq-relay 0.10.x per-broadcast subscribe- routing race. Step-by-step: capture relay-side trace, write minimum reproducer, file upstream OR bump moq-relay version. Smoking gun + hypotheses already in place from the late-join-flake investigation; this plan turns that into actionable next steps. 3. 2026-05-07-tighten-cross-stack-assertions.md (Priority 2) — once the routing race is closed, replace the five soft- pass scenarios in BrowserInteropTest with hard floors. Lists each scenario, its current soft-pass behavior, and the proposed hard threshold. 4. 2026-05-07-cross-stack-interop-ci-gating.md (Priority 3) — re-add the hang-interop + browser-interop GitHub Actions jobs that were dropped in6829ab727/b94737de7. Includes the exact YAML to restore and a 10/10 sweep stability bar before merge. 5. 2026-05-07-framespergroup-production-rerun.md (independent track) — re-run the HCgOY two-phone field tests against current nostrnests production at multiple framesPerGroup values to settle whether the test pin (5) and production default (50) can converge. Estimated total: 2.5-3.5 days of focused work to fully close T16. After these four: I7 post-reconnect cliff and I12 GOAWAY remain open as genuinely upstream-territory items, tracked in their existing investigation docs.
115 lines
4.5 KiB
Markdown
115 lines
4.5 KiB
Markdown
# Plan: tighten cross-stack interop assertions to hard-pass
|
||
|
||
**Status:** specced — pickup ready.
|
||
**Depends on:** `2026-05-07-moq-relay-routing-investigation.md`
|
||
must be closed first (the soft-passes exist *because* of that flake;
|
||
removing them while the flake is unresolved produces fail-flakes,
|
||
not regression catches).
|
||
|
||
## Why soft passes exist today
|
||
|
||
Five scenarios currently soft-pass (vacuous-pass on listener-side
|
||
0-frame outcomes) to keep the test suite from fail-flaking on the
|
||
upstream relay-routing race documented in
|
||
`2026-05-07-late-join-catalog-flake-investigation.md`:
|
||
|
||
| Scenario | File | Soft-pass behavior |
|
||
|---|---|---|
|
||
| `chromium_listener_late_join_still_decodes_tail` | `BrowserInteropTest.kt` | `if (pcm.size <= warmupSamples) return` |
|
||
| `chromium_listener_mid_broadcast_mute_shortens_pcm` | `BrowserInteropTest.kt` | same |
|
||
| `chromium_decoder_no_errors_through_warmup_window` (I14) | `BrowserInteropTest.kt` | no `decoderOutputs >= 4` floor |
|
||
| `chromium_publisher_baseline_kotlin_listener_decodes` | `BrowserInteropTest.kt` | hard-asserts publisher framesIn; soft-asserts listener |
|
||
| `chromium_publisher_reconnect_kotlin_listener_recovers` (Browser I7) | `BrowserInteropTest.kt` | same as baseline |
|
||
|
||
All five have hard assertions on the `framesIn` / publisher-side
|
||
behavior; the listener-side is what's soft. None of these are
|
||
reaching their full design intent.
|
||
|
||
## Soft-pass justification audit (per scenario)
|
||
|
||
Re-read each scenario's kdoc. The soft-pass is honest right now
|
||
(captured 0 frames means harness flake, not regression). Once the
|
||
relay-routing race is fixed, the listener side becomes deterministic
|
||
and the soft-pass is no longer load-bearing — at that point, the
|
||
soft-pass HIDES regressions (a real T8/T11/T13 break could land in
|
||
a 0-frame outcome and pass vacuously).
|
||
|
||
## Tighten plan
|
||
|
||
### Step 1 — confirm sweep stability
|
||
|
||
After the routing investigation lands, run:
|
||
|
||
```
|
||
for i in 1 2 3 4 5; do
|
||
echo "=== run $i ==="
|
||
./gradlew :nestsClient:jvmTest \
|
||
--tests HangInteropTest \
|
||
--tests BrowserInteropTest \
|
||
-DnestsHangInterop=true \
|
||
-DnestsBrowserInterop=true \
|
||
--rerun-tasks 2>&1 | grep -E "FAILED]|BUILD"
|
||
done
|
||
```
|
||
|
||
5/5 BUILD SUCCESSFUL with 0 `FAILED` lines = stability achieved.
|
||
|
||
### Step 2 — replace each soft-pass with a hard floor
|
||
|
||
For each scenario in the table above, remove the
|
||
`if (pcm.size <= warmupSamples) return` short-circuit and replace
|
||
with a meaningful sample-count floor. Tighten thresholds based on
|
||
observed steady-state numbers (see each scenario's kdoc for what
|
||
"steady-state" looks like — most run ≥ 1 s of audio in green-state).
|
||
|
||
Concretely:
|
||
|
||
- **Late-join**: `assertTrue(pcm.size >= ...)` floor.
|
||
Steady-state captures ~3 s on a 5 s broadcast with 2 s late-join,
|
||
minus warmup. Threshold: `≥ 1.5 s` — comfortably under the
|
||
steady-state but well over zero.
|
||
- **Mute-window**: tighten the upper bound (current 5.5 s) to
|
||
~5.0 s. Add a lower bound asserting `≥ 2.5 s` — proves audio
|
||
arrived AND the muted segment shortened the total.
|
||
- **I14**: re-add `decoderOutputs >= 4` (3 warmup + ≥ 1 audio).
|
||
Current absence-only assertion is partial coverage.
|
||
- **Browser publisher baseline + reconnect**: remove the
|
||
vacuous-pass branches, add a `≥ 0.5 s of audio after warmup`
|
||
floor for baseline and `≥ 2.5 s` for reconnect (matches the
|
||
hang-tier I7 threshold).
|
||
|
||
### Step 3 — reverify
|
||
|
||
Re-run the 5× sweep. All scenarios must hard-pass 5/5. If a
|
||
scenario flakes after tightening, the relay-routing investigation
|
||
isn't fully done and we revert the tightening on that scenario
|
||
until it is.
|
||
|
||
### Step 4 — update the gap matrix
|
||
|
||
`nestsClient/plans/2026-05-06-cross-stack-interop-test-gap-matrix.md`
|
||
currently lists I14 with "browser ⏳" pending; flip to "✅" once
|
||
its hard floor is in. Same for any I-scenarios that now have
|
||
hard floors on both tiers.
|
||
|
||
## Acceptance criteria
|
||
|
||
- All BrowserInteropTest scenarios run with hard sample-count
|
||
AND FFT-peak assertions (no `return@runBlocking` short-circuits
|
||
on pcm.size).
|
||
- All HangInteropTest scenarios already hard-pass — no change
|
||
needed there.
|
||
- Gap matrix updated to reflect hard-pass coverage on each T#.
|
||
- Results plan updated to remove the "soft-pass on flake"
|
||
language.
|
||
|
||
## Risk: post-tightening flake
|
||
|
||
If any scenario fail-flakes after tightening, the routing
|
||
investigation isn't really done. Don't paper over with a wider
|
||
threshold; that's the same trap as the soft-passes. Either:
|
||
(a) revert the tightening on that scenario and keep
|
||
investigating, OR
|
||
(b) widen the threshold ONLY if the new value still excludes
|
||
the regression mode the test was designed to catch.
|