# Evolution 16 — architecture

## What was there, and what was missing

| Piece | Where | State before Evolution 16 |
|---|---|---|
| Mission specification, plan, budget, delegation graph, memory, supervisor | `cain/mission_control/` (Evolution 8) | implemented, in memory |
| One admission path over all of them | `governed_runtime.py` (Evolution 15) | implemented, in memory; state lost on restart (U15-02) |
| Durable multi-service workflow coordinator | `cain/execution_chain/coordinator.py` (Evolution 10) | implemented (SQLite); not connected to the governed runtime; re-executed a step after an unknown outcome (F16-01) |
| Compensation rules | `recovery.py` (Evolution 8) | implemented, in memory |
| Skill admission lifecycle | `cain/governed_evolution/`, `cain45/l5/adaptive_governance.py` | implemented |
| Independent verifier for runtime decisions | — | missing (U15-03, Evolution 15 gate J) |
| A way to change a running mission's contract | — | missing |
| A record that an admitted action was dispatched | — | missing: admission was the last step the runtime saw |

Evolution 16 adds one module around the existing runtime and one separate program. No new moat, no second decision
engine, no change to how an admission is decided.

```
 agent ──signed request──▶ ┌──────────────────────── DurableMissionRuntime ───────────────────────┐
 human ──signed approval─▶ │  1 append INPUT (hash-chained, signed, fsync)                          │
 observer ─signed obs.───▶ │  2 Evolution 16 rules: cancelled? expired? stale evidence? used auth?  │
                           │  3 GovernedTaskRuntime (Evolution 15) decides, under the entry's clock │
                           │  4 append DECISION (digest of the decision)                            │
                           │                                                                        │
 caller ─execute(action)─▶ │  re-check: admission bound to this contract version, authorization     │
                           │  unexpired and unrevoked, delegation chain live, not cancelled         │
                           │  append TX_INTENT (idempotency key) ─▶ executor(action, key) ─▶ target │
                           │  append TX_RESULT | TX_AMBIGUOUS                                       │
                           └───────────────┬────────────────────────────────────────────────────────┘
                                           │ mission.journal.jsonl  + head held by a witness
                                           ▼
                              cain-mission-journal-verify/verify.py   (no CAIN imports; pinned public keys)
                              VERIFIED | FAILED | INCOMPLETE | UNSUPPORTED | UNAVAILABLE
```

## Components

**Journal** (`MissionJournal`). JSON lines. Entry *n* holds `seq`, the hash of entry *n-1*, `kind`, `at`, `body`, its
own hash and the runtime key's Ed25519 signature. An append returns after `fsync`. One writer: the file is held under
an exclusive `flock`. A partial last line was never acknowledged and is dropped on load; any other defect refuses to
load.

**Replay** (`_replay`). The runtime is rebuilt from the genesis entry and every `INPUT` is applied again under the time
recorded in that entry (`frozen_clock`). The recomputed decision is hashed and compared with the `DECISION` entry.
A difference raises `RecoveryDivergence` and the runtime does not start. The pinned keys are configuration, not journal
content: if they differ from the digest in genesis, `TrustChanged`.

**Contract succession** (`update_mission`, `classify_mission_update`). See `mission_contract_spec.md`.

**Transactions** (`execute`, `reconcile_absent`, `compensate`, `confirm_compensation`). See
`recovery_execution_spec.md`.

**Verifier** (`cain-mission-journal-verify/verify.py`). A separate file that imports only the standard library and
`cryptography`. It has its own canonicalisation, its own reading of what widens a contract, its own transaction state
machine and its own delegation-liveness check.

## Constitution, as properties with a test

| Invariant | Where it is enforced in Evolution 16 | Test |
|---|---|---|
| Agent proposes | only requests signed by the pinned agent key are applied; the verifier re-checks the signature of every admitted request | `admission.request_signed_by_plan_agent` |
| CAIN decides | the decision comes from the unchanged Evolution 15 runtime; Evolution 16 rules only add refusals | mutation M16-01..25 (each rule removed in turn) |
| MCPGate enforces / system executes | **not wired**: `execute()` calls an executor the caller supplies. The MCPGate boundary is not connected to this journal | open, see limitations |
| Evidence remembers | every input, decision, intent and result is in the journal; the verifier recomputes from it | 15 evidence scenarios |
| No authorization, no execution | no `TX_INTENT` without a live admission bound to the current contract version | `dispatch.admitted_first`, exploration I2/I3 |
| No component grants itself authority | the runtime key signs the journal only; missions, plans, authorizations, approvals and observations are verified against other pinned keys; a widening needs a key that is not the mission authority's | `widening_update_without_the_principal` |

## What is real, simulated, or absent

| | Status |
|---|---|
| Runtime, journal, verifier, tests | implemented and executed locally |
| Target system, observers, agents | **simulated** in the lab (in-process objects; all keys in one process) |
| Language model in the loop | **absent** |
| Connection to MCPGate, to the hosted gateway, to the Evolution 10 coordinator or Evolution 14 state service | **absent** |
| Multi-node or Byzantine operation | **absent**: one process, one file. No Byzantine claim is made |
| Independent reproduction, external review, production deployment, customer use | **absent** |
