# Soma Language Reference — for AI Agents

> Give this file to an AI agent as context when asking it to write Soma code.
> The authoritative builtin list is `soma docs builtins` (published as /docs/builtins.md and /builtins.json).

## Quick rules

- No semicolons. Newlines separate statements.
- No `function`/`def`. Use `on handler_name(params) { }`.
- No `null`. Use `()` for null/unit.
- Lists: `[1, 2, 3]` and `list(1, 2, 3)` both work.
- No `{key: val}`. Use `map("key", val, "key2", val2)`.
- No `import`. Use `use lib::module`.
- No `console.log`. Use `print(value)`.
- No `===`. Use `==`.
- Strings: `"hello {name}"` (interpolation with `{}`).
- Multi-line strings: `"""..."""` (backslashes are literal, quotes work inside; `{x}` IS interpolated — write `{{` for a literal brace, so a template that a later `render(tpl, "name", …)` fills is written `"""hi {{name}}"""`; a bare `{name}` with no such variable is a check error).
- Integer division: `7 / 2 = 3.5` (auto-promotes to float when non-exact).
  Same in `[native]` handlers: `7 / 2 = 3.5`, an exact quotient is an Int (BigInt-exact). Native code is
  statically typed, so a slot that can only hold an Int (an Int variable, an index) refuses a non-exact
  quotient with a runtime error — it never truncates.
  `idiv(a, b)` is the integer quotient on every backend (truncates toward zero, BigInt-exact).

## Cell structure

```soma
cell AppName {
    memory {
        data: Map<String, String> [persistent, consistent]    // → SQLite
        cache: Map<String, String> [ephemeral, local]         // → in-memory
    }

    state workflow {
        initial: draft
        draft -> review
        review -> approved
        review -> rejected
        * -> cancelled
    }

    every 30s {
        // runs periodically
    }

    after 5s {
        // runs once after delay (one-shot timer)
    }

    on handler_name(param1: Type, param2: Type) {
        // handler body
        return value
    }

    on request(method: String, path: String, body: String) {
        match path {
            "/" -> html(dashboard())
            "/api/data" -> get_data()
            _ -> response(404, map("error", "not found"))
        }
    }
}
```

## Types

| Type | Example | Notes |
|------|---------|-------|
| Int | `42`, `-1`, `0` | arbitrary precision (i64 fast path, BigInt beyond — a slot gives it back as an Int) |
| Float | `3.14`, `1.5e3` | 64-bit, scientific notation |
| String | `"hello {name}"` | interpolation with `{}` |
| Bool | `true`, `false` | |
| List | `list(1, 2, 3)` or `[1, 2, 3]` | ordered |
| Map | `map("key", val)` | key-value pairs, MUST have even args |
| Unit | `()` | null equivalent |
| Duration | `5s`, `1min`, `500ms`, `1h` | converts to milliseconds |
| Record | `User { name: "Alice", age: 30 }` | typed map with `_type` field |

## Variables

```soma
let x = 42
x = x + 1                    // reassignment
x += 10                      // compound assignment
x -= 5                       // compound subtraction
x *= 2                       // compound multiplication
x /= 3                       // compound division
let name = "world"
let greeting = "hello {name}" // interpolation
```

## Control flow

```soma
if condition {
    // ...
} else if other {
    // ...
} else {
    // ...
}

while condition {
    if done { break }
    if skip { continue }
}

for item in list(1, 2, 3) {
    print(item)
}

for i in range(0, 10) {
    // 0 to 9
}

match value {
    "a" -> expr1
    "b" -> { stmts; expr2 }
    42 -> expr3
    () -> expr4              // match null
    "x" || "y" -> expr5     // or-pattern
    name -> use(name)        // variable binding (captures value)
    "/api/" + rest -> api(rest) // string prefix pattern
    {method: "GET", path} -> get(path) // map destructuring
    _ -> default_expr        // wildcard
}

// Map destructuring with nested patterns
match request {
    {method: "GET", path: "/"} -> home()
    {method: "POST", path: "/api/" + resource} -> create(resource)
    {method: "DELETE", path: "/api/" + resource} -> delete(resource)
    _ -> response(404, map("error", "not found"))
}

// Guard clauses
match score {
    n if n >= 90 -> "A"
    n if n >= 80 -> "B"
    n if n >= 70 -> "C"
    _ -> "F"
}

// Range patterns
match http_status {
    200..299 -> "success"
    300..399 -> "redirect"
    400..499 -> "client error"
    500..599 -> "server error"
    _ -> "unknown"
}

// If/match as expressions
let x = if cond { a } else { b }
let y = match status {
    "on" -> true
    _ -> false
}
```

