footprint-explainable-ui 0.28.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1984,13 +1984,14 @@ function StageDetailPanel({
1984
1984
  }
1985
1985
 
1986
1986
  // src/components/TimeTravelControls/TimeTravelControls.tsx
1987
- import { useState as useState6, useEffect as useEffect4, useRef as useRef4, useCallback as useCallback3 } from "react";
1988
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1987
+ import { useState as useState6, useEffect as useEffect4, useRef as useRef4, useCallback as useCallback3, useMemo as useMemo7 } from "react";
1988
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1989
1989
  function TimeTravelControls({
1990
1990
  snapshots,
1991
1991
  selectedIndex,
1992
1992
  onIndexChange,
1993
1993
  autoPlayable = true,
1994
+ tracing = null,
1994
1995
  size = "default",
1995
1996
  unstyled = false,
1996
1997
  className,
@@ -1999,10 +2000,41 @@ function TimeTravelControls({
1999
2000
  const [playing, setPlaying] = useState6(false);
2000
2001
  const playRef = useRef4(null);
2001
2002
  const total = snapshots.length;
2002
- const canPrev = selectedIndex > 0;
2003
- const canNext = selectedIndex < total - 1;
2003
+ const isTracing = !!tracing;
2004
+ const stopSet = useMemo7(
2005
+ () => tracing ? new Set(tracing.stopIndices) : null,
2006
+ [tracing]
2007
+ );
2008
+ const earlierStop = useMemo7(() => {
2009
+ if (!tracing) return null;
2010
+ const earlier = tracing.stopIndices.filter((i) => i < selectedIndex);
2011
+ return earlier.length > 0 ? earlier[earlier.length - 1] : null;
2012
+ }, [tracing, selectedIndex]);
2013
+ const laterStop = useMemo7(() => {
2014
+ if (!tracing) return null;
2015
+ return tracing.stopIndices.find((i) => i > selectedIndex) ?? null;
2016
+ }, [tracing, selectedIndex]);
2017
+ const forkPrompt = isTracing && (tracing.forkCount ?? 0) >= 2 && !!tracing.onForkPrompt;
2018
+ const canPrev = isTracing ? forkPrompt || earlierStop !== null : selectedIndex > 0;
2019
+ const canNext = isTracing ? laterStop !== null : selectedIndex < total - 1;
2020
+ const goPrev = useCallback3(() => {
2021
+ setPlaying(false);
2022
+ if (isTracing) {
2023
+ if (forkPrompt) {
2024
+ tracing.onForkPrompt();
2025
+ return;
2026
+ }
2027
+ if (earlierStop !== null) onIndexChange(earlierStop);
2028
+ } else if (selectedIndex > 0) onIndexChange(selectedIndex - 1);
2029
+ }, [isTracing, forkPrompt, tracing, earlierStop, selectedIndex, onIndexChange]);
2030
+ const goNext = useCallback3(() => {
2031
+ setPlaying(false);
2032
+ if (isTracing) {
2033
+ if (laterStop !== null) onIndexChange(laterStop);
2034
+ } else if (selectedIndex < total - 1) onIndexChange(selectedIndex + 1);
2035
+ }, [isTracing, laterStop, selectedIndex, total, onIndexChange]);
2004
2036
  useEffect4(() => {
2005
- if (!playing || !autoPlayable) return;
2037
+ if (!playing || !autoPlayable || isTracing) return;
2006
2038
  if (selectedIndex >= total - 1) {
2007
2039
  setPlaying(false);
2008
2040
  return;
@@ -2018,7 +2050,7 @@ function TimeTravelControls({
2018
2050
  return () => {
2019
2051
  if (playRef.current) clearTimeout(playRef.current);
2020
2052
  };
2021
- }, [playing, selectedIndex, snapshots, total, onIndexChange, autoPlayable]);
2053
+ }, [playing, selectedIndex, snapshots, total, onIndexChange, autoPlayable, isTracing]);
2022
2054
  const togglePlay = useCallback3(() => {
2023
2055
  if (playing) {
2024
2056
  setPlaying(false);
@@ -2031,20 +2063,22 @@ function TimeTravelControls({
2031
2063
  (e) => {
2032
2064
  if (e.key === "ArrowLeft" && canPrev && !playing) {
2033
2065
  e.preventDefault();
2034
- setPlaying(false);
2035
- onIndexChange(selectedIndex - 1);
2066
+ goPrev();
2036
2067
  } else if (e.key === "ArrowRight" && canNext && !playing) {
2037
2068
  e.preventDefault();
2038
- setPlaying(false);
2039
- onIndexChange(selectedIndex + 1);
2040
- } else if (e.key === " " && autoPlayable) {
2069
+ goNext();
2070
+ } else if (e.key === "Escape" && isTracing) {
2071
+ e.preventDefault();
2072
+ tracing.onExit();
2073
+ } else if (e.key === " " && autoPlayable && !isTracing) {
2041
2074
  e.preventDefault();
2042
2075
  togglePlay();
2043
2076
  }
2044
2077
  },
2045
- [canPrev, canNext, playing, selectedIndex, onIndexChange, autoPlayable, togglePlay]
2078
+ [canPrev, canNext, playing, goPrev, goNext, autoPlayable, togglePlay, isTracing, tracing]
2046
2079
  );
2047
2080
  const fs = fontSize[size];
2081
+ const tracingColor = "var(--fp-tracing, #0d9488)";
2048
2082
  if (unstyled) {
2049
2083
  return /* @__PURE__ */ jsxs9(
2050
2084
  "div",
@@ -2052,60 +2086,77 @@ function TimeTravelControls({
2052
2086
  className,
2053
2087
  style,
2054
2088
  "data-fp": "time-travel-controls",
2089
+ "data-tracing": isTracing || void 0,
2055
2090
  role: "toolbar",
2056
- "aria-label": "Time travel controls",
2091
+ "aria-label": isTracing ? `Tracing ${tracing.tracedKey}` : "Time travel controls",
2057
2092
  tabIndex: 0,
2058
2093
  onKeyDown: handleKeyDown,
2059
2094
  children: [
2095
+ isTracing && /* @__PURE__ */ jsxs9("span", { "data-fp": "tt-tracing-header", children: [
2096
+ "Tracing ",
2097
+ tracing.tracedKey,
2098
+ tracing.viaKey && /* @__PURE__ */ jsxs9(Fragment3, { children: [
2099
+ " ",
2100
+ "\u25B8 via ",
2101
+ tracing.viaKey,
2102
+ " ",
2103
+ /* @__PURE__ */ jsx10("button", { "data-fp": "tt-show-all", onClick: tracing.onShowAll, children: "show all" })
2104
+ ] }),
2105
+ " \xB7 ",
2106
+ "stop ",
2107
+ tracing.stopOrdinal,
2108
+ " of ",
2109
+ tracing.totalStops,
2110
+ /* @__PURE__ */ jsx10("button", { "data-fp": "tt-exit-tracing", onClick: tracing.onExit, "aria-label": "Exit tracing", children: "Done" })
2111
+ ] }),
2060
2112
  /* @__PURE__ */ jsx10(
2061
2113
  "button",
2062
2114
  {
2063
2115
  "data-fp": "tt-prev",
2064
2116
  disabled: !canPrev || playing,
2065
- onClick: () => {
2066
- setPlaying(false);
2067
- onIndexChange(selectedIndex - 1);
2068
- },
2069
- "aria-label": "Previous stage",
2070
- children: "Prev"
2117
+ onClick: goPrev,
2118
+ "aria-label": isTracing ? forkPrompt ? "Choose cause" : "Earlier cause" : "Previous stage",
2119
+ children: isTracing ? forkPrompt ? "Choose cause\u2026" : "Earlier cause" : "Prev"
2071
2120
  }
2072
2121
  ),
2073
- autoPlayable && /* @__PURE__ */ jsx10("button", { "data-fp": "tt-play", onClick: togglePlay, "aria-label": playing ? "Pause" : "Play", children: playing ? "Pause" : "Play" }),
2122
+ autoPlayable && !isTracing && /* @__PURE__ */ jsx10("button", { "data-fp": "tt-play", onClick: togglePlay, "aria-label": playing ? "Pause" : "Play", children: playing ? "Pause" : "Play" }),
2074
2123
  /* @__PURE__ */ jsx10(
2075
2124
  "button",
2076
2125
  {
2077
2126
  "data-fp": "tt-next",
2078
2127
  disabled: !canNext || playing,
2079
- onClick: () => {
2080
- setPlaying(false);
2081
- onIndexChange(selectedIndex + 1);
2082
- },
2083
- "aria-label": "Next stage",
2084
- children: "Next"
2128
+ onClick: goNext,
2129
+ "aria-label": isTracing ? "Toward result" : "Next stage",
2130
+ children: isTracing ? "Toward result" : "Next"
2085
2131
  }
2086
2132
  ),
2087
- /* @__PURE__ */ jsx10("div", { "data-fp": "tt-ticks", children: snapshots.map((snap, i) => /* @__PURE__ */ jsx10(
2088
- "button",
2089
- {
2090
- "data-fp": "tt-tick",
2091
- "data-active": i === selectedIndex,
2092
- "data-done": i < selectedIndex,
2093
- onClick: () => {
2094
- setPlaying(false);
2095
- onIndexChange(i);
2133
+ /* @__PURE__ */ jsx10("div", { "data-fp": "tt-ticks", children: snapshots.map((snap, i) => {
2134
+ const isStop = !stopSet || stopSet.has(i);
2135
+ return /* @__PURE__ */ jsx10(
2136
+ "button",
2137
+ {
2138
+ "data-fp": "tt-tick",
2139
+ "data-active": i === selectedIndex,
2140
+ "data-done": i < selectedIndex,
2141
+ "data-stop": isTracing ? isStop : void 0,
2142
+ disabled: isTracing && !isStop,
2143
+ onClick: () => {
2144
+ setPlaying(false);
2145
+ onIndexChange(i);
2146
+ },
2147
+ title: snap.stageLabel
2096
2148
  },
2097
- title: snap.stageLabel
2098
- },
2099
- i
2100
- )) })
2149
+ i
2150
+ );
2151
+ }) })
2101
2152
  ]
2102
2153
  }
2103
2154
  );
2104
2155
  }
2105
2156
  const btnStyle = (disabled) => ({
2106
2157
  background: theme.bgTertiary,
2107
- border: `1px solid ${theme.border}`,
2108
- color: disabled ? theme.textMuted : theme.textPrimary,
2158
+ border: `1px solid ${isTracing ? tracingColor : theme.border}`,
2159
+ color: disabled ? theme.textMuted : isTracing ? tracingColor : theme.textPrimary,
2109
2160
  borderRadius: "6px",
2110
2161
  padding: "4px 12px",
2111
2162
  fontSize: fs.body,
@@ -2121,7 +2172,7 @@ function TimeTravelControls({
2121
2172
  style: {
2122
2173
  padding: "6px 12px",
2123
2174
  background: theme.bgSecondary,
2124
- borderBottom: `1px solid ${theme.border}`,
2175
+ borderBottom: isTracing ? `2px solid ${tracingColor}` : `1px solid ${theme.border}`,
2125
2176
  display: "flex",
2126
2177
  alignItems: "center",
2127
2178
  gap: 6,
@@ -2129,25 +2180,86 @@ function TimeTravelControls({
2129
2180
  ...style
2130
2181
  },
2131
2182
  "data-fp": "time-travel-controls",
2183
+ "data-tracing": isTracing || void 0,
2132
2184
  role: "toolbar",
2133
- "aria-label": "Time travel controls",
2185
+ "aria-label": isTracing ? `Tracing ${tracing.tracedKey}` : "Time travel controls",
2134
2186
  tabIndex: 0,
2135
2187
  onKeyDown: handleKeyDown,
2136
2188
  children: [
2189
+ isTracing && /* @__PURE__ */ jsxs9(
2190
+ "span",
2191
+ {
2192
+ "data-fp": "tt-tracing-header",
2193
+ style: {
2194
+ display: "flex",
2195
+ alignItems: "center",
2196
+ gap: 6,
2197
+ flexShrink: 0,
2198
+ fontSize: fs.body
2199
+ },
2200
+ children: [
2201
+ /* @__PURE__ */ jsx10(
2202
+ "span",
2203
+ {
2204
+ style: {
2205
+ fontSize: 10,
2206
+ fontWeight: 700,
2207
+ letterSpacing: "0.06em",
2208
+ textTransform: "uppercase",
2209
+ color: "#fff",
2210
+ background: tracingColor,
2211
+ borderRadius: 4,
2212
+ padding: "2px 7px"
2213
+ },
2214
+ children: "Tracing"
2215
+ }
2216
+ ),
2217
+ /* @__PURE__ */ jsx10("span", { style: { fontFamily: "monospace", fontWeight: 600, color: tracingColor }, children: tracing.tracedKey }),
2218
+ tracing.viaKey && /* @__PURE__ */ jsxs9("span", { style: { color: theme.textMuted }, children: [
2219
+ "\u25B8 via",
2220
+ " ",
2221
+ /* @__PURE__ */ jsx10("span", { style: { fontFamily: "monospace", color: theme.textSecondary }, children: tracing.viaKey }),
2222
+ " ",
2223
+ /* @__PURE__ */ jsx10(
2224
+ "button",
2225
+ {
2226
+ "data-fp": "tt-show-all",
2227
+ onClick: tracing.onShowAll,
2228
+ style: {
2229
+ border: "none",
2230
+ background: "transparent",
2231
+ color: tracingColor,
2232
+ cursor: "pointer",
2233
+ fontSize: fs.body,
2234
+ textDecoration: "underline",
2235
+ padding: 0
2236
+ },
2237
+ children: "show all"
2238
+ }
2239
+ )
2240
+ ] }),
2241
+ /* @__PURE__ */ jsxs9("span", { style: { color: theme.textMuted }, children: [
2242
+ "\xB7 stop ",
2243
+ tracing.stopOrdinal,
2244
+ " of ",
2245
+ tracing.totalStops
2246
+ ] })
2247
+ ]
2248
+ }
2249
+ ),
2137
2250
  /* @__PURE__ */ jsx10(
2138
2251
  "button",
2139
2252
  {
2140
2253
  style: btnStyle(!canPrev || playing),
2141
2254
  disabled: !canPrev || playing,
2142
- onClick: () => {
2143
- setPlaying(false);
2144
- onIndexChange(selectedIndex - 1);
2145
- },
2146
- "aria-label": "Previous stage",
2147
- children: "\u25C0"
2255
+ onClick: goPrev,
2256
+ "aria-label": isTracing ? forkPrompt ? "Choose cause" : "Earlier cause" : "Previous stage",
2257
+ title: isTracing ? forkPrompt ? "This stop is a fork \u2014 choose which cause to follow" : "Earlier cause" : "Previous stage",
2258
+ "data-fp": "tt-prev",
2259
+ children: isTracing ? forkPrompt ? "\u2442 choose cause\u2026" : "\u25C0 earlier cause" : "\u25C0"
2148
2260
  }
2149
2261
  ),
2150
- autoPlayable && /* @__PURE__ */ jsx10(
2262
+ autoPlayable && !isTracing && /* @__PURE__ */ jsx10(
2151
2263
  "button",
2152
2264
  {
2153
2265
  onClick: togglePlay,
@@ -2175,12 +2287,11 @@ function TimeTravelControls({
2175
2287
  {
2176
2288
  style: btnStyle(!canNext || playing),
2177
2289
  disabled: !canNext || playing,
2178
- onClick: () => {
2179
- setPlaying(false);
2180
- onIndexChange(selectedIndex + 1);
2181
- },
2182
- "aria-label": "Next stage",
2183
- children: "\u25B6"
2290
+ onClick: goNext,
2291
+ "aria-label": isTracing ? "Toward result" : "Next stage",
2292
+ title: isTracing ? "Toward result" : "Next stage",
2293
+ "data-fp": "tt-next",
2294
+ children: isTracing ? "toward result \u25B6" : "\u25B6"
2184
2295
  }
2185
2296
  ),
2186
2297
  /* @__PURE__ */ jsx10(
@@ -2196,6 +2307,8 @@ function TimeTravelControls({
2196
2307
  children: snapshots.map((snap, i) => {
2197
2308
  const isActive = i === selectedIndex;
2198
2309
  const isDone = i < selectedIndex;
2310
+ const isStop = !stopSet || stopSet.has(i);
2311
+ const unlandable = isTracing && !isStop;
2199
2312
  return /* @__PURE__ */ jsx10(
2200
2313
  "button",
2201
2314
  {
@@ -2203,15 +2316,19 @@ function TimeTravelControls({
2203
2316
  setPlaying(false);
2204
2317
  onIndexChange(i);
2205
2318
  },
2206
- title: snap.stageLabel,
2319
+ disabled: unlandable,
2320
+ title: unlandable ? `${snap.stageLabel} (not part of this trace)` : snap.stageLabel,
2321
+ "data-fp": "tt-tick",
2322
+ "data-stop": isTracing ? isStop : void 0,
2323
+ "data-active": isActive || void 0,
2207
2324
  style: {
2208
2325
  flex: 1,
2209
- height: isActive ? 14 : 8,
2326
+ height: isActive ? 14 : unlandable ? 4 : 8,
2210
2327
  borderRadius: 3,
2211
2328
  border: "none",
2212
- cursor: "pointer",
2213
- background: isActive ? theme.primary : isDone ? theme.success : theme.bgTertiary,
2214
- opacity: isDone || isActive ? 1 : 0.4,
2329
+ cursor: unlandable ? "default" : "pointer",
2330
+ background: isTracing ? isActive ? tracingColor : isStop ? "color-mix(in srgb, " + tracingColor + " 55%, transparent)" : theme.bgTertiary : isActive ? theme.primary : isDone ? theme.success : theme.bgTertiary,
2331
+ opacity: unlandable ? 0.3 : isTracing || isDone || isActive ? 1 : 0.4,
2215
2332
  transition: "all 0.15s ease"
2216
2333
  }
2217
2334
  },
@@ -2219,6 +2336,16 @@ function TimeTravelControls({
2219
2336
  );
2220
2337
  })
2221
2338
  }
2339
+ ),
2340
+ isTracing && /* @__PURE__ */ jsx10(
2341
+ "button",
2342
+ {
2343
+ "data-fp": "tt-exit-tracing",
2344
+ onClick: tracing.onExit,
2345
+ "aria-label": "Exit tracing",
2346
+ style: { ...btnStyle(false), background: "transparent" },
2347
+ children: "Done \u2715"
2348
+ }
2222
2349
  )
2223
2350
  ]
2224
2351
  }
@@ -2226,7 +2353,7 @@ function TimeTravelControls({
2226
2353
  }
2227
2354
 
2228
2355
  // src/components/ExplainableShell/ExplainableShell.tsx
2229
- import { memo as memo8, useState as useState14, useCallback as useCallback8, useMemo as useMemo12, useRef as useRef9, useEffect as useEffect11 } from "react";
2356
+ import { memo as memo9, useState as useState15, useCallback as useCallback8, useMemo as useMemo14, useRef as useRef9, useEffect as useEffect11 } from "react";
2230
2357
 
2231
2358
  // src/components/ExplainableShell/_internal/dataTrace.ts
2232
2359
  function readsByStep(tree) {
@@ -2285,9 +2412,651 @@ function buildDataTrace(commitLog, executionTree, targetRuntimeStageId, maxDepth
2285
2412
  queue.push([writerIdx, depth + 1, key]);
2286
2413
  }
2287
2414
  }
2288
- }
2289
- return { frames, readsAvailable };
2290
- }
2415
+ }
2416
+ return { frames, readsAvailable };
2417
+ }
2418
+
2419
+ // src/components/ExplainableShell/_internal/traceWalk.ts
2420
+ var DEFAULT_MAX_DEPTH = 10;
2421
+ var DEFAULT_MAX_FRAMES = 50;
2422
+ function buildTraceWalk(commitLog, executionTree, key, opts) {
2423
+ const log = commitLog ?? [];
2424
+ const cutoff = opts?.beforeCommitIdx ?? log.length;
2425
+ const maxDepth = opts?.maxDepth ?? DEFAULT_MAX_DEPTH;
2426
+ const maxFrames = opts?.maxFrames ?? DEFAULT_MAX_FRAMES;
2427
+ const writerOf = (k, beforeIdx) => {
2428
+ for (let i = Math.min(beforeIdx, log.length) - 1; i >= 0; i--) {
2429
+ if (log[i].trace.some((t) => t.path === k)) return i;
2430
+ }
2431
+ return -1;
2432
+ };
2433
+ const anchorIdx = writerOf(key, cutoff);
2434
+ if (anchorIdx < 0) {
2435
+ const firstEver = log.findIndex((c) => c.trace.some((t) => t.path === key));
2436
+ const missing = firstEver < 0 ? { reason: "never-written" } : {
2437
+ reason: "not-yet-written",
2438
+ firstWriteCommitIdx: firstEver,
2439
+ firstWriterRuntimeStageId: log[firstEver].runtimeStageId,
2440
+ firstWriterStageName: log[firstEver].stage
2441
+ };
2442
+ return { key, stops: [], missing, inputTermini: [], readsAvailable: true, truncated: false };
2443
+ }
2444
+ const slice = buildDataTrace(
2445
+ log.slice(0, anchorIdx + 1),
2446
+ executionTree,
2447
+ log[anchorIdx].runtimeStageId,
2448
+ maxDepth,
2449
+ maxFrames + 1
2450
+ );
2451
+ const truncated = slice.frames.length > maxFrames;
2452
+ const frames = truncated ? slice.frames.slice(0, maxFrames) : slice.frames;
2453
+ const idxOf = /* @__PURE__ */ new Map();
2454
+ for (let i = 0; i < log.length; i++) idxOf.set(log[i].runtimeStageId, i);
2455
+ const readsOf = readKeysByStep(executionTree);
2456
+ const inputTermini = [];
2457
+ const terminiSeen = /* @__PURE__ */ new Set();
2458
+ const stops = frames.map((f) => {
2459
+ const commitIdx = idxOf.get(f.runtimeStageId) ?? -1;
2460
+ const ingredients = (readsOf.get(f.runtimeStageId) ?? []).map((k) => {
2461
+ const w = writerOf(k, commitIdx);
2462
+ if (w < 0 && !terminiSeen.has(k)) {
2463
+ terminiSeen.add(k);
2464
+ inputTermini.push(k);
2465
+ }
2466
+ return {
2467
+ key: k,
2468
+ writerRuntimeStageId: w >= 0 ? log[w].runtimeStageId : null,
2469
+ writerStageName: w >= 0 ? log[w].stage : null,
2470
+ writerCommitIdx: w >= 0 ? w : null
2471
+ };
2472
+ });
2473
+ return {
2474
+ runtimeStageId: f.runtimeStageId,
2475
+ stageId: f.stageId,
2476
+ stageName: f.stageName,
2477
+ commitIdx,
2478
+ contributedKeys: [],
2479
+ keysWritten: f.keysWritten,
2480
+ ingredients,
2481
+ depth: f.depth,
2482
+ loopPass: 0
2483
+ };
2484
+ });
2485
+ const stopById = new Map(stops.map((s) => [s.runtimeStageId, s]));
2486
+ const contributed = /* @__PURE__ */ new Map();
2487
+ contributed.set(log[anchorIdx].runtimeStageId, /* @__PURE__ */ new Set([key]));
2488
+ for (const s of stops) {
2489
+ for (const ing of s.ingredients) {
2490
+ if (!ing.writerRuntimeStageId || !stopById.has(ing.writerRuntimeStageId)) continue;
2491
+ const set = contributed.get(ing.writerRuntimeStageId) ?? /* @__PURE__ */ new Set();
2492
+ set.add(ing.key);
2493
+ contributed.set(ing.writerRuntimeStageId, set);
2494
+ }
2495
+ }
2496
+ for (const s of stops) s.contributedKeys = [...contributed.get(s.runtimeStageId) ?? []];
2497
+ stops.sort((a, b) => b.commitIdx - a.commitIdx);
2498
+ const byStagePart = /* @__PURE__ */ new Map();
2499
+ for (const s of stops) {
2500
+ const part = s.runtimeStageId.split("#")[0];
2501
+ const arr = byStagePart.get(part) ?? [];
2502
+ arr.push(s);
2503
+ byStagePart.set(part, arr);
2504
+ }
2505
+ for (const arr of byStagePart.values()) {
2506
+ if (arr.length < 2) continue;
2507
+ for (let i = 0; i < arr.length; i++) arr[i].loopPass = arr.length - i;
2508
+ }
2509
+ return { key, stops, missing: null, inputTermini, readsAvailable: slice.readsAvailable, truncated };
2510
+ }
2511
+ function readKeysByStep(tree) {
2512
+ const byStep = /* @__PURE__ */ new Map();
2513
+ const root = tree;
2514
+ if (!root) return byStep;
2515
+ const visited = /* @__PURE__ */ new Set();
2516
+ const stack = [root];
2517
+ while (stack.length > 0) {
2518
+ const node = stack.pop();
2519
+ if (visited.has(node)) continue;
2520
+ visited.add(node);
2521
+ if (node.runtimeStageId && node.stageReads) {
2522
+ const keys = Object.keys(node.stageReads);
2523
+ if (keys.length > 0) byStep.set(node.runtimeStageId, keys);
2524
+ }
2525
+ if (node.next) stack.push(node.next);
2526
+ if (node.children) for (const c of node.children) stack.push(c);
2527
+ }
2528
+ return byStep;
2529
+ }
2530
+ function formatTraceWalk(walk, stepNumberOf) {
2531
+ const lines = [];
2532
+ if (walk.missing) {
2533
+ if (walk.missing.reason === "never-written") {
2534
+ lines.push(
2535
+ `\`${walk.key}\` was never written in this run \u2014 it arrived with the run's inputs.`
2536
+ );
2537
+ } else {
2538
+ const at = walk.missing.firstWriterRuntimeStageId ? stepNumberOf(walk.missing.firstWriterRuntimeStageId) : null;
2539
+ lines.push(
2540
+ `\`${walk.key}\` has not been written yet at this moment \u2014 its first write happens later` + (walk.missing.firstWriterStageName ? `, at ${walk.missing.firstWriterStageName}${at ? ` (step ${at})` : ""}.` : ".")
2541
+ );
2542
+ }
2543
+ return lines.join("\n");
2544
+ }
2545
+ lines.push(`Tracing \`${walk.key}\` \u2014 ${walk.stops.length} stops, newest first.`);
2546
+ walk.stops.forEach((stop, i) => {
2547
+ const step = stepNumberOf(stop.runtimeStageId);
2548
+ const pass = stop.loopPass > 0 ? ` (pass ${stop.loopPass})` : "";
2549
+ const made = stop.ingredients.length > 0 ? ` \xB7 made from: ${stop.ingredients.map(
2550
+ (ing) => ing.writerRuntimeStageId ? `${ing.key} (\u2190 ${ing.writerStageName}${stepNumberOf(ing.writerRuntimeStageId) ? `, step ${stepNumberOf(ing.writerRuntimeStageId)}` : ""})` : `${ing.key} (run input \u2014 never written)`
2551
+ ).join(", ")}` : walk.readsAvailable ? " \xB7 reads nothing \u2014 origin" : "";
2552
+ lines.push(
2553
+ `stop ${i + 1}/${walk.stops.length} \xB7 ${step ? `step ${step} \xB7 ` : ""}${stop.stageName}${pass} wrote \`${stop.contributedKeys.join("`, `")}\`${made}`
2554
+ );
2555
+ });
2556
+ if (walk.inputTermini.length > 0) {
2557
+ lines.push(`run inputs (never written): ${walk.inputTermini.join(", ")}`);
2558
+ }
2559
+ if (!walk.readsAvailable) {
2560
+ lines.push("\u26A0 reads were not recorded \u2014 dependencies are unknowable, not absent.");
2561
+ }
2562
+ if (walk.truncated) {
2563
+ lines.push("\u26A0 walk truncated at its frame budget \u2014 the earliest stop may not be the true origin.");
2564
+ }
2565
+ return lines.join("\n");
2566
+ }
2567
+
2568
+ // src/components/DataTracePanel/TraceWalkCard.tsx
2569
+ import { memo, useMemo as useMemo8, useState as useState7 } from "react";
2570
+ import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2571
+ var CHIP_COLORS = ["#0d9488", "#d97706", "#7c3aed", "#e11d48"];
2572
+ var TraceWalkCard = memo(function TraceWalkCard2({
2573
+ walk,
2574
+ cursorRuntimeStageId,
2575
+ viaKey,
2576
+ stepNumberOf,
2577
+ previewValueOf,
2578
+ onFollowIngredient,
2579
+ onJumpToStop,
2580
+ onShowAll,
2581
+ onExit,
2582
+ forkChooserOpen,
2583
+ onContinueTimeOrder,
2584
+ canContinueTimeOrder = true
2585
+ }) {
2586
+ const [copied, setCopied] = useState7(false);
2587
+ const accent = "var(--fp-accent, #6366f1)";
2588
+ const tracingColor = "var(--fp-tracing, #0d9488)";
2589
+ const currentIdx = useMemo8(() => {
2590
+ if (!cursorRuntimeStageId) return 0;
2591
+ const i = walk.stops.findIndex((s) => s.runtimeStageId === cursorRuntimeStageId);
2592
+ return i >= 0 ? i : 0;
2593
+ }, [walk, cursorRuntimeStageId]);
2594
+ const current = walk.stops[currentIdx];
2595
+ const followableCount = current ? current.ingredients.filter((ing) => ing.writerRuntimeStageId !== null).length : 0;
2596
+ const chooserVisible = !!forkChooserOpen && followableCount >= 2;
2597
+ const copyStory = () => {
2598
+ const text = formatTraceWalk(walk, stepNumberOf);
2599
+ void navigator.clipboard?.writeText(text).then(() => {
2600
+ setCopied(true);
2601
+ setTimeout(() => setCopied(false), 1600);
2602
+ });
2603
+ };
2604
+ if (walk.missing) {
2605
+ return /* @__PURE__ */ jsxs10("div", { "data-fp": "trace-walk-card", "data-missing": walk.missing.reason, style: { padding: "14px", fontSize: 13, lineHeight: 1.55 }, children: [
2606
+ /* @__PURE__ */ jsx11(CardHeader, { label: `Why this value \u2014 \`${walk.key}\``, onExit }),
2607
+ /* @__PURE__ */ jsx11("div", { style: { color: theme.textPrimary, marginTop: 8 }, children: walk.missing.reason === "never-written" ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
2608
+ /* @__PURE__ */ jsx11("code", { style: { color: accent }, children: walk.key }),
2609
+ " was ",
2610
+ /* @__PURE__ */ jsx11("b", { children: "never written in this run" }),
2611
+ " \u2014 it arrived with the run's inputs."
2612
+ ] }) : /* @__PURE__ */ jsxs10(Fragment4, { children: [
2613
+ /* @__PURE__ */ jsx11("code", { style: { color: accent }, children: walk.key }),
2614
+ " has ",
2615
+ /* @__PURE__ */ jsx11("b", { children: "not been written yet at this moment" }),
2616
+ " \u2014 its first write happens later",
2617
+ walk.missing.firstWriterStageName && /* @__PURE__ */ jsxs10(Fragment4, { children: [
2618
+ ", at ",
2619
+ /* @__PURE__ */ jsx11("b", { children: walk.missing.firstWriterStageName }),
2620
+ walk.missing.firstWriterRuntimeStageId && stepNumberOf(walk.missing.firstWriterRuntimeStageId) && /* @__PURE__ */ jsxs10(Fragment4, { children: [
2621
+ " (step ",
2622
+ stepNumberOf(walk.missing.firstWriterRuntimeStageId),
2623
+ ")"
2624
+ ] })
2625
+ ] }),
2626
+ "."
2627
+ ] }) })
2628
+ ] });
2629
+ }
2630
+ if (!current) return null;
2631
+ const step = stepNumberOf(current.runtimeStageId);
2632
+ const preview = previewValueOf ? previewValue(previewValueOf(current.contributedKeys[0] ?? walk.key)) : null;
2633
+ return /* @__PURE__ */ jsxs10("div", { "data-fp": "trace-walk-card", style: { padding: "10px 14px 14px", fontSize: 13, lineHeight: 1.5 }, children: [
2634
+ /* @__PURE__ */ jsx11(
2635
+ CardHeader,
2636
+ {
2637
+ label: `Why this value \u2014 stop ${currentIdx + 1} of ${walk.stops.length}`,
2638
+ onExit
2639
+ }
2640
+ ),
2641
+ viaKey && /* @__PURE__ */ jsxs10("div", { "data-fp": "twc-breadcrumb", style: { fontSize: 11, color: theme.textMuted, marginTop: 4 }, children: [
2642
+ /* @__PURE__ */ jsx11("code", { style: { color: accent }, children: walk.key }),
2643
+ " \u25B8 via ",
2644
+ /* @__PURE__ */ jsx11("code", { children: viaKey }),
2645
+ onShowAll && /* @__PURE__ */ jsxs10(Fragment4, { children: [
2646
+ " \xB7 ",
2647
+ /* @__PURE__ */ jsx11(
2648
+ "button",
2649
+ {
2650
+ onClick: onShowAll,
2651
+ style: { border: "none", background: "transparent", color: accent, cursor: "pointer", fontSize: 11, textDecoration: "underline", padding: 0 },
2652
+ children: "show all ingredients"
2653
+ }
2654
+ )
2655
+ ] })
2656
+ ] }),
2657
+ /* @__PURE__ */ jsxs10("div", { "data-fp": "twc-stop-headline", style: { marginTop: 10, fontWeight: 600, color: theme.textPrimary }, children: [
2658
+ step && /* @__PURE__ */ jsxs10("span", { style: { color: theme.textMuted, fontWeight: 500 }, children: [
2659
+ "Step ",
2660
+ step,
2661
+ " \xB7 "
2662
+ ] }),
2663
+ current.stageName,
2664
+ current.loopPass > 0 && /* @__PURE__ */ jsxs10("span", { style: { color: theme.textMuted, fontWeight: 500 }, children: [
2665
+ " (pass ",
2666
+ current.loopPass,
2667
+ ")"
2668
+ ] })
2669
+ ] }),
2670
+ /* @__PURE__ */ jsxs10("div", { style: { marginTop: 2, color: theme.textSecondary }, children: [
2671
+ "wrote",
2672
+ " ",
2673
+ current.contributedKeys.map((k, i) => /* @__PURE__ */ jsxs10("code", { style: { color: accent }, children: [
2674
+ i > 0 && ", ",
2675
+ k
2676
+ ] }, k)),
2677
+ preview !== null && /* @__PURE__ */ jsxs10("span", { style: { color: theme.textMuted }, children: [
2678
+ " = ",
2679
+ preview
2680
+ ] })
2681
+ ] }),
2682
+ chooserVisible && /* @__PURE__ */ jsxs10(
2683
+ "div",
2684
+ {
2685
+ "data-fp": "twc-fork-chooser",
2686
+ style: {
2687
+ marginTop: 10,
2688
+ padding: "10px 12px",
2689
+ border: `1.5px solid ${tracingColor}`,
2690
+ borderRadius: 8,
2691
+ background: `color-mix(in srgb, ${tracingColor} 8%, transparent)`
2692
+ },
2693
+ children: [
2694
+ /* @__PURE__ */ jsxs10("div", { style: { fontWeight: 600, fontSize: 12, color: theme.textPrimary }, children: [
2695
+ "This value was made from ",
2696
+ current.ingredients.length,
2697
+ " ingredients \u2014 which one should the walk follow?"
2698
+ ] }),
2699
+ /* @__PURE__ */ jsx11("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, marginTop: 8 }, children: current.ingredients.map((ing, i) => /* @__PURE__ */ jsx11(
2700
+ IngredientChip,
2701
+ {
2702
+ ing,
2703
+ color: i < CHIP_COLORS.length ? CHIP_COLORS[i] : theme.textMuted,
2704
+ step: ing.writerRuntimeStageId ? stepNumberOf(ing.writerRuntimeStageId) : null,
2705
+ onFollow: onFollowIngredient
2706
+ },
2707
+ ing.key
2708
+ )) }),
2709
+ /* @__PURE__ */ jsx11(
2710
+ "button",
2711
+ {
2712
+ "data-fp": "twc-continue-time",
2713
+ onClick: canContinueTimeOrder ? onContinueTimeOrder : void 0,
2714
+ disabled: !canContinueTimeOrder,
2715
+ title: canContinueTimeOrder ? void 0 : "This is the walk's earliest stop \u2014 there is nothing earlier to visit",
2716
+ style: {
2717
+ display: "block",
2718
+ width: "100%",
2719
+ marginTop: 8,
2720
+ border: `1px solid ${theme.border}`,
2721
+ background: theme.bgTertiary,
2722
+ color: theme.textPrimary,
2723
+ borderRadius: 6,
2724
+ padding: "5px 10px",
2725
+ fontSize: 11,
2726
+ fontWeight: 600,
2727
+ cursor: "pointer"
2728
+ },
2729
+ children: "visit all, oldest cause last (time order)"
2730
+ }
2731
+ )
2732
+ ]
2733
+ }
2734
+ ),
2735
+ /* @__PURE__ */ jsx11("div", { style: { marginTop: 10 }, children: chooserVisible ? null : current.ingredients.length > 0 ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
2736
+ /* @__PURE__ */ jsxs10("div", { style: { fontSize: 11, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.5px", fontWeight: 600 }, children: [
2737
+ "Made from ",
2738
+ current.ingredients.length,
2739
+ " ingredient",
2740
+ current.ingredients.length > 1 ? "s" : ""
2741
+ ] }),
2742
+ /* @__PURE__ */ jsx11("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, marginTop: 6 }, children: current.ingredients.map((ing, i) => /* @__PURE__ */ jsx11(
2743
+ IngredientChip,
2744
+ {
2745
+ ing,
2746
+ color: i < CHIP_COLORS.length ? CHIP_COLORS[i] : theme.textMuted,
2747
+ step: ing.writerRuntimeStageId ? stepNumberOf(ing.writerRuntimeStageId) : null,
2748
+ onFollow: onFollowIngredient
2749
+ },
2750
+ ing.key
2751
+ )) })
2752
+ ] }) : walk.readsAvailable ? /* @__PURE__ */ jsx11("div", { "data-fp": "twc-origin", style: { fontSize: 12, color: theme.textMuted, fontStyle: "italic" }, children: "reads nothing \u2014 this is an origin." }) : /* @__PURE__ */ jsx11("div", { "data-fp": "twc-unknowable", style: { fontSize: 12, color: theme.textMuted, fontStyle: "italic" }, children: "\u26A0 reads were not recorded \u2014 ingredients are unknowable, not absent." }) }),
2753
+ /* @__PURE__ */ jsxs10("div", { style: { marginTop: 14 }, children: [
2754
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 11, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.5px", fontWeight: 600, marginBottom: 4 }, children: "The story, newest first" }),
2755
+ walk.stops.map((s, i) => {
2756
+ const isCurrent = i === currentIdx;
2757
+ return /* @__PURE__ */ jsxs10(
2758
+ "button",
2759
+ {
2760
+ "data-fp": "twc-itinerary-row",
2761
+ "data-current": isCurrent || void 0,
2762
+ onClick: () => onJumpToStop?.(s.runtimeStageId),
2763
+ style: {
2764
+ display: "block",
2765
+ width: "100%",
2766
+ textAlign: "left",
2767
+ border: "none",
2768
+ borderLeft: isCurrent ? `3px solid ${accent}` : "3px solid transparent",
2769
+ background: isCurrent ? "var(--fp-accent-bg, rgba(99,102,241,0.12))" : "transparent",
2770
+ padding: "4px 8px",
2771
+ cursor: onJumpToStop ? "pointer" : "default",
2772
+ color: "inherit",
2773
+ fontSize: 12
2774
+ },
2775
+ children: [
2776
+ /* @__PURE__ */ jsxs10("span", { style: { color: theme.textMuted }, children: [
2777
+ i + 1,
2778
+ "."
2779
+ ] }),
2780
+ " ",
2781
+ /* @__PURE__ */ jsx11("code", { style: { color: accent }, children: s.contributedKeys.join(", ") }),
2782
+ /* @__PURE__ */ jsx11("span", { style: { color: theme.textMuted }, children: " \u2190 " }),
2783
+ s.stageName,
2784
+ s.loopPass > 0 && /* @__PURE__ */ jsxs10("span", { style: { color: theme.textMuted }, children: [
2785
+ " (pass ",
2786
+ s.loopPass,
2787
+ ")"
2788
+ ] }),
2789
+ stepNumberOf(s.runtimeStageId) && /* @__PURE__ */ jsxs10("span", { style: { color: theme.textMuted }, children: [
2790
+ " \xB7 step ",
2791
+ stepNumberOf(s.runtimeStageId)
2792
+ ] }),
2793
+ s.ingredients.length > 1 && /* @__PURE__ */ jsxs10("span", { style: { color: "#d97706", fontWeight: 600 }, children: [
2794
+ " \u2442 ",
2795
+ s.ingredients.length
2796
+ ] })
2797
+ ]
2798
+ },
2799
+ s.runtimeStageId
2800
+ );
2801
+ })
2802
+ ] }),
2803
+ /* @__PURE__ */ jsxs10("div", { style: { marginTop: 12, display: "flex", flexDirection: "column", gap: 4 }, children: [
2804
+ walk.inputTermini.length > 0 && /* @__PURE__ */ jsxs10("div", { "data-fp": "twc-run-inputs", style: { fontSize: 11, color: theme.textMuted }, children: [
2805
+ "\u2691 run inputs (never written): ",
2806
+ walk.inputTermini.map((k, i) => /* @__PURE__ */ jsxs10("code", { children: [
2807
+ i > 0 && ", ",
2808
+ k
2809
+ ] }, k))
2810
+ ] }),
2811
+ walk.truncated && /* @__PURE__ */ jsx11("div", { "data-fp": "twc-truncated", style: { fontSize: 11, color: "#d97706" }, children: "\u26A0 walk truncated at its frame budget \u2014 the earliest stop may not be the true origin." }),
2812
+ /* @__PURE__ */ jsx11(
2813
+ "button",
2814
+ {
2815
+ "data-fp": "twc-copy-story",
2816
+ onClick: copyStory,
2817
+ style: {
2818
+ alignSelf: "flex-start",
2819
+ marginTop: 4,
2820
+ border: `1px solid ${theme.border}`,
2821
+ background: theme.bgTertiary,
2822
+ color: theme.textPrimary,
2823
+ borderRadius: 6,
2824
+ padding: "4px 10px",
2825
+ fontSize: 11,
2826
+ fontWeight: 600,
2827
+ cursor: "pointer"
2828
+ },
2829
+ children: copied ? "Copied \u2713" : "Copy story"
2830
+ }
2831
+ )
2832
+ ] })
2833
+ ] });
2834
+ });
2835
+ function CardHeader({ label, onExit }) {
2836
+ return /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
2837
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 11, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.5px", fontWeight: 600 }, children: label }),
2838
+ onExit && /* @__PURE__ */ jsx11(
2839
+ "button",
2840
+ {
2841
+ "data-fp": "twc-exit",
2842
+ onClick: onExit,
2843
+ "aria-label": "Exit tracing",
2844
+ style: { border: "none", background: "transparent", color: theme.textMuted, cursor: "pointer", fontSize: 12 },
2845
+ children: "Done \u2715"
2846
+ }
2847
+ )
2848
+ ] });
2849
+ }
2850
+ function IngredientChip({
2851
+ ing,
2852
+ color,
2853
+ step,
2854
+ onFollow
2855
+ }) {
2856
+ const terminus = !ing.writerRuntimeStageId;
2857
+ return /* @__PURE__ */ jsxs10(
2858
+ "button",
2859
+ {
2860
+ "data-fp": "twc-ingredient",
2861
+ "data-terminus": terminus || void 0,
2862
+ disabled: terminus || !onFollow,
2863
+ onClick: () => onFollow?.(ing),
2864
+ title: terminus ? `${ing.key} was never written \u2014 it came in with the run's inputs` : `Follow ${ing.key} \u2014 re-anchor the walk on its writer`,
2865
+ style: {
2866
+ display: "inline-flex",
2867
+ alignItems: "center",
2868
+ gap: 4,
2869
+ border: `1px solid ${terminus ? theme.border : color}`,
2870
+ background: "transparent",
2871
+ color: terminus ? theme.textMuted : color,
2872
+ borderRadius: 12,
2873
+ padding: "3px 10px",
2874
+ fontSize: 11,
2875
+ fontWeight: 600,
2876
+ cursor: terminus || !onFollow ? "default" : "pointer"
2877
+ },
2878
+ children: [
2879
+ /* @__PURE__ */ jsx11("code", { children: ing.key }),
2880
+ terminus ? /* @__PURE__ */ jsx11("span", { style: { fontWeight: 400 }, children: "\u2014 run input \u2691" }) : /* @__PURE__ */ jsxs10("span", { style: { fontWeight: 400 }, children: [
2881
+ "\u2190 ",
2882
+ ing.writerStageName,
2883
+ step && ` \xB7 step ${step}`
2884
+ ] })
2885
+ ]
2886
+ }
2887
+ );
2888
+ }
2889
+ function previewValue(v2) {
2890
+ if (v2 === void 0) return null;
2891
+ try {
2892
+ const s = typeof v2 === "string" ? JSON.stringify(v2) : JSON.stringify(v2);
2893
+ if (s === void 0) return null;
2894
+ return s.length > 60 ? `${s.slice(0, 57)}\u2026` : s;
2895
+ } catch {
2896
+ return null;
2897
+ }
2898
+ }
2899
+
2900
+ // src/components/DataTracePanel/DataTracePanel.tsx
2901
+ import { memo as memo2 } from "react";
2902
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2903
+ var DataTracePanel = memo2(function DataTracePanel2({
2904
+ frames,
2905
+ selectedStageId,
2906
+ onFrameClick,
2907
+ fromStageName,
2908
+ note
2909
+ }) {
2910
+ const noteLine = note ? /* @__PURE__ */ jsx12("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", marginBottom: 8 }, children: note }) : null;
2911
+ if (frames.length === 0) {
2912
+ return /* @__PURE__ */ jsxs11("div", { style: { padding: "14px 14px 12px", fontSize: 13, lineHeight: 1.55 }, children: [
2913
+ /* @__PURE__ */ jsx12(
2914
+ "div",
2915
+ {
2916
+ style: {
2917
+ fontSize: 11,
2918
+ color: theme.textMuted,
2919
+ textTransform: "uppercase",
2920
+ letterSpacing: "0.5px",
2921
+ fontWeight: 600,
2922
+ marginBottom: 6
2923
+ },
2924
+ children: "Backward causal chain"
2925
+ }
2926
+ ),
2927
+ /* @__PURE__ */ jsx12("div", { style: { color: theme.textSecondary, marginBottom: 10 }, children: "Trace any value back to the stage that created it \u2014 and everything upstream that influenced it." }),
2928
+ noteLine,
2929
+ /* @__PURE__ */ jsx12("div", { style: { color: theme.textMuted, fontSize: 12 }, children: "Select a stage above to see its dependency chain." })
2930
+ ] });
2931
+ }
2932
+ return /* @__PURE__ */ jsxs11("div", { style: { padding: "8px 0", fontSize: 13 }, children: [
2933
+ note && /* @__PURE__ */ jsx12("div", { style: { padding: "4px 12px 0", fontSize: 11, color: theme.textMuted, fontStyle: "italic" }, children: note }),
2934
+ fromStageName && /* @__PURE__ */ jsxs11("div", { style: { padding: "4px 12px 8px" }, children: [
2935
+ /* @__PURE__ */ jsxs11(
2936
+ "div",
2937
+ {
2938
+ style: {
2939
+ fontSize: 11,
2940
+ color: theme.textMuted,
2941
+ textTransform: "uppercase",
2942
+ letterSpacing: "0.5px",
2943
+ fontWeight: 600
2944
+ },
2945
+ children: [
2946
+ "Data trace from ",
2947
+ fromStageName
2948
+ ]
2949
+ }
2950
+ ),
2951
+ /* @__PURE__ */ jsx12(
2952
+ "div",
2953
+ {
2954
+ style: {
2955
+ fontSize: 11,
2956
+ color: theme.textMuted,
2957
+ fontStyle: "italic",
2958
+ marginTop: 3
2959
+ },
2960
+ children: "Every value here was derived from the stages below."
2961
+ }
2962
+ )
2963
+ ] }),
2964
+ frames.map((frame, i) => /* @__PURE__ */ jsx12(
2965
+ DataTraceFrame,
2966
+ {
2967
+ frame,
2968
+ isFirst: i === 0,
2969
+ isLast: i === frames.length - 1,
2970
+ isSelected: frame.runtimeStageId === selectedStageId,
2971
+ onClick: onFrameClick
2972
+ },
2973
+ frame.runtimeStageId
2974
+ ))
2975
+ ] });
2976
+ });
2977
+ var DataTraceFrame = memo2(function DataTraceFrame2({
2978
+ frame,
2979
+ isFirst,
2980
+ isLast,
2981
+ isSelected,
2982
+ onClick
2983
+ }) {
2984
+ return /* @__PURE__ */ jsxs11(
2985
+ "button",
2986
+ {
2987
+ onClick: () => onClick?.(frame.runtimeStageId),
2988
+ style: {
2989
+ display: "block",
2990
+ width: "100%",
2991
+ textAlign: "left",
2992
+ border: "none",
2993
+ background: isSelected ? "var(--fp-accent-bg, rgba(99,102,241,0.12))" : "transparent",
2994
+ padding: "6px 12px 6px 16px",
2995
+ cursor: onClick ? "pointer" : "default",
2996
+ borderLeft: isSelected ? "3px solid var(--fp-accent, #6366f1)" : "3px solid transparent",
2997
+ color: "inherit",
2998
+ fontSize: 13
2999
+ },
3000
+ children: [
3001
+ /* @__PURE__ */ jsxs11("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
3002
+ !isFirst && /* @__PURE__ */ jsx12("span", { style: { color: theme.textMuted, fontSize: 11 }, children: "\u2191" }),
3003
+ /* @__PURE__ */ jsx12(
3004
+ "span",
3005
+ {
3006
+ style: {
3007
+ fontWeight: isFirst ? 600 : 400,
3008
+ color: isFirst ? "var(--fp-accent, #6366f1)" : theme.textPrimary
3009
+ },
3010
+ children: frame.stageName
3011
+ }
3012
+ ),
3013
+ isLast && !isFirst && /* @__PURE__ */ jsx12(
3014
+ "span",
3015
+ {
3016
+ style: {
3017
+ fontSize: 10,
3018
+ color: theme.textMuted,
3019
+ fontStyle: "italic"
3020
+ },
3021
+ children: "(origin)"
3022
+ }
3023
+ )
3024
+ ] }),
3025
+ frame.keysWritten.length > 0 && /* @__PURE__ */ jsxs11(
3026
+ "div",
3027
+ {
3028
+ style: {
3029
+ fontSize: 11,
3030
+ color: theme.textMuted,
3031
+ paddingLeft: isFirst ? 0 : 18,
3032
+ marginTop: 2
3033
+ },
3034
+ children: [
3035
+ "wrote:",
3036
+ " ",
3037
+ /* @__PURE__ */ jsx12("span", { style: { color: theme.textSecondary }, children: frame.keysWritten.join(", ") })
3038
+ ]
3039
+ }
3040
+ ),
3041
+ frame.linkedBy && /* @__PURE__ */ jsxs11(
3042
+ "div",
3043
+ {
3044
+ style: {
3045
+ fontSize: 11,
3046
+ color: "var(--fp-accent, #6366f1)",
3047
+ paddingLeft: 18,
3048
+ marginTop: 1
3049
+ },
3050
+ children: [
3051
+ "\u2190 via ",
3052
+ frame.linkedBy
3053
+ ]
3054
+ }
3055
+ )
3056
+ ]
3057
+ }
3058
+ );
3059
+ });
2291
3060
 
2292
3061
  // src/utils/narrativeSync.ts
2293
3062
  function buildEntryRangeIndex(entries) {
@@ -2610,7 +3379,7 @@ function createSnapshots(stages) {
2610
3379
  }
2611
3380
 
2612
3381
  // src/components/MemoryPanel/MemoryPanel.tsx
2613
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3382
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2614
3383
  function MemoryPanel({
2615
3384
  snapshots,
2616
3385
  selectedIndex,
@@ -2622,12 +3391,12 @@ function MemoryPanel({
2622
3391
  const prevMemory = selectedIndex > 0 ? snapshots[selectedIndex - 1]?.memory ?? null : null;
2623
3392
  const currMemory = snapshots[selectedIndex]?.memory ?? {};
2624
3393
  if (unstyled) {
2625
- return /* @__PURE__ */ jsxs10("div", { className, style, "data-fp": "memory-panel", children: [
2626
- /* @__PURE__ */ jsx11(MemoryInspector, { snapshots, selectedIndex, unstyled: true }),
2627
- /* @__PURE__ */ jsx11(ScopeDiff, { previous: prevMemory, current: currMemory, unstyled: true })
3394
+ return /* @__PURE__ */ jsxs12("div", { className, style, "data-fp": "memory-panel", children: [
3395
+ /* @__PURE__ */ jsx13(MemoryInspector, { snapshots, selectedIndex, unstyled: true }),
3396
+ /* @__PURE__ */ jsx13(ScopeDiff, { previous: prevMemory, current: currMemory, unstyled: true })
2628
3397
  ] });
2629
3398
  }
2630
- return /* @__PURE__ */ jsxs10(
3399
+ return /* @__PURE__ */ jsxs12(
2631
3400
  "div",
2632
3401
  {
2633
3402
  className,
@@ -2639,19 +3408,19 @@ function MemoryPanel({
2639
3408
  },
2640
3409
  "data-fp": "memory-panel",
2641
3410
  children: [
2642
- /* @__PURE__ */ jsx11(MemoryInspector, { snapshots, selectedIndex, size }),
2643
- /* @__PURE__ */ jsx11("div", { style: { borderTop: `1px solid ${theme.border}` }, children: /* @__PURE__ */ jsx11(ScopeDiff, { previous: prevMemory, current: currMemory, hideUnchanged: true, size }) })
3411
+ /* @__PURE__ */ jsx13(MemoryInspector, { snapshots, selectedIndex, size }),
3412
+ /* @__PURE__ */ jsx13("div", { style: { borderTop: `1px solid ${theme.border}` }, children: /* @__PURE__ */ jsx13(ScopeDiff, { previous: prevMemory, current: currMemory, hideUnchanged: true, size }) })
2644
3413
  ]
2645
3414
  }
2646
3415
  );
2647
3416
  }
2648
3417
 
2649
3418
  // src/components/NarrativePanel/NarrativePanel.tsx
2650
- import { useMemo as useMemo8, useState as useState7, useCallback as useCallback4 } from "react";
3419
+ import { useMemo as useMemo11, useState as useState8, useCallback as useCallback4 } from "react";
2651
3420
 
2652
3421
  // src/components/StoryNarrative/StoryNarrative.tsx
2653
- import { useMemo as useMemo7, useRef as useRef5, useEffect as useEffect5 } from "react";
2654
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
3422
+ import { useMemo as useMemo10, useRef as useRef5, useEffect as useEffect5 } from "react";
3423
+ import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2655
3424
  var ENTRY_ICONS = {
2656
3425
  stage: { icon: "\u25B8", color: theme.primary, label: "Stage" },
2657
3426
  step: { icon: "\xB7", color: theme.textMuted, label: "Data operation" },
@@ -2674,7 +3443,7 @@ function StoryNarrative({
2674
3443
  const fs = fontSize[size];
2675
3444
  const pad = padding[size];
2676
3445
  const revealedCount = revealedEntryCount;
2677
- const revealed = useMemo7(() => {
3446
+ const revealed = useMemo10(() => {
2678
3447
  const raw = entries.slice(0, revealedCount);
2679
3448
  return raw.filter((e) => {
2680
3449
  const sfId = e.subflowId;
@@ -2683,7 +3452,7 @@ function StoryNarrative({
2683
3452
  return false;
2684
3453
  });
2685
3454
  }, [entries, revealedCount]);
2686
- const futureCount = useMemo7(() => {
3455
+ const futureCount = useMemo10(() => {
2687
3456
  let count = 0;
2688
3457
  for (let i = revealedCount; i < entries.length; i++) {
2689
3458
  const e = entries[i];
@@ -2695,7 +3464,7 @@ function StoryNarrative({
2695
3464
  useEffect5(() => {
2696
3465
  latestRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" });
2697
3466
  }, [revealed.length]);
2698
- const numberedEntries = useMemo7(() => {
3467
+ const numberedEntries = useMemo10(() => {
2699
3468
  let counter = 0;
2700
3469
  const subflowSeen = /* @__PURE__ */ new Set();
2701
3470
  let prevType = "";
@@ -2743,13 +3512,13 @@ function StoryNarrative({
2743
3512
  });
2744
3513
  }, [revealed]);
2745
3514
  if (unstyled) {
2746
- return /* @__PURE__ */ jsx12("div", { className, style: outerStyle, "data-fp": "story-narrative", role: "log", children: numberedEntries.map((entry, i) => {
3515
+ return /* @__PURE__ */ jsx14("div", { className, style: outerStyle, "data-fp": "story-narrative", role: "log", children: numberedEntries.map((entry, i) => {
2747
3516
  if (entry.isSubflowExit) return null;
2748
3517
  const ht = entry.headingType;
2749
- return /* @__PURE__ */ jsx12("div", { "data-fp": "narrative-entry", "data-type": entry.type, children: entry.heading ? entry.text.startsWith("[") ? `${entry.heading}. ${entry.text}` : `${entry.heading}. [${ht}: ${entry.stageName ?? ""}] ${entry.text}` : entry.text }, i);
3518
+ return /* @__PURE__ */ jsx14("div", { "data-fp": "narrative-entry", "data-type": entry.type, children: entry.heading ? entry.text.startsWith("[") ? `${entry.heading}. ${entry.text}` : `${entry.heading}. [${ht}: ${entry.stageName ?? ""}] ${entry.text}` : entry.text }, i);
2750
3519
  }) });
2751
3520
  }
2752
- return /* @__PURE__ */ jsxs11(
3521
+ return /* @__PURE__ */ jsxs13(
2753
3522
  "div",
2754
3523
  {
2755
3524
  className,
@@ -2774,7 +3543,7 @@ function StoryNarrative({
2774
3543
  const isSubflow = entry.isSubflow;
2775
3544
  const isLast = i === numberedEntries.length - 1;
2776
3545
  const headingType = entry.headingType;
2777
- return /* @__PURE__ */ jsxs11(
3546
+ return /* @__PURE__ */ jsxs13(
2778
3547
  "div",
2779
3548
  {
2780
3549
  ref: isLast ? latestRef : void 0,
@@ -2787,7 +3556,7 @@ function StoryNarrative({
2787
3556
  marginTop: isHeading && i > 0 ? 8 : 0
2788
3557
  },
2789
3558
  children: [
2790
- /* @__PURE__ */ jsx12(
3559
+ /* @__PURE__ */ jsx14(
2791
3560
  "span",
2792
3561
  {
2793
3562
  style: {
@@ -2803,7 +3572,7 @@ function StoryNarrative({
2803
3572
  children: meta.icon
2804
3573
  }
2805
3574
  ),
2806
- /* @__PURE__ */ jsx12(
3575
+ /* @__PURE__ */ jsx14(
2807
3576
  "span",
2808
3577
  {
2809
3578
  style: {
@@ -2813,15 +3582,15 @@ function StoryNarrative({
2813
3582
  lineHeight: 1.6,
2814
3583
  fontFamily: entry.type === "step" ? theme.fontMono : theme.fontSans
2815
3584
  },
2816
- children: entry.heading && headingType ? entry.text.startsWith("[") ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
2817
- /* @__PURE__ */ jsxs11("strong", { children: [
3585
+ children: entry.heading && headingType ? entry.text.startsWith("[") ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
3586
+ /* @__PURE__ */ jsxs13("strong", { children: [
2818
3587
  entry.heading,
2819
3588
  "."
2820
3589
  ] }),
2821
3590
  " ",
2822
3591
  entry.text
2823
- ] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
2824
- /* @__PURE__ */ jsxs11("strong", { children: [
3592
+ ] }) : /* @__PURE__ */ jsxs13(Fragment5, { children: [
3593
+ /* @__PURE__ */ jsxs13("strong", { children: [
2825
3594
  entry.heading,
2826
3595
  ". [",
2827
3596
  headingType,
@@ -2838,7 +3607,7 @@ function StoryNarrative({
2838
3607
  i
2839
3608
  );
2840
3609
  }),
2841
- futureCount > 0 && /* @__PURE__ */ jsxs11("div", { style: {
3610
+ futureCount > 0 && /* @__PURE__ */ jsxs13("div", { style: {
2842
3611
  opacity: 0.3,
2843
3612
  fontSize: fs.small,
2844
3613
  color: theme.textMuted,
@@ -2856,7 +3625,7 @@ function StoryNarrative({
2856
3625
  }
2857
3626
 
2858
3627
  // src/components/NarrativePanel/NarrativePanel.tsx
2859
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
3628
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
2860
3629
  function safeJsonStringify(value) {
2861
3630
  const seen = /* @__PURE__ */ new WeakSet();
2862
3631
  const MAX_CHARS = 5e5;
@@ -2894,7 +3663,7 @@ function NarrativePanel({
2894
3663
  }) {
2895
3664
  const fs = fontSize[size];
2896
3665
  const pad = padding[size];
2897
- const narrative = useMemo8(() => {
3666
+ const narrative = useMemo11(() => {
2898
3667
  const lines = [];
2899
3668
  for (const snap of snapshots) {
2900
3669
  const stageLines = (snap.narrative ?? "").split("\n").filter(Boolean);
@@ -2902,7 +3671,7 @@ function NarrativePanel({
2902
3671
  }
2903
3672
  return lines;
2904
3673
  }, [snapshots]);
2905
- const revealedCount = useMemo8(() => {
3674
+ const revealedCount = useMemo11(() => {
2906
3675
  if (snapshots.length === 0 || narrative.length === 0) return narrative.length;
2907
3676
  const stageBoundaries = [];
2908
3677
  for (let i = 0; i < narrative.length; i++) {
@@ -2919,16 +3688,16 @@ function NarrativePanel({
2919
3688
  const endIdx = groupsToShow < stageBoundaries.length ? stageBoundaries[groupsToShow] : narrative.length;
2920
3689
  return Math.max(1, endIdx);
2921
3690
  }, [snapshots.length, selectedIndex, narrative]);
2922
- const rangeIndex = useMemo8(
3691
+ const rangeIndex = useMemo11(
2923
3692
  () => narrativeEntries?.length ? buildEntryRangeIndex(narrativeEntries) : void 0,
2924
3693
  [narrativeEntries]
2925
3694
  );
2926
- const revealedEntryCount = useMemo8(
3695
+ const revealedEntryCount = useMemo11(
2927
3696
  () => narrativeEntries?.length ? computeRevealedEntryCount(narrativeEntries, snapshots, selectedIndex, rangeIndex) : 0,
2928
3697
  [narrativeEntries, snapshots, selectedIndex, rangeIndex]
2929
3698
  );
2930
3699
  const hasStructured = narrativeEntries && narrativeEntries.length > 0;
2931
- const [copied, setCopied] = useState7(false);
3700
+ const [copied, setCopied] = useState8(false);
2932
3701
  const buildLLMNarrative = useCallback4(() => {
2933
3702
  if (!narrativeEntries?.length) {
2934
3703
  return narrative.join("\n");
@@ -3048,9 +3817,9 @@ function NarrativePanel({
3048
3817
  setTimeout(() => setCopied(false), 2e3);
3049
3818
  }, [buildLLMNarrative]);
3050
3819
  if (unstyled) {
3051
- return /* @__PURE__ */ jsx13("div", { className, style, "data-fp": "narrative-panel", children: hasStructured ? /* @__PURE__ */ jsx13(StoryNarrative, { entries: narrativeEntries, revealedEntryCount, unstyled: true }) : /* @__PURE__ */ jsx13(NarrativeTrace, { narrative, revealedCount, unstyled: true }) });
3820
+ return /* @__PURE__ */ jsx15("div", { className, style, "data-fp": "narrative-panel", children: hasStructured ? /* @__PURE__ */ jsx15(StoryNarrative, { entries: narrativeEntries, revealedEntryCount, unstyled: true }) : /* @__PURE__ */ jsx15(NarrativeTrace, { narrative, revealedCount, unstyled: true }) });
3052
3821
  }
3053
- return /* @__PURE__ */ jsxs12(
3822
+ return /* @__PURE__ */ jsxs14(
3054
3823
  "div",
3055
3824
  {
3056
3825
  className,
@@ -3062,7 +3831,7 @@ function NarrativePanel({
3062
3831
  },
3063
3832
  "data-fp": "narrative-panel",
3064
3833
  children: [
3065
- /* @__PURE__ */ jsxs12(
3834
+ /* @__PURE__ */ jsxs14(
3066
3835
  "div",
3067
3836
  {
3068
3837
  style: {
@@ -3076,8 +3845,8 @@ function NarrativePanel({
3076
3845
  alignItems: "center"
3077
3846
  },
3078
3847
  children: [
3079
- /* @__PURE__ */ jsx13("span", { style: { fontStyle: "italic" }, children: "What happened at each stage, what data flowed, what decisions were made, and why." }),
3080
- /* @__PURE__ */ jsx13(
3848
+ /* @__PURE__ */ jsx15("span", { style: { fontStyle: "italic" }, children: "What happened at each stage, what data flowed, what decisions were made, and why." }),
3849
+ /* @__PURE__ */ jsx15(
3081
3850
  "button",
3082
3851
  {
3083
3852
  onClick: handleCopy,
@@ -3100,7 +3869,7 @@ function NarrativePanel({
3100
3869
  ]
3101
3870
  }
3102
3871
  ),
3103
- hasStructured ? /* @__PURE__ */ jsx13(
3872
+ hasStructured ? /* @__PURE__ */ jsx15(
3104
3873
  StoryNarrative,
3105
3874
  {
3106
3875
  entries: narrativeEntries,
@@ -3108,7 +3877,7 @@ function NarrativePanel({
3108
3877
  size,
3109
3878
  style: { flex: 1 }
3110
3879
  }
3111
- ) : /* @__PURE__ */ jsx13(
3880
+ ) : /* @__PURE__ */ jsx15(
3112
3881
  NarrativeTrace,
3113
3882
  {
3114
3883
  narrative,
@@ -3123,8 +3892,8 @@ function NarrativePanel({
3123
3892
  }
3124
3893
 
3125
3894
  // src/components/FlowchartView/SubflowTree.tsx
3126
- import { memo, useState as useState8, useCallback as useCallback5, useMemo as useMemo9 } from "react";
3127
- import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
3895
+ import { memo as memo3, useState as useState9, useCallback as useCallback5, useMemo as useMemo12 } from "react";
3896
+ import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
3128
3897
  function graphToSubflowEntries(graph) {
3129
3898
  if (!graph?.nodes?.length) return [];
3130
3899
  const entries = [];
@@ -3140,14 +3909,14 @@ function graphToSubflowEntries(graph) {
3140
3909
  }
3141
3910
  return entries;
3142
3911
  }
3143
- var TreeNode = memo(function TreeNode2({
3912
+ var TreeNode = memo3(function TreeNode2({
3144
3913
  entry,
3145
3914
  depth,
3146
3915
  activeStage,
3147
3916
  doneStages,
3148
3917
  onNodeSelect
3149
3918
  }) {
3150
- const [expanded, setExpanded] = useState8(true);
3919
+ const [expanded, setExpanded] = useState9(true);
3151
3920
  const hasChildren = entry.children && entry.children.length > 0;
3152
3921
  const isActive = activeStage === entry.name;
3153
3922
  const isDone = doneStages?.has(entry.name);
@@ -3157,8 +3926,8 @@ var TreeNode = memo(function TreeNode2({
3157
3926
  }
3158
3927
  onNodeSelect?.(entry.name, !!entry.isSubflow);
3159
3928
  }, [hasChildren, onNodeSelect, entry.name, entry.isSubflow]);
3160
- return /* @__PURE__ */ jsxs13(Fragment4, { children: [
3161
- /* @__PURE__ */ jsxs13(
3929
+ return /* @__PURE__ */ jsxs15(Fragment6, { children: [
3930
+ /* @__PURE__ */ jsxs15(
3162
3931
  "button",
3163
3932
  {
3164
3933
  onClick: handleClick,
@@ -3189,7 +3958,7 @@ var TreeNode = memo(function TreeNode2({
3189
3958
  }
3190
3959
  },
3191
3960
  children: [
3192
- hasChildren ? /* @__PURE__ */ jsx14(
3961
+ hasChildren ? /* @__PURE__ */ jsx16(
3193
3962
  "span",
3194
3963
  {
3195
3964
  style: {
@@ -3204,8 +3973,8 @@ var TreeNode = memo(function TreeNode2({
3204
3973
  },
3205
3974
  children: "\u25B6"
3206
3975
  }
3207
- ) : /* @__PURE__ */ jsx14("span", { style: { width: 12, flexShrink: 0 } }),
3208
- /* @__PURE__ */ jsx14(
3976
+ ) : /* @__PURE__ */ jsx16("span", { style: { width: 12, flexShrink: 0 } }),
3977
+ /* @__PURE__ */ jsx16(
3209
3978
  "span",
3210
3979
  {
3211
3980
  style: {
@@ -3217,8 +3986,8 @@ var TreeNode = memo(function TreeNode2({
3217
3986
  }
3218
3987
  }
3219
3988
  ),
3220
- /* @__PURE__ */ jsxs13("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
3221
- /* @__PURE__ */ jsxs13(
3989
+ /* @__PURE__ */ jsxs15("span", { style: { display: "flex", flexDirection: "column", minWidth: 0 }, children: [
3990
+ /* @__PURE__ */ jsxs15(
3222
3991
  "span",
3223
3992
  {
3224
3993
  style: {
@@ -3230,11 +3999,11 @@ var TreeNode = memo(function TreeNode2({
3230
3999
  },
3231
4000
  children: [
3232
4001
  entry.name,
3233
- entry.isSubflow && /* @__PURE__ */ jsx14("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
4002
+ entry.isSubflow && /* @__PURE__ */ jsx16("span", { style: { opacity: 0.5, marginLeft: 4, fontSize: 10 }, children: "\u229E" })
3234
4003
  ]
3235
4004
  }
3236
4005
  ),
3237
- entry.description && /* @__PURE__ */ jsx14(
4006
+ entry.description && /* @__PURE__ */ jsx16(
3238
4007
  "span",
3239
4008
  {
3240
4009
  style: {
@@ -3251,7 +4020,7 @@ var TreeNode = memo(function TreeNode2({
3251
4020
  ]
3252
4021
  }
3253
4022
  ),
3254
- hasChildren && expanded && /* @__PURE__ */ jsx14("div", { children: entry.children.map((child, i) => /* @__PURE__ */ jsx14(
4023
+ hasChildren && expanded && /* @__PURE__ */ jsx16("div", { children: entry.children.map((child, i) => /* @__PURE__ */ jsx16(
3255
4024
  TreeNode2,
3256
4025
  {
3257
4026
  entry: child,
@@ -3264,8 +4033,8 @@ var TreeNode = memo(function TreeNode2({
3264
4033
  )) })
3265
4034
  ] });
3266
4035
  });
3267
- var SectionLabel = memo(function SectionLabel2({ children }) {
3268
- return /* @__PURE__ */ jsx14(
4036
+ var SectionLabel = memo3(function SectionLabel2({ children }) {
4037
+ return /* @__PURE__ */ jsx16(
3269
4038
  "div",
3270
4039
  {
3271
4040
  style: {
@@ -3280,7 +4049,7 @@ var SectionLabel = memo(function SectionLabel2({ children }) {
3280
4049
  }
3281
4050
  );
3282
4051
  });
3283
- var SubflowTree = memo(function SubflowTree2({
4052
+ var SubflowTree = memo3(function SubflowTree2({
3284
4053
  graph,
3285
4054
  activeStage,
3286
4055
  doneStages,
@@ -3289,9 +4058,9 @@ var SubflowTree = memo(function SubflowTree2({
3289
4058
  className,
3290
4059
  style
3291
4060
  }) {
3292
- const subflowStages = useMemo9(() => graphToSubflowEntries(graph), [graph]);
4061
+ const subflowStages = useMemo12(() => graphToSubflowEntries(graph), [graph]);
3293
4062
  if (subflowStages.length === 0) return null;
3294
- return /* @__PURE__ */ jsxs13(
4063
+ return /* @__PURE__ */ jsxs15(
3295
4064
  "div",
3296
4065
  {
3297
4066
  className,
@@ -3309,8 +4078,8 @@ var SubflowTree = memo(function SubflowTree2({
3309
4078
  ...style
3310
4079
  },
3311
4080
  children: [
3312
- !unstyled && /* @__PURE__ */ jsx14(SectionLabel, { children: "Subflows" }),
3313
- subflowStages.map((entry, i) => /* @__PURE__ */ jsx14(
4081
+ !unstyled && /* @__PURE__ */ jsx16(SectionLabel, { children: "Subflows" }),
4082
+ subflowStages.map((entry, i) => /* @__PURE__ */ jsx16(
3314
4083
  TreeNode,
3315
4084
  {
3316
4085
  entry,
@@ -3327,14 +4096,14 @@ var SubflowTree = memo(function SubflowTree2({
3327
4096
  });
3328
4097
 
3329
4098
  // src/components/FlowchartView/SubflowBreadcrumb.tsx
3330
- import { memo as memo2 } from "react";
3331
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
3332
- var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
4099
+ import { memo as memo4 } from "react";
4100
+ import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
4101
+ var SubflowBreadcrumb = memo4(function SubflowBreadcrumb2({
3333
4102
  breadcrumbs,
3334
4103
  onNavigate
3335
4104
  }) {
3336
4105
  if (breadcrumbs.length <= 1) return null;
3337
- return /* @__PURE__ */ jsx15(
4106
+ return /* @__PURE__ */ jsx17(
3338
4107
  "div",
3339
4108
  {
3340
4109
  style: {
@@ -3351,10 +4120,10 @@ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
3351
4120
  },
3352
4121
  children: breadcrumbs.map((crumb, i) => {
3353
4122
  const isLast = i === breadcrumbs.length - 1;
3354
- return /* @__PURE__ */ jsxs14("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
3355
- i > 0 && /* @__PURE__ */ jsx15("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
3356
- isLast ? /* @__PURE__ */ jsxs14("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
3357
- /* @__PURE__ */ jsx15(
4123
+ return /* @__PURE__ */ jsxs16("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
4124
+ i > 0 && /* @__PURE__ */ jsx17("span", { style: { color: theme.textMuted, fontSize: 10 }, children: "\u203A" }),
4125
+ isLast ? /* @__PURE__ */ jsxs16("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
4126
+ /* @__PURE__ */ jsx17(
3358
4127
  "span",
3359
4128
  {
3360
4129
  style: {
@@ -3364,7 +4133,7 @@ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
3364
4133
  children: crumb.label
3365
4134
  }
3366
4135
  ),
3367
- crumb.description && /* @__PURE__ */ jsxs14(
4136
+ crumb.description && /* @__PURE__ */ jsxs16(
3368
4137
  "span",
3369
4138
  {
3370
4139
  style: {
@@ -3378,7 +4147,7 @@ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
3378
4147
  ]
3379
4148
  }
3380
4149
  )
3381
- ] }) : /* @__PURE__ */ jsx15(
4150
+ ] }) : /* @__PURE__ */ jsx17(
3382
4151
  "button",
3383
4152
  {
3384
4153
  onClick: () => onNavigate(i),
@@ -3410,7 +4179,7 @@ var SubflowBreadcrumb = memo2(function SubflowBreadcrumb2({
3410
4179
  });
3411
4180
 
3412
4181
  // src/components/FlowchartView/TracedFlow.tsx
3413
- import { useCallback as useCallback7, useEffect as useEffect10, useMemo as useMemo10, useRef as useRef8, useState as useState10 } from "react";
4182
+ import { useCallback as useCallback7, useEffect as useEffect10, useMemo as useMemo13, useRef as useRef8, useState as useState11 } from "react";
3414
4183
  import {
3415
4184
  ReactFlow,
3416
4185
  Background,
@@ -3757,9 +4526,9 @@ function sliceOverlay(overlay, index) {
3757
4526
  }
3758
4527
 
3759
4528
  // src/components/StageNode/StageNode.tsx
3760
- import { memo as memo3, useEffect as useEffect6, useRef as useRef6 } from "react";
4529
+ import { memo as memo5, useEffect as useEffect6, useRef as useRef6 } from "react";
3761
4530
  import { Handle, Position } from "@xyflow/react";
3762
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
4531
+ import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
3763
4532
  var KEYFRAMES_ID = "fp-stage-node-keyframes";
3764
4533
  var KEYFRAMES_CSS = `
3765
4534
  @media (prefers-reduced-motion: no-preference) {
@@ -3785,128 +4554,128 @@ function StageIcon({ type, color }) {
3785
4554
  // LLM / AI call — brain/sparkle
3786
4555
  case "llm":
3787
4556
  case "ai":
3788
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3789
- /* @__PURE__ */ jsx16("circle", { cx: "8", cy: "8", r: "6", stroke: color, strokeWidth: "1.5" }),
3790
- /* @__PURE__ */ jsx16("path", { d: "M5.5 8C5.5 6.5 6.5 5 8 5S10.5 6.5 10.5 8", stroke: color, strokeWidth: "1.2", strokeLinecap: "round" }),
3791
- /* @__PURE__ */ jsx16("circle", { cx: "8", cy: "9.5", r: "1", fill: color }),
3792
- /* @__PURE__ */ jsx16("line", { x1: "8", y1: "2", x2: "8", y2: "3.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3793
- /* @__PURE__ */ jsx16("line", { x1: "12.5", y1: "4", x2: "11.2", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3794
- /* @__PURE__ */ jsx16("line", { x1: "3.5", y1: "4", x2: "4.8", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
4557
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4558
+ /* @__PURE__ */ jsx18("circle", { cx: "8", cy: "8", r: "6", stroke: color, strokeWidth: "1.5" }),
4559
+ /* @__PURE__ */ jsx18("path", { d: "M5.5 8C5.5 6.5 6.5 5 8 5S10.5 6.5 10.5 8", stroke: color, strokeWidth: "1.2", strokeLinecap: "round" }),
4560
+ /* @__PURE__ */ jsx18("circle", { cx: "8", cy: "9.5", r: "1", fill: color }),
4561
+ /* @__PURE__ */ jsx18("line", { x1: "8", y1: "2", x2: "8", y2: "3.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
4562
+ /* @__PURE__ */ jsx18("line", { x1: "12.5", y1: "4", x2: "11.2", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
4563
+ /* @__PURE__ */ jsx18("line", { x1: "3.5", y1: "4", x2: "4.8", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
3795
4564
  ] });
3796
4565
  // Tool / function call — gear
3797
4566
  case "tool":
3798
4567
  case "function":
3799
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3800
- /* @__PURE__ */ jsx16("circle", { cx: "8", cy: "8", r: "3", stroke: color, strokeWidth: "1.5" }),
4568
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4569
+ /* @__PURE__ */ jsx18("circle", { cx: "8", cy: "8", r: "3", stroke: color, strokeWidth: "1.5" }),
3801
4570
  [0, 45, 90, 135, 180, 225, 270, 315].map((angle) => {
3802
4571
  const rad = angle * Math.PI / 180;
3803
4572
  const x1 = 8 + Math.cos(rad) * 4.5;
3804
4573
  const y1 = 8 + Math.sin(rad) * 4.5;
3805
4574
  const x2 = 8 + Math.cos(rad) * 6;
3806
4575
  const y2 = 8 + Math.sin(rad) * 6;
3807
- return /* @__PURE__ */ jsx16("line", { x1, y1, x2, y2, stroke: color, strokeWidth: "1.5", strokeLinecap: "round" }, angle);
4576
+ return /* @__PURE__ */ jsx18("line", { x1, y1, x2, y2, stroke: color, strokeWidth: "1.5", strokeLinecap: "round" }, angle);
3808
4577
  })
3809
4578
  ] });
3810
4579
  // RAG / retrieval — magnifying glass + doc
3811
4580
  case "rag":
3812
4581
  case "search":
3813
4582
  case "retrieval":
3814
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3815
- /* @__PURE__ */ jsx16("circle", { cx: "7", cy: "7", r: "4", stroke: color, strokeWidth: "1.5" }),
3816
- /* @__PURE__ */ jsx16("line", { x1: "10", y1: "10", x2: "13.5", y2: "13.5", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" }),
3817
- /* @__PURE__ */ jsx16("line", { x1: "5.5", y1: "6", x2: "8.5", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3818
- /* @__PURE__ */ jsx16("line", { x1: "5.5", y1: "8", x2: "7.5", y2: "8", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
4583
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4584
+ /* @__PURE__ */ jsx18("circle", { cx: "7", cy: "7", r: "4", stroke: color, strokeWidth: "1.5" }),
4585
+ /* @__PURE__ */ jsx18("line", { x1: "10", y1: "10", x2: "13.5", y2: "13.5", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" }),
4586
+ /* @__PURE__ */ jsx18("line", { x1: "5.5", y1: "6", x2: "8.5", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
4587
+ /* @__PURE__ */ jsx18("line", { x1: "5.5", y1: "8", x2: "7.5", y2: "8", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
3819
4588
  ] });
3820
4589
  // Parse / process — diamond with arrows
3821
4590
  case "parse":
3822
4591
  case "process":
3823
4592
  case "transform":
3824
- return /* @__PURE__ */ jsx16("svg", { ...props, children: /* @__PURE__ */ jsx16("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: color, strokeWidth: "1.5", transform: "rotate(45 8 8)" }) });
4593
+ return /* @__PURE__ */ jsx18("svg", { ...props, children: /* @__PURE__ */ jsx18("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", stroke: color, strokeWidth: "1.5", transform: "rotate(45 8 8)" }) });
3825
4594
  // Start / seed — play triangle
3826
4595
  case "start":
3827
4596
  case "seed":
3828
4597
  case "init":
3829
- return /* @__PURE__ */ jsx16("svg", { ...props, children: /* @__PURE__ */ jsx16("path", { d: "M5 3.5L12.5 8L5 12.5V3.5Z", fill: color, opacity: "0.8" }) });
4598
+ return /* @__PURE__ */ jsx18("svg", { ...props, children: /* @__PURE__ */ jsx18("path", { d: "M5 3.5L12.5 8L5 12.5V3.5Z", fill: color, opacity: "0.8" }) });
3830
4599
  // End / finalize — stop square
3831
4600
  case "end":
3832
4601
  case "finalize":
3833
4602
  case "output":
3834
- return /* @__PURE__ */ jsx16("svg", { ...props, children: /* @__PURE__ */ jsx16("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", fill: color, opacity: "0.8" }) });
4603
+ return /* @__PURE__ */ jsx18("svg", { ...props, children: /* @__PURE__ */ jsx18("rect", { x: "4", y: "4", width: "8", height: "8", rx: "1.5", fill: color, opacity: "0.8" }) });
3835
4604
  // Agent — person silhouette
3836
4605
  case "agent":
3837
4606
  case "orchestrator":
3838
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3839
- /* @__PURE__ */ jsx16("circle", { cx: "8", cy: "5", r: "2.5", stroke: color, strokeWidth: "1.5" }),
3840
- /* @__PURE__ */ jsx16("path", { d: "M3.5 14C3.5 11 5.5 9 8 9S12.5 11 12.5 14", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" })
4607
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4608
+ /* @__PURE__ */ jsx18("circle", { cx: "8", cy: "5", r: "2.5", stroke: color, strokeWidth: "1.5" }),
4609
+ /* @__PURE__ */ jsx18("path", { d: "M3.5 14C3.5 11 5.5 9 8 9S12.5 11 12.5 14", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" })
3841
4610
  ] });
3842
4611
  // Swarm — multi-agent
3843
4612
  case "swarm":
3844
4613
  case "multi-agent":
3845
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3846
- /* @__PURE__ */ jsx16("circle", { cx: "5", cy: "5", r: "2", stroke: color, strokeWidth: "1.2" }),
3847
- /* @__PURE__ */ jsx16("circle", { cx: "11", cy: "5", r: "2", stroke: color, strokeWidth: "1.2" }),
3848
- /* @__PURE__ */ jsx16("circle", { cx: "8", cy: "11", r: "2", stroke: color, strokeWidth: "1.2" }),
3849
- /* @__PURE__ */ jsx16("line", { x1: "5", y1: "7", x2: "8", y2: "9", stroke: color, strokeWidth: "1", opacity: "0.5" }),
3850
- /* @__PURE__ */ jsx16("line", { x1: "11", y1: "7", x2: "8", y2: "9", stroke: color, strokeWidth: "1", opacity: "0.5" })
4614
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4615
+ /* @__PURE__ */ jsx18("circle", { cx: "5", cy: "5", r: "2", stroke: color, strokeWidth: "1.2" }),
4616
+ /* @__PURE__ */ jsx18("circle", { cx: "11", cy: "5", r: "2", stroke: color, strokeWidth: "1.2" }),
4617
+ /* @__PURE__ */ jsx18("circle", { cx: "8", cy: "11", r: "2", stroke: color, strokeWidth: "1.2" }),
4618
+ /* @__PURE__ */ jsx18("line", { x1: "5", y1: "7", x2: "8", y2: "9", stroke: color, strokeWidth: "1", opacity: "0.5" }),
4619
+ /* @__PURE__ */ jsx18("line", { x1: "11", y1: "7", x2: "8", y2: "9", stroke: color, strokeWidth: "1", opacity: "0.5" })
3851
4620
  ] });
3852
4621
  // Guard / guardrail — shield
3853
4622
  case "guard":
3854
4623
  case "guardrail":
3855
4624
  case "validate":
3856
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3857
- /* @__PURE__ */ jsx16("path", { d: "M8 2L3 5V9C3 11.5 5 13.5 8 14.5C11 13.5 13 11.5 13 9V5L8 2Z", stroke: color, strokeWidth: "1.5", strokeLinejoin: "round" }),
3858
- /* @__PURE__ */ jsx16("path", { d: "M6 8L7.5 9.5L10 6.5", stroke: color, strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
4625
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4626
+ /* @__PURE__ */ jsx18("path", { d: "M8 2L3 5V9C3 11.5 5 13.5 8 14.5C11 13.5 13 11.5 13 9V5L8 2Z", stroke: color, strokeWidth: "1.5", strokeLinejoin: "round" }),
4627
+ /* @__PURE__ */ jsx18("path", { d: "M6 8L7.5 9.5L10 6.5", stroke: color, strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
3859
4628
  ] });
3860
4629
  // Stream — wave
3861
4630
  case "stream":
3862
4631
  case "streaming":
3863
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3864
- /* @__PURE__ */ jsx16("path", { d: "M2 8C4 5 6 11 8 8S12 5 14 8", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", fill: "none" }),
3865
- /* @__PURE__ */ jsx16("path", { d: "M2 11C4 8 6 14 8 11S12 8 14 11", stroke: color, strokeWidth: "1", strokeLinecap: "round", fill: "none", opacity: "0.5" })
4632
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4633
+ /* @__PURE__ */ jsx18("path", { d: "M2 8C4 5 6 11 8 8S12 5 14 8", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", fill: "none" }),
4634
+ /* @__PURE__ */ jsx18("path", { d: "M2 11C4 8 6 14 8 11S12 8 14 11", stroke: color, strokeWidth: "1", strokeLinecap: "round", fill: "none", opacity: "0.5" })
3866
4635
  ] });
3867
4636
  // Memory / state — database cylinder
3868
4637
  case "memory":
3869
4638
  case "state":
3870
4639
  case "db":
3871
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3872
- /* @__PURE__ */ jsx16("ellipse", { cx: "8", cy: "4.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" }),
3873
- /* @__PURE__ */ jsx16("line", { x1: "3", y1: "4.5", x2: "3", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
3874
- /* @__PURE__ */ jsx16("line", { x1: "13", y1: "4.5", x2: "13", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
3875
- /* @__PURE__ */ jsx16("ellipse", { cx: "8", cy: "11.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" })
4640
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4641
+ /* @__PURE__ */ jsx18("ellipse", { cx: "8", cy: "4.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" }),
4642
+ /* @__PURE__ */ jsx18("line", { x1: "3", y1: "4.5", x2: "3", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
4643
+ /* @__PURE__ */ jsx18("line", { x1: "13", y1: "4.5", x2: "13", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
4644
+ /* @__PURE__ */ jsx18("ellipse", { cx: "8", cy: "11.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" })
3876
4645
  ] });
3877
4646
  // System prompt — document with lines
3878
4647
  case "system-prompt":
3879
4648
  case "prompt":
3880
4649
  case "instructions":
3881
4650
  case "document":
3882
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3883
- /* @__PURE__ */ jsx16("rect", { x: "3.5", y: "2", width: "9", height: "12", rx: "1.5", stroke: color, strokeWidth: "1.3", fill: "none" }),
3884
- /* @__PURE__ */ jsx16("line", { x1: "5.5", y1: "5", x2: "10.5", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3885
- /* @__PURE__ */ jsx16("line", { x1: "5.5", y1: "7.5", x2: "10.5", y2: "7.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3886
- /* @__PURE__ */ jsx16("line", { x1: "5.5", y1: "10", x2: "8.5", y2: "10", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
4651
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4652
+ /* @__PURE__ */ jsx18("rect", { x: "3.5", y: "2", width: "9", height: "12", rx: "1.5", stroke: color, strokeWidth: "1.3", fill: "none" }),
4653
+ /* @__PURE__ */ jsx18("line", { x1: "5.5", y1: "5", x2: "10.5", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
4654
+ /* @__PURE__ */ jsx18("line", { x1: "5.5", y1: "7.5", x2: "10.5", y2: "7.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
4655
+ /* @__PURE__ */ jsx18("line", { x1: "5.5", y1: "10", x2: "8.5", y2: "10", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
3887
4656
  ] });
3888
4657
  // Messages / conversation — chat bubble
3889
4658
  case "messages":
3890
4659
  case "chat":
3891
4660
  case "conversation":
3892
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3893
- /* @__PURE__ */ jsx16("rect", { x: "2.5", y: "3", width: "11", height: "8", rx: "2", stroke: color, strokeWidth: "1.3", fill: "none" }),
3894
- /* @__PURE__ */ jsx16("path", { d: "M5.5 11L5.5 13.5L8.5 11", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
3895
- /* @__PURE__ */ jsx16("line", { x1: "5", y1: "6", x2: "11", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3896
- /* @__PURE__ */ jsx16("line", { x1: "5", y1: "8.5", x2: "9", y2: "8.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
4661
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4662
+ /* @__PURE__ */ jsx18("rect", { x: "2.5", y: "3", width: "11", height: "8", rx: "2", stroke: color, strokeWidth: "1.3", fill: "none" }),
4663
+ /* @__PURE__ */ jsx18("path", { d: "M5.5 11L5.5 13.5L8.5 11", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
4664
+ /* @__PURE__ */ jsx18("line", { x1: "5", y1: "6", x2: "11", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
4665
+ /* @__PURE__ */ jsx18("line", { x1: "5", y1: "8.5", x2: "9", y2: "8.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
3897
4666
  ] });
3898
4667
  // Loop — circular arrow
3899
4668
  case "loop":
3900
4669
  case "retry":
3901
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3902
- /* @__PURE__ */ jsx16("path", { d: "M12 8A4 4 0 1 1 8 4", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", fill: "none" }),
3903
- /* @__PURE__ */ jsx16("path", { d: "M8 1.5L10.5 4L8 6.5", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" })
4670
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4671
+ /* @__PURE__ */ jsx18("path", { d: "M12 8A4 4 0 1 1 8 4", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", fill: "none" }),
4672
+ /* @__PURE__ */ jsx18("path", { d: "M8 1.5L10.5 4L8 6.5", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" })
3904
4673
  ] });
3905
4674
  // Lazy / service — cloud (deferred resolution, loaded on demand)
3906
4675
  case "lazy":
3907
4676
  case "service":
3908
4677
  case "cloud":
3909
- return /* @__PURE__ */ jsx16("svg", { ...props, children: /* @__PURE__ */ jsx16(
4678
+ return /* @__PURE__ */ jsx18("svg", { ...props, children: /* @__PURE__ */ jsx18(
3910
4679
  "path",
3911
4680
  {
3912
4681
  d: "M4.5 12C2.8 12 1.5 10.7 1.5 9C1.5 7.5 2.5 6.3 3.8 6C4 4 5.8 2.5 8 2.5C9.8 2.5 11.3 3.5 11.9 5C13.9 5.2 15.5 6.8 15.5 8.8C15.5 10.8 13.9 12.5 11.8 12.5H4.5",
@@ -3919,15 +4688,15 @@ function StageIcon({ type, color }) {
3919
4688
  // Decision — diamond (already handled by isDecider shape)
3920
4689
  case "decision":
3921
4690
  case "router":
3922
- return /* @__PURE__ */ jsxs15("svg", { ...props, children: [
3923
- /* @__PURE__ */ jsx16("path", { d: "M8 2L14 8L8 14L2 8Z", stroke: color, strokeWidth: "1.5", fill: "none" }),
3924
- /* @__PURE__ */ jsx16("circle", { cx: "8", cy: "8", r: "1.5", fill: color })
4691
+ return /* @__PURE__ */ jsxs17("svg", { ...props, children: [
4692
+ /* @__PURE__ */ jsx18("path", { d: "M8 2L14 8L8 14L2 8Z", stroke: color, strokeWidth: "1.5", fill: "none" }),
4693
+ /* @__PURE__ */ jsx18("circle", { cx: "8", cy: "8", r: "1.5", fill: color })
3925
4694
  ] });
3926
4695
  default:
3927
4696
  return null;
3928
4697
  }
3929
4698
  }
3930
- var StageNode = memo3(function StageNode2({
4699
+ var StageNode = memo5(function StageNode2({
3931
4700
  data
3932
4701
  }) {
3933
4702
  const { label, active, done, error, linked, icon, stepNumbers, dimmed, isSubflow, isLazy, isDecider, isFork, description, stageId, showStageId } = data;
@@ -3955,9 +4724,9 @@ var StageNode = memo3(function StageNode2({
3955
4724
  const borderColor = active ? theme.nodeCursor : isHero && done ? theme.nodeMain : done ? theme.nodeVisited : error ? theme.error : restingBorder;
3956
4725
  const shadow = active ? `0 0 22px color-mix(in srgb, ${theme.nodeCursor} 55%, transparent)` : isHero && done ? `0 0 12px color-mix(in srgb, ${theme.nodeMain} 30%, transparent)` : done ? `0 0 8px color-mix(in srgb, ${theme.nodeVisited} 20%, transparent)` : error ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)` : restingShadow;
3957
4726
  const textColor = active ? "#1a1a1a" : done || error ? "#fff" : theme.textPrimary;
3958
- return /* @__PURE__ */ jsxs15(Fragment5, { children: [
3959
- /* @__PURE__ */ jsx16(Handle, { type: "target", position: Position.Top, style: { opacity: 0 } }),
3960
- /* @__PURE__ */ jsx16("div", { style: { width: "100%", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs15(
4727
+ return /* @__PURE__ */ jsxs17(Fragment7, { children: [
4728
+ /* @__PURE__ */ jsx18(Handle, { type: "target", position: Position.Top, style: { opacity: 0 } }),
4729
+ /* @__PURE__ */ jsx18("div", { style: { width: "100%", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs17(
3961
4730
  "div",
3962
4731
  {
3963
4732
  style: {
@@ -3970,7 +4739,7 @@ var StageNode = memo3(function StageNode2({
3970
4739
  opacity: isMuted ? 0.5 : void 0
3971
4740
  },
3972
4741
  children: [
3973
- stepNumbers && stepNumbers.length > 0 && isOnPath && /* @__PURE__ */ jsx16(
4742
+ stepNumbers && stepNumbers.length > 0 && isOnPath && /* @__PURE__ */ jsx18(
3974
4743
  "div",
3975
4744
  {
3976
4745
  style: {
@@ -3985,7 +4754,7 @@ var StageNode = memo3(function StageNode2({
3985
4754
  const isLatest = i === stepNumbers.length - 1;
3986
4755
  const badgeBg = isLatest && active ? theme.nodeCursor : theme.nodeVisited;
3987
4756
  const glow = isLatest && active ? `color-mix(in srgb, ${theme.nodeCursor} 50%, transparent)` : `color-mix(in srgb, ${theme.nodeVisited} 40%, transparent)`;
3988
- return /* @__PURE__ */ jsx16(
4757
+ return /* @__PURE__ */ jsx18(
3989
4758
  "div",
3990
4759
  {
3991
4760
  style: {
@@ -4008,7 +4777,7 @@ var StageNode = memo3(function StageNode2({
4008
4777
  })
4009
4778
  }
4010
4779
  ),
4011
- linked && /* @__PURE__ */ jsx16(
4780
+ linked && /* @__PURE__ */ jsx18(
4012
4781
  "div",
4013
4782
  {
4014
4783
  style: {
@@ -4022,7 +4791,7 @@ var StageNode = memo3(function StageNode2({
4022
4791
  }
4023
4792
  }
4024
4793
  ),
4025
- active && /* @__PURE__ */ jsx16(
4794
+ active && /* @__PURE__ */ jsx18(
4026
4795
  "div",
4027
4796
  {
4028
4797
  style: {
@@ -4036,7 +4805,7 @@ var StageNode = memo3(function StageNode2({
4036
4805
  }
4037
4806
  }
4038
4807
  ),
4039
- active && /* @__PURE__ */ jsx16(
4808
+ active && /* @__PURE__ */ jsx18(
4040
4809
  "div",
4041
4810
  {
4042
4811
  style: {
@@ -4056,8 +4825,8 @@ var StageNode = memo3(function StageNode2({
4056
4825
  children: "NOW"
4057
4826
  }
4058
4827
  ),
4059
- isDecider ? /* @__PURE__ */ jsxs15("div", { style: { position: "relative", width: 120, height: 72 }, children: [
4060
- /* @__PURE__ */ jsx16(
4828
+ isDecider ? /* @__PURE__ */ jsxs17("div", { style: { position: "relative", width: 120, height: 72 }, children: [
4829
+ /* @__PURE__ */ jsx18(
4061
4830
  "div",
4062
4831
  {
4063
4832
  style: {
@@ -4071,7 +4840,7 @@ var StageNode = memo3(function StageNode2({
4071
4840
  }
4072
4841
  }
4073
4842
  ),
4074
- /* @__PURE__ */ jsx16(
4843
+ /* @__PURE__ */ jsx18(
4075
4844
  "div",
4076
4845
  {
4077
4846
  style: {
@@ -4087,7 +4856,7 @@ var StageNode = memo3(function StageNode2({
4087
4856
  }
4088
4857
  }
4089
4858
  ),
4090
- /* @__PURE__ */ jsxs15(
4859
+ /* @__PURE__ */ jsxs17(
4091
4860
  "div",
4092
4861
  {
4093
4862
  style: {
@@ -4102,10 +4871,10 @@ var StageNode = memo3(function StageNode2({
4102
4871
  zIndex: 1
4103
4872
  },
4104
4873
  children: [
4105
- /* @__PURE__ */ jsxs15("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
4106
- effectiveIcon && /* @__PURE__ */ jsx16(StageIcon, { type: effectiveIcon, color: textColor }),
4107
- !effectiveIcon && /* @__PURE__ */ jsx16("span", { style: { fontSize: 9, color: textColor }, children: "\u25C7" }),
4108
- /* @__PURE__ */ jsx16(
4874
+ /* @__PURE__ */ jsxs17("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
4875
+ effectiveIcon && /* @__PURE__ */ jsx18(StageIcon, { type: effectiveIcon, color: textColor }),
4876
+ !effectiveIcon && /* @__PURE__ */ jsx18("span", { style: { fontSize: 9, color: textColor }, children: "\u25C7" }),
4877
+ /* @__PURE__ */ jsx18(
4109
4878
  "span",
4110
4879
  {
4111
4880
  style: {
@@ -4118,7 +4887,7 @@ var StageNode = memo3(function StageNode2({
4118
4887
  }
4119
4888
  )
4120
4889
  ] }),
4121
- description && /* @__PURE__ */ jsx16(
4890
+ description && /* @__PURE__ */ jsx18(
4122
4891
  "span",
4123
4892
  {
4124
4893
  style: {
@@ -4134,7 +4903,7 @@ var StageNode = memo3(function StageNode2({
4134
4903
  children: description
4135
4904
  }
4136
4905
  ),
4137
- showStageId && stageId && /* @__PURE__ */ jsx16(
4906
+ showStageId && stageId && /* @__PURE__ */ jsx18(
4138
4907
  "span",
4139
4908
  {
4140
4909
  style: {
@@ -4156,7 +4925,7 @@ var StageNode = memo3(function StageNode2({
4156
4925
  )
4157
4926
  ] }) : (
4158
4927
  /* Standard rectangular node */
4159
- /* @__PURE__ */ jsxs15(
4928
+ /* @__PURE__ */ jsxs17(
4160
4929
  "div",
4161
4930
  {
4162
4931
  style: {
@@ -4175,10 +4944,10 @@ var StageNode = memo3(function StageNode2({
4175
4944
  justifyContent: "center"
4176
4945
  },
4177
4946
  children: [
4178
- /* @__PURE__ */ jsxs15("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
4179
- effectiveIcon && /* @__PURE__ */ jsx16(StageIcon, { type: effectiveIcon, color: textColor }),
4180
- done && !effectiveIcon && /* @__PURE__ */ jsx16("span", { style: { fontSize: 10, color: textColor }, children: "\u2713" }),
4181
- active && !effectiveIcon && /* @__PURE__ */ jsx16(
4947
+ /* @__PURE__ */ jsxs17("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
4948
+ effectiveIcon && /* @__PURE__ */ jsx18(StageIcon, { type: effectiveIcon, color: textColor }),
4949
+ done && !effectiveIcon && /* @__PURE__ */ jsx18("span", { style: { fontSize: 10, color: textColor }, children: "\u2713" }),
4950
+ active && !effectiveIcon && /* @__PURE__ */ jsx18(
4182
4951
  "span",
4183
4952
  {
4184
4953
  style: {
@@ -4191,8 +4960,8 @@ var StageNode = memo3(function StageNode2({
4191
4960
  }
4192
4961
  }
4193
4962
  ),
4194
- error && !effectiveIcon && /* @__PURE__ */ jsx16("span", { style: { fontSize: 10, color: textColor }, children: "\u2717" }),
4195
- /* @__PURE__ */ jsx16(
4963
+ error && !effectiveIcon && /* @__PURE__ */ jsx18("span", { style: { fontSize: 10, color: textColor }, children: "\u2717" }),
4964
+ /* @__PURE__ */ jsx18(
4196
4965
  "span",
4197
4966
  {
4198
4967
  style: {
@@ -4204,7 +4973,7 @@ var StageNode = memo3(function StageNode2({
4204
4973
  children: label
4205
4974
  }
4206
4975
  ),
4207
- isSubflow && /* @__PURE__ */ jsx16(
4976
+ isSubflow && /* @__PURE__ */ jsx18(
4208
4977
  "span",
4209
4978
  {
4210
4979
  style: {
@@ -4219,7 +4988,7 @@ var StageNode = memo3(function StageNode2({
4219
4988
  opacity: 0.7,
4220
4989
  flexShrink: 0
4221
4990
  },
4222
- children: /* @__PURE__ */ jsx16(
4991
+ children: /* @__PURE__ */ jsx18(
4223
4992
  "span",
4224
4993
  {
4225
4994
  style: {
@@ -4233,7 +5002,7 @@ var StageNode = memo3(function StageNode2({
4233
5002
  }
4234
5003
  )
4235
5004
  ] }),
4236
- description && /* @__PURE__ */ jsx16(
5005
+ description && /* @__PURE__ */ jsx18(
4237
5006
  "span",
4238
5007
  {
4239
5008
  style: {
@@ -4249,7 +5018,7 @@ var StageNode = memo3(function StageNode2({
4249
5018
  children: description
4250
5019
  }
4251
5020
  ),
4252
- showStageId && stageId && /* @__PURE__ */ jsx16(
5021
+ showStageId && stageId && /* @__PURE__ */ jsx18(
4253
5022
  "span",
4254
5023
  {
4255
5024
  style: {
@@ -4273,7 +5042,7 @@ var StageNode = memo3(function StageNode2({
4273
5042
  ]
4274
5043
  }
4275
5044
  ) }),
4276
- /* @__PURE__ */ jsx16(Handle, { type: "source", position: Position.Bottom, style: { opacity: 0 } })
5045
+ /* @__PURE__ */ jsx18(Handle, { type: "source", position: Position.Bottom, style: { opacity: 0 } })
4277
5046
  ] });
4278
5047
  });
4279
5048
 
@@ -4325,9 +5094,9 @@ function aggregateMountStatus(slice, graph, currentSubflowId) {
4325
5094
  }
4326
5095
 
4327
5096
  // src/components/FlowchartView/_internal/useSubflowDrill.ts
4328
- import { useCallback as useCallback6, useEffect as useEffect7, useRef as useRef7, useState as useState9 } from "react";
5097
+ import { useCallback as useCallback6, useEffect as useEffect7, useRef as useRef7, useState as useState10 } from "react";
4329
5098
  function useSubflowDrill(graph, onSubflowChange) {
4330
- const [currentSubflowId, setCurrentSubflowId] = useState9(null);
5099
+ const [currentSubflowId, setCurrentSubflowId] = useState10(null);
4331
5100
  const lastGraphRef = useRef7(null);
4332
5101
  if (lastGraphRef.current !== graph) {
4333
5102
  lastGraphRef.current = graph;
@@ -4396,9 +5165,9 @@ function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
4396
5165
  }
4397
5166
 
4398
5167
  // src/components/FlowchartView/SubflowBreadcrumbBar.tsx
4399
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
5168
+ import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
4400
5169
  function SubflowBreadcrumbBar({ entries, onNavigate }) {
4401
- return /* @__PURE__ */ jsx17(
5170
+ return /* @__PURE__ */ jsx19(
4402
5171
  "div",
4403
5172
  {
4404
5173
  style: {
@@ -4414,12 +5183,12 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
4414
5183
  "aria-label": "Subflow breadcrumb",
4415
5184
  children: entries.map((entry, i) => {
4416
5185
  const isLast = i === entries.length - 1;
4417
- return /* @__PURE__ */ jsxs16(
5186
+ return /* @__PURE__ */ jsxs18(
4418
5187
  "span",
4419
5188
  {
4420
5189
  style: { display: "inline-flex", alignItems: "center", gap: 6 },
4421
5190
  children: [
4422
- /* @__PURE__ */ jsx17(
5191
+ /* @__PURE__ */ jsx19(
4423
5192
  "button",
4424
5193
  {
4425
5194
  type: "button",
@@ -4439,7 +5208,7 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
4439
5208
  children: entry.label
4440
5209
  }
4441
5210
  ),
4442
- !isLast && /* @__PURE__ */ jsx17("span", { style: { color: theme.textMuted }, children: "\u203A" })
5211
+ !isLast && /* @__PURE__ */ jsx19("span", { style: { color: theme.textMuted }, children: "\u203A" })
4443
5212
  ]
4444
5213
  },
4445
5214
  entry.subflowId ?? "__top__"
@@ -4451,11 +5220,11 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
4451
5220
 
4452
5221
  // src/components/GroupContainerNode/GroupContainerNode.tsx
4453
5222
  import { Handle as Handle2, Position as Position2 } from "@xyflow/react";
4454
- import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
5223
+ import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
4455
5224
  function GroupContainerNode({ data }) {
4456
5225
  const d = data;
4457
5226
  const borderColor = d.error ? theme.error : d.active ? theme.primary : d.done ? theme.nodeVisited : theme.border;
4458
- return /* @__PURE__ */ jsxs17(
5227
+ return /* @__PURE__ */ jsxs19(
4459
5228
  "div",
4460
5229
  {
4461
5230
  style: {
@@ -4471,7 +5240,7 @@ function GroupContainerNode({ data }) {
4471
5240
  position: "relative"
4472
5241
  },
4473
5242
  children: [
4474
- /* @__PURE__ */ jsxs17(
5243
+ /* @__PURE__ */ jsxs19(
4475
5244
  "div",
4476
5245
  {
4477
5246
  style: {
@@ -4485,13 +5254,13 @@ function GroupContainerNode({ data }) {
4485
5254
  letterSpacing: 0.2
4486
5255
  },
4487
5256
  children: [
4488
- d.icon ? /* @__PURE__ */ jsx18("span", { "aria-hidden": true, children: d.icon }) : null,
4489
- /* @__PURE__ */ jsx18("span", { children: d.label })
5257
+ d.icon ? /* @__PURE__ */ jsx20("span", { "aria-hidden": true, children: d.icon }) : null,
5258
+ /* @__PURE__ */ jsx20("span", { children: d.label })
4490
5259
  ]
4491
5260
  }
4492
5261
  ),
4493
- /* @__PURE__ */ jsx18(Handle2, { type: "target", position: Position2.Top, style: { opacity: 0 } }),
4494
- /* @__PURE__ */ jsx18(Handle2, { type: "source", position: Position2.Bottom, style: { opacity: 0 } })
5262
+ /* @__PURE__ */ jsx20(Handle2, { type: "target", position: Position2.Top, style: { opacity: 0 } }),
5263
+ /* @__PURE__ */ jsx20(Handle2, { type: "source", position: Position2.Bottom, style: { opacity: 0 } })
4495
5264
  ]
4496
5265
  }
4497
5266
  );
@@ -4717,7 +5486,7 @@ function wrapInMainChartBox(graph, opts) {
4717
5486
  }
4718
5487
 
4719
5488
  // src/components/LoopBackEdge/LoopBackEdge.tsx
4720
- import { jsx as jsx19 } from "react/jsx-runtime";
5489
+ import { jsx as jsx21 } from "react/jsx-runtime";
4721
5490
  var LOOP_DASH = "5 5";
4722
5491
  var LOOP_STROKE_OPACITY_CAP = 0.55;
4723
5492
  var LOOP_STROKE_WIDTH = 1.5;
@@ -4756,7 +5525,7 @@ function LoopBackEdge({ id, source, target, markerEnd, style }) {
4756
5525
  );
4757
5526
  });
4758
5527
  if (!path) return null;
4759
- return /* @__PURE__ */ jsx19(
5528
+ return /* @__PURE__ */ jsx21(
4760
5529
  BaseEdge,
4761
5530
  {
4762
5531
  id,
@@ -4794,7 +5563,7 @@ function resolveStepBendY(forkBend, staggeredBend) {
4794
5563
  }
4795
5564
 
4796
5565
  // src/components/SmartStepEdge/SmartStepEdge.tsx
4797
- import { jsx as jsx20 } from "react/jsx-runtime";
5566
+ import { jsx as jsx22 } from "react/jsx-runtime";
4798
5567
  function SmartStepEdge({
4799
5568
  id,
4800
5569
  source,
@@ -4845,7 +5614,7 @@ function SmartStepEdge({
4845
5614
  // use its default centerY (== the built-in `smoothstep` path, byte-for-byte).
4846
5615
  ...bendY !== null ? { centerY: bendY } : {}
4847
5616
  });
4848
- return /* @__PURE__ */ jsx20(BaseEdge2, { id, path, markerEnd, style });
5617
+ return /* @__PURE__ */ jsx22(BaseEdge2, { id, path, markerEnd, style });
4849
5618
  }
4850
5619
 
4851
5620
  // src/components/FlowchartView/_internal/MeasuredNodeSizes.tsx
@@ -4892,7 +5661,7 @@ function MeasuredNodeSizes({
4892
5661
  }
4893
5662
 
4894
5663
  // src/components/FlowchartView/TracedFlow.tsx
4895
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
5664
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
4896
5665
  var DEFAULT_COLORS = {
4897
5666
  default: rawDefaults.colors.textMuted,
4898
5667
  done: rawDefaults.colors.success,
@@ -5038,21 +5807,21 @@ function TracedFlow({
5038
5807
  );
5039
5808
  }
5040
5809
  }, [layoutProp]);
5041
- const colors = useMemo10(
5810
+ const colors = useMemo13(
5042
5811
  () => ({ ...DEFAULT_COLORS, ...colorOverrides ?? {} }),
5043
5812
  [colorOverrides]
5044
5813
  );
5045
- const mergedNodeTypes = useMemo10(
5814
+ const mergedNodeTypes = useMemo13(
5046
5815
  () => userNodeTypes ? { ...DEFAULT_NODE_TYPES, ...userNodeTypes } : DEFAULT_NODE_TYPES,
5047
5816
  [userNodeTypes]
5048
5817
  );
5049
- const mergedEdgeTypes = useMemo10(
5818
+ const mergedEdgeTypes = useMemo13(
5050
5819
  () => userEdgeTypes ? { ...DEFAULT_EDGE_TYPES, ...userEdgeTypes } : DEFAULT_EDGE_TYPES,
5051
5820
  [userEdgeTypes]
5052
5821
  );
5053
5822
  const drill = useSubflowDrill(graph, onSubflowChange);
5054
- const groupedSet = useMemo10(() => new Set(groupedSubflows ?? []), [groupedSubflows]);
5055
- const filteredGraph = useMemo10(() => {
5823
+ const groupedSet = useMemo13(() => new Set(groupedSubflows ?? []), [groupedSubflows]);
5824
+ const filteredGraph = useMemo13(() => {
5056
5825
  const base = filterGraphForDrill(graph, drill.currentSubflowId);
5057
5826
  if (groupedSet.size === 0) return base;
5058
5827
  const baseIds = new Set(base.nodes.map((n) => n.id));
@@ -5067,12 +5836,12 @@ function TracedFlow({
5067
5836
  );
5068
5837
  return { nodes: [...base.nodes, ...extraNodes], edges: [...base.edges, ...extraEdges] };
5069
5838
  }, [graph, drill.currentSubflowId, groupedSet]);
5070
- const breadcrumb = useMemo10(
5839
+ const breadcrumb = useMemo13(
5071
5840
  () => buildSubflowBreadcrumb(graph, drill.currentSubflowId),
5072
5841
  [graph, drill.currentSubflowId]
5073
5842
  );
5074
- const [measuredSizes, setMeasuredSizes] = useState10(null);
5075
- const positioned = useMemo10(() => {
5843
+ const [measuredSizes, setMeasuredSizes] = useState11(null);
5844
+ const positioned = useMemo13(() => {
5076
5845
  const nodeSize = measuredSizes ? (n) => measuredSizes.get(n.id) : void 0;
5077
5846
  const sizeOpts = nodeSize ? { nodeSize } : {};
5078
5847
  const dagreBase = withForkCentering(
@@ -5096,7 +5865,7 @@ function TracedFlow({
5096
5865
  }
5097
5866
  return realBase(filteredGraph);
5098
5867
  }, [filteredGraph, layout, layoutProp, groupedSet, mainChartBox, measuredSizes]);
5099
- const slice = useMemo10(() => {
5868
+ const slice = useMemo13(() => {
5100
5869
  const empty = {
5101
5870
  doneStageIds: /* @__PURE__ */ new Set(),
5102
5871
  activeStageId: null,
@@ -5108,7 +5877,7 @@ function TracedFlow({
5108
5877
  const idx = scrubIndex ?? Math.max(0, overlay.executionOrder.length - 1);
5109
5878
  return aggregateMountStatus(sliceOverlay(overlay, idx), graph, drill.currentSubflowId);
5110
5879
  }, [overlay, scrubIndex, graph, drill.currentSubflowId]);
5111
- const reactFlowNodes = useMemo10(
5880
+ const reactFlowNodes = useMemo13(
5112
5881
  () => positioned.nodes.map(
5113
5882
  (n) => toStageNodeWithOverlay(
5114
5883
  n,
@@ -5121,20 +5890,20 @@ function TracedFlow({
5121
5890
  ),
5122
5891
  [positioned.nodes, slice, coActiveStageIds]
5123
5892
  );
5124
- const reactFlowEdges = useMemo10(
5893
+ const reactFlowEdges = useMemo13(
5125
5894
  () => positioned.edges.map(
5126
5895
  (e) => styleEdgeWithOverlay(e, slice.doneStageIds, slice.activeStageId, colors)
5127
5896
  ),
5128
5897
  [positioned.edges, slice, colors]
5129
5898
  );
5130
- const [coneRevealed, setConeRevealed] = useState10(false);
5899
+ const [coneRevealed, setConeRevealed] = useState11(false);
5131
5900
  useEffect10(() => {
5132
5901
  if (!sliceCone) return;
5133
5902
  setConeRevealed(false);
5134
5903
  const raf = requestAnimationFrame(() => setConeRevealed(true));
5135
5904
  return () => cancelAnimationFrame(raf);
5136
5905
  }, [sliceCone]);
5137
- const conedNodes = useMemo10(() => {
5906
+ const conedNodes = useMemo13(() => {
5138
5907
  if (!sliceCone || sliceCone.size === 0) return reactFlowNodes;
5139
5908
  return reactFlowNodes.map((n) => {
5140
5909
  const depth = sliceCone.get(n.id);
@@ -5152,7 +5921,7 @@ function TracedFlow({
5152
5921
  };
5153
5922
  });
5154
5923
  }, [reactFlowNodes, sliceCone, coneRevealed]);
5155
- const conedEdges = useMemo10(() => {
5924
+ const conedEdges = useMemo13(() => {
5156
5925
  if (!sliceCone || sliceCone.size === 0) return reactFlowEdges;
5157
5926
  return reactFlowEdges.map((e) => {
5158
5927
  const inCone = sliceCone.has(e.source) && sliceCone.has(e.target);
@@ -5170,13 +5939,13 @@ function TracedFlow({
5170
5939
  [drill, onNodeClick, groupedSet]
5171
5940
  );
5172
5941
  const wrapperRef = useRef8(null);
5173
- const [rfInstance, setRfInstance] = useState10(null);
5942
+ const [rfInstance, setRfInstance] = useState11(null);
5174
5943
  useChartAutoRefit(wrapperRef, rfInstance, {
5175
5944
  // Re-fit on drill AND after the measured-size re-layout settles.
5176
5945
  refitKey: `${drill.currentSubflowId ?? ""}:${measuredSizes ? "measured" : "estimated"}`,
5177
5946
  padding: 0.18
5178
5947
  });
5179
- return /* @__PURE__ */ jsxs18(
5948
+ return /* @__PURE__ */ jsxs20(
5180
5949
  "div",
5181
5950
  {
5182
5951
  ref: wrapperRef,
@@ -5190,14 +5959,14 @@ function TracedFlow({
5190
5959
  ...style
5191
5960
  },
5192
5961
  children: [
5193
- breadcrumb.length > 1 && /* @__PURE__ */ jsx21(
5962
+ breadcrumb.length > 1 && /* @__PURE__ */ jsx23(
5194
5963
  SubflowBreadcrumbBar,
5195
5964
  {
5196
5965
  entries: breadcrumb,
5197
5966
  onNavigate: drill.setCurrentSubflowId
5198
5967
  }
5199
5968
  ),
5200
- /* @__PURE__ */ jsx21("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsxs18(
5969
+ /* @__PURE__ */ jsx23("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsxs20(
5201
5970
  ReactFlow,
5202
5971
  {
5203
5972
  nodes: conedNodes,
@@ -5211,8 +5980,8 @@ function TracedFlow({
5211
5980
  minZoom: 0.1,
5212
5981
  proOptions: { hideAttribution: true },
5213
5982
  children: [
5214
- /* @__PURE__ */ jsx21(MeasuredNodeSizes, { onSizes: setMeasuredSizes }),
5215
- /* @__PURE__ */ jsx21(Background, { variant: BackgroundVariant.Dots, gap: 20, size: 1 }),
5983
+ /* @__PURE__ */ jsx23(MeasuredNodeSizes, { onSizes: setMeasuredSizes }),
5984
+ /* @__PURE__ */ jsx23(Background, { variant: BackgroundVariant.Dots, gap: 20, size: 1 }),
5216
5985
  children
5217
5986
  ]
5218
5987
  }
@@ -5223,187 +5992,27 @@ function TracedFlow({
5223
5992
  }
5224
5993
 
5225
5994
  // src/components/InspectorPanel/InspectorPanel.tsx
5226
- import { memo as memo5, useState as useState11 } from "react";
5227
-
5228
- // src/components/DataTracePanel/DataTracePanel.tsx
5229
- import { memo as memo4 } from "react";
5230
- import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
5231
- var DataTracePanel = memo4(function DataTracePanel2({
5232
- frames,
5233
- selectedStageId,
5234
- onFrameClick,
5235
- fromStageName,
5236
- note
5237
- }) {
5238
- const noteLine = note ? /* @__PURE__ */ jsx22("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", marginBottom: 8 }, children: note }) : null;
5239
- if (frames.length === 0) {
5240
- return /* @__PURE__ */ jsxs19("div", { style: { padding: "14px 14px 12px", fontSize: 13, lineHeight: 1.55 }, children: [
5241
- /* @__PURE__ */ jsx22(
5242
- "div",
5243
- {
5244
- style: {
5245
- fontSize: 11,
5246
- color: theme.textMuted,
5247
- textTransform: "uppercase",
5248
- letterSpacing: "0.5px",
5249
- fontWeight: 600,
5250
- marginBottom: 6
5251
- },
5252
- children: "Backward causal chain"
5253
- }
5254
- ),
5255
- /* @__PURE__ */ jsx22("div", { style: { color: theme.textSecondary, marginBottom: 10 }, children: "Trace any value back to the stage that created it \u2014 and everything upstream that influenced it." }),
5256
- noteLine,
5257
- /* @__PURE__ */ jsx22("div", { style: { color: theme.textMuted, fontSize: 12 }, children: "Select a stage above to see its dependency chain." })
5258
- ] });
5259
- }
5260
- return /* @__PURE__ */ jsxs19("div", { style: { padding: "8px 0", fontSize: 13 }, children: [
5261
- note && /* @__PURE__ */ jsx22("div", { style: { padding: "4px 12px 0", fontSize: 11, color: theme.textMuted, fontStyle: "italic" }, children: note }),
5262
- fromStageName && /* @__PURE__ */ jsxs19("div", { style: { padding: "4px 12px 8px" }, children: [
5263
- /* @__PURE__ */ jsxs19(
5264
- "div",
5265
- {
5266
- style: {
5267
- fontSize: 11,
5268
- color: theme.textMuted,
5269
- textTransform: "uppercase",
5270
- letterSpacing: "0.5px",
5271
- fontWeight: 600
5272
- },
5273
- children: [
5274
- "Data trace from ",
5275
- fromStageName
5276
- ]
5277
- }
5278
- ),
5279
- /* @__PURE__ */ jsx22(
5280
- "div",
5281
- {
5282
- style: {
5283
- fontSize: 11,
5284
- color: theme.textMuted,
5285
- fontStyle: "italic",
5286
- marginTop: 3
5287
- },
5288
- children: "Every value here was derived from the stages below."
5289
- }
5290
- )
5291
- ] }),
5292
- frames.map((frame, i) => /* @__PURE__ */ jsx22(
5293
- DataTraceFrame,
5294
- {
5295
- frame,
5296
- isFirst: i === 0,
5297
- isLast: i === frames.length - 1,
5298
- isSelected: frame.runtimeStageId === selectedStageId,
5299
- onClick: onFrameClick
5300
- },
5301
- frame.runtimeStageId
5302
- ))
5303
- ] });
5304
- });
5305
- var DataTraceFrame = memo4(function DataTraceFrame2({
5306
- frame,
5307
- isFirst,
5308
- isLast,
5309
- isSelected,
5310
- onClick
5311
- }) {
5312
- return /* @__PURE__ */ jsxs19(
5313
- "button",
5314
- {
5315
- onClick: () => onClick?.(frame.runtimeStageId),
5316
- style: {
5317
- display: "block",
5318
- width: "100%",
5319
- textAlign: "left",
5320
- border: "none",
5321
- background: isSelected ? "var(--fp-accent-bg, rgba(99,102,241,0.12))" : "transparent",
5322
- padding: "6px 12px 6px 16px",
5323
- cursor: onClick ? "pointer" : "default",
5324
- borderLeft: isSelected ? "3px solid var(--fp-accent, #6366f1)" : "3px solid transparent",
5325
- color: "inherit",
5326
- fontSize: 13
5327
- },
5328
- children: [
5329
- /* @__PURE__ */ jsxs19("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
5330
- !isFirst && /* @__PURE__ */ jsx22("span", { style: { color: theme.textMuted, fontSize: 11 }, children: "\u2191" }),
5331
- /* @__PURE__ */ jsx22(
5332
- "span",
5333
- {
5334
- style: {
5335
- fontWeight: isFirst ? 600 : 400,
5336
- color: isFirst ? "var(--fp-accent, #6366f1)" : theme.textPrimary
5337
- },
5338
- children: frame.stageName
5339
- }
5340
- ),
5341
- isLast && !isFirst && /* @__PURE__ */ jsx22(
5342
- "span",
5343
- {
5344
- style: {
5345
- fontSize: 10,
5346
- color: theme.textMuted,
5347
- fontStyle: "italic"
5348
- },
5349
- children: "(origin)"
5350
- }
5351
- )
5352
- ] }),
5353
- frame.keysWritten.length > 0 && /* @__PURE__ */ jsxs19(
5354
- "div",
5355
- {
5356
- style: {
5357
- fontSize: 11,
5358
- color: theme.textMuted,
5359
- paddingLeft: isFirst ? 0 : 18,
5360
- marginTop: 2
5361
- },
5362
- children: [
5363
- "wrote:",
5364
- " ",
5365
- /* @__PURE__ */ jsx22("span", { style: { color: theme.textSecondary }, children: frame.keysWritten.join(", ") })
5366
- ]
5367
- }
5368
- ),
5369
- frame.linkedBy && /* @__PURE__ */ jsxs19(
5370
- "div",
5371
- {
5372
- style: {
5373
- fontSize: 11,
5374
- color: "var(--fp-accent, #6366f1)",
5375
- paddingLeft: 18,
5376
- marginTop: 1
5377
- },
5378
- children: [
5379
- "\u2190 via ",
5380
- frame.linkedBy
5381
- ]
5382
- }
5383
- )
5384
- ]
5385
- }
5386
- );
5387
- });
5388
-
5389
- // src/components/InspectorPanel/InspectorPanel.tsx
5390
- import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
5391
- var InspectorPanel = memo5(function InspectorPanel2({
5995
+ import { memo as memo6, useState as useState12 } from "react";
5996
+ import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
5997
+ var InspectorPanel = memo6(function InspectorPanel2({
5392
5998
  snapshots,
5393
5999
  selectedIndex,
5394
6000
  dataTraceFrames,
5395
6001
  dataTraceNote,
5396
6002
  selectedStageId,
5397
6003
  onNavigateToStage,
5398
- onTabChange
6004
+ onTabChange,
6005
+ tab: controlledTab,
6006
+ traceContent
5399
6007
  }) {
5400
- const [tab, setTabState] = useState11("state");
6008
+ const [internalTab, setTabState] = useState12("state");
6009
+ const tab = controlledTab ?? internalTab;
5401
6010
  const setTab = (t) => {
5402
6011
  setTabState(t);
5403
6012
  onTabChange?.(t);
5404
6013
  };
5405
6014
  const currentSnapshot = snapshots[selectedIndex];
5406
- return /* @__PURE__ */ jsxs20(
6015
+ return /* @__PURE__ */ jsxs21(
5407
6016
  "div",
5408
6017
  {
5409
6018
  style: {
@@ -5413,7 +6022,7 @@ var InspectorPanel = memo5(function InspectorPanel2({
5413
6022
  overflow: "hidden"
5414
6023
  },
5415
6024
  children: [
5416
- /* @__PURE__ */ jsxs20(
6025
+ /* @__PURE__ */ jsxs21(
5417
6026
  "div",
5418
6027
  {
5419
6028
  style: {
@@ -5422,7 +6031,7 @@ var InspectorPanel = memo5(function InspectorPanel2({
5422
6031
  flexShrink: 0
5423
6032
  },
5424
6033
  children: [
5425
- /* @__PURE__ */ jsx23(
6034
+ /* @__PURE__ */ jsx24(
5426
6035
  TabButton,
5427
6036
  {
5428
6037
  active: tab === "state",
@@ -5430,7 +6039,7 @@ var InspectorPanel = memo5(function InspectorPanel2({
5430
6039
  label: "State"
5431
6040
  }
5432
6041
  ),
5433
- /* @__PURE__ */ jsx23(
6042
+ /* @__PURE__ */ jsx24(
5434
6043
  TabButton,
5435
6044
  {
5436
6045
  active: tab === "trace",
@@ -5442,15 +6051,15 @@ var InspectorPanel = memo5(function InspectorPanel2({
5442
6051
  ]
5443
6052
  }
5444
6053
  ),
5445
- /* @__PURE__ */ jsxs20("div", { style: { flex: 1, overflow: "auto" }, children: [
5446
- tab === "state" && /* @__PURE__ */ jsx23(
6054
+ /* @__PURE__ */ jsxs21("div", { style: { flex: 1, overflow: "auto" }, children: [
6055
+ tab === "state" && /* @__PURE__ */ jsx24(
5447
6056
  MemoryPanel,
5448
6057
  {
5449
6058
  snapshots,
5450
6059
  selectedIndex
5451
6060
  }
5452
6061
  ),
5453
- tab === "trace" && /* @__PURE__ */ jsx23(
6062
+ tab === "trace" && (traceContent ?? /* @__PURE__ */ jsx24(
5454
6063
  DataTracePanel,
5455
6064
  {
5456
6065
  frames: dataTraceFrames,
@@ -5459,7 +6068,7 @@ var InspectorPanel = memo5(function InspectorPanel2({
5459
6068
  onFrameClick: onNavigateToStage,
5460
6069
  fromStageName: currentSnapshot?.stageName
5461
6070
  }
5462
- )
6071
+ ))
5463
6072
  ] })
5464
6073
  ]
5465
6074
  }
@@ -5471,7 +6080,7 @@ function TabButton({
5471
6080
  label,
5472
6081
  badge
5473
6082
  }) {
5474
- return /* @__PURE__ */ jsxs20(
6083
+ return /* @__PURE__ */ jsxs21(
5475
6084
  "button",
5476
6085
  {
5477
6086
  onClick,
@@ -5490,7 +6099,7 @@ function TabButton({
5490
6099
  },
5491
6100
  children: [
5492
6101
  label,
5493
- badge && /* @__PURE__ */ jsx23(
6102
+ badge && /* @__PURE__ */ jsx24(
5494
6103
  "span",
5495
6104
  {
5496
6105
  style: {
@@ -5510,28 +6119,28 @@ function TabButton({
5510
6119
  }
5511
6120
 
5512
6121
  // src/components/InsightPanel/InsightPanel.tsx
5513
- import { memo as memo6, useState as useState12 } from "react";
5514
- import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
5515
- var InsightPanel = memo6(function InsightPanel2({
6122
+ import { memo as memo7, useState as useState13 } from "react";
6123
+ import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
6124
+ var InsightPanel = memo7(function InsightPanel2({
5516
6125
  insights,
5517
6126
  expandedId,
5518
6127
  mode
5519
6128
  }) {
5520
6129
  if (insights.length === 0) {
5521
- return /* @__PURE__ */ jsx24("div", { style: { padding: 12, color: theme.textMuted, fontSize: 13 }, children: "No insights available. Attach recorders to see data." });
6130
+ return /* @__PURE__ */ jsx25("div", { style: { padding: 12, color: theme.textMuted, fontSize: 13 }, children: "No insights available. Attach recorders to see data." });
5522
6131
  }
5523
6132
  if (mode === "grid") {
5524
- return /* @__PURE__ */ jsx24(InsightGrid, { insights });
6133
+ return /* @__PURE__ */ jsx25(InsightGrid, { insights });
5525
6134
  }
5526
- return /* @__PURE__ */ jsx24(InsightTabs, { insights, defaultId: expandedId });
6135
+ return /* @__PURE__ */ jsx25(InsightTabs, { insights, defaultId: expandedId });
5527
6136
  });
5528
- var InsightTabs = memo6(function InsightTabs2({
6137
+ var InsightTabs = memo7(function InsightTabs2({
5529
6138
  insights,
5530
6139
  defaultId
5531
6140
  }) {
5532
- const [activeId, setActiveId] = useState12(defaultId ?? insights[0]?.id);
6141
+ const [activeId, setActiveId] = useState13(defaultId ?? insights[0]?.id);
5533
6142
  const active = insights.find((i) => i.id === activeId) ?? insights[0];
5534
- return /* @__PURE__ */ jsxs21(
6143
+ return /* @__PURE__ */ jsxs22(
5535
6144
  "div",
5536
6145
  {
5537
6146
  style: {
@@ -5541,7 +6150,7 @@ var InsightTabs = memo6(function InsightTabs2({
5541
6150
  overflow: "hidden"
5542
6151
  },
5543
6152
  children: [
5544
- /* @__PURE__ */ jsx24(
6153
+ /* @__PURE__ */ jsx25(
5545
6154
  "div",
5546
6155
  {
5547
6156
  style: {
@@ -5550,7 +6159,7 @@ var InsightTabs = memo6(function InsightTabs2({
5550
6159
  flexShrink: 0,
5551
6160
  overflowX: "auto"
5552
6161
  },
5553
- children: insights.map((insight) => /* @__PURE__ */ jsx24(
6162
+ children: insights.map((insight) => /* @__PURE__ */ jsx25(
5554
6163
  "button",
5555
6164
  {
5556
6165
  onClick: () => setActiveId(insight.id),
@@ -5571,16 +6180,16 @@ var InsightTabs = memo6(function InsightTabs2({
5571
6180
  ))
5572
6181
  }
5573
6182
  ),
5574
- /* @__PURE__ */ jsx24("div", { style: { flex: 1, overflow: "auto" }, children: active?.render() })
6183
+ /* @__PURE__ */ jsx25("div", { style: { flex: 1, overflow: "auto" }, children: active?.render() })
5575
6184
  ]
5576
6185
  }
5577
6186
  );
5578
6187
  });
5579
- var InsightGrid = memo6(function InsightGrid2({
6188
+ var InsightGrid = memo7(function InsightGrid2({
5580
6189
  insights
5581
6190
  }) {
5582
6191
  const cols = insights.length <= 2 ? 1 : 2;
5583
- return /* @__PURE__ */ jsx24(
6192
+ return /* @__PURE__ */ jsx25(
5584
6193
  "div",
5585
6194
  {
5586
6195
  style: {
@@ -5591,7 +6200,7 @@ var InsightGrid = memo6(function InsightGrid2({
5591
6200
  gap: 1,
5592
6201
  background: theme.border
5593
6202
  },
5594
- children: insights.map((insight) => /* @__PURE__ */ jsxs21(
6203
+ children: insights.map((insight) => /* @__PURE__ */ jsxs22(
5595
6204
  "div",
5596
6205
  {
5597
6206
  style: {
@@ -5601,7 +6210,7 @@ var InsightGrid = memo6(function InsightGrid2({
5601
6210
  overflow: "hidden"
5602
6211
  },
5603
6212
  children: [
5604
- /* @__PURE__ */ jsxs21(
6213
+ /* @__PURE__ */ jsxs22(
5605
6214
  "div",
5606
6215
  {
5607
6216
  style: {
@@ -5616,7 +6225,7 @@ var InsightGrid = memo6(function InsightGrid2({
5616
6225
  },
5617
6226
  children: [
5618
6227
  insight.name,
5619
- insight.summary && /* @__PURE__ */ jsx24(
6228
+ insight.summary && /* @__PURE__ */ jsx25(
5620
6229
  "span",
5621
6230
  {
5622
6231
  style: {
@@ -5631,7 +6240,7 @@ var InsightGrid = memo6(function InsightGrid2({
5631
6240
  ]
5632
6241
  }
5633
6242
  ),
5634
- /* @__PURE__ */ jsx24("div", { style: { flex: 1, overflow: "auto" }, children: insight.render() })
6243
+ /* @__PURE__ */ jsx25("div", { style: { flex: 1, overflow: "auto" }, children: insight.render() })
5635
6244
  ]
5636
6245
  },
5637
6246
  insight.id
@@ -5641,17 +6250,17 @@ var InsightGrid = memo6(function InsightGrid2({
5641
6250
  });
5642
6251
 
5643
6252
  // src/components/CompactTimeline/CompactTimeline.tsx
5644
- import { memo as memo7, useState as useState13 } from "react";
5645
- import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
5646
- var CompactTimeline = memo7(function CompactTimeline2({
6253
+ import { memo as memo8, useState as useState14 } from "react";
6254
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
6255
+ var CompactTimeline = memo8(function CompactTimeline2({
5647
6256
  snapshots,
5648
6257
  selectedIndex,
5649
6258
  defaultExpanded = false
5650
6259
  }) {
5651
- const [expanded, setExpanded] = useState13(defaultExpanded);
6260
+ const [expanded, setExpanded] = useState14(defaultExpanded);
5652
6261
  if (snapshots.length === 0) return null;
5653
- return /* @__PURE__ */ jsxs22("div", { style: { borderTop: `1px solid ${theme.border}` }, children: [
5654
- /* @__PURE__ */ jsxs22(
6262
+ return /* @__PURE__ */ jsxs23("div", { style: { borderTop: `1px solid ${theme.border}` }, children: [
6263
+ /* @__PURE__ */ jsxs23(
5655
6264
  "button",
5656
6265
  {
5657
6266
  onClick: () => setExpanded((e) => !e),
@@ -5671,13 +6280,13 @@ var CompactTimeline = memo7(function CompactTimeline2({
5671
6280
  letterSpacing: "0.5px"
5672
6281
  },
5673
6282
  children: [
5674
- /* @__PURE__ */ jsx25("span", { style: { fontSize: 10 }, children: expanded ? "\u25BC" : "\u25B8" }),
6283
+ /* @__PURE__ */ jsx26("span", { style: { fontSize: 10 }, children: expanded ? "\u25BC" : "\u25B8" }),
5675
6284
  "Timeline",
5676
- /* @__PURE__ */ jsxs22("span", { style: { fontWeight: 400, fontSize: 10 }, children: [
6285
+ /* @__PURE__ */ jsxs23("span", { style: { fontWeight: 400, fontSize: 10 }, children: [
5677
6286
  snapshots.length,
5678
6287
  " stages"
5679
6288
  ] }),
5680
- !expanded && /* @__PURE__ */ jsxs22(
6289
+ !expanded && /* @__PURE__ */ jsxs23(
5681
6290
  "div",
5682
6291
  {
5683
6292
  style: {
@@ -5688,7 +6297,7 @@ var CompactTimeline = memo7(function CompactTimeline2({
5688
6297
  marginLeft: 8
5689
6298
  },
5690
6299
  children: [
5691
- snapshots.map((snap, i) => /* @__PURE__ */ jsx25(
6300
+ snapshots.map((snap, i) => /* @__PURE__ */ jsx26(
5692
6301
  "div",
5693
6302
  {
5694
6303
  style: {
@@ -5703,7 +6312,7 @@ var CompactTimeline = memo7(function CompactTimeline2({
5703
6312
  },
5704
6313
  i
5705
6314
  )),
5706
- /* @__PURE__ */ jsx25(
6315
+ /* @__PURE__ */ jsx26(
5707
6316
  "div",
5708
6317
  {
5709
6318
  style: {
@@ -5721,7 +6330,7 @@ var CompactTimeline = memo7(function CompactTimeline2({
5721
6330
  ]
5722
6331
  }
5723
6332
  ),
5724
- expanded && /* @__PURE__ */ jsx25("div", { style: { padding: "0 12px 8px" }, children: /* @__PURE__ */ jsx25(
6333
+ expanded && /* @__PURE__ */ jsx26("div", { style: { padding: "0 12px 8px" }, children: /* @__PURE__ */ jsx26(
5725
6334
  GanttTimeline,
5726
6335
  {
5727
6336
  snapshots,
@@ -5732,21 +6341,21 @@ var CompactTimeline = memo7(function CompactTimeline2({
5732
6341
  });
5733
6342
 
5734
6343
  // src/components/ExplainableShell/ExplainableShell.tsx
5735
- import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
5736
- var HLinePill = memo8(function HLinePill2({
6344
+ import { Fragment as Fragment8, jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
6345
+ var HLinePill = memo9(function HLinePill2({
5737
6346
  label,
5738
6347
  detail,
5739
6348
  expanded,
5740
6349
  onClick
5741
6350
  }) {
5742
- return /* @__PURE__ */ jsxs23("div", { style: {
6351
+ return /* @__PURE__ */ jsxs24("div", { style: {
5743
6352
  display: "flex",
5744
6353
  alignItems: "center",
5745
6354
  gap: 0,
5746
6355
  padding: "0"
5747
6356
  }, children: [
5748
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, height: 1, background: theme.border } }),
5749
- /* @__PURE__ */ jsxs23(
6357
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, height: 1, background: theme.border } }),
6358
+ /* @__PURE__ */ jsxs24(
5750
6359
  "button",
5751
6360
  {
5752
6361
  onClick,
@@ -5770,31 +6379,31 @@ var HLinePill = memo8(function HLinePill2({
5770
6379
  transition: "color 0.15s ease"
5771
6380
  },
5772
6381
  children: [
5773
- /* @__PURE__ */ jsx26("span", { style: { fontSize: 7 }, children: expanded ? "\u25BC" : "\u25B6" }),
6382
+ /* @__PURE__ */ jsx27("span", { style: { fontSize: 7 }, children: expanded ? "\u25BC" : "\u25B6" }),
5774
6383
  label,
5775
- detail && /* @__PURE__ */ jsx26("span", { style: { fontWeight: 400, opacity: 0.5, fontSize: 9 }, children: detail })
6384
+ detail && /* @__PURE__ */ jsx27("span", { style: { fontWeight: 400, opacity: 0.5, fontSize: 9 }, children: detail })
5776
6385
  ]
5777
6386
  }
5778
6387
  ),
5779
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, height: 1, background: theme.border } })
6388
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, height: 1, background: theme.border } })
5780
6389
  ] });
5781
6390
  });
5782
- var VLinePill = memo8(function VLinePill2({
6391
+ var VLinePill = memo9(function VLinePill2({
5783
6392
  label,
5784
6393
  expanded,
5785
6394
  side = "right",
5786
6395
  onClick
5787
6396
  }) {
5788
6397
  const arrow = side === "right" ? expanded ? "\u25B6" : "\u25C0" : expanded ? "\u25C0" : "\u25B6";
5789
- return /* @__PURE__ */ jsxs23("div", { style: {
6398
+ return /* @__PURE__ */ jsxs24("div", { style: {
5790
6399
  display: "flex",
5791
6400
  flexDirection: "column",
5792
6401
  alignItems: "center",
5793
6402
  gap: 0,
5794
6403
  padding: "0"
5795
6404
  }, children: [
5796
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, width: 1, background: theme.border } }),
5797
- /* @__PURE__ */ jsxs23(
6405
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, width: 1, background: theme.border } }),
6406
+ /* @__PURE__ */ jsxs24(
5798
6407
  "button",
5799
6408
  {
5800
6409
  onClick,
@@ -5819,12 +6428,12 @@ var VLinePill = memo8(function VLinePill2({
5819
6428
  transition: "color 0.15s ease"
5820
6429
  },
5821
6430
  children: [
5822
- /* @__PURE__ */ jsx26("span", { style: { fontSize: 7, writingMode: "horizontal-tb" }, children: arrow }),
6431
+ /* @__PURE__ */ jsx27("span", { style: { fontSize: 7, writingMode: "horizontal-tb" }, children: arrow }),
5823
6432
  label
5824
6433
  ]
5825
6434
  }
5826
6435
  ),
5827
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, width: 1, background: theme.border } })
6436
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, width: 1, background: theme.border } })
5828
6437
  ] });
5829
6438
  });
5830
6439
  function detectKeyedSteps(data) {
@@ -5861,9 +6470,9 @@ function KeyedRecorderView({
5861
6470
  snapshots,
5862
6471
  selectedIndex
5863
6472
  }) {
5864
- const [showAggregate, setShowAggregate] = useState14(false);
5865
- const detected = useMemo12(() => detectKeyedSteps(data), [data]);
5866
- const visibleKeys = useMemo12(() => {
6473
+ const [showAggregate, setShowAggregate] = useState15(false);
6474
+ const detected = useMemo14(() => detectKeyedSteps(data), [data]);
6475
+ const visibleKeys = useMemo14(() => {
5867
6476
  const keys = /* @__PURE__ */ new Set();
5868
6477
  for (let i = 0; i <= selectedIndex && i < snapshots.length; i++) {
5869
6478
  const snap = snapshots[i];
@@ -5878,7 +6487,7 @@ function KeyedRecorderView({
5878
6487
  }, [snapshots, selectedIndex, detected?.keyType]);
5879
6488
  const isAtEnd = selectedIndex >= snapshots.length - 1;
5880
6489
  if (!detected) {
5881
- return /* @__PURE__ */ jsx26("div", { style: { padding: 12, fontFamily: theme.fontMono, fontSize: 11, whiteSpace: "pre-wrap", overflow: "auto", height: "100%" }, children: typeof data === "string" ? data : JSON.stringify(data, null, 2) });
6490
+ return /* @__PURE__ */ jsx27("div", { style: { padding: 12, fontFamily: theme.fontMono, fontSize: 11, whiteSpace: "pre-wrap", overflow: "auto", height: "100%" }, children: typeof data === "string" ? data : JSON.stringify(data, null, 2) });
5882
6491
  }
5883
6492
  const steps = detected.steps;
5884
6493
  const hints = extractRenderHints(data);
@@ -5892,13 +6501,13 @@ function KeyedRecorderView({
5892
6501
  }
5893
6502
  }
5894
6503
  const grandTotal = hints?.grandTotal ?? 0;
5895
- return /* @__PURE__ */ jsxs23("div", { style: { overflow: "auto", height: "100%", display: "flex", flexDirection: "column" }, children: [
5896
- description && /* @__PURE__ */ jsx26("div", { style: { padding: "6px 12px", fontSize: 11, color: theme.textMuted, fontStyle: "italic", borderBottom: `1px solid ${theme.border}`, flexShrink: 0 }, children: description }),
5897
- /* @__PURE__ */ jsxs23("div", { style: { padding: 12, flex: 1, overflow: "auto" }, children: [
6504
+ return /* @__PURE__ */ jsxs24("div", { style: { overflow: "auto", height: "100%", display: "flex", flexDirection: "column" }, children: [
6505
+ description && /* @__PURE__ */ jsx27("div", { style: { padding: "6px 12px", fontSize: 11, color: theme.textMuted, fontStyle: "italic", borderBottom: `1px solid ${theme.border}`, flexShrink: 0 }, children: description }),
6506
+ /* @__PURE__ */ jsxs24("div", { style: { padding: 12, flex: 1, overflow: "auto" }, children: [
5898
6507
  preferredOperation === "aggregate" ? (
5899
6508
  /* AGGREGATE: collect silently during scrub, button at end to reveal total */
5900
- /* @__PURE__ */ jsxs23(Fragment6, { children: [
5901
- isAtEnd ? /* @__PURE__ */ jsx26("div", { style: { marginBottom: 16 }, children: !showAggregate ? /* @__PURE__ */ jsx26(
6509
+ /* @__PURE__ */ jsxs24(Fragment8, { children: [
6510
+ isAtEnd ? /* @__PURE__ */ jsx27("div", { style: { marginBottom: 16 }, children: !showAggregate ? /* @__PURE__ */ jsx27(
5902
6511
  "button",
5903
6512
  {
5904
6513
  onClick: () => setShowAggregate(true),
@@ -5916,35 +6525,35 @@ function KeyedRecorderView({
5916
6525
  },
5917
6526
  children: "Aggregate \u2014 Show Grand Total"
5918
6527
  }
5919
- ) : /* @__PURE__ */ jsxs23("div", { style: { padding: "14px 16px", background: `color-mix(in srgb, ${theme.success} 12%, transparent)`, borderRadius: 8, border: `1px solid ${theme.success}44` }, children: [
5920
- /* @__PURE__ */ jsx26("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Aggregate \u2014 grand total" }),
5921
- numFieldKey && /* @__PURE__ */ jsxs23("div", { style: { fontSize: 26, fontWeight: 700, color: theme.success }, children: [
6528
+ ) : /* @__PURE__ */ jsxs24("div", { style: { padding: "14px 16px", background: `color-mix(in srgb, ${theme.success} 12%, transparent)`, borderRadius: 8, border: `1px solid ${theme.success}44` }, children: [
6529
+ /* @__PURE__ */ jsx27("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Aggregate \u2014 grand total" }),
6530
+ numFieldKey && /* @__PURE__ */ jsxs24("div", { style: { fontSize: 26, fontWeight: 700, color: theme.success }, children: [
5922
6531
  grandTotal < 1 ? grandTotal.toFixed(3) : grandTotal.toFixed(1),
5923
- /* @__PURE__ */ jsxs23("span", { style: { fontSize: 11, color: theme.textMuted, fontWeight: 400, marginLeft: 8 }, children: [
6532
+ /* @__PURE__ */ jsxs24("span", { style: { fontSize: 11, color: theme.textMuted, fontWeight: 400, marginLeft: 8 }, children: [
5924
6533
  numFieldKey,
5925
6534
  " \xB7 ",
5926
6535
  allKeys.length,
5927
6536
  " steps"
5928
6537
  ] })
5929
6538
  ] })
5930
- ] }) }) : /* @__PURE__ */ jsxs23("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.textMuted} 6%, transparent)`, borderRadius: 6, marginBottom: 16, border: `1px dashed ${theme.border}` }, children: [
5931
- /* @__PURE__ */ jsx26("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", fontWeight: 600 }, children: "Collecting data..." }),
5932
- /* @__PURE__ */ jsxs23("div", { style: { fontSize: 11, color: theme.textMuted, marginTop: 4 }, children: [
6539
+ ] }) }) : /* @__PURE__ */ jsxs24("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.textMuted} 6%, transparent)`, borderRadius: 6, marginBottom: 16, border: `1px dashed ${theme.border}` }, children: [
6540
+ /* @__PURE__ */ jsx27("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", fontWeight: 600 }, children: "Collecting data..." }),
6541
+ /* @__PURE__ */ jsxs24("div", { style: { fontSize: 11, color: theme.textMuted, marginTop: 4 }, children: [
5933
6542
  visibleEntries.length,
5934
6543
  " of ",
5935
6544
  allKeys.length,
5936
6545
  " steps collected. Scrub to end to aggregate."
5937
6546
  ] })
5938
6547
  ] }),
5939
- /* @__PURE__ */ jsx26("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
6548
+ /* @__PURE__ */ jsx27("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
5940
6549
  ] })
5941
6550
  ) : preferredOperation === "accumulate" ? (
5942
6551
  /* ACCUMULATE: running total grows with slider — IS the total at end, no button */
5943
- /* @__PURE__ */ jsxs23(Fragment6, { children: [
5944
- numFieldKey && visibleEntries.length > 0 && /* @__PURE__ */ jsxs23("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.primary} 8%, transparent)`, borderRadius: 6, marginBottom: 16 }, children: [
5945
- /* @__PURE__ */ jsx26("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 4, fontWeight: 600 }, children: "Accumulate \u2014 running total up to this step" }),
5946
- /* @__PURE__ */ jsx26("span", { style: { fontWeight: 700, fontSize: 18, color: theme.primary }, children: runningTotal < 1 ? runningTotal.toFixed(3) : runningTotal.toFixed(1) }),
5947
- /* @__PURE__ */ jsxs23("span", { style: { color: theme.textMuted, marginLeft: 8, fontSize: 10 }, children: [
6552
+ /* @__PURE__ */ jsxs24(Fragment8, { children: [
6553
+ numFieldKey && visibleEntries.length > 0 && /* @__PURE__ */ jsxs24("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.primary} 8%, transparent)`, borderRadius: 6, marginBottom: 16 }, children: [
6554
+ /* @__PURE__ */ jsx27("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 4, fontWeight: 600 }, children: "Accumulate \u2014 running total up to this step" }),
6555
+ /* @__PURE__ */ jsx27("span", { style: { fontWeight: 700, fontSize: 18, color: theme.primary }, children: runningTotal < 1 ? runningTotal.toFixed(3) : runningTotal.toFixed(1) }),
6556
+ /* @__PURE__ */ jsxs24("span", { style: { color: theme.textMuted, marginLeft: 8, fontSize: 10 }, children: [
5948
6557
  numFieldKey,
5949
6558
  " \xB7 ",
5950
6559
  visibleEntries.length,
@@ -5953,27 +6562,27 @@ function KeyedRecorderView({
5953
6562
  " steps"
5954
6563
  ] })
5955
6564
  ] }),
5956
- /* @__PURE__ */ jsx26("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
6565
+ /* @__PURE__ */ jsx27("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
5957
6566
  ] })
5958
6567
  ) : (
5959
6568
  /* TRANSLATE: per-step entries prominent, no totals */
5960
- /* @__PURE__ */ jsx26("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Translate \u2014 per-step detail" })
6569
+ /* @__PURE__ */ jsx27("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Translate \u2014 per-step detail" })
5961
6570
  ),
5962
6571
  visibleEntries.map((key) => {
5963
6572
  const entry = steps[key];
5964
6573
  const label = entry.stageName ?? key;
5965
6574
  const numVal = numFieldKey ? entry[numFieldKey] : void 0;
5966
- return /* @__PURE__ */ jsxs23("div", { style: { display: "flex", alignItems: "center", padding: "4px 0", fontSize: 12, fontFamily: theme.fontMono, borderBottom: `1px solid ${theme.border}22` }, children: [
5967
- /* @__PURE__ */ jsx26("span", { style: { color: theme.textMuted, width: 140, flexShrink: 0, fontSize: 10 }, children: key }),
5968
- /* @__PURE__ */ jsx26("span", { style: { fontWeight: 600, flex: 1 }, children: label }),
5969
- numVal !== void 0 && /* @__PURE__ */ jsx26("span", { style: { color: theme.primary, fontWeight: 700, marginLeft: 8 }, children: numVal < 1 ? numVal.toFixed(3) : numVal.toFixed(1) })
6575
+ return /* @__PURE__ */ jsxs24("div", { style: { display: "flex", alignItems: "center", padding: "4px 0", fontSize: 12, fontFamily: theme.fontMono, borderBottom: `1px solid ${theme.border}22` }, children: [
6576
+ /* @__PURE__ */ jsx27("span", { style: { color: theme.textMuted, width: 140, flexShrink: 0, fontSize: 10 }, children: key }),
6577
+ /* @__PURE__ */ jsx27("span", { style: { fontWeight: 600, flex: 1 }, children: label }),
6578
+ numVal !== void 0 && /* @__PURE__ */ jsx27("span", { style: { color: theme.primary, fontWeight: 700, marginLeft: 8 }, children: numVal < 1 ? numVal.toFixed(3) : numVal.toFixed(1) })
5970
6579
  ] }, key);
5971
6580
  }),
5972
- visibleEntries.length === 0 && /* @__PURE__ */ jsx26("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", padding: "8px 0" }, children: "Scrub the slider to reveal entries..." })
6581
+ visibleEntries.length === 0 && /* @__PURE__ */ jsx27("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", padding: "8px 0" }, children: "Scrub the slider to reveal entries..." })
5973
6582
  ] })
5974
6583
  ] });
5975
6584
  }
5976
- var DetailsContent = memo8(function DetailsContent2({
6585
+ var DetailsContent = memo9(function DetailsContent2({
5977
6586
  snapshots,
5978
6587
  selectedIndex,
5979
6588
  narrativeEntries,
@@ -5985,16 +6594,16 @@ var DetailsContent = memo8(function DetailsContent2({
5985
6594
  {
5986
6595
  id: "memory",
5987
6596
  name: "Memory",
5988
- render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ jsx26(MemoryPanel, { snapshots: snaps, selectedIndex: idx, size, style: fillHeight ? { height: "100%" } : void 0 })
6597
+ render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ jsx27(MemoryPanel, { snapshots: snaps, selectedIndex: idx, size, style: fillHeight ? { height: "100%" } : void 0 })
5989
6598
  },
5990
6599
  {
5991
6600
  id: "narrative",
5992
6601
  name: "Narrative",
5993
- render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ jsx26(NarrativePanel, { snapshots: snaps, selectedIndex: idx, narrativeEntries, size, style: fillHeight ? { height: "100%" } : void 0 })
6602
+ render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ jsx27(NarrativePanel, { snapshots: snaps, selectedIndex: idx, narrativeEntries, size, style: fillHeight ? { height: "100%" } : void 0 })
5994
6603
  }
5995
6604
  ];
5996
6605
  const allViews = [...builtInViews, ...extraViews ?? []];
5997
- const [activeViewId, setActiveViewId] = useState14(allViews[0]?.id ?? "memory");
6606
+ const [activeViewId, setActiveViewId] = useState15(allViews[0]?.id ?? "memory");
5998
6607
  const viewIds = allViews.map((v2) => v2.id).join(",");
5999
6608
  useEffect11(() => {
6000
6609
  if (!allViews.find((v2) => v2.id === activeViewId)) {
@@ -6002,10 +6611,10 @@ var DetailsContent = memo8(function DetailsContent2({
6002
6611
  }
6003
6612
  }, [viewIds]);
6004
6613
  const activeView = allViews.find((v2) => v2.id === activeViewId) ?? allViews[0];
6005
- return /* @__PURE__ */ jsxs23("div", { style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }, children: [
6006
- /* @__PURE__ */ jsx26("div", { style: { display: "flex", borderBottom: `1px solid ${theme.border}`, flexShrink: 0, overflowX: "auto" }, children: allViews.map((view) => {
6614
+ return /* @__PURE__ */ jsxs24("div", { style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }, children: [
6615
+ /* @__PURE__ */ jsx27("div", { style: { display: "flex", borderBottom: `1px solid ${theme.border}`, flexShrink: 0, overflowX: "auto" }, children: allViews.map((view) => {
6007
6616
  const active = view.id === activeViewId;
6008
- return /* @__PURE__ */ jsx26(
6617
+ return /* @__PURE__ */ jsx27(
6009
6618
  "button",
6010
6619
  {
6011
6620
  onClick: () => setActiveViewId(view.id),
@@ -6029,7 +6638,7 @@ var DetailsContent = memo8(function DetailsContent2({
6029
6638
  view.id
6030
6639
  );
6031
6640
  }) }),
6032
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, overflow: "auto" }, children: activeView?.render({ snapshots, selectedIndex }) })
6641
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, overflow: "auto" }, children: activeView?.render({ snapshots, selectedIndex }) })
6033
6642
  ] });
6034
6643
  });
6035
6644
  function resolveSubflowFromRuntime(parentSnapshots, subflowId, narrativeEntries) {
@@ -6046,7 +6655,7 @@ function resolveSubflowFromRuntime(parentSnapshots, subflowId, narrativeEntries)
6046
6655
  if (sfSnapshots.length === 0) return null;
6047
6656
  return { subflowId, label, spec: null, snapshots: sfSnapshots, narrative: sfNarrative };
6048
6657
  }
6049
- var RightPanel = memo8(function RightPanel2({
6658
+ var RightPanel = memo9(function RightPanel2({
6050
6659
  mode,
6051
6660
  onModeChange,
6052
6661
  snapshots,
@@ -6060,15 +6669,17 @@ var RightPanel = memo8(function RightPanel2({
6060
6669
  size,
6061
6670
  onNavigateToStage,
6062
6671
  dataTrace,
6063
- onInspectorTabChange
6672
+ onInspectorTabChange,
6673
+ inspectorTab,
6674
+ traceContent
6064
6675
  }) {
6065
- return /* @__PURE__ */ jsxs23(Fragment6, { children: [
6066
- /* @__PURE__ */ jsx26("div", { style: {
6676
+ return /* @__PURE__ */ jsxs24(Fragment8, { children: [
6677
+ /* @__PURE__ */ jsx27("div", { style: {
6067
6678
  display: "flex",
6068
6679
  borderBottom: `1px solid ${theme.border}`,
6069
6680
  flexShrink: 0,
6070
6681
  background: theme.bgSecondary
6071
- }, children: ["insights", "what"].map((m) => /* @__PURE__ */ jsx26(
6682
+ }, children: ["insights", "what"].map((m) => /* @__PURE__ */ jsx27(
6072
6683
  "button",
6073
6684
  {
6074
6685
  onClick: () => onModeChange(m),
@@ -6090,7 +6701,7 @@ var RightPanel = memo8(function RightPanel2({
6090
6701
  },
6091
6702
  m
6092
6703
  )) }),
6093
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, overflow: "hidden" }, children: mode === "insights" ? /* @__PURE__ */ jsx26(
6704
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, overflow: "hidden" }, children: mode === "insights" ? /* @__PURE__ */ jsx27(
6094
6705
  InsightPanel,
6095
6706
  {
6096
6707
  mode: "tabs",
@@ -6099,16 +6710,16 @@ var RightPanel = memo8(function RightPanel2({
6099
6710
  id: tab.id,
6100
6711
  name: insightName(tab.name),
6101
6712
  render: () => {
6102
- if (tab.id === "narrative") return /* @__PURE__ */ jsx26(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, runtimeSnapshot, size, style: { height: "100%" } });
6713
+ if (tab.id === "narrative") return /* @__PURE__ */ jsx27(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, runtimeSnapshot, size, style: { height: "100%" } });
6103
6714
  const customView = recorderViews?.find((v2) => v2.id === tab.id);
6104
6715
  if (customView?.render) return customView.render({ snapshots, selectedIndex });
6105
6716
  const autoView = autoRecorderViews.find((v2) => v2.id === tab.id);
6106
- if (autoView) return /* @__PURE__ */ jsx26(KeyedRecorderView, { data: autoView.data, description: autoView.description, preferredOperation: autoView.preferredOperation, snapshots, selectedIndex });
6717
+ if (autoView) return /* @__PURE__ */ jsx27(KeyedRecorderView, { data: autoView.data, description: autoView.description, preferredOperation: autoView.preferredOperation, snapshots, selectedIndex });
6107
6718
  return null;
6108
6719
  }
6109
6720
  }))
6110
6721
  }
6111
- ) : /* @__PURE__ */ jsx26(
6722
+ ) : /* @__PURE__ */ jsx27(
6112
6723
  InspectorPanel,
6113
6724
  {
6114
6725
  snapshots,
@@ -6116,6 +6727,8 @@ var RightPanel = memo8(function RightPanel2({
6116
6727
  dataTraceFrames: dataTrace.frames,
6117
6728
  dataTraceNote: dataTrace.readsAvailable ? void 0 : "\u26A0 reads were not recorded (readTracking off) \u2014 dependencies are unknowable, not absent.",
6118
6729
  onTabChange: onInspectorTabChange,
6730
+ tab: inspectorTab,
6731
+ traceContent,
6119
6732
  selectedStageId: snapshots[selectedIndex]?.runtimeStageId,
6120
6733
  onNavigateToStage
6121
6734
  }
@@ -6156,7 +6769,7 @@ function ExplainableShell({
6156
6769
  className,
6157
6770
  style
6158
6771
  }) {
6159
- const derivedFromRuntime = useMemo12(() => {
6772
+ const derivedFromRuntime = useMemo14(() => {
6160
6773
  if (!runtimeSnapshot) return null;
6161
6774
  try {
6162
6775
  const snaps = toVisualizationSnapshots(runtimeSnapshot, narrativeEntries);
@@ -6167,7 +6780,7 @@ function ExplainableShell({
6167
6780
  }, [runtimeSnapshot, narrativeEntries]);
6168
6781
  const snapshots = snapshotsProp ?? derivedFromRuntime?.snapshots ?? [];
6169
6782
  const resultData = resultDataProp ?? derivedFromRuntime?.resultData ?? null;
6170
- const tracedFlowRenderer = useMemo12(() => {
6783
+ const tracedFlowRenderer = useMemo14(() => {
6171
6784
  if (!traceGraph) return void 0;
6172
6785
  return ({ selectedIndex, snapshots: snapshots2, onNodeClick, sliceCone: sliceCone2 }) => {
6173
6786
  const activeRsid = snapshots2[selectedIndex]?.runtimeStageId;
@@ -6188,7 +6801,7 @@ function ExplainableShell({
6188
6801
  ...traceTheme.current !== void 0 && { active: traceTheme.current },
6189
6802
  ...traceTheme.mode !== void 0 && { default: traceTheme.mode === "dark" ? "#94a3b8" : "#64748b" }
6190
6803
  };
6191
- return /* @__PURE__ */ jsx26(
6804
+ return /* @__PURE__ */ jsx27(
6192
6805
  TracedFlow,
6193
6806
  {
6194
6807
  graph: traceGraph,
@@ -6209,8 +6822,8 @@ function ExplainableShell({
6209
6822
  const rightLabel = panelLabels?.details ?? "Details";
6210
6823
  const bottomLabel = panelLabels?.timeline ?? "Timeline";
6211
6824
  const shellRef = useRef9(null);
6212
- const [isNarrow, setIsNarrow] = useState14(false);
6213
- const [isMedium, setIsMedium] = useState14(false);
6825
+ const [isNarrow, setIsNarrow] = useState15(false);
6826
+ const [isMedium, setIsMedium] = useState15(false);
6214
6827
  useEffect11(() => {
6215
6828
  const el = shellRef.current;
6216
6829
  if (!el) return;
@@ -6223,14 +6836,14 @@ function ExplainableShell({
6223
6836
  ro.observe(el);
6224
6837
  return () => ro.disconnect();
6225
6838
  }, []);
6226
- const autoRecorderViews = useMemo12(() => {
6839
+ const autoRecorderViews = useMemo14(() => {
6227
6840
  const recorders = runtimeSnapshot?.recorders;
6228
6841
  if (!recorders?.length) return [];
6229
6842
  const explicitIds = new Set((recorderViews ?? []).map((v2) => v2.id));
6230
6843
  return recorders.filter((r) => !explicitIds.has(r.id)).map((r) => ({ id: r.id, name: r.name, description: r.description, preferredOperation: r.preferredOperation, data: r.data }));
6231
6844
  }, [runtimeSnapshot, recorderViews]);
6232
6845
  const hasNarrative = !!narrativeEntries?.length;
6233
- const allTabs = useMemo12(() => {
6846
+ const allTabs = useMemo14(() => {
6234
6847
  const tabs2 = [
6235
6848
  { id: "result", name: "Result", description: "Final output and console logs" },
6236
6849
  { id: "memory", name: "Memory", description: "Accumulator \u2014 progressive shared state at each stage" }
@@ -6249,14 +6862,20 @@ function ExplainableShell({
6249
6862
  }, [hasNarrative, recorderViews, autoRecorderViews, hideTabsProp]);
6250
6863
  const validTabIds = new Set(allTabs.map((t) => t.id));
6251
6864
  const resolvedDefault = defaultTab && validTabIds.has(defaultTab) ? defaultTab : allTabs[0]?.id ?? "result";
6252
- const [activeTab, setActiveTab] = useState14(resolvedDefault);
6253
- const [snapshotIdx, setSnapshotIdx] = useState14(0);
6254
- const [drillDownStack, setDrillDownStack] = useState14([]);
6255
- const [rightExpanded, setRightExpanded] = useState14(defaultExpanded?.details ?? true);
6256
- const [rightPanelMode, setRightPanelMode] = useState14("insights");
6257
- const [inspectorTab, setInspectorTab] = useState14("state");
6258
- const [leftExpanded, setLeftExpanded] = useState14(defaultExpanded?.topology ?? false);
6259
- const [timelineExpanded, setTimelineExpanded] = useState14(defaultExpanded?.timeline ?? false);
6865
+ const [activeTab, setActiveTab] = useState15(resolvedDefault);
6866
+ const [snapshotIdx, setSnapshotIdx] = useState15(0);
6867
+ const [drillDownStack, setDrillDownStack] = useState15([]);
6868
+ const [rightExpanded, setRightExpanded] = useState15(defaultExpanded?.details ?? true);
6869
+ const [rightPanelMode, setRightPanelMode] = useState15("insights");
6870
+ const [inspectorTab, setInspectorTab] = useState15("state");
6871
+ const [tracing, setTracing] = useState15(null);
6872
+ const [forkChooserOpen, setForkChooserOpen] = useState15(false);
6873
+ const [traceSearch, setTraceSearch] = useState15("");
6874
+ useEffect11(() => {
6875
+ setForkChooserOpen(false);
6876
+ }, [snapshotIdx]);
6877
+ const [leftExpanded, setLeftExpanded] = useState15(defaultExpanded?.topology ?? false);
6878
+ const [timelineExpanded, setTimelineExpanded] = useState15(defaultExpanded?.timeline ?? false);
6260
6879
  useEffect11(() => {
6261
6880
  if (isNarrow) {
6262
6881
  setLeftExpanded(false);
@@ -6281,7 +6900,7 @@ function ExplainableShell({
6281
6900
  triggerReflow();
6282
6901
  }, [triggerReflow]);
6283
6902
  const isInSubflow = drillDownStack.length > 0;
6284
- const currentLevel = useMemo12(() => {
6903
+ const currentLevel = useMemo14(() => {
6285
6904
  if (drillDownStack.length > 0) {
6286
6905
  const top = drillDownStack[drillDownStack.length - 1];
6287
6906
  return { spec: top.spec, snapshots: top.snapshots, narrative: top.narrative };
@@ -6290,11 +6909,47 @@ function ExplainableShell({
6290
6909
  }, [drillDownStack, snapshots]);
6291
6910
  const activeSnapshots = currentLevel.snapshots;
6292
6911
  const safeIdx = activeSnapshots.length > 0 ? Math.max(0, Math.min(snapshotIdx, activeSnapshots.length - 1)) : 0;
6293
- const shellDataTrace = useMemo12(
6912
+ const shellDataTrace = useMemo14(
6294
6913
  () => runtimeSnapshot?.commitLog ? buildDataTrace(runtimeSnapshot.commitLog, runtimeSnapshot.executionTree, activeSnapshots[safeIdx]?.runtimeStageId ?? "") : { frames: [], readsAvailable: true },
6295
6914
  [runtimeSnapshot, activeSnapshots, safeIdx]
6296
6915
  );
6297
- const sliceCone = useMemo12(() => {
6916
+ const allTracedKeys = useMemo14(() => {
6917
+ const log = runtimeSnapshot?.commitLog;
6918
+ if (!log?.length) return [];
6919
+ const seen = /* @__PURE__ */ new Set();
6920
+ const keys = [];
6921
+ for (const c of log) {
6922
+ for (const t of c.trace ?? []) {
6923
+ if (!seen.has(t.path)) {
6924
+ seen.add(t.path);
6925
+ keys.push(t.path);
6926
+ }
6927
+ }
6928
+ }
6929
+ return keys;
6930
+ }, [runtimeSnapshot]);
6931
+ const traceWalk = useMemo14(() => {
6932
+ if (!tracing || !runtimeSnapshot?.commitLog) return null;
6933
+ const scope = tracing.via.length > 0 ? tracing.via[tracing.via.length - 1] : tracing;
6934
+ return buildTraceWalk(runtimeSnapshot.commitLog, runtimeSnapshot.executionTree, scope.key, {
6935
+ beforeCommitIdx: scope.beforeCommitIdx
6936
+ });
6937
+ }, [tracing, runtimeSnapshot]);
6938
+ const traceStopIndices = useMemo14(() => {
6939
+ if (!traceWalk || traceWalk.missing || isInSubflow) return [];
6940
+ const idxByRsid = new Map(activeSnapshots.map((sn, i) => [sn.runtimeStageId, i]));
6941
+ return traceWalk.stops.map((stop) => idxByRsid.get(stop.runtimeStageId)).filter((i) => i !== void 0).sort((a, b) => a - b);
6942
+ }, [traceWalk, activeSnapshots, isInSubflow]);
6943
+ const sliceCone = useMemo14(() => {
6944
+ if (traceWalk && !traceWalk.missing && traceWalk.stops.length >= 2) {
6945
+ const cone2 = /* @__PURE__ */ new Map();
6946
+ for (const stop of traceWalk.stops) {
6947
+ const stagePart = stop.runtimeStageId.split("#")[0];
6948
+ const prev = cone2.get(stagePart);
6949
+ if (prev === void 0 || stop.depth < prev) cone2.set(stagePart, stop.depth);
6950
+ }
6951
+ return cone2;
6952
+ }
6298
6953
  if (rightPanelMode !== "what" || inspectorTab !== "trace") return void 0;
6299
6954
  if (shellDataTrace.frames.length < 2) return void 0;
6300
6955
  const cone = /* @__PURE__ */ new Map();
@@ -6304,19 +6959,19 @@ function ExplainableShell({
6304
6959
  if (prev === void 0 || f.depth < prev) cone.set(stagePart, f.depth);
6305
6960
  }
6306
6961
  return cone;
6307
- }, [rightPanelMode, inspectorTab, shellDataTrace]);
6962
+ }, [traceWalk, rightPanelMode, inspectorTab, shellDataTrace]);
6308
6963
  const activeNarrativeEntries = isInSubflow ? currentLevel.narrative : narrativeEntries;
6309
- const breadcrumbs = useMemo12(() => {
6964
+ const breadcrumbs = useMemo14(() => {
6310
6965
  const root = { label: title || "Flowchart", spec: null, description: void 0 };
6311
6966
  return [root, ...drillDownStack.map((e) => ({ label: e.label, spec: e.spec, description: void 0 }))];
6312
6967
  }, [title, drillDownStack]);
6313
- const showTreeSidebar = useMemo12(() => {
6968
+ const showTreeSidebar = useMemo14(() => {
6314
6969
  if (traceGraph?.nodes?.length) {
6315
6970
  return traceGraph.nodes.some((n) => n.data?.isSubflow === true);
6316
6971
  }
6317
6972
  return false;
6318
6973
  }, [traceGraph]);
6319
- const rootOverlay = useMemo12(() => {
6974
+ const rootOverlay = useMemo14(() => {
6320
6975
  if (isInSubflow || !snapshots.length) return { activeStage: void 0, doneStages: void 0 };
6321
6976
  const doneStages = new Set(snapshots.slice(0, safeIdx).map((s) => s.stageLabel));
6322
6977
  const activeStage = snapshots[safeIdx]?.stageLabel ?? null;
@@ -6329,10 +6984,73 @@ function ExplainableShell({
6329
6984
  const handleSnapshotChange = useCallback8((idx) => {
6330
6985
  if (typeof idx === "number") setSnapshotIdx(idx);
6331
6986
  }, []);
6987
+ const jumpToAnchor = useCallback8(
6988
+ (walk) => {
6989
+ const anchor = walk.stops[0];
6990
+ if (!anchor) return;
6991
+ const idx = activeSnapshots.findIndex((sn) => sn.runtimeStageId === anchor.runtimeStageId);
6992
+ if (idx >= 0) setSnapshotIdx(idx);
6993
+ },
6994
+ [activeSnapshots]
6995
+ );
6996
+ const handleStartTracing = useCallback8(
6997
+ (key) => {
6998
+ if (!runtimeSnapshot?.commitLog || isInSubflow) return;
6999
+ const log = runtimeSnapshot.commitLog;
7000
+ const cursorRsid = activeSnapshots[safeIdx]?.runtimeStageId;
7001
+ const cursorCommitIdx = log.findIndex((c) => c.runtimeStageId === cursorRsid);
7002
+ const beforeCommitIdx = cursorCommitIdx >= 0 ? cursorCommitIdx + 1 : void 0;
7003
+ setTracing({ key, beforeCommitIdx, via: [] });
7004
+ setForkChooserOpen(false);
7005
+ setTraceSearch("");
7006
+ setRightPanelMode("what");
7007
+ setInspectorTab("trace");
7008
+ jumpToAnchor(
7009
+ buildTraceWalk(runtimeSnapshot.commitLog, runtimeSnapshot.executionTree, key, { beforeCommitIdx })
7010
+ );
7011
+ },
7012
+ [runtimeSnapshot, isInSubflow, activeSnapshots, safeIdx, jumpToAnchor]
7013
+ );
7014
+ const handleFollowIngredient = useCallback8(
7015
+ (ing) => {
7016
+ if (!tracing || !runtimeSnapshot?.commitLog || ing.writerCommitIdx === null) return;
7017
+ const scope = { key: ing.key, beforeCommitIdx: ing.writerCommitIdx + 1 };
7018
+ setTracing({ ...tracing, via: [...tracing.via, scope] });
7019
+ setForkChooserOpen(false);
7020
+ jumpToAnchor(
7021
+ buildTraceWalk(runtimeSnapshot.commitLog, runtimeSnapshot.executionTree, scope.key, {
7022
+ beforeCommitIdx: scope.beforeCommitIdx
7023
+ })
7024
+ );
7025
+ },
7026
+ [tracing, runtimeSnapshot, jumpToAnchor]
7027
+ );
7028
+ const handleShowAllIngredients = useCallback8(() => {
7029
+ if (!tracing || !runtimeSnapshot?.commitLog) return;
7030
+ setTracing({ ...tracing, via: [] });
7031
+ setForkChooserOpen(false);
7032
+ jumpToAnchor(
7033
+ buildTraceWalk(runtimeSnapshot.commitLog, runtimeSnapshot.executionTree, tracing.key, {
7034
+ beforeCommitIdx: tracing.beforeCommitIdx
7035
+ })
7036
+ );
7037
+ }, [tracing, runtimeSnapshot, jumpToAnchor]);
7038
+ const handleExitTracing = useCallback8(() => {
7039
+ setTracing(null);
7040
+ setForkChooserOpen(false);
7041
+ }, []);
7042
+ const handleForkPrompt = useCallback8(() => setForkChooserOpen(true), []);
7043
+ const handleContinueTimeOrder = useCallback8(() => {
7044
+ const earlier = traceStopIndices.filter((i) => i < safeIdx);
7045
+ if (earlier.length > 0) setSnapshotIdx(earlier[earlier.length - 1]);
7046
+ setForkChooserOpen(false);
7047
+ }, [traceStopIndices, safeIdx]);
6332
7048
  const handleDrillDown = useCallback8(
6333
7049
  (nodeName) => {
6334
7050
  const entry = resolveSubflowFromRuntime(activeSnapshots, nodeName, narrativeEntries);
6335
7051
  if (entry) {
7052
+ setTracing(null);
7053
+ setForkChooserOpen(false);
6336
7054
  setDrillDownStack((prev) => [...prev, { ...entry, parentSnapshotIdx: snapshotIdx }]);
6337
7055
  setSnapshotIdx(0);
6338
7056
  }
@@ -6379,33 +7097,170 @@ function ExplainableShell({
6379
7097
  },
6380
7098
  [snapshots, narrativeEntries, snapshotIdx]
6381
7099
  );
7100
+ const navigateToStage = useCallback8(
7101
+ (id) => {
7102
+ const idx = activeSnapshots.findIndex((sn) => sn.runtimeStageId === id);
7103
+ if (idx >= 0) setSnapshotIdx(idx);
7104
+ },
7105
+ [activeSnapshots]
7106
+ );
7107
+ const activeViaKey = tracing && tracing.via.length > 0 ? tracing.via[tracing.via.length - 1].key : null;
7108
+ const stepNumberOf = useCallback8(
7109
+ (rsid) => {
7110
+ const i = activeSnapshots.findIndex((sn) => sn.runtimeStageId === rsid);
7111
+ return i >= 0 ? i + 1 : null;
7112
+ },
7113
+ [activeSnapshots]
7114
+ );
7115
+ const tracingRail = useMemo14(() => {
7116
+ if (!tracing || !traceWalk || traceWalk.missing || traceStopIndices.length === 0) return null;
7117
+ const cursorRsid = activeSnapshots[safeIdx]?.runtimeStageId;
7118
+ const walkIdx = traceWalk.stops.findIndex((st) => st.runtimeStageId === cursorRsid);
7119
+ const currentStop = traceWalk.stops[walkIdx >= 0 ? walkIdx : 0];
7120
+ return {
7121
+ tracedKey: tracing.key,
7122
+ viaKey: activeViaKey,
7123
+ stopIndices: traceStopIndices,
7124
+ stopOrdinal: walkIdx >= 0 ? walkIdx + 1 : 1,
7125
+ totalStops: traceWalk.stops.length,
7126
+ onExit: handleExitTracing,
7127
+ onShowAll: activeViaKey ? handleShowAllIngredients : void 0,
7128
+ // Followable ingredients only — termini can't be chosen, so a stop of
7129
+ // run-inputs must not prompt (matches the card's chooser gate).
7130
+ forkCount: currentStop?.ingredients.filter((ing) => ing.writerRuntimeStageId !== null).length ?? 0,
7131
+ onForkPrompt: handleForkPrompt
7132
+ };
7133
+ }, [tracing, traceWalk, traceStopIndices, activeSnapshots, safeIdx, activeViaKey, handleExitTracing, handleShowAllIngredients, handleForkPrompt]);
7134
+ const traceTabContent = useMemo14(() => {
7135
+ if (tracing && traceWalk) {
7136
+ return /* @__PURE__ */ jsx27(
7137
+ TraceWalkCard,
7138
+ {
7139
+ walk: traceWalk,
7140
+ cursorRuntimeStageId: activeSnapshots[safeIdx]?.runtimeStageId ?? null,
7141
+ viaKey: activeViaKey,
7142
+ stepNumberOf,
7143
+ previewValueOf: (k) => activeSnapshots[safeIdx]?.memory?.[k],
7144
+ onFollowIngredient: handleFollowIngredient,
7145
+ onJumpToStop: navigateToStage,
7146
+ onShowAll: activeViaKey ? handleShowAllIngredients : void 0,
7147
+ onExit: handleExitTracing,
7148
+ forkChooserOpen,
7149
+ onContinueTimeOrder: handleContinueTimeOrder,
7150
+ canContinueTimeOrder: traceStopIndices.some((i) => i < safeIdx)
7151
+ }
7152
+ );
7153
+ }
7154
+ const chipStyle = {
7155
+ border: "1px solid var(--fp-accent, #6366f1)",
7156
+ background: "transparent",
7157
+ color: "var(--fp-accent, #6366f1)",
7158
+ borderRadius: 12,
7159
+ padding: "2px 10px",
7160
+ margin: "0 6px 6px 0",
7161
+ fontSize: 11,
7162
+ fontWeight: 600,
7163
+ fontFamily: "monospace",
7164
+ cursor: "pointer"
7165
+ };
7166
+ const query = traceSearch.trim().toLowerCase();
7167
+ const matchedKeys = query ? allTracedKeys.filter((k) => k.toLowerCase().includes(query)) : allTracedKeys;
7168
+ const shownKeys = matchedKeys.slice(0, 12);
7169
+ return /* @__PURE__ */ jsxs24(Fragment8, { children: [
7170
+ !isInSubflow && (shellDataTrace.frames[0]?.keysWritten?.length ?? 0) > 0 && /* @__PURE__ */ jsxs24("div", { "data-fp": "trace-entry", style: { padding: "10px 14px 0", fontSize: 12 }, children: [
7171
+ /* @__PURE__ */ jsx27("span", { style: { color: theme.textMuted, marginRight: 6 }, children: "This step wrote:" }),
7172
+ shellDataTrace.frames[0].keysWritten.map((k) => /* @__PURE__ */ jsx27(
7173
+ "button",
7174
+ {
7175
+ "data-fp": "trace-entry-chip",
7176
+ onClick: () => handleStartTracing(k),
7177
+ title: "Where did " + k + " come from? Walk its causes on the timeline.",
7178
+ style: chipStyle,
7179
+ children: k
7180
+ },
7181
+ k
7182
+ ))
7183
+ ] }),
7184
+ !isInSubflow && allTracedKeys.length > 0 && /* @__PURE__ */ jsxs24("div", { "data-fp": "trace-any", style: { padding: "6px 14px 0", fontSize: 12 }, children: [
7185
+ /* @__PURE__ */ jsx27("div", { style: { color: theme.textMuted, marginBottom: 4 }, children: "Trace any variable:" }),
7186
+ /* @__PURE__ */ jsx27(
7187
+ "input",
7188
+ {
7189
+ "data-fp": "trace-search",
7190
+ value: traceSearch,
7191
+ onChange: (e) => setTraceSearch(e.target.value),
7192
+ placeholder: "search any variable...",
7193
+ style: {
7194
+ display: "block",
7195
+ width: "100%",
7196
+ boxSizing: "border-box",
7197
+ background: theme.bgTertiary,
7198
+ border: `1px solid ${theme.border}`,
7199
+ borderRadius: 6,
7200
+ color: theme.textPrimary,
7201
+ fontSize: 11,
7202
+ fontFamily: "monospace",
7203
+ padding: "4px 8px",
7204
+ marginBottom: 6
7205
+ }
7206
+ }
7207
+ ),
7208
+ shownKeys.map((k) => /* @__PURE__ */ jsx27(
7209
+ "button",
7210
+ {
7211
+ "data-fp": "trace-any-chip",
7212
+ onClick: () => handleStartTracing(k),
7213
+ title: "Where did " + k + " come from? Walk its causes on the timeline.",
7214
+ style: chipStyle,
7215
+ children: k
7216
+ },
7217
+ k
7218
+ )),
7219
+ query === "" && matchedKeys.length > shownKeys.length && /* @__PURE__ */ jsxs24("span", { style: { color: theme.textMuted, fontSize: 11 }, children: [
7220
+ "+",
7221
+ matchedKeys.length - shownKeys.length,
7222
+ " more \u2014 type to search"
7223
+ ] })
7224
+ ] }),
7225
+ /* @__PURE__ */ jsx27(
7226
+ DataTracePanel,
7227
+ {
7228
+ frames: shellDataTrace.frames,
7229
+ note: shellDataTrace.readsAvailable ? void 0 : "\u26A0 reads were not recorded (readTracking off) \u2014 dependencies are unknowable, not absent.",
7230
+ selectedStageId: activeSnapshots[safeIdx]?.runtimeStageId,
7231
+ onFrameClick: navigateToStage,
7232
+ fromStageName: activeSnapshots[safeIdx]?.stageName
7233
+ }
7234
+ )
7235
+ ] });
7236
+ }, [tracing, traceWalk, activeSnapshots, safeIdx, activeViaKey, stepNumberOf, handleFollowIngredient, navigateToStage, handleShowAllIngredients, handleExitTracing, handleStartTracing, isInSubflow, shellDataTrace, forkChooserOpen, handleContinueTimeOrder, traceStopIndices, traceSearch, allTracedKeys]);
6382
7237
  const tabLabels = new Map(allTabs.map((t) => [t.id, t.name]));
6383
7238
  if (unstyled) {
6384
- return /* @__PURE__ */ jsxs23("div", { className, style, "data-fp": "explainable-shell", children: [
6385
- /* @__PURE__ */ jsx26("div", { "data-fp": "shell-tabs", children: allTabs.map((tab) => /* @__PURE__ */ jsx26("button", { "data-fp": "shell-tab", "data-active": tab.id === activeTab, onClick: () => handleTabChange(tab.id), children: tab.name }, tab.id)) }),
6386
- /* @__PURE__ */ jsxs23("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
6387
- activeTab === "result" && /* @__PURE__ */ jsx26(ResultPanel, { data: resultData ?? null, logs, hideConsole, unstyled: true }),
6388
- (activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ jsxs23(Fragment6, { children: [
6389
- /* @__PURE__ */ jsx26(TimeTravelControls, { snapshots: activeSnapshots, selectedIndex: safeIdx, onIndexChange: handleSnapshotChange, unstyled: true }),
6390
- isInSubflow && /* @__PURE__ */ jsx26(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
7239
+ return /* @__PURE__ */ jsxs24("div", { className, style, "data-fp": "explainable-shell", children: [
7240
+ /* @__PURE__ */ jsx27("div", { "data-fp": "shell-tabs", children: allTabs.map((tab) => /* @__PURE__ */ jsx27("button", { "data-fp": "shell-tab", "data-active": tab.id === activeTab, onClick: () => handleTabChange(tab.id), children: tab.name }, tab.id)) }),
7241
+ /* @__PURE__ */ jsxs24("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
7242
+ activeTab === "result" && /* @__PURE__ */ jsx27(ResultPanel, { data: resultData ?? null, logs, hideConsole, unstyled: true }),
7243
+ (activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ jsxs24(Fragment8, { children: [
7244
+ /* @__PURE__ */ jsx27(TimeTravelControls, { snapshots: activeSnapshots, selectedIndex: safeIdx, onIndexChange: handleSnapshotChange, unstyled: true, tracing: tracingRail }),
7245
+ isInSubflow && /* @__PURE__ */ jsx27(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
6391
7246
  traceGraph && effectiveRenderFlowchart?.({ spec: null, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick, showStageId, ...sliceCone && { sliceCone } }),
6392
- /* @__PURE__ */ jsx26(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, unstyled: true }),
6393
- /* @__PURE__ */ jsx26(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, unstyled: true }),
6394
- /* @__PURE__ */ jsx26(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, unstyled: true })
7247
+ /* @__PURE__ */ jsx27(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, unstyled: true }),
7248
+ /* @__PURE__ */ jsx27(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, unstyled: true }),
7249
+ /* @__PURE__ */ jsx27(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, unstyled: true })
6395
7250
  ] })
6396
7251
  ] })
6397
7252
  ] });
6398
7253
  }
6399
7254
  const showTopology = !!effectiveRenderFlowchart && !!traceGraph;
6400
- const detailsContent = useMemo12(() => {
7255
+ const detailsContent = useMemo14(() => {
6401
7256
  if (activeTab === "result") {
6402
- return /* @__PURE__ */ jsx26(ResultPanel, { data: resultData ?? null, logs, hideConsole, size });
7257
+ return /* @__PURE__ */ jsx27(ResultPanel, { data: resultData ?? null, logs, hideConsole, size });
6403
7258
  }
6404
7259
  if (activeTab === "memory") {
6405
- return /* @__PURE__ */ jsx26(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, size, style: { height: "100%" } });
7260
+ return /* @__PURE__ */ jsx27(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, size, style: { height: "100%" } });
6406
7261
  }
6407
7262
  if (activeTab === "narrative") {
6408
- return /* @__PURE__ */ jsx26(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, size, style: { height: "100%" } });
7263
+ return /* @__PURE__ */ jsx27(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, size, style: { height: "100%" } });
6409
7264
  }
6410
7265
  const customView = recorderViews?.find((v2) => v2.id === activeTab);
6411
7266
  if (customView?.render) {
@@ -6413,7 +7268,7 @@ function ExplainableShell({
6413
7268
  }
6414
7269
  const autoView = autoRecorderViews.find((v2) => v2.id === activeTab);
6415
7270
  if (autoView) {
6416
- return /* @__PURE__ */ jsx26(
7271
+ return /* @__PURE__ */ jsx27(
6417
7272
  KeyedRecorderView,
6418
7273
  {
6419
7274
  data: autoView.data,
@@ -6426,8 +7281,8 @@ function ExplainableShell({
6426
7281
  }
6427
7282
  return null;
6428
7283
  }, [activeTab, resultData, logs, hideConsole, size, activeSnapshots, safeIdx, activeNarrativeEntries, recorderViews, autoRecorderViews]);
6429
- const detailsPanel = /* @__PURE__ */ jsxs23("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }, children: [
6430
- /* @__PURE__ */ jsx26("div", { style: {
7284
+ const detailsPanel = /* @__PURE__ */ jsxs24("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }, children: [
7285
+ /* @__PURE__ */ jsx27("div", { style: {
6431
7286
  display: "flex",
6432
7287
  borderBottom: `1px solid ${theme.border}`,
6433
7288
  background: theme.bgSecondary,
@@ -6435,7 +7290,7 @@ function ExplainableShell({
6435
7290
  overflowX: "auto"
6436
7291
  }, children: allTabs.map((tab) => {
6437
7292
  const active = tab.id === activeTab;
6438
- return /* @__PURE__ */ jsx26(
7293
+ return /* @__PURE__ */ jsx27(
6439
7294
  "button",
6440
7295
  {
6441
7296
  onClick: () => handleTabChange(tab.id),
@@ -6459,9 +7314,9 @@ function ExplainableShell({
6459
7314
  tab.id
6460
7315
  );
6461
7316
  }) }),
6462
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, overflow: "auto" }, children: detailsContent })
7317
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, overflow: "auto" }, children: detailsContent })
6463
7318
  ] });
6464
- const shellThemeVars = useMemo12(() => {
7319
+ const shellThemeVars = useMemo14(() => {
6465
7320
  if (!traceTheme) return {};
6466
7321
  const base = traceTheme.mode ? tokensToCSSVars(traceTheme.mode === "light" ? coolLight : coolDark) : {};
6467
7322
  return {
@@ -6470,7 +7325,7 @@ function ExplainableShell({
6470
7325
  ...traceTheme.current !== void 0 && { ["--fp-node-cursor"]: traceTheme.current }
6471
7326
  };
6472
7327
  }, [traceTheme]);
6473
- return /* @__PURE__ */ jsxs23(
7328
+ return /* @__PURE__ */ jsxs24(
6474
7329
  "div",
6475
7330
  {
6476
7331
  ref: shellRef,
@@ -6489,20 +7344,21 @@ function ExplainableShell({
6489
7344
  },
6490
7345
  "data-fp": "explainable-shell",
6491
7346
  children: [
6492
- /* @__PURE__ */ jsx26(
7347
+ /* @__PURE__ */ jsx27(
6493
7348
  TimeTravelControls,
6494
7349
  {
6495
7350
  snapshots: activeSnapshots,
6496
7351
  selectedIndex: safeIdx,
6497
7352
  onIndexChange: handleSnapshotChange,
6498
- size
7353
+ size,
7354
+ tracing: tracingRail
6499
7355
  }
6500
7356
  ),
6501
- isInSubflow && /* @__PURE__ */ jsx26(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
6502
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, overflow: isNarrow ? "auto" : "hidden", display: "flex", flexDirection: "column" }, children: isNarrow ? (
7357
+ isInSubflow && /* @__PURE__ */ jsx27(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
7358
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, overflow: isNarrow ? "auto" : "hidden", display: "flex", flexDirection: "column" }, children: isNarrow ? (
6503
7359
  /* ── Mobile: stacked vertical ── */
6504
- /* @__PURE__ */ jsxs23(Fragment6, { children: [
6505
- showTopology && /* @__PURE__ */ jsx26("div", { style: { height: 350, flexShrink: 0, overflow: "hidden" }, children: effectiveRenderFlowchart({
7360
+ /* @__PURE__ */ jsxs24(Fragment8, { children: [
7361
+ showTopology && /* @__PURE__ */ jsx27("div", { style: { height: 350, flexShrink: 0, overflow: "hidden" }, children: effectiveRenderFlowchart({
6506
7362
  spec: null,
6507
7363
  snapshots: activeSnapshots,
6508
7364
  selectedIndex: safeIdx,
@@ -6510,9 +7366,9 @@ function ExplainableShell({
6510
7366
  showStageId,
6511
7367
  ...sliceCone && { sliceCone }
6512
7368
  }) }),
6513
- showTreeSidebar && /* @__PURE__ */ jsxs23(Fragment6, { children: [
6514
- /* @__PURE__ */ jsx26(HLinePill, { label: leftLabel, expanded: leftExpanded, onClick: () => toggleLeft(!leftExpanded) }),
6515
- leftExpanded && /* @__PURE__ */ jsx26("div", { style: { maxHeight: 180, overflow: "auto", flexShrink: 0 }, children: /* @__PURE__ */ jsx26(
7369
+ showTreeSidebar && /* @__PURE__ */ jsxs24(Fragment8, { children: [
7370
+ /* @__PURE__ */ jsx27(HLinePill, { label: leftLabel, expanded: leftExpanded, onClick: () => toggleLeft(!leftExpanded) }),
7371
+ leftExpanded && /* @__PURE__ */ jsx27("div", { style: { maxHeight: 180, overflow: "auto", flexShrink: 0 }, children: /* @__PURE__ */ jsx27(
6516
7372
  SubflowTree,
6517
7373
  {
6518
7374
  graph: traceGraph ?? { nodes: [], edges: [] },
@@ -6522,17 +7378,17 @@ function ExplainableShell({
6522
7378
  }
6523
7379
  ) })
6524
7380
  ] }),
6525
- /* @__PURE__ */ jsx26(HLinePill, { label: rightLabel, expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
6526
- rightExpanded && /* @__PURE__ */ jsx26("div", { style: { maxHeight: 350, flexShrink: 0, overflow: "hidden" }, children: detailsPanel }),
6527
- /* @__PURE__ */ jsx26(HLinePill, { label: bottomLabel, detail: `${activeSnapshots.length} stages`, expanded: timelineExpanded, onClick: toggleTimeline }),
6528
- timelineExpanded && /* @__PURE__ */ jsx26("div", { style: { flexShrink: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx26(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, size }) })
7381
+ /* @__PURE__ */ jsx27(HLinePill, { label: rightLabel, expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
7382
+ rightExpanded && /* @__PURE__ */ jsx27("div", { style: { maxHeight: 350, flexShrink: 0, overflow: "hidden" }, children: detailsPanel }),
7383
+ /* @__PURE__ */ jsx27(HLinePill, { label: bottomLabel, detail: `${activeSnapshots.length} stages`, expanded: timelineExpanded, onClick: toggleTimeline }),
7384
+ timelineExpanded && /* @__PURE__ */ jsx27("div", { style: { flexShrink: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx27(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, size }) })
6529
7385
  ] })
6530
7386
  ) : (
6531
7387
  /* ── Desktop: two-column — Flowchart | Right Panel ── */
6532
- /* @__PURE__ */ jsxs23(Fragment6, { children: [
6533
- /* @__PURE__ */ jsxs23("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
6534
- showTreeSidebar && (leftExpanded ? /* @__PURE__ */ jsxs23("div", { style: { width: 180, flexShrink: 0, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
6535
- /* @__PURE__ */ jsx26("div", { style: { flex: 1, overflow: "auto" }, children: /* @__PURE__ */ jsx26(
7388
+ /* @__PURE__ */ jsxs24(Fragment8, { children: [
7389
+ /* @__PURE__ */ jsxs24("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
7390
+ showTreeSidebar && (leftExpanded ? /* @__PURE__ */ jsxs24("div", { style: { width: 180, flexShrink: 0, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
7391
+ /* @__PURE__ */ jsx27("div", { style: { flex: 1, overflow: "auto" }, children: /* @__PURE__ */ jsx27(
6536
7392
  SubflowTree,
6537
7393
  {
6538
7394
  graph: traceGraph ?? { nodes: [], edges: [] },
@@ -6541,24 +7397,26 @@ function ExplainableShell({
6541
7397
  onNodeSelect: handleTreeNodeSelect
6542
7398
  }
6543
7399
  ) }),
6544
- /* @__PURE__ */ jsx26(VLinePill, { label: "Topology", expanded: true, side: "left", onClick: () => toggleLeft(false) })
6545
- ] }) : /* @__PURE__ */ jsx26(VLinePill, { label: "Topology", expanded: false, side: "left", onClick: () => toggleLeft(true) })),
6546
- showTopology ? /* @__PURE__ */ jsx26("div", { style: { flex: 1, overflow: "hidden", minWidth: 0 }, children: effectiveRenderFlowchart({
7400
+ /* @__PURE__ */ jsx27(VLinePill, { label: "Topology", expanded: true, side: "left", onClick: () => toggleLeft(false) })
7401
+ ] }) : /* @__PURE__ */ jsx27(VLinePill, { label: "Topology", expanded: false, side: "left", onClick: () => toggleLeft(true) })),
7402
+ showTopology ? /* @__PURE__ */ jsx27("div", { style: { flex: 1, overflow: "hidden", minWidth: 0 }, children: effectiveRenderFlowchart({
6547
7403
  spec: null,
6548
7404
  snapshots: activeSnapshots,
6549
7405
  selectedIndex: safeIdx,
6550
7406
  onNodeClick: handleNodeClick,
6551
7407
  showStageId,
6552
7408
  ...sliceCone && { sliceCone }
6553
- }) }) : /* @__PURE__ */ jsx26("div", { style: { flex: 1 } }),
6554
- /* @__PURE__ */ jsx26(VLinePill, { label: "Details", expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
6555
- rightExpanded && /* @__PURE__ */ jsx26("div", { style: { width: "42%", minWidth: 320, maxWidth: 550, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ jsx26(
7409
+ }) }) : /* @__PURE__ */ jsx27("div", { style: { flex: 1 } }),
7410
+ /* @__PURE__ */ jsx27(VLinePill, { label: "Details", expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
7411
+ rightExpanded && /* @__PURE__ */ jsx27("div", { style: { width: "42%", minWidth: 320, maxWidth: 550, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ jsx27(
6556
7412
  RightPanel,
6557
7413
  {
6558
7414
  mode: rightPanelMode,
6559
7415
  onModeChange: setRightPanelMode,
6560
7416
  dataTrace: shellDataTrace,
6561
7417
  onInspectorTabChange: setInspectorTab,
7418
+ inspectorTab,
7419
+ traceContent: traceTabContent,
6562
7420
  snapshots: activeSnapshots,
6563
7421
  selectedIndex: safeIdx,
6564
7422
  runtimeSnapshot,
@@ -6568,14 +7426,11 @@ function ExplainableShell({
6568
7426
  recorderViews,
6569
7427
  autoRecorderViews,
6570
7428
  size,
6571
- onNavigateToStage: (id) => {
6572
- const idx = activeSnapshots.findIndex((s) => s.runtimeStageId === id);
6573
- if (idx >= 0) setSnapshotIdx(idx);
6574
- }
7429
+ onNavigateToStage: navigateToStage
6575
7430
  }
6576
7431
  ) })
6577
7432
  ] }),
6578
- /* @__PURE__ */ jsx26(
7433
+ /* @__PURE__ */ jsx27(
6579
7434
  CompactTimeline,
6580
7435
  {
6581
7436
  snapshots: activeSnapshots,
@@ -6592,8 +7447,8 @@ function ExplainableShell({
6592
7447
 
6593
7448
  // src/components/TraceViewer/TraceViewer.tsx
6594
7449
  import * as React from "react";
6595
- import { useMemo as useMemo13 } from "react";
6596
- import { jsx as jsx27 } from "react/jsx-runtime";
7450
+ import { useMemo as useMemo15 } from "react";
7451
+ import { jsx as jsx28 } from "react/jsx-runtime";
6597
7452
  function parseTrace(input) {
6598
7453
  if (input == null) {
6599
7454
  return {
@@ -6656,11 +7511,11 @@ function TraceViewer({
6656
7511
  recorderViews,
6657
7512
  renderFlowchart
6658
7513
  }) {
6659
- const parsed = useMemo13(() => parseTrace(trace), [trace]);
7514
+ const parsed = useMemo15(() => parseTrace(trace), [trace]);
6660
7515
  React.useEffect(() => {
6661
7516
  if (!parsed.ok && onError) onError(parsed.error);
6662
7517
  }, [parsed, onError]);
6663
- const snapshots = useMemo13(() => {
7518
+ const snapshots = useMemo15(() => {
6664
7519
  if (!parsed.ok || !parsed.trace.snapshot) return [];
6665
7520
  try {
6666
7521
  return toVisualizationSnapshots(
@@ -6674,7 +7529,7 @@ function TraceViewer({
6674
7529
  if (!parsed.ok || snapshots.length === 0) {
6675
7530
  return fallback ?? null;
6676
7531
  }
6677
- return /* @__PURE__ */ jsx27(
7532
+ return /* @__PURE__ */ jsx28(
6678
7533
  ExplainableShell,
6679
7534
  {
6680
7535
  snapshots,
@@ -6710,13 +7565,16 @@ export {
6710
7565
  SubflowTree,
6711
7566
  TimeTravelControls,
6712
7567
  TraceViewer,
7568
+ TraceWalkCard,
6713
7569
  buildEntryRangeIndex,
7570
+ buildTraceWalk,
6714
7571
  computeRevealedEntryCount,
6715
7572
  coolDark,
6716
7573
  coolLight,
6717
7574
  createSnapshots,
6718
7575
  defaultTokens,
6719
7576
  extractSubflowNarrative,
7577
+ formatTraceWalk,
6720
7578
  mergeWritePatch,
6721
7579
  rawDefaults,
6722
7580
  subflowResultToSnapshots,