SIGN IN SIGN UP

fix(web): no timed rebuild runs under a selection

Selecting a line of an agent's output lost its highlight a few seconds later.
Not focus being stolen -- nothing on this page calls .focus() on a timer. The
mirror is replaced every 3s (pane_content -> replaceChildren) and the herd list
on every 2s `agents` snapshot (innerHTML), and both writes detach the very text
nodes the range's endpoints live in, so the browser has nothing left to anchor
it to. A selection could not survive three seconds, which is less than it takes
to reach the copy button on a phone.

One predicate, selectionInside, gates the three writes:

- mirrorTick, now the interval's whole body and named so the rule can be
  measured rather than read. It does not even SEND the read while a selection is
  held: that is a herdr call, an SSH round trip on a remote host, for content
  this tick has already decided it may not render.
- The pane_content handler, which catches what the tick's guard cannot -- a read
  already in flight when the drag started, and a manual refresh.
- render's list write, placed AFTER the name maps and the sibling strips, so
  only the list itself holds still while the rest keeps tracking the truth.

Nothing is queued: the tick repeats, so the skipped update lands on the next one
once the selection is released, and the pause explains itself because the
highlight is on screen. There is no honest alternative -- a range cannot be
re-anchored to nodes that no longer exist.

A caret is not a selection (isCollapsed). Every tap leaves a collapsed range
behind, and freezing on that would stop the mirror for good on the first touch,
which is worse than the bug being fixed.

tests/test_web_selection.py measures all of it, including the two edges that
pass either way and so would otherwise go unstated: a caret does not freeze the
mirror, and a selection in the header does not freeze the output. Neutering
selectionInside fails 4 of its 7 tests.
N
Nick007 committed
1a8286fd6462980d8d85eb35340adac48049e068
Parent: 41926e4