You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is no explicit dependency declaration; correct ordering
relies on the order of task.add calls.
Cycle detection is impossible because there is no graph.
Fan-out / fan-in cannot be expressed: a task that consumes
outputs from two upstream tasks has no way to receive them both.
Concept
Introduce a real DAG model:
@action accepts an optional depends_on=[...] of upstream
actions.
Manager builds a dict[step, set[step]] adjacency list at
start.
A topological_sort (Kahn's algorithm) produces a level
ordering. Within a level, all tasks are independent and may run in parallel; between levels, the engine waits for joins.
A CycleError is raised at build time if the graph is invalid.
@action(depends_on=[...]) accepted and stored on the Action instance
Manager builds the adjacency list from registered tasks
topological_sort returns levels and raises CycleError
A new DAG executor consumes levels and runs each level via
the existing concurrency primitives
The four current modes (sequential, sequential_group, background, parallel) become DAG executor configurations
Backward-compat: workflows with no depends_on keep current
behavior
Tests: linear chain, fan-out, fan-in, diamond, cycle (raises)
Why this is in scope
Issue #248 (pass previous_context between groups) is a symptom of the missing DAG model. Solving it properly closes #248, makes the four execution modes converge into a single executor, and unlocks features like deterministic replay and dry-run.
Labels:
enhancement,discovery,RFCContext
The current execution model uses sibling-style grouping:
task.add(step=..., group_name="g1")groups tasks.Sequential.runiterates the queue linearly(
workflow.py:235-261).SequentialGroupruns each group in a separate processsequentially.
Parallel.runspawns one process per task with no inter-taskordering, and each subprocess receives an empty
previous_context(workflow.py:459-476, related issue Enhancement: Pass previous_context between task groups #248).This means:
relies on the order of
task.addcalls.outputs from two upstream tasks has no way to receive them both.
Concept
Introduce a real DAG model:
@actionaccepts an optionaldepends_on=[...]of upstreamactions.
Managerbuilds adict[step, set[step]]adjacency list atstart.
topological_sort(Kahn's algorithm) produces a levelordering. Within a level, all tasks are independent and may run in parallel; between levels, the engine waits for joins.
CycleErroris raised at build time if the graph is invalid.API sketch
Topological sort reference (Kahn)
Acceptance criteria
@action(depends_on=[...])accepted and stored on theActioninstanceManagerbuilds the adjacency list from registered taskstopological_sortreturns levels and raisesCycleErrorDAGexecutor consumes levels and runs each level viathe existing concurrency primitives
sequential,sequential_group,background,parallel) become DAG executor configurationsdepends_onkeep currentbehavior
Why this is in scope
Issue #248 (pass
previous_contextbetween groups) is a symptom of the missing DAG model. Solving it properly closes #248, makes the four execution modes converge into a single executor, and unlocks features like deterministic replay and dry-run.