988448664a
CancelRun goes through Runner.Transition → Runs.SetState, which was a bare UPDATE state=? with no completed_at write. The host-page runDuration helper treats nil CompletedAt as "still running", so a cancelled run kept ticking forever. MarkCompleted / MarkFailed / MarkDispatchFailed already stamp completed_at; SetState now does the same for any terminal target state, using COALESCE so we never clobber an already-set timestamp. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>