footprint-explainable-ui 0.20.0 → 0.22.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.
Files changed (149) hide show
  1. package/README.md +1 -0
  2. package/dist/flowchart.cjs +1366 -343
  3. package/dist/flowchart.cjs.map +1 -1
  4. package/dist/flowchart.d.cts +513 -6
  5. package/dist/flowchart.d.ts +513 -6
  6. package/dist/flowchart.js +1257 -262
  7. package/dist/flowchart.js.map +1 -1
  8. package/dist/index.cjs +941 -436
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +6 -0
  11. package/dist/index.d.ts +6 -0
  12. package/dist/index.js +852 -352
  13. package/dist/index.js.map +1 -1
  14. package/package.json +10 -3
  15. package/dist/adapters/fromRuntimeSnapshot.d.ts +0 -81
  16. package/dist/adapters/fromRuntimeSnapshot.d.ts.map +0 -1
  17. package/dist/adapters/fromRuntimeSnapshot.js +0 -226
  18. package/dist/adapters/fromRuntimeSnapshot.js.map +0 -1
  19. package/dist/components/ExplainableShell/ExplainableShell.d.ts +0 -169
  20. package/dist/components/ExplainableShell/ExplainableShell.d.ts.map +0 -1
  21. package/dist/components/ExplainableShell/ExplainableShell.js +0 -702
  22. package/dist/components/ExplainableShell/ExplainableShell.js.map +0 -1
  23. package/dist/components/ExplainableShell/index.d.ts +0 -3
  24. package/dist/components/ExplainableShell/index.d.ts.map +0 -1
  25. package/dist/components/ExplainableShell/index.js +0 -2
  26. package/dist/components/ExplainableShell/index.js.map +0 -1
  27. package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts +0 -11
  28. package/dist/components/FlowchartView/SubflowBreadcrumb.d.ts.map +0 -1
  29. package/dist/components/FlowchartView/SubflowBreadcrumb.js +0 -49
  30. package/dist/components/FlowchartView/SubflowBreadcrumb.js.map +0 -1
  31. package/dist/components/FlowchartView/SubflowTree.d.ts +0 -29
  32. package/dist/components/FlowchartView/SubflowTree.d.ts.map +0 -1
  33. package/dist/components/FlowchartView/SubflowTree.js +0 -153
  34. package/dist/components/FlowchartView/SubflowTree.js.map +0 -1
  35. package/dist/components/FlowchartView/index.d.ts +0 -39
  36. package/dist/components/FlowchartView/index.d.ts.map +0 -1
  37. package/dist/components/FlowchartView/index.js +0 -26
  38. package/dist/components/FlowchartView/index.js.map +0 -1
  39. package/dist/components/FlowchartView/useSubflowNavigation.d.ts +0 -60
  40. package/dist/components/FlowchartView/useSubflowNavigation.d.ts.map +0 -1
  41. package/dist/components/FlowchartView/useSubflowNavigation.js +0 -99
  42. package/dist/components/FlowchartView/useSubflowNavigation.js.map +0 -1
  43. package/dist/components/GanttTimeline/GanttTimeline.d.ts +0 -18
  44. package/dist/components/GanttTimeline/GanttTimeline.d.ts.map +0 -1
  45. package/dist/components/GanttTimeline/GanttTimeline.js +0 -123
  46. package/dist/components/GanttTimeline/GanttTimeline.js.map +0 -1
  47. package/dist/components/GanttTimeline/index.d.ts +0 -3
  48. package/dist/components/GanttTimeline/index.d.ts.map +0 -1
  49. package/dist/components/GanttTimeline/index.js +0 -2
  50. package/dist/components/GanttTimeline/index.js.map +0 -1
  51. package/dist/components/MemoryInspector/MemoryInspector.d.ts +0 -19
  52. package/dist/components/MemoryInspector/MemoryInspector.d.ts.map +0 -1
  53. package/dist/components/MemoryInspector/MemoryInspector.js +0 -118
  54. package/dist/components/MemoryInspector/MemoryInspector.js.map +0 -1
  55. package/dist/components/MemoryInspector/index.d.ts +0 -3
  56. package/dist/components/MemoryInspector/index.d.ts.map +0 -1
  57. package/dist/components/MemoryInspector/index.js +0 -2
  58. package/dist/components/MemoryInspector/index.js.map +0 -1
  59. package/dist/components/NarrativeLog/NarrativeLog.d.ts +0 -15
  60. package/dist/components/NarrativeLog/NarrativeLog.d.ts.map +0 -1
  61. package/dist/components/NarrativeLog/NarrativeLog.js +0 -65
  62. package/dist/components/NarrativeLog/NarrativeLog.js.map +0 -1
  63. package/dist/components/NarrativeLog/index.d.ts +0 -3
  64. package/dist/components/NarrativeLog/index.d.ts.map +0 -1
  65. package/dist/components/NarrativeLog/index.js +0 -2
  66. package/dist/components/NarrativeLog/index.js.map +0 -1
  67. package/dist/components/NarrativeTrace/NarrativeTrace.d.ts +0 -13
  68. package/dist/components/NarrativeTrace/NarrativeTrace.d.ts.map +0 -1
  69. package/dist/components/NarrativeTrace/NarrativeTrace.js +0 -134
  70. package/dist/components/NarrativeTrace/NarrativeTrace.js.map +0 -1
  71. package/dist/components/NarrativeTrace/index.d.ts +0 -3
  72. package/dist/components/NarrativeTrace/index.d.ts.map +0 -1
  73. package/dist/components/NarrativeTrace/index.js +0 -2
  74. package/dist/components/NarrativeTrace/index.js.map +0 -1
  75. package/dist/components/ResultPanel/ResultPanel.d.ts +0 -11
  76. package/dist/components/ResultPanel/ResultPanel.d.ts.map +0 -1
  77. package/dist/components/ResultPanel/ResultPanel.js +0 -54
  78. package/dist/components/ResultPanel/ResultPanel.js.map +0 -1
  79. package/dist/components/ResultPanel/index.d.ts +0 -3
  80. package/dist/components/ResultPanel/index.d.ts.map +0 -1
  81. package/dist/components/ResultPanel/index.js +0 -2
  82. package/dist/components/ResultPanel/index.js.map +0 -1
  83. package/dist/components/ScopeDiff/ScopeDiff.d.ts +0 -17
  84. package/dist/components/ScopeDiff/ScopeDiff.d.ts.map +0 -1
  85. package/dist/components/ScopeDiff/ScopeDiff.js +0 -87
  86. package/dist/components/ScopeDiff/ScopeDiff.js.map +0 -1
  87. package/dist/components/ScopeDiff/index.d.ts +0 -3
  88. package/dist/components/ScopeDiff/index.d.ts.map +0 -1
  89. package/dist/components/ScopeDiff/index.js +0 -2
  90. package/dist/components/ScopeDiff/index.js.map +0 -1
  91. package/dist/components/SnapshotPanel/SnapshotPanel.d.ts +0 -17
  92. package/dist/components/SnapshotPanel/SnapshotPanel.d.ts.map +0 -1
  93. package/dist/components/SnapshotPanel/SnapshotPanel.js +0 -85
  94. package/dist/components/SnapshotPanel/SnapshotPanel.js.map +0 -1
  95. package/dist/components/SnapshotPanel/index.d.ts +0 -3
  96. package/dist/components/SnapshotPanel/index.d.ts.map +0 -1
  97. package/dist/components/SnapshotPanel/index.js +0 -2
  98. package/dist/components/SnapshotPanel/index.js.map +0 -1
  99. package/dist/components/StageNode/StageNode.d.ts +0 -52
  100. package/dist/components/StageNode/StageNode.d.ts.map +0 -1
  101. package/dist/components/StageNode/StageNode.js +0 -314
  102. package/dist/components/StageNode/StageNode.js.map +0 -1
  103. package/dist/components/StageNode/index.d.ts +0 -3
  104. package/dist/components/StageNode/index.d.ts.map +0 -1
  105. package/dist/components/StageNode/index.js +0 -2
  106. package/dist/components/StageNode/index.js.map +0 -1
  107. package/dist/components/TimeTravelControls/TimeTravelControls.d.ts +0 -13
  108. package/dist/components/TimeTravelControls/TimeTravelControls.d.ts.map +0 -1
  109. package/dist/components/TimeTravelControls/TimeTravelControls.js +0 -120
  110. package/dist/components/TimeTravelControls/TimeTravelControls.js.map +0 -1
  111. package/dist/components/TimeTravelControls/index.d.ts +0 -3
  112. package/dist/components/TimeTravelControls/index.d.ts.map +0 -1
  113. package/dist/components/TimeTravelControls/index.js +0 -2
  114. package/dist/components/TimeTravelControls/index.js.map +0 -1
  115. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts +0 -33
  116. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.d.ts.map +0 -1
  117. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js +0 -119
  118. package/dist/components/TimeTravelDebugger/TimeTravelDebugger.js.map +0 -1
  119. package/dist/components/TimeTravelDebugger/index.d.ts +0 -3
  120. package/dist/components/TimeTravelDebugger/index.d.ts.map +0 -1
  121. package/dist/components/TimeTravelDebugger/index.js +0 -2
  122. package/dist/components/TimeTravelDebugger/index.js.map +0 -1
  123. package/dist/flowchart.d.ts.map +0 -1
  124. package/dist/index.d.ts.map +0 -1
  125. package/dist/theme/ThemeProvider.d.ts +0 -27
  126. package/dist/theme/ThemeProvider.d.ts.map +0 -1
  127. package/dist/theme/ThemeProvider.js +0 -30
  128. package/dist/theme/ThemeProvider.js.map +0 -1
  129. package/dist/theme/index.d.ts +0 -9
  130. package/dist/theme/index.d.ts.map +0 -1
  131. package/dist/theme/index.js +0 -6
  132. package/dist/theme/index.js.map +0 -1
  133. package/dist/theme/presets.d.ts +0 -18
  134. package/dist/theme/presets.d.ts.map +0 -1
  135. package/dist/theme/presets.js +0 -92
  136. package/dist/theme/presets.js.map +0 -1
  137. package/dist/theme/styles.d.ts +0 -32
  138. package/dist/theme/styles.d.ts.map +0 -1
  139. package/dist/theme/styles.js +0 -37
  140. package/dist/theme/styles.js.map +0 -1
  141. package/dist/theme/tokens.d.ts +0 -49
  142. package/dist/theme/tokens.d.ts.map +0 -1
  143. package/dist/theme/tokens.js +0 -79
  144. package/dist/theme/tokens.js.map +0 -1
  145. package/dist/tsconfig.tsbuildinfo +0 -1
  146. package/dist/types.d.ts +0 -60
  147. package/dist/types.d.ts.map +0 -1
  148. package/dist/types.js +0 -2
  149. package/dist/types.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -2279,7 +2279,7 @@ function TimeTravelControls({
2279
2279
  }
2280
2280
 
2281
2281
  // src/components/ExplainableShell/ExplainableShell.tsx
2282
- var import_react27 = require("react");
2282
+ var import_react29 = require("react");
2283
2283
 
2284
2284
  // src/utils/narrativeSync.ts
2285
2285
  function buildEntryRangeIndex(entries) {
@@ -3306,12 +3306,150 @@ var SubflowBreadcrumb = (0, import_react14.memo)(function SubflowBreadcrumb2({
3306
3306
  });
3307
3307
 
3308
3308
  // src/components/FlowchartView/TracedFlow.tsx
3309
- var import_react21 = require("react");
3310
- var import_react22 = require("@xyflow/react");
3309
+ var import_react23 = require("react");
3310
+ var import_react24 = require("@xyflow/react");
3311
3311
 
3312
- // src/components/FlowchartView/TraceFlow.tsx
3313
- var import_react17 = require("react");
3314
- var import_react18 = require("@xyflow/react");
3312
+ // src/components/FlowchartView/_internal/dagreTraceLayout.ts
3313
+ var import_dagre = __toESM(require("dagre"), 1);
3314
+ var DEFAULT_NODE_W = 200;
3315
+ var DEFAULT_NODE_H = 80;
3316
+ function sizeOf(node, fallbackW, fallbackH, resolver) {
3317
+ const style = node.style ?? {};
3318
+ const styleW = typeof style.width === "number" ? style.width : void 0;
3319
+ const styleH = typeof style.height === "number" ? style.height : void 0;
3320
+ if (node.data?.isGroupContainer && styleW !== void 0 && styleH !== void 0) {
3321
+ return { width: styleW, height: styleH };
3322
+ }
3323
+ const resolved = resolver?.(node);
3324
+ if (resolved) return { width: resolved.width, height: resolved.height };
3325
+ return {
3326
+ width: styleW ?? fallbackW,
3327
+ height: styleH ?? fallbackH
3328
+ };
3329
+ }
3330
+ function reorderSiblingEdges(edges, siblingOrder) {
3331
+ const bySource = /* @__PURE__ */ new Map();
3332
+ for (const e of edges) {
3333
+ if (e.data?.kind === "loop") continue;
3334
+ const arr = bySource.get(e.source);
3335
+ if (arr) arr.push(e);
3336
+ else bySource.set(e.source, [e]);
3337
+ }
3338
+ const out = [];
3339
+ for (const [src, group] of bySource) {
3340
+ if (group.length < 2) {
3341
+ out.push(...group);
3342
+ continue;
3343
+ }
3344
+ const ordered = siblingOrder(src, group.map((e) => e.target));
3345
+ const byTarget = new Map(group.map((e) => [e.target, e]));
3346
+ const used = /* @__PURE__ */ new Set();
3347
+ for (const t of ordered) {
3348
+ const e = byTarget.get(t);
3349
+ if (e && !used.has(t)) {
3350
+ out.push(e);
3351
+ used.add(t);
3352
+ }
3353
+ }
3354
+ for (const e of group) if (!used.has(e.target)) out.push(e);
3355
+ }
3356
+ return out;
3357
+ }
3358
+ function dagreTraceLayout(graph, options = {}) {
3359
+ if (graph.nodes.length === 0) return graph;
3360
+ const direction = options.direction ?? "TB";
3361
+ const rankSep = options.rankSep ?? 80;
3362
+ const nodeSep = options.nodeSep ?? 60;
3363
+ const edgeSep = options.edgeSep ?? 20;
3364
+ const fallbackW = options.nodeWidth ?? DEFAULT_NODE_W;
3365
+ const fallbackH = options.nodeHeight ?? DEFAULT_NODE_H;
3366
+ const g = new import_dagre.default.graphlib.Graph({ compound: true });
3367
+ g.setGraph({ rankdir: direction, ranksep: rankSep, nodesep: nodeSep, edgesep: edgeSep });
3368
+ g.setDefaultEdgeLabel(() => ({}));
3369
+ const sizes = /* @__PURE__ */ new Map();
3370
+ const resolvedStyleSizes = /* @__PURE__ */ new Map();
3371
+ for (const node of graph.nodes) {
3372
+ const resolved = options.nodeSize?.(node);
3373
+ const size = sizeOf(node, fallbackW, fallbackH, options.nodeSize);
3374
+ sizes.set(node.id, size);
3375
+ if (resolved && resolved.width === size.width && resolved.height === size.height) {
3376
+ resolvedStyleSizes.set(node.id, resolved);
3377
+ }
3378
+ g.setNode(node.id, { width: size.width, height: size.height });
3379
+ if (node.parentId) {
3380
+ g.setParent(node.id, node.parentId);
3381
+ }
3382
+ }
3383
+ const layoutEdges = options.siblingOrder ? reorderSiblingEdges(graph.edges, options.siblingOrder) : graph.edges;
3384
+ for (const e of layoutEdges) {
3385
+ if (e.data?.kind === "loop") continue;
3386
+ if (g.hasNode(e.source) && g.hasNode(e.target)) {
3387
+ const label = {};
3388
+ const weight = options.edgeWeight?.(e);
3389
+ const minlen = options.edgeMinLen?.(e);
3390
+ if (typeof weight === "number") label.weight = weight;
3391
+ if (typeof minlen === "number") label.minlen = minlen;
3392
+ g.setEdge(e.source, e.target, label);
3393
+ }
3394
+ }
3395
+ import_dagre.default.layout(g);
3396
+ const positioned = graph.nodes.map((node) => {
3397
+ const laidOut = g.node(node.id);
3398
+ if (!laidOut) return node;
3399
+ const size = sizes.get(node.id);
3400
+ let x = laidOut.x - size.width / 2;
3401
+ let y = laidOut.y - size.height / 2;
3402
+ if (node.parentId) {
3403
+ const parent = g.node(node.parentId);
3404
+ const parentSize = sizes.get(node.parentId);
3405
+ if (parent && parentSize) {
3406
+ x -= parent.x - parentSize.width / 2;
3407
+ y -= parent.y - parentSize.height / 2;
3408
+ }
3409
+ }
3410
+ const styleSize = resolvedStyleSizes.get(node.id);
3411
+ if (styleSize) {
3412
+ return {
3413
+ ...node,
3414
+ position: { x, y },
3415
+ style: { ...node.style ?? {}, width: styleSize.width, height: styleSize.height }
3416
+ };
3417
+ }
3418
+ return { ...node, position: { x, y } };
3419
+ });
3420
+ return { nodes: positioned, edges: graph.edges };
3421
+ }
3422
+
3423
+ // src/components/FlowchartView/createTraceRuntimeOverlay.ts
3424
+ function sliceOverlay(overlay, index) {
3425
+ const order = overlay.executionOrder;
3426
+ if (order.length === 0) {
3427
+ return {
3428
+ doneStageIds: /* @__PURE__ */ new Set(),
3429
+ activeStageId: null,
3430
+ executedStageIds: /* @__PURE__ */ new Set(),
3431
+ executedOrderIds: [],
3432
+ errors: overlay.errors
3433
+ };
3434
+ }
3435
+ const clampedIndex = Math.max(0, Math.min(index, order.length - 1));
3436
+ const doneStageIds = /* @__PURE__ */ new Set();
3437
+ for (let i = 0; i < clampedIndex; i++) {
3438
+ doneStageIds.add(order[i].stageId);
3439
+ }
3440
+ const activeStep = order[clampedIndex];
3441
+ const activeStageId = activeStep ? activeStep.stageId : null;
3442
+ const executedStageIds = new Set(doneStageIds);
3443
+ if (activeStageId) executedStageIds.add(activeStageId);
3444
+ const executedOrderIds = order.slice(0, clampedIndex + 1).map((s) => s.stageId);
3445
+ return {
3446
+ doneStageIds,
3447
+ activeStageId,
3448
+ executedStageIds,
3449
+ executedOrderIds,
3450
+ errors: overlay.errors
3451
+ };
3452
+ }
3315
3453
 
3316
3454
  // src/components/StageNode/StageNode.tsx
3317
3455
  var import_react15 = require("react");
@@ -3431,6 +3569,27 @@ function StageIcon({ type, color }) {
3431
3569
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("line", { x1: "13", y1: "4.5", x2: "13", y2: "11.5", stroke: color, strokeWidth: "1.3" }),
3432
3570
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("ellipse", { cx: "8", cy: "11.5", rx: "5", ry: "2", stroke: color, strokeWidth: "1.3" })
3433
3571
  ] });
3572
+ // System prompt — document with lines
3573
+ case "system-prompt":
3574
+ case "prompt":
3575
+ case "instructions":
3576
+ case "document":
3577
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { ...props, children: [
3578
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("rect", { x: "3.5", y: "2", width: "9", height: "12", rx: "1.5", stroke: color, strokeWidth: "1.3", fill: "none" }),
3579
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("line", { x1: "5.5", y1: "5", x2: "10.5", y2: "5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3580
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("line", { x1: "5.5", y1: "7.5", x2: "10.5", y2: "7.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3581
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("line", { x1: "5.5", y1: "10", x2: "8.5", y2: "10", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
3582
+ ] });
3583
+ // Messages / conversation — chat bubble
3584
+ case "messages":
3585
+ case "chat":
3586
+ case "conversation":
3587
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { ...props, children: [
3588
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("rect", { x: "2.5", y: "3", width: "11", height: "8", rx: "2", stroke: color, strokeWidth: "1.3", fill: "none" }),
3589
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M5.5 11L5.5 13.5L8.5 11", stroke: color, strokeWidth: "1.3", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
3590
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("line", { x1: "5", y1: "6", x2: "11", y2: "6", stroke: color, strokeWidth: "1", strokeLinecap: "round" }),
3591
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("line", { x1: "5", y1: "8.5", x2: "9", y2: "8.5", stroke: color, strokeWidth: "1", strokeLinecap: "round" })
3592
+ ] });
3434
3593
  // Loop — circular arrow
3435
3594
  case "loop":
3436
3595
  case "retry":
@@ -3481,20 +3640,29 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
3481
3640
  injectedRef.current = true;
3482
3641
  }, []);
3483
3642
  const isOnPath = active || done;
3484
- const bg = active ? theme.primary : done ? theme.success : error ? theme.error : theme.bgSecondary;
3485
- const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : theme.border;
3486
- const shadow = active ? `0 0 16px color-mix(in srgb, ${theme.primary} 40%, transparent)` : done ? `0 0 8px color-mix(in srgb, ${theme.success} 20%, transparent)` : error ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)` : `0 2px 8px rgba(0,0,0,0.15)`;
3643
+ const isHero = data.emphasis === "hero";
3644
+ const isMuted = data.emphasis === "muted";
3645
+ const sizeScale = data.size === "lg" ? 1.3 : data.size === "sm" ? 0.85 : 1;
3646
+ const restingBg = isHero ? `color-mix(in srgb, ${theme.primary} 12%, ${theme.bgSecondary})` : theme.bgSecondary;
3647
+ const restingBorder = isHero ? theme.primary : theme.border;
3648
+ const restingShadow = isHero ? `0 0 10px color-mix(in srgb, ${theme.primary} 22%, transparent)` : `0 2px 8px rgba(0,0,0,0.15)`;
3649
+ const bg = active ? theme.primary : done ? theme.success : error ? theme.error : restingBg;
3650
+ const borderColor = active ? theme.primary : done ? theme.success : error ? theme.error : restingBorder;
3651
+ const shadow = active ? `0 0 22px color-mix(in srgb, ${theme.primary} 55%, transparent)` : done ? `0 0 8px color-mix(in srgb, ${theme.success} 20%, transparent)` : error ? `0 0 12px color-mix(in srgb, ${theme.error} 30%, transparent)` : restingShadow;
3487
3652
  const textColor = active || done || error ? "#fff" : theme.textPrimary;
3488
3653
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3489
3654
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react16.Handle, { type: "target", position: import_react16.Position.Top, style: { opacity: 0 } }),
3490
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3655
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: { width: "100%", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3491
3656
  "div",
3492
3657
  {
3493
3658
  style: {
3494
3659
  position: "relative",
3495
3660
  display: "flex",
3496
3661
  alignItems: "center",
3497
- gap: 6
3662
+ gap: 6,
3663
+ // Plumbing recedes. Layers with the run-overlay `dimmed` (not-yet-run)
3664
+ // — a muted AND not-run node is faintest, which is correct.
3665
+ opacity: isMuted ? 0.5 : void 0
3498
3666
  },
3499
3667
  children: [
3500
3668
  stepNumbers && stepNumbers.length > 0 && isOnPath && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
@@ -3563,6 +3731,26 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
3563
3731
  }
3564
3732
  }
3565
3733
  ),
3734
+ active && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3735
+ "div",
3736
+ {
3737
+ style: {
3738
+ position: "absolute",
3739
+ top: -9,
3740
+ right: -8,
3741
+ zIndex: 11,
3742
+ background: theme.warning,
3743
+ color: "#1a1a1a",
3744
+ fontSize: 9,
3745
+ fontWeight: 800,
3746
+ letterSpacing: 0.6,
3747
+ padding: "2px 6px",
3748
+ borderRadius: 10,
3749
+ boxShadow: `0 0 10px color-mix(in srgb, ${theme.warning} 60%, transparent)`
3750
+ },
3751
+ children: "NOW"
3752
+ }
3753
+ ),
3566
3754
  isDecider ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { position: "relative", width: 120, height: 72 }, children: [
3567
3755
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3568
3756
  "div",
@@ -3668,9 +3856,9 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
3668
3856
  {
3669
3857
  style: {
3670
3858
  background: bg,
3671
- border: `2px ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
3859
+ border: `${isHero ? "2.5px" : isMuted ? "1px" : "2px"} ${isLazyUnresolved ? "dashed" : "solid"} ${borderColor}`,
3672
3860
  borderRadius: theme.radius,
3673
- padding: description ? "8px 16px" : "10px 20px",
3861
+ padding: description ? `${Math.round(8 * sizeScale)}px ${Math.round(16 * sizeScale)}px` : `${Math.round(10 * sizeScale)}px ${Math.round(20 * sizeScale)}px`,
3674
3862
  display: "flex",
3675
3863
  flexDirection: "column",
3676
3864
  alignItems: "center",
@@ -3703,8 +3891,8 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
3703
3891
  "span",
3704
3892
  {
3705
3893
  style: {
3706
- fontSize: 13,
3707
- fontWeight: 500,
3894
+ fontSize: Math.round(13 * sizeScale),
3895
+ fontWeight: isHero ? 700 : 500,
3708
3896
  color: textColor,
3709
3897
  whiteSpace: "nowrap"
3710
3898
  },
@@ -3779,146 +3967,11 @@ var StageNode = (0, import_react15.memo)(function StageNode2({
3779
3967
  )
3780
3968
  ]
3781
3969
  }
3782
- ),
3783
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react16.Handle, { type: "source", position: import_react16.Position.Bottom, style: { opacity: 0 } }),
3784
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3785
- import_react16.Handle,
3786
- {
3787
- id: "loop-source",
3788
- type: "source",
3789
- position: import_react16.Position.Bottom,
3790
- style: { background: "transparent", border: "none", width: 6, height: 6, left: "75%" }
3791
- }
3792
- ),
3793
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3794
- import_react16.Handle,
3795
- {
3796
- id: "loop-target",
3797
- type: "target",
3798
- position: import_react16.Position.Right,
3799
- style: { background: "transparent", border: "none", width: 6, height: 6 }
3800
- }
3801
- )
3970
+ ) }),
3971
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react16.Handle, { type: "source", position: import_react16.Position.Bottom, style: { opacity: 0 } })
3802
3972
  ] });
