# Evolution 3 — predictive consequence governance: architecture

```
invoke(request, PoP)
  decide()                      E1/E2 pure decision (state, validity, RIG authority, model, environment, policy, PoP, conditions)
    │ ALLOW only
  forecast()                    ContractForecaster (models below) -> ConsequenceForecast (integer bp, CJ1)
  gate()  PURE + MONOTONE       ALLOW -> ALLOW | DENY(FORECAST_* / AUTONOMY_BUDGET_*);  DENY -> same DENY
    │ ALLOW only
  [quorum USE certificate]      (Evolution 2, in-process replicas only)
  spend use + nonce + autonomy budget, signed DECISION receipt (forecast_digest, verdict, policy digest, budget_before)
  E8 commit                     binding += forecast_digest + forecast_state_digest(state version, model set, valid-now)
                                -> a forecast-policy change, model change, validity expiry, RIG/policy/epoch change refuses
  product runs inside E8        exec: cwd snapshot before/after (real observation)
  OUTCOME receipt               prediction_error {class, brier_bp, divergence, observation_digest, corpus entry hash}
  corpus (hash-chained)  ──►    history model (raise-only, n >= 10), drift (two-proportion z), calibration
  divergence + policy=revoke ►  contract REVOKED ("the old authorization must not continue")
```

## Forecast (`cain.contract.forecast.v1`)
- **Consequence vector:** all 19 dimensions are always present. Each one is MODELED (impact, probability,
  time-to-effect, reversibility, horizon at T+0/T+300/T+86400, expected value, models, evidence, and optionally a
  mitigation with residual impact), or NOT_MODELED, or NOT_APPLICABLE. Nothing unmeasured is ever 0.
- **Uncertainty:** aleatoric, epistemic, model, data, environment, distribution_shift, sensor, dependency and
  execution. Each is a measured bp value, UNQUANTIFIED or NOT_APPLICABLE.
- **Blast radius:**
  - KNOWN: the target;
  - LIKELY: RIG-authorized memory readers and network endpoints;
  - POSSIBLE: delegated RIG descendants, sandbox-writable state and the delegation chain;
  - UNKNOWN: arbitrary code and remote effects.
  It is bounded (depth 3, 64 readers) and labelled `completeness: NOT_ASSUMED`.
- **Validity:** 30 s, plus a state version (authority, policy, environment, runtime, epoch, forecast-policy digest
  and version). `model_set_digest` covers every model's version and parameter digest.

## Models (`MODELS`, profiles with known failure modes)
| Model | Basis |
|---|---|
| `exec_effect@1` | argv effect-class table (read/write/delete/network/privilege/process/interpreter/unknown) |
| `memory_propagation@1` | MemVault `scan()` (rules + held-out-measured classifier) × RIG-reachable readers; quarantine as the mitigation |
| `evidence@1` | append-only log consequences |
| `history_frequency@1` | the tenant's corpus: Beta posterior, **raise-only**, n ≥ 10 |

The ensemble merge is a per-dimension max, and a mitigation counts only if every model saw it. Agreement never lowers
risk.

## Policy and budget
The tenant forecast policy is operator-only to change, and agent keys are refused. It holds:
- enforce/observe mode;
- per-dimension expected-impact limits;
- an unquantified-high-impact rule;
- a drift rule;
- a budget per agent per window (overrides are a list);
- `on_material_divergence` (revoke/record).

The budget is spent in the decision transaction, so blue and green share it (multi-process test). An agent cannot
raise its own budget, and no prediction can raise it either.

## Counterfactuals (SIMULATED)
`forecast_preview` / `POST /fabric/contracts/forecast` returns the forecast and seven variants:
as_requested, not_executed, later_after_revocation_window, reduced_capability, stronger_policy,
degraded_environment and compromised_dependency. It spends nothing and records nothing. `invoke()` never consumes a
preview.

## Verification
- `scripts/contract_verify_offline.py` (no CAIN imports) re-derives the forecast structure and arithmetic, the gate
  verdict, the forecast, policy and budget bindings in the signed receipt, and the forecast in the ALLOW binding. It
  also checks the structure of `prediction_error`.
- It does **not** verify that a forecast was right about the world.
