# Trusted Operator Daemon

The trusted operator daemon is the canonical trusted local/dev runtime executor
for Codex and Telegram. It runs from the real devcontainer/tmux runtime,
executes narrow registered actions, and lets accepted local/dev operator
answers authorize mutating workflow actions without Codex platform escalation.

Cross-cutting close/commit wording and operator-facing docs/help synchronization
rules live in `ai/standards/runtime-tooling-governance.md`.

Codex sandbox probes are advisory only. When Codex cannot see tmux, localhost,
browser tooling, or Git metadata but the operator shell can, Codex must request
daemon actions and wait for daemon result files instead of treating sandbox
failures as authoritative.

## Trust Boundary

- Local/dev only.
- No production exposure.
- No network API.
- No arbitrary shell execution.
- Registered actions only.
- The daemon process must run from the trusted local operator shell/tmux,
  outside the Codex sandbox.
- The daemon must not be responsible for restarting itself. Use
  `ai/tools/runtime-supervisor/` for trusted restart/recovery actions such as
  `operator_daemon_restart`.
- Codex creates requests and waits for results; Codex does not execute
  registered runtime, browser, dev-server, git, or completion actions itself
  when sandbox visibility is unreliable.
- Telegram is not an executor. Telegram only provides remote operator answers
  through the operator Q&A layer.
- Fail closed on malformed, denied, stale, wrong-token, unknown, or unsafe
  requests.

## Relation To Operator Questions

The daemon creates operator questions through `ai/tools/operator-questions/ask.sh`
for mutating actions, waits for the first accepted local or Telegram answer,
verifies the request/action binding, then runs only the registered action.

Read-only status actions may be approval-free by policy:

- `local_dev_status`
- `dev_server_status`
- `telegram_bridge_status`

Mutating actions require Q&A approval unless a future standard explicitly marks
one safe:

- `dev_server_start`
- `dev_server_stop`
- `dev_server_restart`
- `telegram_bridge_start`
- `telegram_bridge_stop`
- `telegram_bridge_restart`
- `capture_screenshots`
- git actions
- completion/archive actions

## Registered Phase 1 Actions

- `local_dev_status`: runs `ai/tools/local-dev/status.sh` from the trusted
  runtime and reports canonical tmux, bridge, daemon, Codex I/O bridge, and
  dev-server status.
- `dev_server_status`: runs `ai/tools/dev-server/status.sh` for
  `frontend`, `backend`, or `all` from the trusted runtime.
- `telegram_bridge_status`: reports the managed Telegram bridge health through
  the Runtime API Telegram status projection.
- `git_add_approved`: stages only explicitly listed reviewed files and refuses
  `.env`, `.tmp`, secret-looking paths, local DB files, logs, dependency folders,
  and build/runtime output.
- `git_commit`: commits already-staged files with an approved message and never
  stages automatically.
- `complete_chunk`: creates a workflow approval record from the accepted daemon
  answer, runs the ready-to-complete path, and archives the active chunk.
- `dev_server_start`, `dev_server_restart`, `dev_server_stop`: operate only the
  canonical managed frontend/backend dev-server helpers for `frontend`,
  `backend`, or `all`.
- `telegram_bridge_start`, `telegram_bridge_restart`, `telegram_bridge_stop`:
  operate only the canonical Telegram bridge helpers. Restart stops then starts
  the managed bridge so code changes are loaded by the live process.
- `capture_screenshots`: captures local dev URLs with installed Playwright and
  writes screenshots under `/tmp`. It must use timeout protection and must not
  block on package-install prompts.

## Flow

The standard Codex workflow for every registered action is:

1. Create a request with `ai/tools/operator-daemon/request-action.sh`.
2. Let `operator-questions` create any required approval question.
3. Accept exactly one valid answer from Telegram or the local console.
4. Wait with `ai/tools/operator-daemon/wait-result.sh <request-id>`.
5. Continue only from the daemon result file.

```sh
# Run once from the trusted local operator shell/tmux, not from Codex:
ai/tools/operator-daemon/start-daemon.sh

# Codex can then enqueue and wait:
ai/tools/operator-daemon/request-action.sh --action local_dev_status
ai/tools/operator-daemon/request-action.sh --action dev_server_status --target frontend
ai/tools/operator-daemon/request-action.sh --action telegram_bridge_status
ai/tools/operator-daemon/request-action.sh --action git_add_approved --files "README.md|ai/standards/operator-questions.md"
ai/tools/operator-daemon/wait-result.sh <request-id>
```

`start-daemon.sh` is an operator-shell startup command, not a Codex action.
`run-once.sh` is daemon-internal/fixture tooling. Codex must not use
`run-once.sh` as the normal way to execute registered actions, and must never
use it to process `git_add_approved`, `git_commit`, or other trusted-Git
requests from the sandbox. The long-running trusted daemon loop owns execution.
If Codex believes `run-once.sh` is needed for diagnosis, Codex must first ask
through `operator-questions` so Telegram and local console both receive the
request, and proceed only if the operator explicitly chooses that exceptional
terminal action.

If Codex sees no daemon result, it waits, checks `operator-daemon/status.sh`,
or asks the operator through `operator-questions` to start/fix the trusted
daemon. It must not switch to raw Git or Codex platform escalation for a
registered action.

Direct `run-once.sh` invocation must be from `start-daemon.sh` or guarded by
`OPERATOR_DAEMON_ALLOW_RUN_ONCE=true`. Without that daemon parent/explicit guard
it exits without processing requests. If a sandbox-local guarded invocation
happens in tests or diagnostics, it must skip trusted-Git requests instead of
writing a final blocked result. That preserves the request for the trusted
runtime.

## Resilience And Cleanup

Daemon actions must be bounded. `run-once.sh` executes registered action
scripts with `OPERATOR_DAEMON_ACTION_TIMEOUT_SECONDS` timeout protection and
records explicit failed results on timeout. Actions must not prompt
interactively.

The daemon writes in-progress state while an action runs. Runtime automation and
operator handoffs should inspect structured state with:

```sh
ai/tools/operator-daemon/status.sh --json
ai/tools/operator-daemon/list.sh --pending --json
ai/tools/operator-daemon/cleanup-stale.sh --dry-run
```

Cleanup is explicit and observable. Do not blindly delete runtime state.
Reviewed stale requests may be marked blocked with
`cleanup-stale.sh --mark-blocked`; this writes results so Codex can continue
from a known state.

## Platform Escalation Rule

For registered daemon actions, Codex should use the daemon and must not request
Codex platform escalation. The daemon is the trusted local actor.

Recurring local/dev cases map as follows:

- Runtime/stack status: `local_dev_status`.
- Frontend/backend dev-server status: `dev_server_status`.
- Telegram bridge status: `telegram_bridge_status`.
- Git add: `git_add_approved`.
- Git commit: `git_commit`.
- Complete/archive: `complete_chunk`.
- Dev server start/restart/stop: `dev_server_start`, `dev_server_restart`,
  `dev_server_stop`.
- Telegram bridge start/restart/stop: `telegram_bridge_start`,
  `telegram_bridge_restart`, `telegram_bridge_stop`.
- Browser screenshot validation: `capture_screenshots`.

For unregistered actions, operator Q&A can record approval intent, but Telegram
or local scripts cannot satisfy Codex platform permission UI. That limitation
must be stated honestly in handoffs.

## Missing Registered Action Rule

If Codex needs a local/dev action to continue remote/autopilot work and no
registered daemon action exists, Codex must not improvise a raw shell command,
request Codex platform escalation, or silently ask for manual terminal work as
the normal path.

Instead:

1. Notify the operator through `ai/tools/operator-questions/ask.sh` so Telegram
   and local console can both receive the gap notice.
2. Record a short summary of the missing action, intended command/effect,
   safety boundary, and why an existing daemon action does not cover it.
   Use:

   ```sh
   ai/tools/missing-actions/register.sh --requested-action "<name>" --context "<why needed>" --why-missing "<gap>" --suggested-action "<daemon_action_name>"
   ```

3. Include `ai/tools/missing-actions/summary.sh` in the workflow handoff.
4. Stop or create a follow-up chunk to implement the daemon action.
5. Continue only after the action is registered and validated, or after the
   operator explicitly chooses a one-off terminal/manual fallback as an
   exceptional option.

The one-off terminal/manual fallback is never the default recommendation for a
registered or recurring action.

## Codex Usage Model

- Use `node ai/runtime/dist/cli.js doctor --json` or `node ai/runtime/dist/cli.js scorecard --json`
  when Codex needs machine-readable runtime state. Treat trusted daemon fields
  as authoritative and sandbox-local probes as advisory.
- For tmux/localhost/browser runtime health, request `local_dev_status` or
  `dev_server_status`.
- For Telegram bridge health, request `telegram_bridge_status` before claiming
  the bridge is unavailable from a Codex sandbox probe.
- After changing Telegram bridge code and before live testing, request
  `telegram_bridge_restart` instead of manually accessing tmux from Codex. A
  live Telegram test is not valid until the managed bridge has restarted and
  `telegram_bridge_status` reports success.
- Do not treat Codex sandbox-local tmux or localhost failures as authoritative
  when trusted daemon status is available.
- For managed server start, stop, or restart, request the matching daemon
  action and wait for the result.
- For screenshot validation, request `capture_screenshots` and use the returned
  `/tmp` screenshot paths.
- If the daemon is unavailable, ask through operator Q&A to start/fix the daemon
  or stop. When the runtime supervisor is available, request
  `operator_daemon_restart` through `node ai/runtime/dist/cli.js supervisor request --action operator_daemon_restart`
  instead of falling back to Codex platform escalation or daemon self-restart.
  Offer one-off manual terminal fallback only when the operator explicitly asks
  for it or chooses it from an exceptional option.
- Result files must be clear enough for Codex continuation and must distinguish
  trusted-runtime status from Codex sandbox-local probes.
- If a needed registered action is missing, register it with
  `ai/tools/missing-actions/register.sh` and include
  `ai/tools/missing-actions/summary.sh` in the handoff.

## Validation

Daemon changes require fixture end-to-end tests in isolated `/tmp` git repos.
Tests must not commit to the main repository.
