F095: Execution Order — Common Abstraction for Step Display Ordering
Scope
In Scope
- Domain-level graph traversal functions (
ExecutionOrder, NextDefaultStep) in internal/domain/workflow/graph.go
- CLI step display functions refactored to iterate in graph-defined order instead of map iteration order
- TUI
orderedSteps()/nextStepName() replaced by delegation to domain functions
Out of Scope
- Parallel branch ordering within a parallel step (branches remain unordered)
- Persisting execution order in state files or history database
- Reordering based on actual runtime completion timestamps
Deferred
| Item |
Rationale |
Follow-up |
Topological sort for DAG workflows with depends_on |
Current workflows are linear chains; DAG ordering adds complexity without immediate user demand |
future |
| Conditional path display (showing which branch was taken at runtime) |
Requires runtime path tracking not currently stored in ExecutionContext |
future |
User Stories
US1: Deterministic Step Order in CLI Execution Summary (P1 - Must Have)
As a workflow author running awf run,
I want the --- Execution Details --- summary to display steps in workflow-defined order (from Initial following transitions),
So that I can read the execution report as a sequential narrative matching my workflow definition.
Why this priority: The current random map iteration order makes the CLI summary unreadable for workflows with more than 2-3 steps. Every run produces a different display order, making it impossible to quickly scan for the step that failed or took too long.
Acceptance Scenarios:
- Given a workflow with steps
init → build → test → deploy → done defined via Initial and Transitions, When I run awf run and execution completes, Then --- Execution Details --- lists steps in order: init, build, test, deploy, done.
- Given the same workflow run twice, When I compare the two
--- Execution Details --- outputs, Then the step order is identical across both runs.
- Given a workflow with a step that has conditional transitions (
when: "{{states.build.exit_code}} != 0" → rollback, default → test), When the default path is taken, Then the summary lists steps following the default transition path.
Independent Test: Run awf run on a 5-step linear workflow three times and verify the --- Execution Details --- output has identical step ordering each time.
US2: Domain-Level Execution Order Function (P1 - Must Have)
As a developer building CLI or TUI interfaces for AWF,
I want a single workflow.ExecutionOrder() function in the domain layer that returns steps in graph traversal order,
So that all interfaces produce consistent step ordering without duplicating traversal logic.
Why this priority: Without this, the TUI and CLI maintain separate ordering implementations. The TUI already has a correct implementation; extracting it to the domain layer is the architectural prerequisite for US1 and prevents future divergence.
Acceptance Scenarios:
- Given a workflow with
Initial: "step_a" and transitions step_a → step_b → step_c (terminal), When I call workflow.ExecutionOrder(wf), Then it returns [step_a, step_b, step_c] in that order.
- Given a workflow where
step_b has a default transition (empty When) to step_c and a conditional transition to step_d, When I call workflow.ExecutionOrder(wf), Then it follows the default path: [step_a, step_b, step_c].
- Given a workflow with a cycle in the default path (
step_a → step_b → step_a), When I call workflow.ExecutionOrder(wf), Then it stops at the revisited step and returns [step_a, step_b] without infinite loop.
Independent Test: Write unit tests calling ExecutionOrder() with various workflow graph shapes and asserting the returned slice order.
US3: TUI Delegates to Domain Graph Functions (P2 - Should Have)
As a maintainer of AWF,
I want the TUI's orderedSteps() and nextStepName() replaced by calls to workflow.ExecutionOrder() and workflow.NextDefaultStep(),
So that ordering logic has a single source of truth in the domain layer and the TUI code is simplified.
Why this priority: The TUI already works correctly. This refactoring eliminates code duplication and ensures both interfaces stay in sync if the traversal algorithm changes. Lower priority because there is no user-visible behavior change.
Acceptance Scenarios:
- Given the TUI monitoring tab rendering step trees, When I view a running workflow, Then steps appear in the same order as before the refactoring (no visual regression).
Independent Test: Run the TUI on a multi-step workflow and visually confirm the step tree order matches the workflow definition order. Existing TUI tests (if any) continue to pass.
US4: Consistent Step Output Display in CLI (P2 - Should Have)
As a workflow author,
I want showStepOutputs() and showEmptyStepFeedback() in the CLI to display step outputs in workflow-defined order,
So that I can read stdout blocks sequentially matching the execution flow.
Why this priority: Extends US1's ordering to the stdout/stderr output sections, not just the status summary. Important for readability but secondary to the status display.
Acceptance Scenarios:
- Given a 4-step workflow where each step produces stdout, When execution completes, Then the
--- [step_name] stdout --- blocks appear in workflow-defined order.
- Given a workflow where step
build has output but step init does not, When execution completes, Then the empty step feedback for init appears before the output block for build.
Independent Test: Run a multi-step workflow with varying output and verify the stdout blocks are ordered consistently.
Edge Cases
- What happens when
Initial references a step name not present in Steps map? ExecutionOrder returns an empty slice.
- What happens when a step's default transition points to a non-existent step? Traversal stops at that step; the returned slice includes all steps up to but not including the missing target.
- What happens when the workflow has zero steps or an empty
Initial? ExecutionOrder returns nil.
- What happens when a parallel step is encountered? It is included in the ordered list as a single entry; its
Branches are not individually expanded into the sequence.
- What happens when all transitions are conditional (no default
When: "" and no OnSuccess)? Traversal stops at that step since no default path can be determined.
Requirements
Functional Requirements
- FR-001: System MUST provide
ExecutionOrder(wf *Workflow) []Step in internal/domain/workflow/graph.go that returns steps ordered by default-path graph traversal from wf.Initial.
- FR-002: System MUST provide
NextDefaultStep(step *Step) string in internal/domain/workflow/graph.go that resolves the next step name via default transition (empty When), falling back to OnSuccess.
- FR-003:
ExecutionOrder MUST terminate traversal when encountering a terminal step, a visited step (cycle prevention), or a missing step reference.
- FR-004: CLI functions
showExecutionDetails(), showStepOutputs(), showEmptyStepFeedback(), and buildStepInfos() MUST iterate steps in the order returned by ExecutionOrder() instead of map iteration.
- FR-005: TUI's
orderedSteps() and nextStepName() MUST be removed and replaced by calls to workflow.ExecutionOrder() and workflow.NextDefaultStep().
- FR-006:
showExecutionDetails(), showStepOutputs(), showEmptyStepFeedback(), and buildStepInfos() MUST accept *workflow.Workflow as an additional parameter to access graph structure.
Non-Functional Requirements
- NFR-001:
ExecutionOrder execution time MUST be O(n) where n is the number of steps; no repeated traversals or quadratic lookups.
- NFR-002: Zero new external dependencies introduced.
- NFR-003: All existing tests MUST continue to pass after refactoring; no behavioral regression in TUI or CLI output content (only ordering changes in CLI).
Success Criteria
- SC-001: CLI
--- Execution Details --- output displays steps in identical order across 10 consecutive runs of the same workflow.
- SC-002:
make test, make lint, and make build pass with zero violations after implementation.
- SC-003: TUI step display order is unchanged before and after the refactoring.
- SC-004:
graph_test.go covers linear chains, branching defaults, cycles, empty workflows, terminal stops, and missing step references with 100% of ExecutionOrder and NextDefaultStep code paths exercised.
Key Entities
| Entity |
Description |
Key Attributes |
| Workflow |
Directed graph of execution steps with a designated entry point |
Initial string, Steps map[string]*Step |
| Step |
Single node in the workflow graph with outbound transitions |
Name, Type, Transitions, OnSuccess, OnFailure |
| Transition |
Directed edge between steps, optionally conditional |
When string (empty = default), Goto string |
Assumptions
- The default execution path (followed by
ExecutionOrder) is sufficient for display ordering; runtime-actual path tracking is not needed for this feature.
- Workflows are predominantly linear chains or simple branches; complex DAGs with
depends_on are rare and do not need ordered display in this iteration.
- The TUI's existing
orderedSteps() implementation is correct and can be extracted as-is to the domain layer.
- Passing
*workflow.Workflow to CLI display functions is an acceptable signature change since these are internal unexported functions.
Metadata
- Status: backlog
- Version: v0.9.0
- Priority: medium
- Estimation: S
Dependencies
- Blocked by: none
- Unblocks: none
Clarifications
Section populated during clarify step with resolved ambiguities.
Notes
graph.go already contains FindReachableStates, DetectCycles, GetTransitions — the new functions are a natural addition to this file.
- The TUI implementation at
tab_monitoring.go:829-864 serves as the reference implementation; the domain extraction should preserve its exact traversal semantics (default transition first, then OnSuccess, stop at terminal or visited).
- CLI functions at
run.go:716-782 all share the same pattern of for name, state := range execCtx.GetAllStepStates() — each needs the workflow parameter added and the iteration changed to range over ExecutionOrder() output, looking up state by name.
F095: Execution Order — Common Abstraction for Step Display Ordering
Scope
In Scope
ExecutionOrder,NextDefaultStep) ininternal/domain/workflow/graph.goorderedSteps()/nextStepName()replaced by delegation to domain functionsOut of Scope
Deferred
depends_onExecutionContextUser Stories
US1: Deterministic Step Order in CLI Execution Summary (P1 - Must Have)
As a workflow author running
awf run,I want the
--- Execution Details ---summary to display steps in workflow-defined order (fromInitialfollowing transitions),So that I can read the execution report as a sequential narrative matching my workflow definition.
Why this priority: The current random map iteration order makes the CLI summary unreadable for workflows with more than 2-3 steps. Every run produces a different display order, making it impossible to quickly scan for the step that failed or took too long.
Acceptance Scenarios:
init → build → test → deploy → donedefined viaInitialandTransitions, When I runawf runand execution completes, Then--- Execution Details ---lists steps in order:init,build,test,deploy,done.--- Execution Details ---outputs, Then the step order is identical across both runs.when: "{{states.build.exit_code}} != 0"→rollback, default →test), When the default path is taken, Then the summary lists steps following the default transition path.Independent Test: Run
awf runon a 5-step linear workflow three times and verify the--- Execution Details ---output has identical step ordering each time.US2: Domain-Level Execution Order Function (P1 - Must Have)
As a developer building CLI or TUI interfaces for AWF,
I want a single
workflow.ExecutionOrder()function in the domain layer that returns steps in graph traversal order,So that all interfaces produce consistent step ordering without duplicating traversal logic.
Why this priority: Without this, the TUI and CLI maintain separate ordering implementations. The TUI already has a correct implementation; extracting it to the domain layer is the architectural prerequisite for US1 and prevents future divergence.
Acceptance Scenarios:
Initial: "step_a"and transitionsstep_a → step_b → step_c (terminal), When I callworkflow.ExecutionOrder(wf), Then it returns[step_a, step_b, step_c]in that order.step_bhas a default transition (emptyWhen) tostep_cand a conditional transition tostep_d, When I callworkflow.ExecutionOrder(wf), Then it follows the default path:[step_a, step_b, step_c].step_a → step_b → step_a), When I callworkflow.ExecutionOrder(wf), Then it stops at the revisited step and returns[step_a, step_b]without infinite loop.Independent Test: Write unit tests calling
ExecutionOrder()with various workflow graph shapes and asserting the returned slice order.US3: TUI Delegates to Domain Graph Functions (P2 - Should Have)
As a maintainer of AWF,
I want the TUI's
orderedSteps()andnextStepName()replaced by calls toworkflow.ExecutionOrder()andworkflow.NextDefaultStep(),So that ordering logic has a single source of truth in the domain layer and the TUI code is simplified.
Why this priority: The TUI already works correctly. This refactoring eliminates code duplication and ensures both interfaces stay in sync if the traversal algorithm changes. Lower priority because there is no user-visible behavior change.
Acceptance Scenarios:
Independent Test: Run the TUI on a multi-step workflow and visually confirm the step tree order matches the workflow definition order. Existing TUI tests (if any) continue to pass.
US4: Consistent Step Output Display in CLI (P2 - Should Have)
As a workflow author,
I want
showStepOutputs()andshowEmptyStepFeedback()in the CLI to display step outputs in workflow-defined order,So that I can read stdout blocks sequentially matching the execution flow.
Why this priority: Extends US1's ordering to the stdout/stderr output sections, not just the status summary. Important for readability but secondary to the status display.
Acceptance Scenarios:
--- [step_name] stdout ---blocks appear in workflow-defined order.buildhas output but stepinitdoes not, When execution completes, Then the empty step feedback forinitappears before the output block forbuild.Independent Test: Run a multi-step workflow with varying output and verify the stdout blocks are ordered consistently.
Edge Cases
Initialreferences a step name not present inStepsmap?ExecutionOrderreturns an empty slice.Initial?ExecutionOrderreturnsnil.Branchesare not individually expanded into the sequence.When: ""and noOnSuccess)? Traversal stops at that step since no default path can be determined.Requirements
Functional Requirements
ExecutionOrder(wf *Workflow) []Stepininternal/domain/workflow/graph.gothat returns steps ordered by default-path graph traversal fromwf.Initial.NextDefaultStep(step *Step) stringininternal/domain/workflow/graph.gothat resolves the next step name via default transition (emptyWhen), falling back toOnSuccess.ExecutionOrderMUST terminate traversal when encountering a terminal step, a visited step (cycle prevention), or a missing step reference.showExecutionDetails(),showStepOutputs(),showEmptyStepFeedback(), andbuildStepInfos()MUST iterate steps in the order returned byExecutionOrder()instead of map iteration.orderedSteps()andnextStepName()MUST be removed and replaced by calls toworkflow.ExecutionOrder()andworkflow.NextDefaultStep().showExecutionDetails(),showStepOutputs(),showEmptyStepFeedback(), andbuildStepInfos()MUST accept*workflow.Workflowas an additional parameter to access graph structure.Non-Functional Requirements
ExecutionOrderexecution time MUST be O(n) where n is the number of steps; no repeated traversals or quadratic lookups.Success Criteria
--- Execution Details ---output displays steps in identical order across 10 consecutive runs of the same workflow.make test,make lint, andmake buildpass with zero violations after implementation.graph_test.gocovers linear chains, branching defaults, cycles, empty workflows, terminal stops, and missing step references with 100% ofExecutionOrderandNextDefaultStepcode paths exercised.Key Entities
Initial string,Steps map[string]*StepName,Type,Transitions,OnSuccess,OnFailureWhen string(empty = default),Goto stringAssumptions
ExecutionOrder) is sufficient for display ordering; runtime-actual path tracking is not needed for this feature.depends_onare rare and do not need ordered display in this iteration.orderedSteps()implementation is correct and can be extracted as-is to the domain layer.*workflow.Workflowto CLI display functions is an acceptable signature change since these are internal unexported functions.Metadata
Dependencies
Clarifications
Section populated during clarify step with resolved ambiguities.
Notes
graph.goalready containsFindReachableStates,DetectCycles,GetTransitions— the new functions are a natural addition to this file.tab_monitoring.go:829-864serves as the reference implementation; the domain extraction should preserve its exact traversal semantics (default transition first, thenOnSuccess, stop at terminal or visited).run.go:716-782all share the same pattern offor name, state := range execCtx.GetAllStepStates()— each needs the workflow parameter added and the iteration changed to range overExecutionOrder()output, looking up state by name.