Order records with nested line-items, computed totals, and a state machine over the order lifecycle
Demonstrates records carrying lists of records, with() copy-update, and records that drive transitions.
A Soma program from the records part of the verified corpus: 58 lines, cells OrderStatus, Orders, OrdersTest. It passes soma check with soma 3.2.4.
How it is built
The cell Orders declares 4 signals in its face: new_order(customer: String) -> Map, subtotal(o: Map) -> Int, with_discount(o: Map, pct: Int) -> Map and pay(id: String) -> String. Its state machine order starts in Pending and allows 4 transitions: Pending -> Paid, Paid -> Shipped, Shipped -> Delivered and * -> Cancelled. Cancelled and Delivered are terminal. Handlers: new_order (line 25), subtotal (line 32), with_discount (line 37) and pay (line 43).
The file also holds 1 test cell (OrdersTest) with 5 assertions, run by soma test.
The source
orders.cell
// Order records with nested line-items, computed totals, and a state
// machine over the order lifecycle. Demonstrates records carrying lists
// of records, with() copy-update, and records that drive transitions.
cell type OrderStatus {
variants { Pending Paid Shipped Delivered Cancelled }
}
cell Orders {
face {
signal new_order(customer: String) -> Map
signal subtotal(o: Map) -> Int
signal with_discount(o: Map, pct: Int) -> Map
signal pay(id: String) -> String
}
state order: OrderStatus {
initial: Pending
Pending -> Paid
Paid -> Shipped
Shipped -> Delivered
* -> Cancelled
}
on new_order(customer: String) {
return Order { customer: customer, lines: list(
Line { name: "Keyboard", qty: 1, price: 80 },
Line { name: "Mouse", qty: 2, price: 25 }
)}
}
on subtotal(o: Map) {
return sum(o.lines |> map(l => l.qty * l.price))
}
// Functional copy-update: return a new record with a `total` field added.
on with_discount(o: Map, pct: Int) {
let base = subtotal(o)
let total = base - floor(base * pct / 100)
return o |> with("total", total)
}
on pay(id: String) {
transition(id, Paid)
return get_status(id)
}
}
cell test OrdersTest {
rules {
assert subtotal(new_order("Ada")) == 130
assert new_order("Ada").customer == "Ada"
assert with_discount(new_order("Ada"), 10).total == 117
assert pay("ord-1") == "Paid"
assert new_order("Ada").lines[1].name == "Mouse"
}
}What the toolchain says
$ soma check orders.cell
✓ All checks passed.$ soma test orders.cell
test OrdersTest ...
✓ assert subtotal(new_order("Ada")) == 130
✓ assert new_order("Ada").customer == "Ada"
✓ assert with_discount(new_order("Ada"), 10).total == 117
✓ assert pay("ord-1") == "Paid"
✓ assert new_order("Ada").lines[1].name == "Mouse"
5 tests: 5 passed, 0 failed$ soma verify orders.cell
Verifying orders.cell...
State machine 'order': 5 states, initial 'Pending'
States: [Cancelled, Delivered, Paid, Pending, Shipped]
✓ 5 states, 7 transitions
✓ all states reachable from 'Pending'
✓ terminal states: [Cancelled]
✓ no deadlocks
✓ liveness: every state can eventually reach a terminal state
✓ wildcard transitions: * -> [Cancelled]
⚠ `* -> Cancelled` also adds Delivered -> Cancelled — so Delivered is not final. If it should stay final, write `* -> Cancelled except [Delivered]`
✓ think-isolated: CTL safety properties hold regardless of LLM output (1 handlers, 1 literal transitions, 0 dynamic)
✓ termination: all 4 handlers structurally terminate
⚠ refinement: declared transition `Paid → Shipped` is never reached by any handler — spec may be aspirational or stale
⚠ refinement: declared transition `Shipped → Delivered` is never reached by any handler — spec may be aspirational or stale
⚠ refinement: declared transition `* → Cancelled` is never reached by any handler — spec may be aspirational or stale
✓ refinement: handler `pay` ⟶ {Paid}
· transition sources: `pay` 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)
9 passed, 4 warnings, 0 failures
Temporal properties for 'order':
✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OKBuiltins used
floor, get_status, list, map, sum, transition, with