Files
amethyst/nestsClient/plans/2026-05-07-tighten-cross-stack-assertions.md
T
Claude 32065901c8 docs(nests): T16 closure roadmap + 4 follow-up plans
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 in 6829ab727 / 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.
2026-05-07 14:36:21 +00:00

4.5 KiB
Raw Blame History

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.