16 KiB
Gap Card — S02 · Workspace Desktop
Screen S02 of the Waggle OS UX-refactor. PRD §12.2 (lines 412-447). Execution model: in-place incremental refactor of
apps/web+ targeted sidecar extensions. Mockup (screen_02_workspace_desktop.png) is directional; PRD acceptance criteria win. Every claim grounded in repo source (paths cited).
1. Screen & purpose
Purpose (PRD §12.2): the primary runtime for a single bounded work context. It demotes chat from "the whole product" to one widget among many, surfacing workspace state, artifacts, memory, tasks, research, and activity on a single screen, with chat/agent interaction co-resident.
Mockup reading (Waggle_OS_Handoff_Assets/screen_02_workspace_desktop.png): a full-screen
(non-floating) layout for "Germany GTM Strategy" with:
- Left nav rail — Workspaces / Memory / Agents / Automations / Files / MCP Hub / Connectors + favourites + user tile.
- Header — workspace name + status pill ("Active"), team avatar stack, Share button, global search.
- Tab bar — Overview · Chat · Research · Artifacts · Memory · Tasks · Timeline.
- Main canvas (Overview tab) — multi-widget grid: AI workspace/chat preview, Key Artifacts list, Tasks list, Memory highlights, Research overview (donut), Recent activity feed.
- Right panel — Workspace info, Members, Last activity, quick actions.
- (Implied) status bar — agents running / automations active / MCPs connected.
The blueprint text page for "Screen 2 — Workspace Desktop" (
_blueprint_extracted.txt:675) is an image-only placeholder; the only textual spec is PRD §12.2 + the §0/§9/§19 spine references (_blueprint_extracted.txt:15,42,63,274,513,585).
2. Required states (PRD/Blueprint)
Functional requirements (PRD §12.2, lines 423-430):
- Header: workspace name, type, status, team/avatar stack, share controls.
- Tabs: Overview, Chat, Research/Notes, Artifacts, Memory, Tasks, Timeline, Settings.
- Main canvas widgets: AI workspace/chat, key artifacts, tasks, memory highlights, research overview, recent activity.
- Right panel: workspace info, members, last activity, quick actions.
- Bottom/status bar: agents running, automations active, MCPs connected.
- Fixed default layout initial release; configurable widgets deferred to a later phase.
States (PRD §12.2, lines 432-441): No memory · Active work · Agent running · Artifact ready · Task blocked · Sync conflict · Permission denied · Offline.
Acceptance criteria (PRD §12.2, lines 443-447):
- Chat is one widget, not the whole product.
- Workspace state is always visible.
- User can reach memory, artifacts, agents, skills, tasks, automations, and settings from the workspace.
Cross-cutting (Blueprint §state-rules): server-derived state — "Home Cockpit and Workspace
Desktop must use server workspace-state/context APIs" (_blueprint_extracted.txt:513); cache
invalidation on memory import / artifact update / agent-run completion / connector sync / automation
completion / RBAC change (:514).
3. Current state in repo
Disposition: create-new (the tabbed Workspace Desktop screen does not exist), reusing existing
substrate heavily. There is no workspace-runtime surface today. The closest analog is a
chat-only floating window:
apps/web/src/components/os/Desktop.tsx— root OS shell.renderAppContent()is aswitch(win.appId)(:276-360); a workspace "opens" only ascase 'chat'→<ChatWindowInstance>(:278-296). There is nocase 'workspace'and no tabbed runtime. Apps are floating windows (AppWindowchrome), not a full-screen workspace surface.appConfig(:77) has no workspace entry.apps/web/src/components/os/apps/ChatWindowInstance.tsx— per-window wrapper: owns model fetch + per-window persona/autonomy, renders only<ChatApp>(:221-248). Chat is the whole window — the exact inversion PRD §12.2 forbids.apps/web/src/components/os/WorkspaceBriefing.tsx— ChatApp "home screen" shown when a session has no messages. FetchesGET /api/workspaces/:id/contextviaadapter.getWorkspaceContext()(:57) and renders greeting / stats / pending tasks / recent decisions / "I Remember" memories / recent threads / cross-workspace hints / suggested prompts / upcoming schedules. This is the single best reuse seed — it already consumes the "Workspace Now" block the Overview tab needs, but it lives inside chat and is read-only (no artifacts, no tasks CRUD, no tabs, no right panel).apps/web/src/components/os/apps/DashboardApp.tsx— Workspaces grid (select/create/open-chat). This is the workspace list (S01-adjacent), not the per-workspace runtime.apps/web/src/components/os/apps/RoomApp.tsx— live sub-agent tiles viauseRoomStateSSE (:24); the "agents running" status indicator can be derived from this per-workspace.apps/web/src/components/os/overlays/ContextRail.tsx— right-side rail for a clicked frame/entity (ContextRailTarget); a reuse target for the right-panel detail pattern, but it is an overlay keyed to a single frame, not a persistent workspace info/members/activity panel.
Tabs that already have a host component (to embed, not rebuild): Memory → MemoryApp.tsx,
Timeline → TimelineApp.tsx, Chat → ChatWindowInstance/ChatApp, Settings →
SettingsApp.tsx. Tabs with NO host: Overview (new), Research/Notes (new), Artifacts (no
backing entity at all — see §5), Tasks (store exists server-side, never wired to FE — see §4/§5).
Adapter gap (confirmed by grep on apps/web/src/lib/adapter.ts): getWorkspaceContext (:272),
getWorkspaceFiles (:277), getPins/addPin (:1353/:1361), getDocuments (:1371) exist;
no getTasks / getWorkspaceState / getWorkspaceActivity methods (0 matches). So the Tasks
list, the /state Overview source, and the activity feed have no client plumbing yet.
4. Frontend work
Components to create
| Component | Role | Reuse / source |
|---|---|---|
apps/WorkspaceApp.tsx (new) |
Full-screen workspace runtime shell: header (name/type/status/avatars/Share) + Tabs + right panel + status bar. Owns activeTab state. |
components/ui/tabs.tsx; header layout from StatusBar.tsx + chat-header-layout.ts; tab gating via useFeatureGate. |
workspace/OverviewTab.tsx (new) |
Default tab: widget grid (chat preview, key artifacts, tasks, memory highlights, research, recent activity). | Port the read-only sections of WorkspaceBriefing.tsx (greeting/decisions/memories/threads) into widget cards; add artifacts/tasks/activity widgets. |
workspace/WorkspaceInfoPanel.tsx (new) |
Right panel: info, members, last activity, quick actions. | Members from adapter.getTeamMembers(); "last activity" from new activity hook; quick actions raise waggle:open-app. ContextRail stays a separate frame-detail overlay. |
workspace/TasksTab.tsx (new) |
Task list/board for the workspace. | Net-new FE; backs onto existing /api/workspaces/:id/tasks (server store exists, FE plumbing missing). |
workspace/ResearchTab.tsx (new) |
Research/Notes surface. | Lightweight: notes-as-frames (memory) + wiki pages (adapter.getWikiPages). Lowest-fidelity tab; can ship as "notes" v1. |
workspace/ArtifactsTab.tsx (new) |
Artifacts grid (see S05 dependency). | Backs onto new /api/artifacts (net-new) or interim file-registry view via getWorkspaceFiles/getDocuments. |
Components to rework / wire
Desktop.tsx— addcase 'workspace'torenderAppContent+ anappConfig.workspaceentry; routeopenChatForWorkspacecallers that should open the desktop (not a chat window) to a newopenWorkspace(workspaceId). Decide window-vs-fullscreen (recommend full-bleed window using existing maximize path inAppWindow.tsxto avoid a parallel layout system). Surgical — do not refactor the window manager.useWindowManager.ts— addworkspaceto theAppIdconsumption; reuseworkspaceIdfield already onWindowState. No new state shape.- Embed existing apps as tab panels — Memory/Timeline/Chat/Settings render their existing
components scoped by
workspaceId(already accepted props onTimelineApp,ChatWindowInstance).
Adapter methods / hooks to add (lib/adapter.ts — the one contract surface)
getWorkspaceState(id)→GET /api/workspaces/:id/state(Overview; PARTIAL backend, §5).getWorkspaceActivity(id, {limit})→GET /api/workspaces/:id/activity(activity feed; PARTIAL, §5).getTasks(workspaceId)/createTask/updateTask/deleteTask→/api/workspaces/:id/tasks*(routes EXIST, adapter methods MISSING).- New hook
useWorkspaceDesktop(workspaceId)composing state + activity + tasks + members + fleet (agents-running) + cron (automations) + capabilities/status (MCPs-connected) for the status bar. ReuseuseRoomStatefor live agents.
5. Backend work
Per PRD §16.2 plus the substrate the Overview/widgets/status-bar need. Cross-referenced against
backend-routes inventory + backend-map 03c.
| PRD §16 endpoint | Status | Extend vs net-new · substrate · migration |
|---|---|---|
GET /api/workspaces/:id |
EXISTS | workspaces.ts. Header name/team. But type+status fields are MISSING on WorkspaceConfig (hive-mind-core/src/workspace-manager.ts:5-58) — additive JSON fields, no DB migration (workspace.json file). Default status:'active'; derive type from templateId/group. |
PATCH /api/workspaces/:id |
EXISTS | workspaces.ts. Used for status change / Share controls. Stamp updatedAt in update() (workspace-manager.ts:222, currently unstamped). |
GET /api/workspaces/:id/context |
EXISTS | workspaces.ts:311 — the "Workspace Now" block (buildWorkspaceNowBlock(), workspace-context.ts:191-404). Direct feed for Overview widgets (greeting/decisions/memories/threads/pending/schedules). |
GET /api/workspaces/:id/state |
PARTIAL → EXTEND | No /state route. buildWorkspaceState() (workspace-state.ts:234-311) already produces active/openQuestions/pending/blocked/completed/stale/recentDecisions/nextActions and is surfaced inside /context as workspaceState. Add a thin /state route returning that sub-object directly (Overview/Tasks consume pending+blocked as task seeds). Substrate: memory_frames + session JSONL + awareness. No migration. |
GET /api/workspaces/:id/activity |
PARTIAL → EXTEND | No per-workspace /activity. Closest: GET /api/events?workspaceId= (events.ts) and GET /api/teams/:id/activity. Add a thin /activity alias over the audit-event query (substrate: ai_interactions/execution_traces/events). No migration. |
Tasks: GET/POST /api/workspaces/:id/tasks, PATCH/DELETE …/:taskId |
EXISTS (server) | tasks.ts (backend-routes §1.7). Only FE plumbing missing — no net-new backend. |
| Status bar feeds | EXISTS, no aggregate | agents → GET /api/fleet (fleet.ts); automations → GET /api/cron (cron.ts); MCPs connected → GET /api/capabilities/status (mcpServers[]) / install_audit. Compose client-side in v1; an aggregate /status route is optional. |
| Members / Share | PARTIAL | Members → GET /api/team/members (EXISTS). Share → PRD §16.11 POST /api/share is MISSING (grep-confirmed, backend-routes §16.11). Header Share button is net-new backend; for non-team workspaces it can be a no-op/disabled in v1. |
| Artifacts widget/tab | MISSING (largest gap) | No Artifact entity, table, or /api/artifacts* route anywhere (substrate-types §e; backend-routes §16.6). Interim: render the file registry GET /api/workspaces/:id/files (workspaces.ts) + document versions GET /api/workspaces/:id/documents (documents.ts) as "artifacts". Full Artifact Center is S05's scope — S02 should depend on it, not build it. |
Migration flag: the only .mind SQLite migration adjacent to this screen is the optional
memory_frames.metadata/confidence/kind additions (substrate-types §c) needed for richer Memory
filters — not required for S02's Overview/Tasks/Timeline tabs; defer to S04 (Memory Center).
S02's own missing fields (type, status, updatedAt, lastActiveAt) are JSON-file additive — no
DB migration.
6. Shared types needed (PRD §15 vs lib/types.ts)
WorkspaceType,Scope,Confidenceliteral unions (PRD §15.2) — none exist inapps/web/src/lib/types.ts(substrate-types §e). AddWorkspaceType+WorkspaceStatus(active/paused/archived) for header.Workspace→WorkspaceConfigV2alignment (PRD §15.3) — FEWorkspace(types.ts:22-40) lackstype,status,description,updatedAt,lastActiveAtand usespersonavs config'spersonaId. Add the 5 missing fields (optional) for header/last-activity; keep DERIVED display fields.WorkspaceStatetype — exists server-side (workspace-state.ts:38-55) but is not mirrored in FEtypes.ts. Add a FEWorkspaceStatemirror for the newgetWorkspaceStatemethod.Tasktype —lib/types.tshas no Task interface (servertasks.tsshape only). Add one for the Tasks tab.Artifacttype — greenfield (PRD §15.6). Owned by S05; S02 imports it once defined.WorkspaceContextalready exists intypes.ts(consumed byWorkspaceBriefing) — reuse for Overview.
7. Dependencies (screens / phases first)
- Phase 1 (Shell + Ctrl+K) —
_blueprint_extracted.txt:582— must land first: this screen is opened from the shell/route map and the left nav. S02 needs the newroute/activeWorkspaceIdglobal state + thecase 'workspace'shell wiring. - Phase 2 (Home + Workspace) —
_blueprint_extracted.txt:585— S02 ships with S01 (Home Cockpit); both share/api/workspaces/:id/context+/state. S01's cross-workspace briefing reuses S02's per-workspace builder. - S05 Artifact Center — hard dependency for the Artifacts tab/widget (entity +
/api/artifacts*are entirely net-new there). S02 must ship the Artifacts tab as an interim file-registry view if S05 is not ready. - S04 Memory Center — the Memory tab embeds
MemoryApp; richer confidence/kind filters (and thememory_framesmetadata migration) live there, not in S02. - S03 Command Center (Ctrl+K) — the header search + quick actions route through the command provider.
8. Effort
XL. Net-new full-screen tabbed runtime that re-architects the product's primary surface (chat →
one-widget), needs 5-6 new FE components + several adapter methods/hooks, 2 thin backend routes
(/state, /activity) + workspace type/status/updatedAt/lastActiveAt additive fields, and
is gated on S05 (Artifacts) for one full tab. The read-only Overview seed exists
(WorkspaceBriefing), which keeps it from being 2×XL, but the shell-integration + tab embedding +
status-bar aggregation breadth dominate.
9. Open questions
- Window vs full-screen. Should the Workspace Desktop be a maximized
AppWindow(reuse existing window manager + chrome) or a dedicated full-bleed route bypassing the floating-window system? The mockup is full-screen; the current OS is windowed. Recommend maximized-window to avoid a parallel layout system — needs founder/eng confirmation. - Chat-as-widget vs Chat-tab. PRD says "chat is one widget" (Overview) AND lists a "Chat" tab.
Is the Overview chat widget a live mini-composer or a read-only preview that deep-links to the Chat
tab? Affects whether
ChatAppmust run in two render modes. workspace.typetaxonomy. PRD §15.2 namesWorkspaceTypebut no enum values are given. Derive from the 15 existingworkspace-templatescategories, or define a new fixed set?statuslifecycle. Who/what setspaused/archived(manual header action vs automation)? PRD §12.2 lists the status states but not the transitions.- Share scope.
POST /api/shareis net-new (PRD §16.11). Is Share in S02's MVP, or stubbed until Team Workspace (S10)? For a solo/non-team workspace, what does Share do? - Tasks store of record. Tasks tab — back onto the existing
/api/workspaces/:id/tasksstore, or model tasks aspending/blockedStateItems fromWorkspaceState(which are session/awareness- derived, not first-class)? These are two different sources of truth to reconcile.