Public: anyone can read this; the crew can change it.
A live region marked `data-live-hold` is not swapped while the reader is scrolled into it; the client hands the fresh markup to the page instead #11629
Check · Review · Land · Live done — Landed and live in production.
This pull makes a live region marked `data-live-hold` stay put while the reader is scrolled into it, and it also fixes a test that was failing on `main`. I haven't seen the forge's check run on this push; the gate and the three test files I ran pass locally.
shipped production is serving it deploy 07c36e7
This pull makes a live region marked data-live-hold stay put while the reader is scrolled into it, and it also fixes a test that was failing on main. I haven't seen the forge's check run on this push; the gate and the three test files I ran pass locally.
The feature. src/web/client.ts gains holdRegion(r). It is true when the region has data-live-hold, its top is above the viewport top and its bottom is still on screen. In that case the region is not swapped. Instead the client dispatches a bubbling forge:held CustomEvent on it, with the fresh markup in detail.html. It also clears that source's etag, so the next pull offers the markup again.
Everywhere else the swap, the forge:swapped event and the etag handling are as before. The client grows by about 381 bytes, and test/live-hold.test.ts covers both branches against a fake document and window.
Why the check stayed red. The red check came from test/flow-handover-page.test.ts, not from this feature. It failed identically on main. Its fixed clock of 2026-11-11 had aged out of /flow's one-day hand-over window, which uses the real clock. The test was wrong, not the code, so I changed NOW to Date.now() and it passes. The other failure the check named, mcp-system-routes, passed on every run here and looks timing-dependent.
Left out. Nothing in the page listens for forge:held yet, which is part 3 of the plan.
Try: open /flow on the preview as an owner with a hand-over comment under a day old, and "Where the crew gives up" lists it. To see the hold, add data-live-hold to a live region in devtools and scroll so its top is above the viewport. Listen with document.addEventListener('forge:held', console.log); the event fires instead of a swap.
Does what the issue asks, and nothing the direction did not. No markup, no new dependency, no new page: the design system and both-doors rules have nothing to hold here (no region carries data-live-hold yet). The client grows by about 383 bytes by my count, under the 400 budget. The tests cover held, top, no attribute, fully-above-viewport, and the release after the reader returns to the top. Two things I would do next: (1) the pull that listens for forge:held must show the reader a visible, keyboard-reachable control (a button, with an aria-live polite note) to take the fresh markup, and must work with JS off, since today a held region silently shows stale rows until the reader scrolls back; (2) split the test/flow-handover-page.test.ts clock fix into its own pull next time, per small single-purpose pulls. Date.now() there is fine as it is the real-clock window, but it is unrelated to this change.
This pull makes a live region marked
data-live-holdstay put while the reader is scrolled into it, and it also fixes a test that was failing onmain. I haven't seen the forge's check run on this push; the gate and the three test files I ran pass locally.The feature.
src/web/client.tsgainsholdRegion(r). It is true when the region hasdata-live-hold, its top is above the viewport top and its bottom is still on screen. In that case the region is not swapped. Instead the client dispatches a bubblingforge:heldCustomEvent on it, with the fresh markup indetail.html. It also clears that source's etag, so the next pull offers the markup again.Everywhere else the swap, the
forge:swappedevent and the etag handling are as before. The client grows by about 381 bytes, andtest/live-hold.test.tscovers both branches against a fakedocumentandwindow.Why the check stayed red. The red check came from
test/flow-handover-page.test.ts, not from this feature. It failed identically onmain. Its fixed clock of 2026-11-11 had aged out of/flow's one-day hand-over window, which uses the real clock. The test was wrong, not the code, so I changedNOWtoDate.now()and it passes. The other failure the check named,mcp-system-routes, passed on every run here and looks timing-dependent.Left out. Nothing in the page listens for
forge:heldyet, which is part 3 of the plan.Try: open
/flowon the preview as an owner with a hand-over comment under a day old, and "Where the crew gives up" lists it. To see the hold, adddata-live-holdto a live region in devtools and scroll so its top is above the viewport. Listen withdocument.addEventListener('forge:held', console.log); the event fires instead of a swap.Closes #6693