Skip to content

Correct the live view reason rows and watchdog guidance - #704

Merged
robertjamesprior merged 6 commits into
mainfrom
hypeship/live-view-media-reason-bound
Oct 20, 2026
Merged

robertjamesprior merged 6 commits into
mainfrom
hypeship/live-view-media-reason-bound

Conversation

@robertjamesprior

@robertjamesprior robertjamesprior commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Three corrections to the live view embedding guidance, plus a pass over the prose that changed.

The media reason row. It said the bound expires if ICE never reached checking. Since kernel-images#417 the client keeps the media bound armed through connected, so it expires only if ICE never arrives at connected or completed — completed is the other way a healthy connect can land when gathering is already done. An embedder branching on reason would otherwise expect media to fire earlier than it does. This row is the one kernel/docs#698 carried, which this PR supersedes.

The example watchdog. It remounted 15s after mount. The client's connect bounds run in sequence — transport, then signaling, then media — and sum to 48s, so an embedder following the snippet tore the frame down before the client could report which stage stalled. The example now uses 60s, and the prose says why the timer needs room above the budget: it also covers loading the frame itself.

The transport and peer rows. A socket close at any point before the connect succeeds reports transport, not only one before signaling, and peer also covers ICE reaching failed or closed and the data channel closing before the connect. The retry advice under the example follows: remounting repeats a construction or offer throw, but it can fix an ICE failure, so that case is worth one retry.

The note claiming KERNEL_CONNECTION_TIMEOUT stops firing once negotiation begins is corrected the same way: the media bound stays armed past checking until ICE reaches connected or completed, so a connect stalling in between does report one. What never emits it is a viewer whose frames stop after it connected.

Paired with kernel-images#472, which serves the bounds with the page from the live view proxy's environment, so a region can retune them without a browser image release. The defaults stay at transport 15s, signaling 3s and media 30s. Merge order doesn't matter for the docs themselves, but the two describe the same client.

Docs only, prose and one snippet constant. I didn't run mint broken-links on this revision because mint isn't installed in this environment; the change touches no links and the check passed on the previous revision.


Note

Low Risk
Documentation-only changes to live view embedding guidance; no runtime or API behavior changes in this repo.

Overview
Updates live view iframe embedding docs so reason handling and watchdog timing match current client connect behavior.

The media timeout reason now states ICE must reach connected or completed within the bound (not merely checking), including peers that stall after checking. KERNEL_CONNECTION_TIMEOUT guidance is updated the same way: the media bound stays active until those states, and viewers that lose frames after a successful connect will not emit it.

The example remount watchdog increases from 15s to 50s, with new prose that sequential connect stages default to 48s total and embedders should allow extra time for iframe load and waking a sleeping browser.

Reviewed by Cursor Bugbot for commit 044c381. Bugbot is set up for automated code reviews on this repo. Configure here.


Note

Low Risk
Documentation-only updates to embedding guidance; no runtime or API behavior changes.

