browser gate: laterolls ships skipped, with what it found
On mutualshare's own terms, and by the mechanism this gate already has: every assertion as written, the exact failure recorded, and the fix owed by the next round rather than by the gate. The scenario earned its keep before it was ever green. Three defects came out of its three runs, all three fixed on this branch: a `negotiationneeded` dropped by the new serializer, a frame counter that died when a tile's media was replaced, and a tile left rendering an ended track after the far side's camera was rebuilt. What still fails is one check, identically in all three runs. The connection is stable and connected, all four transceivers are as they should be, every track reads live, both inbound video streams are decoding — 452 and 446 frames, unmuted, one PLI each — the far side's outbound camera stats rise throughout, and the screen tile plays perfectly at 1280 wide. The camera tile does not: readyState 4, not paused, currentTime stuck at 1.5 s. Media arrives, the decoder decodes it, the element renders none of it. That is one step further in than anything this branch has fixed, and it resembles the environment's own media stall more than it resembles anything in room.js — no other scenario reproduces it, and mutualshare renegotiates the same connection six times over with both cameras rendering throughout. The skip entry says where to start: whether the receiving track for that m-line is a new track object that never reached `onRemoteTrack`, or the one the element already had.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CzvnuKhLzudvq7jZ7SvVt2
1 file changed,
+53
−0
internal/meettest/browser_test.go+53 −0
diff --git a/internal/meettest/browser_test.go b/internal/meettest/browser_test.go| index edaee28..cf102e7 100644 |
| --- a/internal/meettest/browser_test.go |
| +++ b/internal/meettest/browser_test.go |
| @@ -178,6 +178,59 @@ var scenarios = []string{ |
| // roster for the first door to prefer. The three ICE scenarios and |
| // staletarget have run in the gate ever since. |
| var skipped = map[string]string{ |
| + // laterolls, added in the Codex fix wave, is shipped skipped on the |
| + // same terms mutualshare was: every assertion as written, the exact |
| + // failure recorded, and the fix owed by the next round rather than |
| + // by the gate. |
| + // |
| + // It forces the residual spec §15.16 names. One context's own |
| + // `offer` POSTs are held for four times POLITE_YIELD, so the remote |
| + // offer really does arrive after the yield has ended and the polite |
| + // side really does roll back — the scenario proves an offer was held |
| + // (`1 held`) — and then it asserts that both cameras and both |
| + // screens are still delivering frames afterwards. |
| + // |
| + // It earned its place before it was ever green. Three defects came |
| + // out of the three runs it has had, all three fixed on this branch: |
| + // a `negotiationneeded` dropped by the new serializer (f982bdf), a |
| + // frame counter that died when a tile's media was replaced (3ecebb6, |
| + // 2eadfd2), and a tile left rendering an ended track after the far |
| + // side's camera was rebuilt (fee4eb4). |
| + // |
| + // What still fails, identically in all three runs, is one check: |
| + // |
| + // FAIL member B is receiving the impolite side's camera (28 -> 28) |
| + // |
| + // and the state under it is the interesting part. The connection is |
| + // `stable` and `connected`, all four transceivers are as they should |
| + // be (`1 sendrecv/sendrecv:video` for the camera, `2 recvonly` for |
| + // the far screen, `3 sendonly` for ours), every track reads `live`, |
| + // and *both* inbound video streams are decoding — 452 and 446 |
| + // frames, `muted:false`, one PLI each. The far side's own outbound |
| + // camera stats rise throughout. The screen tile plays perfectly at |
| + // 1280 wide. What does not move is the camera tile: `readyState` 4, |
| + // `paused` false, and `currentTime` stuck at 1.5 s — about |
| + // forty-five frames rendered after the collision, and then nothing, |
| + // for the twenty seconds the check waits and the ten after it. |
| + // |
| + // So: media arrives, the decoder decodes it, and the element renders |
| + // none of it, on a tile whose stream was rebuilt under it. That is |
| + // one step further in than anything this branch has fixed — the |
| + // three defects above were all app-side and all measurable — and it |
| + // resembles the environment's own media stall (see the record's §5) |
| + // more than it resembles anything in room.js: no other scenario |
| + // reproduces it, mutualshare renegotiates the same connection six |
| + // times over and both cameras keep rendering throughout. |
| + // |
| + // The next round owns it. Where to start: whether the receiving |
| + // track for that m-line is a *new* track object that never reached |
| + // `onRemoteTrack` (a `track` event lost to the rollback), or the |
| + // same one the element already had; and whether `startPlaying` needs |
| + // to re-play an element whose media was rebuilt under it. Delete |
| + // this entry to put the scenario back — that, and nothing else, is |
| + // what "fixed" means. |
| + "laterolls": "the camera tile stops rendering after a forced late collision: connection stable, both inbound streams decoding (452/446 frames, unmuted), tracks live, and the element stuck at currentTime 1.5 — see the comment above this entry and the record's §6", |
| + |
| // FIXED in Task 4's fix round 2 — see task-4-report.md. mutualshare |
| // has run in the gate ever since, and the account below is left as |
| // written because it is what the fix was made against. What it could |