Workflow Editor POC Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Build a workflow editor inside Sasha Studio that makes Workflow the first-class concept, with a React Flow canvas, CodeMirror code view, three template models, and two working examples.
Architecture: Workflow .md files stored in workflows/ directory, parsed to AST (frontmatter + fenced blocks), rendered as React Flow graph. Server syncs files to a workflows DB table on startup. Executions use the existing unified executions table. The editor launches from a renamed "Workflows" tab (was "Tasks").
Tech Stack: React 18, React Flow, CodeMirror 6 (existing), Vitest, Express, better-sqlite3 (existing), Tailwind CSS (existing), Phosphor Icons (existing)
Design doc: docs/plans/2026-02-28-workflow-editor-design.md
Spec repo: https://github.com/context-is-everything/sasha-workflow
Task 1: Install React Flow dependency
Files:
- Modify:
claudecodeui/package.json
Step 1: Install reactflow
Run: cd claudecodeui && npm install @xyflow/react
Step 2: Verify install
Run: npm ls @xyflow/react
Expected: Shows installed version
Step 3: Verify build still works
Run: npx vite build
Expected: Build succeeds with no errors
Step 4: Commit
git add package.json package-lock.json
git commit -m "chore(deps): add @xyflow/react for workflow editor"
Task 2: Build the workflow file parser
The parser converts Agent Flow .md files into a typed AST. This is the foundation everything else depends on.
Files:
- Create:
claudecodeui/src/utils/workflowParser.js - Create:
claudecodeui/src/utils/__tests__/workflowParser.test.js
Step 1: Write the failing tests
Test cases needed:
parseFrontmatter: extracts YAML frontmatter, handles missing frontmatter, parses nested objects (budgets, triggers)parseFencedBlocks: extracts step/agent/bundle/runtime/observability blocks, returns empty arrays for missing sectionsparseWorkflow: full parse, layer inference (0=no steps, 1=linear, 2=parallel/conditions, 3=runtime with waitpoints)- Round-trip: parse the example files from
all-project-files/workflows/
Step 2: Run tests to verify they fail
Run: cd claudecodeui && npx vitest run src/utils/__tests__/workflowParser.test.js
Expected: All tests FAIL (module not found)
Step 3: Implement the parser
Key functions:
parseFrontmatter(md)→{ frontmatter: object, body: string }— regex extract---delimited YAML, parse with js-yamlparseFencedBlocks(body)→{ steps[], agents[], bundles[], runtime, observability }— regex for```step,```agent, etc., parse each with js-yamlinferLayer(steps, blocks)→0|1|2|3— check for runtime waitpoints (3), parallel/conditions (2), any steps (1), none (0)parseWorkflow(md)→ full AST combining frontmatter + blocks + derived layer
Uses js-yaml for YAML parsing (check if already in dependencies, install if not).
Step 4: Run tests to verify they pass
Run: cd claudecodeui && npx vitest run src/utils/__tests__/workflowParser.test.js
Expected: All tests PASS
Step 5: Verify build
Run: cd claudecodeui && npx vite build
Expected: Build succeeds
Step 6: Commit
git add src/utils/workflowParser.js src/utils/__tests__/workflowParser.test.js
git commit -m "feat(workflow): add Agent Flow markdown parser with tests"
Task 3: Build the workflow serializer (AST to Markdown)
The serializer converts the AST back to a valid Agent Flow .md file. This powers the visual-to-code direction.
Files:
- Create:
claudecodeui/src/utils/workflowSerializer.js - Create:
claudecodeui/src/utils/__tests__/workflowSerializer.test.js
Step 1: Write the failing tests
Test cases:
- Round-trip: serialize then re-parse, verify AST matches
- Includes agents/bundles/runtime/observability sections only when present
- Omits empty optional sections
- Frontmatter includes triggers, budgets, tools when set
Step 2: Implement the serializer
Key function:
serializeWorkflow(ast)→ markdown string
Structure:
- Build frontmatter object (only non-empty fields)
- Dump as YAML between
---delimiters - Add
# Purposeheading with description - Add
## Agentswith```agentblocks (if any) - Add
## Stepswith```stepblocks - Add
## Bundleswith```bundleblocks (if any) - Add
## Runtimewith```runtimeblock (if present) - Add
## Observabilitywith```observabilityblock (if present)
Step 3: Run tests, verify pass
Step 4: Commit
git add src/utils/workflowSerializer.js src/utils/__tests__/workflowSerializer.test.js
git commit -m "feat(workflow): add workflow serializer (AST to markdown)"
Task 4: Build the server-side workflow API
Files:
- Create:
claudecodeui/server/routes/workflows.js - Create:
claudecodeui/server/database/workflowDb.js - Modify:
claudecodeui/server/database/init.sql(add workflows table after line ~607) - Modify:
claudecodeui/server/index.js(register route near line 2266, add sync on startup)
Step 1: Add workflows table to init.sql
CREATE TABLE IF NOT EXISTS workflows (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
file_path TEXT NOT NULL,
description TEXT,
kind TEXT,
version TEXT,
status TEXT DEFAULT 'draft',
layer INTEGER DEFAULT 0,
triggers_json TEXT,
enabled INTEGER DEFAULT 1,
last_synced_at TEXT,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_workflows_name ON workflows(name);
CREATE INDEX IF NOT EXISTS idx_workflows_enabled ON workflows(enabled);
Step 2: Create workflowDb.js
Functions: listWorkflows(), getWorkflow(name), upsertWorkflow({...}), deleteWorkflow(name)
Follow the pattern in schedulerDb.js:
formatWorkflow(row)converts DB row to camelCase- Prepared statements for each operation
upsertWorkflowusesINSERT ... ON CONFLICT(name) DO UPDATE
Step 3: Create workflows.js routes
Endpoints:
GET /— list all workflowsGET /:name— get workflow metadata + file contentPUT /:name— save workflow content + sync metadata to DBDELETE /:name— delete workflow file + DB recordPOST /sync— rescan workflows directory and sync to DB
The syncWorkflowsFromDisk() function scans workflows/ directory, parses frontmatter from each .md file, and upserts to DB.
Path to workflows directory: process.env.PROJECT_FILES_PATH || path.join(process.cwd(), 'all-project-files') + /workflows
Step 4: Register in server/index.js
- Import:
import workflowRoutes, { syncWorkflowsFromDisk } from './routes/workflows.js'; - Mount:
app.use('/api/workflows', workflowRoutes); - Startup sync: call
syncWorkflowsFromDisk()after scheduler init
Step 5: Verify build
Run: cd claudecodeui && npx vite build
Step 6: Commit
git add server/routes/workflows.js server/database/workflowDb.js server/database/init.sql server/index.js
git commit -m "feat(workflow): add server-side workflow API and database"
Task 5: Create the two example workflow files
Files:
- Create:
claudecodeui/all-project-files/workflows/report-publisher-pipeline.md - Create:
claudecodeui/all-project-files/workflows/transcript-to-report.md
Step 1: Copy examples from spec repo
mkdir -p claudecodeui/all-project-files/workflows
cp /Users/lindsay/Documents/work/sasha-workflow/examples/report-publisher-pipeline.md claudecodeui/all-project-files/workflows/
cp /Users/lindsay/Documents/work/sasha-workflow/examples/transcript-to-report.md claudecodeui/all-project-files/workflows/
Step 2: Commit
git add claudecodeui/all-project-files/workflows/
git commit -m "feat(workflow): add example workflow files (report-publisher, transcript-to-report)"
Task 6: Build the three workflow templates
Files:
- Create:
claudecodeui/src/utils/workflowTemplates.js
Step 1: Create templates module
Export TEMPLATES array with three entries:
- Simple Pipeline (
id: 'simple'): validate_input → process → format_output. Layer 1. Low budgets. - Agentic Workflow (
id: 'agentic'): validate → specialist → QA gate → assemble. Layer 2. Two agents (specialist, critic). Medium budgets. - Parallel Fan-out (
id: 'parallel'): validate → parallel extract → confirmation gate → assemble. Layer 2. Three workers in a bundle with merge config. Higher budgets.
Each template has:
id,name,description,icon,layergenerate(workflowName)→ full workflow AST with best-practice budgets, reason codes, and observability pre-configured
Export helper: generateFromTemplate(templateId, workflowName) → AST
Step 2: Commit
git add src/utils/workflowTemplates.js
git commit -m "feat(workflow): add three workflow template models (simple, agentic, parallel)"
Task 7: Build the Workflow Manager panel (list view)
Files:
- Create:
claudecodeui/src/components/WorkflowManager.jsx - Modify:
claudecodeui/src/components/MainContent.jsx(swap tab) - Modify:
claudecodeui/src/utils/api.js(add workflow API methods)
Step 1: Add workflow API methods to api.js
Add api.workflows object with: list(), get(name), save(name, content, metadata), delete(name), sync()
Step 2: Build WorkflowManager component
Follow SchedulesPanel.jsx pattern exactly for structure and styling. Key sections:
- Header: "Workflows" title + "+ New Workflow" button
- Workflow list: Cards showing name, description, layer badge (L0-L3 with color), trigger summary, last execution status, [Edit] [Run Now] buttons
- Template picker modal: Shown when "+ New" clicked. Three cards (Simple, Agentic, Parallel) with name, description, icon. Click → prompt for workflow name → generate from template → save → open editor.
- Legacy prompts section: Collapsed section at bottom showing existing scheduled prompts with "Convert to Workflow" badge (not functional in POC)
- Search/filter: Debounced search across workflow names and descriptions
State management: useState for workflows list, loading, search filter, template picker visibility. Fetch on mount via api.workflows.list().
Step 3: Update MainContent.jsx
- Import
WorkflowManager - Add state:
showWorkflowManager,editingWorkflow - Change
schedulestab toworkflowstab withTreeStructureicon and "Workflows" label - Wire tab click to
setShowWorkflowManager(true) - Render
<WorkflowManager isOpen={showWorkflowManager} onClose={...} onEdit={(name) => setEditingWorkflow(name)} /> - Keep SchedulesPanel import and rendering (legacy prompts accessible)
Step 4: Verify build
Run: cd claudecodeui && npx vite build
Step 5: Commit
git add src/components/WorkflowManager.jsx src/components/MainContent.jsx src/utils/api.js
git commit -m "feat(workflow): add Workflow Manager panel with template picker"
Task 8: Build the Workflow Editor (React Flow canvas)
Files:
- Create:
claudecodeui/src/components/WorkflowEditor.jsx - Create:
claudecodeui/src/components/workflow/StepNode.jsx - Create:
claudecodeui/src/components/workflow/StepInspector.jsx - Create:
claudecodeui/src/components/workflow/workflowToGraph.js - Modify:
claudecodeui/src/components/MainContent.jsx(render editor overlay)
Step 1: Create workflowToGraph.js
Converts parsed AST to React Flow nodes and edges:
- Each step becomes a node at position
(250, index * 120 + 50) - Node data includes step properties + color + iconName from type lookup tables
- Edges derived from reads/writes: if step B reads what step A writes, edge A→B
- Sequential fallback edges (dashed) for steps without dependency edges
- Explicit edges for
goto(orange) andfallback(red dashed)
Color map: transform=blue, skill=purple, tool=green, decision=orange, gate=red, parallel=teal, end=gray.
Step 2: Create StepNode.jsx
Custom React Flow node component:
- Renders as a card: colored left border, icon, step id (bold), type badge, one-line description
- Gate steps: octagon shape via CSS
clip-path - Decision steps: diamond rotation via CSS transform
- Parallel steps: double border
- Source and target handles for edge connections
Step 3: Create StepInspector.jsx
Bottom panel form for selected step. Fields:
id(readonly text)type(dropdown: transform, skill, tool, decision, gate, parallel, end)description(text input)reads(comma-separated text, parsed to array)writes(comma-separated text, parsed to array)when(text input, optional)on_error(dropdown: stop, skip, fallback, retry)fallback(dropdown of other step IDs, shown when on_error=fallback)expected_output(textarea, optional)reason_code(text input)agent(dropdown of agent IDs, shown for skill/gate types)bundle(dropdown of bundle names, shown for parallel type)
Changes call onStepChange(stepId, updates) prop.
Step 4: Build WorkflowEditor.jsx
Full-screen overlay (z-[300], same pattern as CodeEditor modal). Structure:
- Toolbar: Back button, workflow name (editable), version, status badge, [Save] [Run Now] buttons
- View toggle: [Canvas] [Code] [Split] buttons
- Main area:
- Canvas mode: React Flow full width
- Code mode: CodeMirror full width (read-only for POC, shows serialized MD)
- Split mode: 60/40 split with resizable divider
- Inspector: Bottom panel, 200px height, shown when node selected
- React Flow config:
nodeTypes: { stepNode: StepNode }, background dots, minimap, controls
State flow:
- Load:
api.workflows.get(name)→ content string - Parse:
parseWorkflow(content)→ AST - Graph:
workflowToGraph(ast)→{ nodes, edges } - Edit: Inspector changes → update AST →
workflowToGraph(newAst)→ update nodes/edges +serializeWorkflow(newAst)→ update code pane - Save:
serializeWorkflow(ast)→api.workflows.save(name, md, metadata)
Step 5: Wire into MainContent.jsx
- Import WorkflowEditor
- Render as overlay when
editingWorkflowis set - Pass
onClose={() => setEditingWorkflow(null)}
Step 6: Verify build
Run: cd claudecodeui && npx vite build
Step 7: Commit
git add src/components/WorkflowEditor.jsx src/components/workflow/
git commit -m "feat(workflow): add React Flow workflow editor with canvas and inspector"
Task 9: Add workflow icons to icon management
Files:
- Modify:
claudecodeui/src/components/icons/index.jsx
Step 1: Check which icons need adding
Required icons: TreeStructure, Funnel, Lightning, Wrench, GitBranch, ShieldCheck, ArrowsSplit, Flag
Check existing exports in icons/index.jsx, add any missing.
Step 2: Commit
git add src/components/icons/index.jsx
git commit -m "feat(icons): add workflow step type icons"
Task 10: Docker build and integration test
Step 1: Verify local dev
Run: cd /Users/lindsay/Documents/work/sasha && ./dev.sh
Open http://localhost:3007, verify:
- "Workflows" tab appears (was "Tasks")
- Two example workflows listed
- "+ New Workflow" opens template picker with three models
- Clicking "Edit" opens the workflow editor
- Canvas shows nodes with correct colors and edges
- Code pane shows valid Agent Flow markdown
- Clicking a node opens inspector with editable fields
- Inspector changes update the canvas and code
- Save persists to file and DB
- Existing "Tasks" functionality still accessible
Step 2: Verify Docker build
Run: cd /Users/lindsay/Documents/work/sasha && ./docker-local.sh
Open http://localhost:3006, same verification.
Step 3: Fix any issues, commit fixes
Task 11: Bump version and push
Step 1: Bump version
Run: ./docker-build-ghcr.sh patch
Step 2: Push
Run: git push origin main
Dependency Graph
Task 1 (React Flow) ──────────────────────────┐
Task 2 (Parser) ────── Task 3 (Serializer) ───┤
Task 4 (Server API) ──────────────────────────┤
Task 5 (Example files) ────────────────────────┤
Task 6 (Templates) ───────────────────────────┤── Task 7 (Manager UI) ── Task 8 (Editor) ── Task 10 (Test) ── Task 11 (Ship)
Task 9 (Icons) ────────────────────────────────┘
Tasks 1, 2, 4, 5, 6, 9 can run in parallel.
Task 3 depends on Task 2.
Task 7 depends on Tasks 4, 6.
Task 8 depends on Tasks 1, 2, 3, 7.
Task 10 depends on all above.
