# Operator Notifications

This standard owns non-approval Telegram notifications for orchestration and
runtime work. It keeps notification behavior DRY so roles do not rely on memory.

Canonical operator questions and approvals live in
`ai/standards/operator-questions.md`. Trusted action execution lives in
`ai/standards/trusted-operator-daemon.md`. Cross-cutting close/commit wording
and operator-facing docs/help synchronization rules live in
`ai/standards/runtime-tooling-governance.md`. Top-level run summary,
validation, cleanup, and automatic close/commit approval rules live in
`ai/standards/runtime-sop.md`. This file covers Telegram notification
implementation details only.

## Required Run Boundary Summary

When an orchestration run finishes or stops, send a compact Telegram summary:

```sh
node ai/runtime/dist/cli.js request --method runtime.executor.runSummary --params '<json>'
```

`ai/tools/telegram/send-run-summary.mjs` remains a compatibility facade for
humans and older CI callers; it must not contain notification, approval, or
workflow sequencing policy.

Use this for:

- run completion.
- manual stop.
- blocked stop.
- failed validation stop.
- runtime/tooling stop.
- final handoff before waiting for human review.

The first Telegram message should use the compact mobile-friendly shape:

- `Good`: what improved or completed.
- `Bad`: current blocker, validation failure, or remaining problem.
- `Ugly`: only for design-significant fragility or serious limitation.
- `Next`: the immediate recovery or continuation action.

Always include `Good`, `Bad`, and `Ugly` in the compact Telegram summary. Use
`None` for categories with no meaningful item so the operator does not need to
infer whether the category was omitted accidentally.

The message includes `More: /details`. Tokenized `/details_<token>` remains
scoped to a specific question or confirmation.

## Canonical Run Summary And Approval Linkage

The canonical final summary shape, validation-skip reporting, runtime cleanup
rules, and automatic close/commit approval rule live in
`ai/standards/runtime-sop.md`.

Run-path event emission and notification scheduling are defined in
`ai/governance/registries/run-paths.yaml`. Notification scripts should render
events from canonical runtime event classes and run-path phase outcomes rather
than duplicating phase policy locally.

Runtime Core owns the notification render model for migrated surfaces. Runtime
Executor owns the live run-summary procedure, details persistence, close
approval creation, and summary-before-approval ordering. Runtime API methods
such as `notifications.render`, `telegram.renderMessage`,
`telegram.runSummary`, and `telegram.details` may classify and prepare
messages, summaries, and details references. Live Telegram transport remains
adapter-owned, but outbound queue authorization comes from Runtime Executor.

Recommendation handling is implemented by `runtime.executor.runSummary`;
`ai/tools/operator-notifications/post-run-recommendation.sh` is a compatibility
facade. Roles and Telegram scripts must not duplicate that policy. The valid
recommendations are `close`, `reiterate`, `hold`, and `unsure`.

## Close/Commit Notification Contract

Every close/commit path must be operator-visible or explicitly accounted for.
Canonical manual close/commit uses a Runtime Executor run summary and approval
request before the dispatcher executes `close_commit`. Canonical
autonomous/deemed close/commit uses the Runtime Executor run summary plus
non-actionable autonomous approval/completion notes.

Compatibility helpers that do not own notification delivery must record durable
close/commit notification-contract evidence through:

```sh
ai/tools/operator-notifications/record-close-commit-contract.sh
```

The evidence record must state whether a notification was sent, not applicable,
or covered by a parent dispatcher path. Evidence records are metadata only; they
must not approve, transition, dispatch, close, commit, or mutate authority
state. The current path matrix is maintained in
`ai/reports/report-000012-20260517-close-commit-notification-path-matrix.md`.

When the SOP requires close/commit approval, use:

```sh
node ai/runtime/dist/cli.js request --method runtime.executor.runSummary --params '{"recommendation":"close","askCloseCommit":true,...}'
```

When a chunk has reached completion evidence, prefer deriving the Telegram
summary from the chunk markdown instead of retyping it:

```sh
node ai/runtime/dist/cli.js request --method runtime.executor.runSummary --params '{"fromChunk":"ai/chunks/active/chunk-000000-example.md","recommendation":"close","askCloseCommit":true,...}'
```

The compact Telegram message uses the chunk final summary `Good`, `Bad`,
`Ugly`, and `Next` sections. Plain `/details` stores the richer markdown
details, including `Details`, `Root Cause`, `Drift Mechanism`, `Policy
Enforcement`, `Validation`, and `Next` content.
When carry-forward state is included, `/details` should use the registry or
Runtime carry-forward projection and distinguish blocking from non-blocking
warnings, advisories, compatibility debt, pending enforcement, observations,
and follow-ups.

The helper must report summary delivery and approval-question creation as
separate outcomes. Telegram `summary sent` is not approval. The close/commit
approval is answered through `ai/standards/operator-questions.md` and executed
through the deterministic dispatcher/trusted daemon path documented in
`ai/standards/runtime-tooling-governance.md`.

Approval bypasses are forbidden. `workflow-approve-action.sh
--preapproved-source` may only be used by registered approval paths that have
already validated a concrete operator decision or trusted daemon action. Free
text, inferred operator intent, rejected Telegram replies, stale replies, chat
messages, or Codex memory are not valid preapproval sources.

If autonomous/deemed continuation is active, Runtime Executor must still emit a
non-actionable Telegram summary/notice that names the autonomous authority basis
before any close/commit execution path completes. Autonomous authority is not
silent authority.

Run-boundary summaries and close/commit approvals are exactly-once per stable
`--run-id`. Retrying the same run id must not enqueue another compact
`Orchestration run finished` message and must not create another approval
question. If the operator may take time to respond, Codex should stop after the
single summary and single approval request are recorded; the Telegram bridge,
operator-question store, dispatcher, and daemon retain the durable state for a
later resume.

The Telegram bridge is transport-only for this flow. Summary creation, details
payload storage, approval-question creation, dedupe, supersession, and
summary-before-approval ordering are Runtime Executor responsibilities. The
bridge may send queued messages and consume inbound replies, but it must not
decide whether a summary or approval should exist.

## Telegram Bridge Service Boundary

The current Telegram bridge is a shell compatibility service. Runtime-owned
TypeScript code may read bridge status, delivery health, outbox lag, sent
receipts, and failed-send receipts, but it must not create a second live
`getUpdates` consumer or bypass the shell bridge sender/poller until a later
chunk explicitly migrates that ownership.

Migration should proceed in small adapters:

- Status/delivery-health reader: TypeScript owns structured status projection
  from `.tmp/telegram-dev-bridge`.
- Receipt parser: TypeScript owns typed sent/failed receipt parsing and
  redaction rules.
- Outbox drain/send adapter: TypeScript may own delivery only after the shell
  bridge delegates to it or is replaced behind the same process facade.
- Polling adapter: TypeScript may own `getUpdates` only after the shell bridge
  stops polling, so the bot never has two competing consumers.

Shell wrappers remain compatibility/process facades until a migration chunk
removes that status deliberately. Telegram tokens and chat ids must stay out of
status projections, failed receipts, socket payloads, and UI fields.

When a run summary creates an approval question, the compact summary must be
sent first and the approval question second. The Telegram helper should flush
the summary before emitting the approval question when the bridge is reachable;
otherwise the bridge loop must still drain the queued messages in timestamp
order.

Plain Telegram `/details` returns the latest run summary in this canonical
shape from `ai/standards/runtime-sop.md`. It should be richer than the compact
Telegram notification while staying mobile-readable. Do not dump raw JSON unless
the operator explicitly asks for raw machine output.

This is a notification, not an approval request.

## Autonomous Completion Notifications

When `authority_to_continue_autonomously` / `autonomous_mode=deemed` is active,
Runtime Executor must use the same canonical run-summary rendering path, but the
operator-facing compact summary is framed as a chunk completion note rather
than a run-finished approval request:

- `Chunk autonomously completed`: compact chunk summary derived from the
  canonical chunk summary sections.
- `Chunk autonomously approved`: non-actionable note that the autonomous
  approval boundary has been satisfied by delegated authority.
- `Chunk autonomously committed`: non-actionable note from the guarded
  dispatcher after close/commit completes.

These messages must not request an operator reply. They must be backed by
approved-action metadata:

- `autonomous_mode=deemed`
- `audit_label=authority_to_continue_autonomously`
- `operator_note=closed and committed autonomously`

Manual mode keeps the normal approval-request framing. The distinction must be
implemented and tested in Runtime Executor, approved-action records, dispatcher
execution, and Telegram/operator surfaces; role prompts are not authority.

## Significant Insight Notes

Codex may send a compact Telegram note during a run when it discovers something
that affects design, workflow reliability, runtime architecture, safety, or
future planning.

Send a note for:

- a design-significant limitation.
- a runtime architecture weakness.
- a recurring workflow bug.
- a safety boundary or platform limitation.
- an insight that should change future standards, chunks, or product direction.

Do not send a note for:

- minor bugs that are fixed immediately.
- transient test failures with no design impact.
- ordinary progress updates.
- noisy command output.

Notes should be one short paragraph and should not ask for approval unless a
human decision is actually required.

Use the Runtime-owned progress-note surface for notes:

```sh
node ai/runtime/dist/cli.js runtime progress-note --note "<short note>" --category cfd_relevant --cfd-relevant
```

Routine progress notes are recorded but filtered from Telegram by default.
CFD-relevant notes, or notes sent with `--notify`, are queued through Runtime
Executor and the existing Telegram bridge. The note surface must bound and
redact content, source it to a role, and set `mutates_authority_state=false`.
Do not scrape chat messages or send ad hoc Telegram messages directly from role
prompts.

Allowed note categories are `progress`, `cfd_relevant`, `validation`,
`handoff`, `governance`, and `diagnosis`. Notes must not ask for freeform
replies. Use a real operator question only for `freeform_input_required`,
`operator_decision_required`, or `approval_required` events.
