Skip to content

feat(execution-core): add execution_incomplete terminal state - #99

Open
dawidaksamski wants to merge 1 commit into
feat/WB-430-emit-node-skipped-eventsfrom
feat/WB-430-introduce-execution-incomplete-status
Open

feat(execution-core): add execution_incomplete terminal state#99
dawidaksamski wants to merge 1 commit into
feat/WB-430-emit-node-skipped-eventsfrom
feat/WB-430-introduce-execution-incomplete-status

Conversation

@dawidaksamski

Copy link
Copy Markdown
Contributor

What

A graph could route itself into nothing and report success. When a decision returns a
nextPort no edge carries — deleted edge, renamed branch, never wired — every outgoing
edge is pruned and the run closed as completed with part of the graph never run.

runGraph now records each dead end as { nodeId, port } and, if any were found, emits a
terminal execution_incomplete event in place of execution_completed and writes the
'incomplete' status. Not a failure — nothing threw, so Temporal still closes the Workflow
Execution as Completed. Failure keeps precedence, and the cycle check stays a failure with
its own "stalled" wording.

Dead ends don't stop the run: they're collected run-scoped and reported once at the end, so
parallel branches still deliver their work.

⚠️ Behaviour change

An 'errorRoute' failure with no 'errorRoute' edge now ends the run incomplete — it was
previously documented as a usable silent DLQ. The general rule covers it (the policy names a
port, nothing was wired to it), and excluding it would mean carving out
RESERVED_ERROR_HANDLE. Deliberate absorption is what 'continue' is for; the README now
says so. The test asserting the old behaviour was rewritten, not deleted.

Worth a look in review

Six separate places enumerate terminal states — worker database.ts, backend
drain-events.ts and routes/executions.ts, ai-studio stream adapter, store, and controls.
All six change here; missing one hangs an SSE stream, leaves finished_at null, or strands
the UI mid-run. run-workflow.ts is a comment-only change: its guard is === 'failed', so
the new state correctly falls through.

Naming (incomplete over stalled), why the cycle check stays separate, and the
errorRoute reversal are written up in
packages/execution-core/terminal-states.decision-log.md.

Zrzut ekranu 2026-08-24 o 15 21 04

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.

2 participants