soma.cell

Cargo door — Turkish Airlines 981: "indicated locked" is not LOCKED

On 3 March 1974, Turkish Airlines Flight 981 — a DC-10 climbing out of Paris — lost its aft cargo door at 11,500 feet. The latch cams had never gone over-center; a baggage handler had forced the handle and the indicator showed LOCKED anyway. The door blew, the cabin floor collapsed into the cargo hold, and the control cables running through it were severed. All 346 aboard died. Two years earlier the SAME failure over Windsor, Ontario had been survivable — and the fix was made optional. The defect: "locked" was an INDICATION derived from handle position, not a verified state. Here lock verification is a state you can only REACH by actually doing it — the vent-door visual check is the only edge into locked_verified, and pressurization is only reachable FROM locked_verified. A latched-but-unverified door cannot be pressurized: the edge does not exist. Differential pressure is bounded in memory.

A Soma program from the aerospace part of the verified corpus: 116 lines, cells CargoDoor, DoorTests. It passes soma check with soma 3.2.4.

How it is built

The cell CargoDoor declares 6 signals in its face: close_door(id: String) -> Map, latch_door(id: String) -> Map, verify_lockpins(id: String) -> Map, pressurize(id: String, psi_diff: Int) -> Map, reopen(id: String) -> Map and door_state(id: String) -> String; keeps 1 memory slot: psi_diff (Map<String, Int>, persistent and consistent) under the invariant psi_diff >= 0 && psi_diff <= 9. Its state machine door starts in door_open and allows 8 transitions: door_open -> door_closed, door_closed -> door_open, door_closed -> latched, latched -> door_closed, latched -> locked_verified, locked_verified -> pressurized_flight, pressurized_flight -> locked_verified and locked_verified -> latched. Handlers: door_step (line 53), close_door (line 59), latch_door (line 60), verify_lockpins (line 61), pressurize (line 63), reopen (line 73) and door_state (line 79).

The file also holds 1 test cell (DoorTests) with 18 assertions, run by soma test.

Generated from soma describe on this file.

The source

cargo_door.cell

// ============================================================================
// CARGO DOOR — Turkish Airlines 981: "indicated locked" is not LOCKED
// ============================================================================
//
// On 3 March 1974, Turkish Airlines Flight 981 — a DC-10 climbing out of
// Paris — lost its aft cargo door at 11,500 feet. The latch cams had
// never gone over-center; a baggage handler had forced the handle and
// the indicator showed LOCKED anyway. The door blew, the cabin floor
// collapsed into the cargo hold, and the control cables running through
// it were severed. All 346 aboard died. Two years earlier the SAME
// failure over Windsor, Ontario had been survivable — and the fix was
// made optional.
//
// The defect: "locked" was an INDICATION derived from handle position,
// not a verified state. Here lock verification is a state you can only
// REACH by actually doing it — the vent-door visual check is the only
// edge into locked_verified, and pressurization is only reachable FROM
// locked_verified. A latched-but-unverified door cannot be pressurized:
// the edge does not exist. Differential pressure is bounded in memory.
// ============================================================================

cell CargoDoor {
    face {
        signal close_door(id: String) -> Map
        signal latch_door(id: String) -> Map
        signal verify_lockpins(id: String) -> Map
        signal pressurize(id: String, psi_diff: Int) -> Map
        signal reopen(id: String) -> Map
        signal door_state(id: String) -> String
    }

    memory {
        // cabin differential pressure, psi — structural limit 9
        psi_diff: Map<String, Int> [persistent, consistent]
        invariant psi_diff >= 0 && psi_diff <= 9
    }

    // ABSENT: latched -> pressurized_flight  (the THY 981 departure:
    //         handle stowed, indicator green, cams NOT over-center)
    // ABSENT: door_closed -> pressurized_flight
    state door {
        initial: door_open
        door_open -> door_closed
        door_closed -> door_open
        door_closed -> latched              // handle stowed
        latched -> door_closed              // unlatch
        latched -> locked_verified          // vent-door VISUAL check passed
        locked_verified -> pressurized_flight
        pressurized_flight -> locked_verified   // descent: diff back to zero
        locked_verified -> latched              // ground: ready to unlatch
    }

    on door_step(id: String, target: String) {
        let r = try { transition(id, target) }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        return map("ok", true, "door", get_status(id))
    }

    on close_door(id: String)       { return door_step(id, "door_closed") }
    on latch_door(id: String)       { return door_step(id, "latched") }
    on verify_lockpins(id: String)  { return door_step(id, "locked_verified") }

    on pressurize(id: String, psi_diff_v: Int) {
        let w = try { psi_diff.set(id, psi_diff_v) }
        if w.error != () {
            return map("ok", false, "reason", "{psi_diff_v} psi exceeds the structural limit")
        }
        let r = try { transition(id, "pressurized_flight") }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        return map("ok", true, "door", get_status(id), "diff_psi", psi_diff_v)
    }

    on reopen(id: String) {
        // only a depressurized, unlatch-ready door can open — each step
        // back is its own edge; there is no shortcut from flight to open
        return door_step(id, "door_open")
    }

    on door_state(id: String) { return get_status(id) }
}

