From 023e85bd634db6ce003f3a5ebe4628f8b93314da Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Sun, 26 Jul 2026 23:30:59 +0200 Subject: [PATCH] fix: open a pipeline step on its code, not its output (#10335) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: open a pipeline step on its code, not its output Clicking a script node in a pipeline replay landed on Output. The code is what the step is, and it is the thing a viewer is usually there to read, so open on it and put the Code toggle first. Recordings made before `codes` existed carry no source, and defaulting them to Code would open an empty pane saying nothing was captured, so the default falls back to Output when the step has no recorded source. The reset is keyed on the selected step, so a tab chosen by hand survives until another step is opened. Co-Authored-By: Claude Opus 5 (1M context) * refactor: depend the step-tab reset on the selected path alone untrack the codes lookup so the effect tracks only which step is selected. It could not loop either way — it never reads the tab it writes, and the toggle group's programmatic dispatch settles on an identical value — but the dependency set should say what the reset means: reset on a new step, not on a new recording object. Co-Authored-By: Claude Opus 5 (1M context) --------- Co-authored-by: Claude Opus 5 (1M context) --- .../recording/PipelineRecordingReplay.svelte | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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}