3803
3973
  });
3804
3974
 
3805
- // src/components/FlowchartView/TraceFlow.tsx
3806
- var import_jsx_runtime17 = require("react/jsx-runtime");
3807
- var Y_STEP = 100;
3808
- var X_SPREAD = 200;
3809
- var defaultTraceFlowLayout = (graph) => {
3810
- if (graph.nodes.length === 0) return { nodes: [], edges: graph.edges };
3811
- const branchChildrenOf = /* @__PURE__ */ new Map();
3812
- const nextChildrenOf = /* @__PURE__ */ new Map();
3813
- const hasIncomingForward = /* @__PURE__ */ new Set();
3814
- for (const e of graph.edges) {
3815
- const kind = e.data?.kind;
3816
- if (kind === "loop") continue;
3817
- hasIncomingForward.add(e.target);
3818
- if (kind === "fork-branch" || kind === "decision-branch") {
3819
- const arr = branchChildrenOf.get(e.source) ?? [];
3820
- arr.push(e.target);
3821
- branchChildrenOf.set(e.source, arr);
3822
- } else {
3823
- const arr = nextChildrenOf.get(e.source) ?? [];
3824
- arr.push(e.target);
3825
- nextChildrenOf.set(e.source, arr);
3826
- }
3827
- }
3828
- const seed = graph.nodes.find((n) => !hasIncomingForward.has(n.id)) ?? graph.nodes[0];
3829
- const positions = /* @__PURE__ */ new Map();
3830
- function layoutSubtree(nodeId, x, y) {
3831
- if (positions.has(nodeId)) {
3832
- return positions.get(nodeId).y;
3833
- }
3834
- positions.set(nodeId, { x, y });
3835
- let deepestBranchY = y;
3836
- const branches = branchChildrenOf.get(nodeId) ?? [];
3837
- if (branches.length > 0) {
3838
- const childY = y + Y_STEP;
3839
- const totalWidth = (branches.length - 1) * X_SPREAD;
3840
- const startX = x - totalWidth / 2;
3841
- for (let i = 0; i < branches.length; i++) {
3842
- const childId = branches[i];
3843
- const childX = startX + i * X_SPREAD;
3844
- const subtreeBottom = layoutSubtree(childId, childX, childY);
3845
- if (subtreeBottom > deepestBranchY) deepestBranchY = subtreeBottom;
3846
- }
3847
- }
3848
- const nextChildren = nextChildrenOf.get(nodeId) ?? [];
3849
- if (nextChildren.length > 0) {
3850
- const nextY = branches.length > 0 ? deepestBranchY + Y_STEP : y + Y_STEP;
3851
- const totalWidth = (nextChildren.length - 1) * X_SPREAD;
3852
- const startX = x - totalWidth / 2;
3853
- let deepestNextY = nextY;
3854
- for (let i = 0; i < nextChildren.length; i++) {
3855
- const childId = nextChildren[i];
3856
- const childX = startX + i * X_SPREAD;
3857
- const subtreeBottom = layoutSubtree(childId, childX, nextY);
3858
- if (subtreeBottom > deepestNextY) deepestNextY = subtreeBottom;
3859
- }
3860
- return deepestNextY;
3861
- }
3862
- return deepestBranchY;
3863
- }
3864
- layoutSubtree(seed.id, 0, 0);
3865
- let maxY = 0;
3866
- for (const p of positions.values()) {
3867
- if (p.y > maxY) maxY = p.y;
3868
- }
3869
- let orphanY = maxY + Y_STEP;
3870
- for (const n of graph.nodes) {
3871
- if (!positions.has(n.id)) {
3872
- positions.set(n.id, { x: 0, y: orphanY });
3873
- orphanY += Y_STEP;
3874
- }
3875
- }
3876
- return {
3877
- nodes: graph.nodes.map((n) => ({
3878
- ...n,
3879
- position: positions.get(n.id) ?? n.position
3880
- })),
3881
- edges: graph.edges
3882
- };
3883
- };
3884
- var DEFAULT_EDGE_COLORS = {
3885
- next: rawDefaults.colors.textMuted,
3886
- forkBranch: rawDefaults.colors.textMuted,
3887
- decisionBranch: rawDefaults.colors.primary,
3888
- loop: rawDefaults.colors.warning
3889
- };
3890
-
3891
- // src/components/FlowchartView/createTraceRuntimeOverlay.ts
3892
- function sliceOverlay(overlay, index) {
3893
- const order = overlay.executionOrder;
3894
- if (order.length === 0) {
3895
- return {
3896
- doneStageIds: /* @__PURE__ */ new Set(),
3897
- activeStageId: null,
3898
- executedStageIds: /* @__PURE__ */ new Set(),
3899
- executedOrderIds: [],
3900
- errors: overlay.errors
3901
- };
3902
- }
3903
- const clampedIndex = Math.max(0, Math.min(index, order.length - 1));
3904
- const doneStageIds = /* @__PURE__ */ new Set();
3905
- for (let i = 0; i < clampedIndex; i++) {
3906
- doneStageIds.add(order[i].stageId);
3907
- }
3908
- const activeStep = order[clampedIndex];
3909
- const activeStageId = activeStep ? activeStep.stageId : null;
3910
- const executedStageIds = new Set(doneStageIds);
3911
- if (activeStageId) executedStageIds.add(activeStageId);
3912
- const executedOrderIds = order.slice(0, clampedIndex + 1).map((s) => s.stageId);
3913
- return {
3914
- doneStageIds,
3915
- activeStageId,
3916
- executedStageIds,
3917
- executedOrderIds,
3918
- errors: overlay.errors
3919
- };
3920
- }
3921
-
3922
3975
  // src/components/FlowchartView/_internal/subflowDrill.ts
