docs: add cross-reference / loop-back design document
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>
This commit is contained in:
80
docs/plans/2026-02-28-cross-reference-loopback-design.md
Normal file
80
docs/plans/2026-02-28-cross-reference-loopback-design.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# 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_id` can 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_id` values 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_id` to 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 build` after each piece, manual testing of editor + navigation loops
|
||||
Reference in New Issue
Block a user