VibeAround
InternalsModules

Module: workspace

src/core/src/workspace/ — the conversation state model: workspaces, threads, route attachments, and handover codes. If channels is the postal service, this module is the filing system deciding which conversation every...

Documentation notice: these docs are currently generated with Codex and are being actively reviewed, expanded, and refined.

src/core/src/workspace/ — the conversation state model: workspaces, threads, route attachments, and handover codes. If channels is the postal service, this module is the filing system deciding which conversation every letter belongs to.

Responsibility

Own all persistent conversation state and its runtime counterparts. Three event-sourced stores (workspaces, threads, route attachments) plus an in-memory map of live ThreadRuntimes. Everything the Concepts page describes is implemented here.

Key types

TypeFileRole
WorkspaceThreadManagermanager.rsThe orchestrator: route→thread resolution, thread creation/close, attachments, external session binding, idle shutdown
ThreadRuntimethreads/runtime.rsOne live thread: host agent handle, session id, busy/failed state, subagents, prompt serialization
WorkspaceEventStore / ThreadEventStore / RouteAttachmentEventStorestore.rs, threads/store.rs, threads/attachment.rsAppend-only JSONL logs + projection replay
WorkspaceThread / ThreadProjectionthreads/store.rsPersistent thread record: status, host binding, agent sessions, multi-agent turns
HostBindingthreads/store.rs(agent id, profile id) pair hosting a thread
handoverhandover.rs4-char / 120 s one-shot pickup codes

Interactions

  • ← channels: every prompt/command lands on WorkspaceThreadManager.
  • → agent: ThreadRuntime::ensure_agent spawns Agent (which registers with process::Supervisor).
  • → profiles: host binding's profile is materialized at agent spawn.
  • → launch_sessions: external session resolution during handover/resume.
  • → state: implements StateSource so dashboards poll runtime_entries + subscribe to changes.

Invariants — do not break

  1. Persist before apply: every state change is an event appended to its store before observable behavior depends on it; a crash replays to the same state.
  2. One open thread per route: resolve_route_runtime holds the per-route lock across check-create-attach; new resolution paths must take the same lock.
  3. A thread's agent spawn is single-flight (spawn_lock in ThreadRuntime) and prompts on one thread are serialized (prompt_lock); cancel intentionally bypasses the prompt lock — preserve that or cancellation dies.
  4. Closed is terminal for a thread id; reopening means a new thread.
  5. Session ids are observations, not ownership — the agent's own storage is authoritative; never fabricate one.

Known debt

  • Projections re-read and replay whole JSONL files on the hot path; thread/workspace stores never compact (attachments do). Remediation H1 — the top-priority fix.
  • ThreadRuntime is 10 independent mutexes with manually maintained busy/failed shadows; planned actor-model rewrite (remediation H2, with the supervisor-tree milestone).
  • route_locks map never prunes entries (remediation L8).
  • RouteKey::as_key() drops bot_id — latent for multi-bot futures (remediation L9).

Source anchors: src/core/src/workspace/ (manager, threads/, handover, registry, store), reports/architecture-review-remediation-2026-07-04.md (H1, H2, L8, L9). Last verified: v0.7.11

On this page