soma.cell

Crane load moment — the tipping write is refused by the ledger

"Big Blue", Miller Park, 1999: a 567-ton lift in wind put the crawler crane past its load moment and it came down across the stadium — 3 ironworkers dead. Load moment is load x radius against the rated chart; the killer is that each input looks fine alone. Here the computed moment percentage is written to a slot whose invariant tops out at 100: a lift plan that tips the crane is REJECTED AT THE WRITE, so the hoist edge is never taken. The machine adds the second wall — a crane cannot hoist from `parked`, and an out-of-chart plan leaves it safely in `rigged`.

A Soma program from the safety_interlocks part of the verified corpus: 90 lines, cells LoadMomentIndicator, CraneTests. It passes soma check with soma 3.2.4.

How it is built

The cell LoadMomentIndicator declares 5 signals in its face: rig(id: String) -> String, plan_lift(id: String, tons: Int, radius_m: Int, rated_tm: Int) -> Map, set_down(id: String) -> String, park(id: String) -> String and moment_now(id: String) -> Int; keeps 1 memory slot: moment_pct (Map<String, Int>, persistent and consistent) under the invariant moment_pct >= 0 && moment_pct <= 100. Its state machine crane starts in parked and allows 4 transitions: parked -> rigged, rigged -> parked, rigged -> hoisting and hoisting -> rigged. Handlers: rig (line 35), plan_lift (line 37), set_down (line 54), park (line 60) and moment_now (line 61).

The file also holds 1 test cell (CraneTests) with 10 assertions, run by soma test.

Generated from soma describe on this file.

The source

crane_load_moment.cell

// CRANE LOAD MOMENT — the tipping write is refused by the ledger.
// "Big Blue", Miller Park, 1999: a 567-ton lift in wind put the crawler
// crane past its load moment and it came down across the stadium —
// 3 ironworkers dead. Load moment is load x radius against the rated
// chart; the killer is that each input looks fine alone. Here the
// computed moment percentage is written to a slot whose invariant tops
// out at 100: a lift plan that tips the crane is REJECTED AT THE WRITE,
// so the hoist edge is never taken. The machine adds the second wall —
// a crane cannot hoist from `parked`, and an out-of-chart plan leaves
// it safely in `rigged`.

cell LoadMomentIndicator {
    face {
        signal rig(id: String) -> String
        signal plan_lift(id: String, tons: Int, radius_m: Int, rated_tm: Int) -> Map
        signal set_down(id: String) -> String
        signal park(id: String) -> String
        signal moment_now(id: String) -> Int
    }

    memory {
        // percent of rated load moment — 100 is the chart edge, not a hint
        moment_pct: Map<String, Int> [persistent, consistent]
        invariant moment_pct >= 0 && moment_pct <= 100
    }

    state crane {
        initial: parked
        parked -> rigged           // counterweights on, outriggers set
        rigged -> parked
        rigged -> hoisting         // only a chart-checked load gets here
        hoisting -> rigged
    }

    on rig(id: String) { transition(id, "rigged")  return get_status(id) }

    on plan_lift(id: String, tons: Int, radius_m: Int, rated_tm: Int) {
        if rated_tm <= 0 { return map("ok", false, "reason", "no load chart") }
        let pct = idiv(tons * radius_m * 100, rated_tm)
        // THE wall: a moment past 100% cannot be written, so the
        // hoist below it is never reached.
        let w = try { moment_pct.set(id, pct) }
        if w.error != () {
            return map("ok", false, "state", get_status(id),
                       "reason", "load moment {pct}% of chart — lift refused")
        }
        let r = try { transition(id, "hoisting") }
        if r.error != () {
            return map("ok", false, "reason", "crane not rigged")
        }
        return map("ok", true, "state", get_status(id), "moment_pct", pct)
    }

    on set_down(id: String) {
        moment_pct.set(id, 0)
        transition(id, "rigged")
        return get_status(id)
    }

    on park(id: String) { transition(id, "parked")  return get_status(id) }
    on moment_now(id: String) { return moment_pct.get(id) ?? 0 }
}

