A tool's start and end are two events folded into one row, and the fold
only ever *updated* an existing row -- so an end whose start was not in
the same fold changed nothing and vanished. Not a broken row: no row at
all, which is indistinguishable from a tool that never ran, and is what
Iris saw as gaps where she remembered work happening.
Paging made it routine. Each page was folded on its own and prepended, so
every seam split whatever spanned it: 30 tool ends in the first page of
this conversation, one of them already orphaned before a single scroll.
Two changes, because the two halves fail differently.
Pages are re-folded from the events they came from rather than folded
apart and stitched together. That needs the events kept beside the rows,
since folding is one-way. One pass over everything loaded, paid only when
somebody scrolls back, which is the moment they asked for it.
And an end with no start now creates a row instead of disappearing. Its
name is unknown from an end alone, so it says "tool" until the earlier
page arrives and replaces it -- a row that admits what it does not know
beats silence, because silence is a claim that nothing happened.
Verified across a real seam: scrolling back through the 80-event boundary
of an 864-event import is continuous, with no gaps where tool calls were.