10/10 sweep × 22 tests = 220/220 hard-pass post-recalibration on the merged branch (~5m 28s per sweep). Stability bar from `2026-05-07-cross-stack-interop-ci-gating.md` met; both `hang-interop` and `browser-interop` jobs in build.yml since commit `21947bc5`. Marks Priority 3 closed in: - `2026-05-07-cross-stack-interop-ci-gating.md` - `2026-05-07-t16-closure-roadmap.md` - `2026-05-06-cross-stack-interop-test-results.md` (CI integration § wired) - `2026-05-06-cross-stack-interop-test-gap-matrix.md` (history notes) T16 closure roadmap is now done end-to-end: - Priority 1 ✅ closed by `:quic` main merge (commit `8f8251a5`) - Priority 2 ✅ closed by hard-floor tightening (commits `04be38ad`, `029329af`, `f8dc9c59`) - Priority 3 ✅ closed by CI yaml + 10/10 stability (commit `21947bc5`) Open follow-ups remain (browser hot-swap re-attach, post-reconnect listener cliff, framesPerGroup production rerun) but none block T16 closure.
6.0 KiB
Plan: wire CI gating for the cross-stack interop suite
Status: ✅ CLOSED 2026-05-07. Both jobs wired in commit
21947bc5 (path-tweaked from the original removed shape per
the nestsClient/tests/browser-interop/ move). Stability-bar
sweep: 10/10 BUILD SUCCESSFUL × 22 tests = 220/220 pass.
Acceptance bar from the roadmap met.
Depended on:
2026-05-07-moq-relay-routing-investigation.mdclosed (✅)2026-05-07-tighten-cross-stack-assertions.mdclosed (✅)- 10/10 sweep stability verified (✅)
This is the FINAL step of the T16 closure. With stable hard-pass suites, CI gating becomes safe and meaningful.
What's needed
A) .github/workflows/build.yml — the hang-interop job
The job was originally part of this branch but removed per
maintainer ask in commit 6829ab727 ("ci(nests): drop hang-interop
job from build.yml") because the suite was flaky. Resurrect the
exact same shape:
hang-interop:
needs: lint
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- uses: actions/setup-java@v5
with: { distribution: 'zulu', java-version: 21 }
- uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- uses: dtolnay/rust-toolchain@stable
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
nestsClient/tests/hang-interop/target
~/.cache/amethyst-nests-interop/hang-interop-cargo
key: ${{ runner.os }}-cargo-${{ hashFiles('nestsClient/tests/hang-interop/Cargo.lock', 'nestsClient/tests/hang-interop/REV') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Run cross-stack interop suite
run: ./gradlew :nestsClient:jvmTest -DnestsHangInterop=true
- uses: actions/upload-artifact@v7
if: failure()
with:
name: Hang Interop Test Reports
path: nestsClient/build/reports/tests/jvmTest/
The git show 6829ab727 -- .github/workflows/build.yml reverse
gives the exact diff to re-add. Linux-only is correct: the cargo
install of moq-relay 0.10.x has nontrivial native deps
(aws-lc-sys, ring) that take 5+ min cold; cached runs ~30 s.
macOS / Windows would double matrix cost without catching new
defects.
B) .github/workflows/build.yml — the browser-interop job
Same shape as A, plus bun + Playwright caching:
browser-interop:
needs: lint
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
# ...same checkout + JDK + Gradle + Rust + cargo cache as hang-interop...
- uses: oven-sh/setup-bun@v2
with: { bun-version: 1.3.11 }
- uses: actions/cache@v4
with:
path: |
nestsClient/tests/browser-interop/node_modules
nestsClient/tests/browser-interop/dist
key: ${{ runner.os }}-bun-${{ hashFiles('nestsClient/tests/browser-interop/package.json', 'nestsClient/tests/browser-interop/bun.lock') }}
- uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('nestsClient/tests/browser-interop/package.json') }}
- name: Run browser cross-stack interop suite
run: |
./gradlew :nestsClient:jvmTest \
--tests "com.vitorpamplona.nestsclient.interop.native.BrowserInteropTest" \
-DnestsHangInterop=true \
-DnestsBrowserInterop=true
- uses: actions/upload-artifact@v7
if: failure()
with:
name: Browser Interop Test Reports
path: |
nestsClient/build/reports/tests/jvmTest/
nestsClient/tests/browser-interop/test-results/
nestsClient/tests/browser-interop/playwright-report/
Same git show b94737de7 -- .github/workflows/build.yml reverse
gives the exact diff (feat/nests-browser-interop's removal
commit).
C) Cross-link with :cli interop tests
The existing nests-interop opt-in pattern already lives in
cli/tests/nests/nests-interop.sh. Confirm both new jobs run
in parallel with that without resource contention. They use
different ports (NativeMoqRelayHarness reserves ServerSocket(0))
so they're independent at the network level.
Stability bar — verified ✅
for i in 1..10; do
./gradlew :nestsClient:jvmTest \
--tests HangInteropTest --tests BrowserInteropTest \
-DnestsHangInterop=true -DnestsBrowserInterop=true --rerun-tasks
done
Result: 10/10 BUILD SUCCESSFUL × 22 tests = 220/220 pass. ~5m 28s steady state per sweep on the agent rig.
CI runtime budget
- Hang-interop job: ~3-4 min on warm cache (one suite run, 60 s long-broadcast scenario dominates), ~8 min cold (cargo install moq-relay).
- Browser-interop job: ~5-7 min warm (Chromium boot × N scenarios), ~10 min cold (Playwright install).
- Both run in parallel after
lint.
Total CI overhead: ~5-10 min on the critical path beyond the existing build matrix. Acceptable.
Documentation updates
After CI is green:
nestsClient/plans/2026-05-06-cross-stack-interop-test-results.md— replace the "CI integration: Not wired" section with "wired, tracking flake-rate at 0/N runs".nestsClient/plans/2026-05-06-cross-stack-interop-test-gap-matrix.md— replace#6 CI integration: ⏸ deferredwith✅ live.- Pick a maintainer to monitor the first 2 weeks of CI runs and bisect any new flake immediately (don't let it accumulate as "known flake" again).
Acceptance criteria
- Both jobs added to
build.ymland merge to main. - 10/10 sweep before merge.
- First 2 weeks post-merge: ≥ 95% green rate. If lower, the routing investigation isn't really done — pull the jobs again until it is.
Optional follow-ups
- Add I-12 GOAWAY scenario IF an IETF moq-transport target lands.
Currently N/A in moq-lite-03 per
cross-stack-interop-test-results.md's I12 section. If an IETF target ever ships, this is the cross-stack regression test. - Surface
framesPerGroupas a per-deployment config if the framesPerGroup-rerun outcome shows the two rigs can't converge (see2026-05-07-framespergroup-production-rerun.md).