## Functions (handlers)

```soma
on add(a: Int, b: Int) {
    return a + b
}

on _private_helper() {
    // underscore prefix = not exposed as HTTP endpoint
    return "internal"
}

// Call: let result = add(1, 2)
```

## Lambdas

```soma
let doubled = list(1, 2, 3) |> map(x => x * 2)
let evens = data |> filter(x => x % 2 == 0)
let found = data |> find(x => x.id == target)
let has = data |> any(x => x.active)
let ok = data |> all(x => x.valid)
let n = data |> count(x => x.score > 80)

// Block lambda
let enriched = data |> map(s => {
    let score = s.x * 2 + s.y
    s |> with("score", score)
})

// Reduce
let sum = list(1, 2, 3) |> reduce(0, p => p.acc + p.val)
```

## Collections

```soma
// List
let items = list(1, 2, 3)           // or: let items = [1, 2, 3]
let items = push(items, 4)          // append
let pairs = enumerate(items)        // list of {index, value} maps
let first = items[0]                // bracket index (or nth(items, 0))
items[0] = 99                       // index assignment (in place)
let two = with(items, 1, 88)        // functional: copy with element 1 replaced
let rev = reverse(items)
let r = range(0, 10)                // [0..9]
let down = range(9, -1, -1)         // [9,8,..,0] — step may be negative
let evens = range(0, 10, 2)         // [0,2,4,6,8]
let sorted = sort(items)            // ascending
let sorted = sort(items, "desc")    // descending
let n = len(items)

// Map
let m = map("name", "Alice", "age", 30)
let name = m.name                   // field access
let age = m["age"]                  // bracket index (or m.get("age"))
m["email"] = "a@b.com"              // index assignment
let keys = m.keys()                 // or keys(m); m.keys without parentheses also answers
let vals = m.values()
let updated = m |> with("city", "NYC")
let smaller = without(m, "age")     // copy minus one key
let merged = merge(m, map("x", 1))  // right side wins on conflicts

// String — bracket index returns the 1-char string at that position
let s = "hello"
let h = s[0]                        // "h" ; out-of-bounds raises
```

## Pipe operators

```soma
// Higher-order (with lambdas)
data |> map(s => s.name)
data |> filter(s => s.score > 50)
data |> find(s => s.id == target)
data |> any(s => s.active)
data |> all(s => s.valid)
data |> count(s => s.score > 80)
data |> reduce(0, p => p.acc + p.val)

// Field-based
data |> filter_by("price", ">", 100)     // operators: > >= < <= == !=
data |> sort_by("score", "desc")
data |> top(10)
data |> bottom(5)
data |> group_by("dept")
data |> distinct("category")              // unique values

// Aggregates
data |> sum_by("qty")                     // sum of a field
data |> avg_by("qty")                     // average (Int if whole, else Float)
data |> min_by("qty")                     // row with smallest field value
data |> max_by("qty")                     // row with largest field value
data |> count_by("status", "open")        // count rows where field == value
data |> pluck("name")                     // list of one field's values
data |> select("id", "name")              // project each row to listed fields
data |> agg("dept", "qty:sum", "qty:avg") // group + aggregate; ops: sum avg min max count

// Utilities
data |> flatten()
data |> reverse()
data |> zip(other)
list("a", "b", "c") |> join(", ")        // "a, b, c"
```

## String builtins

```soma
len("hello")                    // 5 (chars, not bytes)
concat("foo", "bar")            // "foobar"
contains("hello", "ell")        // true
starts_with("hello", "he")      // true
ends_with("hello.txt", ".txt")  // true
replace("hello", "l", "r")     // "herro"
split("a,b,c", ",")            // ["a", "b", "c"]
trim("  hi  ")                  // "hi"
uppercase("hello")              // "HELLO"
lowercase("HELLO")              // "hello"
substring("hello", 1, 3)        // "el"
index_of("hello", "ll")         // 2
escape_html("<b>x</b>")         // "&lt;b&gt;x&lt;/b&gt;"
to_json(map("a", 1))            // {"a":1}  (compact, like JSON.stringify; print(m) shows {"a": 1})
from_json("{\"a\": 1}")         // map
```

## Math builtins

```soma
abs(-5)             // 5
round(3.7)          // 4
floor(3.7)          // 3
ceil(3.2)           // 4
min(3, 7)           // 3
max(3, 7)           // 7
idiv(7, 2)          // 3 — integer division, truncates toward zero
ln(2.718)           // ~1.0 — natural log (alias of log)
clamp(15, 0, 10)    // 10
pow(2, 10)          // 1024.0
sqrt(16.0)          // 4.0
log(2.718)          // ~1.0
exp(1.0)            // ~2.718
log10(100.0)        // 2.0
random()            // float 0.0..1.0
random(100)         // int 0..99
random(10, 20)      // int 10..19
```

## Type conversion

```soma
to_int("42")        // 42
to_int("abc")       // () — returns null, not 0
to_int(3.7)         // 3
to_float(42)        // 42.0
to_string(42)       // "42"
type_of(42)         // "Int"
is_type(rec, "User") // true if rec's _type field is "User" (alias: is_a)
```

## Error handling

```soma
let result = try { risky_operation() }     // {value, error, kind, detail}
if result.error != () {
    print("Error: {result.detail}")        // detail = the message alone (Error.message); error = "kind: detail"
    return response(500, map("error", result.detail, "kind", result.kind))
}
let value = result.value

// Short form: ? operator propagates errors (returns early if error)
let value = try { risky_operation() }?
// Equivalent to: if result has error, return error map; else unwrap value

// Agent builtins
let answer = think("What is 2+2?")           // call LLM (configured in soma.toml)
let data = think_json("Return as JSON: ...")  // LLM returns Map, not String

// Bounded think/http — enables compile-time budget proofs
let answer = think("prompt", map("max_tokens", 500, "timeout", 10000))
let data = http_get(url, map("max_bytes", 65536, "timeout", 5000))

delegate("Writer", "write", facts, topic)     // call another agent's handler
remember("key", value)                        // persistent agent memory
let val = recall("key")                       // recall from agent memory
set_budget(5000)                              // hard token cap
let t = tokens_used()                         // tokens consumed
let left = tokens_remaining()                 // budget minus used (-1 = unlimited)
let log = trace()                             // execution log
clear_trace()                                 // reset the execution log
clear_context()                               // reset multi-turn LLM conversation
approve("publish article")                    // human-in-the-loop gate
```

## Matrices

A matrix is a `List<List<Float>>` (a list of equal-length rows) and is a
first-class value: bracket-indexed, method-callable, and operated on with
arithmetic operators.

```soma
let M = [1, 0, 0, 1].reshape(2, 2)    // flat list → 2×2 matrix
let A = [1, 2, 3, 4, 5, 6].reshape(2, 3)
let s = A.shape                        // [2, 3]  (parens-free pseudo-field)
let t = A.T                            // transpose (also A.transpose())
let x = A[1][2]                        // element access (row 1, col 2)
let n = matrix("1 2; 3 4")             // MATLAB-style literal

// vectorized operators (numpy/MATLAB style):
let prod = A * A.T                     // matmul (both matrices)
let scaled = 2 * A                     // scalar broadcast: * / + - both orders
let shifted = A + 10                   // matrix + scalar
let halves = A / 2
let summed = A + A                     // elementwise (equal shapes)
let v = list(1.0, 2.0, 3.0)
let v2 = v * 2                         // vector broadcast: * / + -
let sq = v * v                         // vector elementwise: + * / -
let vsum = v + v                       // elementwise add (numeric vectors)
let mask = A > 2                       // comparison mask → 0/1 matrix
let vm = v >= 2.0                      // 0/1 vector (feed to where_mask)
// list CONCATENATION is explicit: concat(a, b). Non-numeric lists
// (strings, records) keep + = concat.
let d = det([4, 3, 6, 3].reshape(2, 2))   // -6.0

// any builtin is also a method (UFCS): xs.sum(), xs.sort(), xs.reverse(),
// m.det(), m.transpose(), m.matmul(other)
```

Builtins: `reshape(values, r, c)`, `transpose`, `shape`, `matmul`, `det`,
`diag_sum` (trace), `identity(n)` / `eye(n)`, `scale(m, k)`, `mat`, `rows`,
`cols`, `diag`, `zeros`, `ones`, plus the quant suite (`svd_lowrank`,
`regress_sgd`, `clean_covariance`, `var_historical`, …).

## Agent configuration (soma.toml)

```toml
[agent]
provider = "ollama"          # ollama (free, local)
model = "gemma3:12b"

# Or OpenAI:
# provider = "openai"
# model = "gpt-4o-mini"
# key = "sk-..."             # or use SOMA_LLM_KEY env var

# Or Anthropic:
# provider = "anthropic"
# model = "claude-opus-4-6"
# key = "sk-ant-..."         # or use SOMA_LLM_KEY env var

# Or custom endpoint:
# url = "https://your-api.com/v1/chat/completions"
# model = "your-model"
# key = "your-key"
```

Ollama needs no key. OpenAI/Anthropic keys can go in soma.toml or `SOMA_LLM_KEY` env var.
Env vars always override soma.toml.

```soma

// Postconditions: ensure (checked at point of execution)
on withdraw(balance: Int, amount: Int) {
    let result = balance - amount
    ensure result >= 0   // fails with error if false
    return result
}

// try catches: division by zero, type errors, stack overflow, invalid
// transitions, require/invariant/ensure failures, fail(). Undefined
// variables and functions are `soma check` errors: they never reach try.
```

## Storage

```soma
memory {
    accounts: Map<String, Map> [persistent, consistent]  // → SQLite; records as values
    cache: Map<String, String> [ephemeral, local]        // → in-memory
    rows: List<Map> [persistent]                         // an append log: push / rows[i] = v / rows.delete(i)
    balance: Map<String, Int> [persistent]
    invariant balance >= 0 && balance <= 1000   // checked BEFORE every .set()/.push() commits
    invariant size <= 10000                     // entry-count bound (all slots in this section)
}

// Invariant bindings: <slot name> and `value` = the value being written,
// `key` = the key, `size` = entry count after the write. An invariant
// that names slots guards only those; one using just value/key/size
// guards every slot in its section. A violating write raises a
// try-catchable error and the slot is UNCHANGED. `soma verify` proves
// literal, clamp(), require-narrowed and read-modify-write forms by
// induction (docs/guarantees.md); what it cannot prove is runtime-checked
// and reported as ⚠ (a failure under --strict).
// Invariants may call builtins only.

// In handlers:
accounts.set("a1", map("owner", "ada", "cents", 100))
let a = accounts.get("a1")          // returns () if missing
a.cents = a.cents + 5               // edit the copy, write it back:
accounts.set("a1", a)               // (or accounts["a1"].cents = 105 in one step)
accounts.delete("a1")
let keys = accounts.keys             // list of keys
let vals = accounts.values           // list of values
let n = accounts.len                 // count
// The value type is enforced on every write: Map<String, Int> refuses a
// String or 1.5 (kind `type`); an Int written to a Float slot becomes a
// Float; Map<String, Pay> takes only Pay variants. Ints of any size,
// Floats (NaN, inf), (), variants and nested maps/lists round-trip exactly.

// No to_json needed for values: a map stored is a map read back.
```

## State machines

```soma
state order {
    initial: pending
    pending -> validated { guard { amount > 0 } }
    validated -> sent
    sent -> filled
    sent -> rejected
    filled -> settled
    * -> cancelled           // from any state
}

// In handlers:
transition("order_id", "validated")    // move state
let status = get_status("order_id")    // current state
let valid = valid_transitions("order_id") // available transitions
```

## Sum types

```soma
// `cell type` + `variants` = tagged union. Struct, tuple, or bare variants.
cell type PaymentResult {
    variants {
        Charged { transaction_id: String, amount: Int }   // struct variant
        Declined(String)                                   // tuple variant
        Pending                                            // unit variant
    }
}

// Construct directly — bare variants take no parentheses:
on charge(amount: Int) {
    if amount > 0 { return Charged { transaction_id: "tx-1", amount: amount } }
    if amount == 0 { return Pending }
    return Declined("non-positive amount")
}

// match is EXHAUSTIVE — missing a variant is a compile error:
on describe(r: Map) {
    return match r {
        Charged { transaction_id, amount } -> "ok {transaction_id} ${amount}"
        Declined(reason)                   -> "rejected: {reason}"
        Pending                            -> "..."
    }
}
```

```soma
// Typed state machine: states must be variants of the sum type,
// and transition() takes a variant (typo = compile error):
cell type TodoStatus {
    variants { Pending  InProgress  Done  Cancelled }
}

cell TodoList {
    state todo: TodoStatus {
        initial: Pending
        Pending    -> InProgress
        InProgress -> Done
        *          -> Cancelled
    }

    on start(id: String) {
        transition(id, InProgress)         // variant, not string
        return get_status(id)              // "InProgress"
    }
}
```

## HTTP server

```soma
// Run: soma serve app.cell
// HTTP on :8080 (127.0.0.1 unless --host); WS on :8081 only with `on ws`;
// signal bus on :8082 only with emit / scale / --join
// Dashboard: http://localhost:8080/__soma/ (state machines, budget, verification)

on request(method: String, path: String, body: String) {
    match path {
        "/"         -> html(render_page())
        "/api/data" -> get_all_data()
        _           -> response(404, map("error", "not found"))
    }
}

// Response types:
html("<h1>Hello</h1>")                // text/html
map("key", "value")                    // application/json (auto)
response(201, map("id", 1))           // custom status code
redirect("/other")                     // 302 redirect
sse("trade", "update")                // SSE event stream
```

## HTTP client, WebSocket, signal bus

```soma
let resp = http_get(url, map("timeout", 2000))           // GET; JSON bodies auto-parse to Map/List
let resp = http_post(url, body, map("timeout", 2000))    // a Map/List body goes as JSON
// also http_put / http_patch (url, body, opts?) and http_delete(url, opts?)
// opts: timeout (ms, default 30000), max_bytes, headers: map("Authorization", "Bearer …")
let ws = ws_connect("ws://host:9001")     // open WebSocket (send-only) → {status, url}
ws_send(message)                          // send text on the open WebSocket
subscribe("ws://host:9001/stream")        // read-only WS: incoming {"event", "data"} → on event(data)
link("host:8082")                          // TCP signal-bus link: emits reach peer, peer EVENTs → handlers
publish("stream-name", data)              // push to SSE subscribers on a runtime-chosen stream
```

The http builtins never raise. A 2xx answer is its body; anything else is
`{error, kind, status, body}`: kind `http_status` (with the upstream status
and its body, parsed when JSON), `timeout`, `refused` or `network`. Branch on
`resp.kind` / `resp.status`, not on the text. Under `soma serve` the call
holds the handler lock for its whole duration (handlers are serialized):
keep timeouts short. In tests, `mock http_post map(...)` scripts the next
call, `mock http_get error "timeout: slow"` a failure (`status_404: …`
gives status 404); an unscripted real call prints a note.

## Events: `emit`

In one process, `emit trade(data)` calls every cell that declares `on
trade(data: Map)`, synchronously, inside the emitter's transaction (a
listener that raises fails the emitter; the emitter's rollback undoes the
listeners' writes). `soma check` warns when no cell handles the event. Across
processes the same statement goes over the signal bus (`[peers]`), where it
is fire-and-forget:

```soma
// soma.toml
// [peers]
// exchange = "localhost:8082"

// Send (goes to all peers):
signal order(map("ticker", "BTC", "qty", 1))
// or:
emit trade(fill_data)

// Receive (auto-dispatched from bus):
on trade(data: Map) {
    record_fill(data)
}
```

## File I/O

```soma
let content = read_file("data.txt")
write_file("output.txt", content)
let rows = read_csv("data.csv")       // list of maps, auto-typed
write_csv("out.csv", rows)            // list of maps → CSV (headers from first row)
let tpl = load("page.html")           // read file (aliases: include, load_template)
let s = load("page.html", "k", v)     // read + replace {k} placeholders with v
let files = read_files("dir", 100)        // first N files → list of {path, content}
let files = par_read_files("dir", 100)    // parallel version (threaded)
let counts = word_count(text)             // map of word → count (lowercased; also takes a list)
let counts = par_word_count(files)        // parallel version (threaded)
```

## Templates

```soma
let s = render(tpl, "name", "Ada")        // replace {name} with "Ada" in template string
let s = render_each(rows, row_tpl)        // render template once per map in list
```

## Time

```soma
let ts = now()                // unix timestamp (seconds)
let ms = now_ms()             // milliseconds
let today = today()           // "2026-03-29"
let formatted = format_date(ts) // "2026-03-29"
sleep(100)                    // pause 100 milliseconds
```

## Verification

```soma
// soma.toml
// [verify]
// cells = ["Order"]                  # optional: which machines these apply to
// deadlock_free = true
// eventually = ["settled", "cancelled"]
// never = ["invalid"]
// always = ["open", "closed"]        # the machine is only ever in one of these
//
// [verify.after.sent]
// eventually = ["filled", "rejected"]
// [verify.before.filled]
// requires = ["sent"]                 # requires_all = [...] for several
// (an unknown key is an error; --strict turns every ⚠ into a failure)

// Run: soma verify app.cell
```

## Face contracts (compile-time checked)

```soma
cell API {
    face {
        signal create(name: String) -> Map    // MUST have matching handler
        signal delete(id: String)              // MUST have matching handler
        promise all_persistent                 // structural check
        promise "human-readable description"   // a note (not checked)
    }
    // Missing handler for 'delete' → compile error
}
```

## Tests

```soma
cell test MathTests {
    rules {
        assert 1 + 1 == 2
        assert len("hello") == 5
        assert round(3.7) == 4
    }
}
// Run: soma test file.cell
```

## Multi-file projects

```
project/
    app.cell          // main file
    lib/
        helpers.cell  // use lib::helpers
        scoring.cell  // use lib::scoring
    soma.toml         // config + peers + verify
```

```soma
// app.cell
use lib::helpers
use lib::scoring

cell App {
    on run() {
        let result = helper_function()   // from helpers.cell
    }
}
```

## Common patterns

```soma
// CRUD web app
cell App {
    memory { items: Map<String, String> [persistent, consistent] }

    on request(method: String, path: String, body: String) {
        if method == "POST" && path == "/api/items" {
            let data = from_json(body)
            let id = to_string(next_id())
            items.set(id, to_json(data |> with("id", id)))
            return data |> with("id", id)
        }
        match path {
            "/api/items" -> items.values |> map(s => from_json(s))
            _ -> response(404, map("error", "not found"))
        }
    }
}

// Data pipeline
cell Pipeline {
    on run() {
        let data = read_csv("input.csv")
        let result = data
            |> filter(s => s.score > 50)
            |> sort_by("score", "desc")
            |> top(10)
        print(result)
    }
}

// Real-time with state machine
cell OrderSystem {
    memory { orders: Map<String, String> [persistent, consistent] }
    state order { initial: pending  pending -> validated  validated -> shipped  * -> cancelled }
    every 30s { check_stale_orders() }

    on create(data: Map) {
        let id = to_string(next_id())
        orders.set(id, to_json(data |> with("id", id) |> with("status", "pending")))
        return map("id", id)
    }

    on advance(id: String, target: String) {
        return transition(id, target)
    }
}
```

## Linear algebra & risk (`linalg`)

Quantum-inspired sublinear linear algebra (Tang et al.) plus
Bouchaud-Potters covariance cleaning and risk metrics. Every builtin
takes an options Map carrying explicit sample / iteration / dimension
bounds — `soma check` reads them and proves closed-form runtime.

### Matrix constructors

```soma
// Most readable for hand-written matrices
let A = matrix("1 2 3; 4 5 6")          // 2×3, MATLAB-style; ';' rows, ws/',' entries

// When you have row vectors in hand
let B = rows(list(1.0, 2.0), list(3.0, 4.0))

// Column-major constructor (transposes)
let C = cols(list(1.0, 2.0), list(3.0, 4.0))

// Reshape a flat list
let D = mat(2, 3, list(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))

// Standard constructors
let I = eye(3)                          // 3×3 identity
let Z = zeros(2, 4)                     // 2×4 zeros
let O = ones(3, 3)                      // 3×3 ones
let G = diag(list(1.0, 2.0, 3.0))       // 3×3 diagonal
```

### Sublinear sampling (Tang)

Build the BST-backed `Sampled` handle once; pay O(log n) per sample
thereafter.

```soma
let A = to_sampled(dense, map("max_rows", 1000, "max_cols", 50))
// A is a handle: { __sampled__, rows, cols, fro_norm, kind: "sampled" }

let s   = sample_row(A)                       // O(log m) ℓ²-norm row sample
let isr = importance_sample_rows(A, map("samples", 50))
let svd = svd_lowrank(A, map(
    "row_samples", 100, "col_samples", 50, "rank", 10, "max_dim", 1000
))
let fit = regress_sgd(A, b, map(
    "eps", 0.01, "lambda", 0.1, "max_iter", 10000, "max_dim", 1000
))

drop_sampled(A)                               // free the registry entry
```

All four algorithms accept either a sampled handle or a dense
`List<List<Float>>` transparently.

### Covariance cleaning (Bouchaud-Potters)

Replace the noise-bulk eigenvalues of a sample covariance with their
RMT-shrunk versions. Drastically improves out-of-sample portfolio
optimization in any regime where N (assets) is comparable to T
(observations).

```soma
let cov = clean_covariance(returns, map(
    "method", "rie",          // "rie" | "clip" | "raw"
    "eta", 0.1,               // Stieltjes regularizer
    "center", true,
    "max_assets", 500,
    "max_obs", 1000
))
// cov.matrix is the cleaned N×N matrix; cov.eigenvalues_clean is the spectrum.
```

### Market impact (Bouchaud square-root law)

```soma
let imp = impact_sqrt(qty, daily_volume, sigma, map("Y", 1.0))
// imp.bps is the expected slippage in basis points.
ensure imp.bps <= max_slippage_bps    // compile-time pattern, runtime check
```

### Risk metrics

```soma
let var95 = var_historical(returns, map("alpha", 0.95, "max_obs", 250))
let es95  = expected_shortfall_historical(returns, map("alpha", 0.95))
let varg  = var_gaussian(returns, map("alpha", 0.95))   // for comparison
let q     = quantile(returns, 0.05)                      // empirical quantile
```

Historical estimators make no distributional assumption — the
Bouchaud-Potters baseline for fat-tailed markets.

### Verified pre-trade pattern

```soma
on submit(qty: Float, vol: Float, sigma: Float, hist: List<Float>) {
    let imp = impact_sqrt(qty, vol, sigma, map())
    ensure imp.bps <= 30.0                          // 30bps slippage cap

    let var = var_historical(hist, map("alpha", 0.99, "max_obs", 250))
    ensure var <= 0.05                              // 99%-VaR cap of 5%

    emit place_order(qty)
}
```

Wrap the `submit` call in `try { ... }` from the caller to catch the
ensure-failure as a structured error and reject the order. See
`examples/risk_check.cell` for a complete demo with budget proof.