3923
3976
  function filterGraphForDrill(graph, currentSubflowId) {
3924
3977
  if (graph.nodes.length === 0) return graph;
@@ -3946,19 +3999,6 @@ function buildSubflowBreadcrumb(graph, currentSubflowId) {
3946
3999
  }
3947
4000
 
3948
4001
  // src/components/FlowchartView/_internal/overlayProjection.ts
3949
- function leafId(id) {
3950
- const i = id.lastIndexOf("/");
3951
- return i >= 0 ? id.slice(i + 1) : id;
3952
- }
3953
- function normalizeSliceLeafIds(slice) {
3954
- return {
3955
- doneStageIds: new Set(Array.from(slice.doneStageIds).map(leafId)),
3956
- activeStageId: slice.activeStageId ? leafId(slice.activeStageId) : null,
3957
- executedStageIds: new Set(Array.from(slice.executedStageIds).map(leafId)),
3958
- executedOrderIds: slice.executedOrderIds.map(leafId),
3959
- errors: new Map(Array.from(slice.errors).map(([k, v2]) => [leafId(k), v2]))
3960
- };
3961
- }
3962
4002
  function aggregateMountStatus(slice, graph, currentSubflowId) {
3963
4003
  if (graph.nodes.length === 0) return slice;
3964
4004
  const mounts = graph.nodes.filter((n) => n.data?.isSubflow && n.data?.subflowId);
@@ -3970,10 +4010,9 @@ function aggregateMountStatus(slice, graph, currentSubflowId) {
3970
4010
  const members = graph.nodes.filter((n) => n.data?.subflowOf === sfId);
3971
4011
  if (members.length === 0) continue;
3972
4012
  const anyActive = members.some((m) => m.id === slice.activeStageId);
3973
- const anyDone = members.some((m) => slice.doneStageIds.has(m.id));
3974
4013
  const allDone = members.every((m) => slice.doneStageIds.has(m.id));
3975
4014
  if (allDone) doneIds.add(mount.id);
3976
- else if ((anyActive || anyDone) && currentSubflowId === null) {
4015
+ else if (anyActive && currentSubflowId === null) {
3977
4016
  activeId = mount.id;
3978
4017
  }
3979
4018
  }
@@ -3981,18 +4020,18 @@ function aggregateMountStatus(slice, graph, currentSubflowId) {
3981
4020
  }
3982
4021
 
3983
4022
  // src/components/FlowchartView/_internal/useSubflowDrill.ts
3984
- var import_react19 = require("react");
4023
+ var import_react17 = require("react");
3985
4024
  function useSubflowDrill(graph, onSubflowChange) {
3986
- const [currentSubflowId, setCurrentSubflowId] = (0, import_react19.useState)(null);
3987
- const lastGraphRef = (0, import_react19.useRef)(null);
4025
+ const [currentSubflowId, setCurrentSubflowId] = (0, import_react17.useState)(null);
4026
+ const lastGraphRef = (0, import_react17.useRef)(null);
3988
4027
  if (lastGraphRef.current !== graph) {
3989
4028
  lastGraphRef.current = graph;
3990
4029
  if (currentSubflowId !== null && !graph.nodes.some((n) => n.data?.subflowId === currentSubflowId)) {
3991
4030
  queueMicrotask(() => setCurrentSubflowId(null));
3992
4031
  }
3993
4032
  }
3994
- const lastNotifiedRef = (0, import_react19.useRef)(void 0);
3995
- (0, import_react19.useEffect)(() => {
4033
+ const lastNotifiedRef = (0, import_react17.useRef)(void 0);
4034
+ (0, import_react17.useEffect)(() => {
3996
4035
  if (lastNotifiedRef.current === currentSubflowId) return;
3997
4036
  lastNotifiedRef.current = currentSubflowId;
3998
4037
  if (currentSubflowId === null) {
@@ -4002,21 +4041,22 @@ function useSubflowDrill(graph, onSubflowChange) {
4002
4041
  if (mount) onSubflowChange?.(mount.id);
4003
4042
  }
4004
4043
  }, [currentSubflowId, graph, onSubflowChange]);
4005
- const drillInto = (0, import_react19.useCallback)((subflowId) => {
4044
+ const drillInto = (0, import_react17.useCallback)((subflowId) => {
4006
4045
  setCurrentSubflowId(subflowId);
4007
4046
  }, []);
4008
- const drillUp = (0, import_react19.useCallback)(() => {
4047
+ const drillUp = (0, import_react17.useCallback)(() => {
4009
4048
  setCurrentSubflowId(null);
4010
4049
  }, []);
4011
4050
  return { currentSubflowId, drillInto, drillUp, setCurrentSubflowId };
4012
4051
  }
4013
4052
 
4014
4053
  // src/components/FlowchartView/_internal/useChartAutoRefit.ts
4015
- var import_react20 = require("react");
4054
+ var import_react18 = require("react");
4016
4055
  function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
4017
4056
  const duration = options.duration ?? 200;
4018
4057
  const padding2 = options.padding ?? 0.1;
4019
- (0, import_react20.useEffect)(() => {
4058
+ const refitKey = options.refitKey;
4059
+ (0, import_react18.useEffect)(() => {
4020
4060
  const el = wrapperRef.current;
4021
4061
  if (!el || !rfInstance) return;
4022
4062
  let raf = 0;
@@ -4035,12 +4075,25 @@ function useChartAutoRefit(wrapperRef, rfInstance, options = {}) {
4035
4075
  cancelAnimationFrame(raf);
4036
4076
  };
4037
4077
  }, [rfInstance, wrapperRef, duration, padding2]);
4078
+ (0, import_react18.useEffect)(() => {
4079
+ if (!rfInstance) return;
4080
+ let raf2 = 0;
4081
+ const raf1 = requestAnimationFrame(() => {
4082
+ raf2 = requestAnimationFrame(() => {
4083
+ rfInstance.fitView({ duration, padding: padding2 });
4084
+ });
4085
+ });
4086
+ return () => {
4087
+ cancelAnimationFrame(raf1);
4088
+ cancelAnimationFrame(raf2);
4089
+ };
4090
+ }, [rfInstance, refitKey, duration, padding2]);
4038
4091
  }
4039
4092
 
4040
4093
  // src/components/FlowchartView/SubflowBreadcrumbBar.tsx
4041
- var import_jsx_runtime18 = require("react/jsx-runtime");
4094
+ var import_jsx_runtime17 = require("react/jsx-runtime");
4042
4095
  function SubflowBreadcrumbBar({ entries, onNavigate }) {
4043
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4096
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4044
4097
  "div",
4045
4098
  {
4046
4099
  style: {
@@ -4056,12 +4109,12 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
4056
4109
  "aria-label": "Subflow breadcrumb",
4057
4110
  children: entries.map((entry, i) => {
4058
4111
  const isLast = i === entries.length - 1;
4059
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4112
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
4060
4113
  "span",
4061
4114
  {
4062
4115
  style: { display: "inline-flex", alignItems: "center", gap: 6 },
4063
4116
  children: [
4064
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4117
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4065
4118
  "button",
4066
4119
  {
4067
4120
  type: "button",
@@ -4081,7 +4134,7 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
4081
4134
  children: entry.label
4082
4135
  }
4083
4136
  ),
4084
- !isLast && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { color: rawDefaults.colors.textMuted }, children: "\u203A" })
4137
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { color: rawDefaults.colors.textMuted }, children: "\u203A" })
4085
4138
  ]
4086
4139
  },
4087
4140
  entry.subflowId ?? "__top__"
@@ -4091,8 +4144,388 @@ function SubflowBreadcrumbBar({ entries, onNavigate }) {
4091
4144
  );
4092
4145
  }
4093
4146
 
4094
- // src/components/FlowchartView/TracedFlow.tsx
4147
+ // src/components/GroupContainerNode/GroupContainerNode.tsx
4148
+ var import_react19 = require("@xyflow/react");
4149
+ var import_jsx_runtime18 = require("react/jsx-runtime");
4150
+ var C = rawDefaults.colors;
4151
+ function GroupContainerNode({ data }) {
4152
+ const d = data;
4153
+ const borderColor = d.error ? C.error : d.active ? C.primary : d.done ? C.success : C.border;
4154
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4155
+ "div",
4156
+ {
4157
+ style: {
4158
+ width: "100%",
4159
+ height: "100%",
4160
+ boxSizing: "border-box",
4161
+ border: `1.5px ${d.active || d.done || d.error ? "solid" : "dashed"} ${borderColor}`,
4162
+ borderRadius: 12,
4163
+ // Translucent so the dotted background + nested children read clearly.
4164
+ background: "rgba(148, 163, 184, 0.06)",
4165
+ opacity: d.dimmed ? 0.4 : 1,
4166
+ position: "relative"
4167
+ },
4168
+ children: [
4169
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
4170
+ "div",
4171
+ {
4172
+ style: {
4173
+ display: "flex",
4174
+ alignItems: "center",
4175
+ gap: 6,
4176
+ padding: "8px 12px",
4177
+ fontSize: 12,
4178
+ fontWeight: 600,
4179
+ color: C.textMuted,
4180
+ letterSpacing: 0.2
4181
+ },
4182
+ children: [
4183
+ d.icon ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { "aria-hidden": true, children: d.icon }) : null,
4184
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: d.label })
4185
+ ]
4186
+ }
4187
+ ),
4188
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react19.Handle, { type: "target", position: import_react19.Position.Top, style: { opacity: 0 } }),
4189
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react19.Handle, { type: "source", position: import_react19.Position.Bottom, style: { opacity: 0 } })
4190
+ ]
4191
+ }
4192
+ );
4193
+ }
4194
+
4195
+ // src/components/LoopBackEdge/LoopBackEdge.tsx
4196
+ var import_react20 = require("@xyflow/react");
4197
+
4198
+ // src/components/FlowchartView/_internal/loopRouting.ts
4199
+ var LOOP_LANE_GAP = 56;
4200
+ function loopLaneX(contentRights, gap = LOOP_LANE_GAP) {
4201
+ let max = -Infinity;
4202
+ for (const r of contentRights) if (r > max) max = r;
4203
+ if (!Number.isFinite(max)) max = 0;
4204
+ return max + gap;
4205
+ }
4206
+ function loopBackPath(source, target, laneX, radius = 22) {
4207
+ const { right: sx, centerY: sy } = source;
4208
+ const { right: tx, centerY: ty } = target;
4209
+ const r = Math.max(
4210
+ 0,
4211
+ Math.min(radius, Math.abs(sy - ty) / 2, laneX - sx, laneX - tx)
4212
+ );
4213
+ const up = ty <= sy;
4214
+ const vy1 = up ? sy - r : sy + r;
4215
+ const vy2 = up ? ty + r : ty - r;
4216
+ return [
4217
+ `M ${sx},${sy}`,
4218
+ `L ${laneX - r},${sy}`,
4219
+ `Q ${laneX},${sy} ${laneX},${vy1}`,
4220
+ `L ${laneX},${vy2}`,
4221
+ `Q ${laneX},${ty} ${laneX - r},${ty}`,
4222
+ `L ${tx},${ty}`
4223
+ ].join(" ");
4224
+ }
4225
+
4226
+ // src/components/FlowchartView/_internal/groupLayout.ts
4227
+ var GROUP_CONTAINER_NODE_TYPE = "groupContainer";
4228
+ var DEFAULT_PADDING = 16;
4229
+ var DEFAULT_HEADER = 44;
4230
+ var DEFAULT_NODE_W2 = 200;
4231
+ var DEFAULT_NODE_H2 = 80;
4232
+ function footprintOf(node, fallbackW, fallbackH) {
4233
+ const style = node.style ?? {};
4234
+ const w = typeof style.width === "number" ? style.width : fallbackW;
4235
+ const h = typeof style.height === "number" ? style.height : fallbackH;
4236
+ return { width: w, height: h };
4237
+ }
4238
+ function applyGroupLayout(graph, opts) {
4239
+ const padding2 = opts.padding ?? DEFAULT_PADDING;
4240
+ const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;
4241
+ const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W2;
4242
+ const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H2;
4243
+ const baseLayout = opts.baseLayout;
4244
+ const requested = new Set(opts.groupedSubflowIds);
4245
+ const membersBySubflow = /* @__PURE__ */ new Map();
4246
+ for (const n of graph.nodes) {
4247
+ const of = n.data?.subflowOf;
4248
+ if (of !== void 0 && requested.has(of)) {
4249
+ const arr = membersBySubflow.get(of) ?? [];
4250
+ arr.push(n);
4251
+ membersBySubflow.set(of, arr);
4252
+ }
4253
+ }
4254
+ const mountBySubflow = /* @__PURE__ */ new Map();
4255
+ for (const n of graph.nodes) {
4256
+ const sfId = n.data?.subflowId;
4257
+ if (n.data?.isSubflow && sfId !== void 0 && requested.has(sfId) && membersBySubflow.has(sfId)) {
4258
+ mountBySubflow.set(sfId, n);
4259
+ }
4260
+ }
4261
+ const activeGroups = /* @__PURE__ */ new Set();
4262
+ for (const sfId of mountBySubflow.keys()) activeGroups.add(sfId);
4263
+ if (activeGroups.size === 0) {
4264
+ return graph;
4265
+ }
4266
+ const memberIds = /* @__PURE__ */ new Set();
4267
+ for (const sfId of activeGroups) {
4268
+ for (const m of membersBySubflow.get(sfId) ?? []) memberIds.add(m.id);
4269
+ }
4270
+ const containerNodes = [];
4271
+ const nestedMembers = [];
4272
+ const groupBox = /* @__PURE__ */ new Map();
4273
+ for (const sfId of activeGroups) {
4274
+ const members = membersBySubflow.get(sfId);
4275
+ const innerOnlyEdges = graph.edges.filter((e) => {
4276
+ const s = members.some((m) => m.id === e.source);
4277
+ const t = members.some((m) => m.id === e.target);
4278
+ return s && t;
4279
+ });
4280
+ const innerPositioned = baseLayout({ nodes: members, edges: innerOnlyEdges });
4281
+ let minX = Infinity;
4282
+ let minY = Infinity;
4283
+ let maxX = -Infinity;
4284
+ let maxY = -Infinity;
4285
+ for (const m of innerPositioned.nodes) {
4286
+ const p = m.position;
4287
+ const { width, height } = footprintOf(m, nodeW, nodeH);
4288
+ if (p.x < minX) minX = p.x;
4289
+ if (p.y < minY) minY = p.y;
4290
+ if (p.x + width > maxX) maxX = p.x + width;
4291
+ if (p.y + height > maxY) maxY = p.y + height;
4292
+ }
4293
+ if (!Number.isFinite(minX)) {
4294
+ minX = 0;
4295
+ minY = 0;
4296
+ maxX = 0;
4297
+ maxY = 0;
4298
+ }
4299
+ const boxWidth = maxX - minX + padding2 * 2;
4300
+ const boxHeight = maxY - minY + headerHeight + padding2 * 2;
4301
+ groupBox.set(sfId, { width: boxWidth, height: boxHeight, minX, minY, members: innerPositioned.nodes });
4302
+ }
4303
+ const outerNodes = graph.nodes.filter((n) => !memberIds.has(n.id)).map((n) => {
4304
+ const box = n.data?.subflowId ? groupBox.get(n.data.subflowId) : void 0;
4305
+ return box ? {
4306
+ ...n,
4307
+ style: { ...n.style ?? {}, width: box.width, height: box.height },
4308
+ data: { ...n.data, isGroupContainer: true }
4309
+ } : n;
4310
+ });
4311
+ const outerEdges = graph.edges.filter(
4312
+ (e) => !memberIds.has(e.source) && !memberIds.has(e.target)
4313
+ );
4314
+ const outerPositioned = baseLayout({ nodes: outerNodes, edges: outerEdges });
4315
+ const outerPosById = new Map(outerPositioned.nodes.map((n) => [n.id, n.position]));
4316
+ for (const sfId of activeGroups) {
4317
+ const mount = mountBySubflow.get(sfId);
4318
+ const box = groupBox.get(sfId);
4319
+ const { width: boxWidth, height: boxHeight, minX, minY } = box;
4320
+ const mountPos = outerPosById.get(mount.id) ?? mount.position ?? { x: 0, y: 0 };
4321
+ containerNodes.push({
4322
+ ...mount,
4323
+ type: GROUP_CONTAINER_NODE_TYPE,
4324
+ position: mountPos,
4325
+ style: { ...mount.style ?? {}, width: boxWidth, height: boxHeight },
4326
+ data: { ...mount.data, isGroupContainer: true }
4327
+ });
4328
+ for (const m of box.members) {
4329
+ const relX = m.position.x - minX + padding2;
4330
+ const relY = m.position.y - minY + headerHeight + padding2;
4331
+ nestedMembers.push({
4332
+ ...m,
4333
+ parentId: mount.id,
4334
+ extent: "parent",
4335
+ position: { x: relX, y: relY }
4336
+ });
4337
+ }
4338
+ }
4339
+ const containerById = new Map(containerNodes.map((c) => [c.id, c]));
4340
+ const outerOut = outerPositioned.nodes.map(
4341
+ (n) => containerById.get(n.id) ?? n
4342
+ );
4343
+ return {
4344
+ nodes: [...outerOut, ...nestedMembers],
4345
+ edges: graph.edges
4346
+ };
4347
+ }
4348
+ var MAIN_CHART_BOX_ID = "__main_chart__";
4349
+ function wrapInMainChartBox(graph, opts) {
4350
+ if (graph.nodes.length === 0) return graph;
4351
+ const padding2 = opts.padding ?? DEFAULT_PADDING;
4352
+ const headerHeight = opts.headerHeight ?? DEFAULT_HEADER;
4353
+ const nodeW = opts.nodeWidth ?? DEFAULT_NODE_W2;
4354
+ const nodeH = opts.nodeHeight ?? DEFAULT_NODE_H2;
4355
+ const mainId = opts.id ?? MAIN_CHART_BOX_ID;
4356
+ const positioned = opts.baseLayout(graph);
4357
+ const topLevel = positioned.nodes.filter((n) => n.parentId === void 0);
4358
+ let minX = Infinity;
4359
+ let minY = Infinity;
4360
+ let maxX = -Infinity;
4361
+ let maxY = -Infinity;
4362
+ for (const n of topLevel) {
4363
+ const p = n.position;
4364
+ const { width, height } = footprintOf(n, nodeW, nodeH);
4365
+ if (p.x < minX) minX = p.x;
4366
+ if (p.y < minY) minY = p.y;
4367
+ if (p.x + width > maxX) maxX = p.x + width;
4368
+ if (p.y + height > maxY) maxY = p.y + height;
4369
+ }
4370
+ if (!Number.isFinite(minX)) {
4371
+ minX = 0;
4372
+ minY = 0;
4373
+ maxX = 0;
4374
+ maxY = 0;
4375
+ }
4376
+ const hasLoopEdge = graph.edges.some((e) => e.data?.kind === "loop");
4377
+ const loopReserve = hasLoopEdge ? LOOP_LANE_GAP : 0;
4378
+ const boxWidth = maxX - minX + padding2 * 2 + loopReserve;
4379
+ const boxHeight = maxY - minY + headerHeight + padding2 * 2;
4380
+ const container = {
4381
+ id: mainId,
4382
+ type: GROUP_CONTAINER_NODE_TYPE,
4383
+ position: { x: 0, y: 0 },
4384
+ style: { width: boxWidth, height: boxHeight },
4385
+ data: {
4386
+ label: opts.label ?? "Chart",
4387
+ isDecider: false,
4388
+ isFork: false,
4389
+ isStreaming: false,
4390
+ isSubflow: false,
4391
+ isGroupContainer: true,
4392
+ isMainChart: true,
4393
+ ...opts.kind !== void 0 && { kind: opts.kind },
4394
+ prevIds: [],
4395
+ nextIds: []
4396
+ }
4397
+ };
4398
+ const topLevelIds = new Set(topLevel.map((n) => n.id));
4399
+ const reparented = positioned.nodes.map((n) => {
4400
+ if (!topLevelIds.has(n.id)) return n;
4401
+ return {
4402
+ ...n,
4403
+ parentId: mainId,
4404
+ extent: "parent",
4405
+ position: {
4406
+ x: n.position.x - minX + padding2,
4407
+ y: n.position.y - minY + headerHeight + padding2
4408
+ }
4409
+ };
4410
+ });
4411
+ return { nodes: [container, ...reparented], edges: graph.edges };
4412
+ }
4413
+
4414
+ // src/components/LoopBackEdge/LoopBackEdge.tsx
4095
4415
  var import_jsx_runtime19 = require("react/jsx-runtime");
4416
+ var LOOP_DASH = "5 5";
4417
+ var LOOP_STROKE_OPACITY_CAP = 0.55;
4418
+ var LOOP_STROKE_WIDTH = 1.5;
4419
+ function softenLoopStyle(style) {
4420
+ const passedStrokeOpacity = typeof style?.strokeOpacity === "number" ? style.strokeOpacity : 1;
4421
+ return {
4422
+ ...style,
4423
+ strokeDasharray: style?.strokeDasharray ?? LOOP_DASH,
4424
+ strokeOpacity: Math.min(passedStrokeOpacity, LOOP_STROKE_OPACITY_CAP),
4425
+ strokeWidth: LOOP_STROKE_WIDTH
4426
+ };
4427
+ }
4428
+ var LOOP_CORNER_RADIUS = 28;
4429
+ function rightEdge(node) {
4430
+ return node.internals.positionAbsolute.x + (node.measured.width ?? 0);
4431
+ }
4432
+ function centerY(node) {
4433
+ return node.internals.positionAbsolute.y + (node.measured.height ?? 0) / 2;
4434
+ }
4435
+ function LoopBackEdge({ id, source, target, markerEnd, style }) {
4436
+ const path = (0, import_react20.useStore)((s) => {
4437
+ const src = s.nodeLookup.get(source);
4438
+ const tgt = s.nodeLookup.get(target);
4439
+ if (!src || !tgt) return "";
4440
+ const contentRights = [];
4441
+ for (const n of s.nodeLookup.values()) {
4442
+ if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;
4443
+ contentRights.push(rightEdge(n));
4444
+ }
4445
+ const laneX = loopLaneX([...contentRights, rightEdge(src), rightEdge(tgt)], LOOP_LANE_GAP);
4446
+ return loopBackPath(
4447
+ { right: rightEdge(src), centerY: centerY(src) },
4448
+ { right: rightEdge(tgt), centerY: centerY(tgt) },
4449
+ laneX,
4450
+ LOOP_CORNER_RADIUS
4451
+ );
4452
+ });
4453
+ if (!path) return null;
4454
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4455
+ import_react20.BaseEdge,
4456
+ {
4457
+ id,
4458
+ path,
4459
+ markerEnd,
4460
+ style: softenLoopStyle(style),
4461
+ "aria-label": "Loop back"
4462
+ }
4463
+ );
4464
+ }
4465
+
4466
+ // src/components/SmartStepEdge/SmartStepEdge.tsx
4467
+ var import_react21 = require("@xyflow/react");
4468
+ var import_react22 = require("@xyflow/react");
4469
+
4470
+ // src/components/FlowchartView/_internal/stepRouting.ts
4471
+ function staggeredBendY(sourceBottom, targetTop, others, minGapFromTarget = 8) {
4472
+ let lowestSkippedBottom = -Infinity;
4473
+ for (const n of others) {
4474
+ const cy = (n.top + n.bottom) / 2;
4475
+ if (cy > sourceBottom && cy < targetTop && n.bottom > lowestSkippedBottom) {
4476
+ lowestSkippedBottom = n.bottom;
4477
+ }
4478
+ }
4479
+ if (lowestSkippedBottom === -Infinity) return null;
4480
+ return Math.min((lowestSkippedBottom + targetTop) / 2, targetTop - minGapFromTarget);
4481
+ }
4482
+
4483
+ // src/components/SmartStepEdge/SmartStepEdge.tsx
4484
+ var import_jsx_runtime20 = require("react/jsx-runtime");
4485
+ function SmartStepEdge({
4486
+ id,
4487
+ source,
4488
+ target,
4489
+ sourceX,
4490
+ sourceY,
4491
+ targetX,
4492
+ targetY,
4493
+ sourcePosition,
4494
+ targetPosition,
4495
+ markerEnd,
4496
+ style
4497
+ }) {
4498
+ const bendY = (0, import_react21.useStore)((s) => {
4499
+ const src = s.nodeLookup.get(source);
4500
+ const tgt = s.nodeLookup.get(target);
4501
+ if (!src || !tgt) return null;
4502
+ const sourceBottom = src.internals.positionAbsolute.y + (src.measured.height ?? 0);
4503
+ const targetTop = tgt.internals.positionAbsolute.y;
4504
+ const others = [];
4505
+ for (const n of s.nodeLookup.values()) {
4506
+ if (n.id === source || n.id === target) continue;
4507
+ if (n.type === GROUP_CONTAINER_NODE_TYPE) continue;
4508
+ const top = n.internals.positionAbsolute.y;
4509
+ others.push({ top, bottom: top + (n.measured.height ?? 0) });
4510
+ }
4511
+ return staggeredBendY(sourceBottom, targetTop, others);
4512
+ });
4513
+ const [path] = (0, import_react21.getSmoothStepPath)({
4514
+ sourceX,
4515
+ sourceY,
4516
+ sourcePosition: sourcePosition ?? import_react22.Position.Bottom,
4517
+ targetX,
4518
+ targetY,
4519
+ targetPosition: targetPosition ?? import_react22.Position.Top,
4520
+ // Override the bend only for a staggered edge; otherwise let getSmoothStepPath
4521
+ // use its default centerY (== the built-in `smoothstep` path, byte-for-byte).
4522
+ ...bendY !== null ? { centerY: bendY } : {}
4523
+ });
4524
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react21.BaseEdge, { id, path, markerEnd, style });
4525
+ }
4526
+
4527
+ // src/components/FlowchartView/TracedFlow.tsx
4528
+ var import_jsx_runtime21 = require("react/jsx-runtime");
4096
4529
  var DEFAULT_COLORS = {
4097
4530
  default: rawDefaults.colors.textMuted,
4098
4531
  done: rawDefaults.colors.success,
@@ -4100,12 +4533,10 @@ var DEFAULT_COLORS = {
4100
4533
  error: rawDefaults.colors.error,
4101
4534
  loop: rawDefaults.colors.warning
4102
4535
  };
4103
- function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage, executedOrderIds) {
4104
- if (node.type !== void 0 && node.type !== "stage") {
4105
- return node;
4106
- }
4536
+ var EMPTY_SET = /* @__PURE__ */ new Set();
4537
+ function deriveOverlayFields(node, doneStageIds, activeStageId, errorMessage, executedOrderIds, coActiveStageIds) {
4107
4538
  const isDone = doneStageIds.has(node.id);
4108
- const isActive = activeStageId === node.id;
4539
+ const isActive = activeStageId === node.id || coActiveStageIds.has(node.id);
4109
4540
  const wasExecuted = isDone || isActive;
4110
4541
  const hasError = !!errorMessage;
4111
4542
  const dimmed = !wasExecuted && executedOrderIds.length > 0;
@@ -4117,21 +4548,62 @@ function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage,
4117
4548
  }
4118
4549
  if (nums.length > 0) stepNumbers = nums;
4119
4550
  }
4551
+ return {
4552
+ active: isActive,
4553
+ done: isDone,
4554
+ error: hasError,
4555
+ dimmed,
4556
+ ...errorMessage && { errorMessage },
4557
+ ...stepNumbers && { stepNumbers }
4558
+ };
4559
+ }
4560
+ function toStageNodeWithOverlay(node, doneStageIds, activeStageId, errorMessage, executedOrderIds, coActiveStageIds) {
4561
+ const overlayFields = deriveOverlayFields(
4562
+ node,
4563
+ doneStageIds,
4564
+ activeStageId,
4565
+ errorMessage,
4566
+ executedOrderIds,
4567
+ coActiveStageIds
4568
+ );
4569
+ const { dimmed } = overlayFields;
4570
+ if (node.type !== void 0 && node.type !== "stage") {
4571
+ const consumerData = node.data ?? {};
4572
+ const consumerActive = consumerData.active === true;
4573
+ const consumerDone = consumerData.done === true;
4574
+ const consumerError = consumerData.error === true;
4575
+ const finalActive = consumerActive || overlayFields.active;
4576
+ const finalDone = consumerDone || overlayFields.done;
4577
+ const finalError = consumerError || overlayFields.error;
4578
+ const finalDimmed = !finalActive && !finalDone && dimmed;
4579
+ return {
4580
+ ...node,
4581
+ data: {
4582
+ ...node.data,
4583
+ active: finalActive,
4584
+ done: finalDone,
4585
+ error: finalError,
4586
+ ...overlayFields.errorMessage !== void 0 && consumerData.errorMessage === void 0 && {
4587
+ errorMessage: overlayFields.errorMessage
4588
+ },
4589
+ ...finalDimmed && { dimmed: true },
4590
+ ...overlayFields.stepNumbers && { stepNumbers: overlayFields.stepNumbers }
4591
+ },
4592
+ ...finalDimmed && { style: { ...node.style ?? {}, opacity: 0.35 } }
4593
+ };
4594
+ }
4120
4595
  const stageData = {
4121
4596
  label: node.data.label,
4122
4597
  isDecider: node.data.isDecider,
4123
4598
  isFork: node.data.isFork,
4124
4599
  isSubflow: node.data.isSubflow,
4125
- active: isActive,
4126
- done: isDone,
4127
- error: hasError,
4600
+ ...overlayFields,
4128
4601
  ...node.data.description !== void 0 && { description: node.data.description },
4129
4602
  ...node.data.icon !== void 0 && { icon: node.data.icon },
4130
4603
  ...node.data.subflowId !== void 0 && { subflowId: node.data.subflowId },
4131
4604
  ...node.data.isLazy === true && { isLazy: true },
4132
- ...dimmed && { dimmed: true },
4133
- ...stepNumbers && { stepNumbers },
4134
- ...errorMessage && { errorMessage }
4605
+ ...node.data.emphasis !== void 0 && { emphasis: node.data.emphasis },
4606
+ ...node.data.size !== void 0 && { size: node.data.size }
4135
4607
  };
4136
4608
  return {
4137
4609
  ...node,
@@ -4152,23 +4624,27 @@ function styleEdgeWithOverlay(edge, doneStageIds, activeStageId, colors) {
4152
4624
  else if (traversed) color = colors.done;
4153
4625
  const styled = {
4154
4626
  ...edge,
4155
- type: "smoothstep",
4627
+ // Loop back-edges use the custom `loopBack` edge — a curve routed along the
4628
+ // right margin (clear of the spine). It reads node bounds from the store
4629
+ // and anchors on right edges itself, so it needs NO dedicated loop handles
4630
+ // on the node (the old approach broke for any node missing them).
4631
+ // Every other edge uses `smartStep`: a smoothstep superset that routes a
4632
+ // RANK-SKIPPING edge around the node it skips (else identical to smoothstep).
4633
+ type: kind === "loop" ? "loopBack" : "smartStep",
4156
4634
  animated: isLeadingEdge,
4157
4635
  style: { stroke: color, strokeWidth: traversed ? 2 : 1.5 },
4158
- markerEnd: { type: import_react22.MarkerType.ArrowClosed, color, width: 16, height: 16 }
4636
+ markerEnd: { type: import_react24.MarkerType.ArrowClosed, color, width: 16, height: 16 }
4159
4637
  };
4160
4638
  if (kind === "loop") {
4161
4639
  styled.style = { ...styled.style, strokeDasharray: "4 3" };
4162
- styled.data = {
4163
- ...styled.data ?? {},
4164
- pathOptions: { borderRadius: 14, offset: 36 }
4165
- };
4166
- styled.sourceHandle = "loop-source";
4167
- styled.targetHandle = "loop-target";
4168
4640
  }
4169
4641
  return styled;
4170
4642
  }
4171
- var DEFAULT_NODE_TYPES = { stageNode: StageNode };
4643
+ var DEFAULT_NODE_TYPES = {
4644
+ stageNode: StageNode,
4645
+ groupContainer: GroupContainerNode
4646
+ };
4647
+ var DEFAULT_EDGE_TYPES = { loopBack: LoopBackEdge, smartStep: SmartStepEdge };
4172
4648
  function TracedFlow({
4173
4649
  graph,
4174
4650
  overlay,
@@ -4177,35 +4653,64 @@ function TracedFlow({
4177
4653
  colors: colorOverrides,
4178
4654
  onNodeClick,
4179
4655
  onSubflowChange,
4656
+ groupedSubflows,
4657
+ mainChartBox,
4180
4658
  nodeTypes: userNodeTypes,
4181
4659
  edgeTypes: userEdgeTypes,
4660
+ coActiveStageIds,
4182
4661
  children,
4183
4662
  className,
4184
4663
  style
4185
4664
  }) {
4186
- const layout = layoutProp ?? defaultTraceFlowLayout;
4187
- const colors = (0, import_react21.useMemo)(
4665
+ const layout = layoutProp ?? dagreTraceLayout;
4666
+ const colors = (0, import_react23.useMemo)(
4188
4667
  () => ({ ...DEFAULT_COLORS, ...colorOverrides ?? {} }),
4189
4668
  [colorOverrides]
4190
4669
  );
4191
- const mergedNodeTypes = (0, import_react21.useMemo)(
4670
+ const mergedNodeTypes = (0, import_react23.useMemo)(
4192
4671
  () => userNodeTypes ? { ...DEFAULT_NODE_TYPES, ...userNodeTypes } : DEFAULT_NODE_TYPES,
4193
4672
  [userNodeTypes]
4194
4673
  );
4195
- const drill = useSubflowDrill(graph, onSubflowChange);
4196
- const filteredGraph = (0, import_react21.useMemo)(
4197
- () => filterGraphForDrill(graph, drill.currentSubflowId),
4198
- [graph, drill.currentSubflowId]
4674
+ const mergedEdgeTypes = (0, import_react23.useMemo)(
4675
+ () => userEdgeTypes ? { ...DEFAULT_EDGE_TYPES, ...userEdgeTypes } : DEFAULT_EDGE_TYPES,
4676
+ [userEdgeTypes]
4199
4677
  );
4200
- const breadcrumb = (0, import_react21.useMemo)(
4678
+ const drill = useSubflowDrill(graph, onSubflowChange);
4679
+ const groupedSet = (0, import_react23.useMemo)(() => new Set(groupedSubflows ?? []), [groupedSubflows]);
4680
+ const filteredGraph = (0, import_react23.useMemo)(() => {
4681
+ const base = filterGraphForDrill(graph, drill.currentSubflowId);
4682
+ if (groupedSet.size === 0) return base;
4683
+ const baseIds = new Set(base.nodes.map((n) => n.id));
4684
+ const extraNodes = graph.nodes.filter(
4685
+ (n) => n.data?.subflowOf !== void 0 && groupedSet.has(n.data.subflowOf) && !baseIds.has(n.id)
4686
+ );
4687
+ if (extraNodes.length === 0) return base;
4688
+ const allIds = /* @__PURE__ */ new Set([...baseIds, ...extraNodes.map((n) => n.id)]);
4689
+ const baseEdgeIds = new Set(base.edges.map((e) => e.id));
4690
+ const extraEdges = graph.edges.filter(
4691
+ (e) => !baseEdgeIds.has(e.id) && allIds.has(e.source) && allIds.has(e.target)
4692
+ );
4693
+ return { nodes: [...base.nodes, ...extraNodes], edges: [...base.edges, ...extraEdges] };
4694
+ }, [graph, drill.currentSubflowId, groupedSet]);
4695
+ const breadcrumb = (0, import_react23.useMemo)(
4201
4696
  () => buildSubflowBreadcrumb(graph, drill.currentSubflowId),
4202
4697
  [graph, drill.currentSubflowId]
4203
4698
  );
4204
- const positioned = (0, import_react21.useMemo)(
4205
- () => layout === "passthrough" ? filteredGraph : layout(filteredGraph),
4206
- [filteredGraph, layout]
4207
- );
4208
- const slice = (0, import_react21.useMemo)(() => {
4699
+ const positioned = (0, import_react23.useMemo)(() => {
4700
+ const realBase = layout === "passthrough" ? (g) => g : layout;
4701
+ if (groupedSet.size > 0) {
4702
+ const grouped = applyGroupLayout(filteredGraph, {
4703
+ groupedSubflowIds: [...groupedSet],
4704
+ baseLayout: realBase
4705
+ });
4706
+ return mainChartBox ? wrapInMainChartBox(grouped, { baseLayout: (g) => g, ...mainChartBox }) : grouped;
4707
+ }
4708
+ if (mainChartBox) {
4709
+ return wrapInMainChartBox(filteredGraph, { baseLayout: realBase, ...mainChartBox });
4710
+ }
4711
+ return layout === "passthrough" ? filteredGraph : layout(filteredGraph);
4712
+ }, [filteredGraph, layout, groupedSet, mainChartBox]);
4713
+ const slice = (0, import_react23.useMemo)(() => {
4209
4714
  const empty = {
4210
4715
  doneStageIds: /* @__PURE__ */ new Set(),
4211
4716
  activeStageId: null,
@@ -4215,41 +4720,41 @@ function TracedFlow({
4215
4720
  };
4216
4721
  if (!overlay) return empty;
4217
4722
  const idx = scrubIndex ?? Math.max(0, overlay.executionOrder.length - 1);
4218
- const normalized = normalizeSliceLeafIds(sliceOverlay(overlay, idx));
4219
- return aggregateMountStatus(normalized, graph, drill.currentSubflowId);
4723
+ return aggregateMountStatus(sliceOverlay(overlay, idx), graph, drill.currentSubflowId);
4220
4724
  }, [overlay, scrubIndex, graph, drill.currentSubflowId]);
4221
- const reactFlowNodes = (0, import_react21.useMemo)(
4725
+ const reactFlowNodes = (0, import_react23.useMemo)(
4222
4726
  () => positioned.nodes.map(
4223
4727
  (n) => toStageNodeWithOverlay(
4224
4728
  n,
4225
4729
  slice.doneStageIds,
4226
4730
  slice.activeStageId,
4227
4731
  slice.errors.get(n.id),
4228
- slice.executedOrderIds
4732
+ slice.executedOrderIds,
4733
+ coActiveStageIds ?? EMPTY_SET
4229
4734
  )
4230
4735
  ),
4231
- [positioned.nodes, slice]
4736
+ [positioned.nodes, slice, coActiveStageIds]
4232
4737
  );
4233
- const reactFlowEdges = (0, import_react21.useMemo)(
4738
+ const reactFlowEdges = (0, import_react23.useMemo)(
4234
4739
  () => positioned.edges.map(
4235
4740
  (e) => styleEdgeWithOverlay(e, slice.doneStageIds, slice.activeStageId, colors)
4236
4741
  ),
4237
4742
  [positioned.edges, slice, colors]
4238
4743
  );
4239
- const handleNodeClick = (0, import_react21.useCallback)(
4744
+ const handleNodeClick = (0, import_react23.useCallback)(
4240
4745
  (_, node) => {
4241
4746
  const data = node.data ?? {};
4242
- if (data.isSubflow && data.subflowId) {
4747
+ if (data.isSubflow && data.subflowId && !groupedSet.has(data.subflowId)) {
4243
4748
  drill.drillInto(data.subflowId);
4244
4749
  }
4245
4750
  onNodeClick?.(node.id);
4246
4751
  },
4247
- [drill, onNodeClick]
4752
+ [drill, onNodeClick, groupedSet]
4248
4753
  );
4249
- const wrapperRef = (0, import_react21.useRef)(null);
4250
- const [rfInstance, setRfInstance] = (0, import_react21.useState)(null);
4251
- useChartAutoRefit(wrapperRef, rfInstance);
4252
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
4754
+ const wrapperRef = (0, import_react23.useRef)(null);
4755
+ const [rfInstance, setRfInstance] = (0, import_react23.useState)(null);
4756
+ useChartAutoRefit(wrapperRef, rfInstance, { refitKey: drill.currentSubflowId });
4757
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4253
4758
  "div",
4254
4759
  {
4255
4760
  ref: wrapperRef,
@@ -4263,26 +4768,26 @@ function TracedFlow({
4263
4768
  ...style
4264
4769
  },
4265
4770
  children: [
4266
- breadcrumb.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
4771
+ breadcrumb.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4267
4772
  SubflowBreadcrumbBar,
4268
4773
  {
4269
4774
  entries: breadcrumb,
4270
4775
  onNavigate: drill.setCurrentSubflowId
4271
4776
  }
4272
4777
  ),
4273
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
4274
- import_react22.ReactFlow,
4778
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4779
+ import_react24.ReactFlow,
4275
4780
  {
4276
4781
  nodes: reactFlowNodes,
4277
4782
  edges: reactFlowEdges,
4278
4783
  nodeTypes: mergedNodeTypes,
4279
- ...userEdgeTypes && { edgeTypes: userEdgeTypes },
4784
+ edgeTypes: mergedEdgeTypes,
4280
4785
  onNodeClick: handleNodeClick,
4281
4786
  onInit: setRfInstance,
4282
4787
  fitView: true,
4283
4788
  proOptions: { hideAttribution: true },
4284
4789
  children: [
4285
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react22.Background, { variant: import_react22.BackgroundVariant.Dots, gap: 20, size: 1 }),
4790
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react24.Background, { variant: import_react24.BackgroundVariant.Dots, gap: 20, size: 1 }),
4286
4791
  children
4287
4792
  ]
4288
4793
  }
@@ -4293,20 +4798,20 @@ function TracedFlow({
4293
4798
  }
4294
4799
 
4295
4800
  // src/components/InspectorPanel/InspectorPanel.tsx
4296
- var import_react24 = require("react");
4801
+ var import_react26 = require("react");
4297
4802
 
4298
4803
  // src/components/DataTracePanel/DataTracePanel.tsx
4299
- var import_react23 = require("react");
4300
- var import_jsx_runtime20 = require("react/jsx-runtime");
4301
- var DataTracePanel = (0, import_react23.memo)(function DataTracePanel2({
4804
+ var import_react25 = require("react");
4805
+ var import_jsx_runtime22 = require("react/jsx-runtime");
4806
+ var DataTracePanel = (0, import_react25.memo)(function DataTracePanel2({
4302
4807
  frames,
4303
4808
  selectedStageId,
4304
4809
  onFrameClick,
4305
4810
  fromStageName
4306
4811
  }) {
4307
4812
  if (frames.length === 0) {
4308
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "14px 14px 12px", fontSize: 13, lineHeight: 1.55 }, children: [
4309
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4813
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "14px 14px 12px", fontSize: 13, lineHeight: 1.55 }, children: [
4814
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4310
4815
  "div",
4311
4816
  {
4312
4817
  style: {
@@ -4320,13 +4825,13 @@ var DataTracePanel = (0, import_react23.memo)(function DataTracePanel2({
4320
4825
  children: "Backward causal chain"
4321
4826
  }
4322
4827
  ),
4323
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("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." }),
4324
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { color: theme.textMuted, fontSize: 12 }, children: "Select a stage above to see its dependency chain." })
4828
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("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." }),
4829
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { color: theme.textMuted, fontSize: 12 }, children: "Select a stage above to see its dependency chain." })
4325
4830
  ] });
4326
4831
  }
4327
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "8px 0", fontSize: 13 }, children: [
4328
- fromStageName && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "4px 12px 8px" }, children: [
4329
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4832
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "8px 0", fontSize: 13 }, children: [
4833
+ fromStageName && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { padding: "4px 12px 8px" }, children: [
4834
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4330
4835
  "div",
4331
4836
  {
4332
4837
  style: {
@@ -4342,7 +4847,7 @@ var DataTracePanel = (0, import_react23.memo)(function DataTracePanel2({
4342
4847
  ]
4343
4848
  }
4344
4849
  ),
4345
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4850
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4346
4851
  "div",
4347
4852
  {
4348
4853
  style: {
@@ -4355,7 +4860,7 @@ var DataTracePanel = (0, import_react23.memo)(function DataTracePanel2({
4355
4860
  }
4356
4861
  )
4357
4862
  ] }),
4358
- frames.map((frame, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4863
+ frames.map((frame, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4359
4864
  DataTraceFrame,
4360
4865
  {
4361
4866
  frame,
@@ -4368,14 +4873,14 @@ var DataTracePanel = (0, import_react23.memo)(function DataTracePanel2({
4368
4873
  ))
4369
4874
  ] });
4370
4875
  });
4371
- var DataTraceFrame = (0, import_react23.memo)(function DataTraceFrame2({
4876
+ var DataTraceFrame = (0, import_react25.memo)(function DataTraceFrame2({
4372
4877
  frame,
4373
4878
  isFirst,
4374
4879
  isLast,
4375
4880
  isSelected,
4376
4881
  onClick
4377
4882
  }) {
4378
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4883
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4379
4884
  "button",
4380
4885
  {
4381
4886
  onClick: () => onClick?.(frame.runtimeStageId),
@@ -4392,9 +4897,9 @@ var DataTraceFrame = (0, import_react23.memo)(function DataTraceFrame2({
4392
4897
  fontSize: 13
4393
4898
  },
4394
4899
  children: [
4395
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
4396
- !isFirst && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { color: theme.textMuted, fontSize: 11 }, children: "\u2191" }),
4397
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4900
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
4901
+ !isFirst && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { color: theme.textMuted, fontSize: 11 }, children: "\u2191" }),
4902
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4398
4903
  "span",
4399
4904
  {
4400
4905
  style: {
@@ -4404,7 +4909,7 @@ var DataTraceFrame = (0, import_react23.memo)(function DataTraceFrame2({
4404
4909
  children: frame.stageName
4405
4910
  }
4406
4911
  ),
4407
- isLast && !isFirst && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4912
+ isLast && !isFirst && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4408
4913
  "span",
4409
4914
  {
4410
4915
  style: {
@@ -4416,7 +4921,7 @@ var DataTraceFrame = (0, import_react23.memo)(function DataTraceFrame2({
4416
4921
  }
4417
4922
  )
4418
4923
  ] }),
4419
- frame.keysWritten.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4924
+ frame.keysWritten.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4420
4925
  "div",
4421
4926
  {
4422
4927
  style: {
@@ -4428,11 +4933,11 @@ var DataTraceFrame = (0, import_react23.memo)(function DataTraceFrame2({
4428
4933
  children: [
4429
4934
  "wrote:",
4430
4935
  " ",
4431
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { color: theme.textSecondary }, children: frame.keysWritten.join(", ") })
4936
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { style: { color: theme.textSecondary }, children: frame.keysWritten.join(", ") })
4432
4937
  ]
4433
4938
  }
4434
4939
  ),
4435
- frame.linkedBy && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4940
+ frame.linkedBy && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4436
4941
  "div",
4437
4942
  {
4438
4943
  style: {
@@ -4453,17 +4958,17 @@ var DataTraceFrame = (0, import_react23.memo)(function DataTraceFrame2({
4453
4958
  });
4454
4959
 
4455
4960
  // src/components/InspectorPanel/InspectorPanel.tsx
4456
- var import_jsx_runtime21 = require("react/jsx-runtime");
4457
- var InspectorPanel = (0, import_react24.memo)(function InspectorPanel2({
4961
+ var import_jsx_runtime23 = require("react/jsx-runtime");
4962
+ var InspectorPanel = (0, import_react26.memo)(function InspectorPanel2({
4458
4963
  snapshots,
4459
4964
  selectedIndex,
4460
4965
  dataTraceFrames,
4461
4966
  selectedStageId,
4462
4967
  onNavigateToStage
4463
4968
  }) {
4464
- const [tab, setTab] = (0, import_react24.useState)("state");
4969
+ const [tab, setTab] = (0, import_react26.useState)("state");
4465
4970
  const currentSnapshot = snapshots[selectedIndex];
4466
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4971
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4467
4972
  "div",
4468
4973
  {
4469
4974
  style: {
@@ -4473,7 +4978,7 @@ var InspectorPanel = (0, import_react24.memo)(function InspectorPanel2({
4473
4978
  overflow: "hidden"
4474
4979
  },
4475
4980
  children: [
4476
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4981
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4477
4982
  "div",
4478
4983
  {
4479
4984
  style: {
@@ -4482,7 +4987,7 @@ var InspectorPanel = (0, import_react24.memo)(function InspectorPanel2({
4482
4987
  flexShrink: 0
4483
4988
  },
4484
4989
  children: [
4485
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4990
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4486
4991
  TabButton,
4487
4992
  {
4488
4993
  active: tab === "state",
@@ -4490,7 +4995,7 @@ var InspectorPanel = (0, import_react24.memo)(function InspectorPanel2({
4490
4995
  label: "State"
4491
4996
  }
4492
4997
  ),
4493
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4998
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4494
4999
  TabButton,
4495
5000
  {
4496
5001
  active: tab === "trace",
@@ -4502,15 +5007,15 @@ var InspectorPanel = (0, import_react24.memo)(function InspectorPanel2({
4502
5007
  ]
4503
5008
  }
4504
5009
  ),
4505
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { style: { flex: 1, overflow: "auto" }, children: [
4506
- tab === "state" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5010
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { flex: 1, overflow: "auto" }, children: [
5011
+ tab === "state" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4507
5012
  MemoryPanel,
4508
5013
  {
4509
5014
  snapshots,
4510
5015
  selectedIndex
4511
5016
  }
4512
5017
  ),
4513
- tab === "trace" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5018
+ tab === "trace" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4514
5019
  DataTracePanel,
4515
5020
  {
4516
5021
  frames: dataTraceFrames,
@@ -4530,7 +5035,7 @@ function TabButton({
4530
5035
  label,
4531
5036
  badge
4532
5037
  }) {
4533
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
5038
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4534
5039
  "button",
4535
5040
  {
4536
5041
  onClick,
@@ -4549,7 +5054,7 @@ function TabButton({
4549
5054
  },
4550
5055
  children: [
4551
5056
  label,
4552
- badge && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5057
+ badge && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4553
5058
  "span",
4554
5059
  {
4555
5060
  style: {
@@ -4569,28 +5074,28 @@ function TabButton({
4569
5074
  }
4570
5075
 
4571
5076
  // src/components/InsightPanel/InsightPanel.tsx
4572
- var import_react25 = require("react");
4573
- var import_jsx_runtime22 = require("react/jsx-runtime");
4574
- var InsightPanel = (0, import_react25.memo)(function InsightPanel2({
5077
+ var import_react27 = require("react");
5078
+ var import_jsx_runtime24 = require("react/jsx-runtime");
5079
+ var InsightPanel = (0, import_react27.memo)(function InsightPanel2({
4575
5080
  insights,
4576
5081
  expandedId,
4577
5082
  mode
4578
5083
  }) {
4579
5084
  if (insights.length === 0) {
4580
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { padding: 12, color: theme.textMuted, fontSize: 13 }, children: "No insights available. Attach recorders to see data." });
5085
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { padding: 12, color: theme.textMuted, fontSize: 13 }, children: "No insights available. Attach recorders to see data." });
4581
5086
  }
4582
5087
  if (mode === "grid") {
4583
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(InsightGrid, { insights });
5088
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(InsightGrid, { insights });
4584
5089
  }
4585
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(InsightTabs, { insights, defaultId: expandedId });
5090
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(InsightTabs, { insights, defaultId: expandedId });
4586
5091
  });
4587
- var InsightTabs = (0, import_react25.memo)(function InsightTabs2({
5092
+ var InsightTabs = (0, import_react27.memo)(function InsightTabs2({
4588
5093
  insights,
4589
5094
  defaultId
4590
5095
  }) {
4591
- const [activeId, setActiveId] = (0, import_react25.useState)(defaultId ?? insights[0]?.id);
5096
+ const [activeId, setActiveId] = (0, import_react27.useState)(defaultId ?? insights[0]?.id);
4592
5097
  const active = insights.find((i) => i.id === activeId) ?? insights[0];
4593
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5098
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
4594
5099
  "div",
4595
5100
  {
4596
5101
  style: {
@@ -4600,7 +5105,7 @@ var InsightTabs = (0, import_react25.memo)(function InsightTabs2({
4600
5105
  overflow: "hidden"
4601
5106
  },
4602
5107
  children: [
4603
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5108
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4604
5109
  "div",
4605
5110
  {
4606
5111
  style: {
@@ -4609,7 +5114,7 @@ var InsightTabs = (0, import_react25.memo)(function InsightTabs2({
4609
5114
  flexShrink: 0,
4610
5115
  overflowX: "auto"
4611
5116
  },
4612
- children: insights.map((insight) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5117
+ children: insights.map((insight) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4613
5118
  "button",
4614
5119
  {
4615
5120
  onClick: () => setActiveId(insight.id),
@@ -4630,16 +5135,16 @@ var InsightTabs = (0, import_react25.memo)(function InsightTabs2({
4630
5135
  ))
4631
5136
  }
4632
5137
  ),
4633
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: active?.render() })
5138
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: active?.render() })
4634
5139
  ]
4635
5140
  }
4636
5141
  );
4637
5142
  });
4638
- var InsightGrid = (0, import_react25.memo)(function InsightGrid2({
5143
+ var InsightGrid = (0, import_react27.memo)(function InsightGrid2({
4639
5144
  insights
4640
5145
  }) {
4641
5146
  const cols = insights.length <= 2 ? 1 : 2;
4642
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5147
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4643
5148
  "div",
4644
5149
  {
4645
5150
  style: {
@@ -4650,7 +5155,7 @@ var InsightGrid = (0, import_react25.memo)(function InsightGrid2({
4650
5155
  gap: 1,
4651
5156
  background: theme.border
4652
5157
  },
4653
- children: insights.map((insight) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5158
+ children: insights.map((insight) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
4654
5159
  "div",
4655
5160
  {
4656
5161
  style: {
@@ -4660,7 +5165,7 @@ var InsightGrid = (0, import_react25.memo)(function InsightGrid2({
4660
5165
  overflow: "hidden"
4661
5166
  },
4662
5167
  children: [
4663
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5168
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
4664
5169
  "div",
4665
5170
  {
4666
5171
  style: {
@@ -4675,7 +5180,7 @@ var InsightGrid = (0, import_react25.memo)(function InsightGrid2({
4675
5180
  },
4676
5181
  children: [
4677
5182
  insight.name,
4678
- insight.summary && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5183
+ insight.summary && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4679
5184
  "span",
4680
5185
  {
4681
5186
  style: {
@@ -4690,7 +5195,7 @@ var InsightGrid = (0, import_react25.memo)(function InsightGrid2({
4690
5195
  ]
4691
5196
  }
4692
5197
  ),
4693
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: insight.render() })
5198
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: insight.render() })
4694
5199
  ]
4695
5200
  },
4696
5201
  insight.id
@@ -4700,17 +5205,17 @@ var InsightGrid = (0, import_react25.memo)(function InsightGrid2({
4700
5205
  });
4701
5206
 
4702
5207
  // src/components/CompactTimeline/CompactTimeline.tsx
4703
- var import_react26 = require("react");
4704
- var import_jsx_runtime23 = require("react/jsx-runtime");
4705
- var CompactTimeline = (0, import_react26.memo)(function CompactTimeline2({
5208
+ var import_react28 = require("react");
5209
+ var import_jsx_runtime25 = require("react/jsx-runtime");
5210
+ var CompactTimeline = (0, import_react28.memo)(function CompactTimeline2({
4706
5211
  snapshots,
4707
5212
  selectedIndex,
4708
5213
  defaultExpanded = false
4709
5214
  }) {
4710
- const [expanded, setExpanded] = (0, import_react26.useState)(defaultExpanded);
5215
+ const [expanded, setExpanded] = (0, import_react28.useState)(defaultExpanded);
4711
5216
  if (snapshots.length === 0) return null;
4712
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { borderTop: `1px solid ${theme.border}` }, children: [
4713
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
5217
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { borderTop: `1px solid ${theme.border}` }, children: [
5218
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
4714
5219
  "button",
4715
5220
  {
4716
5221
  onClick: () => setExpanded((e) => !e),
@@ -4730,13 +5235,13 @@ var CompactTimeline = (0, import_react26.memo)(function CompactTimeline2({
4730
5235
  letterSpacing: "0.5px"
4731
5236
  },
4732
5237
  children: [
4733
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { fontSize: 10 }, children: expanded ? "\u25BC" : "\u25B8" }),
5238
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: { fontSize: 10 }, children: expanded ? "\u25BC" : "\u25B8" }),
4734
5239
  "Timeline",
4735
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { style: { fontWeight: 400, fontSize: 10 }, children: [
5240
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { style: { fontWeight: 400, fontSize: 10 }, children: [
4736
5241
  snapshots.length,
4737
5242
  " stages"
4738
5243
  ] }),
4739
- !expanded && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
5244
+ !expanded && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
4740
5245
  "div",
4741
5246
  {
4742
5247
  style: {
@@ -4747,7 +5252,7 @@ var CompactTimeline = (0, import_react26.memo)(function CompactTimeline2({
4747
5252
  marginLeft: 8
4748
5253
  },
4749
5254
  children: [
4750
- snapshots.map((snap, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5255
+ snapshots.map((snap, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4751
5256
  "div",
4752
5257
  {
4753
5258
  style: {
@@ -4762,7 +5267,7 @@ var CompactTimeline = (0, import_react26.memo)(function CompactTimeline2({
4762
5267
  },
4763
5268
  i
4764
5269
  )),
4765
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5270
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4766
5271
  "div",
4767
5272
  {
4768
5273
  style: {
@@ -4780,7 +5285,7 @@ var CompactTimeline = (0, import_react26.memo)(function CompactTimeline2({
4780
5285
  ]
4781
5286
  }
4782
5287
  ),
4783
- expanded && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { padding: "0 12px 8px" }, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5288
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { padding: "0 12px 8px" }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4784
5289
  GanttTimeline,
4785
5290
  {
4786
5291
  snapshots,
@@ -4791,21 +5296,21 @@ var CompactTimeline = (0, import_react26.memo)(function CompactTimeline2({
4791
5296
  });
4792
5297
 
4793
5298
  // src/components/ExplainableShell/ExplainableShell.tsx
4794
- var import_jsx_runtime24 = require("react/jsx-runtime");
4795
- var HLinePill = (0, import_react27.memo)(function HLinePill2({
5299
+ var import_jsx_runtime26 = require("react/jsx-runtime");
5300
+ var HLinePill = (0, import_react29.memo)(function HLinePill2({
4796
5301
  label,
4797
5302
  detail,
4798
5303
  expanded,
4799
5304
  onClick
4800
5305
  }) {
4801
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: {
5306
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: {
4802
5307
  display: "flex",
4803
5308
  alignItems: "center",
4804
5309
  gap: 0,
4805
5310
  padding: "0"
4806
5311
  }, children: [
4807
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, height: 1, background: theme.border } }),
4808
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5312
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, height: 1, background: theme.border } }),
5313
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4809
5314
  "button",
4810
5315
  {
4811
5316
  onClick,
@@ -4829,31 +5334,31 @@ var HLinePill = (0, import_react27.memo)(function HLinePill2({
4829
5334
  transition: "color 0.15s ease"
4830
5335
  },
4831
5336
  children: [
4832
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 7 }, children: expanded ? "\u25BC" : "\u25B6" }),
5337
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { fontSize: 7 }, children: expanded ? "\u25BC" : "\u25B6" }),
4833
5338
  label,
4834
- detail && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontWeight: 400, opacity: 0.5, fontSize: 9 }, children: detail })
5339
+ detail && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { fontWeight: 400, opacity: 0.5, fontSize: 9 }, children: detail })
4835
5340
  ]
4836
5341
  }
4837
5342
  ),
4838
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, height: 1, background: theme.border } })
5343
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, height: 1, background: theme.border } })
4839
5344
  ] });
4840
5345
  });
4841
- var VLinePill = (0, import_react27.memo)(function VLinePill2({
5346
+ var VLinePill = (0, import_react29.memo)(function VLinePill2({
4842
5347
  label,
4843
5348
  expanded,
4844
5349
  side = "right",
4845
5350
  onClick
4846
5351
  }) {
4847
5352
  const arrow = side === "right" ? expanded ? "\u25B6" : "\u25C0" : expanded ? "\u25C0" : "\u25B6";
4848
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: {
5353
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: {
4849
5354
  display: "flex",
4850
5355
  flexDirection: "column",
4851
5356
  alignItems: "center",
4852
5357
  gap: 0,
4853
5358
  padding: "0"
4854
5359
  }, children: [
4855
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, width: 1, background: theme.border } }),
4856
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5360
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, width: 1, background: theme.border } }),
5361
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4857
5362
  "button",
4858
5363
  {
4859
5364
  onClick,
@@ -4878,12 +5383,12 @@ var VLinePill = (0, import_react27.memo)(function VLinePill2({
4878
5383
  transition: "color 0.15s ease"
4879
5384
  },
4880
5385
  children: [
4881
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontSize: 7, writingMode: "horizontal-tb" }, children: arrow }),
5386
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { fontSize: 7, writingMode: "horizontal-tb" }, children: arrow }),
4882
5387
  label
4883
5388
  ]
4884
5389
  }
4885
5390
  ),
4886
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, width: 1, background: theme.border } })
5391
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, width: 1, background: theme.border } })
4887
5392
  ] });
4888
5393
  });
4889
5394
  function detectKeyedSteps(data) {
@@ -4920,9 +5425,9 @@ function KeyedRecorderView({
4920
5425
  snapshots,
4921
5426
  selectedIndex
4922
5427
  }) {
4923
- const [showAggregate, setShowAggregate] = (0, import_react27.useState)(false);
4924
- const detected = (0, import_react27.useMemo)(() => detectKeyedSteps(data), [data]);
4925
- const visibleKeys = (0, import_react27.useMemo)(() => {
5428
+ const [showAggregate, setShowAggregate] = (0, import_react29.useState)(false);
5429
+ const detected = (0, import_react29.useMemo)(() => detectKeyedSteps(data), [data]);
5430
+ const visibleKeys = (0, import_react29.useMemo)(() => {
4926
5431
  const keys = /* @__PURE__ */ new Set();
4927
5432
  for (let i = 0; i <= selectedIndex && i < snapshots.length; i++) {
4928
5433
  const snap = snapshots[i];
@@ -4937,7 +5442,7 @@ function KeyedRecorderView({
4937
5442
  }, [snapshots, selectedIndex, detected?.keyType]);
4938
5443
  const isAtEnd = selectedIndex >= snapshots.length - 1;
4939
5444
  if (!detected) {
4940
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("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) });
5445
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("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) });
4941
5446
  }
4942
5447
  const steps = detected.steps;
4943
5448
  const hints = extractRenderHints(data);
@@ -4951,13 +5456,13 @@ function KeyedRecorderView({
4951
5456
  }
4952
5457
  }
4953
5458
  const grandTotal = hints?.grandTotal ?? 0;
4954
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { overflow: "auto", height: "100%", display: "flex", flexDirection: "column" }, children: [
4955
- description && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { padding: "6px 12px", fontSize: 11, color: theme.textMuted, fontStyle: "italic", borderBottom: `1px solid ${theme.border}`, flexShrink: 0 }, children: description }),
4956
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: 12, flex: 1, overflow: "auto" }, children: [
5459
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { overflow: "auto", height: "100%", display: "flex", flexDirection: "column" }, children: [
5460
+ description && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { padding: "6px 12px", fontSize: 11, color: theme.textMuted, fontStyle: "italic", borderBottom: `1px solid ${theme.border}`, flexShrink: 0 }, children: description }),
5461
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { padding: 12, flex: 1, overflow: "auto" }, children: [
4957
5462
  preferredOperation === "aggregate" ? (
4958
5463
  /* AGGREGATE: collect silently during scrub, button at end to reveal total */
4959
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
4960
- isAtEnd ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { marginBottom: 16 }, children: !showAggregate ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5464
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5465
+ isAtEnd ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { marginBottom: 16 }, children: !showAggregate ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4961
5466
  "button",
4962
5467
  {
4963
5468
  onClick: () => setShowAggregate(true),
@@ -4975,35 +5480,35 @@ function KeyedRecorderView({
4975
5480
  },
4976
5481
  children: "Aggregate \u2014 Show Grand Total"
4977
5482
  }
4978
- ) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: "14px 16px", background: `color-mix(in srgb, ${theme.success} 12%, transparent)`, borderRadius: 8, border: `1px solid ${theme.success}44` }, children: [
4979
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Aggregate \u2014 grand total" }),
4980
- numFieldKey && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { fontSize: 26, fontWeight: 700, color: theme.success }, children: [
5483
+ ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { padding: "14px 16px", background: `color-mix(in srgb, ${theme.success} 12%, transparent)`, borderRadius: 8, border: `1px solid ${theme.success}44` }, children: [
5484
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Aggregate \u2014 grand total" }),
5485
+ numFieldKey && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { fontSize: 26, fontWeight: 700, color: theme.success }, children: [
4981
5486
  grandTotal < 1 ? grandTotal.toFixed(3) : grandTotal.toFixed(1),
4982
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { style: { fontSize: 11, color: theme.textMuted, fontWeight: 400, marginLeft: 8 }, children: [
5487
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { style: { fontSize: 11, color: theme.textMuted, fontWeight: 400, marginLeft: 8 }, children: [
4983
5488
  numFieldKey,
4984
5489
  " \xB7 ",
4985
5490
  allKeys.length,
4986
5491
  " steps"
4987
5492
  ] })
4988
5493
  ] })
4989
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.textMuted} 6%, transparent)`, borderRadius: 6, marginBottom: 16, border: `1px dashed ${theme.border}` }, children: [
4990
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", fontWeight: 600 }, children: "Collecting data..." }),
4991
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { fontSize: 11, color: theme.textMuted, marginTop: 4 }, children: [
5494
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.textMuted} 6%, transparent)`, borderRadius: 6, marginBottom: 16, border: `1px dashed ${theme.border}` }, children: [
5495
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", fontWeight: 600 }, children: "Collecting data..." }),
5496
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { fontSize: 11, color: theme.textMuted, marginTop: 4 }, children: [
4992
5497
  visibleEntries.length,
4993
5498
  " of ",
4994
5499
  allKeys.length,
4995
5500
  " steps collected. Scrub to end to aggregate."
4996
5501
  ] })
4997
5502
  ] }),
4998
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
5503
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
4999
5504
  ] })
5000
5505
  ) : preferredOperation === "accumulate" ? (
5001
5506
  /* ACCUMULATE: running total grows with slider — IS the total at end, no button */
5002
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5003
- numFieldKey && visibleEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.primary} 8%, transparent)`, borderRadius: 6, marginBottom: 16 }, children: [
5004
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("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" }),
5005
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontWeight: 700, fontSize: 18, color: theme.primary }, children: runningTotal < 1 ? runningTotal.toFixed(3) : runningTotal.toFixed(1) }),
5006
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { style: { color: theme.textMuted, marginLeft: 8, fontSize: 10 }, children: [
5507
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5508
+ numFieldKey && visibleEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { padding: "10px 14px", background: `color-mix(in srgb, ${theme.primary} 8%, transparent)`, borderRadius: 6, marginBottom: 16 }, children: [
5509
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("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" }),
5510
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { fontWeight: 700, fontSize: 18, color: theme.primary }, children: runningTotal < 1 ? runningTotal.toFixed(3) : runningTotal.toFixed(1) }),
5511
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { style: { color: theme.textMuted, marginLeft: 8, fontSize: 10 }, children: [
5007
5512
  numFieldKey,
5008
5513
  " \xB7 ",
5009
5514
  visibleEntries.length,
@@ -5012,27 +5517,27 @@ function KeyedRecorderView({
5012
5517
  " steps"
5013
5518
  ] })
5014
5519
  ] }),
5015
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
5520
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Per-step detail" })
5016
5521
  ] })
5017
5522
  ) : (
5018
5523
  /* TRANSLATE: per-step entries prominent, no totals */
5019
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Translate \u2014 per-step detail" })
5524
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { fontSize: 10, color: theme.textMuted, textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 6, fontWeight: 600 }, children: "Translate \u2014 per-step detail" })
5020
5525
  ),
5021
5526
  visibleEntries.map((key) => {
5022
5527
  const entry = steps[key];
5023
5528
  const label = entry.stageName ?? key;
5024
5529
  const numVal = numFieldKey ? entry[numFieldKey] : void 0;
5025
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "4px 0", fontSize: 12, fontFamily: theme.fontMono, borderBottom: `1px solid ${theme.border}22` }, children: [
5026
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { color: theme.textMuted, width: 140, flexShrink: 0, fontSize: 10 }, children: key }),
5027
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { fontWeight: 600, flex: 1 }, children: label }),
5028
- numVal !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { style: { color: theme.primary, fontWeight: 700, marginLeft: 8 }, children: numVal < 1 ? numVal.toFixed(3) : numVal.toFixed(1) })
5530
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { display: "flex", alignItems: "center", padding: "4px 0", fontSize: 12, fontFamily: theme.fontMono, borderBottom: `1px solid ${theme.border}22` }, children: [
5531
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { color: theme.textMuted, width: 140, flexShrink: 0, fontSize: 10 }, children: key }),
5532
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { fontWeight: 600, flex: 1 }, children: label }),
5533
+ numVal !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { color: theme.primary, fontWeight: 700, marginLeft: 8 }, children: numVal < 1 ? numVal.toFixed(3) : numVal.toFixed(1) })
5029
5534
  ] }, key);
5030
5535
  }),
5031
- visibleEntries.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", padding: "8px 0" }, children: "Scrub the slider to reveal entries..." })
5536
+ visibleEntries.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { color: theme.textMuted, fontSize: 11, fontStyle: "italic", padding: "8px 0" }, children: "Scrub the slider to reveal entries..." })
5032
5537
  ] })
5033
5538
  ] });
5034
5539
  }
5035
- var DetailsContent = (0, import_react27.memo)(function DetailsContent2({
5540
+ var DetailsContent = (0, import_react29.memo)(function DetailsContent2({
5036
5541
  snapshots,
5037
5542
  selectedIndex,
5038
5543
  narrativeEntries,
@@ -5044,27 +5549,27 @@ var DetailsContent = (0, import_react27.memo)(function DetailsContent2({
5044
5549
  {
5045
5550
  id: "memory",
5046
5551
  name: "Memory",
5047
- render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MemoryPanel, { snapshots: snaps, selectedIndex: idx, size, style: fillHeight ? { height: "100%" } : void 0 })
5552
+ render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MemoryPanel, { snapshots: snaps, selectedIndex: idx, size, style: fillHeight ? { height: "100%" } : void 0 })
5048
5553
  },
5049
5554
  {
5050
5555
  id: "narrative",
5051
5556
  name: "Narrative",
5052
- render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots: snaps, selectedIndex: idx, narrativeEntries, size, style: fillHeight ? { height: "100%" } : void 0 })
5557
+ render: ({ snapshots: snaps, selectedIndex: idx }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(NarrativePanel, { snapshots: snaps, selectedIndex: idx, narrativeEntries, size, style: fillHeight ? { height: "100%" } : void 0 })
5053
5558
  }
5054
5559
  ];
5055
5560
  const allViews = [...builtInViews, ...extraViews ?? []];
5056
- const [activeViewId, setActiveViewId] = (0, import_react27.useState)(allViews[0]?.id ?? "memory");
5561
+ const [activeViewId, setActiveViewId] = (0, import_react29.useState)(allViews[0]?.id ?? "memory");
5057
5562
  const viewIds = allViews.map((v2) => v2.id).join(",");
5058
- (0, import_react27.useEffect)(() => {
5563
+ (0, import_react29.useEffect)(() => {
5059
5564
  if (!allViews.find((v2) => v2.id === activeViewId)) {
5060
5565
  setActiveViewId(allViews[0]?.id ?? "memory");
5061
5566
  }
5062
5567
  }, [viewIds]);
5063
5568
  const activeView = allViews.find((v2) => v2.id === activeViewId) ?? allViews[0];
5064
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }, children: [
5065
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { display: "flex", borderBottom: `1px solid ${theme.border}`, flexShrink: 0, overflowX: "auto" }, children: allViews.map((view) => {
5569
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }, children: [
5570
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { display: "flex", borderBottom: `1px solid ${theme.border}`, flexShrink: 0, overflowX: "auto" }, children: allViews.map((view) => {
5066
5571
  const active = view.id === activeViewId;
5067
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5572
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5068
5573
  "button",
5069
5574
  {
5070
5575
  onClick: () => setActiveViewId(view.id),
@@ -5088,7 +5593,7 @@ var DetailsContent = (0, import_react27.memo)(function DetailsContent2({
5088
5593
  view.id
5089
5594
  );
5090
5595
  }) }),
5091
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: activeView?.render({ snapshots, selectedIndex }) })
5596
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: activeView?.render({ snapshots, selectedIndex }) })
5092
5597
  ] });
5093
5598
  });
5094
5599
  function resolveSubflowLevel(parentSpec, parentSnapshots, subflowNodeName, narrativeEntries) {
@@ -5162,7 +5667,7 @@ function buildDataTrace(commitLog, targetRuntimeStageId, maxDepth = 10) {
5162
5667
  }
5163
5668
  return frames;
5164
5669
  }
5165
- var RightPanel = (0, import_react27.memo)(function RightPanel2({
5670
+ var RightPanel = (0, import_react29.memo)(function RightPanel2({
5166
5671
  mode,
5167
5672
  onModeChange,
5168
5673
  snapshots,
@@ -5177,13 +5682,13 @@ var RightPanel = (0, import_react27.memo)(function RightPanel2({
5177
5682
  size,
5178
5683
  onNavigateToStage
5179
5684
  }) {
5180
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5181
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: {
5685
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5686
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: {
5182
5687
  display: "flex",
5183
5688
  borderBottom: `1px solid ${theme.border}`,
5184
5689
  flexShrink: 0,
5185
5690
  background: theme.bgSecondary
5186
- }, children: ["insights", "what"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5691
+ }, children: ["insights", "what"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5187
5692
  "button",
5188
5693
  {
5189
5694
  onClick: () => onModeChange(m),
@@ -5205,7 +5710,7 @@ var RightPanel = (0, import_react27.memo)(function RightPanel2({
5205
5710
  },
5206
5711
  m
5207
5712
  )) }),
5208
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: mode === "insights" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5713
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, overflow: "hidden" }, children: mode === "insights" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5209
5714
  InsightPanel,
5210
5715
  {
5211
5716
  mode: "tabs",
@@ -5214,16 +5719,16 @@ var RightPanel = (0, import_react27.memo)(function RightPanel2({
5214
5719
  id: tab.id,
5215
5720
  name: insightName(tab.name),
5216
5721
  render: () => {
5217
- if (tab.id === "narrative") return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, runtimeSnapshot, spec, size, style: { height: "100%" } });
5722
+ if (tab.id === "narrative") return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(NarrativePanel, { snapshots, selectedIndex, narrativeEntries: activeNarrativeEntries, runtimeSnapshot, spec, size, style: { height: "100%" } });
5218
5723
  const customView = recorderViews?.find((v2) => v2.id === tab.id);
5219
5724
  if (customView?.render) return customView.render({ snapshots, selectedIndex });
5220
5725
  const autoView = autoRecorderViews.find((v2) => v2.id === tab.id);
5221
- if (autoView) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(KeyedRecorderView, { data: autoView.data, description: autoView.description, preferredOperation: autoView.preferredOperation, snapshots, selectedIndex });
5726
+ if (autoView) return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(KeyedRecorderView, { data: autoView.data, description: autoView.description, preferredOperation: autoView.preferredOperation, snapshots, selectedIndex });
5222
5727
  return null;
5223
5728
  }
5224
5729
  }))
5225
5730
  }
5226
- ) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5731
+ ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5227
5732
  InspectorPanel,
5228
5733
  {
5229
5734
  snapshots,
@@ -5269,7 +5774,7 @@ function ExplainableShell({
5269
5774
  className,
5270
5775
  style
5271
5776
  }) {
5272
- const derivedFromRuntime = (0, import_react27.useMemo)(() => {
5777
+ const derivedFromRuntime = (0, import_react29.useMemo)(() => {
5273
5778
  if (!runtimeSnapshot) return null;
5274
5779
  try {
5275
5780
  const snaps = toVisualizationSnapshots(runtimeSnapshot, narrativeEntries);
@@ -5280,7 +5785,7 @@ function ExplainableShell({
5280
5785
  }, [runtimeSnapshot, narrativeEntries]);
5281
5786
  const snapshots = snapshotsProp ?? derivedFromRuntime?.snapshots ?? [];
5282
5787
  const resultData = resultDataProp ?? derivedFromRuntime?.resultData ?? null;
5283
- const tracedFlowRenderer = (0, import_react27.useMemo)(() => {
5788
+ const tracedFlowRenderer = (0, import_react29.useMemo)(() => {
5284
5789
  if (!traceGraph) return void 0;
5285
5790
  return ({ selectedIndex, snapshots: snapshots2, onNodeClick }) => {
5286
5791
  const activeRsid = snapshots2[selectedIndex]?.runtimeStageId;
@@ -5291,7 +5796,7 @@ function ExplainableShell({
5291
5796
  );
5292
5797
  if (i >= 0) overlayIdx = i;
5293
5798
  }
5294
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5799
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5295
5800
  TracedFlow,
5296
5801
  {
5297
5802
  graph: traceGraph,
@@ -5309,10 +5814,10 @@ function ExplainableShell({
5309
5814
  const leftLabel = panelLabels?.topology ?? "Topology";
5310
5815
  const rightLabel = panelLabels?.details ?? "Details";
5311
5816
  const bottomLabel = panelLabels?.timeline ?? "Timeline";
5312
- const shellRef = (0, import_react27.useRef)(null);
5313
- const [isNarrow, setIsNarrow] = (0, import_react27.useState)(false);
5314
- const [isMedium, setIsMedium] = (0, import_react27.useState)(false);
5315
- (0, import_react27.useEffect)(() => {
5817
+ const shellRef = (0, import_react29.useRef)(null);
5818
+ const [isNarrow, setIsNarrow] = (0, import_react29.useState)(false);
5819
+ const [isMedium, setIsMedium] = (0, import_react29.useState)(false);
5820
+ (0, import_react29.useEffect)(() => {
5316
5821
  const el = shellRef.current;
5317
5822
  if (!el) return;
5318
5823
  const ro = new ResizeObserver(([entry]) => {
@@ -5324,14 +5829,14 @@ function ExplainableShell({
5324
5829
  ro.observe(el);
5325
5830
  return () => ro.disconnect();
5326
5831
  }, []);
5327
- const autoRecorderViews = (0, import_react27.useMemo)(() => {
5832
+ const autoRecorderViews = (0, import_react29.useMemo)(() => {
5328
5833
  const recorders = runtimeSnapshot?.recorders;
5329
5834
  if (!recorders?.length) return [];
5330
5835
  const explicitIds = new Set((recorderViews ?? []).map((v2) => v2.id));
5331
5836
  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 }));
5332
5837
  }, [runtimeSnapshot, recorderViews]);
5333
5838
  const hasNarrative = !!narrativeEntries?.length;
5334
- const allTabs = (0, import_react27.useMemo)(() => {
5839
+ const allTabs = (0, import_react29.useMemo)(() => {
5335
5840
  const tabs2 = [
5336
5841
  { id: "result", name: "Result", description: "Final output and console logs" },
5337
5842
  { id: "memory", name: "Memory", description: "Accumulator \u2014 progressive shared state at each stage" }
@@ -5350,38 +5855,38 @@ function ExplainableShell({
5350
5855
  }, [hasNarrative, recorderViews, autoRecorderViews, hideTabsProp]);
5351
5856
  const validTabIds = new Set(allTabs.map((t) => t.id));
5352
5857
  const resolvedDefault = defaultTab && validTabIds.has(defaultTab) ? defaultTab : allTabs[0]?.id ?? "result";
5353
- const [activeTab, setActiveTab] = (0, import_react27.useState)(resolvedDefault);
5354
- const [snapshotIdx, setSnapshotIdx] = (0, import_react27.useState)(0);
5355
- const [drillDownStack, setDrillDownStack] = (0, import_react27.useState)([]);
5356
- const [rightExpanded, setRightExpanded] = (0, import_react27.useState)(defaultExpanded?.details ?? true);
5357
- const [rightPanelMode, setRightPanelMode] = (0, import_react27.useState)("insights");
5358
- const [leftExpanded, setLeftExpanded] = (0, import_react27.useState)(defaultExpanded?.topology ?? false);
5359
- const [timelineExpanded, setTimelineExpanded] = (0, import_react27.useState)(defaultExpanded?.timeline ?? false);
5360
- (0, import_react27.useEffect)(() => {
5858
+ const [activeTab, setActiveTab] = (0, import_react29.useState)(resolvedDefault);
5859
+ const [snapshotIdx, setSnapshotIdx] = (0, import_react29.useState)(0);
5860
+ const [drillDownStack, setDrillDownStack] = (0, import_react29.useState)([]);
5861
+ const [rightExpanded, setRightExpanded] = (0, import_react29.useState)(defaultExpanded?.details ?? true);
5862
+ const [rightPanelMode, setRightPanelMode] = (0, import_react29.useState)("insights");
5863
+ const [leftExpanded, setLeftExpanded] = (0, import_react29.useState)(defaultExpanded?.topology ?? false);
5864
+ const [timelineExpanded, setTimelineExpanded] = (0, import_react29.useState)(defaultExpanded?.timeline ?? false);
5865
+ (0, import_react29.useEffect)(() => {
5361
5866
  if (isNarrow) {
5362
5867
  setLeftExpanded(false);
5363
5868
  setRightExpanded(false);
5364
5869
  setTimelineExpanded(false);
5365
5870
  }
5366
5871
  }, [isNarrow]);
5367
- const triggerReflow = (0, import_react27.useCallback)(() => {
5872
+ const triggerReflow = (0, import_react29.useCallback)(() => {
5368
5873
  requestAnimationFrame(() => window.dispatchEvent(new Event("resize")));
5369
5874
  setTimeout(() => window.dispatchEvent(new Event("resize")), 320);
5370
5875
  }, []);
5371
- const toggleLeft = (0, import_react27.useCallback)((v2) => {
5876
+ const toggleLeft = (0, import_react29.useCallback)((v2) => {
5372
5877
  setLeftExpanded(v2);
5373
5878
  triggerReflow();
5374
5879
  }, [triggerReflow]);
5375
- const toggleRight = (0, import_react27.useCallback)((v2) => {
5880
+ const toggleRight = (0, import_react29.useCallback)((v2) => {
5376
5881
  setRightExpanded(v2);
5377
5882
  triggerReflow();
5378
5883
  }, [triggerReflow]);
5379
- const toggleTimeline = (0, import_react27.useCallback)(() => {
5884
+ const toggleTimeline = (0, import_react29.useCallback)(() => {
5380
5885
  setTimelineExpanded((p) => !p);
5381
5886
  triggerReflow();
5382
5887
  }, [triggerReflow]);
5383
5888
  const isInSubflow = drillDownStack.length > 0;
5384
- const currentLevel = (0, import_react27.useMemo)(() => {
5889
+ const currentLevel = (0, import_react29.useMemo)(() => {
5385
5890
  if (drillDownStack.length > 0) {
5386
5891
  const top = drillDownStack[drillDownStack.length - 1];
5387
5892
  return { spec: top.spec, snapshots: top.snapshots };
@@ -5392,30 +5897,30 @@ function ExplainableShell({
5392
5897
  const activeSpec = currentLevel.spec;
5393
5898
  const safeIdx = activeSnapshots.length > 0 ? Math.max(0, Math.min(snapshotIdx, activeSnapshots.length - 1)) : 0;
5394
5899
  const activeNarrativeEntries = isInSubflow ? void 0 : narrativeEntries;
5395
- const breadcrumbs = (0, import_react27.useMemo)(() => {
5900
+ const breadcrumbs = (0, import_react29.useMemo)(() => {
5396
5901
  const root = { label: title || "Flowchart", spec, description: spec?.description };
5397
5902
  return [root, ...drillDownStack.map((e) => ({ label: e.label, spec: e.spec, description: void 0 }))];
5398
5903
  }, [spec, title, drillDownStack]);
5399
- const showTreeSidebar = (0, import_react27.useMemo)(() => {
5904
+ const showTreeSidebar = (0, import_react29.useMemo)(() => {
5400
5905
  if (traceGraph?.nodes?.length) {
5401
5906
  return traceGraph.nodes.some((n) => n.data?.isSubflow === true);
5402
5907
  }
5403
5908
  return !!spec && hasSubflowNodes(spec);
5404
5909
  }, [traceGraph, spec]);
5405
- const rootOverlay = (0, import_react27.useMemo)(() => {
5910
+ const rootOverlay = (0, import_react29.useMemo)(() => {
5406
5911
  if (isInSubflow || !snapshots.length) return { activeStage: void 0, doneStages: void 0 };
5407
5912
  const doneStages = new Set(snapshots.slice(0, safeIdx).map((s) => s.stageLabel));
5408
5913
  const activeStage = snapshots[safeIdx]?.stageLabel ?? null;
5409
5914
  return { activeStage, doneStages };
5410
5915
  }, [isInSubflow, snapshots, safeIdx]);
5411
- const handleTabChange = (0, import_react27.useCallback)((tab) => {
5916
+ const handleTabChange = (0, import_react29.useCallback)((tab) => {
5412
5917
  setActiveTab(tab);
5413
5918
  setDrillDownStack([]);
5414
5919
  }, []);
5415
- const handleSnapshotChange = (0, import_react27.useCallback)((idx) => {
5920
+ const handleSnapshotChange = (0, import_react29.useCallback)((idx) => {
5416
5921
  if (typeof idx === "number") setSnapshotIdx(idx);
5417
5922
  }, []);
5418
- const handleDrillDown = (0, import_react27.useCallback)(
5923
+ const handleDrillDown = (0, import_react29.useCallback)(
5419
5924
  (nodeName) => {
5420
5925
  if (!activeSpec) return;
5421
5926
  const entry = resolveSubflowLevel(activeSpec, activeSnapshots, nodeName, narrativeEntries);
@@ -5426,14 +5931,14 @@ function ExplainableShell({
5426
5931
  },
5427
5932
  [activeSpec, activeSnapshots, narrativeEntries, snapshotIdx]
5428
5933
  );
5429
- const handleBreadcrumbNavigate = (0, import_react27.useCallback)((level) => {
5934
+ const handleBreadcrumbNavigate = (0, import_react29.useCallback)((level) => {
5430
5935
  setDrillDownStack((prev) => {
5431
5936
  const popped = level === 0 ? prev[0] : prev[level];
5432
5937
  if (popped) setSnapshotIdx(popped.parentSnapshotIdx);
5433
5938
  return level === 0 ? [] : prev.slice(0, level);
5434
5939
  });
5435
5940
  }, []);
5436
- const handleNodeClick = (0, import_react27.useCallback)(
5941
+ const handleNodeClick = (0, import_react29.useCallback)(
5437
5942
  (indexOrId) => {
5438
5943
  if (typeof indexOrId === "number") {
5439
5944
  setSnapshotIdx(indexOrId);
@@ -5451,7 +5956,7 @@ function ExplainableShell({
5451
5956
  },
5452
5957
  [activeSpec, activeSnapshots, handleDrillDown]
5453
5958
  );
5454
- const handleTreeNodeSelect = (0, import_react27.useCallback)(
5959
+ const handleTreeNodeSelect = (0, import_react29.useCallback)(
5455
5960
  (name, isSubflow) => {
5456
5961
  if (isSubflow && spec) {
5457
5962
  setDrillDownStack([]);
@@ -5470,31 +5975,31 @@ function ExplainableShell({
5470
5975
  );
5471
5976
  const tabLabels = new Map(allTabs.map((t) => [t.id, t.name]));
5472
5977
  if (unstyled) {
5473
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className, style, "data-fp": "explainable-shell", children: [
5474
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { "data-fp": "shell-tabs", children: allTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { "data-fp": "shell-tab", "data-active": tab.id === activeTab, onClick: () => handleTabChange(tab.id), children: tab.name }, tab.id)) }),
5475
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
5476
- activeTab === "result" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ResultPanel, { data: resultData ?? null, logs, hideConsole, unstyled: true }),
5477
- (activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5478
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TimeTravelControls, { snapshots: activeSnapshots, selectedIndex: safeIdx, onIndexChange: handleSnapshotChange, unstyled: true }),
5479
- isInSubflow && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
5978
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className, style, "data-fp": "explainable-shell", children: [
5979
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { "data-fp": "shell-tabs", children: allTabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { "data-fp": "shell-tab", "data-active": tab.id === activeTab, onClick: () => handleTabChange(tab.id), children: tab.name }, tab.id)) }),
5980
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { "data-fp": "shell-content", "data-tab": activeTab, children: [
5981
+ activeTab === "result" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ResultPanel, { data: resultData ?? null, logs, hideConsole, unstyled: true }),
5982
+ (activeTab === "explainable" || activeTab === "ai-compatible") && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5983
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TimeTravelControls, { snapshots: activeSnapshots, selectedIndex: safeIdx, onIndexChange: handleSnapshotChange, unstyled: true }),
5984
+ isInSubflow && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
5480
5985
  activeSpec && effectiveRenderFlowchart?.({ spec: activeSpec, snapshots: activeSnapshots, selectedIndex: safeIdx, onNodeClick: handleNodeClick, showStageId }),
5481
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, unstyled: true }),
5482
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, unstyled: true }),
5483
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, unstyled: true })
5986
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, unstyled: true }),
5987
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, unstyled: true }),
5988
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, unstyled: true })
5484
5989
  ] })
5485
5990
  ] })
5486
5991
  ] });
5487
5992
  }
5488
5993
  const showTopology = !!effectiveRenderFlowchart && !!activeSpec;
5489
- const detailsContent = (0, import_react27.useMemo)(() => {
5994
+ const detailsContent = (0, import_react29.useMemo)(() => {
5490
5995
  if (activeTab === "result") {
5491
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ResultPanel, { data: resultData ?? null, logs, hideConsole, size });
5996
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ResultPanel, { data: resultData ?? null, logs, hideConsole, size });
5492
5997
  }
5493
5998
  if (activeTab === "memory") {
5494
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, size, style: { height: "100%" } });
5999
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MemoryPanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, size, style: { height: "100%" } });
5495
6000
  }
5496
6001
  if (activeTab === "narrative") {
5497
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, size, style: { height: "100%" } });
6002
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(NarrativePanel, { snapshots: activeSnapshots, selectedIndex: safeIdx, narrativeEntries: activeNarrativeEntries, size, style: { height: "100%" } });
5498
6003
  }
5499
6004
  const customView = recorderViews?.find((v2) => v2.id === activeTab);
5500
6005
  if (customView?.render) {
@@ -5502,7 +6007,7 @@ function ExplainableShell({
5502
6007
  }
5503
6008
  const autoView = autoRecorderViews.find((v2) => v2.id === activeTab);
5504
6009
  if (autoView) {
5505
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6010
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5506
6011
  KeyedRecorderView,
5507
6012
  {
5508
6013
  data: autoView.data,
@@ -5515,8 +6020,8 @@ function ExplainableShell({
5515
6020
  }
5516
6021
  return null;
5517
6022
  }, [activeTab, resultData, logs, hideConsole, size, activeSnapshots, safeIdx, activeNarrativeEntries, recorderViews, autoRecorderViews]);
5518
- const detailsPanel = /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }, children: [
5519
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: {
6023
+ const detailsPanel = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }, children: [
6024
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: {
5520
6025
  display: "flex",
5521
6026
  borderBottom: `1px solid ${theme.border}`,
5522
6027
  background: theme.bgSecondary,
@@ -5524,7 +6029,7 @@ function ExplainableShell({
5524
6029
  overflowX: "auto"
5525
6030
  }, children: allTabs.map((tab) => {
5526
6031
  const active = tab.id === activeTab;
5527
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6032
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5528
6033
  "button",
5529
6034
  {
5530
6035
  onClick: () => handleTabChange(tab.id),
@@ -5548,9 +6053,9 @@ function ExplainableShell({
5548
6053
  tab.id
5549
6054
  );
5550
6055
  }) }),
5551
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: detailsContent })
6056
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: detailsContent })
5552
6057
  ] });
5553
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
6058
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5554
6059
  "div",
5555
6060
  {
5556
6061
  ref: shellRef,
@@ -5568,7 +6073,7 @@ function ExplainableShell({
5568
6073
  },
5569
6074
  "data-fp": "explainable-shell",
5570
6075
  children: [
5571
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6076
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5572
6077
  TimeTravelControls,
5573
6078
  {
5574
6079
  snapshots: activeSnapshots,
@@ -5577,20 +6082,20 @@ function ExplainableShell({
5577
6082
  size
5578
6083
  }
5579
6084
  ),
5580
- isInSubflow && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
5581
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: isNarrow ? "auto" : "hidden", display: "flex", flexDirection: "column" }, children: isNarrow ? (
6085
+ isInSubflow && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SubflowBreadcrumb, { breadcrumbs, onNavigate: handleBreadcrumbNavigate }),
6086
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, overflow: isNarrow ? "auto" : "hidden", display: "flex", flexDirection: "column" }, children: isNarrow ? (
5582
6087
  /* ── Mobile: stacked vertical ── */
5583
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5584
- showTopology && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { height: 350, flexShrink: 0, overflow: "hidden" }, children: effectiveRenderFlowchart({
6088
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6089
+ showTopology && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { height: 350, flexShrink: 0, overflow: "hidden" }, children: effectiveRenderFlowchart({
5585
6090
  spec: activeSpec,
5586
6091
  snapshots: activeSnapshots,
5587
6092
  selectedIndex: safeIdx,
5588
6093
  onNodeClick: handleNodeClick,
5589
6094
  showStageId
5590
6095
  }) }),
5591
- showTreeSidebar && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5592
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HLinePill, { label: leftLabel, expanded: leftExpanded, onClick: () => toggleLeft(!leftExpanded) }),
5593
- leftExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { maxHeight: 180, overflow: "auto", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6096
+ showTreeSidebar && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6097
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(HLinePill, { label: leftLabel, expanded: leftExpanded, onClick: () => toggleLeft(!leftExpanded) }),
6098
+ leftExpanded && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { maxHeight: 180, overflow: "auto", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5594
6099
  SubflowTree,
5595
6100
  {
5596
6101
  graph: traceGraph ?? { nodes: [], edges: [] },
@@ -5600,17 +6105,17 @@ function ExplainableShell({
5600
6105
  }
5601
6106
  ) })
5602
6107
  ] }),
5603
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HLinePill, { label: rightLabel, expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
5604
- rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { maxHeight: 350, flexShrink: 0, overflow: "hidden" }, children: detailsPanel }),
5605
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(HLinePill, { label: bottomLabel, detail: `${activeSnapshots.length} stages`, expanded: timelineExpanded, onClick: toggleTimeline }),
5606
- timelineExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flexShrink: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, size }) })
6108
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(HLinePill, { label: rightLabel, expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
6109
+ rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { maxHeight: 350, flexShrink: 0, overflow: "hidden" }, children: detailsPanel }),
6110
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(HLinePill, { label: bottomLabel, detail: `${activeSnapshots.length} stages`, expanded: timelineExpanded, onClick: toggleTimeline }),
6111
+ timelineExpanded && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flexShrink: 0, overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(GanttTimeline, { snapshots: activeSnapshots, selectedIndex: safeIdx, onSelect: handleSnapshotChange, size }) })
5607
6112
  ] })
5608
6113
  ) : (
5609
6114
  /* ── Desktop: two-column — Flowchart | Right Panel ── */
5610
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5611
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
5612
- showTreeSidebar && (leftExpanded ? /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { width: 180, flexShrink: 0, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
5613
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6115
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6116
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
6117
+ showTreeSidebar && (leftExpanded ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { style: { width: 180, flexShrink: 0, display: "flex", flexDirection: "row", overflow: "hidden" }, children: [
6118
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, overflow: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5614
6119
  SubflowTree,
5615
6120
  {
5616
6121
  graph: traceGraph ?? { nodes: [], edges: [] },
@@ -5619,17 +6124,17 @@ function ExplainableShell({
5619
6124
  onNodeSelect: handleTreeNodeSelect
5620
6125
  }
5621
6126
  ) }),
5622
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VLinePill, { label: "Topology", expanded: true, side: "left", onClick: () => toggleLeft(false) })
5623
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VLinePill, { label: "Topology", expanded: false, side: "left", onClick: () => toggleLeft(true) })),
5624
- showTopology ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1, overflow: "hidden", minWidth: 0 }, children: effectiveRenderFlowchart({
6127
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VLinePill, { label: "Topology", expanded: true, side: "left", onClick: () => toggleLeft(false) })
6128
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VLinePill, { label: "Topology", expanded: false, side: "left", onClick: () => toggleLeft(true) })),
6129
+ showTopology ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1, overflow: "hidden", minWidth: 0 }, children: effectiveRenderFlowchart({
5625
6130
  spec: activeSpec,
5626
6131
  snapshots: activeSnapshots,
5627
6132
  selectedIndex: safeIdx,
5628
6133
  onNodeClick: handleNodeClick,
5629
6134
  showStageId
5630
- }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { flex: 1 } }),
5631
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VLinePill, { label: "Details", expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
5632
- rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { width: "42%", minWidth: 320, maxWidth: 550, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6135
+ }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { flex: 1 } }),
6136
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VLinePill, { label: "Details", expanded: rightExpanded, onClick: () => toggleRight(!rightExpanded) }),
6137
+ rightExpanded && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { style: { width: "42%", minWidth: 320, maxWidth: 550, display: "flex", flexDirection: "column", overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5633
6138
  RightPanel,
5634
6139
  {
5635
6140
  mode: rightPanelMode,
@@ -5651,7 +6156,7 @@ function ExplainableShell({
5651
6156
  }
5652
6157
  ) })
5653
6158
  ] }),
5654
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6159
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5655
6160
  CompactTimeline,
5656
6161
  {
5657
6162
  snapshots: activeSnapshots,
@@ -5668,8 +6173,8 @@ function ExplainableShell({
5668
6173
 
5669
6174
  // src/components/TraceViewer/TraceViewer.tsx
5670
6175
  var React = __toESM(require("react"), 1);
5671
- var import_react28 = require("react");
5672
- var import_jsx_runtime25 = require("react/jsx-runtime");
6176
+ var import_react30 = require("react");
6177
+ var import_jsx_runtime27 = require("react/jsx-runtime");
5673
6178
  function parseTrace(input) {
5674
6179
  if (input == null) {
5675
6180
  return {
@@ -5732,11 +6237,11 @@ function TraceViewer({
5732
6237
  recorderViews,
5733
6238
  renderFlowchart
5734
6239
  }) {
5735
- const parsed = (0, import_react28.useMemo)(() => parseTrace(trace), [trace]);
6240
+ const parsed = (0, import_react30.useMemo)(() => parseTrace(trace), [trace]);
5736
6241
  React.useEffect(() => {
5737
6242
  if (!parsed.ok && onError) onError(parsed.error);
5738
6243
  }, [parsed, onError]);
5739
- const snapshots = (0, import_react28.useMemo)(() => {
6244
+ const snapshots = (0, import_react30.useMemo)(() => {
5740
6245
  if (!parsed.ok || !parsed.trace.snapshot) return [];
5741
6246
  try {
5742
6247
  return toVisualizationSnapshots(
@@ -5750,7 +6255,7 @@ function TraceViewer({
5750
6255
  if (!parsed.ok || snapshots.length === 0) {
5751
6256
  return fallback ?? null;
5752
6257
  }
5753
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6258
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5754
6259
  ExplainableShell,
5755
6260
  {
5756
6261
  snapshots,