diff --git a/docs/plans/2026-06-04-002-feat-node-editor-visual-edge-upgrade-plan.md b/docs/plans/2026-06-04-002-feat-node-editor-visual-edge-upgrade-plan.md new file mode 100644 index 0000000000..46eaafc59c --- /dev/null +++ b/docs/plans/2026-06-04-002-feat-node-editor-visual-edge-upgrade-plan.md @@ -0,0 +1,267 @@ +--- +title: "feat: Node editor visual redesign + success/failure edge authoring" +type: feat +status: active +date: 2026-06-04 +depth: standard +origin: none (solo planning bootstrap) +--- + +# feat: Node editor visual redesign + success/failure edge authoring + +## Summary + +Upgrade the workflow node editor's authoring experience: redesign graph nodes from small icon+label pills into larger card-style nodes with kind accent colors and config summaries; generalize edge-condition authoring so success/failure is selectable on regular edges (today only step-review edges are editable) with distinct visual styling; and round out editor power/polish — safe node/edge deletion, proper dialogs replacing `window.prompt`/`window.confirm`, inline rename/description, dirty-state guard, auto-layout, and a real empty/onboarding state. UI/authoring layer only — no engine, IR-schema, or compiler-semantics changes. + +--- + +## Problem Frame + +The editor (`packages/dashboard/app/components/WorkflowNodeEditor.tsx`, built on `@xyflow/react`) has grown to 13 editor node kinds with swimlane columns and an edge inspector, but the authoring surface lags the capability underneath: + +- **Nodes are unreadable at a glance.** `NodeShell` (`packages/dashboard/app/components/nodes/WorkflowNodeTypes.tsx`) renders icon + label + tiny badges. A prompt node configured with a model, an agent, or a CLI command looks identical to an unconfigured one; users must click every node to see what it does. +- **Failure edges exist everywhere except the editor.** The IR accepts any `edge.condition` (`parseWorkflowIr` never validates condition values), and the graph executor natively traverses `failure` edges (`shouldTraverseEdge`, `packages/engine/src/workflow-graph-executor.ts:385-392`). But `onConnect` hardcodes every new edge to `success`, and the edge inspector only offers condition controls when the source node is `step-review`. There is no way to author the branching the engine already supports. +- **Authoring chrome is crude.** `window.prompt` for workflow names, `window.confirm` for deletes, no keyboard deletion, no dirty tracking (switching workflows silently discards edits), no auto-layout, and a bare "Select or create a workflow" empty state. + +--- + +## Scope Boundaries + +### In scope +- Card-style node redesign with config summaries and kind accent colors. +- Success/failure edge-condition authoring on regular edges, with distinct edge styling and an honest "interpreter-only" presentation when branching makes the graph non-compilable to the linear step engine. +- Deletion UX (keyboard + buttons) with explicit cascade semantics. +- Dialogs, inline rename/description, dirty-state guard, auto-layout, empty/onboarding state. + +### Deferred to Follow-Up Work +- Undo/redo history for the canvas. +- Workflow import/export, versioning, templates gallery. +- Localizing edge condition labels (kept as canonical IR tokens — see KTD-8). +- Auto-layout inside `foreach` template groups beyond the existing seeded row. + +### Outside this product's identity +- Changing edge/branching **execution** semantics. The graph interpreter, `parseWorkflowIr` graph validation, and the linear-step compiler keep their current behavior; this plan only lets users author what they already support and presents their limits honestly. + +--- + +## Requirements + +**Visual** +- R1 — Graph nodes render as card-style nodes: kind accent color, icon, label, and a config-summary line (model/agent/skill/CLI for prompt nodes; script name; gate mode; hold release; join mode; parser; review type), with a defined header-overflow priority and truncation; existing badges and error badges preserved. +- R2 — Success, failure, and rework edges are distinguishable by at least two independent visual channels: the condition label is always rendered, and failure edges use a distinct dash pattern from success edges; color (token-only, both themes) is a third channel, never the only one. + +**Edge authoring** +- R3 — A user can set a regular edge's condition to `success` or `failure` from the edge inspector via a native `` gated per KTD-2 inside the existing disabled fieldset; compile-banner suffix match + info tone (KTD-4); `interactionWidth` on edges for a forgiving hit target (touch + pointer). +- `packages/dashboard/app/components/workflow-flow-mapping.ts` (modify) — edge `className` for failure edges in `irEdgeToFlow`; always-rendered condition labels; dash styling hooks; ancestor-reachability helper for the cycle guard. +- `packages/dashboard/app/components/WorkflowNodeEditor.css` (modify) — `.wf-edge-failure` (distinct dash pattern + `--ws-error`-derived stroke), success default styling, info-tone banner. +- `packages/dashboard/app/components/__tests__/workflow-flow-mapping.test.ts` (extend) — mapping-level edge tests. +- `packages/dashboard/app/components/__tests__/WorkflowNodeEditor.test.tsx` (extend) — inspector gating tests. +**Approach:** Edge-level behavior is tested at the mapping layer (React Flow doesn't render edges under jsdom). The inspector reuses `updateSelectedEdge` unchanged — only the rendering gate widens, and the condition control is a native `