diff --git a/docs/current_roadmap.md b/docs/current_roadmap.md index 27578115..68d9cff3 100644 --- a/docs/current_roadmap.md +++ b/docs/current_roadmap.md @@ -795,12 +795,6 @@ stable. - Native subgraph polish: optional per-use-site child deployment overrides and clearer child trace inspection. -- Active concurrent foreach correction: replace item-body `END` routes with - canonical back-edges to the owning foreach. The approved semantics are in the - [`foreach back-edge design`](superpowers/specs/2026-09-04-foreach-back-edge-design.md). - This slice also makes foreach control regions fail-closed, rejects unreachable - workflow nodes, and gives repeated visits to one foreach node distinct - persisted activation identities. - After that correction, reuse the foreach barrier/lineage machinery for fork/gather. The proposed control semantics are recorded in [`ADR-0006`](adr/0006-explicit-fork-and-topology-driven-gather.md). @@ -942,6 +936,11 @@ stable. routes, or outputs. Python, JSON-RPC, MCP, and local/remote CLI surfaces are aligned. Implementation plan: [`capability step updates`](historical/superpowers/plans/2026-07-26-capability-step-update.md). +- Completed: foreach bodies now return through validated back-edges to their + immediate owner, with unique static control regions and fresh persisted + activation identities for every dynamic visit. Design: + [`foreach back-edge design`](superpowers/specs/2026-09-04-foreach-back-edge-design.md). + Fork/gather remains explicitly deferred. Agent evaluation cohort status and policy: diff --git a/docs/superpowers/specs/2026-09-04-foreach-back-edge-design.md b/docs/superpowers/specs/2026-09-04-foreach-back-edge-design.md index aeeb58da..f6673a96 100644 --- a/docs/superpowers/specs/2026-09-04-foreach-back-edge-design.md +++ b/docs/superpowers/specs/2026-09-04-foreach-back-edge-design.md @@ -2,9 +2,9 @@ ## Status -Approved in conversation on 2026-09-04. This document specifies canonical -foreach body-return semantics. It does not include the separately planned -ergonomic Python DSL or authorize fork/gather implementation. +Implemented on 2026-09-04. This document specifies canonical foreach +body-return semantics. It does not include the separately planned ergonomic +Python DSL or authorize fork/gather implementation. ## Purpose diff --git a/docs/wf_authoring_control_flow.md b/docs/wf_authoring_control_flow.md index d3ff1586..881453a5 100644 --- a/docs/wf_authoring_control_flow.md +++ b/docs/wf_authoring_control_flow.md @@ -228,6 +228,17 @@ step with item-local child lineages: In async execution, admitted async item node handlers may run at the same time. Run-state mutation, tracing, and barrier commits remain deterministic. +An iteration body returns through its immediate owning foreach: + +```python +g.connect(each, "loop", record) +g.connect(record, "ok", each) +g.connect(each, "done", END) +``` + +Region conflicts, unreachable nodes, body terminals, non-local returns, empty +bodies, and bodies without possible returns fail validation. + See `examples/authoring_concurrent_foreach.py` for a runnable example covering: - sync concurrent foreach with `item_error={"action": "collect", ...}`; diff --git a/docs/wf_core_architecture.md b/docs/wf_core_architecture.md index 92ac9761..156efd01 100644 --- a/docs/wf_core_architecture.md +++ b/docs/wf_core_architecture.md @@ -74,9 +74,10 @@ interrupted, failed, or deadlocked. This replaces the older assumption that ## Foreach Serial foreach creates one iteration child frame, records typed -`ForeachIterationMetadata`, blocks on that child, and enqueues the child. When -the child reaches `END`, `wake_parent_if_children_complete` wakes the blocked -parent so it can create the next iteration or emit `done`. +`ForeachIterationMetadata`, blocks on that child, and enqueues the child. An +item child returns by targeting its immediate owning foreach. The child +finishes at that owner location without executing the controller; the parent +activation consumes the result and continues or completes its barrier. Concurrent foreach uses the same frame machinery but admits multiple item lineages according to `ForeachConcurrentPolicy`. Each item lineage reads through @@ -98,6 +99,9 @@ See `examples/raw_concurrent_foreach.py` for the canonical raw workflow shape an - validate edge sources, destinations, duplicate outcomes, and declared outcomes - validate reachable nodes have all required outcome edges - validate explicit `EndNode` outcomes against `Workflow.outcomes` +- validate foreach control regions once: region conflicts, unreachable nodes, + body terminals, non-local returns, empty bodies, and bodies without possible + returns fail validation Validation reports multiple issues through `ValidationReport` instead of raising at the first failure.