cell test DoorTests {
    rules {
        // THE THY 981 departure: door latched, indicator green, but the
        // lock pins never verified. Pressurization does not exist here.
        assert close_door("aft1").ok == true
        assert latch_door("aft1").ok == true
        assert_fails transition("aft1", "pressurized_flight")
        assert pressurize("aft1", 8).ok == false
        assert door_state("aft1") == "latched"

        // the verified path: visual check, then climb and pressurize
        assert verify_lockpins("aft1").ok == true
        assert pressurize("aft1", 8).ok == true
        assert door_state("aft1") == "pressurized_flight"

        // no opening a pressurized door — the shortcut edges are absent
        assert_fails transition("aft1", "door_open")
        assert_fails transition("aft1", "door_closed")
        assert reopen("aft1").ok == false

        // descend, depressurize, walk back down to open — each step real
        assert door_step("aft1", "locked_verified").ok == true
        assert door_step("aft1", "latched").ok == true
        assert door_step("aft1", "door_closed").ok == true
        assert reopen("aft1").ok == true

        // an open or merely-closed door can never be pressurized
        assert_fails transition("aft1", "pressurized_flight")

        // the hull never sees a differential beyond its rating
        assert_fails psi_diff.set("aft1", 15)
        assert_fails psi_diff.set("aft1", -2)
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check cargo_door.cell
warning: parameter 2 of `pressurize`: the face calls it `psi_diff`, the handler `psi_diff_v` — an HTTP JSON body is matched by NAME (the handler's), and `soma describe` publishes the face's: use one name
  --> cargo_door.cell:27:9
   |
27 |         signal pressurize(id: String, psi_diff: Int) -> Map
   |         ^
✓ 1 warning(s), no errors.
$ soma test cargo_door.cell
test DoorTests ...
  ✓ assert close_door("aft1").ok == true
  ✓ assert latch_door("aft1").ok == true
  ✓ assert_fails transition("aft1", "pressurized_flight") — raised invalid transition: latched → pressurized_flight. Current state: 'latched'. Valid targets: [door_closed, locked_verified]
  ✓ assert pressurize("aft1", 8).ok == false
  ✓ assert door_state("aft1") == "latched"
  ✓ assert verify_lockpins("aft1").ok == true
  ✓ assert pressurize("aft1", 8).ok == true
  ✓ assert door_state("aft1") == "pressurized_flight"
  ✓ assert_fails transition("aft1", "door_open") — raised invalid transition: pressurized_flight → door_open. Current state: 'pressurized_flight'. Valid targets: [locked_verified]
  ✓ assert_fails transition("aft1", "door_closed") — raised invalid transition: pressurized_flight → door_closed. Current state: 'pressurized_flight'. Valid targets: [locked_verified]
  ✓ assert reopen("aft1").ok == false
  ✓ assert door_step("aft1", "locked_verified").ok == true
  ✓ assert door_step("aft1", "latched").ok == true
  ✓ assert door_step("aft1", "door_closed").ok == true
  ✓ assert reopen("aft1").ok == true
  ✓ assert_fails transition("aft1", "pressurized_flight") — raised invalid transition: door_open → pressurized_flight. Current state: 'door_open'. Valid targets: [door_closed]
  ✓ assert_fails psi_diff.set("aft1", 15) — raised memory invariant violated on 'psi_diff': psi_diff >= 0 && psi_diff <= 9 — rejected write of 15 (key "aft1"); the slot is unchanged
  ✓ assert_fails psi_diff.set("aft1", -2) — raised memory invariant violated on 'psi_diff': psi_diff >= 0 && psi_diff <= 9 — rejected write of -2 (key "aft1"); the slot is unchanged

18 tests: 18 passed, 0 failed
$ soma verify cargo_door.cell
Verifying cargo_door.cell...

State machine 'door': 5 states, initial 'door_open'
  States: [door_closed, door_open, latched, locked_verified, pressurized_flight]

  ✓ 5 states, 8 transitions
  ✓ all states reachable from 'door_open'
  ✓ reactive machine: no terminal state, and every reachable state can return to 'door_open'
  ✓ no deadlocks
  ✓ liveness: every reachable state can return to 'door_open' (reactive machine)
  ⚠ dynamic transition targets: handler `door_step` 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 7 handlers structurally terminate
  ⚠ refinement (partial — dynamic targets fall back to runtime check): handler `door_step` 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 `door_step` ⟶ <dynamic>
  ✓ refinement (partial — dynamic targets fall back to runtime check): handler `pressurize` ⟶ {pressurized_flight}
  · transition sources: `pressurize` calls transition(id, target) without declaring the source — the runtime refuses a move the graph forbids, but the proof does not see where the handler starts; `transition(id, from, to)` names the edge (checked by `soma check`, refused at run time from any other state)

CargoDoor/invariants:

  ⚠ invariant psi_diff >= 0 && psi_diff <= 9 — runtime-checked (computed values): pressurize → psi_diff because `psi_diff_v` is a parameter (narrow it: `require psi_diff_v >= 0 && psi_diff_v <= 9 else …`)

8 passed, 3 warnings, 0 failures

  Temporal properties for 'door':
  ✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK

Builtins used

get_status, map, transition

Source file: /corpus/aerospace/cargo_door.cell · examples/corpus/aerospace/cargo_door.cell