<!-- Sema documentation — Effects Catalog
     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/ -->

# Effects Catalog

> The canonical catalog of Sema's built-in effect capabilities — every enforced effect path, the operations that carry it, where it is checked, and how custom capabilities extend the open row vocabulary.

An effect **row** is the part of a function's type that names the authority the
function may exercise: `def f(x: T) -> R !{fs.read, model.invoke}`. This page is
the canonical catalog of the **built-in** capabilities and where each one is
actually enforced. The row vocabulary itself is **open** — you may declare
capabilities of your own (see [Custom capabilities](#custom-capabilities--the-row-vocabulary-is-open)
below). For how rows are inferred, declared, and checked, see
[Functions & Effects](/language/functions-and-effects/) and the
[declarations quick reference](/quick/declarations/); for how authority is
granted and confined, see [Effects & Capabilities](/governance/effects/).

## The deterministic core: `!{}`

A function typed with the **empty row** `!{}` provably performs no model calls and
no I/O. It is a type-enforced sublanguage, not a convention — the deterministic core
of Sema. An omitted row is not a wildcard: it asks the compiler to *infer* the
minimal row from the body, which is fail-closed (a function that touches nothing
infers `!{}`). Authority is always conspicuous.

```sema
def add(a: int, b: int) -> int !{}:       # provably pure — no model, no I/O
    return a + b

def load_config(path: str) -> Config !{fs.read}:   # authority is stated
    ...
```

`!{*}` is the explicit all-effects top (⊤) — a loud, greppable escape hatch for
spikes and REPL work, **not** the meaning of silence. `sema check` warns on it at
`bronze` and errors at `silver`+, and the runtime refuses to admit it under any
policy that forbids or bounds capability.

## How to read the tables

Each namespace below gets one table:

- **Effect path** — the enforced string that appears in rows, journals, and
  policy rules. Effect *instances* are parameterized — `net.connect("api.internal:443")`,
  `fs.read("data/**")` — and policies match on instances.
- **Granting operations** — the calls and constructs that perform a
  `check_effect_op` for this path before doing real work.
- **Enforcement** — where the check happens, whether the *instance* (scope) is
  enforced, and which Cortex governance capability grants it under a sealed
  posture. *Benign* marks the host-free effects auto-granted under every
  non-admin posture; *taint source/sink* marks the ends of the
  untrusted-data watermark (a model/net/ffi return taints the frame; a tainted
  frame cannot reach an exec sink without `human.approve` endorsement).

Spec-vocabulary spellings are canonicalized before enforcement:
`proc.spawn`/`proc.exec`/`proc.shell` → `proc.run`; `net.get`/`post`/… →
`net.connect`; the §3.6 spellings `memory.query`/`memory.retain` land on
`memory.read`/`memory.write`, `clock` on `clock.read`, and all `config.*` on
`config.read`.

**Recognized ops vs. mapped effects.** Each namespace also carries a
*recognized-op surface* — the typo guard: calling an unrecognized op on a known
namespace (`fs.raed(...)`) is a `NameError` at the call site, never a silently
journaled no-op. That surface is deliberately a **superset** of the operations
that map to an effect today; recognized spellings with no current mapping are
reserved vocabulary (calling an unimplemented one still fails loudly):
`fs.read_bytes`/`read_csv`/`write_bytes`/`glob`/`walk`/`stat`/`size`/`touch`,
`net.listen`/`resolve`/`ping`/`download`/`upload`/`send`/`receive` (as *ops* —
the `net.listen` effect itself is minted by `http.serve`),
`code.eval`/`format`/`lint`/`parse`/`run`/`compile`, and
`proc.kill`/`wait`/`signal`/`pid`. Every recognized `observe`, `event`, `config`,
`memory`, `env`, `ui`, and `package` op maps to its namespace row above. A few
namespaces perform their effect check *inside* the operation rather than at
dispatch, after validating the resource: `skills.load`/`dir` (scoped `fs.read`),
`lean.check` (resource-tagged `proc.run`), and the `python.*` bridge (scoped
`ffi.call`). Intentionally *dynamic* namespaces (`log` by level, `tools`/`mcp`/
`skills`/`stream` by name) stay open by design.

## `model`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `model.invoke` | `generate`, `generate_batch`, `generate_stream`, `caption`, `ocr`, `vqa`, `transcribe`, `transcribe_stream`; `semantic.*` verbs (all except the embed-backed three); `code.gen`; multimodal message routing (a text model that "sees"/"hears"); `simulate def … by`, the `~` operator family, `check`/`ensure semantics(…)` | Checked at the model seam per call. Governance capability `sema.effect.model`. Taint **source**. |
| `model.embed` | `embed(...)`; `semantic.similar`/`cluster`/`dedup`; `~=` when a type coerces via embedding | Checked at the model seam per call. `sema.effect.model`. Taint **source**. |
| `model.load` | Loading real model weights through the config registry (`[models]` pointing at files) | Checked before the backend loads the artifact. `sema.effect.model`. Taint **source**. |

## `fs`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `fs.read` | `fs.read`/`read_text`/`read_json`/`list`/`exists`/`is_dir`/`is_file`; `path.exists`; `io.read_file`/`read`/`lines`/`exists`; `csv.read_rows`; `json.parse`/`read`/`items`; `yaml.parse`/`read`; `file_sha256`; skill loads (`skills.load`/`skills.dir`) | Checked per operation, confined to the project root. Skill loads are **instance-scoped**: the declared `fs.read("path")` scope must admit the canonicalized skill path. Capability `sema.effect.fs.read`. |
| `fs.write` | `fs.write`/`write_text`/`append`/`remove`/`delete`/`mkdir`/`copy`/`move`/`rename`; `io.write_file`/`write` | Checked per operation, confined to the project root. Capability `sema.effect.fs.write`. |

## `net`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `net.connect` | `net.connect`/`get`/`post`/`put`/`patch`/`delete`/`head`/`request`/`fetch`; `service` remote calls; model-scheduler remote endpoints | Checked per operation **plus per endpoint**: every URL/host passes `check_endpoint` against scoped policy instances (`net.connect("host")` rules); redirects are never followed past authorization (redirect hops re-check). Capability `sema.effect.net`. Taint **source**. |
| `net.listen` | `http.serve(port, handler)` | Checked at bind. Capability `sema.effect.net.listen`. |

## `proc`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `proc.run` | `proc.run`/`spawn`/`exec`/`shell` (spawn/exec/shell canonicalize to `proc.run`); `lean.check` (resource-tagged discovery + pinned execution checks) | Checked per operation; `lean.check` passes an explicit resource identity. Capability `sema.effect.exec`. Taint **sink**; under governance the destructive-command denylist and the OS sandbox apply. |

## `code`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `code.exec` | `code.exec`; running staged `Code[T]` values | Staged code runs are **instance-scoped**: `code.exec("sandbox")` must admit the code value's sandbox. Capability `sema.effect.exec`. Taint **sink**. |
| `code.patch` | `code.patch`/`hotpatch`/`reload`/`revert`; `supervise`/`heal` applied patches | Checked per operation; `code.hotpatch` additionally requires `[heal] apply != "staged"` (denied + journaled otherwise). Capability `sema.effect.code.patch`. Taint **sink**. |
| *(note)* | `code.gen` maps to `model.invoke` — generating code is a model call; only executing or patching it needs `code.*` authority. | |

## `db`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `db.read` | `db.query`/`read`/`select`/`count`; typed `sql"…"` SELECTs | Checked per operation. Capability `sema.effect.db.read`. |
| `db.write` | `db.exec`/`write`/`run`/`insert`/`clear`/`drop`; typed `sql"…"` writes | Checked per operation. Capability `sema.effect.db.write`. |
| *(note)* | `db.schema` is §3.6 vocabulary reserved for schema migration; no runtime operation maps to it yet. | |

## `env`, `memory`, `config`, `clock`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `env.read` | `env.var`/`get`/`read`/`has`/`all` | Checked per operation. Not in the benign set — a governed posture must grant it. |
| `env.write` | `env.set`/`unset` | Checked per operation. Not in the benign set. |
| `memory.read` | `memory.get`/`recall`/`query`/`has`/`keys`/`list`/`search` | Checked per operation. **Benign** (auto-granted). |
| `memory.write` | `memory.set`/`put`/`store`/`retain`/`delete`/`remove`/`forget`/`clear` | Checked per operation. **Benign**. |
| `config.read` | all `config.*` reads (`get`/`model`/`temperature`/`set`/`has`/`all`) | Checked per operation (the §3.6 `config.reload`/`config.watch` vocabulary canonicalizes here today). **Benign**. |
| `clock.read` | `clock.wall_s`/`wall_now`/`wall_ms`/`mono_ms` (`clock.now` is the fixed deterministic epoch and needs no grant) | Checked per operation. **Benign**. |

## `observe`, `event`, `ui`, `human`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `observe.record` | every `observe.*` op; `log.*` at any level; `collector` channels and the `\|>` tap; `monitor` declarations | Check is **deferred-recorded** (journal-backed telemetry *is* the sink). **Benign**. `observe.export` is §3.6 vocabulary; observe ops canonicalize to `observe.record` today. |
| `event.emit` | `emit` statements and `event.*` ops | Checked per delivery, policy-checked and journaled. **Benign** (as is the reserved `event.subscribe`). |
| `ui.render` | `ui.render`/`show`/`print`/`display`/`update`; `io.print`/`println`/`print_line` | Checked per operation. **Benign**. |
| `ui.notify` | `ui.notify`/`alert`; `io.eprint`/`error` | Checked per operation. **Benign**. |
| `human.approve` | `ui.prompt`/`ui.input` — interactive human input *is* the approval surface | Checked per operation; endorsing untrusted data to `trusted` (§3.5) and posture approval-sets route through it. Headless approval-required checks **fail closed to deny**. |

## `ffi`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `ffi.call` | `python.import`/`call`/`method`/`attr`/`str`/`free` (the persistent Python worker); `tools.*` and `mcp.*` (tool/MCP servers are foreign calls); `native import`/`bridge` extern calls (C, JS) | Bridge calls are **instance-scoped**: Python-worker and C/JS extern calls check a scoped resource identity (`python:v1:…`, `c:v1:bridge=…:member=…`) against the declared row instances and policy allows. `tools.*`/`mcp.*` are checked at **path level** (`ffi.call`). Capability `sema.effect.ffi`. Taint **source**. |

## `agent`, `package`, `policy`

| Effect path | Granting operations | Enforcement |
|---|---|---|
| `agent.spawn` | the `spawn` expression (agents and durable circuits); running a staged `Code` value with an agent entry | Checked at spawn; `sema check` requires `agent.spawn` declared on functions that spawn, and policy `examples:` verification covers the `agent` namespace. Capability `sema.effect.agent.spawn`. |
| `package.install` | all `package.*` ops (`install`/`remove`/`add`/`update`/`upgrade`/`search`/`list`) | Checked per operation. Capability `package.install`. |
| `policy.change` | policy administration (installing/widening a policy) | **Danger floor**: no posture or program policy may permit past it — policy change is a distinguished, human-approved transaction ([Policy](/governance/policy/)). |

## Vocabulary without a runtime surface yet

`random` is canonical §3.6 vocabulary, but no runtime operation maps to it today:
the tier-0 engine is deterministic and seeded, so there is no ambient randomness
to gate. `db.schema`, `observe.export`, `config.reload`, and `config.watch` are
likewise reserved spellings that today canonicalize onto (or await) their
namespace's enforced paths, as noted above. Declaring them in a row is legal —
rows are open — and they journal as declared.

## Custom capabilities — the row vocabulary is open

The catalog above is the built-in vocabulary, not a closed set: a row may declare
namespaces the runtime has never heard of — `!{mysql.query}` parses, is
containment-checked, and journals like any built-in path. A custom effect is a
**marker**: there is no namespace object behind it (`mysql.query(...)` in a body
is a `NameError`), so mint one with the **wrapper-module pattern** — a connector
module whose public defs carry the custom effect *plus* the real underlying
effects. Callers transitively need BOTH labels, and a policy can deny either:

```sema
# payments.sema — the connector module is the only place the label is minted.
def payments_read(account: str) -> list[dict] !{payments.read, db.read}:
    return db.query("SELECT amount, account FROM payments WHERE account = ?", [account])

# main.sema
from payments import payments_read

policy NoPaymentReads:
    forbid cap:
        payments.read
    justification "auditors may not touch payment rows in this scope"

def audit_exposure(account: str) -> int !{payments.read, db.read}:
    return len(payments_read(account))

def main() -> None !{payments.read, db.read, db.write, observe.record, ui.render}:
    db.exec("CREATE TABLE IF NOT EXISTS payments (account TEXT, amount REAL)")
    db.insert("payments", {"account": "acct-1", "amount": 12.5})
    log.info("payments visible", rows=audit_exposure("acct-1"))
    with policy(NoPaymentReads):
        expect n = audit_exposure("acct-1"):
            log.info("policy failed to bite", rows=n)
        except Denied as d:
            # "policy NoPaymentReads denies effect payments.read in
            #  audit_exposure(): forbidden capability"
            log.info("denied as designed", why=d.message)
```

A caller whose row omits `payments.read` is rejected by `sema check` (`call to
payments_read requires undeclared effect(s) payments.read`) and denied by the
runtime's containment check. Two honest boundaries: effect vocabulary is
authority **labeling**, not OS-level confinement — an `fs.write` holder cannot be
kept away from database *files* by effect kind alone; use scoped instances plus
governance postures and the OS sandbox for confinement. And `sema check` lints
near-misses of *built-in* namespaces (`!{fss.read}` → "did you mean `fs`?") while
genuinely distinct custom names stay clean by design.

## The enforcement model, honestly

Effects are enforced by five cooperating layers. Every native boundary performs a
per-operation check (`check_effect_op`) against the active function row before
doing real work. Caller containment is enforced twice: `sema check` rejects a
call whose callee's declared row exceeds the caller's, and the runtime re-checks
the callee row at every call so unchecked entry points cannot launder authority.
Active policies deny by path (`forbidden capability` / `not in the policy allow
set`), journaling every verdict. Scoped *instance* enforcement applies where
resources have identities — `net` endpoints, skill file loads, staged `code.exec`
sandboxes, and `ffi.call` bridge members — everything else is path-level.
Governance adds what labels cannot: posture allow-sets over the capability map,
the untrusted-source-to-exec-sink taint watermark, the destructive-command
denylist, and the OS sandbox for governed exec.

## See also

- [Effects & Capabilities](/governance/effects/) — granting and confining authority.
- [Functions & Effects](/language/functions-and-effects/) — how rows are written and inferred.
- [Declarations quick reference](/quick/declarations/) — row syntax at a glance.
- [Policy](/governance/policy/) — the full `policy` construct.
- [CLI reference](/reference/cli/) — `sema check` (row discipline) and `sema assure --grade silver` (explicit rows required).