Overview
Updates live view embedding docs so they match current client connect behavior (post kernel-images#417).

The media timeout reason is corrected: the bound applies until ICE reaches connected or completed, not merely checking, so embedders branching on reason won't expect media too early.

The “viewer never starts” section adds that default stage timeouts sum to 48s (transport → signaling → media) and that remount timers must exceed that budget plus iframe load time. The sample watchdog timeout changes from 15s to 60s.

Guidance on KERNEL_CONNECTION_TIMEOUT is rewritten: the media bound clears at connected/completed (not when negotiation starts), so mid-connect stalls can still emit the event; viewers that fail after frames were playing will not.

Reviewed by Cursor Bugbot for commit cf3da30. Bugbot is set up for automated code reviews on this repo. Configure here.


Note

Low Risk
Documentation-only updates to live view embedding guidance; no runtime or API changes in this repo.

Overview
Aligns live view iframe embedding docs in browsers/live-view.mdx with current connect-stage behavior so embedders branch on reason and watchdog timing correctly.

The reason table is updated: transport covers socket closure anytime before connect succeeds; media fires when ICE never reaches connected or completed (not merely checking); peer also covers ICE failed/closed and early data-channel closure.

The “never starts” section adds that default stage bounds run transport → signaling → media and sum to 48s, so remount timers must exceed that plus iframe load. The sample watchdog changes from 15s to 60s. KERNEL_CONNECTION_TIMEOUT prose now matches the media bound (clears at connected/completed; no timeout after a successful connect). Remount guidance splits peer by cause—environment vs network—and limits blind retries accordingly.

Reviewed by Cursor Bugbot for commit 46f1d17. Bugbot is set up for automated code reviews on this repo. Configure here.

@mintlify

mintlify Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
Kernel 🟢 Ready View Preview Oct 20, 2026, 3:45 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

The snippet remounted 15s after mount. The client's connect bounds run in
sequence and sum to 23s, so an embedder following the example tore the frame
down before the client could report which stage stalled — including media,
the stage most likely to have stalled.

Also correct the note about KERNEL_CONNECTION_TIMEOUT never firing once
negotiation begins. The media bound stays armed past `checking` until ICE
reaches `connected`, so a connect that stalls in between does report one;
what never emits it is a viewer whose frames stop after it connected.

@Sayan- Sayan- left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overal looks good. needs a deslop to conform to docs language guidance

…ance

The example remounts at 35s, above the client's connect bounds, which run in
sequence (transport, signaling, media) and now sum to 28s after
kernel-images#472 settled the media bound at 10s. Below the budget the example
reproduces the bug this page was fixing: the embedder tears the frame down
before the client can name the stage that stalled.

The prose around it says what the timer has to clear and why, since the timer
also covers loading the frame and waking a sleeping browser. The timeout
warning names `completed` alongside `connected`, which is the other way the
media bound clears.

The `media` row now reads "connected or completed ... covers a peer that stalls
after checking", folded in from #698, which this supersedes.
…udget

The media bound stays at its interim ceiling. The stretch through ICE
`connected` is unmeasured in every region, so shortening the default is not
something the probe data supports yet; a region that has the timings lowers it
through the live view proxy's override instead.

With the defaults unchanged, the three bounds sum to 48s rather than 28s, so
the example timer moves to 50s to stay above the budget it has to outlast.

@masnwilliams masnwilliams left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. the media row and the timeout note now match the client: the bound stays armed until ICE reaches connected or completed, and the 48s total checks out against the 15/3/30 defaults. a few small notes inline, none blocking.

non-blocking follow-up, separate from this PR: the transport and peer rows still don't match how the client picks a reason. a socket close at any point before the connect succeeds reports transport, not only before signaling. ICE failed/closed or the data channel closing before connect falls through to peer. that makes the line 166 advice wrong for ICE failures, since remounting can fix a network-path failure. worth a separate pass.

Comment thread browsers/live-view.mdx Outdated
### Detecting a viewer that never starts

Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived:
Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived. The timer has to outlast the client's connect bounds, which run in sequence — transport, then signaling, then media — and sum to 48s by default. If you wait less than that, you'll tear the frame down before it can report a stage that stalled late. The timer also covers loading the frame, including waking a browser that has gone to sleep, so leave room above the budget when you set it:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the wake doesn't add time on top of the budget. the proxy wakes the browser before the socket opens, so that time is already inside the 15s transport bound. only loading the page itself is extra. maybe:

Suggested change
Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived. The timer has to outlast the client's connect bounds, which run in sequence — transport, then signaling, then media — and sum to 48s by default. If you wait less than that, you'll tear the frame down before it can report a stage that stalled late. The timer also covers loading the frame, including waking a browser that has gone to sleep, so leave room above the budget when you set it:
Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived. The timer has to outlast the client's connect bounds, which run in sequence — transport, then signaling, then media — and sum to 48s by default. If you wait less than that, you'll tear the frame down before it can report a stage that stalled late. The timer also covers loading the frame itself, so leave room above the budget when you set it:

Comment thread browsers/live-view.mdx Outdated
iframe.src = src;
arm();
}, 15000);
}, 50000);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 50s leaves 2s over a 48s budget, which is thin for "leave room above the budget", and once the bounds can be tuned per region the budget can grow past 48s. 60s seems safer and costs little, because FAILED/TIMEOUT already show the fallback right away and this timer only catches silent stalls.

Suggested change
}, 50000);
}, 60000);

