4.6 KiB
Workflow Execution Orchestration & UI Ref-Lock Fix
Date: 2026-02-27
Problem
Two issues were addressed:
1. Workflow ref editable during edit mode (UI)
When editing an existing workflow action, the pack selector and workflow name fields were editable, allowing users to change the action's ref — which should be immutable after creation.
2. Workflow execution runtime error
Executing a workflow action produced:
Action execution failed: Internal error: Runtime not found: No runtime found for action: examples.single_echo (available: node.js, python, shell)
Root cause: Workflow companion actions are created with runtime: None (they aren't scripts — they're orchestration definitions). When the executor's scheduler received an execution request for a workflow action, it dispatched it to a worker like any regular action. The worker then tried to find a runtime to execute it, failed (no runtime matches a .workflow.yaml entrypoint), and returned the error.
The WorkflowCoordinator in crates/executor/src/workflow/coordinator.rs existed as prototype code but was never integrated into the execution pipeline.
Solution
UI Fix (web/src/pages/actions/WorkflowBuilderPage.tsx)
- Added
disabled={isEditing}to theSearchableSelectpack selector (already supported adisabledprop) - Added
disabled={isEditing}and conditional disabled styling to the workflow name<input> - Both fields are now locked when editing an existing workflow, preventing ref changes
Workflow Orchestration (crates/executor/src/scheduler.rs)
Added workflow detection and orchestration directly in the ExecutionScheduler:
- Detection:
process_execution_requestedchecksaction.workflow_def.is_some()before dispatching to a worker process_workflow_execution: Loads the workflow definition, parses it into aWorkflowDefinition, builds aTaskGraph, creates aworkflow_executionrecord, and marks the parent execution as Runningdispatch_workflow_task: For each entry-point task in the graph, creates a child execution with the task's actual action ref (e.g.,core.echoinstead ofexamples.single_echo) and publishes anExecutionRequestedmessage. The child execution includesworkflow_taskmetadata linking it back to theworkflow_executionrecord.advance_workflow(public): Called by the completion listener when a workflow child task completes. Evaluates transitions from the completed task, schedules successor tasks, checks join barriers, and completes the workflow when all tasks are done.complete_workflow: Updates both theworkflow_executionand parentexecutionrecords to their terminal state.
Key design decisions:
- Child task executions re-enter the normal scheduling pipeline via MQ, so nested workflows (a workflow task that is itself a workflow) are handled recursively
- Transition evaluation supports
succeeded(),failed(),timed_out(),always, and custom conditions (custom defaults to fire-on-success for now) - Join barriers are respected — tasks with
joincounts wait for enough predecessors
Completion Listener (crates/executor/src/completion_listener.rs)
- Added workflow advancement: when a completed execution has
workflow_taskmetadata, callsExecutionScheduler::advance_workflowto schedule successor tasks or complete the workflow - Added an
AtomicUsizeround-robin counter for dispatching successor tasks to workers
Binary Entry Point (crates/executor/src/main.rs)
- Added
mod workflow;so the binary crate can resolvecrate::workflow::graph::*paths used in the scheduler
Files Changed
| File | Change |
|---|---|
web/src/pages/actions/WorkflowBuilderPage.tsx |
Disable pack selector and name input when editing |
crates/executor/src/scheduler.rs |
Workflow detection, orchestration, task dispatch, advancement |
crates/executor/src/completion_listener.rs |
Workflow advancement on child task completion |
crates/executor/src/main.rs |
Added mod workflow; |
Architecture Note
This implementation bypasses the prototype WorkflowCoordinator (crates/executor/src/workflow/coordinator.rs) which had several issues: hardcoded attune. schema prefixes, SELECT * on the execution table, duplicate parent execution creation, and no integration with the MQ-based scheduling pipeline. The new implementation works directly within the scheduler and completion listener, using the existing repository layer and message queue infrastructure.
Testing
- Existing executor unit tests pass
- Workspace compiles with zero errors
- No new warnings introduced (pre-existing warnings from unused prototype workflow code remain)