Thrust reverser — Lauda Air 004: in-flight deployment, made structural
On 26 May 1991, Lauda Air Flight 004 — a Boeing 767 climbing out of Bangkok — lost 223 people when the left engine's thrust reverser deployed IN FLIGHT. Reverse thrust at climb power tore the airflow off the wing; the aircraft broke up in seconds. The reverser system had interlocks, but they were plumbing and relays guarding a hydraulic valve — and a fault sequence got past them. Here flight phase and reverser position are ONE state machine. The state {in flight, reverser deployed} is not guarded against — it is not a state. Deployment is reachable only from on_ground (weight on wheels), and the only exit from reverse thrust is stowing: you cannot rotate back into the air with the buckets out either.
A Soma program from the aerospace part of the verified corpus: 100 lines, cells ThrustReverser, ReverserTests. It passes soma check with soma 3.2.4.
How it is built
The cell ThrustReverser declares 5 signals in its face: touchdown_wow(id: String) -> Map, deploy_reverse(id: String) -> Map, stow_reverse(id: String) -> Map, takeoff_roll(id: String) -> Map and reverser_state(id: String) -> String; keeps 1 memory slot: n1_pct (Map<String, Int>, persistent and consistent) under the invariant n1_pct >= 0 && n1_pct <= 104. Its state machine reverser starts in inflight and allows 4 transitions: inflight -> on_ground, on_ground -> reverse_thrust, reverse_thrust -> on_ground and on_ground -> inflight. Handlers: guarded (line 44), touchdown_wow (line 50), deploy_reverse (line 55), stow_reverse (line 61), takeoff_roll (line 66) and reverser_state (line 72).
The file also holds 1 test cell (ReverserTests) with 12 assertions, run by soma test.
The source
thrust_reverser.cell
// ============================================================================
// THRUST REVERSER — Lauda Air 004: in-flight deployment, made structural
// ============================================================================
//
// On 26 May 1991, Lauda Air Flight 004 — a Boeing 767 climbing out of
// Bangkok — lost 223 people when the left engine's thrust reverser
// deployed IN FLIGHT. Reverse thrust at climb power tore the airflow off
// the wing; the aircraft broke up in seconds. The reverser system had
// interlocks, but they were plumbing and relays guarding a hydraulic
// valve — and a fault sequence got past them.
//
// Here flight phase and reverser position are ONE state machine. The
// state {in flight, reverser deployed} is not guarded against — it is
// not a state. Deployment is reachable only from on_ground (weight on
// wheels), and the only exit from reverse thrust is stowing: you cannot
// rotate back into the air with the buckets out either.
// ============================================================================
cell ThrustReverser {
face {
signal touchdown_wow(id: String) -> Map
signal deploy_reverse(id: String) -> Map
signal stow_reverse(id: String) -> Map
signal takeoff_roll(id: String) -> Map
signal reverser_state(id: String) -> String
}
memory {
// commanded N1, percent — never outside the engine's rated band
n1_pct: Map<String, Int> [persistent, consistent]
invariant n1_pct >= 0 && n1_pct <= 104
}
// ABSENT: inflight -> reverse_thrust (the Lauda Air state)
// ABSENT: reverse_thrust -> inflight (lifting off with buckets out)
state reverser {
initial: inflight
inflight -> on_ground // weight on wheels at touchdown
on_ground -> reverse_thrust // deploy: only with WoW
reverse_thrust -> on_ground // stow is the ONLY exit
on_ground -> inflight // takeoff: only from stowed
}
on guarded(id: String, target: String) {
let r = try { transition(id, target) }
if r.error != () { return map("ok", false, "reason", "{r.error}") }
return map("ok", true, "state", get_status(id))
}
on touchdown_wow(id: String) {
n1_pct.set(id, 30) // idle at touchdown
return guarded(id, "on_ground")
}
on deploy_reverse(id: String) {
let r = guarded(id, "reverse_thrust")
if r.ok { n1_pct.set(id, 85) } // reverse power, on ground only
return r
}
on stow_reverse(id: String) {
n1_pct.set(id, 25)
return guarded(id, "on_ground")
}
on takeoff_roll(id: String) {
let r = guarded(id, "inflight")
if r.ok { n1_pct.set(id, 100) }
return r
}
on reverser_state(id: String) { return get_status(id) }
}
cell test ReverserTests {
rules {
// THE Lauda Air transition: deployment in flight. It does not exist.
assert_fails transition("eng1", "reverse_thrust")
assert deploy_reverse("eng1").ok == false
assert reverser_state("eng1") == "inflight"
// the legal sequence: touchdown, deploy, stow, depart again
assert touchdown_wow("eng1").ok == true
assert deploy_reverse("eng1").ok == true
assert reverser_state("eng1") == "reverse_thrust"
// with the buckets out, the only exit is stowing — no takeoff
assert_fails transition("eng1", "inflight")
assert stow_reverse("eng1").ok == true
assert takeoff_roll("eng1").ok == true
// and airborne again, the interlock holds
assert_fails transition("eng1", "reverse_thrust")
// commanded N1 can never leave the rated band
assert_fails n1_pct.set("eng1", 120)
assert_fails n1_pct.set("eng1", -5)
}
}What the toolchain says
$ soma check thrust_reverser.cell
✓ All checks passed.$ soma test thrust_reverser.cell
test ReverserTests ...
✓ assert_fails transition("eng1", "reverse_thrust") — raised invalid transition: inflight → reverse_thrust. Current state: 'inflight'. Valid targets: [on_ground]
✓ assert deploy_reverse("eng1").ok == false
✓ assert reverser_state("eng1") == "inflight"
✓ assert touchdown_wow("eng1").ok == true
✓ assert deploy_reverse("eng1").ok == true
✓ assert reverser_state("eng1") == "reverse_thrust"
✓ assert_fails transition("eng1", "inflight") — raised invalid transition: reverse_thrust → inflight. Current state: 'reverse_thrust'. Valid targets: [on_ground]
✓ assert stow_reverse("eng1").ok == true
✓ assert takeoff_roll("eng1").ok == true
✓ assert_fails transition("eng1", "reverse_thrust") — raised invalid transition: inflight → reverse_thrust. Current state: 'inflight'. Valid targets: [on_ground]
✓ assert_fails n1_pct.set("eng1", 120) — raised memory invariant violated on 'n1_pct': n1_pct >= 0 && n1_pct <= 104 — rejected write of 120 (key "eng1"); the slot is unchanged
✓ assert_fails n1_pct.set("eng1", -5) — raised memory invariant violated on 'n1_pct': n1_pct >= 0 && n1_pct <= 104 — rejected write of -5 (key "eng1"); the slot is unchanged
12 tests: 12 passed, 0 failed$ soma verify thrust_reverser.cell
Verifying thrust_reverser.cell...
State machine 'reverser': 3 states, initial 'inflight'
States: [inflight, on_ground, reverse_thrust]
✓ 3 states, 4 transitions
✓ all states reachable from 'inflight'
✓ reactive machine: no terminal state, and every reachable state can return to 'inflight'
✓ no deadlocks
✓ liveness: every reachable state can return to 'inflight' (reactive machine)
⚠ dynamic transition targets: handler `guarded` uses a dynamic (computed) transition target — the state these handlers move to is computed at run time (from input or an LLM answer), so the machine's safety is checked at run time for them, not proven
✓ termination: all 6 handlers structurally terminate
⚠ refinement (partial — dynamic targets fall back to runtime check): handler `guarded` calls transition() with a computed target — which edge it takes is checked at run time (invalid_transition), not proven; write the target as a literal state to have it verified
✓ refinement (partial — dynamic targets fall back to runtime check): handler `guarded` ⟶ <dynamic>
ThrustReverser/invariants:
✓ invariant n1_pct >= 0 && n1_pct <= 104 — writer 'deploy_reverse' proven (writes 85)
✓ invariant n1_pct >= 0 && n1_pct <= 104 — writer 'stow_reverse' proven (writes 25)
✓ invariant n1_pct >= 0 && n1_pct <= 104 — writer 'takeoff_roll' proven (writes 100)
✓ invariant n1_pct >= 0 && n1_pct <= 104 — writer 'touchdown_wow' proven (writes 30)
11 passed, 2 warnings, 0 failures
Temporal properties for 'reverser':
✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK