ADR-0003: Synth preserves declaration order
Status: accepted, 2026-08-31
Context
FlowDoc invariant 1 requires stable action ordering. Two candidates: a canonical
order derived from the graph (breadth-first from StartAction), or the order the
author declared blocks in.
Decision
Synth emits declaration order.
Consequences
Reachability order interleaves error handlers into the happy path. On the demo
flow it produces welcome, check-hours, apologize, announce-closed, set-working-queue, ..., because apologize is an error target of welcome.
That is not how a person writes a flow, so codegen would emit code that reads
wrong, against the codegen non-negotiable.
Declaration order also makes codegen(synth(code)) byte-stable with no
normalization pass rather than one, since nothing is reordered in either
direction.
Determinism still holds: declaration order is part of the input, so the same input yields byte-identical output.
Reachability order is still useful for lint's reachable-blocks rule and for
comparing two flows that are semantically identical but declared differently. It
stays available as the exported canonicalOrder, just not applied by synth.