cell test CraneTests {
    rules {
        // no hoisting from parked — the edge does not exist
        assert_fails transition("c1", "hoisting")

        // an in-chart lift proceeds: 400t at 20m on a 10000 t-m chart = 80%
        assert rig("c1") == "rigged"
        assert plan_lift("c1", 400, 20, 10000).ok == true
        assert moment_now("c1") == 80

        // come back down before the next plan
        assert set_down("c1") == "rigged"

        // THE Big Blue lift: 567t at 26m on the same chart = 147%.
        // The ledger refuses the write; the crane never leaves `rigged`.
        assert plan_lift("c1", 567, 26, 10000).ok == false
        assert moment_now("c1") == 0

        // the wall holds even against a direct write
        assert_fails moment_pct.set("c1", 147)
        assert_fails moment_pct.set("c1", -10)

        // a rigged crane that never lifted can stand down
        assert park("c1") == "parked"
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check crane_load_moment.cell
✓ All checks passed.
$ soma test crane_load_moment.cell
test CraneTests ...
  ✓ assert_fails transition("c1", "hoisting") — raised invalid transition: parked → hoisting. Current state: 'parked'. Valid targets: [rigged]
  ✓ assert rig("c1") == "rigged"
  ✓ assert plan_lift("c1", 400, 20, 10000).ok == true
  ✓ assert moment_now("c1") == 80
  ✓ assert set_down("c1") == "rigged"
  ✓ assert plan_lift("c1", 567, 26, 10000).ok == false
  ✓ assert moment_now("c1") == 0
  ✓ assert_fails moment_pct.set("c1", 147) — raised memory invariant violated on 'moment_pct': moment_pct >= 0 && moment_pct <= 100 — rejected write of 147 (key "c1"); the slot is unchanged
  ✓ assert_fails moment_pct.set("c1", -10) — raised memory invariant violated on 'moment_pct': moment_pct >= 0 && moment_pct <= 100 — rejected write of -10 (key "c1"); the slot is unchanged
  ✓ assert park("c1") == "parked"

10 tests: 10 passed, 0 failed
$ soma verify crane_load_moment.cell
Verifying crane_load_moment.cell...

State machine 'crane': 3 states, initial 'parked'
  States: [hoisting, parked, rigged]

  ✓ 3 states, 4 transitions
  ✓ all states reachable from 'parked'
  ✓ reactive machine: no terminal state, and every reachable state can return to 'parked'
  ✓ no deadlocks
  ✓ liveness: every reachable state can return to 'parked' (reactive machine)
  ✓ think-isolated: CTL safety properties hold regardless of LLM output (4 handlers, 4 literal transitions, 0 dynamic)
  ✓ termination: all 5 handlers structurally terminate
  ✓ refinement: handler `rig` ⟶ {rigged}
  ✓ refinement: handler `plan_lift` ⟶ {hoisting}
  ✓ refinement: handler `set_down` ⟶ {rigged}
  ✓ refinement: handler `park` ⟶ {parked}
  · transition sources: `rig`, `plan_lift`, `set_down`, `park` 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)

LoadMomentIndicator/invariants:

  ✓ invariant moment_pct >= 0 && moment_pct <= 100 — writer 'set_down' proven (writes 0)
  ⚠ invariant moment_pct >= 0 && moment_pct <= 100 — runtime-checked (computed values): plan_lift → moment_pct because `pct` = idiv() — a builtin the prover does not bound

12 passed, 1 warnings, 0 failures

  Temporal properties for 'crane':
  ✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK

Builtins used

get_status, idiv, map, transition

Source file: /corpus/safety_interlocks/crane_load_moment.cell · examples/corpus/safety_interlocks/crane_load_moment.cell