soma.cell

Payroll run — the payslips must sum EXACTLY to the approved total

Payroll overpayments are a quiet epidemic: a duplicated payslip or a fat-fingered salary slips into a run, the bank file goes out, and the company spends months clawing money back from employees (legally messy, morale-destroying). The wall here: the approved budget is a slot that each payslip DECREMENTS, with `budget >= 0` as an invariant — a payslip that would overspend the approval RAISES at the write. And the run can only commit when the budget hits exactly zero: paid == approved, proven by arithmetic, not by hope. Committed runs are terminal.

A Soma program from the escrow_finance part of the verified corpus: 100 lines, cells Payroll, PayrollTests. It passes soma check with soma 3.2.4.

How it is built

The cell Payroll declares 4 signals in its face: approve_run(run: String, total: Int) -> Map, add_payslip(run: String, employee: String, amount: Int) -> Map, commit_run(run: String) -> Map and unspent(run: String) -> Int; keeps 2 memory slots: budget (Map<String, Int>, persistent and consistent) under the invariant budget >= 0 and slips (Map<String, Int>, persistent and consistent) under the invariant slips >= 0. Its state machine run starts in open_run and allows 3 transitions: open_run -> approved, approved -> committed and approved -> voided. committed and voided are terminal. Handlers: approve_run (line 41), add_payslip (line 48), commit_run (line 63) and unspent (line 72).

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

Generated from soma describe on this file.

The source

payroll_run.cell

// ============================================================================
// PAYROLL RUN — the payslips must sum EXACTLY to the approved total
// ============================================================================
//
// Payroll overpayments are a quiet epidemic: a duplicated payslip or a
// fat-fingered salary slips into a run, the bank file goes out, and the
// company spends months clawing money back from employees (legally messy,
// morale-destroying). The wall here: the approved budget is a slot that
// each payslip DECREMENTS, with `budget >= 0` as an invariant — a payslip
// that would overspend the approval RAISES at the write. And the run can
// only commit when the budget hits exactly zero: paid == approved, proven
// by arithmetic, not by hope. Committed runs are terminal.
// ============================================================================

cell Payroll {
    face {
        signal approve_run(run: String, total: Int) -> Map
        signal add_payslip(run: String, employee: String, amount: Int) -> Map
        signal commit_run(run: String) -> Map
        signal unspent(run: String) -> Int
    }

    memory {
        // what's left of the approved total — every payslip draws it down,
        // and the invariant makes overspending a rejected write
        budget: Map<String, Int> [persistent, consistent]
        invariant budget >= 0
        slips: Map<String, Int> [persistent, consistent]
        invariant slips >= 0
    }

    // committed is terminal: a run that hit the bank cannot be re-opened
    // and quietly padded with one more payslip.
    state run {
        initial: open_run
        open_run -> approved
        approved -> committed
        approved -> voided
    }

    on approve_run(run: String, total: Int) {
        if total <= 0 { return map("ok", false, "reason", "bad total") }
        transition(run, "approved")
        budget.set(run, total)
        return map("ok", true, "approved", total)
    }

    on add_payslip(run: String, employee: String, amount: Int) {
        if get_status(run) != "approved" {
            return map("ok", false, "reason", "run is not open for payslips")
        }
        if amount <= 0 { return map("ok", false, "reason", "bad amount") }
        let k = "{run}:{employee}"
        if (slips.get(k) ?? 0) > 0 {
            return map("ok", false, "reason", "{employee} already has a payslip")
        }
        let left = budget.get(run) ?? 0
        budget.set(run, left - amount)   // RAISES if the payslip overspends
        slips.set(k, amount)
        return map("ok", true, "employee", employee, "left", left - amount)
    }

    on commit_run(run: String) {
        let left = budget.get(run) ?? -1
        if left != 0 {
            return map("ok", false, "reason", "paid != approved: {left} unallocated")
        }
        transition(run, "committed")
        return map("ok", true, "state", get_status(run))
    }

    on unspent(run: String) {
        return budget.get(run) ?? 0
    }
}

cell test PayrollTests {
    rules {
        assert approve_run("jan", 9000).ok == true
        assert add_payslip("jan", "ada", 4000).ok == true
        assert add_payslip("jan", "bob", 3000).ok == true
        // THE DUPLICATE PAYSLIP: ada cannot be paid twice in one run
        assert add_payslip("jan", "ada", 4000).ok == false
        // THE OVERPAYMENT: 2001 > the 2000 left — the write itself raises
        assert_fails add_payslip("jan", "cy", 2001)
        assert unspent("jan") == 2000
        // cannot commit while money is unallocated (paid != approved)
        assert commit_run("jan").ok == false
        assert add_payslip("jan", "cy", 2000).ok == true
        assert unspent("jan") == 0
        assert commit_run("jan").ok == true
        // committed is terminal: no sneaking in one more payslip
        assert add_payslip("jan", "eve", 1).ok == false
        assert_fails transition("jan", "approved")
        assert_fails transition("jan", "voided")
        // the budget slot itself rejects a negative balance
        assert_fails budget.set("jan", -5)
    }
}

What the toolchain says

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

$ soma check payroll_run.cell
✓ All checks passed.
$ soma test payroll_run.cell
test PayrollTests ...
  ✓ assert approve_run("jan", 9000).ok == true
  ✓ assert add_payslip("jan", "ada", 4000).ok == true
  ✓ assert add_payslip("jan", "bob", 3000).ok == true
  ✓ assert add_payslip("jan", "ada", 4000).ok == false
  ✓ assert_fails add_payslip("jan", "cy", 2001) — raised memory invariant violated on 'budget': budget >= 0 — rejected write of -1 (key "jan"); the slot is unchanged
  ✓ assert unspent("jan") == 2000
  ✓ assert commit_run("jan").ok == false
  ✓ assert add_payslip("jan", "cy", 2000).ok == true
  ✓ assert unspent("jan") == 0
  ✓ assert commit_run("jan").ok == true
  ✓ assert add_payslip("jan", "eve", 1).ok == false
  ✓ assert_fails transition("jan", "approved") — raised invalid transition: committed → approved. Current state: 'committed'. Valid targets: []
  ✓ assert_fails transition("jan", "voided") — raised invalid transition: committed → voided. Current state: 'committed'. Valid targets: []
  ✓ assert_fails budget.set("jan", -5) — raised memory invariant violated on 'budget': budget >= 0 — rejected write of -5 (key "jan"); the slot is unchanged

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

State machine 'run': 4 states, initial 'open_run'
  States: [approved, committed, open_run, voided]

  ✓ 4 states, 3 transitions
  ✓ all states reachable from 'open_run'
  ✓ terminal states: [committed, voided]
  ✓ 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 `approved → voided` is never reached by any handler — spec may be aspirational or stale
  ✓ refinement: handler `approve_run` ⟶ {approved}
  ✓ refinement: handler `commit_run` ⟶ {committed}
  · transition sources: `approve_run`, `commit_run` 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)

Payroll/invariants:

  ✓ invariant budget >= 0 — writer 'approve_run' proven by induction (writes total)
  ⚠ invariant budget >= 0 — runtime-checked (computed values): add_payslip → budget
  ✓ invariant slips >= 0 — writer 'add_payslip' proven by induction (writes amount)

11 passed, 2 warnings, 0 failures

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

Builtins used

get_status, map, transition

Source file: /corpus/escrow_finance/payroll_run.cell · examples/corpus/escrow_finance/payroll_run.cell