Skip to content

Matrix3D: push-based activity via WS /api/activity, retire sqlite subprocess poller (Phase B) #202

@Interstellar-code

Description

@Interstellar-code

Summary

Matrix3D office page (src/screens/matrix3d/) currently derives agent activity by polling each Hermes profile's state.db directly via a Python subprocess every 4s from the SwitchUI server (src/routes/api/crew-status.ts). This is schema-coupled, brittle, has no real-time fidelity, and lacks true delegation identity.

Replace it with a push-based consumer once the gateway exposes a global activity feed.

Blocked on: Interstellar-code/hermes-agent#132 (Phase A — gateway matrix-activity plugin: WS /api/activity + GET /api/activity/recent).

Work

  1. Open ONE WebSocket to /api/activity via the existing /ws-hermes proxy pattern. Drive the office state machine from typed events:
    • subagent_start → character walks to desk, speech bubble = the actual child_goal.
    • tool.start / tool.complete → desk monitor content.
    • subagent_stop → character walks away / returns to idle.
    • on_session_start / on_session_end → main-agent (HERMES) presence.
  2. Seed initial state from GET /api/profiles/sessions (cross-profile list, server-computed is_active, each row tagged with profile) — replaces the per-profile sqlite reads for first paint.
  3. Delete the SwitchUI-side Python subprocess sqlite reader in src/routes/api/crew-status.ts (the readCrewOwnActivity / readDelegatedChildSessions embedded-Python paths) and the 4s polling plumbing in use-matrix3d-office-data.ts.
  4. Keep src/lib/crew-delegation.ts assignment logic only if still needed for avatar mapping; the gateway now provides real subagent_id/role, so most of the heuristic assignment can be retired.

Context

Current interim state (already landed, uncommitted at time of writing): crew-status reads each profile's own state.db for ground-truth recency + lists active delegated child sessions from the hermes-switch db, with a pure assignDelegatedSessions avatar mapper. That was the stopgap to fix desync; this issue is the proper push-based replacement.

Prior root-cause analysis: the three legacy "working" signals (gateway ?profile= filtering, keyword-guessed delegation, name-fuzzy matching) were all dead — see session notes. delegate_task args carry no agent identity, which is exactly why Phase A surfaces subagent_start/subagent_stop hook payloads (parent_session_id, child_session_id, child_role, child_goal).

Acceptance

  • Matrix3D drives all character animation from the /api/activity WebSocket; no sqlite subprocess remains.
  • Delegating a task lights up the correct worker character with the real goal text in its bubble within one event round-trip (not a 4s poll).
  • Reconnect re-seeds from /api/activity/recent + /api/profiles/sessions.

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