Root cause: graph.getNodes() is a flat list with duplicates — handler
compound children appear both nested inside their parent AND as
top-level entries. The previous separation tried to filter the flat
list but missed the duplicates, leaving handler children in rootNode.
New approach: walk from graph.getRoot() following non-ERROR edges to
discover main flow nodes. Edges targeting handler compounds (ON_EXCEPTION,
ON_COMPLETION) are not followed. This cleanly separates main flow from
handler sections using the graph's own structure.
Falls back to flat list filtering (old behavior) when graph.getRoot()
is null (legacy/test graphs).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause found: RouteGraph.getNodes() is a FLAT list that includes
handler compound children (log8, setBody1, etc.) as top-level entries
alongside the main flow nodes. The handler separation only identified
the compound PARENTS (ON_EXCEPTION) but not their children, so 7
handler children leaked into rootNode as main flow nodes, causing
ELK to place the real main flow at wrong Y positions.
Fix: two-pass separation — first identify handler compounds and
collect ALL descendant IDs, then build mainNodes excluding both
handler compounds AND their descendants.
Debug logging left in temporarily for verification.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The root cause of the Y-offset: ELK places main flow nodes at
arbitrary positions (e.g., y=679) within its root graph, and the
frontend rendered them at those raw positions. Handler sections were
already normalized via shiftNodes, but the main section was not.
Now useDiagramData.ts applies the same normalization to the main
section: computes bounding box, shifts nodes and edges so the section
starts at (0,0). This fixes the Y-offset regardless of what ELK
produces internally.
Removed the backend normalizePositions (was ineffective because handler
nodes at y=12 dominated the global minimum, preventing meaningful shift
of main flow nodes at y=679).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Based on thorough code review, fixes all identified issues:
1. **Y-offset root cause**: Added post-layout normalization that shifts
all positioned nodes and edges so the bounding box starts at (0,0).
ELK can place nodes at arbitrary positions within its root graph;
normalizing compensates regardless of what ELK computes internally.
2. **Bounding box**: Compute from recursively flattened node tree +
edge point bounds. Removes double-counting of compound children
(children have absolute coords, not relative to parent).
3. **SVG double-drawing**: Compound children were drawn both inside
drawCompoundContainer and again in the allNodes loop. Now collects
compound child IDs and skips them in the second pass.
4. **findNode**: Now recurses into children for nested compound lookup.
5. **colorForType**: Removed redundant double-check on EIP_TYPES.
6. **Dead code removed**: routeNodeMap/indexNodeRecursive (populated but
never read), MIN_NODE_WIDTH/CHAR_WIDTH/LABEL_PADDING (unused).
7. **Static initialization**: LayoutMetaDataProvider registration moved
from constructor to static block (runs once, not per instance).
8. **Debug logging removed**: Removed diagnostic System.out.println.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. findCommonParent: replaced with correct lowest common ancestor
algorithm using ancestor set intersection (previous version only
walked from node 'a', not a true LCA)
2. Bounding box: compute totalWidth/totalHeight from actual positioned
node coordinates instead of rootNode.getWidth/Height. The rootNode
dimensions don't account for handler sections in separate ELK roots.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Handler section nodes were positioned relative to rootNode, but they
live under separate handlerRoot ELK graphs. Using getElkRoot() to find
each node's actual root ensures correct absolute coordinates.
This combined with the POLYLINE edge routing should eliminate the
Y-offset misalignment between main flow nodes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend:
- Set POLYLINE edge routing on ELK root — eliminates curved/bent edges
between horizontally aligned nodes
- Collect edges from handler section roots (not just main root) so
internal handler edges are included in the layout output
- Use correct root reference for coordinate calculation per edge
Frontend:
- Render ALL edge points as line segments (polylines), not cubic bezier.
ELK bend points are waypoints, not bezier control points — the cubic
bezier interpretation caused false curves.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tap button in the node toolbar now navigates to
/admin/appconfig?app=<application>&processor=<nodeId>, which
auto-selects the application in the AppConfigPage. The AppConfigPage
reads the ?app query param to open the detail panel for that app.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Handler section ELK roots were missing INCLUDE_CHILDREN, causing
edges between a handler compound and its children to fail with
UnsupportedGraphException (cross-hierarchy edge resolution).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Edges connecting main flow nodes to handler section nodes (ON_EXCEPTION,
ON_COMPLETION) now span different ELK root graphs. ELK throws
UnsupportedGraphException when an edge connects nodes in different
layout hierarchies. Skip these cross-root edges — the frontend doesn't
render them anyway (handler sections are separated visually).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Toggle tracing: "T" → 👣 (footprints — trace = following the path)
- Configure tap: ✎ (pencil) → 🚰 (water tap — tap = intercept the flow)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The flex chain from detailArea → detailPanel → tabContent lacked
min-height: 0, so flex children never shrank below content height
and overflow-y: auto never triggered. Added min-height: 0 and
flex: 1 to propagate the height constraint correctly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ON_EXCEPTION, ON_COMPLETION, and ERROR_HANDLER compounds were included
in the same root ELK graph as the main flow. ELK's layered algorithm
offset the main flow nodes vertically to accommodate the handler
compounds, causing bent arrows between the ENDPOINT and first processor.
Now handler sections get their own independent ELK root graphs. The
frontend already separates and repositions them, so they just need
correct internal layout — not positioning relative to the main flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests were using the old 18-param constructor, missing the 5 new
iteration fields (loopIndex, loopSize, splitIndex, splitSize,
multicastIndex) added in V8 migration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
No longer needed — the ProcessDiagram is now integrated into
ExchangeDetail via the ExecutionDiagram wrapper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added centerOnNodeId prop to ProcessDiagram. When set, the diagram
pans to center the specified node in the viewport. Jump to Error
now selects the failed processor AND centers the viewport on it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When an onException/error handler section has any executed processors
(overlay entries), it renders with a stronger red tint (8% vs 3%),
a solid red border frame, and a solid divider line. This makes it
easy to identify which handler was triggered when multiple exist.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The execution overlay data maps to the root route's processor IDs. When
drilled into a sub-route, those IDs don't match, causing all nodes to
appear dimmed. Now clears the overlay and shows pure topology when
viewing a sub-route via drill-down.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When drilled into a sub-route, the pre-fetched diagramLayout (loaded by
content hash for the root execution) doesn't contain the sub-route's
diagram. Only use the pre-loaded layout for the root route; fall back to
useDiagramByRoute for drilled-down sub-routes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make headers tab and timeline tab scrollable when content overflows
- Replace custom <pre> code block with design system CodeBlock component
for body tabs (Input/Output) to match existing styleguide
- Add LINEAR_SEGMENTS node placement strategy to ELK layout to fix
Y-offset misalignment between nodes in left-to-right diagrams
(e.g., ENDPOINT at different Y level than subsequent processors)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Synthesize COMPLETED state for ENDPOINT nodes when overlay is active
(endpoints are route entry points, not in the processor execution tree)
- Move status badge (check/error) inside the card (top-right, below top bar)
to avoid collision with ConfigBadge (TRACE/TAP) badges
- Include ENDPOINT nodes in edge traversal check so the edge from
endpoint to first processor renders as green/traversed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
React's onWheel is passive by default, so preventDefault() doesn't stop
page scrolling. Attach native wheel listener with { passive: false } via
useEffect instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the RouteFlow-based flow view with the new ExecutionDiagram
component which provides execution overlay, iteration stepping, and
an integrated detail panel. The gantt view and all other page sections
remain unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Composes ProcessDiagram with execution overlay data, exchange summary
bar, resizable splitter, and detail panel into a single root component.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the bottom detail panel with processor header bar, tab bar
(Info, Headers, Input, Output, Error, Config, Timeline), and all tab
content components. Info shows processor/exchange metadata in a grid,
Headers fetches per-processor snapshots for side-by-side display,
Input/Output render formatted code blocks, Error extracts exception
types, Config is a placeholder, and Timeline renders a Gantt chart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
useExecutionOverlay maps processor tree to overlay state map, handling
iteration filtering, sub-route failure detection, and trace data flags.
useIterationState detects compound nodes with iterated children and
manages per-compound iteration selection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a left/right stepper widget to compound node headers (LOOP, SPLIT,
MULTICAST) when iteration overlay data is present. Thread executionOverlay,
overlayActive, iterationState, and onIterationChange props through
ProcessDiagram -> CompoundNode -> children and ProcessDiagram ->
ErrorSection -> children so leaf DiagramNode instances render with
execution state (green/red badges, dimming for skipped nodes).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add green solid edges for traversed paths and dashed gray for
not-traversed when execution overlay is active. Includes green
arrowhead marker and overlay threading through CompoundNode and
ErrorSection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DiagramNode now accepts executionState and overlayActive props to render
execution status: green tint + checkmark badge for completed nodes, red
tint + exclamation badge for failed nodes, dimmed opacity for skipped
nodes. Duration is shown at bottom-right, and a drill-down arrow appears
for sub-route failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Define the execution overlay type system (NodeExecutionState, IterationInfo,
DetailTab) and extend ProcessDiagramProps with optional overlay props. Add
diagramLayout prop so ExecutionDiagram can pass a pre-fetched layout by content
hash, bypassing the internal route-based fetch in useDiagramData.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add iteration fields (loopIndex, loopSize, splitIndex, splitSize,
multicastIndex) to ProcessorNode schema. Add new endpoint path
/executions/{executionId}/processors/by-id/{processorId}/snapshot.
Remove stale diagramNodeId field that was dropped in V6 migration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add GET /executions/{id}/processors/by-id/{processorId}/snapshot endpoint
that fetches processor snapshot data by processorId instead of positional
index, which is fragile when the tree structure changes. The existing
index-based endpoint remains unchanged for backward compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add loop_index, loop_size, split_index, split_size, multicast_index
columns to processor_executions table and thread them through the
full storage → ingestion → detail pipeline. These fields enable
execution overlay to display iteration context for loop, split,
and multicast EIPs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Design for overlaying real execution data onto the ProcessDiagram:
- Node status visualization (green OK, red failed, dimmed skipped)
- Per-compound iteration stepping for loops/splits
- Tabbed detail panel (Info, Headers, Input, Output, Error, Config, Timeline)
- Jump to Error with cross-route drill-down
- Backend prerequisites for iteration fields and snapshot-by-id endpoint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Small overview panel in the bottom-left showing the full diagram
layout with colored node rectangles and an amber viewport indicator.
Click or drag on the minimap to pan the main diagram.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update design spec with implementation notes covering recursive
compound nesting, edge z-ordering, ON_COMPLETION sections, drill-down
navigation, CSS transform zoom, and HTML overlay toolbar.
Increase SECTION_GAP to 80px for better visual separation between
completion and error handler sections.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Double-click a DIRECT or SEDA node to navigate into that route's
diagram. Breadcrumbs show the route stack and allow clicking back
to any level. Escape key goes back one level.
Route ID resolution handles camelCase endpoint URIs mapping to
kebab-case route IDs (e.g. direct:callGetProduct → call-get-product)
using the catalog's known route IDs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ON_COMPLETION to backend COMPOUND_TYPES and frontend rendering.
Completion handlers render as teal-tinted sections between the main
flow and error handlers, structurally parallel to onException.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Recursive compound rendering: CompoundNode checks if children are
themselves compound types (WHEN inside CHOICE) and renders them
recursively. Added EIP_WHEN, EIP_OTHERWISE, DO_CATCH, DO_FINALLY
to frontend COMPOUND_TYPES.
- Edge z-ordering: edges are distributed to their containing compound
and rendered after the background rect, so they're not hidden behind
compound containers.
- Error section sizing: normalize error handler node coordinates to
start at (0,0), compute red tint background height from actual
content with symmetric padding for vertical centering.
- Toolbar as HTML overlay: moved from SVG foreignObject to absolute-
positioned HTML div so it stays fixed size at any zoom level. Uses
design system tokens for consistent styling.
- Zoom: replaced viewBox approach with CSS transform on content group.
Default zoom is 100% anchored top-left. Fit-to-view still available
via button.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ELK renderer:
- Add EIP_WHEN, EIP_OTHERWISE, DO_CATCH, DO_FINALLY to COMPOUND_TYPES
so branch body processors nest inside their containers
- Rewrite node creation and result extraction as recursive methods
to support compound-inside-compound (CHOICE → WHEN → processors)
- Use fixed NODE_WIDTH=160 for leaf nodes instead of variable width
Frontend:
- Fix mousewheel crash: capture getBoundingClientRect() before
setState updater (React nulls currentTarget after handler returns)
- Anchor fitToView to top-left instead of centering
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The dev diagram page was calling useRouteCatalog() without time range
params (returned empty) and parsing the wrong response shape (expected
flat {application, routeId} but catalog returns {appId, routes[]}).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New interactive route diagram component with SVG rendering using
server-computed ELK layout coordinates. TIBCO BW5-inspired top-bar
card node style with zoom/pan, hover toolbars, config badges, and
error handler sections below the main flow.
Backend: add direction query parameter (LR/TB) to diagram render
endpoints, defaulting to left-to-right layout.
Frontend: 14-file ProcessDiagram component in ui/src/components/
with DiagramNode, CompoundNode, DiagramEdge, ConfigBadge, NodeToolbar,
ErrorSection, ZoomControls, and supporting hooks. Dev test page at
/dev/diagram for validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>