# Runtime Event Semantics

Runtime/operator events must be classified before they are rendered to an
operator surface. The canonical machine-readable owner is
`ai/governance/registries/runtime-event-semantics.yaml`; this standard explains
the operating rule.

## Authority Rule

Only actionable events may ask the operator for a reply.

Informational, stale, suppressed, or Codex-internal events must not include
`Reply with freeform text`, approval commands, or wording such as `Codex is
waiting for input`.

## Event Classes

- `approval_required`: asks for approval using approval-specific yes/no wording.
  It authorizes a registered dispatcher/daemon action; it does not request
  freeform text.
- `operator_decision_required`: asks for a bounded non-approval decision using
  explicit options.
- `freeform_input_required`: asks for data only when the runtime explicitly
  needs operator-provided text, such as a URL or branch-like value. Freeform text
  is stored as data and is never arbitrary shell execution.
- `informational_note`: communicates state with no reply block.
- `architectural_note`: communicates a design/runtime architecture insight with
  no reply block.
- `runtime_note`: communicates an important runtime observation with no reply
  block.
- `governance_note`: communicates governance or policy implications with no
  reply block.
- `operator_warning`: communicates a warning that needs operator awareness but
  not an answer.
- `validation_failure`: reports failed validation and the next diagnostic or
  repair command. It is not itself an input request.
- `runtime_warning`: reports degraded runtime state and recovery guidance. It is
  not itself an input request.
- `stale_runtime_artifact`: records obsolete or already-consumed runtime state.
  It is suppressed by default or shown as ignored/stale context.
- `codex_internal_context`: Codex pane text, validation notes, self-echoed
  prompts, diffs, and old TUI fragments. It is observability context only and
  must never be promoted into an operator question by pane scraping.
- `lifecycle_transition`: reports chunk lifecycle state changes with no reply
  block.

## Telegram Rendering

Telegram is compact and action-oriented:

- approval prompts show only approval commands, target/action context, and
  `/details_<token>`.
- bounded decisions show only valid options for that question.
- freeform prompts must state the exact data requested and why it is needed.
- informational/stale/internal events do not show a `Reply:` section.
- details/timeline views may show ignored stale/internal context, but must label
  it as non-actionable.

## Approval State Semantics

The canonical approval states are declared in
`ai/governance/registries/runtime-event-semantics.yaml`:

- `pending`: question exists but no accepted answer exists.
- `approved`: accepted yes/approval answer exists.
- `denied`: accepted denial exists.
- `consumed`: approval was consumed by the dispatcher/daemon path.
- `stale`: approval cannot execute because age, git state, target, validation,
  or runtime state changed.
- `ignored`: reviewed and intentionally left non-executable.
- `superseded`: replaced by a fresher approval.
- `invalid`: malformed or unknown approval state.

Default operator surfaces must show only actionable approvals. Stale, invalid,
ignored, superseded, denied, and already executed approvals are audit state and
belong in details/timeline or `--all` output.

## Notification Helpers

Use `ai/tools/operator-notifications/render-event.mjs` or
`ai/tools/operator-notifications/send-event.sh` for notes and warnings. These
helpers read the runtime event semantics registry and reject non-actionable
messages that try to ask for freeform replies.

## Codex I/O Bridge

`ai/tools/codex-io-bridge` is observability/input mirroring only. It must not
create approval or freeform operator questions from tmux pane scraping. If pane
text looks like a prompt, it is `codex_internal_context` unless another
canonical tool explicitly creates an operator question.
