Concepts
Governed actions
A model may propose an action. Fixed rules check it and name the fact that decides. The owner approves, then releases it. The provider's receipt and the observed outcome are kept apart, because they prove different things.
The lifecycle
| Step | Who | What it records |
|---|---|---|
| Propose | Model or person | A proposal with an evidence snapshot and an idempotency key |
| Check | Fixed rules | Admit, refuse or undecidable, with the deciding fact |
| Approve | Owner | An approval bound to exactly the evidence the owner saw |
| Release | Owner | The execution, run under a lock |
| Receipt | Provider | That the call was accepted |
| Outcome | Independent source | That the business changed |
Rules never guess
evaluate_action resolves the subjects to canonical objects, reads the permitted evidence as of now, and returns admit, refuse or undecidable. Each failed rule names the fact, operator, expected and observed values, and the observation that decided it.
"failed_rules": [{ "fact": "Supplier.active", "op": "eq", "expected": true, "observed": false,
"observation_id": "d9bf393f-…" }]
Missing or stale evidence is undecidable. assess_action is the read-only form that scans a bounded set of candidates and never proposes.
Human authority
Proposer and approver roles are declared per action. Agents inherit the proposer's role and cannot hold an approver role. There is no auto-approval path.
States
proposed, approved, executing, executed, refused, uncertain, failed_no_effect. An execution interrupted by a crash is recovered at startup as uncertain, and a late receipt is recorded as its own event.
Note Effects run through an operator-configured HTTP gateway adapter with an idempotency key, or the no-network demo gateway. Connector-executed actions are on a development branch.