Skip to content

Bridge wake path: remaining checks and follow-ups after #122 #154

Description

@evansenter

Follow-ups left after #122 closed. Written to be self-sufficient: a session
pointed here should not need the thread that produced it.

Orientation

The re-awakening bridge (RFC #122) wakes an idle Claude Code session by
typing a fixed prompt into its terminal pane, so a DM reaches a session whose
human is away instead of waiting for the next prompt.

State of the bus host (mac-mini.local, as of 2026-08-16)

  • Multiplexer in use is zellij 0.44.3, not tmux (tmux 3.7b is installed and
    the backend supports it, but no session runs under it).
  • The bridge LaunchAgent is installed with AGENT_EVENT_BUS_BRIDGE_BACKEND=mux
    (injecting). /health reports registered: true.
  • wake/panes.json is {}. Sessions map themselves at SessionStart, so
    any session started before dotfiles#338 merged is unmapped and unwakeable
    until it restarts. An empty file is normal, not a fault.
  • Hooks are live immediately on merge: ~/.claude/settings.json is a
    symlink into the dotfiles repo. The bridge plist is not — it is a copy in
    ~/Library/LaunchAgents, so plist changes need make install-bridge.

1. Reboot ← the one that needs a human

The actual supervision requirement (RunAtLoad plus login), never verified
because it needs the host restarted.

After the next reboot:

launchctl list | grep agent-event-bus          # both jobs present
curl -s http://127.0.0.1:8082/health           # registered: true
grep "Wake injection available via" ~/.claude/contrib/agent-event-bus/agent-event-bus-bridge.err | tail -1

The third line is the one that matters: it must name the multiplexers found on
launchd's PATH, which is narrower than a shell's.

2. ZELLIJ_PANE_ID uniqueness across a full pane set

The writer trusts $ZELLIJ_PANE_ID to identify a pane within a zellij session.
Verified directly: a single-pane session, and cross-tab addressing (pane 0 in
tab 1 accepted a write while tab 2 was focused). Not verified: that the id
stays unique and stable across a session's full pane set in daily use —
splits, closes, reopens.

To check: in one zellij session, open several panes across tabs, and in each
run echo $ZELLIJ_PANE_ID. Confirm no two share an id, then confirm each is
addressable:

zellij --session <name> action dump-screen -p <id> --path /tmp/probe.txt

Failure shape: a wake typed into the wrong pane of the right session, which
looks exactly like the stale-mapping symptom and would be easy to misdiagnose.

3. No established minimum zellij version

Only 0.44.3 has been exercised, so docs/BRIDGE.md names no floor. The
injection surface is zellij --session <n> action write-chars -p <pane> plus
action write -p <pane> 13; -p is the part most likely to differ across
versions.

A spool-mux-failed now carries zellij's own stderr, so a CLI-surface mismatch
is self-diagnosing — but the floor is still unknown. Worth pinning if this ever
runs on a second machine.

4. Optional: per-tool-call marker refresh

--busy-ttl defaults to 1 hour because the only refresh in the default wiring
is UserPromptSubmit. A turn that outruns it reads as idle for the remainder,
so a late DM can inject mid-turn.

Any hook firing during a turn can run agent-event-bus-cli wake-state busy to
make the marker a heartbeat, allowing a much lower TTL. Not wired by default:
it costs a subprocess per tool call. Do this only if long turns turn out to be
common here.

5. The verification-boundaries rule only covers half its problem

CLAUDE.md (#148) says host-specific claims must be marked unverified rather
than asserted. That catches a claim made without evidence. It does not
catch the inverse, which #153 then had to fix twice:

Both are caveats that outlived their uncertainty, with nothing forcing them
to track reality. Same root cause as the rule's original target: prose asserts
in one voice whether or not anything was run, and nothing re-checks it when the
world changes.

Worth extending the rule to say that a resolved caveat is a defect like any
stale claim, and that whoever resolves one is responsible for grepping for its
copies. Not urgent; it is a documentation-discipline change, not a code one.

Out of scope here

docs/BRIDGE.md names several older follow-ups that predate this work and are
not part of this issue: fsync-on-append for spool writes, pruning spools
for dead sessions, list_sessions-based machine scoping (v2), periodic webhook
re-assertion, and a systemd unit for Linux. Don't fold them in.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions