soma.cell

Sepsis bundle — antibiotics never go in before the blood cultures are

drawn, and the 1-hour clock is real The Surviving Sepsis "hour-1 bundle" saves lives by ordering: measure lactate, DRAW BLOOD CULTURES, then give broad-spectrum antibiotics, then start fluids — all within an hour of recognition. The ordering is not bureaucratic: give antibiotics before the cultures are drawn and you sterilize the sample, losing the chance to identify the organism and target therapy. The other failure is the clock: every minute of delay to antibiotics raises mortality. Here the bundle is a state machine where `antibiotics` is reachable ONLY after `cultures_drawn` — there is no edge that lets the drug precede the draw. A memory invariant pins elapsed minutes into [0,60]: a bundle charted as completed past the hour is a rejected write, so "we'll call it on-time" cannot be recorded. `completed` is terminal.

A Soma program from the medical part of the verified corpus: 147 lines, cells SepsisBundle, SepsisTests. It passes soma check with soma 3.2.4.

How it is built

The cell SepsisBundle declares 8 signals in its face: recognize(case_id: String) -> Map, lactate(case_id: String) -> Map, cultures(case_id: String) -> Map, antibiotics(case_id: String, minute: Int) -> Map, fluids(case_id: String) -> Map, complete(case_id: String) -> Map, bundle_state(case_id: String) -> String and demo() -> String; keeps 1 memory slot: abx_minute (Map<String, Int>, persistent and consistent) under the invariant abx_minute >= 0 && abx_minute <= 60. Its state machine bundle starts in recognized and allows 5 transitions: recognized -> lactate_measured, lactate_measured -> cultures_drawn, cultures_drawn -> abx_given, abx_given -> fluids_started and fluids_started -> completed. completed is terminal. Handlers: recognize (line 58), lactate (line 62), cultures (line 68), antibiotics (line 76), fluids (line 90), complete (line 96), bundle_state (line 102) and demo (line 104).

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

Generated from soma describe on this file.

The source

sepsis_bundle.cell

// ============================================================================
// SEPSIS BUNDLE — antibiotics never go in before the blood cultures are
// drawn, and the 1-hour clock is real
// ============================================================================
//
// The Surviving Sepsis "hour-1 bundle" saves lives by ordering: measure
// lactate, DRAW BLOOD CULTURES, then give broad-spectrum antibiotics, then
// start fluids — all within an hour of recognition. The ordering is not
// bureaucratic: give antibiotics before the cultures are drawn and you
// sterilize the sample, losing the chance to identify the organism and
// target therapy. The other failure is the clock: every minute of delay to
// antibiotics raises mortality.
//
// Here the bundle is a state machine where `antibiotics` is reachable ONLY
// after `cultures_drawn` — there is no edge that lets the drug precede the
// draw. A memory invariant pins elapsed minutes into [0,60]: a bundle
// charted as completed past the hour is a rejected write, so "we'll call it
// on-time" cannot be recorded. `completed` is terminal.
//
//   soma verify examples/corpus/medical/sepsis_bundle.cell
//   soma test   examples/corpus/medical/sepsis_bundle.cell
//   soma run    examples/corpus/medical/sepsis_bundle.cell demo
// ============================================================================

cell SepsisBundle {
    face {
        signal recognize(case_id: String) -> Map
        signal lactate(case_id: String) -> Map
        signal cultures(case_id: String) -> Map
        signal antibiotics(case_id: String, minute: Int) -> Map
        signal fluids(case_id: String) -> Map
        signal complete(case_id: String) -> Map
        signal bundle_state(case_id: String) -> String
        signal demo() -> String
    }

    memory {
        // Minute (0..60) at which antibiotics were given, relative to
        // recognition. The hour-1 target is the wall: charting a time past
        // 60 is a rejected write — you cannot record a late dose as if it
        // counted.
        abx_minute: Map<String, Int> [persistent, consistent]
        invariant abx_minute >= 0 && abx_minute <= 60
    }

    // The bundle order, made structural. `antibiotics` is unreachable
    // until `cultures_drawn` — the draw always precedes the drug.
    // `completed` is terminal.
    state bundle {
        initial: recognized
        recognized      -> lactate_measured
        lactate_measured -> cultures_drawn
        cultures_drawn  -> abx_given          // ONLY after the draw
        abx_given       -> fluids_started
        fluids_started  -> completed          // terminal
    }

    on recognize(case_id: String) {
        return map("ok", true, "state", get_status(case_id))
    }

    on lactate(case_id: String) {
        let r = try { transition(case_id, "lactate_measured") }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        return map("ok", true, "state", get_status(case_id))
    }

    on cultures(case_id: String) {
        let r = try { transition(case_id, "cultures_drawn") }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        return map("ok", true, "state", get_status(case_id))
    }

    // Antibiotics — refused before cultures are drawn (the machine raises),
    // and the time is pinned inside the hour by the invariant.
    on antibiotics(case_id: String, minute: Int) {
        let st = get_status(case_id)
        if st != "cultures_drawn" {
            return map("ok", false, "reason",
                "antibiotics before cultures would sterilize the sample (state {st})")
        }
        let w = try { abx_minute.set(case_id, minute) }
        if w.error != () {
            return map("ok", false, "reason", "past the hour-1 window: {w.error}")
        }
        transition(case_id, "abx_given")
        return map("ok", true, "minute", minute, "state", get_status(case_id))
    }

    on fluids(case_id: String) {
        let r = try { transition(case_id, "fluids_started") }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        return map("ok", true, "state", get_status(case_id))
    }

    on complete(case_id: String) {
        let r = try { transition(case_id, "completed") }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        return map("ok", true, "state", get_status(case_id))
    }

    on bundle_state(case_id: String) { return get_status(case_id) }

    on demo() {
        recognize("c-1")
        lactate("c-1")
        // the slip: try antibiotics before drawing cultures — REFUSED
        let early = antibiotics("c-1", 20)
        cultures("c-1")
        antibiotics("c-1", 35)
        fluids("c-1")
        complete("c-1")
        let st = bundle_state("c-1")
        print("abx before cultures: {early}")
        print("final state:         {st}")
        return "demo done"
    }
}

cell test SepsisTests {
    rules {
        assert recognize("a").ok == true
        assert lactate("a").ok == true

        // antibiotics cannot precede the culture draw
        assert antibiotics("a", 10).ok == false
        assert_fails transition("a", "abx_given")

        // correct order: draw, then give within the hour
        assert cultures("a").ok == true
        assert antibiotics("a", 40).ok == true
        assert fluids("a").ok == true
        assert complete("a").ok == true
        assert bundle_state("a") == "completed"

        // completed is terminal
        assert_fails transition("a", "abx_given")

        // the clock invariant refuses a dose charted past the hour
        assert recognize("b").ok == true
        assert lactate("b").ok == true
        assert cultures("b").ok == true
        assert antibiotics("b", 90).ok == false    // 90 > 60 — refused
        assert_fails abx_minute.set("b", 61)
    }
}

What the toolchain says

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

$ soma check sepsis_bundle.cell
✓ All checks passed.
$ soma test sepsis_bundle.cell
test SepsisTests ...
  ✓ assert recognize("a").ok == true
  ✓ assert lactate("a").ok == true
  ✓ assert antibiotics("a", 10).ok == false
  ✓ assert_fails transition("a", "abx_given") — raised invalid transition: lactate_measured → abx_given. Current state: 'lactate_measured'. Valid targets: [cultures_drawn]
  ✓ assert cultures("a").ok == true
  ✓ assert antibiotics("a", 40).ok == true
  ✓ assert fluids("a").ok == true
  ✓ assert complete("a").ok == true
  ✓ assert bundle_state("a") == "completed"
  ✓ assert_fails transition("a", "abx_given") — raised invalid transition: completed → abx_given. Current state: 'completed'. Valid targets: []
  ✓ assert recognize("b").ok == true
  ✓ assert lactate("b").ok == true
  ✓ assert cultures("b").ok == true
  ✓ assert antibiotics("b", 90).ok == false
  ✓ assert_fails abx_minute.set("b", 61) — raised memory invariant violated on 'abx_minute': abx_minute >= 0 && abx_minute <= 60 — rejected write of 61 (key "b"); the slot is unchanged

15 tests: 15 passed, 0 failed
$ soma verify sepsis_bundle.cell
Verifying sepsis_bundle.cell...

State machine 'bundle': 6 states, initial 'recognized'
  States: [abx_given, completed, cultures_drawn, fluids_started, lactate_measured, recognized]

  ✓ 6 states, 5 transitions
  ✓ all states reachable from 'recognized'
  ✓ terminal states: [completed]
  ✓ no deadlocks
  ✓ liveness: every state can eventually reach a terminal state
  ✓ think-isolated: CTL safety properties hold regardless of LLM output (5 handlers, 5 literal transitions, 0 dynamic)
  ✓ termination: all 8 handlers structurally terminate
  ✓ refinement: handler `lactate` ⟶ {lactate_measured}
  ✓ refinement: handler `cultures` ⟶ {cultures_drawn}
  ✓ refinement: handler `antibiotics` ⟶ {cultures_drawn → abx_given}
  ✓ refinement: handler `fluids` ⟶ {fluids_started}
  ✓ refinement: handler `complete` ⟶ {completed}
  · transition sources: `lactate`, `cultures`, `fluids`, `complete` 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)

SepsisBundle/invariants:

  ⚠ invariant abx_minute >= 0 && abx_minute <= 60 — runtime-checked (computed values): antibiotics → abx_minute because `minute` is a parameter (narrow it: `require minute >= 0 && minute <= 60 else …`)

12 passed, 1 warnings, 0 failures

  Temporal properties for 'bundle':
  ✓ deadlock_free — no deadlocks in any reachable state
Temporal: 1 passed, 0 failed
VERIFY OK
$ soma run sepsis_bundle.cell demo
abx before cultures: {"ok": false, "reason": "antibiotics before cultures would sterilize the sample (state lactate_measured)"}
final state:         completed
demo done

Builtins used

get_status, map, print, transition

Source file: /corpus/medical/sepsis_bundle.cell · examples/corpus/medical/sepsis_bundle.cell