On-device runs exposed three bugs the e2e suite could not (it never
feeds layout feedback, and runs headless without size events):
1. WrapIndex poisoning from zero-width shapes. The first frames are
built before the window size is known (px=0x0); the renderer shapes
the editor window at zero width, where every line wraps into many
visual lines. When that feedback arrives, applyWrapCounts writes the
inflated counts to the window's lines. Normally the app stays on
those lines and re-shapes them at a real width, which corrects the
counts before anyone notices. A restored scroll moves the viewport
away instead, so the poisoned counts persist and map the restored
scroll offset to the wrong line (2000 landed on line 11 of 200).
The frame now carries ViewportDegenerate (set at frame-build time,
since feedback delivery lags shaping by a frame), and the main loop
drops layout feedback for such frames.
2. Session saving suppressed forever after a successful restore.
saveSessionIfChanged suppresses saves while l.session is set, and
only abortRestore cleared it — the success path never did, so an
app restored from a session never persisted new state. The
snapshot has fully landed once the cursor/selection/find have
landed with the content and the armed scroll has landed (or there
was none); clear l.session at both points.
3. gofmt on restore_test.go (comment alignment).