# Orchestration as declared structure

> Orchestration is the part of a document that says how work is ordered and where it runs in parallel, and the grammar does not let that be implied.

Page: PAG · Orchestration
Canonical: https://banes-lab.com/pag/orchestration#declared-structure

This section is stop 81 of 102 in the learning route. Previous: [42 - Stating an invariant](https://banes-lab.com/disciplined-methodology/collaborate/stating-an-invariant.md). Next: [02 - Composing a collaboration](https://banes-lab.com/pag/orchestration/composing-a-workflow.md). It builds on [04 - Node design](https://banes-lab.com/pag/guide/node-design.md), [13 - The plan is a graph](https://banes-lab.com/disciplined-methodology/plan/the-flat-checklist.md).

[Orchestration](https://banes-lab.com/records/arch/orchestration.md) is the part of a document that says how work is ordered and where it runs in parallel, and the grammar does not let that be implied. A document declares its structure with constructs, each tied to the representation it makes explicit, as shown in [A1·d prose or construct](https://banes-lab.com/pag/orchestration#declared-structure-panel-d). A [dependency graph](https://banes-lab.com/records/arch/dependency-graph.md) covers a partial order with forward dependencies; [A1·a dependency graph](https://banes-lab.com/pag/orchestration#declared-structure-panel-a) declares one by name, and [A1·e name, never number](https://banes-lab.com/pag/orchestration#declared-structure-panel-e) shows what the name gains. A [finite state machine](https://banes-lab.com/records/arch/finite-state-machine.md) covers a lifecycle drawn from a closed set of states, as shown in [A1·b state machine](https://banes-lab.com/pag/orchestration#declared-structure-panel-b). Alongside these are a priority queue for a ranking, a flowchart for the rendered view of any of them, a surface for state that several parties share, a parallel block for readers that return, and a wait for a reader that never returns; [A1·c join and wait](https://banes-lab.com/pag/orchestration#declared-structure-panel-c) writes that last pair. The same idea is taught in [the plan is a graph](https://banes-lab.com/disciplined-methodology/plan/the-flat-checklist.md). Here it is the project stage of [the loop](https://banes-lab.com/disciplined-methodology/start/the-loop.md), and it yields an edge-list. Ordering carried by the order of sentences is [temporal coupling](https://banes-lab.com/records/arch/temporal-coupling.md), and a model given prose reconstructs a structure of its own.

### Structure is declared

Ordering implied by the order in which sentences appear is reconstructed by every reader, and each reconstructs it differently. A sequence of decisions is numbered, one is raised out of dependency order because the next number was free, and every citation of the displaced decision resolves to the wrong thing with nothing erroring. A sentence has an order and a graph has edges, and only the second survives being read by a party that did not write it.

For this reason concurrency and [event ordering](https://banes-lab.com/records/arch/event-ordering.md) are declared as structure, never implied by the order of the text. The order goes in a graph and the lifecycle in a state machine, rather than the units being numbered and the sequence narrated. In practice, an order is modelled as a dependency graph whose nodes name what they depend on, so the order is partial and a number never stands in for an edge. A lifecycle is modelled as a finite state machine whose states form a closed set, whose transitions name their trigger and their guard, and whose current state is derived from the tree by a function rather than written by a party. Independent investigations run as bounded readers in a parallel block, with their artifacts joined by an await, and a participant waits through a command with its turn kept open.

To check this, reorder the sentences of a node and run it again. Where the outcome changed, the ordering was carried by prose, and the repair is the construct that carries it explicitly. Whether a declared parallel group actually runs in parallel is a fact about the harness. The grammar declares that the readers are independent, the binding decides what that gains, and a harness with no [concurrency](https://banes-lab.com/records/arch/concurrency.md) runs them in order without the document changing.

A dependency graph is the construct for work whose order is a set of edges rather than a line. A node names what it depends on and what comes after it, and the successor is declared by name rather than derived from a position, for the reason given in [the board and the venue](https://banes-lab.com/disciplined-methodology/collaborate/the-board-and-the-venue.md). A [directed acyclic graph](https://banes-lab.com/records/arch/directed-acyclic-graph.md) turns a [circular dependency](https://banes-lab.com/records/arch/circular-dependency.md) into a defect the reader can see. Where one unit holds every other party's work, at most one such unit is open at a time, because two holds are two waits with no defined order between them.

A finite state machine is the construct for a lifecycle, and its states form a closed set because a mechanism can join on a value from a closed set but not on a sentence. A unit moves forward through its states over its life and never backwards, with one correction allowed where an act is reversed before anything depends on it. The current state is a [derived state](https://banes-lab.com/disciplined-methodology/verify/derived-state.md), a function over the tree, and no party writes it. Both constructs are [declarative configuration](https://banes-lab.com/records/arch/declarative-configuration.md) of a run, where a paragraph would only imply the configuration.

A parallel block with an await is the construct for readers that return: each is spawned with a task, receives nothing shared, and returns exactly one typed artifact. Investigations that read a tree and write nothing belong there, one per concern, because reading contends with nothing. A wait is the construct for a participant, which never returns; for a participant, [posting and waiting are one operation](https://banes-lab.com/disciplined-methodology/collaborate/posting-and-waiting-are-one-operation.md), and a wait is a call rather than a halt. The two constructs are not interchangeable, because an await joins a reader that was always going to end, while a wait keeps open a reader that must not end.

A1·a dependency graph

```pag
# NODE 5 — PROJECT   [epistemic · reasoning · graph · yields: edge-list]
@purpose: "Declare the order as edges, so a reader who did not write it can still resolve it"
@cue: "DECLARE_THE_EDGES"

CONTRACT:
input:        <the units of work>
transform:    for each unit → name what it depends on → refuse a cycle → name the groups that are independent
constraints:  a successor is declared by name, never derived from a position; at most one unit that holds the others is open at a time
output:       DAG <units>
handoff:      acyclic AND every unit names its dependencies (yields: edge-list + boolean)

DAG <units>:
NODE <unit-a>:
<what settles it>
NODE <unit-b> AFTER <unit-a>:
<what settles it>
NODE <unit-c> DEPENDS_ON [<unit-a>]:
<what settles it>
PARALLEL_GROUP: <unit-b>, <unit-c>

HANDOFF GATE (evidence-bearing):
rule_id: "PROJECT"   yields: edge-list + boolean
[check] no unit depends on itself through any path (evidence: the walk over DAG <units>) over: <units> measured: <acyclic> / <units>
[check] every successor is named, none is a number (evidence: the AFTER and DEPENDS_ON clauses)
[check] at most one holding unit is open (evidence: count of open holds)
result: pass → NODE 6 | a cycle → REPAIR (owner: NODE 5) | unknown → BLOCKED
```

A1·b state machine

```pag
# a lifecycle as a closed set of states · a transition names its trigger and its guard
STATE_MACHINE <unit>:
STATE <planned>:
ENTRY: <no artifact exists yet>
STATE <open>:
ENTRY: <a party has begun>
STATE <settled>:
ENTRY: <every condition of the exit holds>
STATE <retired>:
ENTRY: <what the settlement implies has landed>

TRANSITION FROM <planned> TO <open> ON <first-reading>
TRANSITION FROM <open> TO <settled> ON <exit-condition>
GUARD: <every party that must agree has agreed>
TRANSITION FROM <settled> TO <retired> ON <implied-work-landed>
GUARD: <nothing the settlement distributed is still open>
TRANSITION FROM <open> TO <planned> ON <artifact-removed>
GUARD: <no argument has landed yet>

FUNCTION state_of(unit):
# derived from the tree on every read · never written by a party
IF NOT EXISTS(unit.artifact): RETURN <planned>
IF every_exit_condition_holds(unit) AND implied_work_landed(unit): RETURN <retired>
IF every_exit_condition_holds(unit): RETURN <settled>
RETURN <open>
```

A1·c join and wait

```pag
# NODE 6 — ACT   [epistemic · formalisation · computation · yields: procedures]
CONTRACT:
input:        DAG <units>
transform:    run each independent group as bounded readers → join their artifacts → a participant waits rather than returns
constraints:  a bounded reader receives a task and nothing shared; whether a group runs together is the harness's fact, declared independence is the document's
output:       artifacts[] per group
handoff:      every group joined or explicitly still open (yields: procedure)

PARALLEL:
TASK "<investigate unit b · mutate nothing>" WITH agent: <role-b> → <artifact-b>
TASK "<investigate unit c · mutate nothing>" WITH agent: <role-c> → <artifact-c>
END
AWAIT <artifact-b>, <artifact-c> INTO <artifacts>

# a participant does not join · it waits, and a wait is a call rather than a halt
WAIT ON <the shared surface> AS <party> INTO <change>
IF <change> == <changed>:
READ_RESOURCE <the shared surface> whole INTO <current>
```

A1·d prose or construct

```mermaid
flowchart TB
prose["Prose · 'first do this, then that, meanwhile the other'"]
implied["Ordering implied by sentence order · the model reconstructs it"]
declared["A construct · DAG, STATE_MACHINE, PARALLEL, AWAIT, WAIT"]
explicit["Edges, states and groups every reader shares"]
prose --> implied
declared --> explicit
```

A1·e name, never number

```mermaid
flowchart LR
ordinal["An ordinal · a position in a total order"]
hidden["A unit raised before its predecessor settles · every number still intact"]
name["A declared successor · an edge in a partial order"]
caught["A successor nobody created, or a unit no predecessor declared · both decidable"]
ordinal -. preserves the violation .-> hidden
name --> caught
```

## Links to

- [Orchestration](https://banes-lab.com/records/arch/orchestration.md)
- [Dependency Graph](https://banes-lab.com/records/arch/dependency-graph.md)
- [Finite State Machine](https://banes-lab.com/records/arch/finite-state-machine.md)
- [The plan is a graph](https://banes-lab.com/disciplined-methodology/plan/the-flat-checklist.md)
- [The loop](https://banes-lab.com/disciplined-methodology/start/the-loop.md)
- [Temporal Coupling](https://banes-lab.com/records/arch/temporal-coupling.md)
- [Concurrency](https://banes-lab.com/records/arch/concurrency.md)
- [Event Ordering](https://banes-lab.com/records/arch/event-ordering.md)
- [The board and the venue](https://banes-lab.com/disciplined-methodology/collaborate/the-board-and-the-venue.md)
- [Directed Acyclic Graph (DAG)](https://banes-lab.com/records/arch/directed-acyclic-graph.md)
- [Circular Dependency](https://banes-lab.com/records/arch/circular-dependency.md)
- [Derived state](https://banes-lab.com/disciplined-methodology/verify/derived-state.md)
- [Declarative Configuration](https://banes-lab.com/records/arch/declarative-configuration.md)
- [Posting and waiting are one operation](https://banes-lab.com/disciplined-methodology/collaborate/posting-and-waiting-are-one-operation.md)

## Linked from

- [Coordination is software](https://banes-lab.com/disciplined-methodology/collaborate/coordination-is-software.md)
