feat(host-service): host sessions sync v1 — canonical sessions over tRPC snapshots + /sessions/sync

Draft
BR
4mo ago
+16867-5936

What

The simplified v1 of the host sessions surface — the agent-agnostic session/thread/event model that mobile and web sync against. One squashed commit, rebased on main.

Read this first: plans/host-sessions-sync.md — the single design doc, structured as three review layers (1: principles + budgets, 2: state ownership + surface + recovery, 3: one realistic scenario with exact payloads), plus rollout and the E2E gym story.

Shape

  • Budgets (hard): 9 tRPC procedures · 12 socket packet types · 2 opaque incarnation-tagged cursor kinds · 1 automatic recovery path + the existing "restart host" hammer.
  • Snapshots ride tRPC (sessions.list/get carry the head cursor); the /sessions/sync socket carries only small frames; subscribe.after is required.
  • Claimless client tool calls: cards render on every device, first resolve wins.
  • Recovery = the cold path re-run per stream, guarded by a client circuit breaker (3 resets / 30 s → error).
  • camelCase everywhere on the wire; inputs AND outputs schema-validated at the router.

Evidence

  • 602 host-service src tests, 46 protocol/client tests, 11-test realistic-scenario suite (mid-stream disconnect, scrollback parity vs the full journal, session switching under load, host reboot with exactly one reset).
  • Gym user story 10/10 with a real Opus instance on this exact surface (ACP_E2E=1 bun test test/integration/sessions-user-story.integration.test.ts).
  • Known gap (pinned by a test, fixed by the durable store next): a host-reboot journal rebuild loses causationId attribution.

Also in here

Doc consolidation: the old protocol/rollout pair and the stale Mastra/ACP-era chat docs are deleted (−5.7k lines); direction recorded — ACP gets replaced by a direct SDK adapter behind this unchanged surface (deferred, prototype in claude-sdk-session-harness), Mastra chat stays frozen for existing desktop users and is never used by mobile.

Out of scope (deferred)

Direct SDK adapter / ACP removal, host control-plane extension (workspace lifecycle etc. — see the "Trajectory" section in the doc). Next up after this: durable history store, React bindings + mobile rewire, Maestro phone replay.

https://claude.ai/code/session_01N98A6Rs53rLfRb8Qf5pM3Y


Open in Stage

Summary by cubic

Ships v1 of Host Sessions sync: a canonical session/thread/event model with tRPC snapshots and a lightweight WebSocket for live updates. Adds sessions.*, /sessions/sync, a shared protocol package, and a small client store; cleans up old Mastra/ACP docs.

  • New Features

    • New @superset/host-service-sync package with zod-validated protocol, a shared projection reducer, and a framework-free zustand client (createSessionsSyncClient).
    • Host sessions.* tRPC (snapshots via list/get, idempotent receipts, camelCase wire) and /sessions/sync hub (hello/ack, subscribe.after from head, replay/reset with invalid/expired cursor handling).
    • Canonical runtime that translates ACP into canonical events and serves both tRPC and the hub; claimless client tool-call resolves; host and client fold the same reducer.
    • Documentation consolidated into plans/host-sessions-sync.md; removed stale Mastra/ACP-era docs.
  • Migration

    • No breaking changes; legacy Mastra chat remains for existing users. This surface is gated.
    • To adopt: fetch sessions.list/sessions.get to seed, then open /sessions/sync and send subscribe.after using the returned head cursor; on reset, refetch the snapshot and resubscribe.
    • The reference client lives in @superset/host-service-sync (createSessionsSyncClient).