<!-- Sema documentation — Decision Log
     Sema is a new AI-native, neurosymbolic programming language most models
     have not been trained on. Full corpus: https://sema.49.12.246.95.sslip.io/llms-full.txt
     Install language support: https://sema.49.12.246.95.sslip.io/install-skill/ -->

# Decision Log

> A readable summary of Sema's language design decisions — why Python-shaped, why no classes, why typed effects, why default-on verification — with the rationale behind each.

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](/reference/language-spec/08-decision-record/); for the motivation
in prose, see [Why Sema](/start/why-sema/).

:::note
The design principle throughout is *no silent no-ops and no dishonest guarantees*.
Where a construct cannot uphold a guarantee, Sema makes it error, decay to a weaker
labeled guarantee, or surface at `sema check` — never quietly do the wrong thing.
:::

## Surface & shape

Why the language looks the way it does.

| # | Decision | Why |
|---|---|---|
| D1 | **Pythonic 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. |
| D27 | **No 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. |
| D28 | **Immutable 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. |
| D43 | Idiomatic 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). |
| D26 | Native `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. |

## Effects, trust & governance

The capability discipline that makes the deterministic core provable.

| # | Decision | Why |
|---|---|---|
| D7 | **Typed 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. |
| D11 | **Trust 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. |
| D71 | **Effect-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. |
| D72 | **Effect 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. |

## Neurosymbolic core

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

| # | Decision | Why |
|---|---|---|
| D5 | **`simulate 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. |
| D44 | **Semantic 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. |
| D3 | **`semantics()` 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. |
| D13 | **Models 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. |

## Contracts & verification

Why correctness is checked by default.

| # | Decision | Why |
|---|---|---|
| D4 | **Contracts 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. |
| D6 | **Verification 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. |
| D34 | **Authored `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. |
| D35 | **Semantic 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. |
| D68 | **Real 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. |
| D15 | **Monitor-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. |

## Runtime & concurrency

| # | Decision | Why |
|---|---|---|
| D30 | **No 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. |
| D31 | **No 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. |
| D32 | **One `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 / D14 | **Self-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. |

## Interop, packages & tooling

| # | Decision | Why |
|---|---|---|
| D9 / D18 | **Split `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 / D60 | **Python 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 / D61 | **Real, 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 / D64 | **Documentation & 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. |
| D49 | **Opt-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

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

| Area | Decisions | The construct |
|---|---|---|
| Configuration, CLI args, DI | D22 | `config`/`args`/`container`/`provide`/`inject` with typed provenance and compile-checked graph resolution. |
| Tap collectors / metrics | D23 | `collector` channels + the reserved `|>` tap that records the left value and returns it unchanged. |
| Parallelism | D24 | One contextual `parallel` construct, typed `=>` lambdas, deterministic merge, optional `worker` profiles — not aliases or raw threads/futures. |
| Events | D29 | `event`/`emit`/`subscriber` with bounded queues and journal-integrated exactly-once-per-run delivery. |
| Templates / patterns / SQL | D16 / D19 / D20 | Native `sem` descriptors; typed interpolation, regex `match`, `sql"…"`; `template`→`Prompt[T]` and `context` state machines. |
| Streams | D39 | One `Stream[T]` with generator/parallel/service producers, affine scoped values, and pull-based backpressure — no `async` coloring. |
| Services (RPC) | D38 | `service` = a typed remote membrane with derived `net.connect` rows, wire-schema handshakes, and blame across the wire. |
| Math | D42 | `equation` blocks where math notation is the syntax, pure by construction (`!{}` row). |

## See also

- [Decision record](/reference/language-spec/08-decision-record/) — the full, normative table with citations.
- [Open questions](/reference/language-spec/09-open-questions/) — what is deliberately still unsettled.
- [Why Sema](/start/why-sema/) — the motivation in prose.
