Daily harness signal

Async hooks observe; sync hooks govern

August 19, 2026 · JST One fresh finding Codex · hooks · policy
Codex 0.148 turns previously skipped asynchronous hooks into live background processes. Before upgrading, separate observers from gates, then prove that delayed output cannot authorize or block the triggering action.
01 · Fresh · source date 2026-08-18

Audit dormant async hooks before they wake up

Use when: upgrading Codex CLI to 0.148.0, importing hooks, or enabling a plugin containing hooks. A command handler marked async: true was previously parsed but skipped outside SessionEnd; it now runs in the background. Any “pre” hook that operators thought was dormant can therefore begin making network calls, writing files, or emitting context after the triggering operation has already continued.

Action: inventory user, project, managed, and plugin hook definitions before rollout. Keep enforcement handlers—command denial, input rewriting, approval decisions, and completion gates—synchronous. Reserve async: true for bounded telemetry, notifications, and advisory analysis whose late result is harmless. In a staging workspace, configure one delayed asynchronous PreToolUse canary that writes an owned sentinel and returns a block request; configure a synchronous twin against a second harmless command. Open /hooks and record each handler’s displayed Mode. Trigger both commands, preserve hook start/completion receipts, then inspect when the sentinel and any model-visible context arrive. Keep SessionEnd synchronous.

Acceptance check: pass only if /hooks labels the canary Async, the first harmless command proceeds without waiting and is not blocked or rewritten, and its sentinel appears later at a safe turn boundary. The synchronous twin must delay or block its command as configured. Shutdown must cancel unfinished async work, and no sentinel may leak into another thread. Fail the rollout if an async handler can change the originating operation, if completion is unreceipted, or if concurrency exceeds the intended per-session bound.

Evidence: OpenAI’s dated 0.148.0 changelog says hooks can now run commands asynchronously. Merged PR #37533 contains the runtime contract and unit/integration coverage for scheduling, concurrency, output delivery, reload, and shutdown; PR #37538 exposes sync/async mode in hook listings. The current hooks guide still says asynchronous handlers are unsupported, making the merged implementation and release boundary the safer authority.

Caveat: asynchronous means non-authoritative, not safe. The process still receives event data and can cause external side effects on its own. Review commands and credentials, set timeouts and output limits, and treat delayed model context as untrusted observation. Documentation is temporarily contradictory, so pin 0.148.0 and rerun this canary after upgrades.

Compact source notes

  1. OpenAI, ChatGPT & Codex changelog (2026-08-18). Official stable 0.148.0 release entry: asynchronous command hooks are now active; links PR #37533.
  2. openai/codex PR #37533 (merged 2026-08-08). Primary implementation with 29 changed files and tests for scheduling, bounded per-session concurrency, delayed delivery, reload, and shutdown.
  3. openai/codex PR #37538 (2026-08). Primary follow-up exposing executionMode through hooks/list and the TUI.
  4. OpenAI Codex hooks guide (retrieved 2026-08-19). The page still says async is parsed but unsupported, a point-in-time documentation conflict with the stable release and merged implementation.
  5. Method: anchor lens—stable release, merged code, and regression coverage; unity lens—observation and execution authority are separate planes joined by hook identity and receipts. Confidence: Confirmed for 0.148.0 behavior; documentation lag remains.