Skip to content

Optional executor→supervisor wake edge (cross-session doorbell) — Codex-native, pilot first #25

Description

@levi-qiao

Problem / motivation

In loop-graph, when the executor closes a milestone it flips the ledger gate to
pending-audit and then keeps cheap-ticking until the supervisor's next
scheduled wake
happens to notice it. The supervisor polls; it is never told.
On interval hosts this adds latency and burns idle ticks.

Idea: an event-driven wake — when the executor flips a gate to pending-audit
(or writes a terminal ledger status), it rings the supervisor directly instead of
letting it poll. Record the supervisor's address (host + session/thread id) in
ops.md at setup; the executor uses it to signal.

Design (in octopus terms)

  • This is a new directed edge (executor → supervisor), not a new node. Add it
    per the model.md / CONTRIBUTING edge rules.
  • A doorbell on the mailbox, not a second mailbox. The wake is content-free
    ("go read the ledger now"). All state stays in the ledger (single writer =
    executor, unchanged
    ). On wake the supervisor does exactly what it does on a poll:
    read ledger → audit the pending-audit gate. → no second scoreboard, invariants
    intact.
  • ops.md holds the supervisor address (host + session/thread id): operational
    metadata, written once at setup, config-like — not a contended edit, not the
    ledger, not directives. Label it best-effort routing (it can go stale).

Host support (researched against source)

  • Codex — ✅ native. First-class thread-coordination tools:
    send_message_to_thread(threadId, msg) (+ wait_threads, create_thread,
    handoff_thread). Executor →
    send_message_to_thread(<supervisor threadId from ops.md>, "M2 pending-audit")
    wakes/queues a turn on the supervisor thread. (Codex Desktop surface.)
  • grok — ❌ no native cross-session wake. Read the source:
    /loopscheduler_create delivers only to its own parent_session_id
    (input fields: task_id/interval/prompt/recurring/durable/foreground/fire_immediately
    no target-session field). The Notification hook fans out to external
    HTTP/shell (owner ping), not into another session. session_admin = fork / rename /
    delete only. The leader IPC (unix socket) is multi-view on one agent, not
    agent-to-agent messaging. → keep poll/park on grok.
  • Claude Code / Cursor / shell. Claude Code's adaptive self-paced re-invoke already
    minimizes park latency; no cross-session inject. shell: you own both loops — a
    touch + the other loop's poll is the crude equivalent.

Must be an optimization, not a replacement

Recorded session ids go stale (ephemeral sessions; grok's scratch dir is deleted
when a goal ends; Codex threads can be archived). Keep the interval-poll / adaptive
re-invoke as the guaranteed backstop
; the wake only cuts latency. Same slot as the
existing grok hooks — "optional reliability upgrade, not required for the base
pattern."

Irony worth recording

The wake helps most on interval hosts (grok / Cursor / shell) where the supervisor
sleeps a fixed cadence — but the main interval host, grok, can't do it. The host
that can (Codex) is adaptive, so the win is smaller (still real: precise wake the
instant the gate flips, and the supervisor loop can sit truly idle between rings
instead of cheap-ticking).

Governance / next step (do not merge into templates yet)

Per the anti-bloat rule, no pattern enters the templates without a real consumer.
Pilot on one real Codex loop-graph run and confirm both:

  1. the ring actually re-activates an idle supervisor thread, and
  2. with the session id removed/stale, the poll/adaptive backstop still catches
    the pending-audit gate (graceful degrade).

If it holds:

  • add a "cross-session wake" capability row to lib/host-dialects.md
    (Codex ✅ · grok ❌ · Claude Code ➖ self-paced covers it · Cursor ❌ · shell ⚠️
    you own both loops), and
  • add an optional wake step to the executor + supervisor templates — host
    specifics behind host-dialects.md, templates staying host-agnostic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions