soma.cell

Grants — budget conservation: the fund cannot award money it does not have

COVID-era relief programs paid out past their appropriations because the "remaining budget" lived in a spreadsheet beside the disbursement system — GAO flagged billions in over- and duplicate disbursements. The bug class is always the same: the balance check and the payment are two systems. Here they are one write: an award debits the fund slot, and a negative balance is unrepresentable — the memory refuses the overdraft. Conservation (awards + remaining == appropriation) holds by construction, and a closed fund is terminal: soma verify proves no path re-opens it.

A Soma program from the civic part of the verified corpus: 107 lines, cells GrantFund, GrantFundTests. It passes soma check with soma 3.2.4.

How it is built

The cell GrantFund declares 7 signals in its face: appropriate(amount: Int) -> Map, award_grant(grantee: String, amount: Int) -> Map, close_fund() -> Map, remaining_balance() -> Int, total_awarded() -> Int, conserved() -> Bool and phase() -> String; keeps 2 memory slots: remaining (Map<String, Int>, persistent and consistent) under the invariant remaining >= 0 and awarded (Map<String, Int>, persistent and consistent) under the invariant awarded >= 0. Its state machine fund starts in proposed and allows 2 transitions: proposed -> disbursing and disbursing -> closed. closed is terminal. Handlers: phase (line 42), appropriate (line 44), award_grant (line 52), close_fund (line 68), remaining_balance (line 74), total_awarded (line 76) and conserved (line 83).

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

Generated from soma describe on this file.

The source

grants.cell

// ============================================================================
// GRANTS — budget conservation: the fund cannot award money it does not have
// ============================================================================
// COVID-era relief programs paid out past their appropriations because the
// "remaining budget" lived in a spreadsheet beside the disbursement system —
// GAO flagged billions in over- and duplicate disbursements. The bug class is
// always the same: the balance check and the payment are two systems. Here
// they are one write: an award debits the fund slot, and a negative balance
// is unrepresentable — the memory refuses the overdraft. Conservation
// (awards + remaining == appropriation) holds by construction, and a closed
// fund is terminal: soma verify proves no path re-opens it.
// ============================================================================

cell GrantFund {
    face {
        signal appropriate(amount: Int) -> Map
        signal award_grant(grantee: String, amount: Int) -> Map
        signal close_fund() -> Map
        signal remaining_balance() -> Int
        signal total_awarded() -> Int
        signal conserved() -> Bool
        signal phase() -> String
    }

    memory {
        // The wall: a balance below zero is rejected at the write,
        // no matter what arithmetic a handler believed.
        remaining: Map<String, Int> [persistent, consistent]
        invariant remaining >= 0

        awarded: Map<String, Int> [persistent, consistent]
        invariant awarded >= 0
    }

    // closed is terminal: a spent fund never disburses again.
    state fund {
        initial: proposed
        proposed -> disbursing
        disbursing -> closed
    }

    on phase() { return get_status("fund") }

    on appropriate(amount: Int) {
        let r = try { transition("fund", "disbursing") }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        remaining.set("fund", amount)
        remaining.set("appropriation", amount)
        return map("ok", true, "fund", amount)
    }

    on award_grant(grantee: String, amount: Int) {
        if phase() != "disbursing" {
            return map("ok", false, "reason", "fund is {phase()}")
        }
        if amount <= 0 { return map("ok", false, "reason", "award must be positive") }
        let bal = remaining.get("fund") ?? 0
        // THE WALL: if amount > bal this write is an overdraft and refuses.
        let w = try { remaining.set("fund", bal - amount) }
        if w.error != () {
            return map("ok", false, "reason", "insufficient fund: {bal} < {amount}")
        }
        let prior = awarded.get(grantee) ?? 0
        awarded.set(grantee, prior + amount)
        return map("ok", true, "grantee", grantee, "remaining", bal - amount)
    }

    on close_fund() {
        let r = try { transition("fund", "closed") }
        if r.error != () { return map("ok", false, "reason", "{r.error}") }
        return map("ok", true, "unspent", remaining_balance())
    }

    on remaining_balance() { return remaining.get("fund") ?? 0 }

    on total_awarded() {
        let names = awarded.keys()
        let n = 0
        for g in names { n = n + (awarded.get(g) ?? 0) }
        return n
    }

    on conserved() {
        let appropriation = remaining.get("appropriation") ?? 0
        return total_awarded() + remaining_balance() == appropriation
    }
}

cell test GrantFundTests {
    rules {
        assert award_grant("arts-coop", 100).ok == false   // nothing appropriated
        assert appropriate(1000).ok == true
        assert award_grant("arts-coop", 600).ok == true
        assert award_grant("food-bank", 600).ok == false   // would overdraft
        assert remaining_balance() == 400
        assert award_grant("food-bank", 400).ok == true
        assert award_grant("library", 1).ok == false       // fund is empty
        assert_fails remaining.set("fund", -1)             // overdraft unrepresentable
        assert_fails awarded.set("ghost", -50)             // no negative awards
        assert total_awarded() == 1000
        assert conserved() == true
        assert close_fund().ok == true
        assert award_grant("late", 1).ok == false          // closed fund pays nobody
        assert_fails transition("fund", "disbursing")      // and stays closed
    }
}

What the toolchain says

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

$ soma check grants.cell
✓ All checks passed.
$ soma test grants.cell
test GrantFundTests ...
  ✓ assert award_grant("arts-coop", 100).ok == false
  ✓ assert appropriate(1000).ok == true
  ✓ assert award_grant("arts-coop", 600).ok == true
  ✓ assert award_grant("food-bank", 600).ok == false
  ✓ assert remaining_balance() == 400
  ✓ assert award_grant("food-bank", 400).ok == true
  ✓ assert award_grant("library", 1).ok == false
  ✓ assert_fails remaining.set("fund", -1) — raised memory invariant violated on 'remaining': remaining >= 0 — rejected write of -1 (key "fund"); the slot is unchanged
  ✓ assert_fails awarded.set("ghost", -50) — raised memory invariant violated on 'awarded': awarded >= 0 — rejected write of -50 (key "ghost"); the slot is unchanged
  ✓ assert total_awarded() == 1000
  ✓ assert conserved() == true
  ✓ assert close_fund().ok == true
  ✓ assert award_grant("late", 1).ok == false
  ✓ assert_fails transition("fund", "disbursing") — raised invalid transition: closed → disbursing. Current state: 'closed'. Valid targets: []

14 tests: 14 passed, 0 failed
$ soma verify grants.cell
Verifying grants.cell...

State machine 'fund': 3 states, initial 'proposed'
  States: [closed, disbursing, proposed]

  ✓ 3 states, 2 transitions
  ✓ all states reachable from 'proposed'
  ✓ terminal states: [closed]
  ✓ 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 7 handlers structurally terminate
  ✓ refinement: handler `appropriate` ⟶ {disbursing}
  ✓ refinement: handler `close_fund` ⟶ {closed}
  · transition sources: `appropriate`, `close_fund` 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)

GrantFund/invariants:

  ⚠ invariant remaining >= 0 — runtime-checked (computed values): appropriate → remaining because `amount` is a parameter (narrow it: `require amount >= 0 else …`), award_grant → remaining
  ✓ invariant awarded >= 0 — writer 'award_grant' proven by induction (writes prior + amount)

10 passed, 1 warnings, 0 failures

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

Builtins used

get_status, map, transition

Source file: /corpus/civic/grants.cell · examples/corpus/civic/grants.cell