A media-player transport state machine
stopped -> playing <-> paused, with stop reachable from play/pause. A typed (sum-type) machine so an illegal transport command is caught statically by the variant name. This is a reactive cyclic system: the proof obligation is deadlock-freedom.
A Soma program from the state_machines part of the verified corpus: 57 lines, cells Transport, MediaPlayer, MediaPlayerTests. It passes soma check with soma 3.2.4.
How it is built
The cell MediaPlayer declares 6 signals in its face: play_track(id: String) -> String, pause_track(id: String) -> String, resume_track(id: String) -> String, stop_track(id: String) -> String, transport_of(id: String) -> String and next(id: String) -> List<String>. Its state machine transport starts in Stopped and allows 5 transitions: Stopped -> Playing, Playing -> Paused, Paused -> Playing, Playing -> Stopped and Paused -> Stopped. Handlers: play_track (line 30), pause_track (line 31), resume_track (line 32), stop_track (line 33), transport_of (line 34) and next (line 35).
The file also holds 1 test cell (MediaPlayerTests) with 9 assertions, run by soma test.
The source
media_player.cell
// A media-player transport state machine.
// stopped -> playing <-> paused, with stop reachable from play/pause.
// A typed (sum-type) machine so an illegal transport command is caught
// statically by the variant name. This is a reactive cyclic system: the
// proof obligation is deadlock-freedom.
cell type Transport {
variants { Stopped Playing Paused }
}
cell MediaPlayer {
face {
signal play_track(id: String) -> String
signal pause_track(id: String) -> String
signal resume_track(id: String) -> String
signal stop_track(id: String) -> String
signal transport_of(id: String) -> String
signal next(id: String) -> List<String>
}
state transport: Transport {
initial: Stopped
Stopped -> Playing
Playing -> Paused
Paused -> Playing
Playing -> Stopped
Paused -> Stopped
}
on play_track(id: String) { transition(id, Playing) return get_status(id) }
on pause_track(id: String) { transition(id, Paused) return get_status(id) }
on resume_track(id: String) { transition(id, Playing) return get_status(id) }
on stop_track(id: String) { transition(id, Stopped) return get_status(id) }
on transport_of(id: String) { return get_status(id) }
on next(id: String) { return valid_transitions(id) }
}
cell test MediaPlayerTests {
rules {
// play, pause, resume, stop
assert play_track("m1") == "Playing"
assert pause_track("m1") == "Paused"
assert resume_track("m1") == "Playing"
assert stop_track("m1") == "Stopped"
// pause then stop directly
assert play_track("m2") == "Playing"
assert pause_track("m2") == "Paused"
assert stop_track("m2") == "Stopped"
// illegal: cannot pause something that is stopped
assert_fails pause_track("m3")
// illegal: a stopped transport cannot jump straight to Paused
assert_fails transition("m4", Paused)
}
}What the toolchain says
$ soma check media_player.cell
✓ All checks passed.$ soma test media_player.cell
test MediaPlayerTests ...
✓ assert play_track("m1") == "Playing"
✓ assert pause_track("m1") == "Paused"
✓ assert resume_track("m1") == "Playing"
✓ assert stop_track("m1") == "Stopped"
✓ assert play_track("m2") == "Playing"
✓ assert pause_track("m2") == "Paused"
✓ assert stop_track("m2") == "Stopped"
✓ assert_fails pause_track("m3") — raised invalid transition: Stopped → Paused. Current state: 'Stopped'. Valid targets: [Playing]
✓ assert_fails transition("m4", Paused) — raised invalid transition: Stopped → Paused. Current state: 'Stopped'. Valid targets: [Playing]
9 tests: 9 passed, 0 failed$ soma verify media_player.cell
Verifying media_player.cell...
State machine 'transport': 3 states, initial 'Stopped'
States: [Paused, Playing, Stopped]
✓ 3 states, 5 transitions
✓ all states reachable from 'Stopped'
✓ reactive machine: no terminal state, and every reachable state can return to 'Stopped'
✓ no deadlocks
✓ liveness: every reachable state can return to 'Stopped' (reactive machine)
✓ think-isolated: CTL safety properties hold regardless of LLM output (4 handlers, 4 literal transitions, 0 dynamic)
✓ termination: all 6 handlers structurally terminate
✓ refinement: handler `play_track` ⟶ {Playing}
✓ refinement: handler `pause_track` ⟶ {Paused}
✓ refinement: handler `resume_track` ⟶ {Playing}
✓ refinement: handler `stop_track` ⟶ {Stopped}
· transition sources: `play_track`, `pause_track`, `resume_track`, `stop_track` 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)
11 passed, 0 warnings, 0 failures
Temporal properties for 'transport':
✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK