`_run_journal_live_snapshot` rebuilds the live UI state for an active run
by replaying the whole durable journal. On a long run (22.7k events /
15MB) that rebuild took ~4.4s per session load and blocked the HTTP
thread - the dominant cost of "switching to a session with a task
running takes forever". Four output-preserving fixes:
1. Locate the journal without parsing it (`find_run_file`) and derive the
durable summary from the single `read_run_events` parse instead of
parsing the file twice (`find_run_summary` + `read_run_events`). The
historical `find_run_summary` lookup is kept as the fallback when no
journal file exists on disk.
2. Skip `metering` rows in the projection loop (~60% of a long live
journal's bytes; nothing in the snapshot is built from them), while
preserving the last_ts watermark they carry.
3. Collect reasoning deltas into a list and materialize lazily instead of
`reasoning_text += chunk` (quadratic inside these closures: ~2.3s of
the replay on a 9.7k-chunk run).
4. Fold only a bounded tail of the reasoning transcript for the
interim-echo suffix check instead of `re.sub` over the whole growing
text (~1.5s over 100+ probes).
Measured on a 15MB / 22.7k-row live journal: 4.34s -> 0.49s (8.9x) with
byte-identical snapshot output (sha256 of the canonical JSON unchanged).
Related work: #7310 (slow /api/session under load), #7534 (incremental
journal read cache - complementary: this removes one of the two parses
entirely and fixes the replay-loop hotspots), #7273/#7291 (metering
write-side skip - the read-side loop skip here complements them for
legacy journals that still carry metering rows).