50670863f40ee1e7a06795eccbec472a0363f27a
A group of adjacent tool calls was identified by its first call, and the list is keyed by that identity. But a run can gain members at *either* end -- a new call arriving beside it, or a page of history arriving in front of it -- so its first member is not a name, it is a description that changes. Every time it changed, the row was a different row as far as the list was concerned: the anchor went with it, and the transcript stepped under whoever was reading. Each call now carries the run it belongs to, decided once when it is folded in and never recomputed, and the row keys on that. A lone call that gains a neighbour becomes a group *without* changing identity, which the old key got wrong in the other direction too -- one row was replaced by another rather than updated. `joinPages` hands the arriving older calls the name of the run they are joining, rather than renaming that run after them. The obvious way round is the wrong one: the newer half is the part already on screen, so naming the joined run after the older half renames the row the reader is looking at, which is the whole failure this is meant to remove. Checked against the same twelve-`/tools 8` rig, whose page boundary falls inside the second group: every group still reads eight, so the grouping is unchanged -- what changed is that none of their identities move. Toward the standing rule for this screen, which is that it may only move when the reader is at the newest end and something new arrives.
Languages
Rust
54%
Kotlin
43.6%
Shell
2.4%