Record which inputs a run's caller passed, and mark defaults from it
`Run.passed` (migration d5a3c8e1f246) keeps the names the caller chose, so the run detail and the comparison table can mark a value as the flow's own again; rows from before it fall back to the names their params lack. Retries hand on their parent's list, imports record their entry's. Also: a cancel of a queued run no longer leaves its id in `_cancelled`, a linked comparison no longer crashes before the list loads, and the pre-commit failures are fixed (stale client, `text-[10px]`, worker formatting). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
This commit is contained in:
@@ -30,6 +30,7 @@ import {
|
||||
runQueryOptions,
|
||||
shortCommit,
|
||||
shortId,
|
||||
tookDefault,
|
||||
useCancelRun,
|
||||
useFlowInputs,
|
||||
useRetryRun,
|
||||
@@ -64,11 +65,15 @@ export function RunDetail({ id }: { id: string }) {
|
||||
...[...declared.keys()].map((name) => ({
|
||||
name,
|
||||
value: name in run.params ? run.params[name] : declared.get(name),
|
||||
fromFlow: !(name in run.params),
|
||||
fromFlow: tookDefault(run, name),
|
||||
})),
|
||||
...Object.keys(run.params)
|
||||
.filter((name) => !declared.has(name))
|
||||
.map((name) => ({ name, value: run.params[name], fromFlow: false })),
|
||||
.map((name) => ({
|
||||
name,
|
||||
value: run.params[name],
|
||||
fromFlow: tookDefault(run, name),
|
||||
})),
|
||||
]
|
||||
|
||||
return (
|
||||
@@ -246,7 +251,7 @@ export function Entry({
|
||||
<dt className={cn(LABEL, "flex items-baseline gap-1.5")}>
|
||||
{name}
|
||||
{note && (
|
||||
<span className="rounded-full border border-border px-1.5 text-[10px]">
|
||||
<span className="rounded-full border border-border px-1.5 text-xs">
|
||||
{note}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -62,6 +62,7 @@ import {
|
||||
STEP_AXIS,
|
||||
shortCommit,
|
||||
shortId,
|
||||
tookDefault,
|
||||
useFlowInputs,
|
||||
varyingKeys,
|
||||
} from "./queries"
|
||||
@@ -96,6 +97,8 @@ export function RunsScreen({
|
||||
|
||||
const runs: RunRow[] = data?.pages.flat() ?? []
|
||||
const selected = search.compare ? search.compare.split(",") : []
|
||||
// Only those the list has read: a linked comparison renders before it has.
|
||||
const picked = runs.filter((run) => selected.includes(run.id))
|
||||
|
||||
const put = (next: string[]) =>
|
||||
update({
|
||||
@@ -305,9 +308,7 @@ export function RunsScreen({
|
||||
{/* Below the chart, and only once there are two runs to hold apart.
|
||||
The table above keeps its height and the page scrolls instead:
|
||||
what differs is worth reading in full. */}
|
||||
{selected.length > 1 && (
|
||||
<ParamDiff rows={runs.filter((run) => selected.includes(run.id))} />
|
||||
)}
|
||||
{picked.length > 1 && <ParamDiff rows={picked} />}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
@@ -359,7 +360,7 @@ export function FlowRail({
|
||||
>
|
||||
<span className="min-w-0 flex-1 truncate">{label}</span>
|
||||
{note && (
|
||||
<span className="rounded-full border border-border px-1.5 text-[10px]">
|
||||
<span className="rounded-full border border-border px-1.5 text-xs">
|
||||
{note}
|
||||
</span>
|
||||
)}
|
||||
@@ -784,16 +785,22 @@ function ParamDiff({ rows }: { rows: RunRow[] }) {
|
||||
)}
|
||||
{varying.map((key) => (
|
||||
<TableCell key={key}>
|
||||
{key in run.params ? (
|
||||
<ParamValue value={run.params[key]} />
|
||||
) : declared.has(key) ? (
|
||||
// Not "empty": this run was never given the parameter, so
|
||||
// what it ran with is what the flow declares.
|
||||
{key in run.params || declared.has(key) ? (
|
||||
// Not "empty": a run never given the parameter ran with
|
||||
// what the flow declares, and says so.
|
||||
<span className="flex items-baseline gap-1.5">
|
||||
<ParamValue value={declared.get(key)} />
|
||||
<span className="rounded-full border border-border px-1.5 text-[10px] text-muted-foreground">
|
||||
default
|
||||
</span>
|
||||
<ParamValue
|
||||
value={
|
||||
key in run.params
|
||||
? run.params[key]
|
||||
: declared.get(key)
|
||||
}
|
||||
/>
|
||||
{tookDefault(run, key) && (
|
||||
<span className="rounded-full border border-border px-1.5 text-xs text-muted-foreground">
|
||||
default
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-muted-foreground text-xs">unset</span>
|
||||
|
||||
@@ -321,6 +321,17 @@ export function varyingKeys(runs: { params: Record<string, unknown> }[]) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a run took `name` from its flow rather than from its caller. A run
|
||||
* from before `passed` was recorded can only say so for a name its params lack.
|
||||
*/
|
||||
export function tookDefault(
|
||||
run: { params: Record<string, unknown>; passed?: string[] | null },
|
||||
name: string,
|
||||
): boolean {
|
||||
return run.passed ? !run.passed.includes(name) : !(name in run.params)
|
||||
}
|
||||
|
||||
/** A parameter value, as narrow as it can be written. */
|
||||
export function paramText(value: unknown): string {
|
||||
if (value === null || value === undefined) return "—"
|
||||
|
||||
Reference in New Issue
Block a user