docs: specify foreach back edge semantics

This commit is contained in:
lda
2026-09-04 01:44:30 +07:00 Verified
parent ca6425af32
commit 9aaf1b4d78
6 changed files with 240 additions and 11 deletions
@@ -185,6 +185,29 @@ Future foreach metadata should evolve into inherited structured lineage context:
- normal node authors should receive foreach values through mapped input;
inspecting runtime context is an advanced escape hatch
## Iteration Body Return
An iteration body returns through an ordinary edge targeting its owning
`ForeachNode`. The runtime recognizes that target using the item frame's typed
owner metadata, completes the child frame, and wakes the parent barrier. It does
not execute the foreach controller inside the child frame.
`END` and explicit `EndNode` are workflow/subgraph terminals, not foreach item
returns. Validation rejects either terminal while traversing an active foreach
item context. This replaces the earlier implementation convention in which an
item reached `END` to wake its parent.
The canonical graph therefore uses:
```text
foreach.loop -> body
body -> foreach
foreach.done -> continuation
```
The exact runtime, validation, migration, and nested-context rules are specified
in the [foreach back-edge design](../superpowers/specs/2026-09-04-foreach-back-edge-design.md).
## Deferred Work
Explicit Fork/Gather is deferred. A future `GatherNode` should expose explicit
@@ -97,12 +97,12 @@ overlap in the asynchronous runtime. Both modes must produce equivalent graph
semantics. Scheduler order decides when compatible work progresses, never which
arrivals belong together.
`END` means completion of the current execution frame, not necessarily
completion of the whole run. The frame owner determines the consequence: a
root frame completes its workflow invocation, a subgraph root returns to its
parent boundary, and a foreach item reports completion to its parent barrier.
For a foreach, normal item-frame completion therefore allows the controller to
admit or resume the next item without introducing a separate continue node.
`END` and explicit `EndNode` represent workflow/subgraph termination, not a
generic way to complete any child frame. A foreach item returns through a
back-edge targeting its owning `ForeachNode`; the runtime completes that item
frame and wakes its parent barrier without executing the controller inside the
child. Future fork branches likewise converge through explicit gathers rather
than independently terminating the containing workflow scope.
General break and race behavior are not part of the first fork/gather design.
The existing foreach `fail`, `skip`, and `collect` policies describe the
@@ -141,10 +141,10 @@ those relationships are canonical on the lineage and duplicated frame fields
can disagree with them. Runtime operations should resolve and validate a
frame's lineage and scope together.
**Model normal foreach completion as a continue node.** Rejected because
completion of an item frame already returns control to the owning foreach.
Break and race semantics remain separate future policies rather than additional
meanings assigned to ordinary outcomes.
**Model normal foreach completion as a continue node.** Rejected because an
ordinary back-edge to the owning foreach already expresses item return in the
canonical graph. Break and race semantics remain separate future policies
rather than additional meanings assigned to ordinary outcomes.
**Reuse or rename `JoinNode`.** Rejected as the default because the existing
node is a pass-through marker with no barrier contract.