# Workflow Editor — Integration Guide

> **Canonical source**: `vl-workflow-engine/ui/workflow-editor.html`
> **Version**: 2.1 (Spec 3.16)
> **Replaces**: project-local copies in VL-Code, VLCode-Lite

---

## What Changed

### v2.1 — Checkpoint, Pause, Re-run, Node Editor

| Feature | Description |
|---------|-------------|
| **Checkpoint persistence** | DAG state (node statuses) is saved to `localStorage` after each step. On page refresh, the DAG re-renders with previous execution state intact. Checkpoints expire after 24h. |
| **Pause execution** | New amber "Pause" button in toolbar. Sends `POST /api/workflow/:runID/pause` (fallback to `/cancel`). Workflow stops cleanly, checkpoint is saved, user can resume from any node. |
| **Re-run from node** | Right-click any node → "Re-run from here". Calls `POST /api/workflow/rerun` with the last checkpoint + target stepID. Downstream nodes are cleared; upstream statuses preserved. |
| **Edit inputs & re-run** | Right-click → "Edit inputs & re-run" opens a modal editor. Type-specific fields (LLM: model/tokens/messages, Service: input params, Set/Write: target/value, Loop: source/while, Download: source/target). Plus a generic "Variable Overrides" JSON field for `$vars`. |
| **Context menu** | Right-click on any node shows: Re-run from here, Edit inputs & re-run, View details, Copy node ID. |
| **New PostMessage APIs** | `setCheckpoint`, `rerunFromStep`, `editNode` — parent can programmatically trigger checkpoint storage, re-runs, and the edit modal. |
| **New outgoing message** | `nodeEdited` — sent to parent when user edits a node's inputs, with the modified `nodeData` and `overrides`. |

### v2.0 — Spec 3.16 Bug Fixes

| # | Issue | Impact |
|---|-------|--------|
| 1 | **`BREAK` phantom connections** | `next: "BREAK"` no longer creates a connection to a non-existent node. Both `RETURN` and `BREAK` are now excluded from connection generation. This was the likely cause of DAG rendering failures. |
| 2 | **Loop `while` mode not rendered** | `renderLoopBody()` now detects `while` vs `source` mode and renders the correct fields (`while` expression, `maxIterations`). |
| 3 | **Missing Download/Unzip node types** | `Download_*` and `Unzip_*` are now recognized with dedicated icons (DL/UZ), colors, accent bars, and body renderers. |
| 4 | **`computeIO` ignored `while` expression** | Variable references in `while` expressions now appear in I/O audit badges. |

### Visual Parity

All existing visuals are preserved:
- Same CSS variables, dark theme, font stack
- Same 11 original node type colors + accent bars + 2 new (Download, Unzip)
- Same connection styles (serial/parallel/branch-case)
- Same minimap, legend, toast, toolbar layout
- Same drag, selection, scroll, resize behavior
- Same PNG/JSON export/import
- Same SSE-based execution with live status updates

---

## How to Integrate

### Option A: Direct Copy (simplest)

```bash
# VL-Code
cp vl-workflow-engine/ui/workflow-editor.html vl-code/src/web/public/workflow-editor.html

# VLCode-Lite
cp vl-workflow-engine/ui/workflow-editor.html VLCode-Lite/public/workflow-editor.html
```

No other changes needed — the PostMessage API is fully backward compatible.

### Option B: Symlink (keeps in sync)

```bash
# VL-Code
ln -sf ../../../../VL-Workflow-Engine/ui/workflow-editor.html vl-code/src/web/public/workflow-editor.html

# VLCode-Lite
ln -sf ../VL-Workflow-Engine/ui/workflow-editor.html VLCode-Lite/public/workflow-editor.html
```

### Option C: npm dependency (for VLClaw and future consumers)

```javascript
const path = require('path');
const editorPath = path.join(require.resolve('vl-workflow-engine'), '..', 'ui', 'workflow-editor.html');
// Serve this file via your static file handler or express.static
```

---

## API Endpoints Required

The editor calls these endpoints directly (same-origin). Consumers must ensure these routes exist:

| Method | Path | Purpose | Required? |
|--------|------|---------|-----------|
| `POST` | `/api/workflow/execute` | Start a workflow (SSE response) | Yes (existing) |
| `POST` | `/api/workflow/rerun` | Re-run from step with checkpoint + overrides (SSE response) | **New** (for re-run feature) |
| `POST` | `/api/workflow/:runID/pause` | Pause a running workflow | **New** (for pause feature) |
| `POST` | `/api/workflow/:runID/abort` | Abort a running workflow | Recommended |
| `GET` | `/api/workflow/:runID/checkpoint` | Fetch latest checkpoint | Recommended (fallback: localStorage) |

