- Shipped
- September 7, 2026 at 5:21 PM UTC
- Author
- Kamo
- Commit
- 1a49eb6
A docked window crept left in 38px steps and then jumped back to the right edge, over and over, for as long as it was open. `rightEdgeReserve` accepts a scrollbar up to NEAR_EDGE_REACH in from the viewport edge, because the bars in this app sit behind the page's padding rather than flush to the glass. Every tool window's body is a marked scroller too — `.kamo-scroll`, the same class the page's panels carry, because it gets the same bar — and the right-most docked window's body sits six pixels in. Well inside the reach. So the measurement became a function of its own result. The dock read its own window's bar, reserved for it, moved the window left, read the bar at its new position, reserved more, moved again: 1435 -> 1386 -> 1348 -> 1310, at which point the gap passed the reach, the bar stopped counting, the reserve fell back to nothing and the window snapped to 1435 to start over. A period-four limit cycle. The two-pixel tolerance that preceded the reach had been rejecting these all along, which is why it appeared only now. The rule: a scroller inside anything the DOCK places is not the page's, whatever its coordinates say. Filtered at adoption rather than at measuring time — whether a scroller is the dock's own is a question about the tree, and the tree cannot change without a mutation bringing us back through that scan. Excluding them from the ResizeObserver is part of the same point: a window's own body resizing must not be a reason to re-pack the row it is in. All three surfaces, not just the window that was reported. The navigator carries the terminal switcher's `.kamo-scroll` and a hexhead is moved by the same engine, so either could close the same loop the day it grows a bar. The maximized tab strip needs no mention — it opts out of having a bar at all. Nor do popovers raised inside a window: they are absolutely positioned within the shell, and the two menus that really do portal to the body are MUI menus, which are deliberately not in the marker list. Verified in a real browser at 1440px, in both overlay and classic scrollbar modes, against /account's nesting: before, the window's right edge walks 1435 -> 1386 -> 1348 -> 1310 -> 1386 -> ...; after, it settles at 1386 on the first tick and stays. 1386 is 1440 - 5 - 49, so the grid's bar at x 1391..1423 is still cleared and the reserve this regressed is intact. The tests drive the real provider rather than a mock, and stub ResizeObserver because the adoption effect returns on its first line without one — which would have made all four pass for the wrong reason.