diff --git a/frontend/src/lib/components/recording/PipelineRecordingReplay.svelte b/frontend/src/lib/components/recording/PipelineRecordingReplay.svelte index 033ff211fe..49b3fbfbd4 100644 --- a/frontend/src/lib/components/recording/PipelineRecordingReplay.svelte +++ b/frontend/src/lib/components/recording/PipelineRecordingReplay.svelte @@ -261,12 +261,24 @@ return (shownStatuses[selection.path] ?? finalStatuses[selection.path])?.status }) - // Output (args/logs/result) vs the step's source code, for a runnable node. - let runnableTab = $state<'output' | 'code'>('output') + // The step's source code vs its output (args/logs/result), for a runnable node. + let runnableTab = $state<'output' | 'code'>('code') let selectedCode = $derived.by(() => { if (selection?.kind !== 'runnable') return undefined return recording.codes?.[selection.path] }) + // Land on the code, since that is what the step *is* — but fall back to Output + // when the recording carries none, so a recording made before `codes` existed + // does not open on an empty pane. Depends on the selected path alone: the + // lookup is untracked so a tab the viewer picked by hand survives until they + // move to another step, rather than resetting if the recording object changes. + $effect(() => { + const path = selection?.kind === 'runnable' ? selection.path : undefined + if (path === undefined) return + untrack(() => { + runnableTab = recording.codes?.[path] ? 'code' : 'output' + }) + }) // Recorded data-sample for a selected asset node (ducklake/datatable). let selectedAssetSample = $derived.by(() => { @@ -382,8 +394,8 @@ on:selected={(e) => (runnableTab = e.detail)} > {#snippet children({ item })} - + {/snippet}