Skip to content

Sema’s design is recorded as a numbered decision log (the “D-log”) in the language specification. Each entry states a decision, the evidence behind it, and the alternatives it rejected. This page summarizes the load-bearing decisions, grouped by theme. For the full normative record — every entry with citations — see Decision record; for the motivation in prose, see Why Sema.

Why the language looks the way it does.

#DecisionWhy
D1Pythonic indentation, not a Python superset; PEG grammar with soft keywords; editions from v0.1.LLMs already emit Python fluently, so a Python-shaped surface transfers that prior; a superset would inherit Python’s semantics (which Sema deliberately replaces). Mojo/Codon precedent.
D27No classes. Methods live in struct/enum bodies; polymorphism is traits + ADTs with laws-as-contracts, header or impl conformance, and coherence rules.Trait laws make obligations (e.g. reducer associativity) assure-checkable instead of merely asserted; inheritance and structural duck typing are rejected.
D28Immutable bindings by default, mut to opt in; value semantics for structs/collections.The trust lattice and contracts sit on the binding model; pervasive shared mutability would let trust labels launder through aliasing. Rust-grade borrow checking was judged too costly for the audience.
D43Idiomatic ergonomics: lambda/=>, one *args + one **kwargs, ...expr spread, generic [T] params erased at runtime.Day-one LLM emission needs idiomatic variadics and lambdas; erased generics add expressiveness without a second guarantee regime (contracts + rows stay the guarantee story).
D26Native dict/set/comprehensions/slicing, homogeneous, one Iterable/Iterator protocol; canonical sorted-order flattening.Guarantees that LLMs emit dict literals and comprehensions on day one; collections cannot cross an FFI bridge without losing trust labels and policy meet.

The capability discipline that makes the deterministic core provable.

#DecisionWhy
D7Typed effects-and-handlers spine. policy = capability/effect restriction plus a Cedar-shaped decision layer with compile-verified examples; typed effects, never string matching.One mechanism covers policy, replay, mock, and batching; every string-based gate is respellable and therefore unsound. Rejected a Turing-complete (Rego-class) policy language.
D11Trust lattice untrusted < validated < trusted on all values; generative outputs are born untrusted; endorsement only via contracts, verifiers, or human approval.Object-capability cleanliness from day one (CaMeL/FIDES lineage). Pure control-flow confinement without value labels was rejected.
D71Effect-operation calls are checked. Calling an unrecognized op on a known namespace (fs.raed(...)) raises NameError at the call site; effect rows stay open (!{fs.raed} still parses).Closes the last silent-ignore: a typo’d effect call must fail like any builtin, while capability declarations stay extensible.
D72Effect namespaces are fully real + configurable — real fs/net (HTTP+HTTPS)/db (embedded SQLite, swappable by DSN or a @provides("db") backend)/env/proc/ui.”No stubs”: every effect performs its real operation, and the HTTP knobs and SQL server swap via config + providers without touching Rust.

Making model calls first-class, legible, and honest.

#DecisionWhy
D5simulate def … by <model> — a model implements the body, with sem descriptors, a public cached meaning-IR, contracts, budgets, and untrusted labeling.Adopts the published, user-studied Meaning-Typed-Programming result; rejects prompt-template DSLs (LMQL died) and LLM-as-VM designs.
D44Semantic operations are first-party: the ~ sigil family (~=, ~<, ~in, ~+, ~and, ~[query], …) all derive model.invoke, plus a semantic namespace of primitive verbs and a coercion protocol (a type picks its own embed/sem_text).SymbolicAI proved semantic operators are ergonomic but hid failure behind fuzzy bools; marking the operation keeps model calls legible and forces a complete strict/bitwise/semantic logic story.
D2~= returns a graded Sim, not a bool. Branching on it requires calibration; regions are typed statistical(α).Fuzzy-bool casts are the SymbolicAI defect class; a calibrated conformal threshold gives an honest certificate instead of a silent coercion.
D3semantics() pins a judge in the type(judge hash, calibration id, α) — evaluated by protocol, never one raw judge.Hallucination is inevitable and single-judge truth is ill-posed; the judge identity is part of the program’s semantics.
D13Models are pinned first-class values with roles and calibrations; no floating string refs, ever.A "latest" string resolved at runtime makes the program’s semantics non-reproducible; the model artifact is pinned like any other dependency.

Why correctness is checked by default.

