Stages
Arc stage reference for stage declaration, entry semantics, parallel monitoring, and inline sequences
Stage declaration
stage name {
flow_statement
flow_statement
flow_statement
}Stage bodies contain flow statements. All flow statements in a stage run concurrently while the stage is active.
Stage body syntax
stage pressurize {
// Conditional transitions (propagate while truthy)
pressure > 500 => next
abort_btn => abort
// Continuous flows
true -> press_vlv_cmd // once on entry
sensor -> controller{} // every sample
}Conditional flows whose target is a stage or sequence name are
transitions: next,
named-stage jumps, or cross-sequence jumps.
Stage entry semantics
When entering a stage:
- Local variables (
:=) reset to their initial values; stateful variables ($=) keep their state - Continuous flows (
->) start fresh - Timing nodes (
time.wait,time.interval) reset their countdowns - Inline sub-sequences restart from their first item
- Channel triggers only react to new writes. Values written before stage activation are ignored
Aside from stateful variables ($=), a stage holds no state between entries.
Resumable controllers
Stage entry semantics enable a common pattern: a controller that parks in a yield
stage and waits for a fresh command to re-enter:
sequence controller {
stage run {
// ... control logic ...
stop_cmd => stop
}
stage stop {
false -> valve_cmd
time.wait{duration=250ms} => yield
}
stage yield {
// Only a new write to start_cmd will re-enter run.
start_cmd => run
}
}
start_cmd => controllerBecause channel triggers only react to new writes after stage entry, a held-truthy
start_cmd won’t immediately re-enter run. The operator has to issue a fresh start.
Parallel monitoring
All flow statements in a stage run concurrently:
stage pressurize {
// ALL of these run simultaneously
ox_pt_1 > 600 => abort // monitor
fuel_pt_1 > 400 => abort // monitor
abort_btn => abort // listen
pressure > 500 => next // advance
sensor -> controller{target=500} // control loop
}Line order and priority
When multiple conditional transitions (=>) are truthy in the same cycle, the first one
listed wins:
stage pressurize {
// Safety conditions first (higher priority)
ox_pt_1 > 600 => abort // 1st priority
fuel_pt_1 > 400 => abort // 2nd priority
abort_btn => abort // 3rd priority
// Success condition after safety
pressure > 500 => next // only if no abort
}Between a stage and a sequence declared inside it, the line written first wins only when
both lines jump to a top-level sequence or stage. A transition inside the inner
sequence, such as => next, does not compete with the stage’s jump: it acts first, then
the jump acts in the same cycle, so the stage the inner sequence entered stops at once.
For continuous flows (->), if multiple flows write to the same channel, last write
wins based on line order.
Inline sequences in a stage
An anonymous sequence { ... } inside a stage runs its items in order while the stage’s
parallel flows continue. The inline sequence restarts from its first item every time the
parent stage is entered.
stage fire {
chamber_temp > 2000 => abort
sequence {
true -> igniter_cmd
time.wait{200ms}
true -> ox_main_vlv_cmd
}
}