Design for allowing tree nodes to reference any node in the tree (not just direct children), enabling loop-back patterns. Ghost reference approach — no schema changes, SVG overlay arrows on canvas, node picker + drag-to-link in editor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.4 KiB
Cross-Reference / Loop-Back Support — Design
Goal: Allow tree nodes to reference any other node in the tree (not just direct children), enabling loop-back patterns like "remediate → re-verify from earlier checkpoint."
Architecture: Ghost references on existing tree structure. No schema change, no migration. A cross-reference is any next_node_id that points outside the current node's children array. The canvas renders these as dashed SVG overlay arrows. Navigation already supports this.
Approach chosen: Approach 1 — "Ghost references" (keep tree structure, add visual cross-ref edges)
1. Data Model — No Changes
The TreeStructure type and database stay as-is. The distinction is semantic:
- Local link:
next_node_id→ direct child → normal tree edge - Cross-reference:
next_node_id→ node elsewhere in tree → dashed overlay arrow
No new fields, no new node types, no migration.
2. Validation Changes
Backend (ai_tree_validator.py)
- Relax decision option validation:
option.next_node_idcan reference any node in the tree (not just children). Check existence only, same as action nodes.
Frontend circular reference detector (treeEditorStore.ts)
- Change loop detection from error to warning. Loops are now intentional. Warning text: "This path loops back to [node title]."
Frontend orphan detection
- Keep as-is. Orphaned nodes still flagged as warnings.
3. Canvas Rendering — Cross-Reference Edges
- SVG overlay layer on top of the canvas (absolute positioned)
- Dashed line with arrowhead pointing at target node
- Purple/primary color to distinguish from normal gray tree connectors
- Small label on the arrow (option label or "loops back")
- After dagre layout, scan all nodes for
next_node_idvalues not matching a direct child - Look up source/target positions from layout, draw curved SVG bezier path
- Target node gets a subtle badge/indicator for inbound cross-references
- Hovering the badge highlights source nodes
4. Editor UX — Creating Cross-References
A. Node picker dropdown (in node form)
- Action nodes and decision option rows get "Link to existing node" dropdown
- Lists all nodes by title/question, grouped by type
- Selecting sets
next_node_id; orphaned answer stubs cleaned up - "Clear link" option to remove
B. Canvas drag-to-link
- Small output port (dot) at bottom of each node
- Drag from port starts a dashed line following cursor
- Drop on any node creates cross-reference
- Drop on empty space cancels
- Existing answer stubs cleaned up if replaced
Visual feedback
- Node form: "Linked to: [node title]" with navigate + remove actions
- Canvas: dashed arrow (Section 3)
5. AI Flow Assist — Prompt Changes
- Update system prompt STRUCTURAL RULES: "Action nodes can set
next_node_idto any node in the tree, including ancestors, for loop-backs." - Add SSH loop example to schema context
- No changes to generation or progressive validation
6. Navigation — No Changes
findNode already searches the full tree. handleSelectOption and handleContinue follow next_node_id without hierarchy checks. Session pathTaken will contain repeated IDs for loops — this is correct behavior.
7. Testing
- Backend: extend validator tests for cross-references
- Frontend:
npm run buildafter each piece, manual testing of editor + navigation loops