fix(executor): stop run-from-block reusing the source run's branch state

Merged
WA
1mo ago
+226-1

Summary

  • Run-from-block seeds the new run from a previous execution's snapshot. It filtered block states, executed blocks, and loop/parallel state to the reachable set, but restored the source run's deactivatedEdges / nodesWithActivatedEdge unfiltered (since #4604 added edge restore for pause/resume)
  • With the join-readiness rule from #7537, that stale state made a condition's unselected target run whenever the source run had taken that branch, and released a join before its live input finished (the join then ran a second time with the real value)
  • Fix: after restoring, clear the edge state for the run-from-block dirty set with the existing EdgeManager.clearDeactivatedEdgesForNodes — the same reset the loop orchestrator does per iteration and the parallel orchestrator does per batch
  • Resume is unaffected (it never sets runFromBlockContext); parallels were already reset per batch; upstream cached state is untouched

Type of Change

  • Bug fix

Testing

  • New executor.run-from-block.test.ts: a real full run, then a real executeFromBlock from that run's snapshot, through the actual engine (only block handlers mocked). Covers unselected branch, re-selected branch, diamond join both ways, cached sibling input, fan-in join, condition in a loop, condition in a parallel. 5 of 8 fail without the fix; the other 3 guard unchanged behavior
  • executor, lib/workflows, app/api/workflows, lib/mothership/tools suites: 7,613 tests passing
  • tsc, lint, block registry, check:audits (49 audits), docs manifest all pass

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)