iris fe6a36bde4 Page back at all, and merge the run the boundary fell through
Two defects on the same path, the second found while trying to reproduce
the first. Both are invisible against a loopback server and both show up at
`--delay 150`, which is what a phone over the tunnel actually costs.

**A run of tool calls came back as two groups.** `joinPages` heals three
things across a page boundary -- a message cut in half, a call separated
from its result, and the *run* a group is named after -- but the third only
ran on the path where a split call had been found. A boundary landing
cleanly between two finished calls, which is most of them, went straight to
concatenation and left the older page's calls under the name they were
folded with. On screen, one run of twelve drawn as "Called 7 tools" and
"Called 5 tools", with the seam wherever the reader happened to have paged.
The two early returns were an optimisation on a list the size of one page,
and what they saved was the work.

**And nothing older loaded at all.** The history pager fires on the first
layout, before a single event has arrived: `moreHistory` starts true, so the
spinner is in the list, so `visibleItemsInfo` is not empty, and with no
units loaded the room ahead adds up to zero. It then asked for the events
`before = 0` -- the ones before the first one, which is none -- and an empty
page is precisely how this code is told it has reached the start of the
conversation. So `moreHistory` latched false, racing the opening page's own
write of true, and a session that lost the race stopped one page from its
newest end with no spinner and nothing on screen to say why. Guarded inside
`loadOlderPage`, because it is a fact about the question rather than about
who asked: the post-open fetch reaches it too, on the path where the opening
page failed and left `oldestSeq` unset.

Checked both ways round on the emulator, with the boundary placed on
purpose (the opening page is 80 events, so it is a matter of counting back
from the newest): 7 + 5 without the join fix, one group of 12 with it. And
the case the change had no reason to touch still holds -- a boundary that
*does* split a call, which is the path that always worked, and one through a
streamed reply, which `healSplitMessage` owns and this does not go near.
2026-08-31 22:56:23 -04:00
S
Description
No description provided
30 MiB
0 Stars 1 Watchers 0 Forks
Languages
Rust 53%
Kotlin 44.4%
Shell 2.6%