#DecisionWhy
D4Contracts in the public signature. Failed values are typed-failed and cannot flow; check (graded, monitored) vs ensure (fatal); Findler–Felleisen blame everywhere.Enforcement, not advice — advisory contracts (comments/decorators outside the type) are rejected.
D6Verification is default-on. The opt-in testable keyword is retired; assure bronze/silver/gold grades with a red/amber/green verdict and a mutation-adequacy gate.Weak suites launder wrong LLM code (EvalPlus); opt-out beats opt-in; property-based testing surfaces ~50× the mutant density of line coverage.
D34Authored test declarations are native (test "name": block) with ensure/check as the assertion vocabulary and record-replay under pinned seeds; red-verdict counterexamples materialize back into test blocks.Every mainstream language ships native test entry points; reusing contract clauses keeps one semantics for all expectations. A separate matcher DSL was rejected.
D35Semantic assertions reuse the contract forms — hard ensure semantics(...), soft check semantics(...) — with no new keyword; assert is a reserved, rejected token with a fix-it to ensure/check.One assertion semantics for deterministic and semantic predicates; Python’s assert strips under -O and would teach the wrong semantics.
D68Real static checker + verification engine + constraint solver. sema check catches arity/field/type errors conservatively (zero false positives); sema assure fuzzes properties and mutation-tests at gold; solve: does finite-domain search.Backs the “statically typed + default-on verification + neurosymbolic” claim with real machinery, not lint.
D15Monitor-or-decay. A statistical(α) obligation needs an active monitor on its input; without one it decays to best_effort at the type level. The compiler derives shared input monitors where none is declared.The α certificate is honest only while the deployment distribution matches calibration; the monitor is what guards that assumption.
#DecisionWhy
D30No unwinding exceptions. Failures are Error-trait values in Result/sums, handled by expect/except, propagated by a trust- and blame-preserving ?; unwrap is a checked abort rejected under assure gold.Unwinding is invisible to effect rows and hostile to replay and blame; “a failed value cannot flow into non-handling code” needs a defined handling construct.
D31No colored functions. async/await do not exist; concurrency is structural (scope/spawn/parallel over non-blocking effect handlers).The runtime is already non-blocking under structured concurrency; a vestigial async token would invite LLMs to emit an unspecified construct.
D32One with <expr> as x: construct unifies scoped resources, policy scoping, and model rebinding, with deterministic journaled release and no user destructors.Nondeterministic finalization breaks replay; effect-handler scoping is the mechanism the runtime already uses.
D10 / D14Self-healing is supervision-scoped and repair-only (supervise/heal, patch-scoped code.patch, a deterministic gauntlet) — not a program-wide mode, and not program growth. Sanctioned growth is descriptor-space regeneration at simulate sites plus human-approved patch-scope widening.Intrinsic self-modification without external grounded feedback degrades results; a general write capability would break healing’s escalation-proof property.
#DecisionWhy
D9 / D18Split native (bind) vs ported (translate with a differential gate); foreign code uses typed bridge membranes by default (normal .py/.ts/.c files + expose def signatures), with inline begin/end blocks as small trusted glue.Bind ecosystems, translate only self-contained code; guarantees hold only at typed membranes, which keep native toolchains while adding Sema’s contracts, policy, and re-validation.
D57 / D58 / D59 / D60Python bridge + native packages. python.call runs real Python behind a persistent warm worker (non-JSON results become object handles); sema add/remove/list wraps uv for PyPI and installs native Sema packages by path/git.Ecosystem access from day one is table stakes; a warm worker makes real classes/objects first-class Sema values.
D47 / D56 / D61Real, feature-gated model backends. sema-model = pure-Rust local GGUF inference on candle (Metal/CPU); a real candle BERT embedder; both behind the real-model feature so default builds link no ML stack (mock stays the hermetic default).The mock needs a credible real counterpart; candle keeps it single-binary and Python-free; feature-gating preserves fast portable builds.
D62 / D63 / D64Documentation & debugging via reflection. sema doc reflects signatures + docstrings to Markdown; the trace keyword reflects error frames into a self-repair packet; sema repl + sema dap share the real evaluator.Docs must not drift (reflect them); a stack trace is already the agent’s self-repair context; a separate debug interpreter would drift from the real one.
D49Opt-in bytecode VM. The tree-walker stays the reference/default; SEMA_VM=1 runs compilable functions on a stack VM with function-granularity fallback and delegated value ops.Beating CPython needs slot resolution + flat dispatch; partial-but-safe (fallback + delegated semantics) ships incrementally with no divergence.

Native constructs over library conventions

Section titled “Native constructs over library conventions”

Sema makes several concerns that are usually library conventions into typed, checked language constructs, so the compiler can see them.

AreaDecisionsThe construct
Configuration, CLI args, DID22config/args/container/provide/inject with typed provenance and compile-checked graph resolution.
Tap collectors / metricsD23collector channels + the reserved `
ParallelismD24One contextual parallel construct, typed => lambdas, deterministic merge, optional worker profiles — not aliases or raw threads/futures.
EventsD29event/emit/subscriber with bounded queues and journal-integrated exactly-once-per-run delivery.
Templates / patterns / SQLD16 / D19 / D20Native sem descriptors; typed interpolation, regex match, sql"…"; templatePrompt[T] and context state machines.
StreamsD39One Stream[T] with generator/parallel/service producers, affine scoped values, and pull-based backpressure — no async coloring.
Services (RPC)D38service = a typed remote membrane with derived net.connect rows, wire-schema handshakes, and blame across the wire.
MathD42equation blocks where math notation is the syntax, pure by construction (!{} row).