zebra-report/web
Russell Ballestrini 07fcec7775
zebra-spaces: refactor sub PC ontrack into handleRemoteSfuTrack + multi-peer mesh tests
Receive-side mesh state machine (the bit that decides which peer gets
which tile) was buried inside an anonymous pc.ontrack callback inside
sfuSubscribe(). Extracted into a named top-level function
handleRemoteSfuTrack so tests can drive it directly with synthetic
RTCTrackEvents — no real RTCPeerConnection, no real SFU.

test/multi-peer-mesh.test.js pins fox's stated invariant:
  'whatever one device shares all should see, and when unshared none
   should see.'

Eight scenarios across 2-3 fake browser sandboxes, each holding the
shipped handleRemoteSfuTrack + renderVideoTile + removeVideoTile +
watchVideoTrackForRemoval + the maps they own:

- one peer publishes camera -> every other peer ends with that pubHex
  in cameraStreams + a tile entry
- one peer unshares (track ended) -> every other peer drops that pubHex
- one peer unshares mid-flow (mute past window) -> drops correctly
- hiccup supplant (same pubkey, new track) -> tile preserved AND
  pointed at the new stream object (this is the MSID-supplant fix from
  d5e9e4e — fresh MediaStream per track means the video element binds
  to the new RTP cleanly)
- hiccup supplant + the OLD track's stream-identity guard prevents the
  NEW tile from being reaped
- supplant + sustained mute past window on the NEW track -> reaped
  correctly
- echo guard: a peer's own publish never enters their own cameraStreams
- three publishers fan-out: A B C all publish, every peer ends with
  exactly the other two

Wired into Makefile as test-mesh + added to test-all. Pure Node, no
browser or proxy server needed. Will catch the regressions where one
peer's publish/unpublish silently desyncs another peer's view.
2026-06-03 11:24:38 -04:00
..
blog phase 1: unfirehose reconstruction from session JSONL ingest 2026-05-27 13:51:14 -04:00
fonts phase 2: gap analysis — cat>> append + binary asset recovery 2026-05-27 13:54:19 -04:00
chat.html css: .row uses minmax(0, max-content) so long labels shrink + wrap 2026-06-02 09:27:55 -04:00
host-your-own.html zebra: dark mode default on all pages + unified theme key 2026-06-01 22:18:02 -04:00
how-it-works.html zebra: dark mode default on all pages + unified theme key 2026-06-01 22:18:02 -04:00
index.html web: bump mobile body padding from 1rem to 1.25rem so the right edge has visible breathing room 2026-05-31 14:13:25 -04:00
kernel.html web: bump mobile body padding from 1rem to 1.25rem so the right edge has visible breathing room 2026-05-31 14:13:25 -04:00
stamp.js web: stamp each zebra-report page with build date + md5/sha256 2026-05-28 17:50:12 -04:00
zebra-audio.html css: .row uses minmax(0, max-content) so long labels shrink + wrap 2026-06-02 09:27:55 -04:00
zebra-spaces.html zebra-spaces: refactor sub PC ontrack into handleRemoteSfuTrack + multi-peer mesh tests 2026-06-03 11:24:38 -04:00