Two holes in revision 14, both found by review of this lane's own first
commit, and both would have been discovered during implementation at
much greater cost.
Q#LL7 --- the mode never reached the GPU. Section 4 resolves
ui.line-wrap into Viewport, which reaches the GRID renderer. The GPU is
not a grid consumer: it lays out locally, ignores CellDelta,
BufferSnapshot carries only CRDT bytes, and no InstanceMessage variant
expresses a wrap mode. So truncate would have changed the TUI and left
the GPU wrapping --- the two frontends still disagreeing, which is the
one thing this lane exists to fix. Q#LL5's "character wrap in both" was
equally unreachable: setting Wrap::Glyph at startup is not honoring a
mode that can change.
Specified as an additive variant at v22, appended after the current
final variant with the advertised baseline left at 20 --- the path
FontFacts took at v17 and the panel shapes at v21, and the baseline
constant's own doc reserves moving it for changes that cannot be
expressed additively. This one can.
It carries buffer_id, and is resent on attach, on config change, AND on
buffer switch. The third trigger is the one a FontFacts-shaped design
misses: font size is global, wrap mode is per buffer, so switching from
a truncate buffer to a wrap buffer changes the effective mode with no
config event at all. A design listening only to on_change is silently
wrong and passes every single-buffer test.
Q#LL8 --- the scroll indicator falsifies the locality claim. Revision
14 asserted every vertical consumer is local. format_scroll_indicator
is not: a one-line buffer wrapping to fifty screen rows has
total_lines == 1, so the first branch returns "All" while forty-nine
rows sit below the viewport. The indicator claims the whole buffer is
visible when almost none of it is.
The claim is narrowed rather than abandoned, because the distinction
that bounds the cost survives: a TOTAL is one number, lazily computed
and cached; a PREFIX-SUM INDEX is O(N) resident storage. Stage 3 needs
the first and still does not need the second. All, Top and Bot need no
aggregate at all --- each is a local predicate falling out of the
render walk --- so only NN% pays, which matters because the M1 gate
measures open time on a 100MB file.
Also fixes a notation hazard. Section 7 said pos_to_display returns
"the visual row", which reads as redefining row --- the exact thing
5b.5 forbids, stated two sections apart. Every wrap-point example is
now the explicit triple {row, sub_row, col}. Writing them out makes the
point visible: both coordinates at a soft break share the same row,
because a wrap does not cross a source line. That is the information a
redefinition would have destroyed, and the pair notation hid it.
Status returns to not-approved. Both questions change what gets built,
not how, so implementation waits on them.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai