Container weight — the misdeclared box that breaks the ship
When the MSC Napoli was beached off Devon in 2007, investigators weighed the containers coming off her deck: 137 of 660 were more than 3 tonnes heavier than their declared weight — one was 20 tonnes over. Misdeclared container weights overload stacks, snap lashings, and capsize feeder ships. The IMO's answer was SOLAS VGM (2016): no verified gross mass, no loading. Period. Here the rule is structural. A container's gross mass lives behind a memory invariant capped at the ISO max for a 40-foot box (30,480 kg): the write that would overload it is REFUSED by the memory itself, and a container only reaches the `laden_aboard` state through `vgm_certified` — there is no path from packing straight onto the ship.
A Soma program from the logistics part of the verified corpus: 97 lines, cells ContainerYard, SolasVgm. It passes soma check with soma 3.2.4.
How it is built
The cell ContainerYard declares 4 signals in its face: stuff_cargo(box_id: String, kg: Int) -> Map, certify_vgm(box_id: String) -> Map, load_aboard(box_id: String) -> Map and gross_kg(box_id: String) -> Int; keeps 1 memory slot: gross (Map<String, Int>, persistent and consistent) under the invariant gross >= 0 && gross <= 30480. Its state machine container starts in packing and allows 3 transitions: packing -> vgm_certified, vgm_certified -> packing and vgm_certified -> laden_aboard. laden_aboard is terminal. Handlers: stuff_cargo (line 41), certify_vgm (line 54), load_aboard (line 63) and gross_kg (line 69).
The file also holds 1 test cell (SolasVgm) with 12 assertions, run by soma test.
The source
container_weight.cell
// ============================================================================
// CONTAINER WEIGHT — the misdeclared box that breaks the ship
// ============================================================================
//
// When the MSC Napoli was beached off Devon in 2007, investigators weighed
// the containers coming off her deck: 137 of 660 were more than 3 tonnes
// heavier than their declared weight — one was 20 tonnes over. Misdeclared
// container weights overload stacks, snap lashings, and capsize feeder
// ships. The IMO's answer was SOLAS VGM (2016): no verified gross mass,
// no loading. Period.
//
// Here the rule is structural. A container's gross mass lives behind a
// memory invariant capped at the ISO max for a 40-foot box (30,480 kg):
// the write that would overload it is REFUSED by the memory itself, and
// a container only reaches the `laden_aboard` state through `vgm_certified`
// — there is no path from packing straight onto the ship.
// ============================================================================
cell ContainerYard {
face {
signal stuff_cargo(box_id: String, kg: Int) -> Map
signal certify_vgm(box_id: String) -> Map
signal load_aboard(box_id: String) -> Map
signal gross_kg(box_id: String) -> Int
}
memory {
// tare (3,800 kg) + cargo. ISO 40ft max gross: 30,480 kg.
gross: Map<String, Int> [persistent, consistent]
invariant gross >= 0 && gross <= 30480
}
// No edge from `packing` to `laden_aboard`: VGM first, always.
state container {
initial: packing
packing -> vgm_certified
vgm_certified -> packing // re-opened: certificate void
vgm_certified -> laden_aboard
}
on stuff_cargo(box_id: String, kg: Int) {
if get_status(box_id) != "packing" {
return map("ok", false, "reason", "container is sealed for VGM")
}
if kg <= 0 { return map("ok", false, "reason", "cargo weight must be positive") }
let current = gross.get(box_id) ?? 3800 // empty box = tare weight
let w = try { gross.set(box_id, current + kg) }
if w.error != () {
return map("ok", false, "reason", "REFUSED: {current} + {kg} kg exceeds 30480 kg max gross")
}
return map("ok", true, "gross_kg", current + kg)
}
on certify_vgm(box_id: String) {
if gross.get(box_id) == () {
return map("ok", false, "reason", "nothing stuffed — no mass to verify")
}
let r = try { transition(box_id, "vgm_certified") }
if r.error != () { return map("ok", false, "reason", "{r.error}") }
return map("ok", true, "vgm_kg", gross.get(box_id))
}
on load_aboard(box_id: String) {
let r = try { transition(box_id, "laden_aboard") }
if r.error != () { return map("ok", false, "reason", "no VGM on file: {r.error}") }
return map("ok", true, "state", get_status(box_id))
}
on gross_kg(box_id: String) { return gross.get(box_id) ?? 0 }
}
cell test SolasVgm {
rules {
// legal stuffing accumulates from tare weight
assert stuff_cargo("MSCU100", 20000).ok == true
assert gross_kg("MSCU100") == 23800
// the Napoli box: 20 tonnes over — memory refuses the write
assert stuff_cargo("MSCU100", 20000).ok == false
assert gross_kg("MSCU100") == 23800
assert_fails gross.set("MSCU100", 43800)
assert_fails gross.set("MSCU100", -1)
// NO VGM, NO LOAD: packing -> laden_aboard does not exist
assert_fails transition("MSCU100", "laden_aboard")
assert certify_vgm("MSCU100").ok == true
assert load_aboard("MSCU100").ok == true
// aboard, the box is sealed: no more cargo, no re-certification
assert stuff_cargo("MSCU100", 100).ok == false
assert_fails transition("MSCU100", "packing")
// an empty box cannot be VGM-certified
assert certify_vgm("GHOST01").ok == false
}
}What the toolchain says
$ soma check container_weight.cell
✓ All checks passed.$ soma test container_weight.cell
test SolasVgm ...
✓ assert stuff_cargo("MSCU100", 20000).ok == true
✓ assert gross_kg("MSCU100") == 23800
✓ assert stuff_cargo("MSCU100", 20000).ok == false
✓ assert gross_kg("MSCU100") == 23800
✓ assert_fails gross.set("MSCU100", 43800) — raised memory invariant violated on 'gross': gross >= 0 && gross <= 30480 — rejected write of 43800 (key "MSCU100"); the slot is unchanged
✓ assert_fails gross.set("MSCU100", -1) — raised memory invariant violated on 'gross': gross >= 0 && gross <= 30480 — rejected write of -1 (key "MSCU100"); the slot is unchanged
✓ assert_fails transition("MSCU100", "laden_aboard") — raised invalid transition: packing → laden_aboard. Current state: 'packing'. Valid targets: [vgm_certified]
✓ assert certify_vgm("MSCU100").ok == true
✓ assert load_aboard("MSCU100").ok == true
✓ assert stuff_cargo("MSCU100", 100).ok == false
✓ assert_fails transition("MSCU100", "packing") — raised invalid transition: laden_aboard → packing. Current state: 'laden_aboard'. Valid targets: []
✓ assert certify_vgm("GHOST01").ok == false
12 tests: 12 passed, 0 failed$ soma verify container_weight.cell
Verifying container_weight.cell...
State machine 'container': 3 states, initial 'packing'
States: [laden_aboard, packing, vgm_certified]
✓ 3 states, 3 transitions
✓ all states reachable from 'packing'
✓ terminal states: [laden_aboard]
✓ no deadlocks
✓ liveness: every state can eventually reach a terminal state
✓ think-isolated: CTL safety properties hold regardless of LLM output (2 handlers, 2 literal transitions, 0 dynamic)
✓ termination: all 4 handlers structurally terminate
⚠ refinement: declared transition `vgm_certified → packing` is never reached by any handler — spec may be aspirational or stale
✓ refinement: handler `certify_vgm` ⟶ {vgm_certified}
✓ refinement: handler `load_aboard` ⟶ {laden_aboard}
· transition sources: `certify_vgm`, `load_aboard` 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)
ContainerYard/invariants:
✓ invariant gross >= 0 — writer 'stuff_cargo' proven by induction (writes current + kg)
⚠ invariant gross >= 0 && gross <= 30480 — runtime-checked (computed values): stuff_cargo → gross [gross <= 30480] because `current + kg` is only known to lie in [1, ∞) — narrow it: `require (current + kg) <= 30480 else …`
10 passed, 2 warnings, 0 failures
Temporal properties for 'container':
✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK