diff --git a/web/hwlab-cloud-web/src/composables/useTraceSubscription.ts b/web/hwlab-cloud-web/src/composables/useTraceSubscription.ts index 49c087e2..79af5121 100644 --- a/web/hwlab-cloud-web/src/composables/useTraceSubscription.ts +++ b/web/hwlab-cloud-web/src/composables/useTraceSubscription.ts @@ -447,7 +447,14 @@ function mergeTraceSnapshots(previous: TraceSnapshot | null, next: TraceSnapshot } function traceSnapshotWithTurnStatus(trace: TraceSnapshot, turn: TraceSnapshot): TraceSnapshot { - const timing = mergeTraceTimingProjection(trace, turn, { preserveVisibleTerminalDuration: traceTimingWasRunning(trace) && traceTimingIsTerminal(turn) }); + const turnTiming = traceTimingCandidate(turn); + const turnIsTerminal = traceTimingIsTerminal(turn) || isTerminalStatus(turn.status); + // Running card timing belongs to the turn status projection. Trace pages may + // hydrate older detail rows later; they must not move the visible running + // card's startedAt/lastEventAt source and create multi-second jumps. + const timing = !turnIsTerminal && turnTiming + ? turnTiming + : mergeTraceTimingProjection(trace, turn, { preserveVisibleTerminalDuration: traceTimingWasRunning(trace) && traceTimingIsTerminal(turn) }); return { ...trace, traceId: trace.traceId ?? turn.traceId,