Each superstep runs every ready task against the same committed ThreadState, then commits their updates and schedules the next frontier together:
Tasks run in frontier order (possibly concurrently); none sees another's writes.
If any task fails, the superstep commits nothing and the run fails with the first failure in frontier order.
Each command is checked: every update is to a key in the node's declared write set, every route targets a node and join of this graph, and a task fans out to a join at most once.
Updates apply task by task in frontier order, and in emission order within a task.
The next frontier is, for each task in order, its static edges (declaration order) then its routes (route order, fan-out payloads in item order); then the targets of joins this commit released - static joins in declaration order, then dynamic activations in the order they opened.
The run completes when the frontier is empty and no join is waiting; a join still waiting at that point can never release and fails the run with GraphError.UnsatisfiedJoin.
Rebuilds an execution from a snapshot, checking it against this graph first: the graph id, version and structural fingerprint; that every state value and pending input decodes with this graph's codec for that key or node; that every join exists with the right kind; and that every arrival a dynamic join still expects is a pending task in its fan-out. Every problem is reported at once.
Rebuilds an execution from a snapshot, checking it against this graph first: the graph id, version and structural fingerprint; that every state value and pending input decodes with this graph's codec for that key or node; that every join exists with the right kind; and that every arrival a dynamic join still expects is a pending task in its fan-out. Every problem is reported at once.