# Evolution 16 — recovery-aware execution specification

## Action classes

Derived by the runtime (`recovery_class`) from the signed plan and operator configuration, never from the agent.

| Class | Derived from | Dispatch needs | After an unknown outcome | Compensation |
|---|---|---|---|---|
| READ_ONLY | plan says `READ_ONLY` and no external side effect | admission | may be dispatched again, same key, up to `max_attempts` | none |
| IDEMPOTENT_WRITE | the operator listed `target_system:operation` as honouring idempotency keys | admission | may be dispatched again with the **same** key | as the plan declares |
| REVERSIBLE | plan | admission | **not** dispatched again; needs an observation | allowed |
| COMPENSATABLE | plan | admission | **not** dispatched again; needs an observation | allowed, separately authorized |
| IRREVERSIBLE | plan says so, **or** anything unknown | admission including a human approval (existing supervisor rule) | **not** dispatched again; needs an observation | **refused**; handled as an incident |

IDEMPOTENT_WRITE is only as good as the operator's statement that the target really deduplicates on the key.

## Transaction states

```
(admitted) ─execute─▶ INTENT ─result────▶ REPORTED ─observer: matches──▶ CONFIRMED
                        │                     └─────observer: mismatch─▶ CONTRADICTED
                        ├─timeout/error/crash─▶ AMBIGUOUS ─observer: present──▶ CONFIRMED
                        │                          ├────────observer: ABSENT───▶ NOT_APPLIED ─(new admission)─▶ INTENT
                        │                          └────────retry (READ_ONLY / IDEMPOTENT_WRITE only)──────────▶ INTENT
                        └─executor: nothing sent (repeatable classes only)─▶ NOT_APPLIED
CONFIRMED ─pinned observer contradicts─▶ CONTRADICTED
CONFIRMED | CONTRADICTED | REPORTED | AMBIGUOUS ─compensate (own authorization)─▶ COMP_INTENT
COMP_INTENT ─▶ COMP_REPORTED | COMP_AMBIGUOUS ─observer: undone─▶ COMPENSATED
                                              └observer: not undone─▶ COMPENSATION_FAILED
```

Unresolved (block completion): INTENT, AMBIGUOUS, REPORTED, CONTRADICTED, COMP_INTENT, COMP_REPORTED, COMP_AMBIGUOUS,
COMPENSATION_FAILED. Resolved: CONFIRMED, COMPENSATED, NOT_APPLIED.

## Dispatch (`execute`)

Refused, with a journaled `TX_REFUSED`, unless all hold at that moment: the action is in the plan; the mission is not
cancelled or suspended; the action is not already executed and has no unresolved outcome (except a retry of a
repeatable class); an admission exists and was made under the current contract version for this exact plan action; the
mission and the authorization have not expired; the authorization is not revoked; the agent's delegation chain is live
and covers the action.

Then: `TX_INTENT` is forced to disk **before** the executor is called. The idempotency key is
`SHA-256(mission_id, action_id, canonical action digest, authorization id)`: stable across retries of one admission,
different after a new admission.

The executor's return is a **report**. `NoEffect` from the executor is accepted for repeatable classes only; for the
others the executor's word does not establish absence and the outcome is AMBIGUOUS. Any other exception is AMBIGUOUS.

## Recovery

On start, an `INTENT` with no result becomes `AMBIGUOUS` (reason `RECOVERED_INTENT_WITHOUT_RESULT`); a `COMP_INTENT`
with no result becomes `COMP_AMBIGUOUS`. Nothing is dispatched by recovery. An `INPUT` with no `DECISION` is decided
(replay is deterministic and has no external effect).

## Reconciliation

Only an observation signed by a pinned observer changes an unknown outcome: present → CONFIRMED; `observed="ABSENT"`
→ NOT_APPLIED, the reservation is released and the action may be admitted again with a **new** authorization. An
observation for an action with no open dispatch is refused (an effect arrived that the runtime never dispatched).

## Compensation

A new consequential action. Needs an authorization signed by a pinned issuer for
`digest(COMP-ACTION, original action digest, compensation action id)`, unexpired and never used. Journaled like a
dispatch. Complete only on a pinned observer's confirmation; otherwise `COMPENSATION_FAILED` and
`represents_successful_rollback: false`. Allowed after cancellation (cleanup is not a new forward action).

## What this does not do

It does not undo an email, a settled payment, a disclosure or any other irreversible effect, and never reports one as
rolled back. It does not make two systems atomic. It does not prevent a duplicate effect if the target ignores the
idempotency key **and** a pinned observer wrongly reports absence (scenario
`evidence_misleading_but_correctly_signed_observation`). The executor runs while the runtime holds its lock, so
dispatches are serial. There is no automatic incident workflow: an unresolved transaction stays unresolved until an
observation or a compensation settles it.
