# 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 `DashboardApp` — `DashboardApp` 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.ts` → `adapter.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|task|link|file`. For `task` also write an `awareness` row so it surfaces in `nextActions`; for `file` route through `POST /api/ingest`. **Substrate:** `memory_frames` (personal `.mind`), `awareness`. No migration. | | `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.