docs: the four things the render watch is not for
§15.16 gains the four cases the watch deliberately leaves alone, each of which cost a red gate run to learn: a tile receiving nothing (idle, not stalled), a track ended or muted (the sender's doing), an element the autoplay policy paused (the person's, and §5's Play control says so), and an element painting one frame every few seconds (stalling with a tic, which is why the clock must advance by a quarter of a second in a poll to count as health). Its measured numbers are updated with the run that stopped dead and came back — `[25,25,25,25,25,25]`, then 21 → 26 across two successive intervals — and with the sentence that keeps the claim honest: the stall is the browser's, and what is claimed here is a bounded recovery from it and nothing more. The record's §7 gains the same account, as three red runs and what each was right about; the wave report likewise.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CzvnuKhLzudvq7jZ7SvVt2
2 files changed,
+54
−9
docs/superpowers/reviews/2026-09-10-slice-4-record.md+27 −0docs/superpowers/specs/2026-09-07-meet-design.md+27 −9
diff --git a/docs/superpowers/reviews/2026-09-10-slice-4-record.md b/docs/superpowers/reviews/2026-09-10-slice-4-record.md| index bf48c24..955af92 100644 |
| --- a/docs/superpowers/reviews/2026-09-10-slice-4-record.md |
| +++ b/docs/superpowers/reviews/2026-09-10-slice-4-record.md |
| @@ -523,3 +523,30 @@ closed.** |
| counts remote offers applied over this side's own outstanding offer — |
| the rollback, seen from outside — and fails if there was none to |
| recover from. One was seen on every run. |
| + |
| +### Three red runs, and what each of them was right about |
| + |
| +The render watch did not land clean, and the gate was right every time. |
| + |
| +1. **`playfallback`, twice.** §5 offers a Play control when the |
| + browser's autoplay policy refuses a remote video, and it stopped |
| + appearing. Guarding the watch on `paused` was not enough: the tile |
| + binds more than once now — audio arrives, then the camera — and the |
| + second bind called `play()` again behind the refusal and hid a |
| + question nobody had answered. `shouldPlay` is the rule that came out |
| + of it, and it is a product rule rather than a watch rule: while the |
| + Play control is showing, the gesture is the person's to give. |
| +2. **`laterolls`, on a stutter.** The tile painted one frame every few |
| + seconds — `[22,23,23,23,23,25]` across three seconds — and any |
| + advance at all counted as health, so the watch's budget reset for |
| + ever and the connection never earned the reset that would rebuild |
| + it. A second of video is a second of clock; a frame is thirty |
| + milliseconds. `RENDER_MOVED` is 0.25 s now, a clock that goes |
| + backwards is the watch's own repair landing rather than a stall to |
| + judge, and the replay hands the element a *new* `MediaStream` over |
| + the same tracks rather than the object it was already holding. |
| + |
| +Measured on the run that had been failing: `[25,25,25,25,25,25]` — |
| +stopped dead — and then 21 → 26 across two successive intervals once |
| +the watch escalated. **The stall is the browser's; what is claimed here |
| +is a bounded recovery from it, and nothing more.** |
diff --git a/docs/superpowers/specs/2026-09-07-meet-design.md b/docs/superpowers/specs/2026-09-07-meet-design.md| index 716cd64..4c778f6 100644 |
| --- a/docs/superpowers/specs/2026-09-07-meet-design.md |
| +++ b/docs/superpowers/specs/2026-09-07-meet-design.md |
| @@ -1745,12 +1745,24 @@ two seconds. |
| back.** One link further along, and the one nothing else notices. The |
| same `getStats` walk reads `framesDecoded` per tile; three polls in a |
| row where the decoder is delivering, the tile's track is live and |
| -unmuted, and the element's own `currentTime` has not moved is a |
| -rendering stall. The repair is to take the stream off the element and |
| -give it back and ask it to play again; two of those, then a reset, then |
| -it stops asking. A tile receiving nothing is idle rather than stalled — |
| -that is what reading the decode count alongside the clock is for — and |
| -a track that has ended or gone muted is the sender's business. |
| +unmuted, and the element's own clock has not moved is a rendering |
| +stall. The repair is a fresh `MediaStream` over the same tracks put |
| +back on the element and played again; two of those, then a reset, then |
| +it stops asking. |
| + |
| +Four things are deliberately not its business, and each of them cost a |
| +red gate run to learn. A tile **receiving nothing** is idle, not |
| +stalled, which is what reading the decode count alongside the clock is |
| +for. A track that has **ended or gone muted** is the sender's doing. An |
| +element the autoplay policy **paused** is the person's: §5 offers a |
| +Play control, and this watch — and every rebinding of a tile — leaves |
| +it alone while that control is showing, because calling `play()` behind |
| +it hides a question nobody has answered. And an element painting **one |
| +frame every few seconds** is stalling with a tic rather than playing: |
| +a second of video is a second of clock and a frame is thirty |
| +milliseconds, so the clock must advance by `RENDER_MOVED` (0.25 s) in a |
| +poll to count as health. Reading any advance at all as health let such |
| +a tile reset the budget for ever and never earn its reset. |
| **Three separate facts, recorded separately**, because they were run |
| together once and the section contradicted itself. |
| @@ -1799,9 +1811,15 @@ kept rising throughout — and what did was the rendering stall: the tile |
| bound to exactly the receiver's own live, unmuted track (`meet.media()` |
| reports `agrees: true`), the decoder delivering, and the picture |
| stopped at `currentTime` 1.452 for as long as anything watched it. |
| -Rendered frames every 500 ms read `[25,26,26,26,26,26]` before the |
| -render watch and `[25,25,25,25,25,26]` after it: frozen for the three |
| -polls it takes to notice, then moving again. |
| +Rendered frames every 500 ms read `[25,26,26,26,26,26]` — stopped, and |
| +stopped for as long as anything watched — before the render watch, and |
| +`[25,25,25,25,25,26]` after it: frozen for the three polls it takes to |
| +notice, then moving again. A later run of the same scenario stopped |
| +dead at `[25,25,25,25,25,25]` and came back 21 → 26 across two |
| +successive intervals once the watch escalated past the stutter rule. |
| +Two of these paragraphs are recovery *after* a failure that is the |
| +browser's, not this app's; none of them is a claim that the rollback |
| +has stopped costing anything. |
| **If a deployment reports a face freezing after two people share at |
| once**, the order to check is: `POLITE_YIELD` against the pair's actual |