**If `/api/workflow/rerun` is not implemented**, the editor falls back to `/api/workflow/execute` with `{ fromStep, checkpoint, overrides }` params. See the engine's `executeFrom()` API for implementation details in [API.md](../API.md).

---

## PostMessage API (Extended)

### Parent → iframe

| Message | Payload | Since | Description |
|---------|---------|-------|-------------|
| `loadWorkflow` | `{ type: 'loadWorkflow', data: workflowJSON }` | v1.0 | Parse and render a workflow |
| `updateNodeStatus` | `{ type: 'updateNodeStatus', nodeId, status }` | v1.0 | Update node status |
| `highlightNode` | `{ type: 'highlightNode', nodeId }` | v1.0 | Select and scroll to a node |
| `clearStatus` | `{ type: 'clearStatus' }` | v1.0 | Clear all node statuses |
| **`setCheckpoint`** | `{ type: 'setCheckpoint', checkpoint, runID }` | **v2.1** | Store a checkpoint (persists to localStorage) |
| **`rerunFromStep`** | `{ type: 'rerunFromStep', nodeId, overrides? }` | **v2.1** | Programmatically trigger re-run from a step |
| **`editNode`** | `{ type: 'editNode', nodeId }` | **v2.1** | Open the edit modal for a node |

### iframe → Parent

| Message | Payload | Since | Description |
|---------|---------|-------|-------------|
| `ready` | `{ type: 'ready' }` | v1.0 | iframe is ready |
| `nodeClick` | `{ type: 'nodeClick', nodeId, nodeType, nodeData }` | v1.0 | User clicked a node |
| `workflowImported` | `{ type: 'workflowImported', workflow }` | v1.0 | User imported JSON |
| **`nodeEdited`** | `{ type: 'nodeEdited', nodeId, nodeData, overrides }` | **v2.1** | User edited node inputs and triggered re-run |

---

## Supported Node Types (13 total)

| Type | Icon | Color | Since |
|------|------|-------|-------|
| LLM | AI | Indigo-purple | v1.0 |
| Service | SV | Green | v1.0 |
| API | AP | Cyan | v1.0 |
| Component | CP | Teal | v1.0 |
| Set | = | Blue | v1.0 |
| Write | WR | Orange | v1.0 |
| Branch | BR | Purple | v1.0 |
| Loop | LP | Pink | v1.0 |
| Stop | ST | Red | v1.0 |
| Pause | ⏸ | Violet | v1.0 |
| Fork | FK | Emerald | v1.0 |
| **Download** | **DL** | **Sky blue** | **v2.0** |
| **Unzip** | **UZ** | **Yellow** | **v2.0** |

---

## User Workflows

### Breakpoint Resume (page refresh)

1. User runs workflow → nodes light up green/orange/red
2. Page refreshes / closes
3. User reopens → DAG renders with last-known node statuses (from localStorage)
4. User right-clicks a failed/incomplete node → "Re-run from here"
5. Engine resumes from that step using saved checkpoint

### Edit & Re-run (fix bad input)

1. Workflow finishes but LLM output was wrong
2. User right-clicks the LLM node → "Edit inputs & re-run"
3. Modal shows: model, max_tokens, messages (editable JSON)
4. User fixes the prompt, adds variable overrides if needed
5. Clicks "Re-run from here" → engine resumes from that node with new inputs
6. Downstream nodes re-execute; upstream results are preserved

### Pause & Inspect

1. User clicks "Pause" during execution
2. Workflow pauses cleanly; checkpoint saved
3. User inspects node statuses, variables
4. User can resume from any node or edit inputs first

---

## Testing

After integration, verify:
1. **Spec 3.16**: Loop `while` mode, `BREAK` badge, Download/Unzip nodes
2. **Context menu**: Right-click a node → menu appears with 4 options
3. **Re-run**: Right-click → "Re-run from here" → workflow resumes from that step
4. **Edit modal**: Right-click → "Edit inputs" → modal shows type-specific fields
5. **Checkpoint persistence**: Run workflow, refresh page → node statuses restored
6. **Pause**: Click pause during execution → workflow stops, checkpoint saved
