PR #354 — transcript navigation

PR #354 (ts-mono, branch transcript-navigation), from METR/hawk#545.

❌ user-reported broken 🧪 agent-tested only ⌛ ready for Peter's retest ✅ Peter personally verified 🙈 resolved not-a-bug / declined / deferred
What the PR delivers
Charles round-2 items ✅

Source: dragonstyle's review comment 2026-07-06T15:10:31Z. Re-verified by Peter 2026-07-20 pre-push.

Two inline Charles comments re-checked, both still satisfied: getEventFocusUrl in shared url.ts since the original focus-page commit; FocusTabContext already refactored to the callback pattern.

Charles round-3 items (2026-07-21) ✅

Source: dragonstyle's CHANGES_REQUESTED review 2026-07-21T22:10Z ("this is looking so good! A couple more nits"). 2026-07-22: origin/main merged into the branch (140481c9; textual conflicts trivial; semantic risk of main's hidden-turn changes: see the hidden-turns section below). Fixes implemented and reviewed 2026-07-22 as commits db8f25ad / 652bd671 / d2df5cf3 / 1b70adbb (the 4th folds the utility-toggle parity fix together with the deep-link force-include for both ?event= surfaces — le.48; kept in this PR deliberately rather than split to a follow-up, to be named explicitly in the PR comment for Charles's re-review), unit-tested with red-first guards, Peter-verified per t.65–t.68 and le.48 (t.68 carries the standing qualifier "verified on synthetic data only" — see t.68).

Fable round-4 items (2026-07-22 review)

Source: dragonstyle's follow-up review (agent-generated, comment 5051900334 on PR #354) found the branch conflicting with main and a list of issues below. origin/main (chunked-log viewer #451) merged as c08fbb48 — one visible conflict resolved preserving both sides, one silently auto-merged import break caught by gates and fixed in the merge commit; eight fix commits appended, all four gates green (sole failure = known load-flake, 3× green isolated; a second load-flake in the logs-listing fetch engine documented the same way).

REPLIES:

Review verdict 2026-07-23: CLEAN, no must-fix (independent pass + grok concurrence on the two riskiest diffs). Red-first capability verified for every behavior fix; consolidation confirmed behavior-preserving except the one intended fix (ResultBody now suppresses chrome collapse while find is open, matching the transcript page — the divergence ruled a bug). Two informational notes: a negligible null-scroller expand micro-divergence in ResultBody (harmless, aligns with scout's existing semantics), and the small-fixes commit carries two untested low-risk touches (jumpToEnd scrollHeight target, document titles). Remaining e2e waits are all constants-verified justified-keeps, not polls.

Utility agents × turn navigation — context for the fourth commit

Context for Charles on commit 1b70adbb, the 4th append-only commit on the branch (on top of d2df5cf3), added after merging main's utility-agent classification (#425: "N utility agents hidden" header button) and solver-span keep (#443).

Mechanism. The utility-agent classifier only runs when the client builds a sample's timeline from raw events (classifyUtilityAgents, inside buildTimeline). Samples that ship a server-baked timeline skip it entirely — convertServerTimeline copies utility flags verbatim from the server payload, so a log baked without those flags renders with no "hidden" button and always will, regardless of client code; the audit log used for testing is one such log. Bringing the feature to those logs needs the Python timeline writer to add the same classification at write time; that's out of scope for this PR and tracked as a loose end (le.44).

The bug this commit fixes. The focus page and the h/l lane stepper hardcoded the utility toggle to off, while the transcript view honored the user's persisted toggle. Once main's utility classification made utility lanes selectable in the transcript, selecting one and pressing f (or opening its focus URL) landed on a blank focus page, and h/l in focus covered a different set of lanes than the transcript did. This commit makes focus and h/l read the same persisted toggle the transcript already uses, so a selected utility lane now renders its turn and the lane set matches everywhere. Red-first unit-tested through the real wrapUtilityEvents pipeline (pre-fix failures reproduced verbatim, e.g. lane count off by one; toggle-OFF assertions passed pre-fix, confirming no regression). Peter-verified 2026-07-22 in browser (t.68), on a timelines-stripped copy of an audit log (original left byte-identical, sha256-verified) — standing qualifier: verified on synthetic data only, since no real log in the corpus currently exercises this path (real logs with server-baked timelines never carry utility flags to begin with; see mechanism above). Mirror behavior confirmed: a selected utility lane's turn is reachable in focus view. Not verified/possible: stepping between same-named sibling utility wrappers from within focus view — that is the known lane-model follow-up (le.47), not a defect of this PR.

Deliberately not fixed in this PR:

Charles's "Fable" findings (2026-07-06T15:46:31Z)

Charles's second CHANGES_REQUESTED review relayed an 8-item agentic-review list. Verdicts with file:line evidence per item: #1–#7 fixed, #8 not reproducible.

Independent review findings (2026-07-20)

Two blind reviews (gpt-5.6-sol, grok-4.5) ran against tip c2ccb288 with the report withheld; every finding adversarially verified; only fixes for P1-2 and P1-5 shipped per Peter's ruling ("fixes are just a risk of new bugs").

Peter's verification record & retest counts
Loose ends for follow-up after the PR lands