zebra-spaces: re-apply sink on every attach + per-tick ctx.sink telemetry (kill blanka-chrome sink drift)

After caa0548 (fixes A + B for ticket 0001), blanka-chrome was still
silent. Fresh telemetry pinned a third failure mode:

  21:31:31  audio via AudioContext 47e5 sink=c38572ec…   ← good
  …leave + rejoin…
  21:31:33  audio via AudioContext 47e5 sink=default     ← drifted

No `audioCtx sink → c38572ec…` log line between the two attaches.
applySinkToAudioCtx was only invoked inside the `if (!audioCtx)` branch
in attachAudioStreamViaWorklet — a persistent audioCtx whose .sinkId
getter returned '' (system default) after a leave/rejoin never got
its sink re-applied, so every subsequent attach emitted to the system
default speaker instead of the device the user picked in the dropdown.

Fix: when audioCtx already exists AND speakerDeviceId is set AND
audioCtx.sinkId !== speakerDeviceId, call applySinkToAudioCtx() to
restore routing. Idempotent (same-sink call is a noop).

Telemetry: every 5s tick now includes `ctx.sink=…` and `want=…` when
the active sink doesn't match the picked one, so drift is visible
without grepping for the rare attach event.

Test: attach re-applies sink when audioCtx persists across leave/rejoin
and the picked sink drifted. Sandbox now exposes setSpeakerDeviceId so
the test can drive the picked-device path through the real
attachAudioStreamViaWorklet branch.

Ticket 0001 updated with the second-pass telemetry and fix (C).
This commit is contained in:
Russell Ballestrini 2026-06-07 17:42:12 -04:00
parent b9e254172b
commit 4cedd85dc6
No known key found for this signature in database
3 changed files with 115 additions and 6 deletions

View file

@ -168,11 +168,49 @@ for >5s, swap the worklet back to the cached SFU stream — same
pattern the `connectionState === 'failed'` path already uses at line
6755.
## 2026-06-07 second telemetry pass — sink DRIFT identified
After deploying (A) + (B), blanka-chrome was still silent. Fresh
telemetry pinned a different per-attach failure mode:
```
21:31:30 audio attach uuid=47e5 target=0.5s (current pool=1)
21:31:31 audio via AudioContext 47e5 target=0.5s ctxState=running sink=c38572ec…
21:31:31 jitter-buffer started uuid=47e5 target=0.5s
…leave/rejoin cycle…
21:31:33 audio attach uuid=47e5 target=0.5s (current pool=1)
21:31:33 audio via AudioContext 47e5 target=0.5s ctxState=running sink=default ← drifted
```
No `audioCtx sink → c38572ec…` log line ever appeared. So
`applySinkToAudioCtx()` either never ran or hit the
`typeof audioCtx.setSinkId !== 'function'` early-return at the moment
of execution. The earlier sink fix only invoked
`applySinkToAudioCtx()` inside the `if (!audioCtx)` branch — a
persistent audioCtx whose `.sinkId` getter returned `''` (default) was
never re-corrected.
## Fix (C) — re-apply sink on every attach when it drifted
`attachAudioStreamViaWorklet` now: if `audioCtx` already exists AND
`speakerDeviceId` is set AND `audioCtx.sinkId !== speakerDeviceId`,
call `applySinkToAudioCtx()`. Idempotent — same-sink call is a no-op.
Also added per-tick `ctx.sink=` to the telemetry stream so sink drift
is visible on every 5s line instead of needing to find the rare attach
log. When the active sink doesn't match the picked one, the line
includes `want=…` so the mismatch jumps out.
## Status notes
- **2026-06-07 (in-progress):** sink hypothesis ruled out by fresh
telemetry; root cause is (A) tracks=0 race + (B) mesh-swap orphan.
Implementing both fixes in this branch.
- **2026-06-07 (in-progress, fix C deployed):** sink-drift on
audioCtx-persistent path identified + patched. Need a third telemetry
pass to confirm the per-tick `ctx.sink=` line now stays on the
picked device across leave/rejoin.
- **2026-06-07 (fixes A + B deployed):** sink hypothesis from 467146a
ruled out by fresh telemetry; (A) tracks=0 race + (B) mesh-swap
orphan landed in caa0548. blanka-chrome was still silent, leading
to fix (C) above.
- **2026-06-06:** the Jun 5 cascade + flushSfuStreams prefix-match fix
(`0ce1339`) helped firefox but not chrome. Telemetry above ruled out
the FSM / attach defects.