Files
waggle-os/docs/ux-refactor/gap-cards/S01-home-cockpit.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

15 KiB

Gap Card — S01 Home Cockpit

Execution model: in-place incremental refactor of apps/web + targeted backend extensions. PRD source of truth: §12.1 (lines 373-410), §15 (data model), §16.1 (API), §20.1 (keep/promote). Mockup screen_01_home_cockpit.png is directional — acceptance criteria win over pixels.


1. Screen & purpose

Home Cockpit is the daily executive briefing and launch surface — the first thing the user sees after boot, before opening any workspace. PRD §12.1: "Give the user a useful daily briefing and immediate next actions." Acceptance bar (§12.1): user understands the day in <30 s, continues a workspace in one click, opens Ctrl+K from the keyboard, and captures a note/task/link/file from Home.

This is a new top-level surface in the IA spine (PRD §1: spine item #1). Today there is no Home Cockpit; the closest things are the per-workspace WorkspaceBriefing (chat home screen) and the modal LoginBriefing (one-shot catch-up overlay). The mockup shows six regions: greeting + date, "You were working on" (recent workspaces with Continue), "Overnight" (consolidated / artifacts / failures counters), "Up next" (events/tasks), "Suggested next actions", "Quick capture", and an "Active models" tile.


2. Required states (PRD §12.1 + Blueprint p.265/447)

Functional requirements (§12.1):

  • Greeting with user name + date/time.
  • Active/recent workspaces ranked by recency and priority, each with one-click Continue.
  • Overnight summary: memories consolidated, artifacts created, automations completed, failures.
  • Upcoming meetings/events/tasks ("Up next").
  • Suggested next actions (memory/session/task/schedule-derived).
  • Quick capture for note/task/link/file.
  • Active models + current mode, only if relevant (do not clutter).
  • Ctrl+K hint/access.

States to implement (§12.1 "States" + Blueprint line 447): Loading · First-run empty · Normal populated · Attention required · Offline/local-only · Overnight failure · Permission denied for shared/team data.


3. Current state in repo — disposition: partial (keep-promote + create-new)

PRD §20.1 explicitly: WorkspaceBriefing.tsx → "seed for Home Cockpit widgets" (keep and promote). There is no HomeCockpit component today — it is a §20.3 "Create" item. So the work is: extract reusable widget logic from the two existing briefing surfaces, build a new full-screen HomeCockpit, and wire it to a new cross-workspace aggregation endpoint.

Existing files that feed this screen:

File What it does Reuse role
apps/web/src/components/os/WorkspaceBriefing.tsx (283 LOC) Per-workspace "home screen" inside ChatApp when a chat has no messages. Fetches GET /api/workspaces/:id/context; renders greeting, stats bar, pending tasks, recent decisions, "I Remember" memories, recent threads, cross-workspace hints, persona skill chips, suggested prompts, upcoming schedules. Collapse state persisted per-workspace via lib/workspace-briefing-state. Keep-promote. Its section components (memory list, pending tasks, decisions, suggested-prompt chips, upcoming schedules) are the widget vocabulary the Cockpit reuses. It is per-workspace, so it can't be the Cockpit as-is.
apps/web/src/components/os/overlays/LoginBriefing.tsx (363 LOC) Modal "I remember…" catch-up shown once after boot. Already does cross-workspace aggregation client-side: getWorkspaces() → per-workspace getWorkspaceContext() (N calls) + searchMemory('…','global') + getMemoryStats(). Builds workspace summaries (memoryCount/sessionCount/lastActive/summary/pendingTasks), ranked memory highlights (lib/briefing-highlights), brag header (lib/login-briefing-brag), time-aware greeting + identity name. Has first-run empty hook (3 demo bubbles). Filters E2E/test workspaces. Keep-promote (heaviest reuse). Its data-gathering and ranking is exactly the Cockpit's "You were working on" + greeting + first-run-empty logic — but it does the N+1 fan-out on the client, which §20.4 forbids ("do not duplicate backend state calculation in frontend"). Promote this logic into the new GET /api/home/briefing server route.
apps/web/src/components/os/apps/DashboardApp.tsx Dock app home — Workspaces grid (select/create/open chat), brain-health tier. Currently the thing the home dock key opens. Rework/keep. Becomes the workspaces-grid sub-view; Home Cockpit becomes the new default home surface. Not the briefing itself.
apps/web/src/components/os/apps/CockpitApp.tsx (315 LOC) "Cockpit" = system/ops dashboard (health, cost, crons, connectors, weaver, event stats, compliance). Dock id cockpit. Name collision only — this is the ops Command-Center surface, NOT the PRD Home Cockpit. Out of scope / do not conflate. Maps to PRD §12.3-ish ops, not §12.1. Flag the naming clash.
apps/web/src/components/os/cockpit/ComplianceDashboard.tsx EU AI Act compliance tiles, hosted inside CockpitApp. Not relevant to S01.

Supporting lib (frontend, reuse as-is): lib/briefing-highlights.ts (selectBriefingHighlights — importance-then-recency ranking), lib/login-briefing-brag.ts (computeBragSummary/formatBragLine/timeAgo), lib/workspace-briefing-state.ts (collapse persistence), lib/persona-display.ts, lib/skill-recommendations.ts (persona skill chips). Note: lib/suggested-actions.ts is for chat follow-up chips (regex over the last assistant message) — it is NOT the Home "suggested next actions" generator; do not reuse it for the Cockpit. Suggested actions for Home come from buildWorkspaceState().nextActions (backend) aggregated cross-workspace.

Backend builder already present (keep-promote, §20.1): packages/server/src/local/workspace-state.ts buildWorkspaceState() → typed WorkspaceState (active/openQuestions/pending/blocked/completed/stale/ recentDecisions/nextActions) with freshness classification. This is the per-workspace next-action engine the Home briefing aggregates over.


4. Frontend work

Create apps/web/src/components/os/apps/HomeCockpitApp.tsx (new top-level surface; register in Desktop.tsx appConfig + renderAppContent, and make the home dock key open it instead of DashboardAppDashboardApp demotes to a "Workspaces" grid reachable from a Cockpit tile/Ctrl+K).

Widget components (extract from the two briefing files so logic is shared, not copy-pasted — CLAUDE.md "many small files"):

  • home/GreetingHeader.tsx — greeting + name + date/time (promote from LoginBriefing lines 84-95 + WorkspaceBriefing greeting). Reuse buildTimeAwareGreeting semantics from backend; client just renders.
  • home/RecentWorkspacesPanel.tsx — "You were working on": ranked workspace cards w/ Continue button → openChatForWorkspace(id) (via useWindowManager). Promote LoginBriefing summaries list (lines 277-334).
  • home/OvernightPanel.tsx — counters (consolidated / artifacts / automations done / failures); failure rows expandable → Automation Center. New (no current equivalent).
  • home/UpNextPanel.tsx — upcoming events/tasks/schedules. Reuse upcomingSchedules + pendingTasks shapes; aggregate across workspaces.
  • home/SuggestedActionsPanel.tsx — top N nextActions aggregated from buildWorkspaceState, each routing to its workspace. Not lib/suggested-actions.ts.
  • home/QuickCapturePanel.tsx — note/task/link/file input → POST /api/quick-capture. New.
  • home/ActiveModelsTile.tsx — promote ModelPilotCard / useProviders; render only when relevant.

Data layer:

  • New hook hooks/useHomeBriefing.tsadapter.getHomeBriefing() + adapter.getOvernight(), with the §12.1 state machine (loading/empty/populated/attention/offline/overnight-failure/permission-denied).
  • Extend lib/adapter.ts (the single sidecar gateway) with getHomeBriefing(), getOvernight(), quickCapture(payload). Per the frontend inventory, all PRD §16 endpoints get added here.
  • First-run empty: reuse LoginBriefing's demo-bubble hook (lines 222-247).
  • Offline/local-only: reuse useOfflineStatus; degrade overnight/team tiles, keep local workspaces.
  • Ctrl+K hint: surface the existing GlobalSearch (Ctrl+K) — already wired in useKeyboardShortcuts.

Decision required (Open Q): does LoginBriefing (modal) survive alongside Home Cockpit, or does the Cockpit absorb it? They overlap ~80%. Recommend: collapse LoginBriefing into the Cockpit's first paint and retire the modal (avoid two catch-up surfaces).


5. Backend work (PRD §16.1)

PRD endpoint Status Plan
GET /api/home/briefing MISSING NET-NEW route (new routes/home.ts registered in local/index.ts). Server-side aggregation that promotes LoginBriefing's client N+1 fan-out: iterate workspaceManager workspaces → reuse per-workspace logic already in routes/workspaces.ts /context handler (greeting/summary/recentMemories/pendingTasks/upcomingSchedules) + buildWorkspaceState() (workspace-state.ts) for nextActions, ranked by recency/priority. Reuse briefing-highlights ranking server-side. Substrate touched: memory_frames (per-workspace .mind), session JSONL, awareness, cron-store. No new store. Refactor over EXTEND: factor the /context body into a shared builder so /context and /home/briefing don't duplicate SQL.
POST /api/quick-capture PARTIAL EXTEND routes/memory.ts (or thin new handler delegating to it). Closest existing write is POST /api/memory/frames. Quick-capture = thin wrapper: default to personal mind, stamp source: 'quick-capture', accept `kind ∈ note
GET /api/home/overnight MISSING NET-NEW route (same routes/home.ts). Aggregate from existing substrates — no new store: cron/automation runs via GET /api/cron/:id/history (notifications.ts) + cron-store; consolidation/artifact counts from events.ts audit events (GET /api/events?since=) and weaver status (/api/weaver/status); failures from cron history error rows + notifications. Returns { consolidated, artifactsCreated, automationsCompleted, failures[] }. The Overnight failure state is driven by failures.length > 0.

Notes for the implementer:

  • Reuse, don't reinvent (§20.4): the per-workspace catch-up math lives in routes/workspaces.ts lines 311-592 and workspace-state.ts. Extract the shared body before adding the cross-workspace loop.
  • Privacy gate (CRITICAL — already bit us): cross-workspace content aggregation was previously a privacy leak. routes/workspaces.ts lines 553-564 show crossWorkspaceHints is deliberately DISABLED (returns []) because the original iterated every workspace MindDB and returned content snippets with no grant check (security review: cowork/Code-Review_MultiMind_April-2026.md Critical #1). GET /api/home/briefing is the SAME pattern (read every workspace) — but for Home it is the user's own workspaces, so it is legitimate for personal scope. Team/shared workspace rows must respect approvalGrantStore / team RBAC (PRD §12.1 Permission denied for shared/team data state). Do not leak team-workspace content the caller can't access.
  • Tier: Home briefing must work on FREE/TRIAL (it's the daily landing surface). Team-overnight rows are TEAMS-gated; gate the team slice, not the whole endpoint.

No .mind schema migration required. All three endpoints read existing tables (memory_frames, awareness, audit events) and write only via existing frame/awareness paths. (PRD §15.4 confidence/ provenance fields are a separate, later migration — not needed for S01.)


6. Shared types needed (PRD §15 vs lib/types.ts)

Today lib/types.ts has WorkspaceContext (lines 66-85) — per-workspace, already carries greeting/recentMemories/pendingTasks/upcomingSchedules/crossWorkspaceHints. Reuse its sub-shapes.

Add new interfaces (in lib/types.ts, mirrored server-side):

  • HomeBriefing { greeting; date; recentWorkspaces: RecentWorkspaceCard[]; suggestedActions: SuggestedAction[]; upNext: UpNextItem[]; activeModels?; isFirstRun: boolean }
  • RecentWorkspaceCard { id; name; group; summary?; lastActive; pendingCount; continueSessionId? }
  • OvernightSummary { consolidated: number; artifactsCreated: number; automationsCompleted: number; failures: OvernightFailure[] }
  • OvernightFailure { id; label; automationId?; error; at }
  • QuickCaptureInput { kind: 'note'|'task'|'link'|'file'; content; workspaceId? }
  • SuggestedAction { label; workspaceId; sessionId?; kind }

Align kinds with PRD §15.2 (MemoryKind, ArtifactKind) where they overlap. These are net-new vs the current lib/types.ts (which has no Home/Overnight/QuickCapture types).


7. Dependencies (screens/phases first)

  • AppShell / IA (Sprint 1, PRD §21): Home Cockpit is the default landing surface — needs the dock home key repointed and the §10 IA buckets settled first.
  • Command Center (Ctrl+K) (S03): §12.1 acceptance "open Ctrl+K from the keyboard" — GlobalSearch already exists, so this is a soft dep (hint only).
  • Workspace Desktop (S02): "Continue" routes into the per-workspace runtime; needs openChatForWorkspace (already in useWindowManager) — soft dep.
  • Automation Center (S11): overnight failure rows link there; can ship Home with the count + a stub link.
  • Belongs to Sprint 2 ("Home and workspace state") per PRD §21 — after shell, alongside the workspace-context/state API extension.

8. Effort: L

Frontend is mostly promotion of two existing briefing surfaces into shared widgets (medium), but the backend adds two net-new aggregation routes (/home/briefing, /home/overnight) that must (a) refactor the per-workspace /context body into a shared builder to avoid duplication and (b) re-implement the cross-workspace aggregation safely behind the grant/RBAC gate that previously caused a privacy leak. The security-sensitive cross-workspace read is what pushes this from M to L. Not XL — no new data store, no schema migration, and the ranking/greeting logic already exists.


9. Open questions

  1. LoginBriefing fate: retire the modal and absorb its catch-up into Home Cockpit's first paint, or keep both? (~80% overlap; two catch-up surfaces is confusing.)
  2. "Overnight" semantics: time-window = since last app close? since midnight local? last 12 h? Affects the since= query for events/cron history.
  3. Cross-workspace personal read: confirm reading the user's own workspaces server-side (for the briefing) is acceptable now that it's same-user (the prior leak was content snippets without grant checks). Team/shared rows still gate through approvalGrantStore/RBAC — confirm the gate boundary.
  4. home vs cockpit naming: CockpitApp already owns "Cockpit" (ops). PRD calls S01 "Home Cockpit". Final dock/app naming to avoid the collision (proposal: S01 = home/"Home"; keep ops as cockpit).
  5. DashboardApp role: does the Workspaces grid live as a Cockpit tab, a Ctrl+K destination, or stay a separate dock app? (Affects whether home dock key fully repoints to HomeCockpit.)
  6. Quick-capture file flow: does a file capture upload into a default/personal store, or prompt for a target workspace? POST /api/ingest needs a destination.