moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,219 @@
# 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 a
`switch(win.appId)` (`:276-360`); a workspace "opens" only as `case 'chat'`
`<ChatWindowInstance>` (`:278-296`). There is **no `case 'workspace'`** and no tabbed runtime.
Apps are floating windows (`AppWindow` chrome), 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. Fetches `GET /api/workspaces/:id/context` via `adapter.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 via `useRoomState` SSE
(`: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`** — add `case 'workspace'` to `renderAppContent` + an `appConfig.workspace`
entry; route `openChatForWorkspace` callers that should open the *desktop* (not a chat window) to a
new `openWorkspace(workspaceId)`. Decide window-vs-fullscreen (recommend full-bleed window using
existing maximize path in `AppWindow.tsx` to avoid a parallel layout system). **Surgical** — do
not refactor the window manager.
- **`useWindowManager.ts`** — add `workspace` to the `AppId` consumption; reuse `workspaceId` field
already on `WindowState`. No new state shape.
- **Embed existing apps as tab panels** — Memory/Timeline/Chat/Settings render their existing
components scoped by `workspaceId` (already accepted props on `TimelineApp`, `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. Reuse `useRoomState` for 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`, `Confidence` literal unions** (PRD §15.2) — **none exist** in
`apps/web/src/lib/types.ts` (substrate-types §e). Add `WorkspaceType` + `WorkspaceStatus`
(`active`/`paused`/`archived`) for header.
- **`Workspace``WorkspaceConfigV2` alignment** (PRD §15.3) — FE `Workspace` (`types.ts:22-40`)
lacks `type`, `status`, `description`, `updatedAt`, `lastActiveAt` and uses `persona` vs config's
`personaId`. Add the 5 missing fields (optional) for header/last-activity; keep DERIVED display
fields.
- **`WorkspaceState` type** — exists server-side (`workspace-state.ts:38-55`) but is **not mirrored**
in FE `types.ts`. Add a FE `WorkspaceState` mirror for the new `getWorkspaceState` method.
- **`Task` type** — `lib/types.ts` has no Task interface (server `tasks.ts` shape only). Add one for
the Tasks tab.
- **`Artifact` type** — **greenfield** (PRD §15.6). Owned by S05; S02 imports it once defined.
- `WorkspaceContext` already exists in `types.ts` (consumed by `WorkspaceBriefing`) — 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 new `route`/`activeWorkspaceId`
global state + the `case '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 the
`memory_frames` metadata 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
1. **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.
2. **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 `ChatApp` must run in two render modes.
3. **`workspace.type` taxonomy.** PRD §15.2 names `WorkspaceType` but no enum values are given. Derive
from the 15 existing `workspace-templates` categories, or define a new fixed set?
4. **`status` lifecycle.** Who/what sets `paused`/`archived` (manual header action vs automation)?
PRD §12.2 lists the status states but not the transitions.
5. **Share scope.** `POST /api/share` is 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?
6. **Tasks store of record.** Tasks tab — back onto the existing `/api/workspaces/:id/tasks` store, or
model tasks as `pending`/`blocked` `StateItem`s from `WorkspaceState` (which are session/awareness-
derived, not first-class)? These are two different sources of truth to reconcile.