# Local Dev Runtime Standard

This standard owns the canonical local/dev tmux session architecture for Codex,
the Remote Dev Operator Console, Telegram bridge, managed dev servers, and
browser/screenshot validation.

Keep operational runtime naming here. Roles, helper READMEs, UI review, and
remote-operator standards should reference this file instead of duplicating the
full startup model.

Top-level runtime operating procedures, validation/cleanup expectations, final
summary requirements, and console-vs-Telegram surface separation live in
`ai/standards/runtime-sop.md`.

## Canonical Tmux Sessions

| Session                      | Purpose                                  | Owner                                                     |
| ---------------------------- | ---------------------------------------- | --------------------------------------------------------- |
| `codex-autopilot`            | Codex/Orchestrator/operator shell        | human/operator                                            |
| `telegram-bridge`            | Telegram bridge daemon                   | `ai/tools/telegram/start-bridge.sh`                       |
| `runtime-supervisor`         | Trusted restart/recovery supervisor      | `node ai/runtime/dist/cli.js supervisor start`            |
| `operator-daemon`            | Trusted registered-action daemon         | `ai/tools/operator-daemon/start-daemon.sh`                |
| `approved-action-dispatcher` | Deterministic approved-action dispatcher | `ai/tools/approved-action-dispatcher/start-dispatcher.sh` |
| `codex-io-bridge`            | Codex prompt mirror/input bridge         | `ai/tools/codex-io-bridge/start-bridge.sh`                |
| `blueprint-dev-frontend`     | Angular dev server                       | `ai/tools/dev-server/start.sh frontend`                   |
| `blueprint-dev-backend`      | NestJS dev server                        | `ai/tools/dev-server/start.sh backend`                    |

Helpers must use deterministic names and must print the session name they use.
They must not silently create random session names.

## Startup From Scratch

Use the stack helper for normal startup:

```sh
ai/tools/local-dev/start-stack.sh --with-dev-servers
tmux attach -t codex-autopilot
```

The stack helper should start `codex-autopilot` with approval and sandbox
bypass enabled in the trusted local/dev environment:

```sh
codex --dangerously-bypass-approvals-and-sandbox -C /workspace
```

Set `CODEX_AUTOPILOT_COMMAND` only for explicit recovery or compatibility
cases.

This command is the canonical trusted local runtime profile recorded in
`ai/governance/registries/runtime-permissions.yaml`. It avoids broken nested
`bwrap`/sandbox loops and repeated repo-local approval prompts. It does not
weaken Blueprint governance: close/commit, lifecycle authority mutation,
dispatcher execution, registered daemon git actions, and operator approval
boundaries still flow through the canonical Blueprint tools.

If sandboxing is degraded, such as namespace exhaustion from `bwrap ENOSPC`,
do not retry through repeated Codex sandbox escalation loops for trusted
repo-local work. Continue through deterministic local runtime helpers,
Runtime API requests, validators, and registered wrappers, while preserving
Blueprint approval gates for authority-state mutation and external side
effects.

When runtime state is unclear, start with the canonical Runtime CLI doctor
command:

```sh
node ai/runtime/dist/cli.js doctor --json
```

The doctor uses trusted daemon read-only status actions where available and
labels direct Codex/shell probes as advisory.

Doctor/scorecard performance expectation: a healthy trusted runtime should
normally complete in a few seconds, not tens of seconds. The scorecard should
avoid duplicate daemon read-only requests; `local_dev_status` is the bundled
trusted status source for managed dev servers, Telegram bridge, runtime
supervisor, operator daemon, and Codex I/O bridge. Use
`node ai/runtime/dist/cli.js validate --tier fast` first when runtime diagnosis
feels slow; expensive smoke checks are opt-in.

For AI consumption, use the stable machine-readable scorecard:

```sh
node ai/runtime/dist/cli.js scorecard --json
```

The JSON scorecard is the preferred input when Codex needs to reason about
runtime state without parsing prose.

Runtime automation should prefer structured helper output such as `--json`,
`--kv`, or env-style records over parsing human-oriented prose. If a helper is
used by the scorecard, add a structured mode before adding brittle regex
parsing where practical.

When runtime helper behavior changes, update operator-facing help, README,
status output, Telegram guidance, and standards according to
`ai/standards/runtime-tooling-governance.md`.

Closed-loop runtime validation is owned by
`ai/standards/runtime-closed-loop-e2e.md`. Use fixture-only tests for normal
regression coverage, trusted-runtime tests when tmux/daemon/dev-server state is
required, and live Telegram/browser checks only when their runtime prerequisites
are healthy.

Operator-question state is part of runtime health. Use the readable helper
instead of inspecting `.tmp/operator-questions/questions/*.env` directly:

```sh
ai/tools/operator-questions/list.sh --pending
ai/tools/operator-questions/list.sh --pending --json
ai/tools/operator-questions/status.sh --json
ai/tools/operator-questions/resolve-stale.sh --id <id> --reason "<reviewed reason>"
```

Doctor and scorecard output must surface pending/stale operator questions,
missing actions, restart recommendations, and recovery recommendations in
structured form so Codex can stop cleanly instead of improvising.
They must also surface approved-but-unexecuted and stale approved-action
intents. Approval validity is owned by `ai/standards/operator-questions.md`;
runtime automation must not reuse stale approvals when trusted runtime,
validation, target, or git state changed.

Daemon request state is managed through structured helpers:

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

Use cleanup dry-runs first. Runtime cleanup must write observable results or
archives; it must not silently delete active state.

For manual startup, open the devcontainer or trusted local/dev shell, then
start the canonical operator shell:

```sh
tmux new -s codex-autopilot "codex --dangerously-bypass-approvals-and-sandbox -C /workspace"
```

Run Codex/Orchestrator inside that session. The Remote Dev Operator Console
captures and sends operator instructions to this session by default.

Start the Telegram bridge:

```sh
ai/tools/telegram/start-bridge.sh
node ai/runtime/dist/cli.js telegram status --json
```

The bridge helper owns the `telegram-bridge` session when tmux is available.
If tmux is unavailable, it may fall back to the documented background listener,
but status output must make the bridge health visible.

Start the trusted operator daemon and Codex I/O bridge:

```sh
node ai/runtime/dist/cli.js supervisor start
ai/tools/operator-daemon/start-daemon.sh
ai/tools/approved-action-dispatcher/start-dispatcher.sh
ai/tools/codex-io-bridge/start-bridge.sh
```

The runtime supervisor is separate from the operator daemon and handles
restart/recovery actions that the daemon cannot safely perform on itself,
including `operator_daemon_restart`.

The daemon runs registered privileged local/dev actions outside the Codex
sandbox. The approved-action dispatcher owns deterministic continuation for
accepted durable approvals and runs as its own trusted tmux session. It validates
approved-action freshness and then executes registered dispatcher actions such as
`close_commit`, delegating bounded privileged work to the trusted daemon where
appropriate. The Codex I/O bridge is optional observability/input mirroring for
`codex-autopilot:0.0`; it must not create approval/freeform questions from pane
scraping. Pane text is `codex_internal_context` under
`ai/standards/runtime-event-semantics.md`, not an operator question. It does not
wake Codex and does not approve Codex platform permission UI.

The dispatcher records action history in the canonical action timeline. Use
`ai/tools/action-timeline/list.sh --human` for shell review,
`ai/tools/action-timeline/list.sh --telegram` for mobile-readable output, and
`ai/tools/action-timeline/archive.sh --dry-run` before rotating old runtime
events into `.tmp/action-timeline/archive/`.

When Codex sandbox checks disagree with the trusted devcontainer shell, the
trusted operator daemon is authoritative for local runtime status. Codex should
request `local_dev_status`, `dev_server_status`, or `telegram_bridge_status`
instead of treating sandbox tmux/localhost/bridge failures as final. After
Telegram bridge code changes, request daemon `telegram_bridge_restart` before
live Telegram testing so the managed bridge reloads code from the trusted
runtime. Do not assume bridge code changes are live until the restart action
has completed and `telegram_bridge_status` succeeds.

When changing any long-running runtime component, consider what must be
restarted before validation:

- Telegram tooling or dispatch code: `telegram_bridge_restart`.
- Operator daemon action code: request supervisor `operator_daemon_restart`.
- Approved-action dispatcher code: request supervisor
  `approved_action_dispatcher_restart`.
- Codex prompt mirror/injection code: request supervisor
  `codex_io_bridge_restart`.
- Frontend/backend app code after routing, auth, GraphQL, config, or runtime
  changes: restart the matching managed dev server.

Document the restart performed or the reason it was not needed in the chunk
notes.

Start managed dev servers:

```sh
ai/tools/dev-server/start.sh backend
ai/tools/dev-server/start.sh frontend
ai/tools/dev-server/status.sh backend
ai/tools/dev-server/status.sh frontend
```

The frontend URL is `http://127.0.0.1:4220/`. The backend GraphQL URL is
`http://127.0.0.1:3720/graphql`. The managed backend helper starts local/dev
Remote Dev Console interaction with
`REMOTE_DEV_CONSOLE_INTERACTION_ENABLED=true`; production remains blocked by
the backend environment guard.

Before screenshots or browser validation, verify reachability from the same
command context used for the Runtime-owned browser proof:

```sh
ai/tools/dev-server/wait-url.sh http://127.0.0.1:4220/
node ai/runtime/dist/cli.js testing runtime-action-panel-browser-smoke --json
```

`yarn smoke:browser:runtime-action-panel` is a human convenience facade for the
same Runtime Core testing method. Do not replace it with ad hoc Playwright
commands unless diagnosing severe tooling failure and recording why the Runtime
path could not run.

For routing, auth/session, GraphQL/codegen, backend, environment/config, Dev
Console, or major UI changes, restart the managed servers cleanly instead of
reusing a stale process:

```sh
ai/tools/dev-server/restart.sh backend
ai/tools/dev-server/restart.sh frontend
```

## Command-Bound Readiness Checks

After disruptive local/dev operations, such as Runtime builds, Runtime daemon
restart, managed backend/frontend restart, Telegram bridge restart, or Socket.IO
diagnosis, run a command-bound readiness check instead of relying on constant
polling or memory:

```sh
ai/commands/service-readiness-check.sh --json
```

When Runtime source or generated Runtime build output changed, use the same
check with Runtime recovery enabled:

```sh
ai/commands/service-readiness-check.sh --recover-runtime --json
```

The readiness check is intentionally bounded and event/command-triggered. It
verifies:

- Runtime API daemon process status.
- Runtime daemon generation freshness, including `restart_required`.
- Runtime services surfaced by the canonical Runtime status projection.
- Managed backend and frontend session reachability.
- Socket.IO Runtime Health namespace reachability, distinct from GraphQL/API
  reachability.

The check may restart the Runtime API daemon only when `--recover-runtime` is
provided and the Runtime daemon reports stale generation or unavailable
freshness. It does not silently restart backend/frontend/Telegram/operator
services; those still use their canonical managed helper or trusted daemon
actions. If a required service is degraded, the check prints structured
evidence and the next canonical recovery action.

Authenticated browser, mobile browser, and installed PWA membership is proven
through the Runtime Action Panel socket diagnostics registry, not by assuming
that page load or GraphQL reachability means Socket.IO has joined
`admin.runtime_health`.

When Codex is running in a sandbox that cannot see the real tmux/socket/network
namespace, use daemon actions for status/start/stop/restart and screenshots:

```sh
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 telegram_bridge_restart
ai/tools/operator-daemon/request-action.sh --action dev_server_restart --target frontend
ai/tools/operator-daemon/request-action.sh --action capture_screenshots --target http://127.0.0.1:4220/ --message ui-smoke
ai/tools/operator-daemon/wait-result.sh <request-id>
```

When the daemon itself is stale, wedged, or needs code reload, use the trusted
runtime supervisor instead of asking the daemon to restart itself:

```sh
node ai/runtime/dist/cli.js supervisor request --action operator_daemon_restart --json
node ai/runtime/dist/cli.js supervisor wait --request-id <request-id> --json
```

## Dev Console Target

The default Remote Dev Operator Console tmux target is:

```env
REMOTE_DEV_CONSOLE_TMUX_TARGET=codex-autopilot:0.0
```

If the target session or pane does not exist, the Dev Console must show a clear
unavailable state from the tmux error and must not fabricate terminal output.
The UI should display the configured target so the operator can compare it with
the canonical session names.

The Dev Console may show a compact runtime status strip from
`remoteDevRuntimeStatus`. It must remain admin-only, local/dev-only, compact,
and backed by the runtime scorecard; do not create a second status model in the
UI.

## Helper Ownership

`ai/tools/dev-server/` owns frontend/backend dev-server lifecycle. The helpers:

- create or reuse only `blueprint-dev-frontend` and `blueprint-dev-backend`
  unless explicitly overridden through documented environment variables.
- stop only managed tmux sessions that they own.
- detect reachable unmanaged URLs and report a conflict instead of killing
  unrelated processes.
- write logs under `/tmp/blueprint-dev-server/`.
- print attach instructions so the operator can inspect managed sessions.

`ai/tools/telegram/start-bridge.sh` owns the bridge runtime. Its canonical tmux
session is `telegram-bridge` through `TELEGRAM_BRIDGE_TMUX_SESSION`.

`ai/tools/runtime-supervisor/` owns restart/recovery actions for the daemon,
Telegram bridge, Codex I/O bridge, and managed dev servers when the trusted
runtime needs a separate recovery loop.

`ai/tools/local-dev/` owns startup/status/stop orchestration for the full stack.
It must use the canonical session names above and must not kill unrelated
unmanaged processes.

## Local/Dev Boundary

This runtime architecture is for trusted local/dev use only. Do not expose the
Remote Dev Operator Console, tmux control, Telegram bridge state, dev-server
ports, logs, screenshots, `.env`, local databases, or runtime state to
production or the public internet.
