Skip to content

[Gastown] Rig DO Event Log — Append-Only Bead Events for Real-Time Dashboard Feed #344

@jrf0110

Description

@jrf0110

Parent: #204 | Priority: P0 — Required for real-time activity feed

Problem

The product vision requires a live activity feed on the town dashboard showing "beads created, agents spawned, mail sent, molecules advancing, merges completed." But there is no event log anywhere in the system. The Rig DO mutates state (creates beads, updates statuses, sends mail) but doesn't write an append-only event stream.

The gastown_bead_events table was described in the original proposal but was never implemented in the DO SQLite schema. Without it, the dashboard has no source of truth for "what happened" — only "what is the current state."

What This Enables

  1. Town-wide activity feed — SSE/polling endpoint that returns recent events across all rigs
  2. Bead detail timeline — "Created by Mayor at 14:32 → Assigned to Toast at 14:32 → Hooked at 14:33 → Status changed to in_progress at 14:35 → Closed at 15:12"
  3. Future Postgres replication — Events can be synced to Postgres for analytics
  4. Debugging — Trace exactly what happened to any bead

Implementation

1. Add bead_events table to Rig DO SQLite

CREATE TABLE bead_events (
  id TEXT PRIMARY KEY,
  bead_id TEXT NOT NULL,
  agent_id TEXT,
  event_type TEXT NOT NULL,  -- 'created', 'assigned', 'hooked', 'unhooked', 'status_changed', 'closed', 'escalated', 'mail_sent', 'agent_spawned', 'agent_exited'
  old_value TEXT,
  new_value TEXT,
  metadata TEXT DEFAULT '{}',
  created_at TEXT NOT NULL
);
CREATE INDEX idx_bead_events_bead ON bead_events(bead_id);
CREATE INDEX idx_bead_events_created ON bead_events(created_at);

2. Write events on every state mutation in Rig DO

  • createBead() → write created event
  • hookBead() → write hooked event (with agent_id)
  • unhookBead() → write unhooked event
  • updateBeadStatus() → write status_changed event (with old/new)
  • closeBead() → write closed event
  • sendMail() → write mail_sent event
  • agentDone() → write closed + unhooked events
  • registerAgent() / agent status changes → write agent_spawned / agent_exited events

3. Expose events via HTTP

New handler: GET /api/rigs/:rigId/events?since=<iso-timestamp>&limit=<n>

Returns events newer than since, ordered by created_at. Default limit 100.

4. Town-wide event aggregation

New endpoint on the gastown worker: GET /api/towns/:townId/events?since=<iso-timestamp>

Fans out to all Rig DOs in the town, merges and sorts events. This drives the dashboard activity feed. For Phase 1, simple polling (every 3-5s). For Phase 3, SSE.

Acceptance Criteria

  • bead_events table in Rig DO SQLite schema
  • Events written on all state mutations (bead, agent, mail)
  • GET /api/rigs/:rigId/events endpoint
  • GET /api/towns/:townId/events endpoint (fan-out across rigs)
  • Events include enough context for the dashboard to render meaningful descriptions
  • Bead detail panel can show full event timeline

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions