Skip to content

feat: Workflow execution snapshotting for safe live editing#339

Draft
geoffwellman wants to merge 2 commits intouseplunk:nextfrom
geoffwellman:feature/workflow-execution-snapshotting
Draft

feat: Workflow execution snapshotting for safe live editing#339
geoffwellman wants to merge 2 commits intouseplunk:nextfrom
geoffwellman:feature/workflow-execution-snapshotting

Conversation

@geoffwellman
Copy link
Copy Markdown

Summary

  • Freeze the workflow graph (steps, transitions, template content) into a JSON snapshot on each execution at start time
  • Execution engine reads from the snapshot instead of the live DB, so in-flight contacts are isolated from workflow edits
  • Soft-delete for workflow steps preserving execution history and FK integrity
  • All active-execution edit restrictions removed — users can freely edit live workflows
  • UI updated with informational banner, per-step execution count badges, and node position persistence

What this enables

Users can now edit step configs, add/remove/reorder steps, change templates, and rewire transitions on live workflows without affecting contacts already in-flight. Each execution runs the version of the workflow it started with.

Changes

Backend:

  • workflowSnapshot Json? field on WorkflowExecution — stores frozen graph at execution start
  • WorkflowSnapshot types + buildWorkflowSnapshot() / resolveWorkflowGraph() helpers
  • WorkflowExecutionService rewired to resolve graph from snapshot (with legacy fallback for pre-existing executions)
  • WorkflowStep.deletedAt for soft-delete, SetNull on step execution FKs
  • Edit restriction guards removed from WorkflowService (update, updateStep, deleteStep, deleteTransition)
  • New GET /workflows/:id/step-execution-counts endpoint

Frontend:

  • Restrictive edit-lock banner replaced with informational "N contacts in workflow, changes only affect new executions"
  • Execution count badges on each workflow node
  • Node positions persist across page loads (saved on drag stop, dagre skipped for positioned nodes)

Test plan

  • 7 new snapshot isolation tests passing
  • 15 existing integration tests passing (zero regressions)
  • 47 condition operator tests passing
  • TypeScript compiles with zero new errors
  • Manual: Create workflow → trigger execution → edit step config → verify in-flight execution uses original config
  • Manual: Drag nodes → refresh page → positions persist
  • Manual: View workflow with active executions → badges show per-step counts

🤖 Generated with Claude Code

geoffwellman and others added 2 commits April 2, 2026 22:33
Freeze the workflow graph (steps, transitions, template content) into a
JSON snapshot on each execution at start time. The execution engine reads
from this snapshot instead of the live DB, so in-flight contacts are
completely isolated from workflow edits.

- Add workflowSnapshot Json field to WorkflowExecution
- Add WorkflowSnapshot types and buildWorkflowSnapshot/resolveWorkflowGraph helpers
- Rewire WorkflowExecutionService to resolve graph from snapshot with legacy fallback
- Implement soft-delete for WorkflowStep (deletedAt field)
- Change StepExecution.stepId and Execution.currentStepId to SetNull on delete
- Remove active-execution edit restrictions from WorkflowService
- Add 7 snapshot isolation tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace restrictive edit-lock banner with informational message
  ("N contacts in workflow, changes only affect new executions")
- Add execution count badges on workflow nodes showing active
  contacts per step via new step-execution-counts API endpoint
- Fix position persistence: save node positions to DB on drag stop
  and skip dagre auto-layout for nodes with saved positions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant