soma.cell

Soma 2.6.0 — 2026-09-19

This page describes Soma as of release 2.6.0. Some of it may have changed since: the current release is 3.2.4, and the current language is in the guide.

  • soma.lock records a sha256 of each package's files: a package modified after install is refused at import, and soma install restores it.

  • Check warns when an imported cell defines request or ws (it would own HTTP routing / the WebSocket port).

  • self_call counts only ports this process listens on; a failed guard's source is not sent to clients; 204 / 304 carry no Content-Type; a quote inside {…} in a call argument gets the escaping hint.

  • Performance: a lambda's captured lists and maps are no longer copied per element — |> map / filter / … over a captured list is linear (was quadratic).

  • [native]: an Int / stays exact after the BigInt re-run (it truncated the docs' midpoint example); a handler returning its String parameter compiles; an Int overflow inside a Float/Bool expression is kind range.

  • sort_by puts NaN last; an unclosed CSV quote is an error; quantile refuses q outside [0, 1]; blank CSV cells are missing values for sum_by / avg_by; operator chains count toward the nesting limit.

  • "s" |> map(f) and "s".map(f) raise a type error; kinds rate_limited / too_many_requests answer 429.

  • WebSocket: a returned response(…) sends its body; error bodies hide private handler names; binary frames are answered with an error.

  • Clearer errors for reserved words used as JSON fields (d["cell"]) and for guard locals of a handler that may take a guarded edge.

  • Soundness: "C".delegate(…) / "C" |> delegate(…) are seen by the termination and size proofs; a let hiding a slot no longer lends the slot's bound; the latency bound counts retries (think timeout now covers them), tool rounds, sleep, and is advisory with approve / file I/O; an interpolated transition target is treated as computed.

  • [native]: an exact Int / Int with operands past 2^53 is exact; stdin read before a BigInt re-run is replayed.

  • New ipow (exact Int power) and from_csv(text); read_csv takes delimiter and refuses unknown options; map/filter/… on a non-list raise a type error; format("%.2f", Int) is exact; to_float past the Float range raises range; pow of a non-number raises.

  • In an invariant, slot.get(key) reads the stored value on Map- and record-valued slots too: write-once invariants on Map<String, Map> / List<Map> slots were not enforced.

  • approve() shows control characters as escapes (a model could redraw the prompt); every reply shape is measured against max_tokens and the budget, a reply with no text raises kind llm; a set_budget reached from a tool call can only lower the caller's budget; ..;/ is refused by capability path scopes.

  • A List delete is checked by size invariants only (as verify says); require … else budget answers 400.

  • A JSON request body or bus event with more than 1 000 000 values is refused before parsing (a 15 MB line became 2.4 GB in memory).

  • Events sent after a linked peer disconnected are logged NOT delivered; soma run warns when an emit meant for [peers] goes nowhere.

  • Check warns on m.size ?? default (.size is the entry count, never ()); a negative [native] buffer index is reported as written.

  • Every path-taking builtin (load, include, load_template, read_files, par_read_files, word_count) refuses a .. segment: load("templates/" + name) could serve any file.

  • The bus port opens only for [peers], [bus] accept, scale or --join: an in-process emit no longer exposes the program's listeners.

  • Kinds unauthorized / unauthenticated answer 401; error bodies no longer name private handlers; the loopback Host check parses the whole authority and refuses duplicate Host headers.

  • SOMA_LLM_MOCK=fixed: over max_tokens raises kind llm like a scripted mock; guard locals bound after a transition to another state are accepted.

  • The file write guard is case-insensitive; self_call recognises every spelling of this machine; Origin: null / file:// writes are refused on loopback servers.

  • LLM replies are measured as well as counted: an under-reported reply cannot pass max_tokens or the proven cost bound.

  • File builtins refuse .. segments and writes over the program, its configuration or storage; a loopback server refuses foreign Host headers and cross-origin writes; an HTTP call to the server itself answers self_call; tool capabilities match query spaces encoded.

  • get_status & co. from a machine-less cell with several machines, and variant literals with wrong fields, are check errors; the secret recipe fails closed; security notes in the serving docs.

  • pow_mod work is bounded (bits(exp) × bits(m) ≤ 2^30); to_int / parse_int refuse text past the 2^24-bit Int cap.

  • A bus event that reaches no peer is logged as NOT delivered; the docs give an outbox + acknowledgement pattern for transfers between processes.

  • An Int holds at most 2^24 bits: products, shl and product() past it raise kind range before they are built (interpreter and native); matmul is capped at 10^9 multiply-adds.

  • substring and range refuse wrongly typed arguments (kind type).

  • A huge declared Content-Length no longer aborts soma serve (tiny_http vendored with a chunked drain; bodies past 256 MB are refused 413).

  • A scripted mock think reply longer than max_tokens raises kind llm.

  • Bus peers have bounded send queues (a peer that stops reading is disconnected); WebSocket clients are also dropped past 64 MB queued; the WebSocket Origin check refuses userinfo and control characters.

  • A split string as the last statement of a loop body is a check error; disjunctive invariants over the written value are proven.

  • Duplicate or list-valued Content-Length is refused and the connection's pipelined bytes never run; request-log lines escape control characters.

  • Unary operator chains count toward the nesting limit; a List slot's invariant key is the Int index; html() with header pairs passes the arity check; guard variables bound in a loop body are recognised.

  • emit arity mismatches are check errors; a computed Float is refused by an Int parameter; CSV rows of empty cells survive a round trip and duplicate CSV headers are refused.

  • Parameter types are checked all the way down (HTTP, bus, tools, calls); a Float past 2^53 is not coerced into an Int parameter; [native] handlers and mocks are held to the face's return type.

  • from_json refuses undeclared _types; misspelled builtin types and extra builtin arguments are check errors; () is refused where a nested scalar is declared; write_csv keeps rows holding an empty String.

  • The equal-clause proof tolerates callees that cannot write the slot; contextual keywords work as statement variables.

  • A handler parameter may not take a slot's name; face parameter types must match the handler's.

  • verify and the guard rule see every / after ticks of machine-less cells; instance ids are Strings or Ints (() refused); a renamed machine is reported under soma run too.

  • soma run treats any non-data token as a handler name when several exist; NaN / lambdas in responses are valid JSON.

  • [native] bnot is exact past 2^63; native loop_bound errors keep their kind; soma run … request decodes the path like serve.

  • Guards of transitions taken from machine-less cells are checked; --strict fails when [verify] cells names no cell of the file; for over any finite value terminates; an emit in an imported file opens the bus.

  • The equal-clause proof applies only to pure clauses (locals, arithmetic, ??, .get of the written slot) with a plain key — other slots, nondeterministic or external reads between the require and the write made it prove refused writes.

  • Invariant slot references are counted deep (interpolation, lambdas, match arms) by the checker and the runtime; verify hints never name size / key / value; undefined functions in properties are check errors.

  • mock Cell.handler stubs that cell's handler only; mocks naming nothing, test helpers shadowing program handlers or builtins, and test cells with no assertion are errors; mocks reach [native] sibling calls.

  • --record logs calls that raised; describe / the dashboard keep except on * edges; soma fix exits 1 when errors remain.

  • A require that is exactly an invariant clause over the written value proves it (monotone versions); value / key / size outside an invariant are check errors; slots in nested lambdas are not function values.

  • soma serve refuses to start on a damaged database (quick_check); a file that is not a database is a clean error, not a panic.

  • A materialized range() is capped at 10M elements; dotfiles under static/ are not served; Content-Length + Transfer-Encoding is a 400.

  • Quant builtins enforce max_obs / max_assets and a confidence alpha in (0, 1); no false "share the path" warning for emit listeners.

  • The invariant prover is exact for Ints past 2^53 (intervals widen outward instead of rounding), counts think() tools and computed delegates among a handler's callees, and does not prove a bare slot read that may be ().

  • http_get in a loop, lambda or tool no longer makes a token bound advisory (only a latency bound); a saturated cost peak is advisory.

  • [native] i64::MIN / -1 raises instead of returning a rounded Float; guarded transitions in lambdas see the handler's locals; refinement paths keep their parentheses.

  • Statements inside block lambdas, try { }, if-expressions and match arms (slot[k] = v, emit) are seen by GET→405, the listener set, the termination graph, the size prover and guard / invariant purity.

  • return inside a block lambda is a check error; a bare return returns (); soma run … request GET "/a?x=1" splits the query; every 90m names the duration units.

  • x |> h with a bare handler name is a call for every analysis (termination, cost, route ownership, GET→405, model-driven recursion).

  • subscribe() dispatches only events the program emits or [bus] accept lists; invariants and guards may not read files, print or read stdin.

  • .field on a String or a List raises kind type; serve lists only real endpoints; [native] literal arithmetic that overflows i64 promotes to BigInt as interpreted code does.

  • Capability-scoped tools cannot load files (load, include, par_read_files, …) or link(); invariants are pure conditions (no handler call or effect builtin, however hidden); a tool calling back its think() handler is a termination ⚠; link() makes a handler POST-only; load() substitutes in one pass; a reply over its max_tokens raises.

  • Errors in imported files are reported in that file.

  • ?? short-circuits; with() stores BigInt values; strict Float bounds after a require are proven; tools_allowed must name tools.

  • Interpolation segments are analysed exactly where the runtime finds them: "{ { expr } }" ran expr unseen by route ownership, termination, cost, GET→405, guard and invariant checks.

  • A returned String is sent raw only when it is valid JSON text; JSON answers carry nosniff. [native] string literals unescape {{/}}. Face return types are checked element-wise.

  • An interpolation segment holding a block ("{if c { 1 } else { 2 }}") ends at its matching brace; .size on a record without that field is (); from_json checks a declared variant's shape (a missing or mistyped field raises kind type).

  • A stack overflow is not caught by try; lambdas handing function values to map/filter are a termination ⚠; a computed delegate in request owns the cell's handlers; face tools are not HTTP endpoints.

  • Storage escapes map keys starting with __ (no refusal, no forgery); () is false in every condition; invariants must be Bool.

  • Floats print shortest digits; format("%e"); 5 redirect hops; f(a)(b) refused; unknown handler names in soma run are errors.

  • Storage refuses map keys and slot keys starting with __ (reserved by the encoding: a client body could come back as a forged variant, and such keys escaped len and size invariants).

  • A block lambda's last statement runs when it is not an expression (an emit there was dropped); conditions and predicates take Bools; route ownership follows calls through other cells; run --fresh refuses to wipe a directory a soma serve is using; verify names machines per cell.

  • A lambda call counts toward the recursion guard (self-application aborted the process); calling a function value is a termination ⚠.

  • Cost sees think() in index/field assignments; the guard rule and route ownership see UFCS, interpolation, require and emit chains.

  • A bare slot name never reaches another cell's storage (it bypassed the owner's invariant); writes to slots with non-size invariants no longer count the slot (bulk loads were quadratic).

  • mock think token accounting is capped at max_tokens.