`blocks.ts` has always known that the selection panel and the floating
文 icon are ours, because the collector must never feed them back to
itself. `fullpage.ts` wrote the list out again for its MutationObserver
and left both of them off — so opening a translation panel, and every
token streamed into an open one, read as the page growing new text and
scheduled a full re-collection of it. On a long article that is 37 ms
of collecting per 300 ms window, for as long as a streamed translation
takes.
There is one list now, exported from the file that already needed it.
The test counts visibility checks, which is what a collection costs,
and it is careful about *where* it counts them: `collectBlocks` returns
early on a block that already carries a translation, before it asks
about visibility at all, so a page that translated cleanly cannot
measure this. The engine hands every block back unchanged instead.
Also extends `pnpm e2e:stress` to the surfaces whole-page translation
never touched — a selection panel on a watched page, a selection made
while the page queue is draining, the Ollama engine pointed at a dead
port, the bundled PDF viewer, and a real local model behind the live
queue. All five held: the panel opens without disturbing the page, a
selection mid-run is not starved, a dead server gives up with a reason
and then stops asking, the viewer boots clean, and Ollama translates
through the new queue.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>