# Operator Questions

`ai/tools/operator-questions` is the canonical local/dev operator
question/answer interface.

Rules:

- One question object.
- One accepted answer.
- Local console and Telegram are alternative answer channels.
- The first valid answer wins.
- Late answers are recorded as stale and cannot affect later questions.
- Waiting has no timeout by default; tests may pass `--timeout`.
- Freeform is disabled unless explicitly requested with `--freeform`.

Examples:

```sh
ai/tools/operator-questions/ask.sh --type yes-no --question "Commit changes?" --wait
ai/tools/operator-questions/answer.sh --id <id> --answer yes --source local
ai/tools/operator-questions/wait-answer.sh <id>
ai/tools/operator-questions/consume-pending.sh
ai/tools/operator-questions/list.sh --pending
ai/tools/operator-questions/list.sh --pending --json
ai/tools/operator-questions/list-approved-actions.sh
ai/tools/operator-questions/list-approved-actions.sh --all
ai/tools/operator-questions/resolve-stale-approved-actions.sh --dry-run
ai/tools/approved-action-dispatcher/dispatch.sh --dry-run --once --question-id <id>
ai/tools/operator-questions/status.sh --json
ai/tools/operator-questions/resolve-stale.sh --id <id> --reason "reviewed stale test question"
```

Telegram mirroring uses the existing Telegram checkpoint bridge as compatibility
plumbing. New workflow code should call this Q&A layer, not
`create-checkpoint.mjs` directly.

Do not inspect `.tmp/operator-questions/questions/*.env` as the normal workflow.
Use `list.sh` and structured status output so Codex, Telegram, doctor, and
handoffs share the same pending-question view.

Stale question cleanup is explicit. Use `resolve-stale.sh` for reviewed
abandoned questions; it writes a resolved record and does not delete runtime
state or create an accepted answer.

`consume-pending.sh` canonicalizes already-recorded Telegram decisions into
operator-question answers. Use it before treating Telegram approval as complete
when no wait loop was running.

Close/commit and similar lifecycle approvals create a durable approved-action
intent in addition to the question. If Telegram approval arrives after Codex has
stopped, the intent remains approved-but-unexecuted and must be resumed
explicitly through the deterministic dispatcher. `list-approved-actions.sh` and
`ai/tools/approved-action-dispatcher/dispatch.sh --dry-run --once --question-id
<id>` show whether the target, git status, and age are still safe. Stale
approvals require a fresh question; do not execute them silently on a later run.
Default approved-action lists show only actionable approvals. Use `--all` for
audit/history, and `resolve-stale-approved-actions.sh` to mark stale
non-executed intents as reviewed without deleting evidence.

Runtime Core owns read-only approval-state classification for approved actions:
pending, approved, denied, consumed, stale, ignored, superseded, invalid, and
resolved-stale. `list-approved-actions.sh` preserves the operator shell
entrypoint but now routes that classification through `ai/runtime`.

Runtime Core classification is not execution authority. The approved-action
dispatcher remains the only owner of approved execution, operator-daemon remains
the trusted local action owner, and `close_commit` still requires the
deterministic approved-action dispatcher path.
