Uh oh!
There was an error while loading. Please reload this page.
improvement(copilot): state persistence, subflow recreation, dynamic handle topologies - #3569
Conversation
PR SummaryMedium Risk Overview Stabilizes copilot edits by preserving configured subblock types, normalizing condition/router branch IDs server-side, merging Improves canvas behavior for subflows and dynamic handles: subflow bodies no longer capture clicks (edges inside remain clickable), node z-index is computed consistently, shift-click multi-select now resolves parent/child conflicts, and dynamic condition/router handle topology is centralized ( Written by Cursor Bugbot for commit 1bd97ff. Configure here. |
The latest updates on your projects. Learn more about Vercel for GitHub. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Greptile SummaryThis PR introduces a unified workflow state normalization pipeline and several targeted fixes for subflow interaction, copilot stability, and dynamic handle topology. It's a substantial, well-structured improvement across the full stack. Key changes:
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Full-state write trigger\n(hydration / copilot apply /\nsocket sync / undo-redo)"] --> B["normalizeWorkflowState()"]
B --> B1["Validate blocks\n(type + name required)"]
B1 --> B2["Validate parentIds\n(container exists, not self-ref)"]
B2 --> B3["validateEdges()\nstrip missing / annotation /\ntrigger / scope-crossing edges"]
B3 --> B4["generateLoopBlocks()\ngenerateParallelBlocks()"]
B4 --> C["NormalizationResult\n{ state, warnings }"]
C --> D["replaceWorkflowState()\nWorkflow Zustand store"]
C --> E["DB persist\n(PUT /api/workflows/id/state)"]
C --> F["Socket broadcast\nenqueueReplaceWorkflowState()"]
G["Copilot edit-workflow tool"] --> H["applyOperationsToWorkflowState()\nPass 1: block ops\nPass 2: deferred edges\nPass 3: removeInvalidScopeEdges()"]
H --> I["applyTargetedLayout()\nnew + repositioned blocks only"]
I --> J["normalizeWorkflowState()\nfinal DB write"]
J --> E
K["SubBlock value change\n(conditions / routes)"] --> L["syncDynamicHandleSubblockValue()\nWorkflow store – topology only"]
L --> M["collectDynamicHandleTopologySignatures()"]
M --> N["useDynamicHandleRefresh()\nupdateNodeInternals() via rAF\nfor changed blocks"]
Last reviewed commit: 20312df |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
icecrasher321
commented
Mar 14, 2026
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…handle topologies (simstudioai#3569) * improvement(copilot): state persistence, subflow recreation, dynamic handle topologies * address comments

Summary
Unified workflow state validation pipeline: all full-state writes (hydration, copilot apply, socket sync, undo/redo) now route through normalizeWorkflowState, which validates parentIds, edges (existence + scope + trigger), and regenerates subflows. Eliminates ghost edges that persist in DB but don't render on canvas.
Fixed subflow interaction model: edges inside subflows are now directly clickable without needing to select a block first, condition/router handle topology is derived from canonical workflow block state with centralized React Flow internals refresh, and parent-child selection conflicts are resolved bidirectionally on shift-click.
Stabilized nested block IDs across copilot edits: edit operations with nestedNodes now merge by name instead of delete-and-recreate, preserving child block IDs. Condition/router branch IDs are generated server-side via normalizeConditionRouterIds so the LLM doesn't need to construct internal IDs.
Copilot feedback improvements: scope-crossing edges, sanitization warnings, and invalid branch configurations are now reported back to the LLM via skippedItems and validationErrors instead of being silently normalized. Removed the double-save race between server and client persistence paths.
Type of Change
Testing
Tested manually
Checklist