diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index af516f13..46145c30 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -14,7 +14,7 @@ None
- ✅ **v1.1 Improvements** - Phases 7-14 (shipped 2026-01-12)
- ✅ **v1.2 Improvements** - Phases 15-24 (shipped 2026-01-17)
- ✅ **v1.3 Improvements** - Phases 25-30 (shipped 2026-01-24)
-- 🚧 **v1.4 Features** - Phases 31-35 (in progress)
+- 🚧 **v1.4 Features** - Phases 31-35, 40 (in progress)
- 📋 **v1.5 Store Refactoring** - Phases 36-39 (planned)
## Phases
@@ -517,6 +517,26 @@ Plans:
- [ ] 35-02-PLAN.md — Selection-aware subgraph extraction (TDD)
- [ ] 35-03-PLAN.md — Client-side wiring, ChatPanel selection chip, API subgraph integration
+#### Phase 40: Node Enhancements
+
+**Goal**: Add new node types and UI improvements — output gallery, image compare node, prompt constructor node, and image numbering on connections
+**Depends on**: Phase 35
+**Research**: Likely (gallery UI patterns, image comparison approaches)
+**Research topics**: Gallery/carousel component patterns, image diff/compare slider UX, prompt builder UX patterns, edge label rendering in React Flow
+**Plans**: 4 plans
+
+**Features:**
+1. Output gallery node — scrollable thumbnail grid with full-screen lightbox
+2. Image compare node — slider overlay comparison of two images
+3. Prompt constructor node — template-based prompts with @variable interpolation
+4. Connection numbering — "Image N" labels on image edges when selected
+
+Plans:
+- [ ] 40-01-PLAN.md — OutputGallery node (thumbnail grid + lightbox)
+- [ ] 40-02-PLAN.md — Connection numbering (image edge sequence labels)
+- [ ] 40-03-PLAN.md — ImageCompare node (react-compare-slider)
+- [ ] 40-04-PLAN.md — PromptConstructor node (variable system + template interpolation)
+
### 📋 v1.5 Store Refactoring (Planned)
**Milestone Goal:** Major refactoring of workflowStore.ts (2,900+ lines) into modular, testable components. Extract execution engine, create Zustand slices, and improve code maintainability while maintaining full backward compatibility.
@@ -631,7 +651,7 @@ Plans:
## Progress
**Execution Order:**
-Phases execute in numeric order: 1 → 2 → ... → 35 → 36 → 37 → 38 → 39
+Phases execute in numeric order: 1 → 2 → ... → 35 → 40 → 36 → 37 → 38 → 39
| Phase | Milestone | Plans Complete | Status | Completed |
|-------|-----------|----------------|--------|-----------|
@@ -668,8 +688,9 @@ Phases execute in numeric order: 1 → 2 → ... → 35 → 36 → 37 → 38 →
| 31. Workflow Proposal System | v1.4 | 2/2 | Complete | 2026-01-26 |
| 32. Chat UI Foundation | v1.4 | 2/2 | Complete | 2026-01-27 |
| 33. Workflow Edit Safety | v1.4 | 2/2 | Complete | 2026-01-30 |
-| 34. Context-Aware Agentic Editing | v1.4 | 1/3 | In progress | - |
-| 35. Large Workflow Handling | v1.4 | 0/? | Not started | - |
+| 34. Context-Aware Agentic Editing | v1.4 | 3/3 | Complete | 2026-01-31 |
+| 35. Large Workflow Handling | v1.4 | 3/3 | Complete | 2026-01-31 |
+| 40. Node Enhancements | v1.4 | 0/? | Not started | - |
| 36. Execution Engine Extraction | v1.5 | 0/3 | Not started | - |
| 37. Pure Helpers Extraction | v1.5 | 0/2 | Not started | - |
| 38. Zustand Slice Pattern | v1.5 | 0/3 | Not started | - |
diff --git a/.planning/STATE.md b/.planning/STATE.md
index 80eb4e12..0041879a 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -211,6 +211,7 @@ Recent decisions affecting current work:
- Phase 30 added: Small fixes
- Milestone v1.4 Features created: 5 phases (Phase 31-35), agentic workflow builder with proposal dialogs and chat-based editing
- Milestone v1.5 Store Refactoring created: 4 phases (Phase 36-39), major refactor of workflowStore.ts into modular execution engine and Zustand slices
+- Phase 40 added to v1.4: Node enhancements — output gallery, image compare node, prompt constructor node, image numbering on connections
## Session Continuity
diff --git a/src/components/EdgeToolbar.tsx b/src/components/EdgeToolbar.tsx
index a9d31ea0..e19bf359 100644
--- a/src/components/EdgeToolbar.tsx
+++ b/src/components/EdgeToolbar.tsx
@@ -1,6 +1,7 @@
"use client";
import { useWorkflowStore } from "@/store/workflowStore";
+import { WorkflowEdgeData } from "@/types";
import { useMemo, useEffect, useState, useRef } from "react";
export function EdgeToolbar() {
@@ -13,6 +14,41 @@ export function EdgeToolbar() {
[edges]
);
+ // Helper function to compute the image connection sequence number
+ const getImageSequenceNumber = (edge: typeof selectedEdge): number | null => {
+ if (!edge) return null;
+
+ // Only show for image connections
+ const sourceHandle = edge.sourceHandle;
+ const targetHandle = edge.targetHandle;
+ const isImageConnection =
+ (sourceHandle === "image" || sourceHandle?.startsWith("image-")) ||
+ (targetHandle === "image" || targetHandle?.startsWith("image-"));
+
+ if (!isImageConnection) return null;
+
+ // Find all image edges going to the same target + target handle
+ const siblingEdges = edges.filter(
+ (e) => e.target === edge.target && e.targetHandle === edge.targetHandle
+ );
+
+ // If only one connection, no need for numbering
+ if (siblingEdges.length <= 1) return null;
+
+ // Sort by createdAt timestamp (fallback to edge ID for legacy edges without timestamp)
+ const sorted = [...siblingEdges].sort((a, b) => {
+ const timeA = (a.data as WorkflowEdgeData)?.createdAt || 0;
+ const timeB = (b.data as WorkflowEdgeData)?.createdAt || 0;
+ if (timeA !== timeB) return timeA - timeB;
+ return a.id.localeCompare(b.id);
+ });
+
+ const index = sorted.findIndex((e) => e.id === edge.id);
+ return index >= 0 ? index + 1 : null;
+ };
+
+ const sequenceNumber = getImageSequenceNumber(selectedEdge);
+
// Track mouse position when edge selection changes
useEffect(() => {
const handleMouseDown = (e: MouseEvent) => {
@@ -62,6 +98,11 @@ export function EdgeToolbar() {
transform: "translateX(-50%)",
}}
>
+ {sequenceNumber !== null && (
+
+ Image {sequenceNumber}
+
+ )}