## ADDED Requirements ### Requirement: DAG topological execution The engine SHALL execute workflow nodes in topological order determined by `depends_on` edges using Kahn's algorithm. #### Scenario: Independent nodes run concurrently - **WHEN** a workflow has nodes A and B with no `depends_on` - **THEN** both A and B SHALL execute in the same topological layer, concurrently #### Scenario: Dependent nodes run sequentially - **WHEN** node B lists `depends_on: [A]` - **THEN** A SHALL complete before B begins #### Scenario: Cycle detection - **WHEN** nodes form a cycle (A → B → C → A) - **THEN** the loader SHALL reject the workflow with a cycle detection error ### Requirement: Trigger rules The engine SHALL support 4 trigger rules for join semantics. #### Scenario: all_success (default) - **WHEN** a node has multiple upstream dependencies and no explicit `trigger_rule` - **THEN** it SHALL only run if ALL upstream nodes completed successfully - **THEN** it SHALL be skipped if any upstream node failed #### Scenario: one_success - **WHEN** a node sets `trigger_rule: one_success` - **THEN** it SHALL run if at least one upstream node completed successfully #### Scenario: all_done - **WHEN** a node sets `trigger_rule: all_done` - **THEN** it SHALL run when all upstream nodes have finished (any status), regardless of success/failure #### Scenario: none_failed_min_one_success - **WHEN** a node sets `trigger_rule: none_failed_min_one_success` - **THEN** it SHALL run only if no upstream node failed AND at least one succeeded ### Requirement: when conditions Nodes SHALL support a `when:` string that evaluates to a boolean condition. #### Scenario: when condition prevents execution - **WHEN** a node has `when: "false"` or any expression that evaluates falsy - **THEN** the node SHALL be skipped as if its trigger_rule prevented execution ### Requirement: Node retry with configurable policy Nodes SHALL support a `retry` config with `max_attempts`, `delay_ms`, and `on_error` (transient|all). #### Scenario: retry on transient error - **WHEN** a node with `retry: { max_attempts: 3 }` fails with a transient error - **THEN** it SHALL retry up to 3 times with configured delay between attempts #### Scenario: retry exhausted - **WHEN** all retry attempts fail - **THEN** the node SHALL be marked as failed and trigger_rule evaluation proceeds