Ticket desk — one cell written skeleton-first
The skeleton is the whole design: memory, the lifecycle, and for each signal its frame (what its body may read, write, call, which edges it may take). The flesh below holds the bodies; `soma check` refuses a body that does anything its frame does not say. Read the skeleton and you know that only `open` creates a ticket, that `close` cannot reopen one, and that `summary` writes nothing — without reading a body.
A Soma program from the skeleton part of the verified corpus: 122 lines, cells Desk, DeskTests. It passes soma check with soma 3.2.4.
How it is built
The cell Desk declares 7 signals in its face: open(id: String, title: String) -> Map, assign(id: String, owner: String) -> String, resolve(id: String, by: String) -> String, reopen(id: String) -> String, close(id: String) -> String, summary(id: String) -> Map and count() -> Int; keeps 3 memory slots: titles (Map<String, String>, persistent), owners (Map<String, String>, persistent) and opened (Map<String, Int>, persistent) under the invariant opened >= 0. Its state machine ticket starts in new and allows 5 transitions: new -> assigned, assigned -> resolved, resolved -> closed, resolved -> assigned and new -> closed. closed is terminal. Handlers: open (line 53), assign (line 60), resolve (line 67), reopen (line 74), close (line 79), summary (line 85) and count (line 90). Private helpers: _must_exist.
The file also holds 1 test cell (DeskTests) with 15 assertions, run by soma test.
The source
ticket_desk.cell
// TICKET DESK — one cell written skeleton-first.
//
// The skeleton is the whole design: memory, the lifecycle, and for each
// signal its frame (what its body may read, write, call, which edges it
// may take). The flesh below holds the bodies; `soma check` refuses a body
// that does anything its frame does not say. Read the skeleton and you
// know that only `open` creates a ticket, that `close` cannot reopen one,
// and that `summary` writes nothing — without reading a body.
//
// soma check ticket_desk.cell
// soma skeleton ticket_desk.cell Desk.assign the brief for one body
// soma verify ticket_desk.cell
// soma test ticket_desk.cell
skeleton Desk {
memory {
titles: Map<String, String> [persistent]
owners: Map<String, String> [persistent]
opened: Map<String, Int> [persistent] // how many tickets, under "n"
invariant opened >= 0
}
state ticket {
initial: new
new -> assigned
assigned -> resolved
resolved -> closed
resolved -> assigned // the fix did not hold: back to its owner
new -> closed // not a real ticket
}
face {
signal open(id: String, title: String) -> Map
writes titles, opened
calls count
signal assign(id: String, owner: String) -> String
reads titles
writes owners
moves new -> assigned
signal resolve(id: String, by: String) -> String
reads titles, owners
moves assigned -> resolved
signal reopen(id: String) -> String moves resolved -> assigned
signal close(id: String) -> String
reads titles
moves resolved -> closed, new -> closed
signal summary(id: String) -> Map reads titles, owners, ticket
signal count() -> Int reads opened
}
}
flesh Desk {
on open(id, title) {
require titles.get(id) == () else Taken "ticket '{id}' exists"
titles.set(id, title)
opened.set("n", count() + 1)
return map("id", id, "title", title, "state", "new")
}
on assign(id, owner) {
_must_exist(id)
transition(id, "new", "assigned")
owners.set(id, owner)
return owner
}
on resolve(id, by) {
_must_exist(id)
require owners.get(id) == by else Forbidden "only its owner resolves a ticket"
transition(id, "assigned", "resolved")
return "resolved"
}
on reopen(id) {
transition(id, "resolved", "assigned")
return "assigned"
}
on close(id) {
_must_exist(id)
transition(id, "closed")
return "closed"
}
on summary(id) {
_must_exist(id)
return map("id", id, "title", titles.get(id), "owner", owners.get(id) ?? "nobody", "state", get_status(id) ?? "new")
}
on count() {
return opened.get("n") ?? 0
}
// a private helper: `_name`, typed. What it reads counts against every
// signal that calls it: each of them has `titles` in its frame — leave
// it out of one and `soma check` names that signal and the clause.
on _must_exist(id: String) {
require titles.get(id) != () else NotFound "no ticket '{id}'"
}
}
cell test DeskTests {
rules {
assert open("t1", "printer on fire").state == "new"
assert count() == 1
assert_fails open("t1", "again") matching "Taken"
assert assign("t1", "ines") == "ines"
assert_fails resolve("t1", "omar") matching "Forbidden"
assert resolve("t1", "ines") == "resolved"
assert reopen("t1") == "assigned"
assert resolve("t1", "ines") == "resolved"
assert close("t1") == "closed"
assert_fails reopen("t1") // closed is terminal
assert summary("t1").owner == "ines"
assert_fails summary("nope") matching "NotFound"
assert open("t2", "spam").state == "new"
assert close("t2") == "closed" // straight from new
assert count() == 2
}
}What the toolchain says
$ soma check ticket_desk.cell
✓ All checks passed.$ soma test ticket_desk.cell
test DeskTests ...
✓ assert open("t1", "printer on fire").state == "new"
✓ assert count() == 1
✓ assert_fails open("t1", "again") matching "Taken" — raised Taken: ticket 't1' exists
✓ assert assign("t1", "ines") == "ines"
✓ assert_fails resolve("t1", "omar") matching "Forbidden" — raised Forbidden: only its owner resolves a ticket
✓ assert resolve("t1", "ines") == "resolved"
✓ assert reopen("t1") == "assigned"
✓ assert resolve("t1", "ines") == "resolved"
✓ assert close("t1") == "closed"
✓ assert_fails reopen("t1") — raised invalid transition: closed → assigned — transition(id, "resolved", "assigned") declares its source, and 't1' is in 'closed', not 'resolved'
✓ assert summary("t1").owner == "ines"
✓ assert_fails summary("nope") matching "NotFound" — raised NotFound: no ticket 'nope'
✓ assert open("t2", "spam").state == "new"
✓ assert close("t2") == "closed"
✓ assert count() == 2
15 tests: 15 passed, 0 failed$ soma verify ticket_desk.cell
Verifying ticket_desk.cell...
State machine 'ticket': 4 states, initial 'new'
States: [assigned, closed, new, resolved]
✓ 4 states, 5 transitions
✓ all states reachable from 'new'
✓ terminal states: [closed]
✓ no deadlocks
✓ liveness: every state can eventually reach a terminal state
✓ think-isolated: CTL safety properties hold regardless of LLM output (4 handlers, 4 literal transitions, 0 dynamic)
✓ termination: all 8 handlers structurally terminate
✓ refinement: handler `assign` ⟶ {new → assigned}
✓ refinement: handler `resolve` ⟶ {assigned → resolved}
✓ refinement: handler `reopen` ⟶ {resolved → assigned}
✓ refinement: handler `close` ⟶ {closed}
· transition sources: `close` 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)
Desk/invariants:
✓ invariant opened >= 0 — writer 'open' proven by induction (writes count() + 1)
12 passed, 0 warnings, 0 failures
Temporal properties for 'ticket':
✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK