7caf56f332
Found in a browser Live run on the rig: the run drew API, DB and Notify nodes from its inline rows; the 5 s pending-refresh re-read the tree through Replay before the site's cached-call telemetry (12 s) had reached central, swapped the graph wholesale, and the resolved DB node vanished (7 -> 6 steps) until a manual refresh. Polling had already stopped because nothing was Pending. MergeRefreshedGraph now unions the re-read rows into the run's known rows by EventId (fresh copy wins), stores the union back on _raw and rebuilds through FlowGraphBuilder, so a refresh only ever adds nodes. The union is exact: the inline rows are the same AuditEvent objects the site writer persists (FlowTraceCollector). Tests: new PendingRefresh_KeepsStepsTheLiveRunAlreadyHad_WhenReplayLagsBehindTelemetry (fails on the old code). Two existing fixtures were internally inconsistent and only passed under the old replace semantics: ParkedThenResolved built its Resolved outcome with the Parked raw rows, and OutboundOutcome minted fresh event/correlation ids per call, so no row could ever match across live and replay. Both now share rows per run. Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29