Comment thread browsers/live-view.mdx Outdated
```

Do not gate on `KERNEL_CONNECTION_TIMEOUT` alone. The watchdog behind it is cleared once negotiation begins, so a connection that stalls after that point never emits it. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled.
Do not gate on `KERNEL_CONNECTION_TIMEOUT` alone. It only covers a connect that is still negotiating: the media bound clears once ICE reaches `connected` or `completed`, and a viewer whose frames stop after it connected never emits one. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the docs style guide asks for contractions.

Suggested change
Do not gate on `KERNEL_CONNECTION_TIMEOUT` alone. It only covers a connect that is still negotiating: the media bound clears once ICE reaches `connected` or `completed`, and a viewer whose frames stop after it connected never emits one. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled.
Don't gate on `KERNEL_CONNECTION_TIMEOUT` alone. It only covers a connect that is still negotiating: the media bound clears once ICE reaches `connected` or `completed`, and a viewer whose frames stop after it connected never emits one. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled.

The prose said the timer covers waking a browser. It doesn't: the proxy wakes the
browser before the socket opens, so that time is already inside the transport
bound, and only loading the page itself is extra.

The example timer moves to 60s. 50s left 2s over the 48s budget, which is thin
for "leave room above the budget", and a region that raises its bounds moves the
budget past 48s anyway. The earlier terminal events still show the fallback as
soon as they arrive, so this timer only catches a silent stall.

Also contracts "Do not" to "Don't", which the docs style guide asks for.
A socket close at any point before the connect succeeds reports `transport`, not
only one before signaling, and `peer` also covers ICE reaching `failed` or
`closed` and the data channel closing before the connect.

The retry advice follows: remounting repeats a construction or offer throw, but
it can fix an ICE failure, so that case is worth one retry.
@robertjamesprior robertjamesprior changed the title Correct the media stage bound to connected Correct the live view reason rows and watchdog guidance Oct 20, 2026
Comment thread browsers/live-view.mdx
### Detecting a viewer that never starts

Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived:
Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived. The timer has to outlast the client's connect bounds, which run in sequence — transport, then signaling, then media — and sum to 48s by default. If you wait less than that, you'll tear the frame down before it can report a stage that stalled late. The timer also covers loading the frame itself, so leave room above the budget when you set it:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should be encoding timeout values in our docs, esp since we may tune these dynamically, etc. I don't have a counter proposal, however, at this point.

@Sayan- Sayan- left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for iterating! No other blocks from me

@robertjamesprior
robertjamesprior merged commit 1ea676c into main Oct 20, 2026
3 checks passed
@robertjamesprior
robertjamesprior deleted the hypeship/live-view-media-reason-bound branch October 20, 2026 16:34
robertjamesprior added a commit to kernel/kernel-images that referenced this pull request Oct 20, 2026
## Summary

The per-stage connect bounds the live view client arms while connecting
are now served with the page instead of compiled into the bundle, so a
region can retune one without a browser image release. This follows
review feedback on the earlier revision of this branch, which shortened
the media bound in the client.

The bounds are read at load from
window.KERNEL_LIVE_VIEW_CONNECT_TIMEOUTS_MS, which the live-view proxy
injects ahead of the first script in the page from its own environment
(kernel/kernel#4889, kernel/infra#1693). A stage the proxy does not
name, or names with a value that is not a positive number of
milliseconds, keeps the default the image ships, so the client behaves
the same on a proxy that injects nothing.

The defaults stay transport 15s, signaling 3s and media 30s, a worst
case of 48s across the three, and a test pins them so a silent change
fails CI.

## Why the media default stays at 30s

The bound covers the connect through ICE `connected`, and that stretch
is unmeasured in every region: 44 of the 130 probe runs stopped at
`checking`, all 30 ap-southeast runs among them. The measured paths land
in 1-16ms direct and \~90ms relay-only, which is what made a shorter
default tempting, but an expired bound is terminal and the client does
not retry, so the default stays at the ceiling the data supports rather
than the shortest value that fits the measured regions. A region with
the timings lowers it through the override.

Transport stays at 15s: the live-view proxy can spend \~12s waking a
browser before the socket opens, so shortening it would report a slow
wake as dead.

## Testing

`bun test tests` in images/chromium-headful/client, 235 pass, 0 fail,
including cases for a partial override, values that are not positive
milliseconds, an unknown stage, and the shipped defaults being the
documented 15 / 3 / 30. `tsc --noEmit` clean.

## Related

browsers/live-view.mdx moves with this in kernel/docs#704: the example
watchdog goes from 15s to 50s, above the 48s budget, and the sentence
claiming KERNEL_CONNECTION_TIMEOUT stops firing once negotiation begins,
which describes the pre-kernel-images#417 client, is corrected.

This branch was successfully deployed

1 active deployment
staging — 46f1d173 Deployed Oct 20, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants