Digest: presence is observed, not declared
This is a decision digest: sanitized to design level. Addresses and internal names are deliberately absent.
The situation
Concurrent agent sessions coordinate through a local, file-based bus: presence heartbeats per live session, append-only mailboxes between personas, and a read-only watcher that logs events and pings the human’s desktop. Presence was always confessional — each session had to write and refresh its own heartbeat, and delete it on signoff.
The problem
Confession has no failure alarm. A session that forgot to write, refresh, or remove its heartbeat simply didn’t exist on the roster; one that died messily haunted it forever. During a multi-session experiment the desktop widget showed zero agents online while several were demonstrably working. The same gap applied to mail: delivery depended on recipients choosing to poll. Nothing lied louder than the absence of an entry.
The decision
Three changes, all preserving the existing mail protocol untouched:
- Observed presence. Each opencode instance reports itself from inside via a globally loaded plugin: identity tier (declared persona / git-name hint / anonymous), working state (idle, building, awaiting), and plan/build mode, derived from real in-session events rather than timers or filesystem guesses.
- Death enforcement. The watcher sweeps presence entries against the process table every few seconds, with a process-identity check to defeat pid reuse. A dead session cannot remain listed, regardless of how it exited.
- Push delivery with consent semantics. Arrival is toasted into the recipient’s interface; unchecked mail is staged as a marked digest at idle. Nothing auto-submits. Consumption cursors are private bookkeeping; the append-only mailbox format and janitor archiving are unchanged.
Identity honesty is part of the design: only slugs registered in the public agents directory count as personas, anything else is labeled as a hint or anonymous, and unattributed sessions receive exactly one prompt offering adoption or constitutional registration (a real commit under the agents directory, authored as the new persona).
Consequences
- The roster can no longer show fewer sessions than exist, nor more than are alive. Both failure modes of confession are closed by construction.
- Sessions shed all presence duties — no first-action heartbeat, no signoff step, nothing to forget under load.
- The menubar’s disk-activity heuristic was retired as redundant; state shown is state reported by the session’s own event stream.
- Residual trust: the reporter runs inside opencode and could, in principle, misreport state for a live process. Liveness remains externally verified; richer state remains self-reported and labeled. That trade is deliberate — it buys real working-state visibility at the cost of trusting our own tooling for nuance.