CX · Reference guideCommands and effects
PlaygroundDownloadsAboutv0.17.0

Commands and effects

A command is a def that declares its effects

Most CX definitions are pure. The ones that change the world — refund an order, send an email, advance a ref — are commands, and a command is not a new kind of thing: it is an ordinary [?def] carrying an [effects] clause. That clause is the discriminator; everything else in this section hangs off it.

      [?def refund-order impure ($order-id $amount)
        [requires cap:sha2-256:1f4b…]     [; the authority artifact it needs ]
        [preconditions [order-exists $order-id] [not-already-refunded $order-id]]
        [effects [write "orders"] [net "payments.example"]]
        [idempotent [window P30D]]
        [compensates cancel-refund]
        …body…]
    

Two rules make the declaration worth reading. First, pure plus a non-empty [effects] is a static contradiction — a typed error at definition time, not a runtime surprise. Second, [effects] is checked and enforced, never advisory: each item is a [CAP scope…] pair whose capability name comes from the closed table in spec/03-approved/core/security.md §2 (read, write, net, env, clock, random, subprocess, eval, secret-reveal), an unknown name is a fail-closed refusal, and at runtime the declared set acts as a narrowing — an effect point outside the declaration is a loud typed error, exactly as if the capability had been denied. The house sentence: effect conformance is enforced; type conformance is advisory.

Effects and capabilities compose but differ in direction. A capability grant (see capabilities) is the caller saying what a run may reach. An [effects] clause is the author saying what this command will do — and the runtime holds them to it. The narrower of the two always wins.

Idempotency — retry-safe by declaration

Networks retry. The question is never whether a refund request will arrive twice, but what happens when it does. A command with an [idempotent] clause deduplicates at the effect boundary; a command without one is not idempotent and not retry-safe — deny-by-default, like everything else.

The key. An explicit caller key wins when present — only the caller knows that two structurally identical requests are distinct business events. The derived default is a hash of the command's identity, the argument record normalized by parameter name, and the tenant. Name-keying matters: the positional and named spellings of the same refund must produce one key, or the retry double-executes — the sharpest trap in this design space. Deliberately not in the key: the capability set (the same refund under a wider grant is the same refund) and the authority chain (recorded for audit, never keyed).

The commit. Dedup is enforced with a must-not-exist compare-and-set on the dedup record — the same one-conflict vocabulary refs use (see value-model), applied as exactly-once-create at the effect boundary. A dedup hit does not error and does not vanish into an absence: it returns a present value carrying the original outcome plus a deduped=true marker — \"already done; here is what happened.\"

The window. Dedup records are journal-backed facts with a declared retention window, and compaction may not reap one before its window expires — a dedup record that silently disappears is a reopened double-execution hole. Within the window, [?retry] around a declared-idempotent command is safe by construction; the delivery substrate stays honestly at-least-once (see consistency for why exactly-once delivery is refused as a vocabulary word).

Budgets — quantitative authority

Every other attenuation in the authority model is spatial — which capabilities, which slice, which time window. A budget is the quantitative fourth axis: how much. It rides on a delegation as a [bounds] child.

      [bounds [rate 10 :per PT1M]                 token bucket
               [count 500]                          monotone, no refill
               [spend 250.00::decimal :currency :USD :per P1D]]
    

Enforcement is placed where it cannot race: the debit happens at the commit point, under the journal stream's commit lock, so the meter is linearizable for free. The policy check reads the meter as part of its materialized snapshot, so authorization stays a pure function over declared inputs — dry-runs stay regression-testable. Exhaustion is a value ([deny [reason :budget-exhausted] [retry-after …]]), not a crash.

  • Refunds do not credit back. Budgets meter authority exercised, not net economic effect — undoing an action does not un-spend the authority that took it.
  • Sub-delegation shares the meter by default. A pool never multiplies authority; ten sub-agents of a $250/day delegation share $250/day. A sub-delegation may carry a reserved allocation drawn from the parent's meter at delegation time — escrow, not multiplication.
  • Bounds and scopes are independent conjuncts. A bound never widens a scope; a scope never relaxes a bound; a denial names the failing conjunct.
  • Spend windows are UTC-calendar-aligned — no tenant-local midnight surprises.

Propose mode — approval binds the address

At a trust boundary — an agent tool call, an MCP edge, a propose-only delegation — a command does not execute. It produces a proposal: an ordinary CX value capturing the exact definition (by content address of its source text), the name-keyed argument record, the resolved effect set, the evaluated preconditions, the authority chain, and the idempotency key. Being a value, the proposal has an address.

Approval is a signed claim binding that address — a Lane-2 value about the proposal, never a nod to a name or an argument list. Approving by name or args is forgeable; approving an address means any re-lowering, rewording, or effect-widening produces a different address and needs its own approval. At commit, live preconditions re-evaluate, and divergence from what was approved is a loud refusal — some facts bind at propose time, live facts re-check at commit time.

The mode is decided by the boundary, not the caller: an agent-tool edge always proposes, and a delegation can carry a propose-only flag — the grant that lets an agent draft actions all day and commit none of them. The campaign story this enables: \"you have hand-approved thirty sub-$50 refunds — delegate that band?\" is a propose-mode history turning into a budget-bounded delegation, with every step of the transition auditable.

The pieces compose into one auditable pipeline: an agent holding a propose-only, budget-bounded delegation proposes a $42 refund; a principal approves the proposal's address; commit re-checks preconditions, debits the spend meter under the stream's lock, deduplicates by key, and the journal records actor and authority chain. Every noun in that sentence is a CX value with a content address.