> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uselayerup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Action Plane

> The only path from a Decision to a mutation of a system of record. Every effect is typed, idempotent, approved, audited, and reversible. The threshold between AI suggestion and governed agency.

# 14 — Action plane — lifecycle, idempotency & compensation.

The Action Plane is the only path from a Decision to a mutation of a system of record. It
is opinionated: every effect is typed, idempotent, approved, audited, and reversible
(forward or compensating). This is the threshold between AI suggestion and governed agency.

## 14.1  Action lifecycle

```mermaid theme={null}
stateDiagram-v2
  [*] --> proposed
  proposed --> staged: tool.stage(args, idemKey)
  staged --> approved: policy.auto | human.approve
  staged --> rejected: human.deny | policy.deny
  approved --> committing: dispatcher.start
  committing --> committed: adapter.success
  committing --> failed:    adapter.error
  committed --> reverted:   compensation.committed
  rejected --> [*]
  failed --> [*]
  reverted --> [*]
  committed --> [*]
```

*Fig. 14.1 — Action state machine. Every transition is a typed AuditEvent.*

## 14.2  State semantics

| State        | Meaning                                                                                               | Visible?                         |
| ------------ | ----------------------------------------------------------------------------------------------------- | -------------------------------- |
| `proposed`   | Reasoning has produced a Decision; an Action object draft exists but no staging tool has been called. | internal only                    |
| `staged`     | Action is registered with idempotency key, attached to a Decision, awaiting approval.                 | visible to operators & reviewers |
| `approved`   | Approval policy satisfied (auto-approval rule or human approval). Ready to commit.                    | visible                          |
| `committing` | Dispatcher is talking to the SoR adapter.                                                             | visible                          |
| `committed`  | SoR confirmed the effect and returned a receipt.                                                      | visible & persistent             |
| `rejected`   | Approval denied by policy or human.                                                                   | visible                          |
| `failed`     | SoR adapter failed; subject to retry per policy.                                                      | visible                          |
| `reverted`   | A compensating action committed.                                                                      | visible                          |

## 14.3  Idempotency key construction

Idempotency keys are deterministic over the action's *intent*, not its execution. A
replay of the same intent — even from a different run, a different reviewer, or a different
agent revision — must commit at most once.

```text theme={null}
k = sha256(
      tenantId
    · actionKind             // e.g. "claim.exposure.reserve.set"
    · targetSor               // e.g. "policy_admin"
    · targetRefHash           // hash of canonical target reference
    · payloadCanonical        // canonical JSON of payload
    · ontologyPin
)
```

Where `payloadCanonical` is RFC-8785 JCS-canonicalised. The platform never
commits twice with the same `k`; the second commit returns the first commit's
receipt unchanged.

## 14.4  Approval policy

Approval is per *(actionKind, severity, marking, principal)*. The platform supports four approval modes:

| Mode                | Trigger                                                                   | Audit signature          |
| ------------------- | ------------------------------------------------------------------------- | ------------------------ |
| **auto**            | Action kind, principal scopes, marking and policy all permit auto-commit. | `action.approval.auto`   |
| **human-in-review** | Approval Task created; human approver must commit before timeout.         | `action.approval.human`  |
| **quorum**          | N-of-M reviewers must approve; commonly N=2 for high-effect actions.      | `action.approval.quorum` |
| **chain**           | Sequential approval through a fixed chain (e.g. authority escalation).    | `action.approval.chain`  |

## 14.5  Pre-commit reality arbitration

Before `committing`, the dispatcher performs a fixed sequence of checks. Any failure aborts the commit and raises a typed Exception.

1. Target object still exists in the SoR at the version observed when the Action was staged (optimistic concurrency).
2. No subsequent reviewer or agent has changed the same object in a way that invalidates the staged Action's preconditions.
3. The staged Action's marking and purpose still pass the PDP.
4. The Action is unique under its idempotency key (no prior commit).
5. The principal's authority still covers this Action (authority limits not breached at commit time).

## 14.6  Adapter strategies

The Action Plane writes to systems of record through pluggable adapters. Two strategies are supported:

<CardGroup cols={2}>
  <Card title="Adapter calls a SoR API in real-time" icon="bolt">
    **Transactional** — Synchronous request/response (or async with a callback). Receipt is the SoR's confirmation. Most policy admin / claims / billing systems support this.
  </Card>

  <Card title="Adapter writes to a file drop or batch queue" icon="file">
    **Flat-file / batch** — Used when the SoR has no real-time API. Receipt is the file/batch identifier; eventual confirmation arrives via the standard pull adapter (§7) and is correlated by idempotency key.
  </Card>
</CardGroup>

<Note>
  Adapter selection is a tenant configuration. Both strategies enforce idempotency; the
  difference is only in latency and how the receipt is materialised.
</Note>

## 14.7  Compensation algebra

Reversal is typed. The platform refuses to "undo" a committed Action by mutation; reversal is always a separate, named compensating Action.

| Original action               | Compensating action           | Notes                                                      |
| ----------------------------- | ----------------------------- | ---------------------------------------------------------- |
| create \<X>                   | cancel \<X> or void \<X>      | SoR-specific; never a hard delete unless the SoR offers it |
| update \<X> from v\_a to v\_b | update \<X> from v\_b to v\_a | Pre-commit arbitration must verify v\_b still active       |
| commit transfer of value      | reverse transfer of value     | For payments: refund / chargeback / reverse-payment        |
| set state to S                | set state to prior\_state(S)  | State machines must declare reversible transitions         |

The pair *(Action, CompensatingAction)* is recorded together in lineage; the
original Action's `compensatedBy` field is set on commit of the reversal.

## 14.8  Reversal vs supersession

* **Reversal** — the prior effect is undone; nothing replaces it. Used when the original Action was wrong.
* **Supersession** — the prior effect is replaced by a new effect; both are recorded; the prior is marked `superseded` but not `reverted`. Used when the underlying Decision was correct but circumstances changed.

## 14.9  Batch commit semantics

Some Actions are batched (file drops, end-of-day uploads). The platform treats a batch as a typed object with its own state machine; per-record receipts are matched back by idempotency key. Partial batch failures produce typed Exceptions per record; successful records remain `committed`.

## 14.10  Action observability

* Every state transition emits an AuditEvent and a span.
* Metrics: *staging rate, approval rate, auto-approval ratio, reversal rate, time-to-commit p50/p99, adapter error class distribution*.
* SLO: time from `approved` to `committed` — per adapter strategy.
