Autoclave door — a quick-opening door never unlocks under pressure
Quick-opening pressure vessel doors (autoclaves, sterilizers, curing vessels) have killed operators for a century the same way: residual pressure behind a door someone believed was vented, and the door becomes a projectile. ASME PCC interlocks demand the door cannot unlock until pressure is verifiably zero. Here {pressurized, door open} is not a state: steam is only admitted behind a locked door, and the lock releases only from `sealed_cold` — the exhaust edge zeroes the chamber BEFORE the unlock edge exists. The chamber ledger refuses any pressure beyond the 300 kPa nameplate.
A Soma program from the safety_interlocks part of the verified corpus: 96 lines, cells AutoclaveControl, AutoclaveTests. It passes soma check with soma 3.2.4.
How it is built
The cell AutoclaveControl declares 5 signals in its face: lock_door(id: String) -> String, admit_steam(id: String, kpa: Int) -> Map, exhaust(id: String) -> String, unlock_door(id: String) -> Map and chamber_kpa(id: String) -> Int; keeps 1 memory slot: chamber (Map<String, Int>, persistent and consistent) under the invariant chamber >= 0 && chamber <= 300. Its state machine door starts in open_cold and allows 4 transitions: open_cold -> sealed_cold, sealed_cold -> open_cold, sealed_cold -> pressurized and pressurized -> sealed_cold. Handlers: lock_door (line 35), admit_steam (line 37), exhaust (line 50), unlock_door (line 56) and chamber_kpa (line 65).
The file also holds 1 test cell (AutoclaveTests) with 15 assertions, run by soma test.
The source
autoclave_door.cell
// AUTOCLAVE DOOR — a quick-opening door never unlocks under pressure.
// Quick-opening pressure vessel doors (autoclaves, sterilizers, curing
// vessels) have killed operators for a century the same way: residual
// pressure behind a door someone believed was vented, and the door
// becomes a projectile. ASME PCC interlocks demand the door cannot
// unlock until pressure is verifiably zero. Here {pressurized, door
// open} is not a state: steam is only admitted behind a locked door,
// and the lock releases only from `sealed_cold` — the exhaust edge
// zeroes the chamber BEFORE the unlock edge exists. The chamber ledger
// refuses any pressure beyond the 300 kPa nameplate.
cell AutoclaveControl {
face {
signal lock_door(id: String) -> String
signal admit_steam(id: String, kpa: Int) -> Map
signal exhaust(id: String) -> String
signal unlock_door(id: String) -> Map
signal chamber_kpa(id: String) -> Int
}
memory {
// chamber pressure, kPa gauge; nameplate is 300
chamber: Map<String, Int> [persistent, consistent]
invariant chamber >= 0 && chamber <= 300
}
state door {
initial: open_cold
open_cold -> sealed_cold // door shut, lugs engaged
sealed_cold -> open_cold // unlock: only ever from cold
sealed_cold -> pressurized // steam ONLY behind a locked door
pressurized -> sealed_cold // exhaust to zero, then the lock frees
}
on lock_door(id: String) { transition(id, "sealed_cold") return get_status(id) }
on admit_steam(id: String, kpa: Int) {
let r = try { transition(id, "pressurized") }
if r.error != () {
return map("ok", false, "reason", "door not proven locked")
}
let w = try { chamber.set(id, kpa) }
if w.error != () {
transition(id, "sealed_cold")
return map("ok", false, "reason", "{kpa} kPa exceeds the 300 kPa nameplate")
}
return map("ok", true, "state", get_status(id), "kpa", kpa)
}
on exhaust(id: String) {
chamber.set(id, 0) // verified zero BEFORE the state moves
transition(id, "sealed_cold")
return get_status(id)
}
on unlock_door(id: String) {
let r = try { transition(id, "open_cold") }
if r.error != () {
let p = chamber_kpa(id)
return map("ok", false, "reason", "chamber at {p} kPa — door stays locked")
}
return map("ok", true, "state", get_status(id))
}
on chamber_kpa(id: String) { return chamber.get(id) ?? 0 }
}
cell test AutoclaveTests {
rules {
// steam into an open chamber: the edge does not exist
assert_fails transition("a1", "pressurized")
assert admit_steam("a1", 200).ok == false
// lawful cycle: lock, pressurize
assert lock_door("a1") == "sealed_cold"
assert admit_steam("a1", 210).ok == true
assert chamber_kpa("a1") == 210
// THE killer: unlocking under pressure. Refused — no such edge.
assert unlock_door("a1").ok == false
assert_fails transition("a1", "open_cold")
// exhaust zeroes the chamber, and only then the lock frees
assert exhaust("a1") == "sealed_cold"
assert chamber_kpa("a1") == 0
assert unlock_door("a1").ok == true
// the nameplate is a wall, not a warning
assert_fails chamber.set("a1", 301)
assert_fails chamber.set("a1", -5)
assert lock_door("a1") == "sealed_cold"
assert admit_steam("a1", 999).ok == false
assert chamber_kpa("a1") == 0
}
}What the toolchain says
$ soma check autoclave_door.cell
✓ All checks passed.$ soma test autoclave_door.cell
test AutoclaveTests ...
✓ assert_fails transition("a1", "pressurized") — raised invalid transition: open_cold → pressurized. Current state: 'open_cold'. Valid targets: [sealed_cold]
✓ assert admit_steam("a1", 200).ok == false
✓ assert lock_door("a1") == "sealed_cold"
✓ assert admit_steam("a1", 210).ok == true
✓ assert chamber_kpa("a1") == 210
✓ assert unlock_door("a1").ok == false
✓ assert_fails transition("a1", "open_cold") — raised invalid transition: pressurized → open_cold. Current state: 'pressurized'. Valid targets: [sealed_cold]
✓ assert exhaust("a1") == "sealed_cold"
✓ assert chamber_kpa("a1") == 0
✓ assert unlock_door("a1").ok == true
✓ assert_fails chamber.set("a1", 301) — raised memory invariant violated on 'chamber': chamber >= 0 && chamber <= 300 — rejected write of 301 (key "a1"); the slot is unchanged
✓ assert_fails chamber.set("a1", -5) — raised memory invariant violated on 'chamber': chamber >= 0 && chamber <= 300 — rejected write of -5 (key "a1"); the slot is unchanged
✓ assert lock_door("a1") == "sealed_cold"
✓ assert admit_steam("a1", 999).ok == false
✓ assert chamber_kpa("a1") == 0
15 tests: 15 passed, 0 failed$ soma verify autoclave_door.cell
Verifying autoclave_door.cell...
State machine 'door': 3 states, initial 'open_cold'
States: [open_cold, pressurized, sealed_cold]
✓ 3 states, 4 transitions
✓ all states reachable from 'open_cold'
✓ reactive machine: no terminal state, and every reachable state can return to 'open_cold'
✓ no deadlocks
✓ liveness: every reachable state can return to 'open_cold' (reactive machine)
✓ think-isolated: CTL safety properties hold regardless of LLM output (4 handlers, 5 literal transitions, 0 dynamic)
✓ termination: all 5 handlers structurally terminate
✓ refinement: handler `lock_door` ⟶ {sealed_cold}
✓ refinement: handler `admit_steam` ⟶ {pressurized, sealed_cold [if w.error != ()]}
✓ refinement: handler `exhaust` ⟶ {sealed_cold}
✓ refinement: handler `unlock_door` ⟶ {open_cold}
· transition sources: `lock_door`, `admit_steam`, `exhaust`, `unlock_door` call 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)
AutoclaveControl/invariants:
✓ invariant chamber >= 0 && chamber <= 300 — writer 'exhaust' proven (writes 0)
⚠ invariant chamber >= 0 && chamber <= 300 — runtime-checked (computed values): admit_steam → chamber because `kpa` is a parameter (narrow it: `require kpa >= 0 && kpa <= 300 else …`)
12 passed, 1 warnings, 0 failures
Temporal properties for 'door':
✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK