# Decision Memo state transitions v0.2 Actors: `requester`, `assignee` (current ready step), `party` (any listed party), `subject` (session principal after bind), `system`, `agent`. Guards: | Id | Meaning | |---|---| | G_STEP | Verb is in `route.steps[current].required_verbs` **or** is a always-on overlay verb for that step kind (table B) | | G_PRES | `presentation_id` exists, `memo_version` matches, `phase` is `pre_bind` or `bind` | | G_ACK | All `highlights[required_ack=true]` are in `presentation.acked_highlight_ids` | | G_MAND | Actor mandate covers `requested_act` + legal/value constraints | | G_LEVEL | Actor signature meets `step.min_binding_level` and memo `binding_level` | | G_REASONS | `return.reasons` has ≥1 coded reason | | G_TARGET | `transfer.to` is a resolvable party with compatible mandate | | G_ESC | Target mandate is *strictly higher* than current assignee for this act | | G_NOAGENT | `actor.kind ≠ agent` | | G_SESSION | `session.status = active` and actor is `session` subject | | G_HAT | `configure.hat.id` ∈ `awareness.available_hats` and `hat.elevates = false` | | G_PROMOTE | Field moved from awareness → binding; new memo version; presentations invalidated | Overlay verbs (always available when status allows, even if not in `required_verbs`): `comment`, `discuss`. Requester-only overlay: `withdraw` while not terminal. System-only: `stamp`, expiry. ## A. Memo-level status machine ``` submit draft ──────────────► submitted ▲ │ │ │ route.started │ edit (ver++) ▼ │ circulating │ │ │ ├── first ready step → awaiting_actor │ ├── discuss → in_discussion │ │ │ │ │ └── assignee resumes → awaiting_actor │ │ │ ├── return → returned ──requester revises (ver++)──► submitted │ ├── last binding verb → completed (+ outcome) │ ├── withdraw → withdrawn │ └── due passed → expired (outcome timed_out) │ └── completed ── new memo relation.supersedes ──► superseded L0/L1 extra: completed + requested_act ∈ {login, elevate} → session.status = active (bound_configuring window) → configure / session.ended → session.status = ended ``` `in_discussion` is a substate of circulation. It does not reset the step. ## B. Verb × status × step kind Legend: `✓` allowed · `—` forbidden · `C` allowed and may complete the step · `M` allowed and may complete the *memo* · `S` session-only after bind. Step kinds are grouped: - **Weak:** `inform`, `comment`, `review`, `acknowledge` - **Co-sign:** `mitzeichnung`, `approve` - **Bind:** `schlusszeichnung`, `sign`, `seal`, `deposit` ### B1. Status `draft` | Verb | requester | assignee | agent | Effect | |---|---|---|---|---| | comment | ✓ | — | ✓ | thread only | | discuss | ✓ | — | — | stays draft | | withdraw | ✓ | — | — | → withdrawn | | accept / decline / acknowledge / return / forward / escalate / configure | — | — | — | not circulating | | submit (system/requester) | ✓ | — | — | → submitted | ### B2. Status `submitted` / `circulating` / `awaiting_actor` / `in_discussion` | Verb | Weak step | Co-sign | Bind step | Guards | Status after | |---|---|---|---|---|---| | comment | ✓ any party | ✓ | ✓ | — | unchanged (`in_discussion` if was circulating) | | discuss | ✓ any party | ✓ | ✓ | — | `in_discussion` | | return | ✓ assignee | ✓ | ✓ | G_NOAGENT G_REASONS | `returned` | | forward | ✓ assignee | ✓ | ✓ | G_NOAGENT G_TARGET | stays circulating; step assignee replaced | | escalate | ✓ assignee | ✓ | ✓ | G_NOAGENT G_TARGET G_ESC | circulating; higher step inserted/activated | | acknowledge | C assignee | C | ✓ overlay | G_NOAGENT G_PRES G_ACK | step complete; memo completes only if this was the last step *and* `requested_act=acknowledge` | | accept | — | C assignee | **M** assignee | G_NOAGENT G_PRES G_ACK G_MAND G_LEVEL G_STEP | last bind/co-sign step → `completed` outcome=`accepted` | | decline | — | C assignee | **M** assignee | G_NOAGENT G_PRES G_STEP | → `completed` outcome=`declined` (memo ends; later steps skipped) | | abstain | — | C assignee | C assignee | G_NOAGENT G_PRES | step complete for this actor; parallel group may continue; if actor was sole bind step → `completed` outcome=`abstained` | | recuse | ✓ | C | C | G_NOAGENT G_PRES | step unassigned; must forward/escalate or return | | withdraw | requester only | same | same | not terminal | → `withdrawn` | | stamp | system | system | system | after a bind disposition or on completion | unchanged | | configure | — | — | — | not yet bound | — | | promote | requester | requester | requester | G_PROMOTE | version++; back toward submitted | `accept` on a **weak** step is illegal. Weak steps take `acknowledge`. That is how Kenntnisnahme stays distinct from Schlusszeichnung. ### B3. Status `returned` | Verb | Who | Effect | |---|---|---| | comment / discuss | any party | thread | | revise + submit | requester | version++; → submitted; new route from policy | | withdraw | requester | → withdrawn | | binding verbs | — | illegal on a returned version | ### B4. Status `completed` | Verb | Who | Effect | |---|---|---| | comment | parties | thread; does not unseal | | stamp | system | file.stamped / bundle.sealed | | configure | subject | **S** session hat; see §C | | promote | requester | not on this version; open child memo | | accept / return / … | — | sealed | If `requested_act ∈ {login, elevate}` then `session.status` becomes `active` at the completing accept/acknowledge. ### B5. Terminal `withdrawn` | `expired` | `superseded` No actor verbs except system `stamp` of the evidence bundle already accumulated. ## C. Post-bind session transitions Applies when `session.status = active`. ``` pre_bind presentation │ actor chooses identity + bind-scope │ sees proposed hat / other tenants as AWARENESS only ▼ bind disposition (accept | acknowledge) │ view_hash covers binding_slice only │ awareness_hash recorded alongside, not signed ▼ session.active ├── configure(hat) if hat.elevates=false ∧ hat in available_hats ├── attempt other scope │ requires_new_bind=false → still configure (same bind) │ requires_new_bind=true → emit scope.rebind_required, open child memo └── session.ended logout / expiry / revoke ``` | Event | In `view_hash`? | In `awareness_hash`? | Evidence event | |---|---|---|---| | Chosen identity | yes | copy ok | identity.authenticated | | Chosen bind-scope / tenant of *this* login | yes | copy ok | disposition.recorded | | Privileges granted *at the gate* | yes | preview ok | disposition.recorded | | Proposed / last-used hat shown | no | yes | awareness.shown | | Hat selected after login | no | yes | session.hat_selected | | Hat with `elevates=true` | must promote | — | promote + new bind | | Other tenant with `requires_new_bind` | no | listed | scope.rebind_required | Defaulting the hat to `last_used` or `system_default` is an awareness act. Showing it on the login banner is required for situational awareness and forbidden from silently entering `view_hash`. ## D. Completing a step vs completing the memo A step completes when the assignee records a verb in that step’s completion set: | Step kind | Completion set | |---|---| | inform, review, acknowledge | acknowledge, return, recuse | | comment | comment (if so configured) or acknowledge | | mitzeichnung, approve | accept, decline, abstain, recuse, return | | schlusszeichnung, sign, seal, deposit | accept, decline, abstain, recuse, return | The memo completes when: 1. A bind-step `decline` is recorded, or 2. Every required step is `completed` or `skipped`, and at least one completing verb in the memo’s `requested_act` family was recorded, or 3. Requester `withdraw`, or system expiry. Parallel groups: all members must reach a terminal step status before the next ordinal becomes `ready`. ## E. Illegal combinations (explicit) - Agent + any binding verb - `accept` on `inform`/`review` - `configure` before `session.active` - `configure` of a hat with `elevates=true` - `configure` of a scope with `requires_new_bind=true` - Binding verb whose presentation `phase=post_bind` - Binding verb whose presentation `awareness_hash` was substituted for `view_hash` - Mutating `identity_context.binding` after the first bind disposition of that version