// Human-in-the-loop approval gate guarding an irreversible action. // Demonstrates: approve() as a lifecycle gate, a state machine where the // "executing" path is only reachable past the gate, and a rejected path // that lands in a distinct terminal. // // approve() never answers on its own: a test scripts it with // `mock approve true|false`; `soma run` asks the person at the terminal; // under `soma serve` (nobody attached) it raises kind "approval_required" // unless SOMA_APPROVE=always|never states an explicit policy. // // Run: soma run approval_gate.cell deploy "v2.1.0" (asks y/N) // SOMA_APPROVE=never soma run approval_gate.cell deploy "v2.1.0" // Test: soma test approval_gate.cell cell agent Deployer { face { signal deploy(version: String) -> Map } memory { history: List [persistent] } state pipeline { initial: idle idle -> planning planning -> awaiting awaiting -> executing awaiting -> rejected executing -> done * -> failed except [done, rejected] } on deploy(version: String) { set_budget(1500) let id = to_string(next_id()) transition(id, "planning") transition(id, "awaiting") let approved = approve("Deploy {version} to production?") if !approved { transition(id, "rejected") return map("status", "rejected", "version", version) } transition(id, "executing") history.push(version) transition(id, "done") map("status", "done", "version", version, "count", len(history)) } } cell test DeployTests { rules { mock approve true assert deploy("v1").status == "done" mock approve false assert deploy("v2").status == "rejected" // nobody answers: the gate fails closed and the handler rolls back assert_fails deploy("v3") matching "approval_required" // one answer per call: only v1 and v4 were ever deployed mock approve true let d4 = deploy("v4") assert d4.count == 2 } }