diff --git a/.gitignore b/.gitignore index 1281dfc..6b1620b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,8 +27,11 @@ logs/security/ # Runtime data .adc/ -# Claude Code session artifacts (local-only, events sync to Hub) -.claude/progress/ +# Workflow plugin runtime data (ephemeral, not committed) +.claude/progress/*/events.jsonl +.claude/progress/*/current.md +.claude/progress/*/history.md +.claude/progress/index.md .claude/teams/ .claude/tasks/ .claude/settings.json diff --git a/CLAUDE.md b/CLAUDE.md index 92717e8..83fe2ba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -112,7 +112,7 @@ If tests don't exist for the area you're modifying, **that doesn't exempt you fr > that future agents read. If agent docs are stale, agents produce wrong code, which wastes time and money. > **Failing to update docs is the same as shipping broken code. Treat it that way.** -`npm run check:docs` enforces that source changes include doc updates. Accepted doc paths: `ai-docs/`, `docs/plans/`, `docs/progress/`, `.claude/agents/`, `docs/tracker.json`, and `CLAUDE.md`. Use this mapping to know which docs to update: +`npm run check:docs` enforces that source changes include doc updates. Accepted doc paths: `ai-docs/`, `docs/plans/`, `.claude/agents/`, `docs/tracker.json`, and `CLAUDE.md`. Use this mapping to know which docs to update: | Change Type | Docs to Update | |-------------|----------------| @@ -122,10 +122,9 @@ If tests don't exist for the area you're modifying, **that doesn't exempt you fr | New shared utility | `FEATURES-INDEX.md` (shared sections), `CODEBASE-GUARDIAN.md` (placement rules) | | UI layout changes | `user-interface-flow.md` (UX flow sections), `FEATURES-INDEX.md` (layouts) | | New feature module | `FEATURES-INDEX.md` (feature table), `ARCHITECTURE.md` (system diagram if applicable) | -| Gap resolution | `user-interface-flow.md` (mark gap RESOLVED with date and description) | | New pattern or convention | `PATTERNS.md` (pattern example with code), **ALL relevant agent files** | | Feature plan or design doc | `docs/plans/-plan.md` (implementation plan) | -| Plan lifecycle changes | `docs/tracker.json` (update status, add new entry) | +| Plan lifecycle changes | `docs/tracker.json` | | Any change to file structure, imports, or conventions | **ALL `.claude/agents/*.md` files that reference the affected area** | **Checklist before committing — ALL items are mandatory:** diff --git a/ai-docs/CODEBASE-GUARDIAN.md b/ai-docs/CODEBASE-GUARDIAN.md index 6085eed..3dcd16a 100644 --- a/ai-docs/CODEBASE-GUARDIAN.md +++ b/ai-docs/CODEBASE-GUARDIAN.md @@ -40,15 +40,11 @@ |------|----------|------| | `tracker.json` | `docs/tracker.json` | Single source of truth for plan status. MUST be updated when plans change status. | | `validate-tracker.mjs` | `scripts/validate-tracker.mjs` | Validation script — do not move. | -| Active plans | `docs/plans/` | Plans with status DRAFT, APPROVED, IN_PROGRESS, BLOCKED, TRACKING | -| Active progress | `docs/progress/` | Progress files for features currently being implemented | -| Archived plans | `doc-history/plans/` | Plans with status IMPLEMENTED, SUPERSEDED, ABANDONED, ARCHIVED | -| Archived progress | `doc-history/progress/` | Progress files for completed features | - -**Archival rules:** -- Plans with status `IMPLEMENTED` or `SUPERSEDED` that are older than 14 days should be archived -- When archiving: `git mv` the file to `doc-history/`, update `docs/tracker.json` paths, set status to `ARCHIVED` -- `npm run validate:tracker` must pass after any archival operation +| Active plans | `docs/plans/` | Plans with status DRAFT, APPROVED, IN_PROGRESS, TRACKING | + +**Cleanup rules:** +- Plans for features with status `IMPLEMENTED` that are older than 14 days should be deleted and their tracker entry removed +- `npm run validate:tracker` must pass after any cleanup operation ### Feature Module Structure (MANDATORY) diff --git a/ai-docs/FEATURES-INDEX.md b/ai-docs/FEATURES-INDEX.md index 8bf4b7a..ecb6f30 100644 --- a/ai-docs/FEATURES-INDEX.md +++ b/ai-docs/FEATURES-INDEX.md @@ -296,6 +296,7 @@ The IPC contract has been split from a single monolithic file into **27 domain f | `data-management` | Data store registry, retention settings, cleanup, usage, export/import (8 invoke + 1 event) | | `security` | Security settings, audit export (3 channels) | | `window` | Window controls (minimize, maximize, close, isMaximized) | +| `tracker` | Plan tracker (list, get, update docs/tracker.json via IPC) | | `workflow` | Workflow execution | Each domain folder contains: @@ -608,19 +609,14 @@ npm run format # Prettier format | `DRAFT` | Initial write-up, not yet approved | | `APPROVED` | Design approved, ready for implementation | | `IN_PROGRESS` | Currently being implemented | -| `BLOCKED` | Implementation blocked by external dependency | | `IMPLEMENTED` | Code merged and working | -| `SUPERSEDED` | Replaced by a newer plan (see `supersededBy` field) | -| `ABANDONED` | Decided not to implement | -| `ARCHIVED` | Completed and moved to `doc-history/` | +| `ARCHIVED` | Completed and removed from active tracking | | `TRACKING` | Living document (roadmap, etc.) — no implementation phase | ### File Organization -- **Active plans**: `docs/plans/` — plans currently in backlog or in progress -- **Active progress**: `docs/progress/` — crash-recovery files for active features -- **Archived plans**: `doc-history/plans/` — completed/superseded plans -- **Archived progress**: `doc-history/progress/` — progress files for completed features +- **Plans**: `docs/plans/` — design docs for active and recently completed features +- **Tracker**: `docs/tracker.json` — single source of truth for plan status (v2 schema) --- diff --git a/ai-docs/prompts/implementing-features/AGENT-SPAWN-TEMPLATES.md b/ai-docs/prompts/implementing-features/AGENT-SPAWN-TEMPLATES.md index 9265f9d..13c4979 100644 --- a/ai-docs/prompts/implementing-features/AGENT-SPAWN-TEMPLATES.md +++ b/ai-docs/prompts/implementing-features/AGENT-SPAWN-TEMPLATES.md @@ -321,7 +321,7 @@ When starting a new feature, the Team Lead follows this sequence: ``` 1. READ the design document 2. DECOMPOSE into tasks with dependencies -3. CREATE progress file: docs/progress/-progress.md +3. UPDATE `docs/tracker.json`: add entry with status `IN_PROGRESS` 4. CREATE team: TeamCreate with team_name 5. CREATE tasks: TaskCreate for each task with descriptions + acceptance criteria 6. SET dependencies: TaskUpdate with addBlockedBy for each task diff --git a/ai-docs/prompts/implementing-features/PROGRESS-FILE-TEMPLATE.md b/ai-docs/prompts/implementing-features/PROGRESS-FILE-TEMPLATE.md index 1b4a80f..ff7deaa 100644 --- a/ai-docs/prompts/implementing-features/PROGRESS-FILE-TEMPLATE.md +++ b/ai-docs/prompts/implementing-features/PROGRESS-FILE-TEMPLATE.md @@ -1,6 +1,6 @@ # Progress File Template -> Copy this to `docs/progress/-progress.md` when starting a new feature. +> Template for crash-recovery progress tracking. Used by the workflow plugin in `.claude/progress/`. --- diff --git a/ai-docs/prompts/implementing-features/README.md b/ai-docs/prompts/implementing-features/README.md index 0dc71af..fc1610f 100644 --- a/ai-docs/prompts/implementing-features/README.md +++ b/ai-docs/prompts/implementing-features/README.md @@ -43,8 +43,7 @@ PLAN ──▶ TRACK ──▶ ASSIGN ──▶ BUILD+DOCS ──▶ TEST ── │ │ └─ TeamCreate, TaskCreate with dependencies, │ │ spawn agents with full initialization │ │ - │ └─ Create progress file at docs/progress/-progress.md - │ Update tracker.json: add entry with status IN_PROGRESS + │ └─ Update tracker.json: add entry with status IN_PROGRESS │ └─ Read design doc, decompose into tasks, identify agent roles, map dependencies. @@ -78,7 +77,7 @@ The Team Lead MUST update `docs/tracker.json` at each lifecycle transition: | Work blocked | Set status to `BLOCKED` | | Implementation complete | Set status to `IMPLEMENTED` | | Feature superseded | Set status to `SUPERSEDED`, set `supersededBy` field | -| Feature archived | Move files to `doc-history/`, update paths, set status to `ARCHIVED` | +| Feature archived | Delete plan file, remove tracker entry or set status to `ARCHIVED` | Always update `statusChangedAt` when changing status. Run `npm run validate:tracker` to verify. @@ -92,9 +91,7 @@ Claude Code sessions can terminate unexpectedly (terminal close, timeout, proces ### The Progress File -**Location**: `docs/progress/-progress.md` - -The Team Lead MUST create this file BEFORE spawning any agents, and update it after EVERY significant state change (agent complete, agent failed, phase transition). +Progress is tracked via the team's TaskList and the `.claude/progress/` runtime directory (auto-managed by the workflow plugin). The Team Lead updates tracker.json status after each phase transition. **When to update the progress file:** - After creating the team and tasks @@ -163,7 +160,7 @@ If resuming from crash: The Team Lead must update `docs/tracker.json` at these lifecycle points: - **New feature**: Add entry with status `IN_PROGRESS` - **Feature complete**: Set status to `IMPLEMENTED` -- **Feature archived**: Move files to `doc-history/`, update paths, set status to `ARCHIVED` +- **Feature archived**: Delete plan file, remove tracker entry or set status to `ARCHIVED` - **Feature superseded**: Set status to `SUPERSEDED`, set `supersededBy` field Run `npm run validate:tracker` to verify tracker integrity after any changes. @@ -172,7 +169,7 @@ Run `npm run validate:tracker` to verify tracker integrity after any changes. When a Team Lead agent starts and detects existing progress: -1. Read `docs/progress/-progress.md` +1. Check `docs/tracker.json` for feature status 2. Run `git worktree list` to verify worktree state 3. Check if the team still exists (read `~/.claude/teams//config.json`) 4. If team exists: use `TaskList` to get current state, resume from first pending task @@ -272,7 +269,7 @@ Claude-UI/ │ ├── ipc-contract.ts # THE source of truth for IPC │ ├── constants/ # Theme constants, route paths │ └── types/ # Domain type definitions -└── doc-history/ # Archived planning docs +└── docs/tracker.json # Plan status tracker (v2) ``` ### Updating the Structure @@ -655,7 +652,7 @@ Use this checklist when starting any new feature implementation: 1. READ design doc / plan 2. DECOMPOSE into tasks with dependencies -3. CREATE progress file at `docs/progress/-progress.md` +3. UPDATE `docs/tracker.json`: add entry with status `IN_PROGRESS` 3b. UPDATE tracker: Add entry to `docs/tracker.json` with status `IN_PROGRESS` 4. CREATE team via TeamCreate 5. CREATE tasks via TaskCreate with proper `blockedBy` relationships diff --git a/doc-history/2026-02-13-assistant-built-in-design.md b/doc-history/2026-02-13-assistant-built-in-design.md deleted file mode 100644 index f947a8a..0000000 --- a/doc-history/2026-02-13-assistant-built-in-design.md +++ /dev/null @@ -1,931 +0,0 @@ -# Built-In Persistent Assistant — Full Design - -**Date**: 2026-02-13 -**Status**: IMPLEMENTED — all tasks complete, typecheck + lint clean -**Scope**: Remove standalone Assistant page, embed assistant into top nav as a global command bar, wire Slack/GitHub webhooks through Hub for external task creation, replace regex intent classifier with Claude API. - ---- - -## 1. Philosophy - -The assistant is NOT a chatbot page. It is a **background service** embedded in the app shell — always reachable from the top nav, always listening via webhooks. Its job: take cognitive load off the user by turning natural language from any source (keyboard, Slack, GitHub) into real actions (tasks, notes, time blocks, reminders). - -No mock data. No stubs. Every path either executes a real action against a real service, or tells the user exactly what configuration is missing. - ---- - -## 2. Architecture - -``` - ┌───────────────────────────────────────────┐ - │ Electron App │ - │ ┌────────────────────────────────────┐ │ - │ │ Command Bar (top nav) │ │ - │ │ [icon] [___________________] [⏎] │ │ - │ └───────────┬────────────────────────┘ │ - │ │ IPC: assistant.sendCommand │ - │ ┌───────────▼────────────────────────┐ │ - │ │ Assistant Service (main) │ │ - │ │ ┌──────────┐ ┌────────────────┐ │ │ - │ │ │ Fast Path│ │ Claude API Path│ │ │ - │ │ │ (regex) │ │ (structured) │ │ │ - │ │ └────┬─────┘ └───────┬────────┘ │ │ - │ │ └───────┬─────────┘ │ │ - │ │ ▼ │ │ - │ │ Command Executor │ │ - │ │ ┌─────┬──────┬──────┬─────────┐ │ │ - │ │ │Notes│Tasks │Plann.│Alerts │ │ │ - │ │ │Svc │Svc │Svc │Svc │ │ │ - │ │ └─────┴──────┴──────┴─────────┘ │ │ - │ └────────────────────────────────────┘ │ - │ ▲ │ - │ │ WebSocket (hub relay) │ - └──────────────┼────────────────────────────┘ - │ - ┌──────────────┼────────────────────────────┐ - │ Hub Server (Docker) │ - │ │ │ - │ ┌───────────┴────────────────────────┐ │ - │ │ Webhook Router │ │ - │ │ POST /api/webhooks/slack │ │ - │ │ POST /api/webhooks/github │ │ - │ └───────────┬────────────────────────┘ │ - │ │ │ - │ ┌───────────▼────────────────────────┐ │ - │ │ Webhook Processor │ │ - │ │ - Validates signatures │ │ - │ │ - Extracts command text │ │ - │ │ - Creates task/note in Hub DB │ │ - │ │ - Broadcasts to Electron via WS │ │ - │ │ - Responds to Slack/GitHub │ │ - │ └────────────────────────────────────┘ │ - └───────────────────────────────────────────┘ - ▲ ▲ - │ │ - ┌──────────────┘ └──────────────┐ - │ Slack GitHub │ - │ /claude or @Claude @claudeassistant│ - │ in any channel/thread in PR comments │ - └─────────────────────────────────────────┘ -``` - -### Why the Hub handles webhooks (not Electron directly) - -1. **Always reachable** — Hub runs 24/7 in Docker. Electron may be closed. -2. **Public URL** — Hub can be exposed via nginx/cloudflare. Electron cannot. -3. **Fast response** — Slack requires a 3-second response. Hub responds immediately, broadcasts to Electron for enrichment. -4. **Single webhook endpoint** — No need for each client to register its own webhook. - -### Data flow for external triggers - -``` -Slack/GitHub → Hub webhook endpoint → Hub validates signature - → Hub creates item in Hub SQLite (task/note/capture) - → Hub responds to Slack/GitHub in-thread with confirmation - → Hub broadcasts WebSocket message to all connected Electron clients - → Electron receives broadcast, creates item locally, updates UI -``` - ---- - -## 3. Command Bar — Top Nav - -### Location - -Replace the current `ProjectTabBar` header with a unified top bar that includes both project tabs AND the command bar. - -**Current layout:** -``` -┌──────────┬─────────────────────────────────────────────┐ -│ Sidebar │ ProjectTabBar │ -│ ├─────────────────────────────────────────────┤ -│ │ (page content) │ -└──────────┴─────────────────────────────────────────────┘ -``` - -**New layout:** -``` -┌──────────┬─────────────────────────────────────────────┐ -│ Sidebar │ TopBar │ -│ │ [ProjectTabs...] [CommandBar___________] [⏎] │ -│ ├─────────────────────────────────────────────┤ -│ │ (page content) │ -└──────────┴─────────────────────────────────────────────┘ -``` - -### Component: `TopBar.tsx` - -Replaces `ProjectTabBar`. Contains: -- **Left**: Project tabs (same as current ProjectTabBar, slightly compressed) -- **Right**: Command bar input + submit button - -### Component: `CommandBar.tsx` - -``` -┌──────────────────────────────────────────┐ -│ ⌘ Ask Claude... [⏎] │ -└──────────────────────────────────────────┘ -``` - -**Behavior:** -- Single-line text input, always visible -- Placeholder: "Ask Claude... (notes, tasks, reminders)" -- Submit on Enter -- Keyboard shortcut: `Ctrl+K` / `Cmd+K` to focus -- Shows inline loading spinner while processing -- Shows toast notification with result (success/error) -- Up/Down arrows cycle through command history -- Escape clears input and blurs - -**States:** -1. **Idle** — Shows placeholder -2. **Focused** — Cursor in input, placeholder fades -3. **Processing** — Input disabled, spinner shows -4. **Result** — Toast appears below with response, input clears - -### Response Toast - -Shown below the command bar as a small floating element, auto-dismisses after 4 seconds: - -``` -┌─────────────────────────────────────────┐ -│ ✓ Task created: "Fix type errors in PR" │ -│ Added to today's plan │ -└─────────────────────────────────────────┘ -``` - -Uses existing theme colors: `bg-card`, `border-border`, `text-foreground`. - ---- - -## 4. Enhanced Assistant Service - -### 4a. Intent Classification — Two-Tier System - -**Tier 1: Fast Path (regex, sync, <1ms)** - -Keep the existing regex rules for deterministic commands where regex is reliable: - -| Prefix | Intent | Action | -|--------|--------|--------| -| `note:` or `remember` | quick_command / notes | Create note | -| `#standup` | quick_command / standup | Create standup note | -| `remind` or `alert` | quick_command / reminder | Create alert | -| `play`, `pause`, `skip`, `next`, `previous`, `volume` | quick_command / spotify | Control Spotify | -| `open` or `launch` | quick_command / launcher | Open URL/app | - -**Tier 2: Smart Path (Claude API, async, ~500ms)** - -For anything that doesn't match a regex rule, use Claude API for structured classification: - -```typescript -// System prompt for intent classification -const CLASSIFIER_SYSTEM_PROMPT = `You are an intent classifier for a developer productivity app. -Classify the user's input into exactly one action. Respond with JSON only. - -Available actions: -- create_task: Create a task for a project (extract: title, description, projectName?) -- create_time_block: Add to today's schedule (extract: label, startTime, endTime, type) -- create_note: Save a note (extract: title, content, tags?) -- create_reminder: Set a reminder (extract: message, triggerAt) -- search: Search across tasks/notes/projects (extract: query, scope?) -- conversation: General question that needs a conversational answer - -Respond with: -{"action": "...", "entities": {...}, "confidence": 0.0-1.0}`; -``` - -**API call:** -- Model: `claude-haiku-4-5-20251001` (fast, cheap, sufficient for classification) -- Max tokens: 200 -- Temperature: 0 -- Input: user's command text -- Output: structured JSON with action + entities - -**Fallback chain:** -1. Try regex fast path -2. If no match → call Claude API -3. If API fails (no key, network error) → fall back to `conversation` intent with Claude CLI - -### 4b. Expanded Command Executor - -New capabilities beyond current: - -| Action | Service | Method | -|--------|---------|--------| -| `create_task` | TaskService | `createTask(draft)` | -| `create_time_block` | PlannerService | `addTimeBlock(todayDate, block)` | -| `create_note` | NotesService | `createNote(data)` | -| `create_reminder` | AlertService | `createAlert(data)` | -| `search` | NotesService + TaskService | `searchNotes(q)` + task search | -| `conversation` | Claude CLI | `claude --print -p "..."` | - -**Task creation flow:** -``` -Input: "fix the login redirect bug" -→ Claude classifies: {action: "create_task", entities: {title: "Fix login redirect bug"}} -→ Executor: calls taskService.createTask({title, description, projectId: activeProjectId}) -→ Also: calls plannerService.addTimeBlock(today, {label: title, type: 'focus'}) -→ Response: "Task created: 'Fix login redirect bug' — added to today's plan" -``` - -**Time block creation flow:** -``` -Input: "block 2-3pm for code review" -→ Claude classifies: {action: "create_time_block", entities: {label: "Code review", startTime: "14:00", endTime: "15:00", type: "focus"}} -→ Executor: calls plannerService.addTimeBlock(today, block) -→ Response: "Time block added: Code review 2:00 PM – 3:00 PM" -``` - -### 4c. Context Awareness - -The assistant receives context about the current state: - -```typescript -interface AssistantContext { - activeProjectId: string | null; - activeProjectName: string | null; - currentPage: string; // e.g. '/projects/abc/tasks' - todayDate: string; // '2026-02-13' -} -``` - -This context is passed with every `assistant.sendCommand` call so the assistant can: -- Create tasks in the active project (not requiring the user to specify which project) -- Add time blocks to today's plan -- Know what page the user is on for contextual actions - -### 4d. AssistantService Interface Changes - -```typescript -export interface AssistantService { - /** Process a command from any source (UI, Slack, GitHub). */ - sendCommand: (input: string, context?: AssistantContext) => Promise; - /** Process a webhook-triggered command. */ - processWebhookCommand: (command: WebhookCommand) => Promise; - /** Get command history entries, newest first. */ - getHistory: (limit?: number) => CommandHistoryEntry[]; - /** Clear all command history. */ - clearHistory: () => void; -} -``` - ---- - -## 5. Hub Webhook System - -### 5a. Slack Webhook Route - -**File:** `hub/src/routes/webhooks/slack.ts` - -**Endpoints:** - -``` -POST /api/webhooks/slack/commands — Slash command handler (/claude) -POST /api/webhooks/slack/events — Event subscription (app_mention) -POST /api/webhooks/slack/interactions — Interactive component callbacks -``` - -**Slash command flow (`/claude fix the login bug`):** - -``` -1. Slack sends POST to /api/webhooks/slack/commands -2. Hub validates request signature (HMAC-SHA256 with signing secret) -3. Hub extracts: - - command text: "fix the login bug" - - user_id, user_name - - channel_id, channel_name - - response_url (for deferred responses) -4. Hub creates capture in SQLite: - INSERT INTO captures (text, source, source_id, source_channel, created_at) - VALUES ('fix the login bug', 'slack', 'U123', '#qa', now()) -5. Hub broadcasts WebSocket message: - {type: 'webhook', source: 'slack', action: 'command', data: {...}} -6. Hub responds to Slack immediately (within 3s): - {"response_type": "ephemeral", "text": "✓ Got it — creating task: 'Fix the login bug'"} -7. Electron receives WS message, processes through assistant service -8. Electron creates task locally -9. (Optional) Electron calls Hub API to update Slack thread via response_url -``` - -**App mention flow (`@Claude Assistant add this to my tasks`):** - -``` -1. Slack sends event to /api/webhooks/slack/events -2. Hub validates, extracts mention text (strips bot mention prefix) -3. Hub captures the Slack message context: - - thread_ts (for thread context) - - channel - - user - - permalink (constructed from channel + ts) -4. Hub creates capture with full context -5. Hub broadcasts to Electron -6. Hub posts ephemeral response in channel -``` - -**Slack App Configuration Required:** - -| Setting | Value | -|---------|-------| -| Slash Command | `/claude` with request URL `https:///api/webhooks/slack/commands` | -| Event Subscription | `app_mention` with request URL `https:///api/webhooks/slack/events` | -| Bot Token Scopes | `chat:write`, `channels:history`, `groups:history`, `users:read` | -| Signing Secret | Stored in Hub settings (via Settings page) | -| Bot OAuth Token | Stored in Hub settings (via Settings page) | - -### 5b. GitHub Webhook Route - -**File:** `hub/src/routes/webhooks/github.ts` - -**Endpoint:** - -``` -POST /api/webhooks/github -``` - -**PR comment flow (`@claudeassistant create a task to fix the type errors`):** - -``` -1. GitHub sends issue_comment or pull_request_review_comment event -2. Hub validates webhook signature (HMAC-SHA256 with webhook secret) -3. Hub checks if comment body contains @claudeassistant (case-insensitive) -4. Hub extracts: - - Command text (everything after @claudeassistant) - - Repository: owner/name - - PR number - - Comment author - - PR title, branch, URL -5. Hub creates capture in SQLite: - INSERT INTO captures (text, source, source_id, source_url, project_id, created_at) - VALUES ('fix type errors', 'github', 'owner/repo#42', 'https://...', project_id, now()) -6. Hub broadcasts to Electron: - {type: 'webhook', source: 'github', action: 'command', data: { - command: 'create a task to fix the type errors', - repo: 'owner/repo', - prNumber: 42, - prTitle: 'Add user auth', - prUrl: 'https://github.com/...', - author: 'parke' - }} -7. Hub responds to GitHub with a PR comment: - POST /repos/owner/repo/issues/42/comments - Body: "✓ Task created: 'Fix the type errors'\n\n— Claude Assistant" -8. Electron receives WS message, creates task in matching project -``` - -**GitHub Webhook Configuration Required:** - -| Setting | Value | -|---------|-------| -| Payload URL | `https:///api/webhooks/github` | -| Content type | `application/json` | -| Secret | Stored in Hub settings | -| Events | `Issue comments`, `Pull request review comments` | - -**Project matching logic:** -When a GitHub webhook arrives, the Hub broadcasts the repo name. Electron matches it against projects that have `githubRepo` set in their project settings. If no match, the task is created as a standalone capture. - -### 5c. Hub Settings for Webhooks - -New settings stored in Hub SQLite `settings` table: - -| Key | Description | -|-----|-------------| -| `slack.botToken` | Slack Bot OAuth Token (xoxb-...) | -| `slack.signingSecret` | Slack App Signing Secret | -| `github.webhookSecret` | GitHub Webhook Secret | - -These are configured from the Electron Settings page and synced to the Hub. - -### 5d. Hub Database Changes - -New columns on `captures` table (or create if not exists): - -```sql -CREATE TABLE IF NOT EXISTS webhook_commands ( - id TEXT PRIMARY KEY, - source TEXT NOT NULL, -- 'slack' | 'github' | 'manual' - source_id TEXT, -- user/repo identifier - source_channel TEXT, -- Slack channel or GitHub repo - source_url TEXT, -- permalink to original message - command_text TEXT NOT NULL, -- extracted command - project_id TEXT, -- matched project (nullable) - status TEXT DEFAULT 'pending', -- 'pending' | 'processed' | 'failed' - result_text TEXT, -- response sent back - created_at TEXT NOT NULL, - processed_at TEXT -); -``` - ---- - -## 6. Remove Assistant Page - -### What to remove - -- Remove `Assistant` from sidebar nav in `Sidebar.tsx` -- Remove `assistantRoute` from `router.tsx` -- Remove `ROUTES.ASSISTANT` usage from sidebar navigation -- Keep the `@features/assistant` module — its hooks and API layer are reused by the command bar -- Remove `AssistantPage.tsx`, `QuickActions.tsx`, `ResponseStream.tsx`, `CommandInput.tsx` components - -### What to keep - -- `src/main/services/assistant/` — the entire service layer stays -- `src/renderer/features/assistant/api/useAssistant.ts` — React Query hooks stay -- `src/renderer/features/assistant/hooks/useAssistantEvents.ts` — event hooks stay -- `src/shared/types/assistant.ts` — types stay and expand - ---- - -## 7. IPC Contract Changes - -### New channels - -```typescript -// ── Assistant (expanded) ──────────────────────────────────── - -'assistant.sendCommand': { - input: z.object({ - input: z.string(), - context: z.object({ - activeProjectId: z.string().nullable(), - activeProjectName: z.string().nullable(), - currentPage: z.string(), - todayDate: z.string(), - }).optional(), - }), - output: AssistantResponseSchema, -}, - -'assistant.getHistory': { - input: z.object({ limit: z.number().optional() }), - output: z.array(CommandHistoryEntrySchema), -}, - -'assistant.clearHistory': { - input: z.object({}), - output: z.object({ success: z.boolean() }), -}, - -// ── Webhook settings ──────────────────────────────────────── - -'settings.getWebhookConfig': { - input: z.object({}), - output: z.object({ - slack: z.object({ - botToken: z.string(), - signingSecret: z.string(), - configured: z.boolean(), - }), - github: z.object({ - webhookSecret: z.string(), - configured: z.boolean(), - }), - }), -}, - -'settings.updateWebhookConfig': { - input: z.object({ - slack: z.object({ - botToken: z.string().optional(), - signingSecret: z.string().optional(), - }).optional(), - github: z.object({ - webhookSecret: z.string().optional(), - }).optional(), - }), - output: z.object({ success: z.boolean() }), -}, -``` - -### New events - -```typescript -'event:assistant.commandCompleted': { - payload: { - id: string; - source: 'commandbar' | 'slack' | 'github'; - action: string; - summary: string; - timestamp: string; - }, -}, - -'event:webhook.received': { - payload: { - source: 'slack' | 'github'; - commandText: string; - sourceContext: Record; - timestamp: string; - }, -}, -``` - ---- - -## 8. Type Definitions - -### Updated `src/shared/types/assistant.ts` - -```typescript -/** - * Assistant-related types - */ - -export type IntentType = 'quick_command' | 'task_creation' | 'conversation'; - -/** Expanded action types for Claude API classification */ -export type AssistantAction = - | 'create_task' - | 'create_time_block' - | 'create_note' - | 'create_reminder' - | 'search' - | 'spotify_control' - | 'open_url' - | 'conversation'; - -export interface AssistantContext { - activeProjectId: string | null; - activeProjectName: string | null; - currentPage: string; - todayDate: string; -} - -export interface AssistantCommand { - input: string; - context?: AssistantContext; -} - -export interface AssistantResponse { - type: 'text' | 'action' | 'error'; - content: string; - intent?: IntentType; - action?: AssistantAction; - metadata?: Record; -} - -export interface CommandHistoryEntry { - id: string; - input: string; - source: 'commandbar' | 'slack' | 'github'; - intent: IntentType; - action?: AssistantAction; - responseSummary: string; - timestamp: string; -} - -export interface WebhookCommand { - source: 'slack' | 'github'; - commandText: string; - sourceContext: { - userId?: string; - userName?: string; - channelId?: string; - channelName?: string; - threadTs?: string; - permalink?: string; - repo?: string; - prNumber?: number; - prTitle?: string; - prUrl?: string; - commentAuthor?: string; - }; -} - -export interface WebhookConfig { - slack: { - botToken: string; - signingSecret: string; - configured: boolean; - }; - github: { - webhookSecret: string; - configured: boolean; - }; -} -``` - ---- - -## 9. Settings Page — Webhook Configuration - -### New section in SettingsPage: "Assistant & Webhooks" - -Add a new section to the existing Settings page (NOT a new page): - -``` -┌─ Assistant & Webhooks ───────────────────────────────────┐ -│ │ -│ Anthropic API Key │ -│ [••••••••••••••••••••] [Show] [Test] │ -│ Required for smart command classification │ -│ │ -│ ── Slack Integration ────────────────────────────── │ -│ Bot Token (xoxb-...) │ -│ [________________________________] [Save] │ -│ Signing Secret │ -│ [________________________________] [Save] │ -│ Webhook URL (copy this to Slack App settings): │ -│ https:///api/webhooks/slack/commands │ -│ [Copy] │ -│ │ -│ ── GitHub Integration ───────────────────────────── │ -│ Webhook Secret │ -│ [________________________________] [Save] │ -│ Webhook URL (copy this to GitHub repo settings): │ -│ https:///api/webhooks/github │ -│ [Copy] │ -│ │ -└──────────────────────────────────────────────────────────┘ -``` - -The webhook URLs are computed from the Hub URL already configured in Settings. - ---- - -## 10. Implementation Plan - -### Phase 1: Command Bar UI (renderer only) - -**Goal:** Replace ProjectTabBar with TopBar that includes CommandBar. - -1. Create `src/renderer/app/layouts/TopBar.tsx` — contains ProjectTabs + CommandBar -2. Create `src/renderer/app/layouts/CommandBar.tsx` — input + submit + toast -3. Create `src/renderer/shared/stores/command-bar-store.ts` — Zustand store for: - - `isProcessing: boolean` - - `lastResponse: AssistantResponse | null` - - `history: string[]` (recent inputs for up/down cycling) -4. Update `RootLayout.tsx` — replace `` with `` -5. Remove `Assistant` from sidebar nav items in `Sidebar.tsx` -6. Wire CommandBar to existing `assistant.sendCommand` IPC (works with current regex classifier immediately) - -**Files created:** -- `src/renderer/app/layouts/TopBar.tsx` -- `src/renderer/app/layouts/CommandBar.tsx` -- `src/renderer/shared/stores/command-bar-store.ts` - -**Files modified:** -- `src/renderer/app/layouts/RootLayout.tsx` (swap ProjectTabBar → TopBar) -- `src/renderer/app/layouts/Sidebar.tsx` (remove Assistant nav item) - -### Phase 2: Enhanced Intent Classifier - -**Goal:** Replace regex-only classifier with two-tier system. - -1. Create `src/main/services/assistant/claude-classifier.ts`: - - Uses Anthropic SDK (already in dependencies) or `claude` CLI with `--print` - - Takes user input + system prompt - - Returns structured JSON: `{action, entities, confidence}` - - Falls back gracefully on API failure -2. Update `src/main/services/assistant/intent-classifier.ts`: - - Keep regex fast path - - Add `classifyWithClaude()` async fallback - - Export new `classifyIntentAsync()` that tries regex first, then Claude -3. Update `src/main/services/assistant/assistant-service.ts`: - - Use `classifyIntentAsync()` instead of `classifyIntent()` -4. Add `anthropicApiKey` to settings schema + settings service - -**Files created:** -- `src/main/services/assistant/claude-classifier.ts` - -**Files modified:** -- `src/main/services/assistant/intent-classifier.ts` -- `src/main/services/assistant/assistant-service.ts` -- `src/main/services/settings/settings-service.ts` (add API key to settings) -- `src/shared/ipc-contract.ts` (update assistant channels) -- `src/shared/types/assistant.ts` (expanded types) -- `src/shared/types/settings.ts` (add anthropicApiKey) - -### Phase 3: Expanded Command Executor - -**Goal:** Wire all action types to real services. - -1. Update `src/main/services/assistant/command-executor.ts`: - - Add `handleCreateTask()` — calls TaskService, optionally adds time block to today - - Add `handleCreateTimeBlock()` — calls PlannerService - - Add `handleSearch()` — calls NotesService.searchNotes + project task search - - Update `handleNotes()` — enrich with auto-tagging - - Accept `AssistantContext` so actions know the active project/date -2. Update `CommandExecutorDeps` to include TaskService, PlannerService, ProjectService -3. Wire new deps in `src/main/index.ts` where assistant service is created - -**Files modified:** -- `src/main/services/assistant/command-executor.ts` -- `src/main/services/assistant/assistant-service.ts` (pass context) -- `src/main/index.ts` (inject new service deps) -- `src/main/ipc/handlers/assistant-handlers.ts` (pass context through) - -### Phase 4: Assistant Context from Renderer - -**Goal:** Send current app state with every command. - -1. Update `useSendCommand` hook to include context: - ```typescript - function useSendCommand() { - const activeProjectId = useLayoutStore(s => s.activeProjectId); - const projects = useProjects(); - const routerState = useRouterState(); - - return useMutation({ - mutationFn: (input: string) => ipc('assistant.sendCommand', { - input, - context: { - activeProjectId, - activeProjectName: projects.data?.find(p => p.id === activeProjectId)?.name ?? null, - currentPage: routerState.location.pathname, - todayDate: new Date().toISOString().slice(0, 10), - }, - }), - }); - } - ``` - -**Files modified:** -- `src/renderer/features/assistant/api/useAssistant.ts` - -### Phase 5: Hub Webhook Routes - -**Goal:** Hub receives and processes Slack/GitHub webhooks. - -1. Create `hub/src/routes/webhooks/slack.ts`: - - Slack signature validation (timecode + HMAC-SHA256) - - Slash command handler - - Event subscription handler (app_mention + URL verification challenge) - - Broadcast to connected clients - - Respond to Slack with confirmation -2. Create `hub/src/routes/webhooks/github.ts`: - - GitHub HMAC-SHA256 signature validation - - `issue_comment` + `pull_request_review_comment` event handling - - `@claudeassistant` mention detection - - Broadcast to connected clients - - Reply on PR via GitHub API -3. Create `hub/src/routes/webhooks/index.ts` — registers both routes -4. Create `hub/src/lib/webhook-validator.ts` — shared HMAC validation -5. Update `hub/src/app.ts` — register webhook routes -6. Add webhook_commands table migration in `hub/src/db/database.ts` - -**Files created:** -- `hub/src/routes/webhooks/slack.ts` -- `hub/src/routes/webhooks/github.ts` -- `hub/src/routes/webhooks/index.ts` -- `hub/src/lib/webhook-validator.ts` - -**Files modified:** -- `hub/src/app.ts` (register webhook routes) -- `hub/src/db/database.ts` (add webhook_commands table) -- `hub/src/lib/types.ts` (add webhook types) - -### Phase 6: Electron Webhook Relay - -**Goal:** Electron receives Hub WebSocket broadcasts and processes webhook commands. - -1. Create `src/main/services/hub/webhook-relay.ts`: - - Listens for `webhook` type messages from Hub WebSocket - - Parses into `WebhookCommand` type - - Passes to `assistantService.processWebhookCommand()` - - Emits `event:webhook.received` for UI notification -2. Update `src/main/services/assistant/assistant-service.ts`: - - Add `processWebhookCommand()` method - - Maps webhook source context to assistant context - - Matches GitHub repos to projects -3. Create `src/renderer/shared/components/WebhookNotification.tsx`: - - Toast notification when a webhook command is processed - - "Slack: Task created from #qa" or "GitHub: Task created from PR #42" - -**Files created:** -- `src/main/services/hub/webhook-relay.ts` -- `src/renderer/shared/components/WebhookNotification.tsx` - -**Files modified:** -- `src/main/services/assistant/assistant-service.ts` -- `src/main/index.ts` (wire webhook relay) -- `src/renderer/app/layouts/RootLayout.tsx` (add WebhookNotification) - -### Phase 7: Webhook Settings UI - -**Goal:** Settings page for configuring Slack/GitHub webhook credentials. - -1. Create `src/renderer/features/settings/components/WebhookSettings.tsx`: - - Slack bot token + signing secret inputs - - GitHub webhook secret input - - Webhook URL display (computed from Hub URL) with copy button - - Test connection button for each -2. Add to existing `SettingsPage.tsx` as a new section -3. Add IPC channels for webhook config CRUD -4. Add `webhook-settings-handlers.ts` in Hub + Electron - -**Files created:** -- `src/renderer/features/settings/components/WebhookSettings.tsx` -- `src/main/ipc/handlers/webhook-settings-handlers.ts` - -**Files modified:** -- `src/renderer/features/settings/components/SettingsPage.tsx` -- `src/shared/ipc-contract.ts` -- `src/main/ipc/index.ts` -- `src/main/services/settings/settings-service.ts` - ---- - -## 11. Full File Manifest - -### New Files (15) - -| File | Purpose | -|------|---------| -| `src/renderer/app/layouts/TopBar.tsx` | Top bar with project tabs + command bar | -| `src/renderer/app/layouts/CommandBar.tsx` | Global assistant input | -| `src/renderer/shared/stores/command-bar-store.ts` | Command bar UI state | -| `src/main/services/assistant/claude-classifier.ts` | Claude API intent classification | -| `src/main/services/hub/webhook-relay.ts` | Hub WS → assistant service bridge | -| `src/renderer/shared/components/WebhookNotification.tsx` | Webhook action toast | -| `src/renderer/features/settings/components/WebhookSettings.tsx` | Webhook config UI | -| `src/main/ipc/handlers/webhook-settings-handlers.ts` | Webhook settings IPC | -| `hub/src/routes/webhooks/slack.ts` | Slack webhook handler | -| `hub/src/routes/webhooks/github.ts` | GitHub webhook handler | -| `hub/src/routes/webhooks/index.ts` | Webhook route registration | -| `hub/src/lib/webhook-validator.ts` | HMAC signature validation | - -### Modified Files (18) - -| File | Change | -|------|--------| -| `src/renderer/app/layouts/RootLayout.tsx` | Swap ProjectTabBar → TopBar, add WebhookNotification | -| `src/renderer/app/layouts/Sidebar.tsx` | Remove Assistant nav item | -| `src/renderer/app/router.tsx` | Remove assistantRoute (keep feature module for hooks) | -| `src/main/services/assistant/intent-classifier.ts` | Add async Claude API fallback | -| `src/main/services/assistant/assistant-service.ts` | Add processWebhookCommand, accept context | -| `src/main/services/assistant/command-executor.ts` | Add task/timeblock/search handlers, accept context | -| `src/main/services/settings/settings-service.ts` | Add anthropicApiKey, webhook config | -| `src/main/index.ts` | Wire new deps, webhook relay | -| `src/main/ipc/index.ts` | Register webhook settings handlers | -| `src/main/ipc/handlers/assistant-handlers.ts` | Pass context through | -| `src/shared/ipc-contract.ts` | New channels + updated schemas | -| `src/shared/types/assistant.ts` | Expanded types | -| `src/shared/types/settings.ts` | Add anthropicApiKey | -| `src/renderer/features/assistant/api/useAssistant.ts` | Include context in mutation | -| `src/renderer/features/settings/components/SettingsPage.tsx` | Add webhook section | -| `hub/src/app.ts` | Register webhook routes | -| `hub/src/db/database.ts` | Add webhook_commands table | -| `hub/src/lib/types.ts` | Add webhook message types | - ---- - -## 12. What the User Needs to Configure - -After implementation, the user needs to provide: - -| Item | Where | Required For | -|------|-------|-------------| -| Anthropic API Key | Settings > Assistant | Smart intent classification | -| Slack Bot Token | Settings > Webhooks > Slack | Slack integration | -| Slack Signing Secret | Settings > Webhooks > Slack | Slack webhook validation | -| Slack App creation | api.slack.com | Slash command + event subscriptions | -| GitHub Webhook Secret | Settings > Webhooks > GitHub | GitHub webhook validation | -| GitHub Webhook setup | Repo Settings > Webhooks | PR comment events | -| Hub URL (already configured) | Settings > Hub | Webhook endpoint base URL | - -Everything else is handled by the app. No API keys = no smart classification (falls back to regex + CLI). No Slack config = no Slack integration (command bar still works). No GitHub config = no GitHub integration (command bar still works). Each integration degrades gracefully. - ---- - -## 13. Guard Rails & Anti-Pattern Checks - -### Follows existing patterns: -- Services return sync values, handlers wrap with `Promise.resolve()` ✓ -- IPC contract is the source of truth ✓ -- Feature modules use api/, components/, hooks/, store.ts structure ✓ -- React Query for server state, Zustand for UI state ✓ -- Named function declarations for components ✓ -- `import type` for type-only imports ✓ -- `color-mix()` for theme-aware colors (no hardcoded RGBA) ✓ - -### Does NOT introduce: -- No new Context providers ✓ -- No Redux ✓ -- No floating promises (all async paths use void or await) ✓ -- No `any` types ✓ -- No array index as key ✓ -- No hardcoded colors outside theme variables ✓ -- No mock data anywhere ✓ - -### Exception: Claude classifier is async -The `claude-classifier.ts` makes an async API call. This is acceptable because: -- It's an external API call (same category as `selectDirectory()`) -- The handler wraps it properly -- The fast path (regex) remains sync for <1ms response on simple commands - ---- - -## 14. End State - -After all phases: - -1. **Command bar** in top nav — type anything, get real results -2. **Slack** — `/claude fix the login bug` in any channel → task appears in app -3. **GitHub** — `@claudeassistant add task for this` on a PR → task created in project -4. **No Assistant page** — it's built into the shell, not a destination -5. **Smart classification** — Claude API understands natural language, regex handles simple commands -6. **Full context** — knows active project, today's date, current page -7. **Graceful degradation** — works without API key (regex + CLI fallback), works without Slack/GitHub config (command bar only) diff --git a/doc-history/2026-02-13-remove-mock-data-real-integrations-design.md b/doc-history/2026-02-13-remove-mock-data-real-integrations-design.md deleted file mode 100644 index 46ff9c9..0000000 --- a/doc-history/2026-02-13-remove-mock-data-real-integrations-design.md +++ /dev/null @@ -1,298 +0,0 @@ -# Remove Mock Data & Wire Real Integrations - -**Date**: 2026-02-13 -**Status**: IMPLEMENTED — all tasks complete, typecheck + lint clean - ---- - -## 1. Audit Summary - -### Pages Explored (UI Walkthrough) - -| Page | Status | Mock Data? | Notes | -|------|--------|-----------|-------| -| Dashboard | Visited | **YES** | 3 components with hardcoded mock data | -| Assistant | Visited | No | Empty state, rule-based classifier works | -| Notes | Visited | No | Real file-backed CRUD | -| Fitness (4 tabs) | Visited | No | Real file-backed CRUD, Withings is stub | -| Planner | Visited | No | Real file-backed, time blocks persist | -| Productivity (3 tabs) | Visited | No | Calendar/Spotify need OAuth | -| Alerts (3 tabs) | Visited | No | Real file-backed CRUD | -| Comms (4 tabs) | Visited | No | Buttons disabled when disconnected, but **no onClick handlers** | -| Projects | Visited | No | Real file-backed | -| Settings | Visited | No | All sections functional, **UI Scale bug** | -| Tasks (Table Dashboard) | Blocked | N/A | Requires project — disabled in sidebar | -| Terminals | Blocked | N/A | Requires project — disabled in sidebar | -| Agents | Blocked | N/A | Requires project — disabled in sidebar | -| Roadmap | Blocked | N/A | Requires project — API-driven | -| Ideation | Blocked | N/A | Requires project — API-driven | -| GitHub | Blocked | N/A | Requires project + OAuth | -| Changelog | Blocked | N/A | Requires project — API-driven | -| Insights | Blocked | N/A | Requires project — computed from real data | - ---- - -## 2. Mock Data To Remove (3 Components) - -### 2a. `TodayView.tsx` — Fake Schedule - -**File**: `src/renderer/features/dashboard/components/TodayView.tsx:28-35` - -```typescript -const MOCK_TIME_BLOCKS: TimeBlock[] = [ - { id: 'tb-1', time: '9:00 AM', label: 'Daily standup', category: 'work' }, - { id: 'tb-2', time: '10:00 AM', label: 'Feature development', category: 'work' }, - { id: 'tb-3', time: '1:00 PM', label: 'Claude-UI dashboard', category: 'side-project' }, - { id: 'tb-4', time: '3:00 PM', label: 'Code review', category: 'work' }, - { id: 'tb-5', time: '5:30 PM', label: 'Gym', category: 'personal' }, -]; -``` - -**Fix**: Replace with React Query hook that calls `planner.getDay` IPC channel for today's date. The Planner service already stores time blocks on disk — this component just doesn't read them. - -**Changes**: -- Import `usePlannerDay` hook from `@features/planner` -- Fetch today's plan: `usePlannerDay(todayDateString)` -- Map `plan.timeBlocks` to the existing UI -- Show "Nothing scheduled today" when empty (already handled) -- Remove `MOCK_TIME_BLOCKS` constant entirely - -### 2b. `ActiveAgents.tsx` — Fake Agents - -**File**: `src/renderer/features/dashboard/components/ActiveAgents.tsx:27-43` - -```typescript -const MOCK_AGENTS: MockAgent[] = [ - { id: 'ma-1', projectName: 'Claude-UI', taskName: 'Build dashboard feature', status: 'running', progress: 65 }, - { id: 'ma-2', projectName: 'API Server', taskName: 'Fix auth middleware', status: 'running', progress: 30 }, -]; -``` - -**Fix**: Replace with React Query hook that calls `agents.list` IPC channel. The Agent service tracks real agent sessions in memory. - -**Changes**: -- Import `useAgents` hook from `@features/agents` -- Fetch running agents: `useAgents()` filtered to `status === 'running'` -- Map real `AgentSession` data to the existing card UI -- Show "No agents running" when empty (already handled) -- Remove `MOCK_AGENTS`, `MockAgent`, `MockAgentStatus` types entirely - -### 2c. `DailyStats.tsx` — Hardcoded Counts - -**File**: `src/renderer/features/dashboard/components/DailyStats.tsx:10-12` - -```typescript -const tasksCompleted = 0; -const agentsRan = 2; -``` - -**Fix**: Compute from real services. - -**Changes**: -- `tasksCompleted`: Query `insights.getMetrics` or compute from today's completed tasks -- `agentsRan`: Query `agents.list` and count sessions started today -- `captureCount`: Already uses real store data (no change needed) -- Remove hardcoded constants - ---- - -## 3. Non-Functional Features - -### 3a. Communications — Buttons Have No onClick Handlers - -**Files**: -- `src/renderer/features/communications/components/SlackPanel.tsx:44-59` -- `src/renderer/features/communications/components/DiscordPanel.tsx:44-59` - -**Problem**: The action buttons (Send Message, Read Channel, Search, Set Status) have `disabled={status !== 'connected'}` but **zero onClick handlers**. Even if connected, clicking does nothing. - -**Fix**: Wire buttons to MCP server tool calls or open modals: -- "Send Message" → Open modal with channel/message inputs → call `slack.sendMessage` MCP tool -- "Read Channel" → Open modal with channel selector → call `slack.readChannel` MCP tool -- "Search" → Open modal with search input → call `slack.search` MCP tool -- "Set Status" → Open modal with status/emoji inputs → call `slack.setStatus` MCP tool -- Same pattern for Discord actions - -### 3b. Spotify — Requires OAuth, No Setup Prompt - -**File**: `src/renderer/features/productivity/components/SpotifyPanel.tsx` - -**Problem**: Shows "No active playback" with a search bar, but no indication that Spotify OAuth is required. If user searches or interacts, it silently fails. - -**Fix**: Check OAuth token status. If no Spotify token exists, show a setup card: -> "Connect Spotify to control playback and search tracks." -> [Configure in Settings] button → navigates to Settings > OAuth Providers - -### 3c. Calendar — Requires OAuth, No Setup Prompt - -**File**: `src/renderer/features/productivity/components/CalendarWidget.tsx` - -**Problem**: Shows "No events scheduled for today" but doesn't tell user they need Google Calendar OAuth. - -**Fix**: Same pattern as Spotify — check token, show setup card if missing. - -### 3d. GitHub — Requires OAuth, No Setup Prompt - -**File**: `src/renderer/features/github/components/GitHubPage.tsx` - -**Problem**: Requires GitHub OAuth token. No indication to user. - -**Fix**: Check token, show setup card with link to Settings > OAuth Providers. - -### 3e. Fitness > Withings — Service is a Stub - -**File**: `src/main/services/fitness/fitness-service.ts` - -**Problem**: The service references "withings" as a data source but has NO actual Withings API integration. It only deduplicates data by source tag. The Withings OAuth provider is configured in settings but connecting does nothing for fitness. - -**Fix (two options)**: -1. **Wire it**: Add actual Withings API calls to sync body measurements → `fitness-service.ts` -2. **Remove it**: Remove Withings from OAuth providers if not implementing the integration. Hide the "Withings" option in Settings. - -**Recommendation**: Option 2 for now — remove the dead Withings provider until real integration is built. - -### 3f. Assistant — No Claude API, Rule-Based Only - -**Files**: -- `src/main/services/assistant/intent-classifier.ts` — Regex-based classification -- `src/main/services/assistant/command-executor.ts` — Routes to local services or Claude CLI - -**Problem**: The Assistant page looks like a chat interface but uses hardcoded regex patterns for intent classification. It can: -- Create notes, reminders, alerts (works locally) -- Control Spotify (works if OAuth configured) -- Fall back to Claude CLI for conversations (requires `claude` in PATH) - -But there's no indication to the user about what it can/can't do, and no error handling when Claude CLI is missing. - -**Fix**: -- Add placeholder suggestions showing supported commands -- When Claude CLI fallback fails, show actionable error: "Claude CLI not found. Install it to enable AI conversations." -- Consider adding a "capabilities" tooltip or help card - -### 3g. Hub Connection — No Connection Status Indicator - -**File**: `src/renderer/features/settings/components/HubSettings.tsx` - -**Problem**: Hub connection shows "Disconnected" only on the Settings page. No global indicator. - -**Fix**: This is lower priority — hub is optional infrastructure. - ---- - -## 4. Missing Auth/Setup Notifications - -### 4a. Claude CLI Authentication — Bottom-Left Notification - -**Problem**: The core app functionality (running agents, AI assistant conversations) depends on Claude CLI being installed and authenticated. There is NO check for this anywhere in the UI. - -**Implementation**: -1. Add IPC channel `app.checkClaudeAuth` that runs `claude --version` and checks for valid auth -2. On app startup, check Claude CLI status -3. If not found or not authenticated, show a persistent notification in the **bottom-left corner** of the app: - ``` - ⚠ Claude CLI not configured - [Set Up] [Re-authenticate] - ``` -4. "Set Up" → opens a guided setup flow or links to install docs -5. "Re-authenticate" → runs `claude login` in a terminal -6. Notification component: `src/renderer/shared/components/AuthNotification.tsx` -7. Position: fixed bottom-left, above sidebar, non-blocking - -### 4b. OAuth Provider Status — Contextual Prompts - -**Problem**: When a user navigates to a feature requiring OAuth (Spotify, Calendar, GitHub, Slack), there's no indication that setup is needed. - -**Implementation**: -1. Create a reusable `` component: - ```tsx - - ``` -2. Each feature page checks its provider's token status via an `useOAuthStatus(provider)` hook -3. If no token: show the setup card instead of (or above) the feature content -4. "Configure in Settings" button navigates to Settings > OAuth Providers section - -### 4c. MCP Server Status — Connection Indicators - -**Problem**: Slack and Discord show "Disconnected" but no way to connect from the Comms page. - -**Implementation**: -1. Add "Connect" button next to "Disconnected" status on Comms page -2. "Connect" → opens Settings > OAuth Providers (for Slack) or shows MCP server config -3. Optionally: add MCP server health status to a global status bar - ---- - -## 5. Bugs Found During Audit - -### 5a. UI Scale Shows "Current: 1%" - -**File**: `src/renderer/features/settings/components/SettingsPage.tsx:208` -**Store**: `src/renderer/shared/stores/theme-store.ts:49` (default: 100) - -**Problem**: The UI Scale slider shows "Current: 1%" which is outside the valid range (75-150%). The theme store defaults to 100 but the persisted settings value isn't synced back to the Zustand store on load. - -**Fix**: When settings load from IPC, sync `uiScale` from persisted settings into the theme store: -```typescript -// In SettingsPage or a startup effect -useEffect(() => { - if (settings?.uiScale) setUiScale(settings.uiScale); -}, [settings?.uiScale]); -``` - -### 5b. Theme Store Not Hydrated From Persisted Settings - -**Related to 5a**: The theme store (`mode`, `colorTheme`, `uiScale`) uses hardcoded defaults and doesn't hydrate from the persisted settings on app startup. The Settings page changes persist to disk but the Zustand store resets on reload. - -**Fix**: Add a startup hydration effect that reads settings and calls `setMode()`, `setColorTheme()`, `setUiScale()`. - ---- - -## 6. Implementation Priority - -### Phase 1 — Remove Mock Data (Quick wins) -1. Wire `TodayView` to Planner service -2. Wire `ActiveAgents` to Agent service -3. Wire `DailyStats` to computed real values -4. Fix UI Scale hydration bug - -### Phase 2 — Auth Notifications -5. Add Claude CLI auth check + bottom-left notification -6. Create `` component -7. Add OAuth status checks to Spotify, Calendar, GitHub pages - -### Phase 3 — Wire Non-Functional UI -8. Add onClick handlers to Slack action buttons (with modals) -9. Add onClick handlers to Discord action buttons (with modals) -10. Add "Connect" buttons on Comms page for disconnected services - -### Phase 4 — Cleanup -11. Remove or properly implement Withings integration -12. Add Assistant capabilities help/suggestions -13. Hydrate full theme store from persisted settings on startup - ---- - -## 7. Files To Modify - -| File | Change | -|------|--------| -| `src/renderer/features/dashboard/components/TodayView.tsx` | Replace MOCK_TIME_BLOCKS with planner query | -| `src/renderer/features/dashboard/components/ActiveAgents.tsx` | Replace MOCK_AGENTS with agents query | -| `src/renderer/features/dashboard/components/DailyStats.tsx` | Replace hardcoded counts with real queries | -| `src/renderer/features/communications/components/SlackPanel.tsx` | Add onClick handlers + modals | -| `src/renderer/features/communications/components/DiscordPanel.tsx` | Add onClick handlers + modals | -| `src/renderer/features/productivity/components/SpotifyPanel.tsx` | Add OAuth status check + setup card | -| `src/renderer/features/productivity/components/CalendarWidget.tsx` | Add OAuth status check + setup card | -| `src/renderer/features/github/components/GitHubPage.tsx` | Add OAuth status check + setup card | -| `src/renderer/shared/stores/theme-store.ts` | Add hydration from persisted settings | -| `src/renderer/features/settings/components/SettingsPage.tsx` | Fix UI scale sync | -| `src/shared/ipc-contract.ts` | Add `app.checkClaudeAuth` channel | -| `src/main/ipc/handlers/` | Add Claude auth check handler | -| **NEW** `src/renderer/shared/components/AuthNotification.tsx` | Claude CLI auth notification | -| **NEW** `src/renderer/shared/components/IntegrationRequired.tsx` | Reusable OAuth setup card | -| **NEW** `src/renderer/shared/hooks/useOAuthStatus.ts` | Hook to check provider token status | diff --git a/doc-history/IMPLEMENTATION-PROMPTS.md b/doc-history/IMPLEMENTATION-PROMPTS.md deleted file mode 100644 index bd68ee3..0000000 --- a/doc-history/IMPLEMENTATION-PROMPTS.md +++ /dev/null @@ -1,923 +0,0 @@ -# Claude-UI Expansion: Master Implementation Guide - -**Project Location:** `C:\Users\Parke\Desktop\Claude-UI` -**AI Reference Docs:** `C:\Users\Parke\Desktop\Claude-UI\ai-docs\` (copied from Auto-Claude) -**Current State:** Phase 4 complete (services implemented), Phase 5 in progress (build works, dev mode launches) - ---- - -## Overview - -Claude-UI is being expanded from a coding-focused task manager into a comprehensive personal AI command center with: - -1. **Coding Workspace** (existing) - Task dashboard, terminals, agents for development -2. **Assistant Mode** (new) - Persistent AI for quick commands, notes, reminders -3. **Integrations Hub** (new) - Slack, Discord, GitHub, Spotify, Calendar, etc. -4. **Fitness Dashboard** (new) - Withings scale integration, workout logging -5. **Project Intelligence** (new) - Poly-repo support, worktree management - ---- - -## Parallel Workstream Breakdown - -Each section below is designed to run as a separate Claude Code instance. They are ordered by dependency - Workstream 1 should start first, others can run in parallel after the foundation is laid. - - ---- - -## WORKSTREAM 1: Foundation & Architecture (START FIRST) - -### Prompt for Claude Code Instance 1: - -``` -You are working on Claude-UI, an Electron + React + TypeScript desktop application. - -**Project:** C:\Users\Parke\Desktop\Claude-UI -**Reference:** Read ai-docs/AUTO-CLAUDE-REFERENCE.md for architecture patterns - -## Your Task: Foundation Infrastructure - -### 1. Fix the Current Startup Issue -The app builds but exits immediately in dev mode. Debug and fix: -- Run `npm run dev` and capture any errors -- Check if preload script path is correct (index.cjs vs index.mjs) -- Verify electron main process initialization -- Check for unhandled promise rejections - -### 2. Create the MCP Integration Layer -Build a generic MCP (Model Context Protocol) client that can connect to multiple MCP servers: - -Create: `src/main/mcp/` -- `mcp-client.ts` - Generic MCP client wrapper -- `mcp-registry.ts` - Registry of available MCP servers (spotify, calendar, slack, etc.) -- `mcp-manager.ts` - Manages connections, reconnection, health checks - -The MCP client should: -- Support SSE-based MCP servers (standard protocol) -- Handle authentication per server -- Emit events when tools are available -- Queue requests when disconnected - -### 3. Create the Assistant Service -Build the persistent assistant daemon that handles quick commands: - -Create: `src/main/services/assistant/` -- `assistant-service.ts` - Main service -- `intent-classifier.ts` - Determines if input is: quick_command | task_creation | conversation -- `command-executor.ts` - Routes commands to appropriate MCP/service - -Intent classification rules: -- "note: ..." or "remember ..." → quick_command (notes) -- "create task: ..." or "build ..." → task_creation (add to task dashboard) -- "play ..." → quick_command (spotify) -- "open ..." → quick_command (app launcher) -- Multi-sentence or ambiguous → conversation (send to Claude API) - -### 4. Add IPC Channels for Assistant -Update `src/shared/ipc-contract.ts`: -- `assistant.sendCommand` - Send text command -- `assistant.getHistory` - Get command history -- `event:assistant.response` - Stream responses back -- `event:assistant.thinking` - Show "thinking" indicator - -### 5. Create Assistant UI Tab -Add to renderer: -- `src/renderer/features/assistant/` - New feature folder -- `AssistantPage.tsx` - Main page component -- `CommandInput.tsx` - Always-visible input at bottom -- `ResponseStream.tsx` - Shows AI responses -- `QuickActions.tsx` - Common action buttons - -The assistant tab should feel like a chat interface but optimized for commands. - -### Deliverables: -1. App starts and runs without crashing -2. MCP client infrastructure in place -3. Assistant service with intent classification -4. Basic assistant UI tab -5. IPC wiring complete - -### Tech Stack Reference: -- React 19, TypeScript strict, Zustand 5, Tailwind v4 -- Path aliases: @shared, @renderer, @features, @ui -- IPC pattern: Zod schemas in ipc-contract.ts, handlers in src/main/ipc/handlers/ -``` - - ---- - -## WORKSTREAM 2: Integrations - Communication (Slack, Discord) - -### Prompt for Claude Code Instance 2: - -``` -You are working on Claude-UI, an Electron + React + TypeScript desktop application. - -**Project:** C:\Users\Parke\Desktop\Claude-UI -**Reference:** Read ai-docs/prompts/ for prompt patterns - -## Your Task: Slack & Discord Integration - -### 1. Slack MCP Server -Create a local MCP server for Slack integration: - -Create: `src/main/mcp-servers/slack/` -- `index.ts` - MCP server entry point -- `slack-client.ts` - Slack Web API wrapper -- `tools.ts` - MCP tool definitions - -Required Slack tools: -- `slack_send_message` - Send to channel/DM -- `slack_read_channel` - Get recent messages from channel -- `slack_search` - Search messages -- `slack_get_threads` - Get thread replies -- `slack_set_status` - Update user status -- `slack_list_channels` - List available channels - -Slack standup parser (user mentioned this use case): -When user types: "#standup channel Y: ticket 123 T: ticket 445 and 556 B: BE work" -Parse into structured standup format: -- Y (Yesterday): ticket 123 -- T (Today): ticket 445, 556 -- B (Blockers): BE work -Then format and post to the specified channel. - -### 2. Discord MCP Server -Create: `src/main/mcp-servers/discord/` -- `index.ts` - MCP server entry point -- `discord-client.ts` - Discord.js or REST API wrapper -- `tools.ts` - MCP tool definitions - -Required Discord tools: -- `discord_send_message` - Send to channel/DM -- `discord_call_user` - Initiate voice call (open Discord app) -- `discord_read_channel` - Get recent messages -- `discord_list_servers` - List servers/guilds -- `discord_set_status` - Update presence - -For "open discord and call xyz": -- Use Discord deeplinks: discord://discord.com/users/{user_id} -- Or spawn Discord app with specific channel/call - -### 3. Notification System -Create: `src/main/services/notifications/` -- `notification-service.ts` - Central notification hub -- `watchers/slack-watcher.ts` - Watch for Slack events -- `watchers/github-watcher.ts` - Watch for PR events (placeholder) - -Notification rules engine: -- User can define rules like: "notify me when PR is opened on my blocking tickets" -- Rules are stored in settings -- Watchers poll or use webhooks to check conditions - -### 4. Communication UI -Create: `src/renderer/features/communications/` -- `CommunicationsPage.tsx` - Overview of connected services -- `SlackPanel.tsx` - Quick Slack actions -- `DiscordPanel.tsx` - Quick Discord actions -- `NotificationRules.tsx` - Configure notification rules - -### 5. OAuth Flow for Slack -Slack requires OAuth. Implement: -- `src/main/auth/slack-oauth.ts` - OAuth2 flow -- Store tokens in electron's safeStorage -- Token refresh handling - -### Deliverables: -1. Slack MCP server with all tools -2. Discord MCP server with all tools -3. Standup parser for Slack -4. Notification watcher system -5. Basic communications UI -6. OAuth flow for Slack - -### API References: -- Slack Web API: https://api.slack.com/methods -- Discord API: https://discord.com/developers/docs -- Consider using slack-bolt for Slack -- Consider discord.js for Discord -``` - - ---- - -## WORKSTREAM 3: Integrations - Productivity (GitHub, Calendar, Spotify) - -### Prompt for Claude Code Instance 3: - -``` -You are working on Claude-UI, an Electron + React + TypeScript desktop application. - -**Project:** C:\Users\Parke\Desktop\Claude-UI -**Reference:** Read ai-docs/prompts/github/ for GitHub review patterns - -## Your Task: GitHub, Calendar, Spotify Integration - -### 1. GitHub MCP Server -Create: `src/main/mcp-servers/github/` -- `index.ts` - MCP server entry -- `github-client.ts` - GitHub REST/GraphQL API -- `tools.ts` - MCP tools - -Required GitHub tools: -- `github_list_prs` - List PRs (mine, reviewing, all) -- `github_get_pr` - Get PR details -- `github_review_pr` - Submit review -- `github_list_issues` - List issues -- `github_create_issue` - Create new issue -- `github_get_notifications` - Get notifications -- `github_watch_repo` - Add repo to watch list - -PR notification integration: -- Watch for PRs on specific repos/branches -- Notify when PR is opened that affects blocking work -- Store "blocking tickets" list in task metadata - -### 2. Google Calendar MCP Server -Create: `src/main/mcp-servers/calendar/` -- `index.ts` - MCP server entry -- `calendar-client.ts` - Google Calendar API -- `tools.ts` - MCP tools - -Required Calendar tools: -- `calendar_list_events` - Get events for date range -- `calendar_create_event` - Create new event -- `calendar_update_event` - Modify event -- `calendar_delete_event` - Remove event -- `calendar_get_free_busy` - Check availability - -Daily planner features: -- Morning summary: "Here's your day..." -- Reminder alerts before meetings -- Quick add: "meeting with John at 3pm" - -### 3. Spotify MCP Server -Create: `src/main/mcp-servers/spotify/` -- `index.ts` - MCP server entry -- `spotify-client.ts` - Spotify Web API -- `tools.ts` - MCP tools - -Required Spotify tools: -- `spotify_play` - Play track/album/playlist -- `spotify_pause` - Pause playback -- `spotify_next` - Skip track -- `spotify_previous` - Previous track -- `spotify_search` - Search music -- `spotify_get_playing` - Current track info -- `spotify_set_volume` - Adjust volume -- `spotify_add_to_queue` - Queue a track - -Voice-style commands support: -- "play lo-fi" → search playlists, play first result -- "play some jazz" → search jazz, shuffle play -- "pause" / "skip" / "volume 50%" - -### 4. Chrome/Browser Control -Create: `src/main/mcp-servers/browser/` -- `index.ts` - MCP server -- `tools.ts` - Browser tools - -Tools: -- `browser_open_url` - Open URL in default browser -- `browser_search` - Open Google search -- `browser_open_app` - Open web app (gmail, docs, etc.) - -Use: `shell.openExternal()` for URLs -Consider: Chrome DevTools Protocol for deeper control (optional) - -### 5. OAuth Manager -Create: `src/main/auth/` -- `oauth-manager.ts` - Generic OAuth2 flow handler -- `token-store.ts` - Secure token storage (electron safeStorage) -- `providers/google.ts` - Google OAuth config -- `providers/spotify.ts` - Spotify OAuth config -- `providers/github.ts` - GitHub OAuth config - -### 6. Productivity UI -Create: `src/renderer/features/productivity/` -- `ProductivityPage.tsx` - Dashboard overview -- `CalendarWidget.tsx` - Today's schedule -- `SpotifyWidget.tsx` - Now playing + controls -- `GitHubWidget.tsx` - PR/notification summary - -### Deliverables: -1. GitHub MCP server with PR watching -2. Google Calendar MCP server -3. Spotify MCP server with play commands -4. Browser control tools -5. OAuth manager for all providers -6. Productivity dashboard UI - -### API References: -- GitHub REST: https://docs.github.com/en/rest -- Google Calendar: https://developers.google.com/calendar/api -- Spotify Web API: https://developer.spotify.com/documentation/web-api -``` - - ---- - -## WORKSTREAM 4: Fitness Dashboard & Health Tracking - -### Prompt for Claude Code Instance 4: - -``` -You are working on Claude-UI, an Electron + React + TypeScript desktop application. - -**Project:** C:\Users\Parke\Desktop\Claude-UI - -## Your Task: Fitness Dashboard with Withings Integration - -### 1. Withings MCP Server -Create: `src/main/mcp-servers/withings/` -- `index.ts` - MCP server entry -- `withings-client.ts` - Withings Public API client -- `tools.ts` - MCP tools - -Withings API Setup: -- Register at https://developer.withings.com/ -- Use OAuth2 for authentication -- Public API provides: weight, body fat, bone mass, muscle mass, water %, visceral fat - -Required tools: -- `withings_get_measurements` - Get recent measurements -- `withings_get_weight_history` - Weight over time -- `withings_get_body_composition` - Full body comp data -- `withings_sync` - Trigger manual sync - -### 2. Workout Logging System -Create: `src/main/services/fitness/` -- `fitness-service.ts` - Main service -- `workout-store.ts` - Store workouts (JSON file in app data) -- `models.ts` - Workout, Exercise, Set types - -Workout data model: -```typescript -interface Workout { - id: string; - date: string; - type: 'strength' | 'cardio' | 'flexibility' | 'sport'; - duration: number; // minutes - exercises: Exercise[]; - notes?: string; -} - -interface Exercise { - name: string; - sets: Set[]; - muscleGroup?: string; -} - -interface Set { - reps?: number; - weight?: number; - duration?: number; // for timed exercises - distance?: number; // for cardio -} -``` - -Workout tools for assistant: -- `fitness_log_workout` - Log a workout -- `fitness_log_weight` - Manual weight entry -- `fitness_get_stats` - Get fitness statistics -- `fitness_get_progress` - Progress over time - -Natural language workout logging: -- "logged chest day: bench 3x10 185lbs, incline 3x8 135lbs" -- Parse into structured workout data - -### 3. Fitness Dashboard UI -Create: `src/renderer/features/fitness/` -- `FitnessPage.tsx` - Main dashboard -- `WeightChart.tsx` - Weight trend over time (use Recharts) -- `BodyComposition.tsx` - Body comp breakdown -- `WorkoutLog.tsx` - Recent workouts list -- `WorkoutForm.tsx` - Log new workout -- `StatsOverview.tsx` - Summary stats (weekly volume, consistency) - -Dashboard components: -- Weight trend chart (line graph, goal line) -- Body composition pie/bar chart -- Workout streak/consistency indicator -- Recent workouts list -- Quick log button - -### 4. Goals & Targets -Create goal tracking: -- `goals-store.ts` - Store fitness goals -- Weight goal (target weight, deadline) -- Workout frequency goal (X workouts per week) -- Specific lift goals (bench 225, etc.) - -UI for goals: -- `GoalsPanel.tsx` - Set and view goals -- Progress indicators on dashboard - -### 5. Withings OAuth Flow -- `src/main/auth/providers/withings.ts` - Withings OAuth config -- Withings uses OAuth2 with specific scopes -- Store refresh token for background sync - -### 6. Background Sync -- Periodic sync of Withings data (every 4 hours) -- Store locally for offline access -- Notification when new measurement detected - -### Deliverables: -1. Withings MCP server with OAuth -2. Workout logging service -3. Natural language workout parser -4. Fitness dashboard with charts -5. Goal tracking system -6. Background sync for Withings - -### API Reference: -- Withings: https://developer.withings.com/api-reference/ -- Use Recharts for charts (already in dependencies) -``` - - ---- - -## WORKSTREAM 5: Advanced Project Management (Poly-repo, Worktrees) - -### Prompt for Claude Code Instance 5: - -``` -You are working on Claude-UI, an Electron + React + TypeScript desktop application. - -**Project:** C:\Users\Parke\Desktop\Claude-UI -**Reference:** Read ai-docs/core/worktree.py and ai-docs/core/workspace.py for worktree patterns - -## Your Task: Advanced Git & Project Management - -### 1. Enhanced Project Model -Update the project system to support complex repo structures: - -Update: `src/shared/types/project.ts` -```typescript -interface Project { - id: string; - name: string; - path: string; - type: 'single' | 'monorepo' | 'polyrepo'; - subprojects?: SubProject[]; - // ... existing fields -} - -interface SubProject { - id: string; - name: string; - relativePath: string; // e.g., "backend", "frontend" - gitRemote?: string; // If separate git repo - defaultBranch?: string; -} - -interface Worktree { - id: string; - projectId: string; - subprojectId?: string; // Which sub-repo this worktree is for - path: string; - branch: string; - taskId?: string; // Linked task - createdAt: string; -} -``` - -### 2. Git Service Enhancement -Create: `src/main/services/git/` -- `git-service.ts` - Git operations wrapper -- `worktree-service.ts` - Worktree management -- `polyrepo-service.ts` - Multi-repo coordination - -Git operations needed: -- `git_status` - Get repo status -- `git_branches` - List branches -- `git_create_branch` - Create new branch -- `git_switch_branch` - Switch branches -- `git_create_worktree` - Create isolated worktree -- `git_remove_worktree` - Clean up worktree -- `git_detect_structure` - Detect mono/poly repo structure - -Poly-repo detection: -- Scan for nested .git directories -- Check for common patterns (backend/, frontend/, packages/) -- Ask user to confirm structure on first open - -### 3. Worktree UI for Task Isolation -When user creates a coding task: -1. Ask which sub-project (if poly-repo) -2. Create worktree from appropriate branch -3. Link worktree to task -4. Clean up worktree when task completes/merges - -Create: `src/renderer/features/projects/` -- `ProjectSetup.tsx` - Configure project structure -- `WorktreeManager.tsx` - View/manage worktrees -- `BranchSelector.tsx` - Select branch for new worktree -- `SubprojectSelector.tsx` - Choose which sub-repo - -### 4. Task-Worktree Integration -Update task creation flow: -- `CreateTaskModal.tsx` - Add worktree options -- Auto-create worktree when task starts -- Show worktree path in task detail -- Terminal opens in worktree directory - -### 5. Merge Workflow -Reference: ai-docs/merge/ for merge patterns - -Create: `src/main/services/merge/` -- `merge-service.ts` - Handle merging worktrees back - -Merge flow: -1. Task complete → User clicks "Merge" -2. Show diff preview -3. Handle conflicts (show in UI, allow manual resolution) -4. Merge to target branch -5. Clean up worktree - -### 6. Project Dashboard Enhancement -Update: `src/renderer/features/projects/` -- `ProjectDashboard.tsx` - Overview with sub-projects -- `RepoHealth.tsx` - Branch status, pending merges -- `ActiveWorktrees.tsx` - List of active worktrees - -### Deliverables: -1. Enhanced project model for poly-repos -2. Git service with worktree support -3. Poly-repo detection on project add -4. Worktree creation UI -5. Task-worktree linking -6. Merge workflow with conflict handling - -### Reference: -- Study ai-docs/core/worktree.py for worktree patterns -- Study ai-docs/core/workspace.py for workspace isolation -- Use simple-git npm package for git operations -``` - - ---- - -## WORKSTREAM 6: Notes, Daily Planner & Task System - -### Prompt for Claude Code Instance 6: - -``` -You are working on Claude-UI, an Electron + React + TypeScript desktop application. - -**Project:** C:\Users\Parke\Desktop\Claude-UI -**Reference:** Read ai-docs/spec/ for task specification patterns - -## Your Task: Notes, Daily Planner, Alerts System - -### 1. Notes Service -Create: `src/main/services/notes/` -- `notes-service.ts` - CRUD for notes -- `notes-store.ts` - Persist notes to disk - -Notes data model: -```typescript -interface Note { - id: string; - content: string; - tags: string[]; - projectId?: string; // Link to project - taskId?: string; // Link to task - createdAt: string; - updatedAt: string; - pinned: boolean; -} -``` - -Quick note commands: -- "note: buy groceries" → Create note with content -- "note for project X: remember to update API" → Link to project -- "show notes" → List recent notes -- "search notes: groceries" → Search - -### 2. Daily Planner Service -Create: `src/main/services/planner/` -- `planner-service.ts` - Daily plan management -- `planner-store.ts` - Persist plans - -Daily plan model: -```typescript -interface DailyPlan { - date: string; // YYYY-MM-DD - goals: string[]; - scheduledTasks: ScheduledTask[]; - timeBlocks: TimeBlock[]; - reflection?: string; -} - -interface ScheduledTask { - taskId: string; - scheduledTime?: string; - estimatedDuration?: number; - completed: boolean; -} - -interface TimeBlock { - startTime: string; - endTime: string; - label: string; - type: 'focus' | 'meeting' | 'break' | 'other'; -} -``` - -Planner features: -- Morning planning: Set daily goals -- Evening reflection: What got done -- Integration with Calendar (show meetings as time blocks) -- Integration with Tasks (schedule coding tasks) - -### 3. Alerts & Reminders Service -Create: `src/main/services/alerts/` -- `alert-service.ts` - Schedule and trigger alerts -- `alert-store.ts` - Persist alerts - -Alert types: -```typescript -interface Alert { - id: string; - type: 'reminder' | 'deadline' | 'notification' | 'recurring'; - message: string; - triggerAt: string; // ISO datetime - recurring?: { - frequency: 'daily' | 'weekly' | 'monthly'; - time: string; // HH:mm - daysOfWeek?: number[]; // 0-6 for weekly - }; - linkedTo?: { - type: 'task' | 'event' | 'note'; - id: string; - }; - dismissed: boolean; -} -``` - -Alert commands: -- "remind me at 3pm to call John" -- "remind me tomorrow to review PR" -- "every day at 9am remind me to check email" - -System tray notifications: -- Use Electron's Notification API -- Show notification at trigger time -- Click to open relevant item - -### 4. Notes UI -Create: `src/renderer/features/notes/` -- `NotesPage.tsx` - Notes list and editor -- `NoteEditor.tsx` - Markdown editor for notes -- `NotesList.tsx` - Searchable/filterable list -- `QuickNote.tsx` - Floating quick-add widget - -### 5. Planner UI -Create: `src/renderer/features/planner/` -- `PlannerPage.tsx` - Daily/weekly view -- `DayView.tsx` - Today's plan -- `TimeBlockEditor.tsx` - Visual time block editor -- `GoalsList.tsx` - Daily goals checklist -- `WeekOverview.tsx` - Week at a glance - -### 6. Alerts UI -Create: `src/renderer/features/alerts/` -- `AlertsPage.tsx` - Manage all alerts -- `CreateAlertModal.tsx` - Create new alert -- `AlertNotification.tsx` - System notification component -- `RecurringAlerts.tsx` - Manage recurring reminders - -### 7. Natural Language Parsing -Create: `src/main/services/nlp/` -- `time-parser.ts` - Parse time expressions - - "at 3pm" → specific time - - "tomorrow" → date - - "in 2 hours" → relative time - - "every weekday at 9am" → recurring - -Use chrono-node for time parsing (add to dependencies) - -### Deliverables: -1. Notes service with tagging and linking -2. Daily planner service -3. Alerts/reminders with recurring support -4. Notes UI with markdown editor -5. Planner UI with time blocks -6. Alerts UI with notification system -7. Natural language time parsing - -### Dependencies to add: -- chrono-node (time parsing) -- Consider: @uiw/react-md-editor for markdown -``` - - ---- - -## WORKSTREAM 7: System Tray, Background Mode & Voice Input (Future) - -### Prompt for Claude Code Instance 7: - -``` -You are working on Claude-UI, an Electron + React + TypeScript desktop application. - -**Project:** C:\Users\Parke\Desktop\Claude-UI - -## Your Task: Background Operations & Voice Input - -### 1. System Tray Integration -Create: `src/main/tray/` -- `tray-manager.ts` - System tray icon and menu -- `quick-input.ts` - Global hotkey popup - -System tray features: -- Minimize to tray option -- Tray icon shows status (idle, working, notification) -- Right-click menu: - - Show/Hide window - - Quick command (opens input popup) - - Recent commands - - Active tasks - - Quit - -Quick input popup (global hotkey, e.g., Ctrl+Shift+Space): -- Small floating window -- Single input field -- Type command, press Enter -- Closes after execution - -### 2. Global Hotkeys -Use electron's globalShortcut: -- `Ctrl+Shift+Space` - Quick command popup -- `Ctrl+Shift+N` - Quick note -- `Ctrl+Shift+T` - Quick task -- Make hotkeys configurable in settings - -### 3. Background Service Manager -Create: `src/main/services/background/` -- `background-manager.ts` - Orchestrate background tasks -- `scheduler.ts` - Cron-like scheduler - -Background tasks: -- Withings sync (every 4 hours) -- Slack/Discord message watching -- GitHub PR notifications -- Calendar reminder checks -- Alert trigger checks - -### 4. Voice Input (Optional/Future) -Create: `src/main/services/voice/` -- `voice-service.ts` - Voice input handling -- `whisper-client.ts` - OpenAI Whisper API or local whisper.cpp - -Voice flow: -1. User holds hotkey or clicks mic button -2. Audio recorded -3. Sent to Whisper for transcription -4. Transcription sent to assistant - -Options: -- OpenAI Whisper API (requires API key) -- Local whisper.cpp (larger, but offline) -- Azure Speech Services -- Consider: voice activity detection - -### 5. Persistent Mode Toggle -Allow app to run in two modes: -- **Window Mode**: Normal desktop app -- **Background Mode**: Minimized to tray, responds to hotkeys - -Settings: -- Start minimized to tray -- Keep running on window close -- Launch at system startup -- Background sync intervals - -### 6. Settings UI for Background -Update: `src/renderer/features/settings/` -- `BackgroundSettings.tsx` - Configure background behavior -- `HotkeySettings.tsx` - Customize global hotkeys -- `TraySettings.tsx` - Tray icon behavior -- `VoiceSettings.tsx` - Voice input config (future) - -### Deliverables: -1. System tray with context menu -2. Quick input popup window -3. Global hotkeys (configurable) -4. Background service scheduler -5. Settings UI for all background features -6. (Optional) Voice input integration - -### Notes: -- Test hotkeys don't conflict with other apps -- Handle tray icon on different OS (Windows vs Mac) -- Background mode should use minimal resources -``` - - ---- - -## Execution Order & Dependencies - -``` -WORKSTREAM 1 (Foundation) ─────────────────────────────────────────┐ - Must complete first: MCP layer, Assistant service, App startup │ - │ - ┌────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌──────────────────────┬──────────────────────┬──────────────────────┐ -│ WORKSTREAM 2 │ WORKSTREAM 3 │ WORKSTREAM 4 │ -│ Slack/Discord │ GitHub/Calendar/ │ Fitness/Withings │ -│ │ Spotify │ │ -│ Can run in parallel │ Can run in parallel │ Can run in parallel │ -└──────────────────────┴──────────────────────┴──────────────────────┘ - │ │ │ - └────────────────────────┼────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────────────────────────────────┐ -│ WORKSTREAM 5 │ WORKSTREAM 6 │ -│ Git/Worktrees/Poly-repo │ Notes/Planner/Alerts │ -│ │ │ -│ Can run in parallel │ Can run in parallel │ -└─────────────────────────────────┴────────────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────────────────────────────────┐ -│ WORKSTREAM 7 │ -│ System Tray / Background / Voice │ -│ │ -│ Should run last (ties everything together) │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -## Quick Start Instructions - -### For Each Terminal Instance: - -1. **Navigate to project:** - ```bash - cd C:\Users\Parke\Desktop\Claude-UI - ``` - -2. **Read your workstream prompt from:** - ``` - IMPLEMENTATION-PROMPTS.md - ``` - -3. **Read reference docs:** - ``` - ai-docs/AUTO-CLAUDE-REFERENCE.md - ai-docs/prompts/ (relevant prompts) - ai-docs/agents/ (agent patterns) - ai-docs/core/ (core utilities) - ``` - -4. **Understand current codebase:** - ``` - src/main/ - Electron main process - src/renderer/ - React frontend - src/shared/ - Shared types, IPC contracts - src/preload/ - Electron preload scripts - ``` - -5. **Follow the patterns:** - - Services go in `src/main/services/` - - MCP servers go in `src/main/mcp-servers/` - - IPC handlers go in `src/main/ipc/handlers/` - - UI features go in `src/renderer/features/` - - All IPC channels defined in `src/shared/ipc-contract.ts` - ---- - -## API Keys & OAuth Apps You'll Need - -| Service | Where to Get | -|---------|-------------| -| Slack | https://api.slack.com/apps | -| Discord | https://discord.com/developers/applications | -| GitHub | https://github.com/settings/tokens | -| Google (Calendar) | https://console.cloud.google.com/ | -| Spotify | https://developer.spotify.com/dashboard | -| Withings | https://developer.withings.com/ | -| OpenAI (Whisper) | https://platform.openai.com/ | - -Store API keys/tokens securely using Electron's safeStorage. - ---- - -## Notes for All Instances - -1. **Use TypeScript strict mode** - The project has strict: true -2. **Follow existing patterns** - Look at existing services as templates -3. **Zod for validation** - All IPC uses Zod schemas -4. **Zustand for state** - Frontend state management -5. **Tailwind for styling** - v4 with CSS variables -6. **Test as you go** - Run `npm run dev` frequently -7. **Commit often** - Make atomic commits per feature - -Good luck! 🚀 diff --git a/doc-history/LOCAL-DEV-GUIDE.md b/doc-history/LOCAL-DEV-GUIDE.md deleted file mode 100644 index 0664807..0000000 --- a/doc-history/LOCAL-DEV-GUIDE.md +++ /dev/null @@ -1,295 +0,0 @@ -# Claude-UI Local Development Guide - -## Prerequisites - -| Tool | Version | Check | -|------|---------|-------| -| **Node.js** | 20+ (LTS) | `node -v` | -| **npm** | 10+ | `npm -v` | -| **Git** | 2.40+ | `git -v` | -| **Windows 10/11** or **macOS 12+** | - | - | -| **Python 3** + **Visual Studio Build Tools** | Windows only, for native modules | `python --version` | - -> **Windows note:** `@lydell/node-pty` (terminal emulation) requires native compilation. -> Install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) with the "Desktop development with C++" workload, or run: -> ``` -> npm install -g windows-build-tools -> ``` - ---- - -## Quick Start - -```bash -# 1. Clone the repo -git clone https://github.com/ParkerM2/Claude-UI.git -cd Claude-UI - -# 2. Install dependencies -npm install - -# 3. Start dev mode (hot-reload for renderer, auto-restart for main) -npm run dev -``` - -The app opens automatically. Electron main process logs appear in the terminal. Renderer DevTools can be opened with `Ctrl+Shift+I` (or `Cmd+Opt+I` on macOS). - ---- - -## Available Scripts - -| Command | Description | -|---------|-------------| -| `npm run dev` | Start in development mode (electron-vite, hot reload) | -| `npm run build` | Production build to `out/` | -| `npm run preview` | Preview production build locally | -| `npm run lint` | ESLint check (zero tolerance) | -| `npm run lint:fix` | Auto-fix lint issues | -| `npm run format` | Prettier format all files | -| `npm run typecheck` | TypeScript type check (`tsc --noEmit`) | -| `npm run test` | Run Vitest test suite | - ---- - -## Project Structure - -``` -Claude-UI/ -├── src/ -│ ├── main/ # Electron main process (Node.js) -│ │ ├── index.ts # App entry — creates window, initializes services -│ │ ├── auth/ # OAuth2 manager, token store, provider configs -│ │ ├── ipc/ # IPC router + domain handlers -│ │ ├── mcp/ # MCP client/registry/manager infrastructure -│ │ ├── mcp-servers/ # External service clients (GitHub, Slack, Spotify, etc.) -│ │ ├── services/ # Business logic (one folder per domain) -│ │ └── tray/ # System tray, hotkeys, quick input -│ ├── preload/ # Context bridge (typed API for renderer) -│ ├── renderer/ # React app (browser context) -│ │ ├── app/ # Router, providers, layouts, sidebar -│ │ ├── features/ # Feature modules (self-contained) -│ │ │ ├── alerts/ # Alerts & reminders -│ │ │ ├── assistant/ # AI command assistant -│ │ │ ├── changelog/ # Version history -│ │ │ ├── communications/ # Slack & Discord -│ │ │ ├── dashboard/ # Home dashboard -│ │ │ ├── fitness/ # Workout & body tracking -│ │ │ ├── github/ # PRs, issues, notifications -│ │ │ ├── ideation/ # Idea board -│ │ │ ├── insights/ # Project metrics -│ │ │ ├── tasks/ # Task dashboard (table-based) -│ │ │ ├── notes/ # Quick notes -│ │ │ ├── planner/ # Daily planner -│ │ │ ├── productivity/ # Spotify + Calendar widgets -│ │ │ ├── projects/ # Project management + git -│ │ │ ├── roadmap/ # Milestone timeline -│ │ │ ├── settings/ # App settings + hub config -│ │ │ └── terminals/ # Terminal emulation -│ │ └── shared/ # Shared hooks, stores, components -│ └── shared/ # Code shared between main + renderer -│ ├── ipc-contract.ts # THE source of truth for all IPC -│ ├── constants/ # Routes, themes, etc. -│ └── types/ # Domain type definitions -├── hub/ # Hub backend (Fastify + SQLite, runs in Docker) -├── nginx/ # Reverse proxy config for hub -├── docker-compose.yml # Hub + nginx stack -├── ai-docs/ # Architecture, patterns, linting docs -├── .claude/agents/ # AI agent specifications (27 agents) -└── CLAUDE.md # AI agent guidelines -``` - ---- - -## Architecture at a Glance - -``` -┌─────────────────────────────────────────────────────────┐ -│ Renderer (React) │ -│ Features → React Query hooks → ipc() helper │ -│ │ │ -│ ▼ │ -│ Preload Bridge (contextBridge) │ -├─────────────────────────────────────────────────────────┤ -│ Main Process (Node) │ -│ IPC Router → Handlers → Services → Data (JSON files) │ -│ │ │ -│ ┌───┴───┐ │ -│ MCP Servers OAuth Manager │ -│ (GitHub, Slack, (GitHub, Google, │ -│ Spotify, etc.) Spotify tokens) │ -├─────────────────────────────────────────────────────────┤ -│ Hub Backend (optional, Docker) │ -│ Fastify REST + WebSocket → SQLite │ -└─────────────────────────────────────────────────────────┘ -``` - -**Data flow:** `ipc-contract.ts` defines Zod schemas → IPC Router validates & routes → Handlers call Services → Services return data → React Query caches it. - ---- - -## Setting Up Integrations (Optional) - -Most features work locally without any API keys. The integrations below are optional and require OAuth credentials: - -### GitHub Integration - -1. Create a [GitHub OAuth App](https://github.com/settings/developers) -2. Set callback URL to `claude-ui://oauth/callback` -3. Add client ID/secret to `src/main/auth/providers/github.ts` - -### Spotify Integration - -1. Create a [Spotify App](https://developer.spotify.com/dashboard) -2. Add `claude-ui://oauth/callback` as a redirect URI -3. Add client ID/secret to `src/main/auth/providers/spotify.ts` - -### Google Calendar Integration - -1. Create a project in [Google Cloud Console](https://console.cloud.google.com) -2. Enable the Calendar API -3. Create OAuth 2.0 credentials with `claude-ui://oauth/callback` redirect -4. Add client ID/secret to `src/main/auth/providers/google.ts` - -### Slack Integration - -1. Create a [Slack App](https://api.slack.com/apps) -2. Add OAuth scopes: `channels:read`, `chat:write`, `users:read` -3. Add `claude-ui://oauth/callback` as a redirect URL -4. Add client ID/secret to `src/main/auth/providers/slack.ts` - -> **Security note:** OAuth credentials are stored locally via Electron's `safeStorage` API (OS keychain encryption). Never commit client secrets to the repo. - ---- - -## Hub Backend (Optional) - -The hub provides cloud sync, multi-device access, and a REST API for external tools. - -### Running with Docker - -```bash -# Generate self-signed TLS certs (first time only) -# PowerShell: -./scripts/generate-certs.ps1 -# Bash: -./scripts/generate-certs.sh - -# Start hub + nginx -docker compose up -d - -# Check logs -docker compose logs -f hub -``` - -The hub runs at `https://localhost:4443` (nginx) / `http://localhost:3001` (direct). - -### Connecting the App to Hub - -1. Open **Settings** in the app -2. Go to the **Hub** tab -3. Enter hub URL: `https://localhost:4443` -4. Generate an API key from the hub admin, paste it in -5. Click **Connect** - ---- - -## Development Workflow - -### Adding a New Feature - -1. **Define types** in `src/shared/types/.ts` -2. **Add IPC channels** in `src/shared/ipc-contract.ts` (Zod schemas) -3. **Create service** in `src/main/services//-service.ts` -4. **Create handler** in `src/main/ipc/handlers/-handlers.ts` -5. **Register handler** in `src/main/ipc/index.ts` -6. **Create service instance** in `src/main/index.ts` -7. **Build feature module** in `src/renderer/features//`: - - `api/queryKeys.ts` — React Query cache keys - - `api/use.ts` — Query/mutation hooks - - `components/Page.tsx` — UI - - `store.ts` — Zustand UI state - - `index.ts` — Barrel export -8. **Add route** in `src/renderer/app/router.tsx` -9. **Add sidebar entry** in `src/renderer/app/layouts/Sidebar.tsx` -10. **Run checks**: `npm run lint && npm run typecheck && npm run build` - -### Key Patterns - -- **Services** return sync values (not Promises); handlers wrap with `Promise.resolve()` -- **Exception**: network calls (OAuth, GitHub API, etc.) are async -- **IPC contract** is the single source of truth — types flow automatically from Zod schemas -- **React Query** for server state, **Zustand** for UI state -- **Feature modules** are self-contained: each has its own api/, components/, hooks/, store - -### Linting Rules - -This project enforces extremely strict ESLint (zero violations). Key rules: - -- No `any` — use `unknown` + type narrowing -- No `!` (non-null assertion) — use `?? fallback` -- `strict-boolean-expressions` — use `arr.length > 0` not `arr.length` -- `no-floating-promises` — prefix with `void` operator -- `consistent-type-imports` — always `import type { T }` -- `jsx-a11y strict` — buttons need `type="button"` - -Run `npm run lint:fix` to auto-fix what's possible, then manually fix the rest. - ---- - -## Troubleshooting - -### `npm install` fails with native module errors - -On Windows, ensure Visual Studio Build Tools are installed: -```bash -npm install -g windows-build-tools -``` - -Or install manually: VS Build Tools with "Desktop development with C++" workload. - -### Dev server fails to start - -```bash -# Clear build cache and node_modules -rm -rf node_modules out dist -npm install -npm run dev -``` - -### Terminal feature doesn't work - -The terminal requires `@lydell/node-pty`, which needs native compilation. If it fails: -1. Ensure Python 3 is in your PATH -2. Ensure C++ build tools are installed -3. Try: `npm rebuild @lydell/node-pty` - -### Port conflicts - -- Dev server: `5173` (Vite renderer) -- Hub backend: `3001` -- Nginx proxy: `4443` - -Kill conflicting processes or change ports in config. - -### "Cannot find module" errors after branch switch - -```bash -npm install # Reinstall deps -npm run dev # Restart -``` - ---- - -## Building for Production - -```bash -# Build all bundles -npm run build - -# Output structure: -# out/main/index.cjs — Main process bundle -# out/preload/index.mjs — Preload script -# out/renderer/ — React app (HTML + JS + CSS) -``` - -To package as a distributable app, add `electron-builder` config (not yet configured). diff --git a/doc-history/MASTER-CHECKLIST.md b/doc-history/MASTER-CHECKLIST.md deleted file mode 100644 index 9e8498f..0000000 --- a/doc-history/MASTER-CHECKLIST.md +++ /dev/null @@ -1,514 +0,0 @@ -# Claude-UI Master Implementation Checklist - -> Generated from IMPLEMENTATION-PROMPTS.md + VISION.md analysis -> Status: What's done, what's left, what to build next - ---- - -## CURRENT STATE SUMMARY - -### Fully Implemented & Working -- [x] Dashboard (GreetingHeader, TodayView, RecentProjects, ActiveAgents, QuickCapture, DailyStats) -- [x] Project Management (CRUD, file persistence, directory picker) -- [x] Task System (create, update, delete, execute, subtasks, progress) -- [x] Task Dashboard (table-based with filters, sorting, and status columns; replaced former Kanban board) -- [x] Terminal Grid (xterm.js + node-pty, tabs, resize, PTY spawning) -- [x] Agent Dashboard (spawn Claude CLI, stop/pause/resume, log parsing) -- [x] Settings (theme, profiles, UI scale, font family/size, color themes) -- [x] IPC Architecture (26 invoke channels, 10 event channels, Zod validation) -- [x] 5 Main Process Services (project, task, agent, terminal, settings) -- [x] 5 IPC Handler Files (all wired and registered) -- [x] ESLint 0 violations, Prettier clean, TypeScript compiles -- [x] Production build verified - -### Stubs (Placeholder UI Only) -- [ ] GitHub integration page → needs real implementation -- [ ] Roadmap page → needs real implementation -- [ ] Ideation page → needs real implementation -- [ ] Task list view (route exists, no component) - -### Mock Data (Hardcoded, Not Connected) -- [ ] Changelog (static v0.1.0-v0.3.0) → needs real data source -- [ ] Insights (static stats) → needs real metrics from services - -### Hub Backend (Exists but NOT Integrated) -- [x] Hub Fastify server exists (hub/) -- [x] SQLite database schema -- [x] 7 REST route groups -- [x] WebSocket broadcaster -- [x] API key auth middleware -- [ ] Hub NOT connected to Electron app -- [ ] No offline mode / local cache -- [ ] No connection manager in Electron -- [ ] No cross-device sync - ---- - -## WORKSTREAM 1: Foundation & Architecture - -### 1.1 MCP Integration Layer -- [ ] Create `src/main/mcp/mcp-client.ts` — Generic MCP client wrapper -- [ ] Create `src/main/mcp/mcp-registry.ts` — Registry of available MCP servers -- [ ] Create `src/main/mcp/mcp-manager.ts` — Connection management, reconnection, health checks -- [ ] SSE-based MCP server support -- [ ] Per-server authentication handling -- [ ] Event emission when tools are available -- [ ] Request queuing when disconnected - -### 1.2 Assistant Service -- [ ] Create `src/main/services/assistant/assistant-service.ts` — Main service -- [ ] Create `src/main/services/assistant/intent-classifier.ts` — Classify: quick_command | task_creation | conversation -- [ ] Create `src/main/services/assistant/command-executor.ts` — Route commands to MCP/service -- [ ] Intent rules: note/remember → notes, create task/build → task dashboard, play → spotify, open → launcher, multi-sentence → conversation - -### 1.3 Assistant IPC Channels -- [ ] Add `assistant.sendCommand` to ipc-contract.ts -- [ ] Add `assistant.getHistory` to ipc-contract.ts -- [ ] Add `event:assistant.response` to ipc-contract.ts -- [ ] Add `event:assistant.thinking` to ipc-contract.ts -- [ ] Create `src/main/ipc/handlers/assistant-handlers.ts` -- [ ] Register handlers in `src/main/ipc/index.ts` - -### 1.4 Assistant UI -- [ ] Create `src/renderer/features/assistant/` feature folder -- [ ] Create `AssistantPage.tsx` — Main page component -- [ ] Create `CommandInput.tsx` — Always-visible input at bottom -- [ ] Create `ResponseStream.tsx` — Shows AI responses -- [ ] Create `QuickActions.tsx` — Common action buttons -- [ ] Create `src/renderer/features/assistant/api/` — React Query hooks -- [ ] Create `src/renderer/features/assistant/hooks/` — Event hooks -- [ ] Create `src/renderer/features/assistant/store.ts` — Zustand store -- [ ] Add route `/assistant` to router -- [ ] Add sidebar navigation entry - -### 1.5 Shared Types for Assistant -- [ ] Add `AssistantCommand` type to `src/shared/types/` -- [ ] Add `AssistantResponse` type -- [ ] Add `IntentType` union type -- [ ] Add `CommandHistory` type - ---- - -## WORKSTREAM 2: Communication Integrations (Slack & Discord) - -### 2.1 Slack MCP Server -- [ ] Create `src/main/mcp-servers/slack/index.ts` — MCP server entry -- [ ] Create `src/main/mcp-servers/slack/slack-client.ts` — Slack Web API wrapper -- [ ] Create `src/main/mcp-servers/slack/tools.ts` — MCP tool definitions -- [ ] Implement `slack_send_message` tool -- [ ] Implement `slack_read_channel` tool -- [ ] Implement `slack_search` tool -- [ ] Implement `slack_get_threads` tool -- [ ] Implement `slack_set_status` tool -- [ ] Implement `slack_list_channels` tool -- [ ] Standup parser (#standup channel Y: T: B:) - -### 2.2 Discord MCP Server -- [ ] Create `src/main/mcp-servers/discord/index.ts` -- [ ] Create `src/main/mcp-servers/discord/discord-client.ts` -- [ ] Create `src/main/mcp-servers/discord/tools.ts` -- [ ] Implement `discord_send_message` tool -- [ ] Implement `discord_call_user` tool (deeplink) -- [ ] Implement `discord_read_channel` tool -- [ ] Implement `discord_list_servers` tool -- [ ] Implement `discord_set_status` tool - -### 2.3 Notification System -- [ ] Create `src/main/services/notifications/notification-service.ts` -- [ ] Create `src/main/services/notifications/watchers/slack-watcher.ts` -- [ ] Create `src/main/services/notifications/watchers/github-watcher.ts` -- [ ] Notification rules engine (user-defined rules) -- [ ] Rules stored in settings - -### 2.4 Communication UI -- [ ] Create `src/renderer/features/communications/CommunicationsPage.tsx` -- [ ] Create `SlackPanel.tsx` — Quick Slack actions -- [ ] Create `DiscordPanel.tsx` — Quick Discord actions -- [ ] Create `NotificationRules.tsx` — Configure notification rules -- [ ] Add route and sidebar entry - -### 2.5 Slack OAuth -- [ ] Create `src/main/auth/slack-oauth.ts` — OAuth2 flow -- [ ] Token storage in electron safeStorage -- [ ] Token refresh handling - ---- - -## WORKSTREAM 3: Productivity Integrations (GitHub, Calendar, Spotify) - -### 3.1 GitHub MCP Server -- [ ] Create `src/main/mcp-servers/github/index.ts` -- [ ] Create `src/main/mcp-servers/github/github-client.ts` -- [ ] Create `src/main/mcp-servers/github/tools.ts` -- [ ] Implement `github_list_prs` tool -- [ ] Implement `github_get_pr` tool -- [ ] Implement `github_review_pr` tool -- [ ] Implement `github_list_issues` tool -- [ ] Implement `github_create_issue` tool -- [ ] Implement `github_get_notifications` tool -- [ ] Implement `github_watch_repo` tool -- [ ] PR notification integration -- [ ] Replace GitHub stub page with real implementation - -### 3.2 Google Calendar MCP Server -- [ ] Create `src/main/mcp-servers/calendar/index.ts` -- [ ] Create `src/main/mcp-servers/calendar/calendar-client.ts` -- [ ] Create `src/main/mcp-servers/calendar/tools.ts` -- [ ] Implement `calendar_list_events` tool -- [ ] Implement `calendar_create_event` tool -- [ ] Implement `calendar_update_event` tool -- [ ] Implement `calendar_delete_event` tool -- [ ] Implement `calendar_get_free_busy` tool -- [ ] Morning summary generation -- [ ] Meeting reminders - -### 3.3 Spotify MCP Server -- [ ] Create `src/main/mcp-servers/spotify/index.ts` -- [ ] Create `src/main/mcp-servers/spotify/spotify-client.ts` -- [ ] Create `src/main/mcp-servers/spotify/tools.ts` -- [ ] Implement `spotify_play` tool -- [ ] Implement `spotify_pause` tool -- [ ] Implement `spotify_next` / `spotify_previous` tools -- [ ] Implement `spotify_search` tool -- [ ] Implement `spotify_get_playing` tool -- [ ] Implement `spotify_set_volume` tool -- [ ] Implement `spotify_add_to_queue` tool -- [ ] Natural language play commands - -### 3.4 Browser Control -- [ ] Create `src/main/mcp-servers/browser/index.ts` -- [ ] Create `src/main/mcp-servers/browser/tools.ts` -- [ ] Implement `browser_open_url` tool (shell.openExternal) -- [ ] Implement `browser_search` tool -- [ ] Implement `browser_open_app` tool - -### 3.5 OAuth Manager -- [ ] Create `src/main/auth/oauth-manager.ts` — Generic OAuth2 flow -- [ ] Create `src/main/auth/token-store.ts` — Secure token storage (safeStorage) -- [ ] Create `src/main/auth/providers/google.ts` -- [ ] Create `src/main/auth/providers/spotify.ts` -- [ ] Create `src/main/auth/providers/github.ts` - -### 3.6 Productivity UI -- [ ] Create `src/renderer/features/productivity/ProductivityPage.tsx` -- [ ] Create `CalendarWidget.tsx` — Today's schedule -- [ ] Create `SpotifyWidget.tsx` — Now playing + controls -- [ ] Create `GitHubWidget.tsx` — PR/notification summary -- [ ] Add route and sidebar entry - ---- - -## WORKSTREAM 4: Fitness Dashboard - -### 4.1 Withings MCP Server -- [ ] Create `src/main/mcp-servers/withings/index.ts` -- [ ] Create `src/main/mcp-servers/withings/withings-client.ts` -- [ ] Create `src/main/mcp-servers/withings/tools.ts` -- [ ] Implement `withings_get_measurements` tool -- [ ] Implement `withings_get_weight_history` tool -- [ ] Implement `withings_get_body_composition` tool -- [ ] Implement `withings_sync` tool - -### 4.2 Fitness Service -- [ ] Create `src/main/services/fitness/fitness-service.ts` -- [ ] Create `src/main/services/fitness/workout-store.ts` -- [ ] Create `src/main/services/fitness/models.ts` — Workout, Exercise, Set types -- [ ] Implement `fitness_log_workout` tool -- [ ] Implement `fitness_log_weight` tool -- [ ] Implement `fitness_get_stats` tool -- [ ] Implement `fitness_get_progress` tool -- [ ] Natural language workout parser - -### 4.3 Fitness UI -- [ ] Create `src/renderer/features/fitness/FitnessPage.tsx` -- [ ] Create `WeightChart.tsx` — Weight trend (Recharts) -- [ ] Create `BodyComposition.tsx` — Body comp breakdown -- [ ] Create `WorkoutLog.tsx` — Recent workouts list -- [ ] Create `WorkoutForm.tsx` — Log new workout -- [ ] Create `StatsOverview.tsx` — Summary stats -- [ ] Add route and sidebar entry - -### 4.4 Fitness Goals -- [ ] Create `src/main/services/fitness/goals-store.ts` -- [ ] Create `GoalsPanel.tsx` — Set and view goals -- [ ] Weight goal tracking -- [ ] Workout frequency goals -- [ ] Lift progression goals - -### 4.5 Withings OAuth & Sync -- [ ] Create `src/main/auth/providers/withings.ts` -- [ ] Background sync (every 4 hours) -- [ ] Local storage for offline access -- [ ] New measurement notifications - ---- - -## WORKSTREAM 5: Advanced Project Management - -### 5.1 Enhanced Project Model -- [ ] Update `src/shared/types/project.ts` — Add `type`, `subprojects` fields -- [ ] Add `SubProject` type -- [ ] Add `Worktree` type -- [ ] Update IPC contract for new project fields - -### 5.2 Git Service -- [ ] Create `src/main/services/git/git-service.ts` — Git operations wrapper -- [ ] Create `src/main/services/git/worktree-service.ts` — Worktree management -- [ ] Create `src/main/services/git/polyrepo-service.ts` — Multi-repo coordination -- [ ] Implement `git_status`, `git_branches`, `git_create_branch`, `git_switch_branch` -- [ ] Implement `git_create_worktree`, `git_remove_worktree` -- [ ] Implement `git_detect_structure` — Detect mono/poly-repo -- [ ] Install `simple-git` npm package - -### 5.3 Worktree UI -- [ ] Create `src/renderer/features/projects/ProjectSetup.tsx` -- [ ] Create `WorktreeManager.tsx` -- [ ] Create `BranchSelector.tsx` -- [ ] Create `SubprojectSelector.tsx` - -### 5.4 Task-Worktree Integration -- [ ] Update `CreateTaskModal` with worktree options -- [ ] Auto-create worktree on task start -- [ ] Show worktree path in task detail -- [ ] Terminal opens in worktree directory - -### 5.5 Merge Workflow -- [ ] Create `src/main/services/merge/merge-service.ts` -- [ ] Diff preview UI -- [ ] Conflict handling UI -- [ ] Merge + cleanup flow - ---- - -## WORKSTREAM 6: Notes, Daily Planner & Alerts - -### 6.1 Notes Service -- [ ] Create `src/main/services/notes/notes-service.ts` -- [ ] Create `src/main/services/notes/notes-store.ts` -- [ ] Add `Note` type to shared types -- [ ] Add IPC channels: `notes.list`, `notes.create`, `notes.update`, `notes.delete`, `notes.search` -- [ ] Add IPC handlers -- [ ] Tagging system -- [ ] Project/task linking - -### 6.2 Notes UI -- [ ] Create `src/renderer/features/notes/NotesPage.tsx` -- [ ] Create `NoteEditor.tsx` — Markdown editor -- [ ] Create `NotesList.tsx` — Searchable/filterable list -- [ ] Create `QuickNote.tsx` — Floating quick-add -- [ ] Add route and sidebar entry - -### 6.3 Daily Planner Service -- [ ] Create `src/main/services/planner/planner-service.ts` -- [ ] Create `src/main/services/planner/planner-store.ts` -- [ ] Add `DailyPlan`, `ScheduledTask`, `TimeBlock` types -- [ ] Add IPC channels for planner -- [ ] Calendar integration (show meetings as time blocks) -- [ ] Task scheduling integration - -### 6.4 Planner UI -- [ ] Create `src/renderer/features/planner/PlannerPage.tsx` -- [ ] Create `DayView.tsx` — Today's plan -- [ ] Create `TimeBlockEditor.tsx` — Visual time block editor -- [ ] Create `GoalsList.tsx` — Daily goals checklist -- [ ] Create `WeekOverview.tsx` — Week at a glance -- [ ] Add route and sidebar entry - -### 6.5 Alerts Service -- [ ] Create `src/main/services/alerts/alert-service.ts` -- [ ] Create `src/main/services/alerts/alert-store.ts` -- [ ] Add `Alert` type with recurring support -- [ ] Electron Notification API integration -- [ ] Natural language time parsing (chrono-node) -- [ ] Reminder commands: "remind me at 3pm..." - -### 6.6 Alerts UI -- [ ] Create `src/renderer/features/alerts/AlertsPage.tsx` -- [ ] Create `CreateAlertModal.tsx` -- [ ] Create `AlertNotification.tsx` -- [ ] Create `RecurringAlerts.tsx` -- [ ] Add route and sidebar entry - -### 6.7 NLP Time Parser -- [ ] Create `src/main/services/nlp/time-parser.ts` -- [ ] Install `chrono-node` dependency -- [ ] Parse: "at 3pm", "tomorrow", "in 2 hours", "every weekday at 9am" - ---- - -## WORKSTREAM 7: System Tray, Background & Voice - -### 7.1 System Tray -- [ ] Create `src/main/tray/tray-manager.ts` — Tray icon and menu -- [ ] Create `src/main/tray/quick-input.ts` — Global hotkey popup -- [ ] Minimize to tray option -- [ ] Tray icon status (idle, working, notification) -- [ ] Right-click context menu (show/hide, quick command, recent, active tasks, quit) - -### 7.2 Global Hotkeys -- [ ] `Ctrl+Shift+Space` — Quick command popup -- [ ] `Ctrl+Shift+N` — Quick note -- [ ] `Ctrl+Shift+T` — Quick task -- [ ] Configurable hotkeys in settings - -### 7.3 Background Service Manager -- [ ] Create `src/main/services/background/background-manager.ts` -- [ ] Create `src/main/services/background/scheduler.ts` — Cron-like scheduler -- [ ] Schedule: Withings sync, Slack/Discord watching, GitHub notifications, calendar reminders, alert triggers - -### 7.4 Voice Input (Future) -- [ ] Create `src/main/services/voice/voice-service.ts` -- [ ] Create `src/main/services/voice/whisper-client.ts` -- [ ] Push-to-talk / hotkey recording -- [ ] Whisper API transcription -- [ ] Route transcription to assistant - -### 7.5 Persistent Mode -- [ ] Window mode vs background mode toggle -- [ ] Start minimized to tray setting -- [ ] Keep running on window close -- [ ] Launch at system startup -- [ ] Background sync intervals - -### 7.6 Background Settings UI -- [ ] Create `BackgroundSettings.tsx` -- [ ] Create `HotkeySettings.tsx` -- [ ] Create `TraySettings.tsx` -- [ ] Create `VoiceSettings.tsx` (future) - ---- - -## CROSS-CUTTING: Hub Integration (VISION Phase 2) - -### Hub Connection -- [ ] Create `src/main/services/hub/hub-connection.ts` — Connection manager -- [ ] Hub URL + API key configuration in settings -- [ ] WebSocket client for real-time sync -- [ ] REST client for CRUD operations -- [ ] Fallback to local storage when hub unreachable - -### Offline Mode -- [ ] Local SQLite cache in Electron app -- [ ] Queue mutations when offline -- [ ] Sync on reconnect -- [ ] Conflict resolution (last-write-wins) - -### Data Migration -- [ ] Migrate JSON file storage to SQLite (local cache) -- [ ] Sync local SQLite ↔ hub SQLite -- [ ] Machine-specific data (terminals, paths) stays local - ---- - -## CROSS-CUTTING: Existing Stubs → Real Features - -### GitHub Page (Replace Stub) -- [ ] Replace `src/renderer/features/github/index.tsx` stub -- [ ] Create full GitHub feature module (api/, components/, hooks/, store.ts) -- [ ] PR list, issue list, notification views -- [ ] Depends on: GitHub MCP Server (WS3) - -### Roadmap Page (Replace Stub) -- [ ] Replace `src/renderer/features/roadmap/index.tsx` stub -- [ ] Create roadmap feature with timeline/milestone views -- [ ] Integration with task system - -### Ideation Page (Replace Stub) -- [ ] Replace `src/renderer/features/ideation/index.tsx` stub -- [ ] Create ideation board (brainstorming, idea capture) -- [ ] Integration with notes and tasks - -### Changelog (Connect to Real Data) -- [ ] Replace mock data with real version tracking -- [ ] Auto-generate from git tags/commits - -### Insights (Connect to Real Data) -- [ ] Replace mock data with real metrics -- [ ] Query actual task completion rates, agent runs, etc. - ---- - -## AGENT REQUIREMENTS PER WORKSTREAM - -### WS1 Agents Needed -- `mcp-engineer` — MCP client/registry/manager implementation -- `assistant-engineer` — Assistant service + intent classifier -- Schema Designer → assistant types -- Service Engineer → assistant service -- IPC Handler Engineer → assistant handlers -- Hook Engineer → assistant React Query hooks -- Component Engineer → assistant UI components -- Router Engineer → assistant route - -### WS2 Agents Needed -- `integration-engineer` — Slack/Discord MCP servers -- `oauth-engineer` — OAuth2 flow implementation -- `notification-engineer` — Notification service + watchers -- Component Engineer → communication UI - -### WS3 Agents Needed -- `integration-engineer` — GitHub/Calendar/Spotify MCP servers -- `oauth-engineer` — OAuth manager + providers -- Component Engineer → productivity UI - -### WS4 Agents Needed -- `integration-engineer` — Withings MCP server -- `fitness-engineer` — Workout logging + goals -- Component Engineer → fitness dashboard + charts -- `oauth-engineer` → Withings OAuth - -### WS5 Agents Needed -- `git-engineer` — Git/worktree/polyrepo services -- Schema Designer → enhanced project types -- Component Engineer → worktree UI -- Service Engineer → merge service - -### WS6 Agents Needed -- Service Engineer → notes, planner, alerts services -- `nlp-engineer` — Time parser (chrono-node) -- Component Engineer → notes, planner, alerts UI -- Hook Engineer → React Query hooks for all 3 - -### WS7 Agents Needed -- `tray-engineer` — System tray + global hotkeys -- `scheduler-engineer` — Background task scheduler -- Component Engineer → settings UI for background features - ---- - -## PRIORITY ORDER - -1. **WS1** (Foundation) — FIRST, others depend on MCP layer -2. **WS6** (Notes/Planner/Alerts) — High user value, fewer external deps -3. **WS5** (Git/Worktrees) — Core coding workflow enhancement -4. **WS3** (GitHub/Calendar/Spotify) — Productivity integrations -5. **WS2** (Slack/Discord) — Communication integrations -6. **WS4** (Fitness) — Personal dashboard -7. **WS7** (System Tray/Voice) — Polish, ties everything together - ---- - -## DEPENDENCIES TO INSTALL - -```bash -# WS1: MCP -npm install @modelcontextprotocol/sdk - -# WS5: Git -npm install simple-git - -# WS6: NLP -npm install chrono-node - -# WS4: Charts (already have recharts? verify) -npm install recharts - -# WS2: Communication -npm install @slack/web-api discord.js - -# WS3: OAuth -# Built-in with Electron (no extra deps for OAuth flow) - -# WS7: Voice (future) -# npm install whisper.cpp or use API -``` diff --git a/doc-history/PROGRESS.md b/doc-history/PROGRESS.md deleted file mode 100644 index 2e7b229..0000000 --- a/doc-history/PROGRESS.md +++ /dev/null @@ -1,253 +0,0 @@ -# Claude-UI Build Progress - -**Last Updated:** 2026-02-14 -**Architecture Plan:** ../Claude-UI-Architecture.md - ---- - -## Phase 1: Scaffold + IPC Contract ✅ COMPLETE -- [x] Folder structure matching architecture plan -- [x] `shared/ipc-contract.ts` — All Zod schemas, invoke + event contracts, type utilities -- [x] `main/ipc/router.ts` — IpcRouter class with Zod validation at boundary -- [x] `preload/index.ts` — Typed IPC bridge (invoke + on) -- [x] Shared types: task, project, terminal, agent, settings -- [x] `package.json` with all dependencies -- [x] `tsconfig.json` with path aliases (@shared, @renderer, @features, @ui) -- [x] `electron.vite.config.ts` with main/preload/renderer configs + aliases -- [x] ESLint 9 + Prettier 3 (strict config with 8 plugins) - -## Phase 2: Core Infrastructure ✅ COMPLETE -- [x] React Query provider (`providers.tsx`) with desktop-optimized defaults -- [x] TanStack Router (`router.tsx`) — all routes defined -- [x] App shell: `App.tsx` (~16 lines), `RootLayout.tsx`, `Sidebar.tsx`, `ProjectTabBar.tsx` -- [x] Theme system: `theme-store.ts` + CSS custom properties (light/dark) -- [x] Layout store: sidebar collapse, active project, tab management -- [x] `useIpcEvent` hook (replaces old 415-line useIpc.ts) -- [x] `useIpcQuery` / `ipc()` wrapper for React Query + IPC -- [x] Shared utils: `cn()`, `formatRelativeTime()`, `formatDuration()`, `truncate()` -- [x] `globals.css` with full light/dark theme variables + scrollbar styling - -## Phase 3: Feature-by-Feature Port ✅ UI COMPLETE - -### Projects ✅ COMPLETE -- [x] `useProjects`, `useAddProject`, `useRemoveProject`, `useSelectDirectory` -- [x] `projectKeys` factory -- [x] `useProjectEvents` — cache invalidation on project updates -- [x] `ProjectListPage` — full UI (list, add via directory picker, remove, open) - -### Tasks ✅ COMPLETE (Task Table Dashboard) -- [x] `useTasks`, `useTask`, `useAllTasks`, `useCreateTask` -- [x] `useUpdateTaskStatus`, `useDeleteTask`, `useExecuteTask`, `useCancelTask` (with optimistic updates) -- [x] `taskKeys` factory -- [x] `useTaskEvents` — status change, progress, log, plan events -- [x] `useTaskUI` store — selections, filters, search -- [x] `TaskTable` — main table component with sortable columns -- [x] `TaskTableRow` — individual row with inline actions -- [x] `TaskTableHeader` — sortable column headers -- [x] `TaskTableFilters` — status, project, date range filters -- [x] `TaskCard` — progress bar, subtask count, relative time -- [x] `TaskStatusBadge` — color-coded status chips -- [x] Kanban board removed, replaced with table-based dashboard (see `docs/plans/2026-02-13-kanban-workflow-refactor.md`) - -### Terminals ✅ UI COMPLETE -- [x] `TerminalGrid` — tabs, create/close terminals, empty state -- [x] `TerminalInstance` — full xterm.js with WebGL, FitAddon, WebLinksAddon -- [x] `useTerminals`, `useCreateTerminal`, `useCloseTerminal` -- [x] `useTerminalEvents` — output, closed, title changed -- [x] `useTerminalUI` store -- [x] xterm.js IPC integration (sendInput, resize, output events) - -### Agents ✅ UI COMPLETE -- [x] `AgentDashboard` — list agents, pause/stop/resume controls -- [x] `useAgents`, `useStopAgent`, `usePauseAgent`, `useResumeAgent` -- [x] `useAgentEvents` — status change, log events - -### Settings ⚠️ BASIC -- [x] `SettingsPage` — theme toggle (light/dark/system) -- [x] `useSettings`, `useUpdateSettings` -- [ ] UI scale, font settings, language selector -- [ ] Profile management - -### Stubs (UI placeholders exist, no build errors) -- [ ] GitHub — "Coming soon" placeholder -- [ ] Roadmap — "Coming soon" placeholder -- [ ] Ideation — "Coming soon" placeholder -- [ ] Changelog — "Coming soon" placeholder -- [ ] Insights — "Coming soon" placeholder - -## Phase 4: Main Process Services ✅ COMPLETE - -### TerminalService ✅ IMPLEMENTED -- [x] Spawn actual PTY via @lydell/node-pty -- [x] Pipe PTY stdout → IPC event:terminal.output -- [x] Pipe renderer input → PTY stdin -- [x] Handle resize (cols/rows → PTY resize) -- [x] Kill PTY on close -- [x] Claude CLI invocation in terminal - -### ProjectService ✅ IMPLEMENTED -- [x] Persist projects to disk (JSON in app data dir) -- [x] Load projects on startup -- [x] Create .claude-ui directory in project folder -- [x] Validate project paths exist - -### TaskService ✅ IMPLEMENTED -- [x] Read/write task spec files from .auto-claude directory -- [x] Task status persistence -- [x] Task execution → spawn agent -- [x] Subtask tracking from agent output - -### AgentService ✅ IMPLEMENTED -- [x] Spawn Claude CLI process via PTY -- [x] Parse agent output for status/progress/logs -- [x] Lifecycle management (pause/resume via process signals) -- [x] Emit agent events to renderer -- [ ] Queue management for parallel agents (future enhancement) - -### SettingsService ✅ IMPLEMENTED -- [x] Read/write settings JSON to app data directory -- [x] Profile management (single default profile) -- [x] App version from package.json - -## Phase 5: Build & Distribution — ✅ PRODUCTION BUILD VERIFIED -- [x] npm install + dependencies resolved -- [x] TypeScript compiles without errors -- [x] Vite build passes (main, preload, renderer) -- [x] Dev mode hot reload working -- [x] Production build verified (typecheck + lint + build pass clean) -- [x] App icons generated (SVG source + PNG at 16/32/48/64/128/256px) -- [x] electron-builder config verified (appId, targets, icon paths) -- [ ] electron-builder distribution packaging (Windows installer, macOS dmg) - -### Bundle Sizes (Production) -| Output | Size | -|--------|------| -| Main (`out/main/index.cjs`) | 36.59 kB | -| Preload (`out/preload/index.mjs`) | 0.42 kB | -| Renderer JS (`out/renderer/assets/index.js`) | 1,748.47 kB | -| Renderer CSS (`out/renderer/assets/index.css`) | 29.40 kB | - -## Phase 6: Code Quality & Documentation ✅ COMPLETE -- [x] Replaced Biome with ESLint 9 + Prettier 3 (maximum strictness) -- [x] ESLint plugins: typescript-eslint, react, react-hooks, jsx-a11y, import-x, unicorn, sonarjs, promise -- [x] Fixed 549 ESLint violations → 0 (clean pass) -- [x] All services refactored: async → sync return values, handlers use Promise.resolve() -- [x] Created CLAUDE.md — root-level AI agent guidelines -- [x] Created ai-docs/ARCHITECTURE.md — system architecture reference -- [x] Created ai-docs/PATTERNS.md — code patterns and conventions -- [x] Created ai-docs/LINTING.md — ESLint rules reference and fix patterns - -## Known Issues -1. ~~No Tailwind v4 `@theme` directive in CSS (using raw CSS vars)~~ — **RESOLVED**: `@theme` block and 7 color themes implemented in globals.css (on feature/task branch) -2. ~~9 unused dependencies in package.json~~ — **RESOLVED**: Removed @anthropic-ai/sdk, i18next, react-i18next, react-markdown, remark-gfm, electron-updater, semver, motion, chokidar (114 packages removed) -3. UI scale backend is complete (theme store + CSS custom properties) — frontend controls being built separately -4. Agent pause/resume uses Unix signals (SIGTSTP/SIGCONT) — no-op on Windows - -## Session Log -- **2026-02-11 18:00** — Audited full codebase. Updated PROGRESS.md to reflect actual state. - Phase 3 UI is essentially complete (task table, xterm, task modal all done). - Starting Phase 4: real main process services. - Priority: TerminalService (PTY) → ProjectService (persistence) → TaskService → AgentService - -- **2026-02-11 22:00** — Phase 4 complete! All main process services now have real implementations: - - TerminalService: Real PTY spawning with @lydell/node-pty - - ProjectService: Disk persistence with JSON in app data directory - - TaskService: Spec file integration with .auto-claude/specs - - AgentService: Claude CLI process spawning, lifecycle management, event emission - - SettingsService: Disk persistence with settings.json - -- **2026-02-11 22:15** — Phase 5 build verification: - - Fixed Zod 4 compatibility (z.record needs key type) - - Fixed node-pty onTitleChange type issue - - Fixed electron-vite CJS output config - - Dev mode launches successfully! - - **Next:** Test the app manually, then build Windows installer. - -- **2026-02-11 23:30** — Phase 6 code quality & documentation: - - Replaced Biome with ESLint 9 flat config + Prettier 3 (maximum strictness) - - 8 ESLint plugins: typescript-eslint strict, react, jsx-a11y strict, import-x, unicorn, sonarjs, promise - - Fixed all 549 ESLint violations (auto-fix: 341, manual: 208) → 0 errors - - Major refactor: all services now return sync values, IPC handlers wrap with Promise.resolve() - - Created AI documentation: CLAUDE.md, ai-docs/ARCHITECTURE.md, ai-docs/PATTERNS.md, ai-docs/LINTING.md - - **Next:** Remove unused dependencies, test app manually, build Windows installer. - -- **2026-02-12** — Build cleanup & distribution prep: - - Removed 9 unused dependencies (114 packages removed): @anthropic-ai/sdk, i18next, react-i18next, react-markdown, remark-gfm, electron-updater, semver, motion, chokidar - - Generated app icons: SVG source + PNG at 16/32/48/64/128/256px sizes - - Updated electron-builder config to use PNG icons (cross-platform compatible) - - Fixed 6 pre-existing TypeScript errors (ImplementationPlanJson types, preload generic scope, undefined narrowing) - - Production build verified: typecheck + lint + build all pass clean - - Bundle sizes documented (renderer JS: 1.7 MB, CSS: 29 kB, main: 37 kB) - -## Phase 7: Full Codebase Audit (P0-P4) ✅ COMPLETE - -### P0 — Security Hardening (6/6) ✅ -- [x] OAuth credentials encrypted via Electron safeStorage (DPAPI on Windows) -- [x] Webhook secrets encrypted via safeStorage -- [x] Hub bootstrap endpoint protected with HUB_BOOTSTRAP_SECRET -- [x] Rate limiting added (100 req/min global, 10 req/min auth routes) -- [x] CORS restricted to HUB_ALLOWED_ORIGINS -- [x] WebSocket auth changed from query param to first-message auth - -### P1 — Wiring Gaps (5/5) ✅ -- [x] Slack/Discord action buttons wired to MCP tools -- [x] DailyStats tasksCompleted wired to real query -- [x] Claude CLI auth check wired into startup -- [x] Listeners added for 4 emitted-but-unlistened events -- [x] Calendar overlay wired into Planner view - -### P2 — Setup & Onboarding (5/5) ✅ -- [x] First-run onboarding wizard (5-step: Welcome, CLI, API Key, Integrations, Complete) -- [x] Webhook setup instructions + test/ping button -- [x] OAuth credential validation before saving -- [x] `.env.example` created with all supported variables -- [x] Hub connection pre-save validation - -### P3 — Missing Features (7/7) ✅ -- [x] Natural language time parser (chrono-node integration) -- [x] Agent queue + parallelism config -- [x] Cost tracking (token usage parsing from Claude CLI output) -- [x] My Work view (cross-project task aggregation) -- [x] Merge workflow UI (diff preview, conflict resolution, merge confirmation) -- [x] Changelog auto-generation from git history -- [x] Weekly review auto-generation from planner data - -### P4 — Large Scope Features (7/7) ✅ -- [x] Persistent Claude session (Anthropic SDK integration, conversation persistence) -- [x] Notification watchers (background Slack/GitHub polling) -- [x] Voice interface (Web Speech API STT + TTS) -- [x] Screen capture (Electron desktopCapturer) -- [x] Smart task creation (LLM decomposition + GitHub issue import) -- [x] Email integration (SMTP support) -- [x] Daily briefing with proactive suggestions - -### Summary -- **30 audit items completed** across 4 priority levels -- **7 new main services** added (claude, email, notifications, screen, tasks, time-parser, voice, briefing) -- **6 new renderer features** added (briefing, merge, my-work, onboarding, screen, voice) -- **8 new IPC handler files** added -- **IPC contract expanded** from ~115 to ~163 invoke channels -- **Overall VISION completion**: ~70% → ~95% - ---- - -- **2026-02-13** — Full codebase audit: - - Ran 5 parallel audit agents (VISION mapping, IPC contract, services, renderer, Hub+setup) - - Identified 30 gaps across P0-P4 priorities - - P0 security fixes: all 6 complete (same session) - - P1 wiring gaps: all 5 complete (same session) - - P2 onboarding: all 5 complete (same session) - - P3 missing features: all 7 complete (5 parallel agents with QA) - - P4 large scope features: all 7 complete (7 parallel agents with QA) - - Created `ai-docs/FEATURES-INDEX.md` — full feature/service inventory - - Created team workflow docs: `ai-docs/prompts/implementing-features/` - - Created `/implement-feature` skill for agent team orchestration - -- **2026-02-14** — Documentation refresh: - - Pulled 29 commits from master - - Updated all progress trackers and audit docs to reflect P4 completion - - Updated FEATURES-INDEX.md counts (21→25 features, 23→30 services, 22→35 handlers) - - Kanban board removed and replaced with Task Table dashboard - - Task Dashboard refactor plan: `docs/plans/2026-02-13-kanban-workflow-refactor.md` diff --git a/doc-history/VISION.md b/doc-history/VISION.md deleted file mode 100644 index 58b8474..0000000 --- a/doc-history/VISION.md +++ /dev/null @@ -1,419 +0,0 @@ -# Claude-UI — Product Vision - -> One app. Every side project. A full-time AI assistant that never sleeps. - ---- - -## What Exists Today - -### Working Features -- **Project Management** — Add/remove projects by directory, tab-based multi-project switching -- **Task Dashboard** — Table-based task management with filtering, sorting, and live status updates (replaced former Kanban board) -- **Task System** — Create, update, delete tasks with subtasks, execution phases, and progress tracking -- **Terminal Grid** — Tabbed xterm.js terminals with real PTY (PowerShell/bash), per-project -- **Agent Dashboard** — Spawn Claude CLI agents per task, view status, stop/pause/resume -- **Settings** — Light/dark/system theme toggle -- **IPC Architecture** — 31 typed channels with Zod validation, fully wired main-to-renderer - -### Stubs (UI placeholder only) -- GitHub integration page -- Roadmap page -- Ideation page -- Insights (barrel export only) -- Changelog (barrel export only) - -### Tech Stack Already in Place -- Electron 39, React 19, TypeScript strict, Zustand 5, Tailwind v4 -- React Query for server state, dnd-kit for drag-and-drop -- node-pty for terminal, Radix UI primitives, Lucide icons -- Anthropic SDK, react-markdown, motion (installed but unused) - ---- - -## The Vision - -### Who Is This For? - -**A solo developer** who juggles a day job and multiple side projects. They want: - -- One place to see everything — not 5 tabs of Notion, Linear, Google Calendar, Discord, and terminal -- AI that actually *does work*, not just answers questions -- To say "hey Claude, move that task to done" while cooking dinner -- A daily cockpit: what happened overnight, what's next, what's blocked - -### Core Identity - -**Claude-UI is a personal command center** — part project manager, part daily planner, part AI workforce. It's the app that's always open on your second monitor. - ---- - -## Feature Vision — Organized by Priority - -### Tier 1: The Dashboard (Home Base) - -**The first thing you see. Everything at a glance.** - -``` -+---------------------------------------------------------------+ -| Good morning, Parker. Wed Feb 12 [voice] [?] | -+---------------------------------------------------------------+ -| | -| TODAY | RECENT PROJECTS | -| +--------------------------+ | +---------+ +---------+ | -| | 09:00 Stand-up (work) | | | Claude | | SaaS | | -| | 10:00 Fix auth bug | | | -UI | | App | | -| | 12:00 Lunch | | | 3 tasks | | 1 agent | | -| | 14:00 PR review | | +---------+ +---------+ | -| | 16:00 Side project time | | +---------+ +---------+ | -| | 18:00 Gym | | | Portfolio| | CLI | | -| +--------------------------+ | | idle | | Tool | | -| | +---------+ +---------+ | -| ACTIVE AGENTS | | -| +---------------------------+ | QUICK CAPTURE | -| | [*] claude-ui: fixing | | +-------------------------+ | -| | auth middleware (67%) | | | "Add dark mode to..." | | -| | [*] saas-app: running | | +-------------------------+ | -| | tests (100%) DONE | | | -| | [ ] portfolio: idle | | DAILY STATS | -| +---------------------------+ | 12 tasks completed | -| | 3 PRs merged | -| | 2 agents ran | -+---------------------------------------------------------------+ -``` - -**Key elements:** -- **Today view** — Minified daily planner pulled from your schedule. Time blocks, not a cluttered list. -- **Recent projects** — Cards with project name, active task count, agent status. Click to dive in. -- **Active agents** — Live status of all running Claude agents across all projects. Progress bars, current phase. -- **Quick capture** — Text input to dump ideas, tasks, notes. Claude triages them to the right project. -- **Daily stats** — What got done today. Subtle, motivating, not gamified. - -### Tier 2: Daily Planner & Time Tracking - -**Your day, structured. Work + side projects in one timeline.** - -- **Time blocks** — Drag-to-create blocks for "work", "side project", "personal". Color coded. -- **Task scheduling** — Drag tasks from any project's backlog onto a time slot. -- **Daily notes** — Quick markdown scratchpad per day. "What I learned", "blockers", etc. -- **Work/life separation** — Tags or contexts: "work", "side-project", "personal". Filter by context. -- **Weekly review** — Auto-generated summary: tasks completed, time spent, agents run, PRs merged. -- **Calendar integrations** (future) — Pull from Google Calendar, Outlook. Read-only overlay. - -### Tier 3: The Persistent Claude Assistant - -**A Claude instance that's always on. Your full-time AI coworker.** - -#### Always-On Agent -- A long-running Claude session that persists across app restarts -- Has memory of your preferences, projects, patterns, and past conversations -- Can be given standing instructions: "every morning, summarize what changed overnight" -- Runs in background, surfaces notifications when it needs you - -#### Computer & Screen Access -- Can see your screen (screenshot capture + vision API) -- Can control your mouse/keyboard (with explicit permission gates) -- Use cases: - - "Claude, look at this error on my screen and fix it" - - "Fill out this form for me" - - "Navigate to the PR and approve it" -- Safety: explicit permission prompt before any action, undo history, kill switch - -#### Voice Interface -- Wake word: "Hey Claude" (local speech-to-text, e.g., Whisper) -- Natural language commands: - - "Update my task list — mark the auth bug as done" - - "Send Conor a message on Discord saying I'll be late" - - "What's on my schedule today?" - - "Start an agent on the portfolio project to fix that CSS bug" - - "Read me the latest PR comments" -- Text-to-speech responses (optional, toggleable) -- Push-to-talk alternative for noisy environments - -#### Cross-App Actions -- Discord: send messages, read channels, react -- GitHub: create PRs, review code, merge, comment on issues -- Slack: post updates, read messages -- Email: draft and send (with confirmation) -- Browser: open URLs, fill forms, navigate - -### Tier 4: Enhanced Project Management - -**What you already have, but smarter.** - -#### Multi-Project Task Dashboard -- Unified view across all projects — filter by project, priority, status -- "My Work" view — all tasks assigned to you across every project, sorted by priority/deadline -- Batch operations — move multiple tasks, bulk assign to agents - -#### Agent Orchestration -- **Parallel agent queue** — Queue 10 tasks, Claude runs them sequentially or in parallel (configurable) -- **Agent profiles** — Different Claude configs per project (model, temperature, system prompt) -- **Agent handoff** — When one agent finishes, it can trigger the next task automatically -- **Cost tracking** — Token usage per agent run, daily/weekly/monthly spend dashboard -- **Agent logs** — Searchable, filterable history of every agent run - -#### Smart Task Creation -- Describe a feature in natural language, Claude breaks it into subtasks -- Paste a GitHub issue URL, Claude creates a task with implementation plan -- Screenshot a bug, Claude creates a task from the image -- Voice-to-task: "Hey Claude, add a task to fix the login page redirect" - -### Tier 5: Intelligence Layer - -**Claude doesn't just execute. It thinks ahead.** - -#### Proactive Suggestions -- "You haven't touched the portfolio project in 2 weeks. Want me to review what's pending?" -- "The SaaS app has 3 tasks that could run in parallel. Want me to start agents?" -- "Your auth token handling looks similar across 3 projects. Want me to extract a shared lib?" - -#### Cross-Project Insights -- Which projects are active vs stale -- Code pattern reuse opportunities -- Dependency update alerts across all projects -- "You fixed this same bug in project A last week — here's the solution" - -#### Daily Briefing -- Morning summary (auto or on-demand): - - Agent activity overnight - - New GitHub notifications - - Today's scheduled tasks - - Blockers or failures that need attention - ---- - -## Design Philosophy - -### 1. Minimal by Default, Powerful on Demand -- Dashboard shows only what matters *right now* -- Details are one click away, never in your face -- No feature should require more than 2 clicks to reach - -### 2. Solo Developer, Not Enterprise -- No team features, no permissions, no "workspace" overhead -- Everything is *yours* — your projects, your schedule, your AI -- Fast, lightweight, no unnecessary abstractions - -### 3. AI-First, Not AI-Bolted-On -- Claude isn't a chatbot sidebar — it's the engine -- Every feature should leverage AI: task creation, scheduling, code review, communication -- The app should feel like having a competent junior developer who never sleeps - -### 4. Always Visible, Never Intrusive -- Designed for a second monitor / always-open workflow -- Notifications are subtle (system tray, badge counts, gentle sounds) -- Voice is opt-in and polite, not Clippy - -### 5. Local-First, Multi-Device -- Hub on your desktop is the brain — no cloud, no monthly bills, no data leaving your network -- Every client caches locally — app works even if hub is off -- Same dashboard, same planner, same tasks on every machine -- Terminals are local (your shell), agents are remote (where the code lives) - ---- - -## Network Architecture: Multi-Device, Local-First - -### The Setup - -``` - YOUR LOCAL NETWORK - ┌──────────────────────────────────────────────┐ - │ │ - │ WINDOWS DESKTOP (Home Server) │ - │ ┌────────────────────────────────────┐ │ - │ │ Docker │ │ - │ │ ┌──────────────────────────────┐ │ │ - │ │ │ claude-ui-hub (container) │ │ │ - │ │ │ ┌────────────────────────┐ │ │ │ - │ │ │ │ REST/WebSocket API │ │ │ │ - │ │ │ │ SQLite (shared data) │ │ │ │ - │ │ │ │ File sync (projects) │ │ │ │ - │ │ │ │ Agent runner (PTY) │ │ │ │ - │ │ │ │ Persistent Claude │ │ │ │ - │ │ │ └────────────────────────┘ │ │ │ - │ │ └──────────────────────────────┘ │ │ - │ │ │ │ - │ │ nginx (reverse proxy + TLS) │ │ - │ └──────────┬─────────────────────────┘ │ - │ │ │ - │ ┌──────────┴──────────┐ │ - │ │ │ │ - │ ▼ ▼ │ - │ Electron App Electron App │ - │ (Windows) (MacBook) │ - │ - Local UI - Local UI │ - │ - Local data - Local data │ - │ - Agents run HERE - View/control │ - │ (has the code) agents remotely │ - │ - Own terminals │ - └──────────────────────────────────────────────┘ -``` - -### How It Works - -#### The Hub (Docker on Windows Desktop) -Your Windows machine runs a lightweight Docker container that acts as the central brain: - -- **REST + WebSocket API** — Every Electron client connects to it -- **SQLite database** — Single source of truth for tasks, planner, settings, agent history -- **WebSocket push** — Real-time sync: change a task on Mac, it updates on Windows instantly -- **Agent runner** — Agents execute here (where the code and compute lives) -- **Persistent Claude** — The always-on assistant lives in this container -- **nginx in front** — Reverse proxy with self-signed TLS, accessible at `https://claude.local` or `https://192.168.x.x` - -#### The Clients (Electron on Each Machine) -Each Electron app is a thin-ish client that: - -- **Stores a local cache** — App works even if hub is unreachable (offline mode) -- **Syncs on connect** — When hub is reachable, pulls latest state via WebSocket -- **Runs its own terminals** — PTY is local to each machine (you want *that machine's* shell) -- **Can trigger remote agents** — "Start an agent on the desktop" from the MacBook -- **Settings sync** — Theme, planner, preferences follow you across devices - -#### What Stays Local vs What Syncs - -| Data | Where It Lives | Why | -|------|---------------|-----| -| Tasks, task state | Hub (SQLite) + local cache | Need it everywhere, hub is source of truth | -| Daily planner / calendar | Hub (SQLite) + local cache | Same schedule on both machines | -| Settings / preferences | Hub (SQLite) + local cache | Theme, layout should follow you | -| Project file paths | Local only | `/Users/parker/code` vs `C:\Users\Parke\code` — paths are machine-specific | -| Terminal sessions | Local only | PTY is bound to the machine's shell | -| Agent execution | Hub (runs on desktop) | Desktop has the code, the GPU, the compute | -| Agent logs / history | Hub (SQLite) | Viewable from any client | -| Quick capture / notes | Hub (SQLite) + local cache | Jot something on Mac, see it on Windows | -| Persistent Claude memory | Hub (filesystem) | One Claude brain, accessible from anywhere | - -#### Conflict Resolution (Simple) -- **Last-write-wins** for most things (settings, task status, notes) -- **Append-only** for logs, capture, and history (no conflicts possible) -- **Machine-specific** data never conflicts (terminals, paths, local cache) -- No need for CRDTs or complex merge — you're one person on two machines - -### Network Discovery & Setup - -#### First Run (Windows Desktop) -```bash -# One command to spin up the hub -docker compose up -d claude-ui-hub -``` - -#### First Run (MacBook Client) -The Electron app shows a setup screen: -1. "Connect to Hub" — enter IP or hostname (`claude.local`, `192.168.1.100`) -2. App pings the hub, confirms connection -3. Pulls initial state (tasks, planner, settings) -4. Done — everything syncs from here - -#### mDNS / Zero-Config (Nice to Have) -- Hub broadcasts itself as `_claude-ui._tcp.local` -- Mac client auto-discovers: "Found Claude-UI Hub on Parker's Desktop. Connect?" -- No manual IP entry needed - -### Security (Local Network) -- **Self-signed TLS** via nginx — encrypted on LAN, no external exposure -- **API key** — Simple shared secret generated on first hub setup, entered once per client -- **No internet exposure** — Hub binds to LAN interface only (`192.168.x.x`, not `0.0.0.0`) -- **Optional Tailnet** — If you want access outside home, add Tailscale. Hub becomes reachable at `claude-ui.tailnet` with zero config - -### Why This Architecture? - -| Approach | Rejected Because | -|----------|-----------------| -| Cloud sync (Firebase, Supabase) | Monthly cost, internet dependency, data leaves your network | -| Peer-to-peer sync | Complex, unreliable, no single source of truth | -| Shared filesystem (NFS/SMB) | Fragile, locking issues, no real-time push | -| Web app only (no Electron) | Loses native features: PTY, system tray, voice, screen capture | -| Single machine only | Can't use from the couch with the MacBook | - -**Docker hub + Electron clients** gives you: zero cloud cost, LAN-speed sync, real-time updates, offline resilience, and native OS features on every device. - ---- - -## Implementation Phases - -### Phase 1: Dashboard & Multi-Project Polish ✅ COMPLETE -- [x] Build the home dashboard (today view, recent projects, active agents) -- [x] Fix existing TypeScript errors -- [x] Complete settings page (fonts, UI scale, accent color, 7 color themes) -- [x] Add quick-capture input on dashboard -- [x] Project cards with live agent status indicators -- [x] My Work view (cross-project task aggregation) -- [x] Daily stats widget - -### Phase 2: Hub + Multi-Device Sync ✅ COMPLETE -- [x] Extract data layer into standalone API server (Fastify + SQLite) -- [x] Migrate JSON file storage to SQLite (tasks, projects, settings, planner) -- [x] WebSocket server for real-time state push (broadcaster pattern) -- [x] Dockerize the hub: `Dockerfile` + `docker-compose.yml` -- [x] Rate limiting (100 req/min global, 10 req/min auth) -- [x] Bootstrap secret for initial API key generation -- [x] WebSocket first-message authentication -- [x] Electron client: hub connection manager (URL + API key) -- [x] Hub status indicator in TopBar -- [x] Offline banner when Hub unreachable -- [x] Device registration + heartbeat (30s interval) -- [x] Secure token storage (safeStorage encryption) -- [x] Hub task API (CRUD + execute + cancel) -- [x] Hub auth API (register, login, logout, refresh) -- [x] Real-time event sync (useHubEvent hooks, hub-query-sync) - -### Phase 3: Daily Planner -- [ ] Calendar day/week view component -- [ ] Time block creation and editing -- [ ] Task-to-timeblock scheduling (drag from backlog) -- [ ] Daily notes scratchpad -- [ ] Work/side-project/personal context tags -- [ ] Data syncs through hub — same planner on both machines - -### Phase 4: Agent Orchestration (Core Value) -- [ ] Task queue with configurable parallelism -- [ ] Remote agent control: trigger agents on desktop from MacBook -- [ ] Agent cost tracking (token usage) -- [ ] Agent run history with searchable logs (stored in hub) -- [ ] Auto-chain: task completion triggers next task -- [ ] Agent profiles per project - -### Phase 5: Persistent Assistant (Differentiator) -- [ ] Long-running Claude session in hub container (survives app restarts) -- [ ] Standing instructions system ("every morning, do X") -- [ ] Notification system (tray icon, badge counts, push to all clients) -- [ ] Quick command palette (Cmd+K / Ctrl+K style) -- [ ] Natural language task/schedule manipulation from any device - -### Phase 6: Voice & Computer Use (Ambitious) -- [ ] Local speech-to-text integration (Whisper.cpp or similar) -- [ ] Wake word detection ("Hey Claude") -- [ ] Text-to-speech for responses -- [ ] Screen capture + Claude vision for "look at this" -- [ ] Controlled computer actions with permission gates -- [ ] Voice works on whichever machine you're using — routes commands to hub - -### Phase 7: Cross-App Integration (Ecosystem) -- [ ] GitHub: PR creation, review, merge from within app -- [ ] Discord: send/read messages via bot or API -- [ ] Slack integration -- [ ] Email drafting and sending -- [ ] Browser automation for form filling / navigation -- [ ] Integrations run on hub — accessible from any client - ---- - -## What Makes This Different - -| Other Tools | Claude-UI | -|---|---| -| Notion/Linear = passive task boards | Tasks that execute themselves via AI agents | -| Google Calendar = view-only schedule | Planner that *does* the work on the schedule | -| Terminal = manual commands | Terminals + AI agents working autonomously | -| ChatGPT = ask questions, copy answers | Claude runs code, creates PRs, ships features | -| Multiple apps for multiple projects | One dashboard, every project, one AI | -| Cloud SaaS = monthly fees, data offsite | Self-hosted hub, zero cost, your data stays home | -| Single-machine tools | Same view from desktop or MacBook, real-time sync | - ---- - -## One-Line Vision - -**Claude-UI is the solo developer's mission control — where every side project lives, AI agents do the work, your day runs itself, and it all syncs across every machine you own.** diff --git a/doc-history/plans/2026-02-13-full-codebase-audit.md b/doc-history/plans/2026-02-13-full-codebase-audit.md deleted file mode 100644 index c58f268..0000000 --- a/doc-history/plans/2026-02-13-full-codebase-audit.md +++ /dev/null @@ -1,460 +0,0 @@ -# Full Codebase Audit — Gaps, Missing Features & Guardrails - -> Tracker Key: `full-codebase-audit` | Status: **IMPLEMENTED** | Created: 2026-02-13 - -**Sources**: VISION.md, MASTER-CHECKLIST.md, IMPLEMENTATION-PROMPTS.md, full codebase analysis -**Coverage**: 5 parallel audits — VISION mapping, IPC contract, services, renderer features, Hub + setup flows - ---- - -## Executive Summary - -**Overall completion: ~95% of VISION.md scope** (updated 2026-02-14 after P0-P4 audit completion) - -| Category | Done | Partial | Missing | Total | -|----------|------|---------|---------|-------| -| Services (main process) | 29 | 0 | 0 | 29 | -| IPC Channels (invoke) | ~163 | 0 | 0 | ~163 | -| IPC Events (defined) | ~40 | 0 | 0 | ~40 | -| Renderer Features | 25 | 0 | 0 | 25 | -| Setup/Onboarding Flows | 9 | 0 | 0 | 9 | -| Security Hardening | 9 | 0 | 0 | 9 | - -What works well: All P0-P4 audit items are complete. Core infrastructure is solid — IPC contract has 100% handler coverage, all 29 main services are real implementations, 25 renderer features are fully wired, security hardening is done, and onboarding is in place. New capabilities include persistent Claude sessions, voice interface, screen capture, email, notification watchers, smart task creation, and daily briefings. - -What remains: P5 polish items (Hub connection indicator, configurable hotkeys UI, auto-updater, database migrations, dead code cleanup). The Kanban board has been removed and replaced with the Task Table dashboard. Further Task Dashboard enhancements (AG-Grid evaluation, Hub-first data, multi-device sync) are planned in `docs/plans/2026-02-13-kanban-workflow-refactor.md`. - ---- - -## 1. CRITICAL — Security & Data Protection - -These must be addressed before any public release or multi-user deployment. - -### 1a. OAuth Credentials Stored in Plaintext — DONE -- **File**: `src/main/auth/providers/provider-config.ts` -- **Status**: FIXED (2026-02-13) -- **Implementation**: OAuth client credentials (clientId, clientSecret) are now encrypted using Electron `safeStorage` (OS-level encryption: Keychain on macOS, DPAPI on Windows, libsecret on Linux). Falls back to base64 when safeStorage is unavailable (CI/testing). Existing plaintext credentials are automatically migrated to encrypted format on first read. - -### 1b. Webhook Secrets Stored in Plaintext — DONE -- **File**: `src/main/services/settings/settings-service.ts` -- **Status**: FIXED (2026-02-13) -- **Implementation**: Webhook secrets (Slack bot token, Slack signing secret, GitHub webhook secret) are now encrypted using Electron `safeStorage`. Same encryption pattern as OAuth credentials with automatic migration of plaintext values. - -### 1c. Hub Bootstrap API Key Endpoint Unprotected — DONE -- **File**: `hub/src/routes/auth.ts` -- **Status**: FIXED (2026-02-13) -- **Implementation**: Bootstrap endpoint now requires `HUB_BOOTSTRAP_SECRET` environment variable. The secret is validated using `crypto.timingSafeEqual()` to prevent timing attacks. Returns 403 if secret is missing from env or doesn't match request header. - -### 1d. No Rate Limiting on Hub Endpoints — DONE -- **File**: `hub/src/app.ts` -- **Status**: FIXED (2026-02-13) -- **Implementation**: Added `@fastify/rate-limit` with two tiers: - - **Global**: 100 requests/minute per IP (all endpoints) - - **Auth routes**: 10 requests/minute per IP (stricter for bootstrap/key generation) - -### 1e. CORS Allows All Origins — DONE -- **File**: `hub/src/app.ts` -- **Status**: FIXED (2026-02-13) -- **Implementation**: CORS origin validation now uses `HUB_ALLOWED_ORIGINS` environment variable (comma-separated list). If set, only those origins are allowed. Falls back to `origin: true` if not configured (development mode). - -### 1f. WebSocket Auth via Query Parameter — DONE -- **File**: `hub/src/app.ts`, `hub/src/ws/broadcaster.ts` -- **Status**: FIXED (2026-02-13) -- **Implementation**: WebSocket connections now require first-message authentication. Clients must send `{ type: "auth", apiKey: "..." }` as their first message within 5 seconds. The server validates the API key and upgrades to `addAuthenticatedClient()`. Connections that fail to authenticate are closed with code 4001. - -### 1g. No API Key Rotation or Expiry -- **File**: `hub/src/routes/auth.ts` -- **Risk**: LOW (single-user) / HIGH (multi-user) -- **Fix**: Add key rotation endpoint, expiry timestamps, revocation - -### 1h. Docker Runs as Root -- **File**: `hub/Dockerfile` -- **Risk**: LOW — Container breakout gives root access -- **Fix**: Add `USER node` directive, create non-root user - -### 1i. No .dockerignore -- **Risk**: LOW — Build context may include sensitive files -- **Fix**: Create `.dockerignore` excluding `node_modules`, `.env`, `certs/`, `data/` - ---- - -## 2. HIGH — Missing Setup & Onboarding Flows - -### 2a. First-Run Onboarding Experience — DONE -- **Status**: FIXED (2026-02-13) -- **Implementation**: Created onboarding feature module with 5-step wizard: - 1. **Welcome** — Introduction to the app - 2. **Claude CLI** — Checks CLI installation and authentication status - 3. **API Key** — Validates Anthropic API key configuration - 4. **Integrations** — Optional OAuth provider setup (skip/defer available) - 5. **Complete** — Marks `onboardingCompleted` and redirects to dashboard -- **Location**: `src/renderer/features/onboarding/` with components, hooks, and store -- **Wiring**: RootLayout checks `onboardingCompleted` and renders wizard on first run - -### 2b. Claude CLI Detection Exists But Is Never Called — DONE -- **Handler exists**: `app.checkClaudeAuth` in `app-handlers.ts` — runs `claude --version` -- **Hook exists**: `useClaudeAuth.ts` — calls the IPC channel -- **Component exists**: `AuthNotification.tsx` — displays the notification -- **Status**: FIXED (2026-02-13) -- **Implementation**: `AuthNotification` is already rendered in `RootLayout.tsx` and calls `useClaudeAuth()` on startup. The hook checks Claude CLI authentication status and displays a banner if not authenticated. - -### 2c. Webhook Setup Has No Guided Instructions — DONE -- **File**: `WebhookSettings.tsx` -- **Status**: FIXED (2026-02-13) -- **Implementation**: Added collapsible setup instruction sections for both Slack and GitHub webhooks. Each section includes step-by-step guidance with links to developer consoles, required scopes/permissions, and test URL buttons that copy webhook URLs to clipboard for easy testing. - -### 2d. OAuth Provider Setup Has No Validation — DONE -- **File**: `OAuthProviderSettings.tsx` -- **Status**: FIXED (2026-02-13) -- **Implementation**: Added OAuth credential validation that tests credentials against provider endpoints before saving. Each provider card now includes links to developer consoles and displays required scopes. Validation feedback shows success/error states with helpful messages. - -### 2e. Hub Connection Setup Has No Pre-Save Validation — DONE -- **File**: `HubSettings.tsx` -- **Status**: FIXED (2026-02-13) -- **Implementation**: Added `hub.validateConnection` IPC channel that pings the Hub's `/api/health` endpoint before saving. The HubSettings form now validates the connection and displays success/error feedback before persisting configuration. - -### 2f. No Environment Variable Documentation — DONE -- **Status**: FIXED (2026-02-13) -- **Implementation**: Created `.env.example` at project root documenting all supported environment variables including: `ANTHROPIC_API_KEY`, OAuth provider credentials (GitHub, Google, Linear, Notion, Todoist, Withings), Hub configuration (`HUB_API_KEY`, `HUB_BOOTSTRAP_SECRET`, `HUB_ALLOWED_ORIGINS`), and database settings. - ---- - -## 3. HIGH — Wiring Gaps (Components Exist But Aren't Connected) - -### 3a. Communications — Action Buttons Are No-Ops — DONE -- **Files**: `SlackPanel.tsx`, `DiscordPanel.tsx`, `SlackActionModal.tsx`, `DiscordActionModal.tsx` -- **Status**: FIXED (2026-02-13) -- **Implementation**: Added `SlackActionModal` and `DiscordActionModal` components that wire panel action buttons to real MCP tool calls via new IPC channels (`mcp.callTool`, `mcp.listConnected`, `mcp.getConnectionState`). Users can now send messages, read channels, search, and set status through the Communications panel. - -### 3b. DailyStats — tasksCompleted Still Hardcoded to 0 — DONE -- **File**: `DailyStats.tsx` -- **Status**: FIXED (2026-02-13) -- **Implementation**: DailyStats now uses `useProjectTasks()` to fetch real task data and counts tasks with `status === 'done'` that were completed today (by checking `completedAt` timestamp). - -### 3c. 7 IPC Events Defined But Not Fully Wired — PARTIAL (4 of 7 DONE) - -| Event | Emitted? | Listened? | Issue | -|-------|----------|-----------|-------| -| `event:alert.changed` | NO | NO | Defined in contract but never emitted | -| `event:app.updateAvailable` | NO | NO | Stub for electron-updater (not implemented) | -| `event:app.updateDownloaded` | NO | NO | Stub for electron-updater (not implemented) | -| `event:assistant.commandCompleted` | YES | YES | **DONE** — HubNotification listens and shows toast | -| `event:git.worktreeChanged` | YES | YES | **DONE** — HubNotification listens and shows toast | -| `event:hub.connectionChanged` | YES | YES | **DONE** — HubNotification listens and shows toast | -| `event:hub.syncCompleted` | YES | YES | **DONE** — HubNotification listens and shows toast | - -**Implementation** (2026-02-13): Added `HubNotification` component in `src/renderer/app/components/` with `useHubEvents` hook that listens to all 4 emitted events and displays toast notifications via the existing toast system. Rendered in `RootLayout.tsx`. - -### 3d. 5 IPC Invoke Channels Have No Renderer Usage -- `tasks.update` — renderer uses `tasks.updateStatus` variant instead -- `terminals.invokeClaudeCli` — reserved, no UI trigger -- `changelog.addEntry` — read-only changelog viewer -- `github.createIssue` — handler exists, no UI button wires to it -- `app.getVersion` — internal use only - -### 3e. Calendar-Planner Integration — DONE -- **Both exist**: CalendarWidget shows Google Calendar events, Planner manages time blocks -- **Status**: FIXED (2026-02-13) -- **Implementation**: Added CalendarOverlay component that displays Google Calendar events directly in the Planner view. Events are shown with distinct visual styling (info color, dashed border) to differentiate them from time blocks. Users can toggle the calendar overlay visibility via a button in the Planner header. - -### 3f. Merge Workflow Has No UI -- **Service exists**: `merge-service.ts` with `previewDiff`, `checkConflicts`, `mergeBranch`, `abort` -- **IPC exists**: All 4 channels registered with handlers -- **Gap**: No renderer component for diff preview, conflict resolution, or merge confirmation - -### 3g. Worktree Management Has Incomplete UI -- **Service exists**: `worktree-service.ts` with full CRUD -- **Component exists**: `WorktreeManager.tsx` in projects feature -- **Gap**: No task-worktree linking (auto-create worktree on task start) - -### 3h. Insights Metrics Are Computed But May Be Shallow -- **Service exists**: `insights-service.ts` aggregates from TaskService, AgentService, ProjectService -- **UI exists**: Full metrics dashboard with charts -- **Gap**: Time-series data depends on tasks having timestamps; if no tasks completed, all metrics are zero - -### 3i. Background Manager Handlers Are Empty Placeholders -- **File**: `background-manager.ts` -- **Evidence**: `handleAlertCheck()` and `handleHealthCheck()` only log, don't execute -- **Note**: Alert checking is already handled by `AlertService.startChecking()` (60s polling) — this may be dead code - ---- - -## 4. MEDIUM — Missing VISION Features (Tier 3-5) - -### 4a. Persistent Claude Session (Tier 3) -- **VISION**: "Always-on agent maintaining state across all app interactions" -- **Current**: Assistant processes one-shot commands via CLI (`claude --print -p`) -- **Missing**: - - Background Claude process with persistent conversation state - - Standing instructions system (per-user preferences) - - Cross-app memory (remembers past interactions) - - Anthropic SDK integration (currently shells out to CLI) -- **Scope**: LARGE — requires Anthropic Messages API, conversation persistence, context management - -### 4b. Screen Capture & Computer Control (Tier 3) -- **VISION**: "Screenshot capture, mouse/keyboard control, vision API" -- **Current**: Nothing exists -- **Missing**: - - `desktopCapturer` Electron API for screenshots - - Vision API (Anthropic) for image analysis - - Mouse/keyboard automation (robotjs or similar) -- **Scope**: LARGE - -### 4c. Voice Interface (Tier 3) -- **VISION**: "Whisper STT, wake word, push-to-talk, TTS" -- **Current**: Nothing exists -- **Missing**: - - Local speech-to-text (Whisper.cpp or Web Speech API) - - Wake word detection ("Hey Claude") - - Text-to-speech responses - - Microphone permission handling -- **Scope**: LARGE - -### 4d. Smart Task Creation (Tier 4) -- **VISION**: "NL description → subtask generation, GitHub issue import, screenshot → task" -- **Current**: Basic task creation via assistant command -- **Missing**: - - LLM-powered task decomposition - - GitHub issue URL → task import - - Screenshot → task with image attachment - - Voice-to-task -- **Scope**: MEDIUM - -### 4e. Agent Queue & Parallelism (Tier 4) -- **Current**: Single agent spawn/stop/pause/resume -- **Missing**: - - Queue system (FIFO, priority) - - Parallelism config (max concurrent agents) - - Auto-chaining (next task on completion) - - Agent handoff protocols -- **Scope**: MEDIUM - -### 4f. Agent Profiles (Tier 4) -- **VISION**: "Per-project Claude configuration: model, temperature, system prompt" -- **Current**: Nothing exists -- **Scope**: SMALL — store in project settings, pass to agent spawn - -### 4g. Cost Tracking (Tier 4) -- **VISION**: "Token usage per agent run, spend dashboard" -- **Current**: Hub schema has `tokens_used` and `cost_usd` fields in `agent_runs` table but nothing populates them -- **Missing**: - - Parse token usage from Claude CLI output - - Accumulate costs per project/agent - - Dashboard widget showing spend -- **Scope**: MEDIUM - -### 4h. My Work View (Tier 4) -- **VISION**: "Unified view across all projects showing tasks assigned to user" -- **Current**: Tasks are per-project only -- **Missing**: Cross-project task query, dedicated "My Work" page/sidebar item -- **Scope**: SMALL - -### 4i. Batch Operations (Tier 4) -- **VISION**: "Move multiple tasks, bulk assign to agents" -- **Current**: Single-task operations only -- **Missing**: Multi-select UI, bulk IPC calls -- **Scope**: SMALL - -### 4j. Proactive Suggestions (Tier 5) -- **VISION**: "Stale project detection, parallel task identification, code reuse" -- **Current**: Nothing exists -- **Scope**: LARGE — requires heuristics or LLM analysis - -### 4k. Daily Briefing (Tier 5) -- **VISION**: "Morning summary, overnight agent activity, GitHub notifications, blockers" -- **Current**: Nothing exists -- **Missing**: Summary generation, scheduled trigger, notification -- **Scope**: MEDIUM - -### 4l. Weekly Review Auto-Generation (Tier 2) -- **VISION**: "Automatic weekly summary from planner data" -- **Current**: Nothing exists -- **Scope**: SMALL — aggregate planner data, format as note - ---- - -## 5. MEDIUM — External Integration Gaps - -### 5a. Withings Integration Is Dead Code -- **OAuth provider configured**: `WITHINGS_OAUTH_CONFIG` in `providers/withings.ts` -- **Fitness service references it**: Deduplication by source tag -- **Gap**: No actual Withings API calls, no sync, no MCP server -- **Decision**: Remove dead config OR implement real integration -- **Scope**: MEDIUM if implementing, SMALL if removing - -### 5b. Email Integration Missing -- **VISION**: "Email drafting and sending" -- **Current**: Nothing exists -- **Missing**: SMTP service, email composer UI, MCP server for email -- **Scope**: MEDIUM - -### 5c. Notification Watchers Missing -- **VISION**: "Watch Slack channels, GitHub repos for relevant events" -- **Current**: Webhooks receive pushed events, but no polling/watching -- **Missing**: `src/main/services/notifications/` — background watchers for Slack/GitHub -- **Scope**: MEDIUM - -### 5d. Natural Language Time Parser Missing -- **VISION reference**: IMPLEMENTATION-PROMPTS mentions `chrono-node` integration -- **Current**: Alert reminders use hardcoded 30-minute offset -- **Missing**: Parse "tomorrow at 3pm", "in 2 hours", "next Monday" from assistant input -- **Scope**: SMALL — install chrono-node, wire into intent classifier - -### 5e. Changelog Auto-Generation -- **Service exists**: `changelog-service.ts` with `list` and `addEntry` -- **Gap**: No auto-generation from git tags/commits — entries are manual only -- **Scope**: SMALL — parse `git log` between tags, format as entries - -### 5f. Electron Auto-Updater -- **IPC events defined**: `event:app.updateAvailable`, `event:app.updateDownloaded` -- **Gap**: `electron-updater` is listed as dependency but never initialized -- **Scope**: SMALL — wire `autoUpdater` in main process, emit events - ---- - -## 6. LOW — Polish & UX Gaps - -### 6a. No Global Hub Connection Indicator -- **Current**: Hub status only visible on Settings page -- **Fix**: Add status dot in sidebar footer or top bar - -### 6b. No Configurable Hotkeys UI -- **Service exists**: `hotkey-manager.ts` with global hotkey registration -- **Gap**: Hotkeys are hardcoded, no Settings UI to customize them - -### 6c. No App Launch at System Startup -- **VISION**: Mentioned in Workstream 7 -- **Fix**: Use `app.setLoginItemSettings()` Electron API, add toggle in Settings - -### 6d. No Database Migration Versioning -- **Current**: `hub/src/db/schema.sql` is run once on creation -- **Gap**: No migration system for schema changes -- **Fix**: Use `better-sqlite3` migrations or a simple version table - -### 6e. No Hub Database Backup Strategy -- **Current**: SQLite file in Docker volume, no backups -- **Fix**: Scheduled `VACUUM INTO` or file copy - -### 6f. MCP Client SSE Transport Is Placeholder -- **File**: `mcp/mcp-client.ts:329` -- **Evidence**: Comment indicates SSE transport is not fully implemented -- **Impact**: Only stdio transport works; SSE-based MCP servers won't connect - -### 6g. TaskService.executeTask() Is a Stub -- **File**: `src/main/services/project/task-service.ts:313-327` -- **Evidence**: Returns fake agentId, only marks task as in_progress -- **Note**: Real execution is in `AgentService.startAgent()` — this stub is intentional but could be removed or properly delegated - ---- - -## 7. Guardrails for Future Development - -### 7a. IPC Contract Discipline -- **Rule**: Every new IPC channel MUST be added to `ipc-contract.ts` with Zod schemas FIRST -- **Rule**: Every channel MUST have a handler AND a renderer hook before merging -- **Rule**: Every event channel MUST have both an emitter and a listener -- **Check**: Run audit script comparing contract channels vs handler registrations - -### 7b. No New Mock Data -- **Rule**: Zero hardcoded mock data in any component — use real services or show empty state -- **Rule**: If a service isn't ready, show "Not configured" with a link to Settings -- **Check**: `grep -r "MOCK\|mock\|hardcoded\|fake\|placeholder" src/renderer/` - -### 7c. Security Baseline -- **Rule**: All secrets (OAuth creds, webhook secrets, API keys) MUST use `safeStorage` encryption -- **Rule**: No `origin: true` CORS — specify explicit allowed origins -- **Rule**: All Hub endpoints MUST have rate limiting -- **Rule**: WebSocket auth MUST NOT use query parameters -- **Check**: Security review before any public-facing deployment - -### 7d. Feature Completeness Standard -- **Rule**: A feature is not "done" until it has: real data source, loading state, empty state, error state, and "not configured" state (if applicable) -- **Rule**: Every button MUST have an onClick handler — no empty/noop buttons -- **Rule**: Every form MUST have onSubmit + validation + error display -- **Check**: `grep -r "TODO\|FIXME\|STUB\|HACK" src/` - -### 7e. Type Safety -- **Rule**: Zero `any` types — use `unknown` + narrowing -- **Rule**: Zero `as` type assertions without eslint-disable justification -- **Rule**: `tsc --noEmit` MUST pass clean before every commit -- **Rule**: `npm run lint` MUST pass clean before every commit - -### 7f. Service Architecture -- **Rule**: Services return sync values; handlers wrap with `Promise.resolve()` -- **Rule**: Services MUST handle "not configured" gracefully (return null/error, don't throw) -- **Rule**: External API services MUST validate OAuth tokens before making calls -- **Rule**: All file I/O MUST be in services, never in components or handlers - -### 7g. Testing -- **Current state**: 137 tests passing (75 unit + 62 integration), added during Task Dashboard Refactor (2026-02-16) -- **Test infrastructure**: vitest (unit + integration configs) + playwright (e2e) + AI QA agent scenarios -- **Coverage**: Services (project-service, task-service, hub-token-store), IPC handlers (project-handlers, task-handlers) -- **Rule**: New services and handlers SHOULD have corresponding tests -- **Rule**: Critical services (assistant, agent, task, planner) SHOULD have unit tests - ---- - -## 8. Prioritized Action Items - -### P0 — Security (Do Before Any Deployment) -1. ~~Encrypt OAuth credentials via safeStorage~~ **DONE** (2026-02-13) -2. ~~Encrypt webhook secrets via safeStorage~~ **DONE** (2026-02-13) -3. ~~Protect Hub bootstrap endpoint~~ **DONE** (2026-02-13) -4. ~~Add rate limiting to Hub~~ **DONE** (2026-02-13) -5. ~~Fix CORS to explicit origins~~ **DONE** (2026-02-13) -6. ~~Fix WebSocket auth~~ **DONE** (2026-02-13) - -### P1 — Wiring Gaps (Components Exist, Just Need Connection) -7. ~~Wire Slack/Discord action buttons to MCP tools~~ **DONE** (2026-02-13) -8. ~~Wire DailyStats tasksCompleted to real query~~ **DONE** (2026-02-13) -9. ~~Wire Claude CLI auth check into app startup / RootLayout~~ **DONE** (2026-02-13) — already wired -10. ~~Add listeners for 4 emitted-but-unlistened events (hub.connectionChanged, hub.syncCompleted, git.worktreeChanged, assistant.commandCompleted)~~ **DONE** (2026-02-13) -11. ~~Wire Calendar overlay into Planner view~~ **DONE** (2026-02-13) - -### P2 — Setup & Onboarding -12. ~~Build first-run onboarding wizard~~ **DONE** (2026-02-13) -13. ~~Add webhook setup instructions + test/ping button~~ **DONE** (2026-02-13) -14. ~~Add OAuth credential validation before saving~~ **DONE** (2026-02-13) -15. ~~Create `.env.example` with all supported variables~~ **DONE** (2026-02-13) -16. ~~Hub connection pre-save validation (ping before save)~~ **DONE** (2026-02-13) - -### P3 — Missing Features (High Value) -17. ~~Natural language time parser (chrono-node)~~ **DONE** (2026-02-13) -18. ~~Agent queue + parallelism config~~ **DONE** (2026-02-13) -19. ~~Cost tracking (parse Claude CLI token output)~~ **DONE** (2026-02-13) -20. ~~My Work view (cross-project tasks)~~ **DONE** (2026-02-13) -21. ~~Merge workflow UI (diff preview + conflict resolution)~~ **DONE** (2026-02-13) -22. ~~Changelog auto-generation from git~~ **DONE** (2026-02-13) -23. ~~Weekly review auto-generation~~ **DONE** (2026-02-13) - -### P4 — Missing Features (Large Scope) -24. ~~Persistent Claude session (Anthropic Messages API)~~ **DONE** (2026-02-13) -25. ~~Notification watchers (background Slack/GitHub polling)~~ **DONE** (2026-02-13) -26. ~~Voice interface (Web Speech API STT + TTS)~~ **DONE** (2026-02-13) -27. ~~Screen capture + computer control~~ **DONE** (2026-02-13) -28. ~~Smart task creation (LLM decomposition + GitHub import)~~ **DONE** (2026-02-13) -29. ~~Email integration (SMTP support)~~ **DONE** (2026-02-13) -30. ~~Proactive suggestions / daily briefing~~ **DONE** (2026-02-13) - -### P5 — Polish -31. Global Hub connection indicator -32. Configurable hotkeys UI -33. App launch at system startup -34. Database migration versioning -35. Electron auto-updater wiring -36. Remove Withings dead code (or implement) -37. Clean up background-manager.ts dead code - ---- - -## Appendix: Files Referenced - -**Security fixes**: `hub/src/routes/auth.ts`, `hub/src/app.ts`, `hub/Dockerfile`, `src/main/services/settings/settings-service.ts`, `src/main/auth/providers/provider-config.ts` - -**Wiring gaps**: `SlackPanel.tsx`, `DiscordPanel.tsx`, `DailyStats.tsx`, `RootLayout.tsx`, `CalendarWidget.tsx`, `PlannerPage.tsx` - -**Setup flows**: `SettingsPage.tsx`, `WebhookSettings.tsx`, `HubSettings.tsx`, `app-handlers.ts`, `useClaudeAuth.ts`, `AuthNotification.tsx` - -**P4 services (all implemented)**: `claude/claude-client.ts`, `notifications/notification-watcher.ts`, `voice/voice-service.ts`, `screen/screen-capture-service.ts`, `email/email-service.ts`, `tasks/task-decomposer.ts`, `briefing/briefing-service.ts`, `time-parser/time-parser-service.ts` - -**Dead code candidates**: `background-manager.ts`, `scheduler.ts`, Withings OAuth config, `TaskService.executeTask()` stub diff --git a/doc-history/plans/2026-02-13-kanban-workflow-refactor.md b/doc-history/plans/2026-02-13-kanban-workflow-refactor.md deleted file mode 100644 index d5a65d3..0000000 --- a/doc-history/plans/2026-02-13-kanban-workflow-refactor.md +++ /dev/null @@ -1,736 +0,0 @@ -# Task Dashboard & Multi-Device Workflow - -> Tracker Key: `kanban-workflow` | Status: **SUPERSEDED** | Created: 2026-02-13 - ---- - -## Problem Statement - -The current Kanban automated workflow has three competing systems: - -1. **Python Orchestration** (`ai-docs/`) — Standalone, well-built, but creates coupling -2. **Electron PTY Wrapper** — Broken `claude --task` invocation, no real execution -3. **Claude Workflow Skills** (`.claude/`) — Native Claude Code integration, team-based - -Additionally: -- Kanban board is visually nice but information-sparse -- No mobile access for monitoring/managing tasks -- No multi-computer coordination -- Hub server exists but isn't fully utilized - ---- - -## Goal - -Replace the Kanban board with a **Jira-style task dashboard** that: - -1. Displays all tasks in a filterable/sortable table -2. Syncs across devices via Hub server (local network or hosted) -3. Allows any authenticated device to view, create, and assign tasks -4. Executes tasks on the workspace host device -5. Uses Claude Workflow skills for orchestration (not internal PTY) -6. Supports complex project structures (monorepo, multi-repo) - -**Pipeline**: `Any Device (authenticated) → Hub Sync → Workspace Host (execute) → Progress Files → Hub Sync → All Devices Updated` - ---- - -## Related Documents - -- **Workspace & Project Management**: `docs/plans/2026-02-14-workspace-project-management.md` -- **Hub Protocol Contract**: `docs/contracts/hub-device-protocol.md` -- **Protocol Types**: `src/shared/types/hub-protocol.ts` - ---- - -## Architecture - -### Current (Broken) - -``` -┌─────────────┐ ┌──────────────┐ ┌─────────────┐ -│ Kanban UI │────▶│ agent-service│────▶│ PTY Process │ -│ │ │ (TypeScript) │ │ claude --task│ ← BROKEN -└─────────────┘ └──────────────┘ └─────────────┘ - │ - ▼ - ┌──────────────┐ - │ Python Specs │ ← Not actually called - └──────────────┘ -``` - -### Proposed: Multi-Device Architecture - -``` - ┌─────────────────────────────────┐ - │ HUB SERVER │ - │ (Local Network or Hosted) │ - │ │ - │ ┌─────────┐ ┌───────────────┐ │ - │ │ SQLite │ │ WebSocket │ │ - │ │ DB │ │ Broadcast │ │ - │ └─────────┘ └───────────────┘ │ - │ │ - │ Users, Devices, Workspaces, │ - │ Projects, Tasks, Sessions │ - └─────────────────────────────────┘ - ▲ - ┌────────────────────────────┼────────────────────────────┐ - │ │ │ - ┌──────────────┴──────────────┐ ┌─────────┴─────────┐ ┌───────────────┴───────────────┐ - │ DESKTOP DEVICES │ │ MOBILE DEVICES │ │ WEB CLIENTS │ - │ (can host workspaces) │ │ (view & manage) │ │ (friend's computer, etc.) │ - └──────────────┬──────────────┘ └───────────────────┘ └───────────────────────────────┘ - │ - ┌──────────────┼──────────────┐ - │ │ │ - ▼ ▼ ▼ -┌─────────┐ ┌─────────┐ ┌─────────┐ -│WORKSPACE│ │WORKSPACE│ │WORKSPACE│ -│"Work PC"│ │"Home PC"│ │"Laptop" │ -│ │ │ │ │ │ -│Projects:│ │Projects:│ │Projects:│ -│• company│ │• claude │ │• blog │ -│• infra │ │• dotfile│ │• learn │ -└─────────┘ └─────────┘ └─────────┘ -``` - -### Key Concepts - -**User** (authenticated account): -- Can sign in from ANY device (phone, friend's laptop, tablet) -- Owns workspaces, sees all their data across devices -- Single account, multiple devices - -**Device** (physical machine): -- Desktop: Can host workspaces, execute tasks -- Mobile/Web: View and manage only, cannot execute -- Registered to a user, has capabilities - -**Workspace** (logical execution environment): -- User-named: "Work PC", "Home Desktop", "Personal Laptop" -- Hosted on a specific desktop device -- Contains projects -- Configurable in Settings → Workspaces tab - -**Project** (git repository within workspace): -- Three types: `single` | `monorepo` | `multi-repo` -- Multi-repo: Parent folder containing child git repos -- Sub-projects: Child repos in multi-repo (e.g., /frontend, /backend) -- Tasks can target entire project or specific sub-project - -**Hub Server**: -- Central database: Users, Devices, Workspaces, Projects, Tasks -- Authentication (JWT) -- WebSocket for real-time sync -- Self-hosted (local network) or cloud-hosted - -> **Full Details**: See `docs/plans/2026-02-14-workspace-project-management.md` - -### Execution Flow - -``` -1. USER (on mobile, or friend's laptop, etc.) creates task: - "Add dark mode to settings page" - Workspace: "Home Desktop" - Project: claude-ui - Target: (entire project) ← or specific sub-project for multi-repo - -2. HUB validates user auth, broadcasts task to all user's connected devices - -3. HOME DESKTOP (workspace host) sees new task in dashboard - - Status: QUEUED - - Workspace: this machine hosts it - -4. USER (from any device) or AUTO starts task - - Workspace host receives command - - Launches: claude -p "Use /implement-feature for: Add dark mode..." - - Claude Workflow takes over - -5. PROGRESS FILES written locally on workspace host - - Progress watcher syncs to Hub - - Hub broadcasts to ALL user's devices - -6. USER (on mobile, anywhere) sees real-time updates: - - Task: IN_PROGRESS - - Current agent: component-engineer - - Files changed: 3 - -7. WORKFLOW COMPLETES - - PR created - - Task status: REVIEW - - All devices see final state - - Notification sent to mobile -``` - -### Multi-Repo Example - -``` -USER creates task in "company-monolith" project (multi-repo): - Title: "Add auth middleware" - Target: backend (sub-project) ← only this sub-repo - -Claude executes in: /work/company-monolith/backend/ - - Only touches backend code - - PR scoped to backend repo -``` - ---- - ---- - -## Task Dashboard (Replaces Kanban) - -### Why Table Over Kanban - -| Aspect | Kanban Board | Task Table | -|--------|--------------|------------| -| Information density | Low (card-based) | High (rows with columns) | -| Filtering | Limited | Full (status, project, computer, date) | -| Sorting | None | Any column | -| Bulk actions | Awkward | Natural (checkbox select) | -| Completed tasks | Clutters board | Filter out, still queryable | -| Mobile-friendly | Poor (horizontal scroll) | Good (responsive columns) | -| Scale | 20-30 tasks max | Hundreds with pagination | - -### Table Columns - -| Column | Description | Sortable | Filterable | -|--------|-------------|----------|------------| -| Status | Backlog, Queued, Running, Review, Done, Error | ✓ | ✓ | -| Title | Task name (clickable for details) | ✓ | Search | -| Workspace | Which workspace | ✓ | ✓ | -| Project | Which project | ✓ | ✓ | -| Target | Sub-project if multi-repo (e.g., "frontend") | - | ✓ | -| Agent | Current active agent (if running) | - | - | -| Progress | Progress bar or phase indicator | - | - | -| Created | Timestamp | ✓ | Date range | -| Updated | Last activity | ✓ | Date range | -| Actions | Start, Stop, Delete buttons | - | - | - -### Views / Filters - -- **My Work**: Tasks on current workspace (if viewing from host) -- **All Tasks**: Full table across all workspaces -- **By Workspace**: Filter by specific workspace -- **Active**: Currently running tasks -- **Review**: Awaiting human review -- **History**: Completed tasks (last 30 days) - -### Quick Actions - -- **New Task**: Modal with title, description, project, target computer -- **Bulk Start**: Start multiple queued tasks -- **Bulk Archive**: Archive completed tasks - ---- - -## Communication Protocol - -### Progress File Format - -Agents write structured progress to `docs/progress/-progress.md`: - -```markdown ---- -feature: my-feature -status: IN_PROGRESS -started: 2026-02-13T10:00:00Z -updated: 2026-02-13T10:15:00Z -team_lead: session-abc123 ---- - -# Feature: My Feature - -## Tasks - -| ID | Task | Status | Agent | Worktree | -|----|------|--------|-------|----------| -| 1 | Schema types | COMPLETE | schema-eng | audit/schema | -| 2 | Service impl | IN_PROGRESS | service-eng | audit/service | -| 3 | IPC handlers | BLOCKED | - | - | - -## Active Agents - -- `service-eng` (session-xyz789): Working on task #2 - - Last activity: 2026-02-13T10:14:32Z - - Current file: src/main/services/foo.ts - -## Logs - -- 10:00:00 — Team initialized -- 10:02:15 — Task #1 assigned to schema-eng -- 10:08:42 — Task #1 COMPLETE, QA PASS -- 10:09:00 — Task #2 assigned to service-eng -``` - -### UI File Watcher - -The Electron app watches progress files using `chokidar`: - -```typescript -// src/main/services/workflow/progress-watcher.ts -import chokidar from 'chokidar'; -import { parse as parseYaml } from 'yaml'; - -interface ProgressUpdate { - feature: string; - status: 'PENDING' | 'IN_PROGRESS' | 'COMPLETE' | 'ERROR'; - tasks: TaskProgress[]; - agents: AgentProgress[]; - logs: string[]; -} - -export function createProgressWatcher(router: IpcRouter) { - const watcher = chokidar.watch('docs/progress/*.md', { - persistent: true, - ignoreInitial: false, - }); - - watcher.on('change', (path) => { - const content = readFileSync(path, 'utf-8'); - const progress = parseProgressFile(content); - router.emit('event:workflow.progress', progress); - }); - - return { dispose: () => watcher.close() }; -} -``` - -### Task Launcher - -Minimal launcher that starts a Claude session with the workflow skill: - -```typescript -// src/main/services/workflow/task-launcher.ts -import { spawn } from 'child_process'; - -export function launchWorkflow(taskDescription: string, projectPath: string) { - const prompt = ` -Use /implement-feature to execute this task: - -${taskDescription} - -Project path: ${projectPath} -Write progress to: docs/progress/ -`; - - // Spawn detached Claude session - const child = spawn('claude', ['-p', prompt], { - cwd: projectPath, - detached: true, - stdio: 'ignore', - }); - - child.unref(); // Don't wait for it - return { sessionId: `workflow-${Date.now()}` }; -} -``` - ---- - -## What to Keep - -### From Current App -- `TaskDetailModal.tsx` — Task details view (adapt for table row click) -- `task-service.ts` — Task CRUD (but sync to Hub instead of local-only) -- `useTasks.ts`, `useTaskMutations.ts` — React Query hooks (point to Hub API) -- `hub/` — Hub server (SQLite, WebSocket, REST API) — **Core infrastructure** -- `hub-connection.ts`, `hub-sync.ts` — Client-side Hub integration - -### From Claude Workflow Skills -- `/implement-feature` — Team orchestration -- Agent definitions (`.claude/agents/`) -- Progress file format (`PROGRESS-FILE-TEMPLATE.md`) -- QA checklist templates -- Worktree management - ---- - -## What to Remove/Replace - -### Remove -- `KanbanBoard.tsx`, `KanbanColumn.tsx`, `KanbanCard.tsx` — Replace with table -- `agent-service.ts` — PTY-based agent spawning (broken) -- `agent-queue.ts` — Internal queue (let Claude handle parallelism) -- `token-parser.ts` — PTY output parsing -- Python orchestration (`ai-docs/agents/`, `ai-docs/spec/`, etc.) — Archive to `doc-history/` - -### Replace -- `tasks.execute` IPC handler → Call `launchWorkflow()` instead -- Local task storage → Hub database (SQLite) -- Agent status tracking → Progress files synced to Hub -- Kanban view → Task table with filters - ---- - -## New Components - -### 1. Task Table UI -``` -src/renderer/features/tasks/ -├── components/ -│ ├── TaskTable.tsx # Main table component -│ ├── TaskTableRow.tsx # Individual row with actions -│ ├── TaskTableFilters.tsx # Status, project, computer filters -│ ├── TaskTableHeader.tsx # Sortable column headers -│ ├── TaskQuickCreate.tsx # Inline task creation -│ └── TaskDetailPanel.tsx # Side panel for task details -├── hooks/ -│ └── useTaskFilters.ts # Filter/sort state management -└── store.ts # UI state (selected rows, view mode) -``` - -### 2. Device & Workspace Services -``` -src/main/services/device/ -├── device-service.ts # Register this device with Hub -├── device-identity.ts # Unique machine ID generation -└── heartbeat.ts # Periodic "I'm online" ping to Hub - -src/main/services/workspace/ -├── workspace-service.ts # Workspace CRUD, host assignment -└── workspace-sync.ts # Sync workspace state to Hub -``` - -### 2b. Project Initialization -``` -src/main/services/project/ -├── project-detector.ts # Detect repo type, child repos -├── project-initializer.ts # Create project with sub-projects -└── sub-project-service.ts # Manage sub-projects -``` - -### 2c. Workspace Settings UI -``` -src/renderer/features/settings/ -├── components/ -│ ├── WorkspacesTab.tsx # Settings → Workspaces -│ ├── WorkspaceCard.tsx # Individual workspace in list -│ ├── WorkspaceEditor.tsx # Edit workspace modal -│ └── DeviceSelector.tsx # Host device dropdown -``` - -### 2d. Project Initialization UI -``` -src/renderer/features/projects/ -├── components/ -│ ├── ProjectInitWizard.tsx # Multi-step init flow -│ ├── RepoTypeSelector.tsx # Single/Monorepo/Multi-repo -│ ├── SubRepoDetector.tsx # Shows detected child repos -│ └── SubRepoSelector.tsx # Checkboxes for sub-projects -``` - -### 3. Progress Sync Service -``` -src/main/services/workflow/ -├── progress-watcher.ts # chokidar watches docs/progress/ -├── progress-parser.ts # YAML frontmatter + markdown parser -├── progress-syncer.ts # Push progress updates to Hub -└── task-launcher.ts # Spawn Claude with workflow skill -``` - -### 4. Hub Enhancements -``` -hub/src/ -├── routes/ -│ ├── computers.ts # Computer registration endpoints -│ └── progress.ts # Progress update endpoints -├── db/ -│ └── schema.sql # Add: computers table, task.computer_id -└── ws/ - └── handlers.ts # Add: computer online/offline broadcasts -``` - -### 5. Mobile/Web Client (Future) -``` -mobile/ # React Native or PWA -├── src/ -│ ├── screens/ -│ │ ├── TaskList.tsx # Table view -│ │ ├── TaskDetail.tsx # Task details -│ │ └── CreateTask.tsx # New task form -│ └── api/ -│ └── hub-client.ts # REST + WebSocket to Hub -``` - -### 6. New IPC Channels -```typescript -// src/shared/ipc-contract.ts additions - -// Authentication -'auth.login': { input: { email: string; password: string }; output: AuthResult } -'auth.logout': { input: void; output: void } -'auth.me': { input: void; output: User } - -// Device management -'devices.register': { input: { name: string }; output: Device } -'devices.list': { input: void; output: Device[] } - -// Workspace management -'workspaces.list': { input: void; output: Workspace[] } -'workspaces.create': { input: CreateWorkspaceInput; output: Workspace } -'workspaces.update': { input: UpdateWorkspaceInput; output: Workspace } -'workspaces.delete': { input: { id: string }; output: void } - -// Project management -'projects.detect': { input: { path: string }; output: ProjectDetectionResult } -'projects.create': { input: CreateProjectInput; output: Project } -'projects.addSubProject': { input: AddSubProjectInput; output: SubProject } - -// Workflow execution -'workflow.launch': { - input: { taskId: string; workspaceId: string }; - output: { sessionId: string } -} -'workflow.cancel': { input: { sessionId: string }; output: { success: boolean } } - -// Events -'event:workflow.progress': { taskId: string; progress: ProgressUpdate } -'event:workspace.online': { workspaceId: string } -'event:workspace.offline': { workspaceId: string } -'event:device.online': { deviceId: string } -'event:device.offline': { deviceId: string } -``` - ---- - -## Hub Database Schema Changes - -> **Full Schema**: See `docs/plans/2026-02-14-workspace-project-management.md` for complete schema - -```sql --- Summary of new tables: --- users — Authentication accounts --- devices — Physical devices (desktop, mobile, web) --- workspaces — Logical execution environments (host_device_id) --- projects — Git repos within workspaces (repo_structure) --- sub_projects — Child repos in multi-repo projects --- tasks — Updated with workspace_id, project_id, sub_project_id --- sessions — JWT session management - --- Key relationships: --- User 1:N Devices --- User 1:N Workspaces --- Workspace 1:1 Host Device --- Workspace 1:N Projects --- Project 1:N Sub-Projects (for multi-repo) --- Project 1:N Tasks --- Task N:1 Sub-Project (optional targeting) -``` - ---- - -## Migration Path - -### Phase 0: User Authentication -1. Add `users`, `sessions` tables to Hub -2. Implement login/register endpoints -3. Add login UI to desktop app -4. JWT-based auth for all Hub requests -5. **Result**: Authenticated access from any device - -### Phase 1: Devices + Workspaces -1. Add `devices`, `workspaces` tables to Hub -2. Create `device-service.ts` for machine identity -3. Desktop registers as device on login -4. Auto-create workspace for new desktop users -5. Add Settings → Workspaces tab -6. **Result**: Workspaces configurable, devices tracked - -### Phase 2: Project Enhancements -1. Add `repo_structure` to projects -2. Add `sub_projects` table -3. Create `project-detector.ts` for auto-detection -4. Add Project Initialization Wizard UI -5. **Result**: Multi-repo projects supported - -### Phase 3: Task Table UI -1. Create `TaskTable.tsx` and related components -2. Replace Kanban route with Table route -3. Add filters (status, workspace, project) -4. Add sub-project selector in task creation -5. **Result**: New table UI with multi-repo support - -### Phase 4: Hub-First Data -1. Migrate all storage from local to Hub database -2. Update services to use Hub API -3. WebSocket broadcasts all changes -4. **Result**: Full sync across devices - -### Phase 5: Progress Watcher + Sync -1. Create `progress-watcher.ts` (chokidar) -2. Create `progress-syncer.ts` (push to Hub) -3. Hub broadcasts progress updates -4. Table shows real-time agent/phase status -5. **Result**: Live execution visibility everywhere - -### Phase 6: Workflow Launcher -1. Create `task-launcher.ts` with `launchWorkflow()` -2. Update `tasks.execute` to use new launcher -3. Only workspace hosts can execute -4. Remove broken PTY agent spawning -5. **Result**: Working execution via Claude Workflow - -### Phase 7: Mobile/Web Client -1. Create PWA (simpler than native) -2. Login UI, connect to Hub -3. View workspaces, projects, tasks -4. Create/edit tasks, assign to workspaces -5. Real-time progress updates -6. **Result**: Full multi-device experience - -### Phase 8: Cleanup -1. Archive Python orchestration to `doc-history/` -2. Remove Kanban components -3. Remove `agent-service.ts`, `agent-queue.ts` -4. Update documentation -5. **Result**: Clean codebase - ---- - -## Open Questions - -1. **Cancel mechanism**: How should the UI cancel a running workflow? - - Option A: Write `CANCELLED` to progress file, agents check periodically - - Option B: Store PID and send SIGTERM from workspace host - - Option C: Hub broadcasts cancel, workspace host handles it - - **Recommendation**: Option C — Hub-mediated for multi-device consistency - -2. **Device identification**: How to uniquely identify machines? - - Option A: UUID generated on first run, stored in userData - - Option B: Hardware fingerprint (MAC address hash + hostname) - - **Recommendation**: Option A with user-friendly name - -3. **Offline execution**: What if workspace host loses Hub connection? - - Task continues locally (progress files still written) - - Re-sync when connection restored - - Other devices see "offline" indicator - -4. **Authentication provider**: How do users sign in? - - Option A: Email/password only (simpler) - - Option B: OAuth (GitHub, Google) + email fallback - - **Recommendation**: Email/password for MVP, OAuth later - -5. **Hub hosting options**: - - Local network (mDNS/Bonjour discovery?) - - Self-hosted VPS (requires domain/SSL) - - Cloud-hosted SaaS (future monetization?) - - **MVP**: Local network with manual IP/port config - -6. **Mobile app approach**: - - PWA (works everywhere, easier to build) - - React Native (better native feel, more work) - - **Recommendation**: PWA first, native later if needed - -7. **Multi-repo detection**: How to detect child repos? - - Scan for `.git` folders in immediate children - - Ask user to confirm which are "real" sub-projects - - Allow manual add later - -8. **Workspace migration**: Can user move workspace to new host? - - Projects are local paths, not trivially portable - - Option: Re-point paths on new host - - Option: Future "clone to new host" feature - ---- - -## Success Criteria - -### Phase 0-1 (Authentication + Workspaces) -- [ ] User can register/login from any device -- [ ] Device registers with Hub on login -- [ ] Workspaces visible in Settings tab -- [ ] User can rename workspaces -- [ ] User can change workspace host device - -### Phase 2-3 (Projects + Task Table) -- [ ] Project initialization detects repo type -- [ ] Multi-repo projects show sub-projects -- [ ] Tasks displayed in table view (not Kanban) -- [ ] Sub-project selector in task creation -- [ ] Filter/sort by status, workspace, project - -### Phase 4-6 (Sync + Execution) -- [ ] All data synced through Hub -- [ ] Real-time updates via WebSocket -- [ ] Progress files watched and synced -- [ ] Workflow launches via Claude Workflow skills -- [ ] PR created on workflow completion - -### Phase 7 (Mobile) -- [ ] PWA connects to Hub with login -- [ ] View workspaces, projects, tasks -- [ ] Create/edit tasks from mobile -- [ ] Real-time progress updates -- [ ] Works from any device (friend's phone, etc.) - -### Cleanup -- [ ] No PTY parsing or broken CLI flags -- [ ] Python orchestration archived -- [ ] Kanban components removed - ---- - -## Dependencies - -- **Claude Workflow Skills Package**: Must be finalized with `/implement-feature` -- **Progress File Format**: Standardize YAML frontmatter schema -- **Agent Definitions**: Ensure `.claude/agents/` are complete -- **Hub Server**: Already exists, needs schema updates -- **Hub Protocol Contract**: `docs/contracts/hub-device-protocol.md` (enforced) - ---- - -## Protocol Contract - -**CRITICAL**: All Hub ↔ Device communication is governed by: - -- **Specification**: `docs/contracts/hub-device-protocol.md` -- **Types**: `src/shared/types/hub-protocol.ts` - -### Enforcement Rules - -1. **Single Source of Truth**: Types live ONLY in `hub-protocol.ts` -2. **Hub imports from shared**: `import { Task, WsEvent } from '@shared/types'` -3. **Clients import from shared**: Same import path -4. **Validation script**: `npm run validate:protocol` checks compliance -5. **Pre-commit hook**: Blocks commits if protocol violated -6. **CI check**: PR cannot merge if protocol mismatched - -### Updating the Protocol - -1. Update `docs/contracts/hub-device-protocol.md` first (spec) -2. Update `src/shared/types/hub-protocol.ts` to match (types) -3. Update Hub routes to match new spec -4. Update client API calls to match new spec -5. Run `npm run validate:protocol` to verify -6. Bump version number in both files - ---- - -## Timeline - -| Phase | Scope | Blocked By | Effort | -|-------|-------|------------|--------| -| Phase 0 | User Authentication | None | Medium | -| Phase 1 | Devices + Workspaces | Phase 0 | Medium | -| Phase 2 | Project Enhancements | None | Medium | -| Phase 3 | Task Table UI | Phase 2 | Medium | -| Phase 4 | Hub-First Data | Phase 1, 3 | Medium | -| Phase 5 | Progress Watcher + Sync | Phase 4 | Medium | -| Phase 6 | Workflow Launcher | Skills package | Small | -| Phase 7 | Mobile/Web Client | Phase 4, 5 | Large | -| Phase 8 | Cleanup | Phase 6 stable | Small | - ---- - -## Notes - -- **Execution is always on workspace host** — any device can manage, only host executes -- **Hub is the source of truth** — all data synced through Hub -- **Workspaces are logical, devices are physical** — workspace can change host -- **Orchestration lives in prompts** — Claude Workflow skills, not app code -- **Work/Personal separation** — different workspaces, different projects, same account -- **Multi-repo native** — create task for specific sub-project in complex repos -- **Any device access** — log in from friend's phone to check task status diff --git a/doc-history/plans/2026-02-14-hub-frontend-integration.md b/doc-history/plans/2026-02-14-hub-frontend-integration.md deleted file mode 100644 index 7973fa9..0000000 --- a/doc-history/plans/2026-02-14-hub-frontend-integration.md +++ /dev/null @@ -1,468 +0,0 @@ -# Hub-Frontend Integration Plan — Parallel Execution - -> Tracker Key: `hub-frontend` | Status: **IMPLEMENTED** | Created: 2026-02-14 - -**Teams**: Team Alpha (Hub/WebSocket), Team Beta (Frontend Integration) -**Base Branch**: master -**Audit Reference**: Post-merge audit 2026-02-14 - ---- - -## Problem Statement - -The Hub API backend is 100% complete, but frontend integration is only 40%. Critical gaps: - -1. **Zero WebSocket listeners** — Real-time sync unavailable -2. **Tasks use local IPC** — Not routed through Hub API -3. **Auth uses mocks** — Can't test real user flows -4. **Incomplete Hub API client** — Only task methods exist - ---- - -## Architecture Target - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ RENDERER │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ -│ │ TaskTable │ │ Workspaces │ │ Auth (Login/Reg) │ │ -│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │ -│ │ │ │ │ -│ └────────────┬────┴──────────────────────┘ │ -│ ▼ │ -│ ┌──────────────┐ │ -│ │ React Query │ ◄─── invalidateQueries on WS events│ -│ └──────┬───────┘ │ -└─────────────────────┼───────────────────────────────────────────┘ - │ ipc() -┌─────────────────────┼───────────────────────────────────────────┐ -│ ▼ MAIN PROCESS │ -│ ┌──────────────────────────────────────────────────────────┐ │ -│ │ IPC Router │ │ -│ │ hub.* handlers ──► HubApiClient ──► HTTP to Hub │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌──────────────────────────────────────────────────────────┐ │ -│ │ WebSocket Connection Manager │ │ -│ │ Connect to ws://hub/ws ──► Parse events ──► IPC emit │ │ -│ └──────────────────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────┘ - │ - ▼ HTTP + WebSocket -┌──────────────────────────────────────────────────────────────────┐ -│ HUB SERVER │ -│ REST API (35 endpoints) + WebSocket Broadcaster │ -└──────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Team Assignments - -### Team Alpha: Hub Connection Layer -**Branch**: `feature/alpha-hub-connection` -**Focus**: WebSocket client, connection management, event relay - -**File Ownership:** -- `src/main/services/hub/` — Full ownership -- `src/main/ipc/handlers/hub-handlers.ts` — Expand handlers -- `src/shared/types/hub-events.ts` — New file for WS event types - -### Team Beta: Frontend Integration -**Branch**: `feature/beta-frontend-integration` -**Focus**: Hook updates, query invalidation, UI wiring - -**File Ownership:** -- `src/renderer/features/*/api/` — Update hooks to use Hub -- `src/renderer/features/*/hooks/` — Add event listeners -- `src/renderer/shared/hooks/useHubEvents.ts` — New event hook - ---- - -## Wave 1: WebSocket Foundation (Parallel) - -### Team Alpha — Wave 1 -**Deliverables:** - -1. **WebSocket Connection Manager** - ``` - src/main/services/hub/hub-websocket.ts - ``` - - Connect to Hub WebSocket with API key auth - - Auto-reconnect with exponential backoff - - Parse incoming broadcast messages - - Emit typed IPC events to renderer - -2. **Hub Event Types** - ``` - src/shared/types/hub-events.ts - ``` - - Define all 18 WebSocket event types - - Type-safe event payloads matching Hub protocol - -3. **IPC Event Channels** - ``` - src/shared/ipc-contract.ts (update ipcEventContract) - ``` - - Add hub event channels: - - `event:hub.tasks.created` - - `event:hub.tasks.updated` - - `event:hub.tasks.deleted` - - `event:hub.tasks.progress` - - `event:hub.tasks.completed` - - `event:hub.devices.*` - - `event:hub.workspaces.*` - - `event:hub.projects.*` - -4. **Connection Lifecycle** - - Start connection when Hub is configured - - Stop on disconnect - - Expose connection status via IPC - -**Success Criteria:** -- [ ] WebSocket connects to Hub with auth -- [ ] Reconnects automatically on disconnect -- [ ] Events parsed and emitted via IPC -- [ ] TypeScript types for all events - -### Team Beta — Wave 1 -**Deliverables:** - -1. **Hub Event Hook** - ``` - src/renderer/shared/hooks/useHubEvents.ts - ``` - - Subscribe to hub IPC events - - Generic hook: `useHubEvent('hub.tasks.updated', callback)` - - Cleanup on unmount - -2. **Query Invalidation Setup** - ``` - src/renderer/shared/lib/hub-query-sync.ts - ``` - - Map hub events to React Query invalidations: - - `hub.tasks.*` → invalidate `['tasks']` - - `hub.workspaces.*` → invalidate `['workspaces']` - - etc. - -3. **Connection Status UI** - ``` - src/renderer/shared/components/HubStatus.tsx - ``` - - Show connected/disconnected/reconnecting - - Add to TopBar or StatusBar - -**Success Criteria:** -- [ ] Event hook works for all hub events -- [ ] Query keys invalidated on relevant events -- [ ] Connection status visible in UI - ---- - -## Sync Point 1: WebSocket Verification - -**When**: After Wave 1 complete -**Duration**: 30 minutes -**Actions:** - -1. Start Hub server -2. Connect Electron app -3. Verify WebSocket auth succeeds -4. Create task via Hub API (curl) -5. Verify frontend receives event and invalidates query -6. Fix any event mapping issues - ---- - -## Wave 2: Task Hub Integration (Parallel) - -### Team Alpha — Wave 2 -**Deliverables:** - -1. **Expand Hub API Client** - ``` - src/main/services/hub/hub-api-client.ts - ``` - Add methods: - - `createTask(data)` → POST /api/tasks - - `updateTask(id, data)` → PUT /api/tasks/:id - - `updateTaskStatus(id, status)` → PATCH /api/tasks/:id/status - - `executeTask(id)` → POST /api/tasks/:id/execute - - `cancelTask(id)` → POST /api/tasks/:id/cancel - - `pushProgress(id, data)` → POST /api/tasks/:id/progress - - `completeTask(id, result)` → POST /api/tasks/:id/complete - -2. **Hub Task IPC Handlers** - ``` - src/main/ipc/handlers/hub-handlers.ts - ``` - Add handlers: - - `hub.tasks.list` → hubClient.listTasks() - - `hub.tasks.create` → hubClient.createTask() - - `hub.tasks.update` → hubClient.updateTask() - - `hub.tasks.updateStatus` → hubClient.updateTaskStatus() - - `hub.tasks.execute` → hubClient.executeTask() - - `hub.tasks.delete` → hubClient.deleteTask() - -3. **Workspace Context** - - Get current workspace from settings - - Include workspace_id in task operations - -**Success Criteria:** -- [ ] All task CRUD operations available via IPC -- [ ] Task execution routes through Hub -- [ ] Workspace context included - -### Team Beta — Wave 2 -**Deliverables:** - -1. **Update Task Hooks** - ``` - src/renderer/features/tasks/api/useTasks.ts - ``` - - Change from `ipc('tasks.list')` to `ipc('hub.tasks.list')` - - Add workspace_id filter parameter - - Keep local fallback for offline mode (optional) - -2. **Update Task Mutations** - ``` - src/renderer/features/tasks/api/useTaskMutations.ts - ``` - - Route through hub.tasks.* channels - - Remove optimistic updates (let WebSocket handle) - - Add error handling for hub errors - -3. **Task Event Listeners** - ``` - src/renderer/features/tasks/hooks/useTaskEvents.ts - ``` - - Listen for hub task events - - Invalidate task queries on any task event - - Show toast on task completion - -4. **Progress Display** - - Show real-time progress from WebSocket events - - Update TaskTableRow progress bar live - -**Success Criteria:** -- [ ] Tasks load from Hub API -- [ ] Create/update/delete sync to Hub -- [ ] Execute sends to Hub, progress updates live -- [ ] Multi-device: changes on one device appear on others - ---- - -## Sync Point 2: Task Flow Verification - -**When**: After Wave 2 complete -**Duration**: 1 hour -**Actions:** - -1. Open app on two devices (or two instances) -2. Create task on Device A -3. Verify appears on Device B within 1 second -4. Execute task on Device A -5. Verify progress updates on Device B -6. Complete task, verify both update - ---- - -## Wave 3: Auth & Workspace Integration (Parallel) - -### Team Alpha — Wave 3 -**Deliverables:** - -1. **Auth API Client Methods** - ``` - src/main/services/hub/hub-api-client.ts - ``` - - `register(email, password, displayName)` - - `login(email, password, device?)` - - `logout()` - - `refreshToken(token)` - - `getCurrentUser()` - -2. **Token Storage** - ``` - src/main/services/hub/hub-token-store.ts - ``` - - Secure storage for access/refresh tokens - - Auto-refresh before expiry - - Clear on logout - -3. **Auth IPC Handlers** - - `hub.auth.register` - - `hub.auth.login` - - `hub.auth.logout` - - `hub.auth.refresh` - - `hub.auth.me` - -4. **Device Registration** - - Register device on first login - - Send heartbeat every 30s when connected - - Update capabilities on change - -**Success Criteria:** -- [ ] Can register new user via app -- [ ] Can login and receive tokens -- [ ] Tokens persist across restart -- [ ] Auto-refresh works -- [ ] Device registered and sending heartbeats - -### Team Beta — Wave 3 -**Deliverables:** - -1. **Update Auth Store** - ``` - src/renderer/features/auth/store.ts - ``` - - Remove mock user - - Store real user from Hub - - Track auth state (loading, authenticated, error) - -2. **Update Auth Hooks** - ``` - src/renderer/features/auth/api/useAuth.ts - ``` - - `useLogin()` → `ipc('hub.auth.login')` - - `useRegister()` → `ipc('hub.auth.register')` - - `useLogout()` → `ipc('hub.auth.logout')` - - `useCurrentUser()` → `ipc('hub.auth.me')` - -3. **Auth Flow UI** - - Redirect to login if not authenticated - - Show loading state during auth - - Handle auth errors gracefully - -4. **Workspace Hooks Update** - ``` - src/renderer/features/settings/api/useWorkspaces.ts - ``` - - Route through hub.workspaces.* channels - - Add device selection for host - -**Success Criteria:** -- [ ] Login/register works with real Hub -- [ ] User persists across restart -- [ ] Logout clears state -- [ ] Workspaces load from Hub - ---- - -## Wave 4: Cleanup & Polish (Parallel) - -### Team Alpha — Wave 4 -**Deliverables:** - -1. **Remove Mock Auth** - - Delete MOCK_USER, MOCK_TOKEN from handlers - - Remove mock fallbacks - -2. **Offline Mode (Optional)** - - Queue operations when Hub unreachable - - Sync when reconnected - -3. **Error Handling** - - Standardize error responses - - Add retry logic for transient failures - -4. **Logging & Diagnostics** - - Log connection events - - Add debug mode for troubleshooting - -### Team Beta — Wave 4 -**Deliverables:** - -1. **Remove Unused Local Handlers** - - Identify IPC handlers that are now Hub-routed - - Archive or remove dead code - -2. **Loading & Error States** - - Add skeletons for loading - - Show meaningful errors - - Retry buttons where appropriate - -3. **Connection Lost Handling** - - Show banner when Hub disconnected - - Disable mutations (or queue them) - - Re-enable when reconnected - -4. **Testing** - - Test all flows end-to-end - - Verify multi-device sync - ---- - -## Final Sync: Integration Test - -**When**: All waves complete -**Duration**: 2 hours -**Actions:** - -1. Fresh install test (register → login → create workspace → create project → create task → execute) -2. Multi-device test (same user, two devices) -3. Offline/reconnect test -4. Load test (many tasks, rapid updates) -5. Fix any issues found -6. Merge to master - ---- - -## File Ownership Matrix - -| Path | Alpha | Beta | Shared | -|------|-------|------|--------| -| `src/main/services/hub/*` | ✓ | | | -| `src/main/ipc/handlers/hub-handlers.ts` | ✓ | | | -| `src/shared/types/hub-events.ts` | ✓ | | | -| `src/shared/ipc-contract.ts` | | | ✓ | -| `src/renderer/features/*/api/*` | | ✓ | | -| `src/renderer/features/*/hooks/*` | | ✓ | | -| `src/renderer/shared/hooks/useHubEvents.ts` | | ✓ | | -| `src/renderer/shared/lib/hub-query-sync.ts` | | ✓ | | - ---- - -## Quick Start - -### Team Alpha -```bash -git checkout master && git pull -git checkout -b feature/alpha-hub-connection -# Start Wave 1 -``` - -### Team Beta -```bash -git checkout master && git pull -git checkout -b feature/beta-frontend-integration -# Start Wave 1 -``` - ---- - -## Success Criteria (Final) - -- [ ] WebSocket connects and receives all event types -- [ ] Tasks sync through Hub in real-time -- [ ] User can register/login with real credentials -- [ ] Workspaces and devices managed via Hub -- [ ] Multi-device: changes propagate within 1 second -- [ ] Offline mode handles disconnection gracefully -- [ ] `npm run lint && npx tsc --noEmit && npm run build` passes - ---- - -## Estimated Timeline - -| Wave | Duration | Alpha | Beta | -|------|----------|-------|------| -| Wave 1 | 3-4 hours | WebSocket + Events | Event hooks + Query sync | -| Sync 1 | 30 min | Verify WS flow | | -| Wave 2 | 3-4 hours | Task API client | Task hooks update | -| Sync 2 | 1 hour | Multi-device test | | -| Wave 3 | 3-4 hours | Auth + Tokens | Auth UI + Workspace hooks | -| Wave 4 | 2-3 hours | Cleanup + Offline | Polish + Testing | -| Final | 2 hours | Integration test | | - -**Total**: ~16-20 hours parallel work diff --git a/doc-history/plans/2026-02-14-p5-polish.md b/doc-history/plans/2026-02-14-p5-polish.md deleted file mode 100644 index c579ad4..0000000 --- a/doc-history/plans/2026-02-14-p5-polish.md +++ /dev/null @@ -1,543 +0,0 @@ -# P5 Polish — Full Implementation Plan - -> Tracker Key: `p5-polish` | Status: **IMPLEMENTED** | Created: 2026-02-14 - -**Base Branch**: master -**Feature Branch**: feature/p5-polish -**Source**: docs/plans/2026-02-13-full-codebase-audit.md (items 31-37) - ---- - -## Executive Summary - -P5 is the final polish pass before the app is considered feature-complete. It covers 7 items across UI gaps, dead code cleanup, infrastructure hardening, and system integration. The scope ranges from 30-minute deletions to multi-hour service wiring. - -**Goal**: After P5, every button does something, every screen is reachable, every service is wired end-to-end, and there's zero dead code. The user should only need API keys saved and Claude authorized — everything else should "just work." - -**Total estimated effort**: ~20-25 hours across 7 items -**Parallelization**: Items 36+37 (cleanup), 31+33 (UI), 32+34 (wiring) can run in parallel - ---- - -## Item 31: Global Hub Connection Indicator - -### Problem -Hub connection status is only visible on the Settings page. Users have no persistent visual indicator of whether they're connected to the Hub server. - -### Current State -- `hub-connection.ts` tracks status: `connected | disconnected | connecting | error` -- `event:hub.connectionChanged` is emitted on status changes -- `HubNotification.tsx` shows temporary toast notifications (auto-dismisses after 4s) -- Sidebar footer has a Settings button but no status indicator - -### Implementation - -**Create**: `src/renderer/shared/components/HubConnectionIndicator.tsx` -- Small dot indicator component: green (connected), yellow (connecting), red (error), gray (disconnected) -- Tooltip showing connection details (Hub URL, status text) -- Listens to `event:hub.connectionChanged` via `useIpcEvent` -- Fetch initial status via existing `hub.getStatus` IPC channel -- Click navigates to Hub Settings - -**Modify**: `src/renderer/app/layouts/Sidebar.tsx` -- Add `HubConnectionIndicator` next to the Settings button in the sidebar footer -- Show only the dot when sidebar is collapsed, dot + "Hub" label when expanded - -**Modify**: `src/shared/ipc-contract.ts` -- Verify `hub.getStatus` channel exists (it should — if not, add it) - -### Acceptance Criteria -- [ ] Green dot visible in sidebar when Hub is connected -- [ ] Gray dot when not configured/disconnected -- [ ] Yellow dot when connecting -- [ ] Red dot when connection error -- [ ] Tooltip shows status text on hover -- [ ] Click navigates to Settings > Hub section -- [ ] Works in both expanded and collapsed sidebar modes -- [ ] `npx tsc --noEmit` passes -- [ ] `npm run lint` passes - -### Files -| Action | Path | -|--------|------| -| CREATE | `src/renderer/shared/components/HubConnectionIndicator.tsx` | -| MODIFY | `src/renderer/app/layouts/Sidebar.tsx` | -| MODIFY | `src/shared/ipc-contract.ts` (only if `hub.getStatus` missing) | - ---- - -## Item 32: Configurable Hotkeys UI - -### Problem -Global hotkeys are hardcoded in `hotkey-manager.ts`. The `HotkeySettings.tsx` component exists with a full edit UI, but it's not rendered in SettingsPage and has no backend persistence or re-registration logic. - -### Current State -- `hotkey-manager.ts` has hardcoded `DEFAULT_HOTKEYS` (quickCommand, quickNote, quickTask) -- `HotkeySettings.tsx` has full edit/save UI but: - - Uses local `useState` only — not persisted to disk - - Calls `updateSettings.mutate({ hotkeys: ... })` but `AppSettings` has no `hotkeys` field - - Not imported or rendered in `SettingsPage.tsx` -- `settings-service.ts` has no logic for hotkey persistence -- No IPC channels for hotkey read/update/re-registration - -### Implementation - -**Modify**: `src/shared/types/settings.ts` -- Add `hotkeys?: Record` field to `AppSettings` - -**Modify**: `src/shared/ipc-contract.ts` -- Add `hotkeys.get` channel: returns current hotkey bindings -- Add `hotkeys.update` channel: accepts partial hotkey map, persists and re-registers -- Add `hotkeys.reset` channel: resets to defaults and re-registers - -**Create**: `src/main/ipc/handlers/hotkey-handlers.ts` -- `hotkeys.get` → reads from settings service (falls back to defaults) -- `hotkeys.update` → saves to settings, calls hotkey manager to unregister + re-register -- `hotkeys.reset` → clears custom hotkeys, re-registers defaults - -**Modify**: `src/main/tray/hotkey-manager.ts` -- Add `registerFromConfig(config: Record)` method -- Reads hotkey config, maps action names to callbacks -- Unregisters existing, registers new -- Keep `registerDefaults()` as fallback - -**Modify**: `src/main/index.ts` -- After creating hotkey manager, check settings for custom hotkeys -- If custom exist, call `registerFromConfig()`; else `registerDefaults()` -- Register hotkey IPC handlers - -**Modify**: `src/renderer/features/settings/components/HotkeySettings.tsx` -- Load initial hotkey values from `hotkeys.get` IPC channel (not local state) -- Save calls `hotkeys.update` IPC channel -- Show success/error feedback after save -- Add "Reset to Defaults" button calling `hotkeys.reset` - -**Modify**: `src/renderer/features/settings/components/SettingsPage.tsx` -- Import and render `` section between Webhooks and About - -### Acceptance Criteria -- [ ] HotkeySettings section visible in Settings page -- [ ] Current bindings loaded from persisted settings on page load -- [ ] Editing a binding + saving persists to disk AND re-registers the hotkey globally -- [ ] Reset to Defaults restores original bindings and re-registers -- [ ] Invalid accelerator format shows error feedback -- [ ] Hotkeys survive app restart (persistence verified) -- [ ] `npx tsc --noEmit` passes -- [ ] `npm run lint` passes - -### Files -| Action | Path | -|--------|------| -| CREATE | `src/main/ipc/handlers/hotkey-handlers.ts` | -| MODIFY | `src/shared/types/settings.ts` | -| MODIFY | `src/shared/ipc-contract.ts` | -| MODIFY | `src/main/tray/hotkey-manager.ts` | -| MODIFY | `src/main/index.ts` | -| MODIFY | `src/main/ipc/index.ts` | -| MODIFY | `src/renderer/features/settings/components/HotkeySettings.tsx` | -| MODIFY | `src/renderer/features/settings/components/SettingsPage.tsx` | - ---- - -## Item 33: App Launch at System Startup - -### Problem -No option to launch the app at system startup. `BackgroundSettings.tsx` exists with tray/background toggles but has no startup toggle and isn't rendered in SettingsPage. - -### Current State -- `BackgroundSettings.tsx` has 3 toggles (minimize to tray, start minimized, keep running) -- All use local `useState` — not persisted -- Not rendered in `SettingsPage.tsx` -- `AppSettings` has no `openAtLogin`, `minimizeToTray`, `startMinimized`, `keepRunning` fields -- `app.setLoginItemSettings()` Electron API never called - -### Implementation - -**Modify**: `src/shared/types/settings.ts` -- Add to `AppSettings`: - - `openAtLogin?: boolean` - - `minimizeToTray?: boolean` - - `startMinimized?: boolean` - - `keepRunning?: boolean` - -**Modify**: `src/shared/ipc-contract.ts` -- Add `app.setOpenAtLogin` channel: `{ enabled: boolean }` → `{ success: boolean }` -- Add `app.getOpenAtLogin` channel: `void` → `{ enabled: boolean }` - -**Modify**: `src/main/ipc/handlers/app-handlers.ts` -- Add handler for `app.setOpenAtLogin` → calls `app.setLoginItemSettings({ openAtLogin: value })` -- Add handler for `app.getOpenAtLogin` → calls `app.getLoginItemSettings()` -- Also persist to settings service for the other background toggles - -**Modify**: `src/renderer/features/settings/components/BackgroundSettings.tsx` -- Add "Launch at system startup" toggle -- Load initial values from settings via `useSettings()` hook (not local state) -- Save calls appropriate IPC channels -- For `openAtLogin`: call `app.setOpenAtLogin` IPC -- For other toggles: call `settings.update` with the field - -**Modify**: `src/renderer/features/settings/components/SettingsPage.tsx` -- Import and render `` section (after Appearance, before Profiles) - -**Modify**: `src/main/index.ts` -- On app ready, read settings for `startMinimized` → if true, don't show window initially -- Read `minimizeToTray` → wire into window close handler -- Read `keepRunning` → wire into app quit behavior - -### Acceptance Criteria -- [ ] BackgroundSettings section visible in Settings page -- [ ] "Launch at system startup" toggle sets system login item -- [ ] Toggle state persists across app restart -- [ ] Other toggles (minimize to tray, start minimized, keep running) persist and function -- [ ] Works on Windows (tested platform) -- [ ] `npx tsc --noEmit` passes -- [ ] `npm run lint` passes - -### Files -| Action | Path | -|--------|------| -| MODIFY | `src/shared/types/settings.ts` | -| MODIFY | `src/shared/ipc-contract.ts` | -| MODIFY | `src/main/ipc/handlers/app-handlers.ts` | -| MODIFY | `src/renderer/features/settings/components/BackgroundSettings.tsx` | -| MODIFY | `src/renderer/features/settings/components/SettingsPage.tsx` | -| MODIFY | `src/main/index.ts` | - ---- - -## Item 34: Database Migration Versioning (Hub) - -### Problem -Hub database schema is applied as a raw `db.exec(schema.sql)` on every startup. No version tracking, no migration history, no safe path for schema changes. - -### Current State -- `hub/src/db/schema.sql` defines 9 tables with `CREATE TABLE IF NOT EXISTS` -- `hub/src/db/database.ts` runs `readFileSync(schema.sql)` → `db.exec(schema)` on init -- No `schema_version` or `migrations` table -- No way to add columns or alter tables without data loss risk - -### Implementation - -**Create**: `hub/src/db/migrations/` directory -- `001_initial_schema.sql` — the current schema.sql content (baseline) - -**Create**: `hub/src/db/migration-runner.ts` -- Reads migration files from `migrations/` directory -- Creates `schema_version` table if not exists: `(version INT PRIMARY KEY, name TEXT, applied_at TEXT)` -- Gets current version from `schema_version` -- Applies all pending migrations in order -- Wraps each migration in a transaction for atomicity -- Logs applied migrations - -**Modify**: `hub/src/db/database.ts` -- Replace `runMigrations()` call with `runMigrationRunner(db)` from migration-runner -- Remove the old `readFileSync(schema.sql)` approach - -**Keep**: `hub/src/db/schema.sql` -- Keep for reference/documentation, but mark as "see migrations/" at the top - -### Migration Runner Design -```typescript -interface Migration { - version: number; - name: string; - sql: string; -} - -function runMigrationRunner(db: Database): void { - // 1. Create schema_version table if not exists - // 2. Read current version (SELECT MAX(version)) - // 3. Read all .sql files from migrations/ directory - // 4. Sort by version number (filename prefix) - // 5. Apply each pending migration in a transaction - // 6. Insert into schema_version after each success -} -``` - -### Acceptance Criteria -- [ ] Fresh database: all migrations applied, schema_version table populated -- [ ] Existing database: only new migrations applied, data preserved -- [ ] Migration failure: transaction rolls back, no partial state -- [ ] Hub server starts and runs cleanly -- [ ] Current schema is exactly reproduced by running migration 001 -- [ ] `npx tsc --noEmit` passes (hub project) -- [ ] Hub tests pass (if any) - -### Files -| Action | Path | -|--------|------| -| CREATE | `hub/src/db/migrations/001_initial_schema.sql` | -| CREATE | `hub/src/db/migration-runner.ts` | -| MODIFY | `hub/src/db/database.ts` | -| MODIFY | `hub/src/db/schema.sql` (add header note) | - ---- - -## Item 35: Electron Auto-Updater Wiring - -### Problem -IPC events `event:app.updateAvailable` and `event:app.updateDownloaded` are defined in the contract but nothing emits them. The `electron-updater` dependency was previously removed as unused. - -### Current State -- `event:app.updateAvailable` and `event:app.updateDownloaded` defined in IPC contract (stubs) -- `electron-updater` was removed from package.json (marked as unused during P6 cleanup) -- No auto-updater service, no handlers, no UI - -### Implementation - -**Install**: `electron-updater` package -```bash -npm install electron-updater -``` - -**Create**: `src/main/services/app/app-update-service.ts` -- Wraps `electron-updater`'s `autoUpdater` -- `checkForUpdates()` → triggers update check -- `downloadUpdate()` → downloads available update -- `quitAndInstall()` → applies update and restarts -- Emits IPC events: `event:app.updateAvailable`, `event:app.updateDownloaded` -- Configurable: auto-check on startup (with 30s delay), periodic check interval - -**Create**: `src/main/ipc/handlers/app-update-handlers.ts` -- `app.checkForUpdates` → calls update service -- `app.downloadUpdate` → starts download -- `app.quitAndInstall` → applies and restarts -- `app.getUpdateStatus` → returns current update state - -**Modify**: `src/shared/ipc-contract.ts` -- Add invoke channels: `app.checkForUpdates`, `app.downloadUpdate`, `app.quitAndInstall`, `app.getUpdateStatus` -- Verify event channels already exist (they do) - -**Create**: `src/renderer/shared/components/AppUpdateNotification.tsx` -- Listens for `event:app.updateAvailable` → shows "Update available" notification -- Shows version number and "Download" button -- After download completes (`event:app.updateDownloaded`): shows "Restart to update" button -- Dismissible - -**Modify**: `src/renderer/app/layouts/RootLayout.tsx` -- Add `` component - -**Modify**: `src/main/index.ts` -- Create update service on app ready (with 30s startup delay) -- Register update handlers - -**Modify**: `src/main/ipc/index.ts` -- Register update handler file - -### Acceptance Criteria -- [ ] App checks for updates 30s after startup -- [ ] "Update available" notification appears when update exists -- [ ] Download button triggers update download -- [ ] "Restart to update" button appears after download -- [ ] Graceful handling when no update available (silent, no UI) -- [ ] Works offline (no crash, no error toast) -- [ ] `npx tsc --noEmit` passes -- [ ] `npm run lint` passes -- [ ] `npm run build` passes (electron-updater compatible with build) - -### Files -| Action | Path | -|--------|------| -| CREATE | `src/main/services/app/app-update-service.ts` | -| CREATE | `src/main/ipc/handlers/app-update-handlers.ts` | -| CREATE | `src/renderer/shared/components/AppUpdateNotification.tsx` | -| MODIFY | `package.json` (add `electron-updater`) | -| MODIFY | `src/shared/ipc-contract.ts` | -| MODIFY | `src/main/index.ts` | -| MODIFY | `src/main/ipc/index.ts` | -| MODIFY | `src/renderer/app/layouts/RootLayout.tsx` | - ---- - -## Item 36: Remove Withings Dead Code - -### Problem -Withings OAuth provider config exists but no actual Withings API calls or sync logic are implemented. It's dead code. - -### Current State -- `src/main/auth/providers/withings.ts` — OAuth config stub (empty clientId/clientSecret) -- `src/main/services/fitness/fitness-service.ts` — References `source === 'withings'` in deduplication -- `src/renderer/features/settings/components/OAuthProviderSettings.tsx` — Shows Withings card -- `src/shared/types/fitness.ts` — `MeasurementSource` type includes `'withings'` -- `src/main/index.ts` — Imports Withings config -- Multiple doc/agent files reference Withings - -### Implementation - -**Delete**: `src/main/auth/providers/withings.ts` - -**Modify**: `src/main/index.ts` -- Remove import of `WITHINGS_OAUTH_CONFIG` -- Remove Withings from provider registration - -**Modify**: `src/renderer/features/settings/components/OAuthProviderSettings.tsx` -- Remove Withings from the `PROVIDER_CONFIG` array - -**Modify**: `src/shared/types/fitness.ts` -- Remove `'withings'` from `MeasurementSource` type -- Simplify to only real sources: `'manual'` (and any other active sources) - -**Modify**: `src/main/services/fitness/fitness-service.ts` -- Remove Withings-specific deduplication logic -- Simplify the measurement filtering - -**Modify**: Agent/doc references (if they cause lint/build failures) -- `.claude/agents/fitness-engineer.md` — remove Withings mentions -- `.claude/agents/oauth-engineer.md` — remove Withings mentions - -### Acceptance Criteria -- [ ] No references to "withings" in runtime source code (`src/`) -- [ ] Withings card no longer appears in OAuth Provider Settings -- [ ] `MeasurementSource` type only includes valid, active sources -- [ ] `npx tsc --noEmit` passes -- [ ] `npm run lint` passes -- [ ] `npm run build` passes - -### Files -| Action | Path | -|--------|------| -| DELETE | `src/main/auth/providers/withings.ts` | -| MODIFY | `src/main/index.ts` | -| MODIFY | `src/renderer/features/settings/components/OAuthProviderSettings.tsx` | -| MODIFY | `src/shared/types/fitness.ts` | -| MODIFY | `src/main/services/fitness/fitness-service.ts` | - ---- - -## Item 37: Background Manager Dead Code Cleanup - -### Problem -`BackgroundManager` and `Scheduler` are stub code that's never instantiated. Alert checking is already handled by `AlertService.startChecking()`. - -### Current State -- `background-manager.ts` — Has `handleAlertCheck()` and `handleHealthCheck()` that only log -- `scheduler.ts` — Generic interval scheduler (working code, but no consumer) -- Neither is instantiated in `src/main/index.ts` -- `AlertService` already polls for alerts every 60 seconds independently - -### Implementation - -**Delete**: `src/main/services/background/background-manager.ts` -**Delete**: `src/main/services/background/scheduler.ts` - -**Verify**: `src/main/index.ts` — confirm no BackgroundManager references (remove if found) - -**Verify**: No other imports reference these files (grep to confirm) - -### Acceptance Criteria -- [ ] `background-manager.ts` deleted -- [ ] `scheduler.ts` deleted -- [ ] No import references to deleted files -- [ ] Alert checking still works (AlertService unaffected) -- [ ] `npx tsc --noEmit` passes -- [ ] `npm run lint` passes - -### Files -| Action | Path | -|--------|------| -| DELETE | `src/main/services/background/background-manager.ts` | -| DELETE | `src/main/services/background/scheduler.ts` | -| VERIFY | `src/main/index.ts` (remove any references if found) | - ---- - -## Task Decomposition & Agent Assignment - -### Wave 1: Cleanup (No Dependencies, Can Run in Parallel) - -| Task | Agent | Scope | Blocked By | -|------|-------|-------|------------| -| T1: Remove Withings dead code | cleanup-eng | Item 36 | None | -| T2: Remove background-manager dead code | cleanup-eng | Item 37 | None | - -**Note**: T1 and T2 can be handled by the same agent since they're both small deletions with no overlap. - -### Wave 2: Type & Contract Layer (Foundation for Waves 3-4) - -| Task | Agent | Scope | Blocked By | -|------|-------|-------|------------| -| T3: Add settings types + IPC channels for P5 features | schema-eng | Items 31-33, 35 | None | - -This task adds all new types and IPC contract channels needed by items 31, 32, 33, and 35. All subsequent service/UI work depends on these types being defined first. - -### Wave 3: Services & Handlers (Can Parallelize) - -| Task | Agent | Scope | Blocked By | -|------|-------|-------|------------| -| T4: Hub connection indicator (service + UI) | indicator-eng | Item 31 | T3 | -| T5: Hotkey persistence + re-registration | hotkey-eng | Item 32 | T3 | -| T6: App startup + background settings wiring | startup-eng | Item 33 | T3 | -| T7: Auto-updater service + UI | updater-eng | Item 35 | T3 | -| T8: Hub database migration system | migration-eng | Item 34 | None | - -**Note**: T8 (Hub migrations) has no dependency on T3 since it's Hub-server-only code. - -### Wave 4: Integration & Settings Page Assembly - -| Task | Agent | Scope | Blocked By | -|------|-------|-------|------------| -| T9: Wire all new sections into SettingsPage | settings-eng | Items 32, 33 | T5, T6 | - -**Note**: T4, T7 integrate into Sidebar/RootLayout (not SettingsPage), so they complete independently. - -### Wave 5: Documentation - -| Task | Agent | Scope | Blocked By | -|------|-------|-------|------------| -| T10: Update all documentation | doc-eng | All items | T1-T9 | - ---- - -## Dependency Graph - -``` -T1 (Withings cleanup) ─────────────────────────────────────────┐ -T2 (BG manager cleanup) ───────────────────────────────────────┤ - │ -T3 (Types + IPC contract) ─────┬──────┬──────┬──────┐ │ - │ │ │ │ │ - ▼ ▼ ▼ ▼ │ - T4(Hub) T5(Keys) T6(Start) T7(Update)│ - │ │ │ - ▼ ▼ │ - T9 (SettingsPage assembly) │ - │ │ -T8 (Hub migrations) ─────────────────────┤ │ - │ │ - ▼ │ - T10 (Documentation) ◀──────────┘ -``` - ---- - -## Out-of-Scope Issues to Address - -During scoping, these issues were identified as adjacent problems worth fixing in the same pass: - -1. **HotkeySettings.tsx calls `updateSettings.mutate({ hotkeys: ... })` but `hotkeys` isn't in `AppSettings`** — Fixed by T3 (adding the type) and T5 (wiring the backend) - -2. **BackgroundSettings.tsx uses local state instead of persisted settings** — Fixed by T6 (wiring to real settings) - -3. **BackgroundSettings.tsx is never rendered in SettingsPage** — Fixed by T9 (settings page assembly) - -4. **HotkeySettings.tsx is never rendered in SettingsPage** — Fixed by T9 (settings page assembly) - -5. **SettingsPage has no "About" version display from IPC** — Can fix in T9 (call `app.getVersion` and display) - ---- - -## Success Criteria (Full P5) - -- [ ] All 7 audit items implemented or cleaned up -- [ ] Hub connection indicator visible in sidebar -- [ ] Hotkeys configurable and persisted -- [ ] App launch at startup toggleable -- [ ] Hub database has migration versioning -- [ ] Auto-updater wired and emitting events -- [ ] Zero Withings references in runtime code -- [ ] Zero dead code in background-manager -- [ ] SettingsPage shows all settings sections -- [ ] `npm run lint` — 0 violations -- [ ] `npx tsc --noEmit` — 0 errors -- [ ] `npm run build` — passes clean -- [ ] All new features testable with only API keys + Claude auth configured diff --git a/doc-history/plans/2026-02-14-parallel-implementation-plan.md b/doc-history/plans/2026-02-14-parallel-implementation-plan.md deleted file mode 100644 index ae17068..0000000 --- a/doc-history/plans/2026-02-14-parallel-implementation-plan.md +++ /dev/null @@ -1,456 +0,0 @@ -# Parallel Implementation Plan — Two-Team Execution - -> Tracker Key: `parallel-plan` | Status: **IMPLEMENTED** | Created: 2026-02-14 - -**Teams**: Team Alpha (Hub/Backend), Team Beta (Frontend/UI) -**Base Branch**: master -**Source Plans**: -- `2026-02-13-kanban-workflow-refactor.md` -- `2026-02-14-workspace-project-management.md` - ---- - -## Overview - -This plan splits the workflow refactor into two parallel workstreams that can be executed by separate Claude Code instances in different terminals. Each team works on a dedicated branch, coordinating at defined sync points. - -``` - master - │ - ┌────────────┴────────────┐ - │ │ - ▼ ▼ - feature/team-alpha feature/team-beta - (Hub + Backend) (Frontend + UI) - │ │ - │ ◄── Sync Point 1 ──► │ - │ │ - │ ◄── Sync Point 2 ──► │ - │ │ - ▼ ▼ - Merge to master (coordinated) -``` - ---- - -## Team Assignments - -### Team Alpha: Hub + Backend -**Branch**: `feature/team-alpha-hub` -**Focus**: Hub server, authentication, database, API endpoints - -**File Ownership:** -- `hub/` — Full ownership -- `src/shared/types/hub-protocol.ts` — Shared (coordinate with Beta) -- `src/main/services/device/` — New service -- `src/main/services/workspace/` — New service -- `docs/contracts/` — Protocol specification - -### Team Beta: Frontend + UI -**Branch**: `feature/team-beta-frontend` -**Focus**: React components, UI flows, desktop app integration - -**File Ownership:** -- `src/renderer/features/tasks/` — Table UI -- `src/renderer/features/settings/` — Workspace settings tab -- `src/renderer/features/projects/` — Project init wizard -- `src/main/services/project/` — Project detection -- `src/main/services/workflow/` — Progress watcher, task launcher - ---- - -## Execution Waves - -### Wave 1: Foundation (Parallel) - -Both teams start simultaneously on independent work. - -#### Team Alpha — Wave 1 -**Duration**: ~2-3 hours -**Deliverables**: - -1. **Hub Database Schema** - - Add tables: `users`, `sessions`, `devices`, `workspaces`, `projects`, `sub_projects` - - Update `tasks` table with new foreign keys - - Run migrations - -2. **Authentication Endpoints** - ``` - POST /api/auth/register - POST /api/auth/login - POST /api/auth/logout - POST /api/auth/refresh - GET /api/auth/me - ``` - -3. **Device Endpoints** - ``` - POST /api/devices - GET /api/devices - PATCH /api/devices/:id - DELETE /api/devices/:id - ``` - -4. **Update Protocol Types** - - Add User, Device types to `hub-protocol.ts` - - Add auth request/response types - -**Success Criteria**: -- [ ] Can register a new user via API -- [ ] Can login and receive JWT -- [ ] Can register a device -- [ ] All new tables exist with correct schema - -#### Team Beta — Wave 1 -**Duration**: ~2-3 hours -**Deliverables**: - -1. **Task Table UI Components** - - `TaskTable.tsx` — Main table component - - `TaskTableRow.tsx` — Row with actions - - `TaskTableHeader.tsx` — Sortable headers - - `TaskTableFilters.tsx` — Filter controls - -2. **Project Detection Service** - - `src/main/services/project/project-detector.ts` - - Detect repo type (single, monorepo, multi-repo) - - Find child git repos - -3. **Stub IPC Handlers** (local-only, to be wired to Hub later) - - Tasks CRUD against local storage temporarily - - Project detection IPC - -**Success Criteria**: -- [ ] Task table renders with mock data -- [ ] Columns are sortable -- [ ] Filters work (status, search) -- [ ] Project detector identifies repo types - ---- - -### Sync Point 1: API Contract Verification - -**When**: After Wave 1 complete -**Duration**: 30 minutes -**Actions**: - -1. **Team Alpha** publishes final API endpoints to `hub-device-protocol.md` -2. **Team Beta** reviews and confirms frontend can consume APIs -3. Both teams sync `hub-protocol.ts` types -4. Resolve any contract mismatches before proceeding - ---- - -### Wave 2: Core Features (Parallel) - -#### Team Alpha — Wave 2 -**Duration**: ~3-4 hours -**Deliverables**: - -1. **Workspace Endpoints** - ``` - GET /api/workspaces - POST /api/workspaces - GET /api/workspaces/:id - PATCH /api/workspaces/:id - DELETE /api/workspaces/:id - POST /api/workspaces/:id/host - ``` - -2. **Project Endpoints** - ``` - GET /api/workspaces/:wid/projects - POST /api/workspaces/:wid/projects - POST /api/projects/detect - GET /api/projects/:id - PATCH /api/projects/:id - DELETE /api/projects/:id - ``` - -3. **Sub-Project Endpoints** - ``` - GET /api/projects/:id/sub-projects - POST /api/projects/:id/sub-projects - DELETE /api/projects/:pid/sub-projects/:sid - ``` - -4. **WebSocket Events** - - workspace:created, workspace:updated, workspace:deleted - - project:created, project:updated - - device:online, device:offline - -**Success Criteria**: -- [ ] Can create/update/delete workspaces -- [ ] Can create projects with sub-projects -- [ ] WebSocket broadcasts workspace changes -- [ ] Device online/offline status tracked - -#### Team Beta — Wave 2 -**Duration**: ~3-4 hours -**Deliverables**: - -1. **Login/Register UI** - - Login page component - - Register page component - - Auth context/store - - Token storage (secure) - -2. **Settings → Workspaces Tab** - - `WorkspacesTab.tsx` - - `WorkspaceCard.tsx` - - `WorkspaceEditor.tsx` (modal) - - `DeviceSelector.tsx` (host dropdown) - -3. **Project Initialization Wizard** - - `ProjectInitWizard.tsx` (multi-step) - - `RepoTypeSelector.tsx` - - `SubRepoDetector.tsx` - - `SubRepoSelector.tsx` - -4. **Wire Task Table to IPC** (still local storage) - -**Success Criteria**: -- [ ] Can login/register in app -- [ ] Workspaces tab shows workspace list -- [ ] Can rename workspace, change host -- [ ] Project wizard detects and creates multi-repo projects - ---- - -### Sync Point 2: Integration Test - -**When**: After Wave 2 complete -**Duration**: 1 hour -**Actions**: - -1. **Start Hub server** with Team Alpha changes -2. **Team Beta** points frontend to Hub APIs -3. Test full flows: - - Register → Login → Create Workspace → Create Project - - Verify WebSocket receives events -4. Fix any integration issues -5. Both teams merge latest from each other's branch - ---- - -### Wave 3: Data Migration & Sync (Sequential) - -**Note**: This wave has dependencies, so teams coordinate closely. - -#### Team Alpha — Wave 3 (First) -**Duration**: ~2 hours -**Deliverables**: - -1. **Task Endpoints Update** - - Add `workspace_id`, `sub_project_id` to task endpoints - - Task list filtered by workspace/project - -2. **Progress Endpoints** - ``` - POST /api/tasks/:id/progress - POST /api/tasks/:id/complete - ``` - -3. **Hub-First Task Storage** - - All tasks stored in Hub database - - WebSocket broadcasts task changes - -**Success Criteria**: -- [ ] Tasks have workspace_id and sub_project_id -- [ ] Progress updates stored and broadcast -- [ ] Task list filters by workspace - -#### Team Beta — Wave 3 (After Alpha) -**Duration**: ~2 hours -**Deliverables**: - -1. **Wire Frontend to Hub APIs** - - Update `useTasks` hooks to call Hub - - Update task mutations to call Hub - - Subscribe to WebSocket task events - -2. **Progress Watcher Service** - - `progress-watcher.ts` — Watch `docs/progress/*.md` - - `progress-syncer.ts` — Push to Hub API - -3. **Sub-Project Selector in Task Creation** - - Task form shows sub-project dropdown for multi-repo - -**Success Criteria**: -- [ ] Tasks sync through Hub -- [ ] Real-time updates via WebSocket -- [ ] Progress files sync to Hub -- [ ] Can create task targeting sub-project - ---- - -### Wave 4: Execution & Polish (Parallel) - -#### Team Alpha — Wave 4 -**Duration**: ~2 hours -**Deliverables**: - -1. **Execution Command Endpoints** - ``` - POST /api/tasks/:id/execute - POST /api/tasks/:id/cancel - ``` - -2. **WebSocket Execution Commands** - - command:execute (Hub → Host Device) - - command:cancel - - execution:started, execution:ack (Device → Hub) - -3. **Final Protocol Documentation** - - Update `hub-device-protocol.md` with all endpoints - - Ensure types match implementation - -**Success Criteria**: -- [ ] Execute command routes to correct workspace host -- [ ] Cancel broadcasts to executing device -- [ ] Protocol doc is complete and accurate - -#### Team Beta — Wave 4 -**Duration**: ~2 hours -**Deliverables**: - -1. **Workflow Launcher** - - `task-launcher.ts` — Spawn Claude with workflow skill - - Wire to execute button in task table - -2. **Kanban Removal -- COMPLETED** - - Kanban components already deleted - - Router already uses `TaskTable` from `@features/tasks` - -3. **Remove Broken Agent Service** - - Archive `agent-service.ts`, `agent-queue.ts`, `token-parser.ts` - - Update imports - -**Success Criteria**: -- [ ] Execute button launches Claude workflow -- [x] Kanban components removed (completed) -- [ ] Old agent code archived -- [ ] App builds and runs - ---- - -### Final Sync: Merge to Master - -**When**: All waves complete -**Duration**: 1-2 hours -**Actions**: - -1. **Team Alpha** merges `feature/team-alpha-hub` to master -2. **Team Beta** rebases `feature/team-beta-frontend` on master -3. **Team Beta** resolves any merge conflicts -4. **Team Beta** merges to master -5. Run full verification: - ```bash - npm run lint && npx tsc --noEmit && npm run build - ``` -6. Create release PR with combined changes - ---- - -## File Ownership Matrix - -| Path | Team Alpha | Team Beta | Shared | -|------|------------|-----------|--------| -| `hub/**` | ✓ | | | -| `src/shared/types/hub-protocol.ts` | | | ✓ | -| `src/shared/ipc-contract.ts` | | | ✓ | -| `src/main/services/device/**` | ✓ | | | -| `src/main/services/workspace/**` | ✓ | | | -| `src/main/services/project/**` | | ✓ | | -| `src/main/services/workflow/**` | | ✓ | | -| `src/main/ipc/handlers/**` | | | ✓ | -| `src/renderer/features/tasks/**` | | ✓ | | -| `src/renderer/features/settings/**` | | ✓ | | -| `src/renderer/features/projects/**` | | ✓ | | -| `src/renderer/features/auth/**` | | ✓ | | -| `docs/contracts/**` | ✓ | | | -| `docs/plans/**` | | | ✓ | - ---- - -## Communication Protocol - -### Between Teams - -1. **Slack/Discord channel** for real-time coordination -2. **Sync points are blocking** — don't proceed until both teams ready -3. **Shared files** require notification before editing -4. **API changes** must be communicated immediately - -### Progress Tracking - -Each team maintains a progress file: -- `docs/progress/team-alpha-progress.md` -- `docs/progress/team-beta-progress.md` - -Update after each wave with: -- Completed tasks -- Blockers encountered -- Files modified -- Ready for sync point (yes/no) - ---- - -## Quick Start Commands - -### Team Alpha -```bash -cd Claude-UI -git checkout master && git pull -git checkout -b feature/team-alpha-hub -# Start work on Wave 1 -``` - -### Team Beta -```bash -cd Claude-UI -git checkout master && git pull -git checkout -b feature/team-beta-frontend -# Start work on Wave 1 -``` - ---- - -## Rollback Plan - -If integration fails at any sync point: - -1. Both teams stop work -2. Identify breaking change -3. Revert problematic commit(s) -4. Re-sync protocol types -5. Resume from last good state - ---- - -## Estimated Timeline - -| Wave | Duration | Team Alpha | Team Beta | -|------|----------|------------|-----------| -| Wave 1 | 2-3 hours | Auth + Devices | Task Table + Detection | -| Sync 1 | 30 min | API Contract Review | | -| Wave 2 | 3-4 hours | Workspaces + Projects | UI + Settings | -| Sync 2 | 1 hour | Integration Test | | -| Wave 3 | 2+2 hours | Tasks API | Wire Frontend | -| Wave 4 | 2 hours | Execution | Launcher + Cleanup | -| Final | 1-2 hours | Merge | | - -**Total**: ~14-18 hours of parallel work - ---- - -## Success Criteria (Final) - -- [ ] User can register/login from any device -- [ ] Workspaces configurable in Settings -- [ ] Projects support multi-repo with sub-projects -- [x] Task table replaces Kanban (completed) -- [ ] Tasks sync through Hub in real-time -- [ ] Execute launches Claude workflow on workspace host -- [x] Kanban removed (completed); old agent code still to be archived -- [ ] `npm run lint && npx tsc --noEmit && npm run build` passes diff --git a/doc-history/plans/2026-02-14-test-suite-design.md b/doc-history/plans/2026-02-14-test-suite-design.md deleted file mode 100644 index 762294a..0000000 --- a/doc-history/plans/2026-02-14-test-suite-design.md +++ /dev/null @@ -1,785 +0,0 @@ -# Test Suite Design — Claude-UI - -> Tracker Key: `test-suite` | Status: **IMPLEMENTED** | Created: 2026-02-14 - -**Branch**: `feature/test-suite` - ---- - -## Overview - -Comprehensive testing strategy for the Claude-UI Electron application with four layers: - -1. **Unit Tests** — Vitest, services and utilities in isolation -2. **Integration Tests** — Vitest, IPC flow and Hub server -3. **E2E Tests** — Playwright + Electron, critical user journeys -4. **AI QA Agent** — Claude + MCP Electron, exploratory visual testing - ---- - -## Architecture - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ CLAUDE-UI TEST PYRAMID │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────┐ │ -│ │ AI QA AGENT │ ← Claude + MCP Electron │ -│ │ (Exploratory) │ Visual verification │ -│ └────────┬────────┘ Natural language scenarios │ -│ │ │ -│ ┌─────────────┴─────────────┐ │ -│ │ E2E TESTS │ ← Playwright + Electron │ -│ │ (Critical Journeys) │ Scripted, deterministic │ -│ └─────────────┬─────────────┘ CI-friendly │ -│ │ │ -│ ┌───────────────────────┴───────────────────────┐ │ -│ │ INTEGRATION TESTS │ ← Vitest │ -│ └───────────────────────┬───────────────────────┘ │ -│ │ │ -│ ┌───────────────────────────────┴───────────────────────────────────────┐ │ -│ │ UNIT TESTS │ │ -│ │ (Services, Utilities, Zod Schemas, Pure Functions) │ │ -│ └───────────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - -| Layer | Tool | Speed | When to Run | Coverage Target | -|-------|------|-------|-------------|-----------------| -| Unit | Vitest | <1s | Every save | 80% of services | -| Integration | Vitest | <10s | Pre-commit | IPC contract, Hub API | -| E2E | Playwright | <60s | Pre-push/CI | 10 critical journeys | -| AI QA | Claude + MCP | ~5min | PR review | Exploratory, visual | - ---- - -## Directory Structure - -``` -tests/ -├── setup/ -│ ├── vitest.setup.ts # Global test setup -│ └── mocks/ -│ ├── electron.ts # Mock app, dialog, safeStorage -│ ├── node-fs.ts # Mock file system -│ ├── node-pty.ts # Mock PTY spawning -│ └── ipc.ts # Mock window.api.invoke -│ -├── unit/ -│ ├── services/ -│ │ ├── project-service.test.ts -│ │ ├── task-service.test.ts -│ │ ├── hub-sync-service.test.ts -│ │ ├── hub-token-store.test.ts -│ │ └── agent-service.test.ts -│ ├── ipc/ -│ │ ├── router.test.ts -│ │ └── contract.test.ts -│ └── shared/ -│ ├── time-parser.test.ts -│ └── utils.test.ts -│ -├── integration/ -│ ├── ipc-handlers/ -│ │ ├── task-handlers.test.ts -│ │ ├── project-handlers.test.ts -│ │ └── hub-handlers.test.ts -│ ├── hub-server/ -│ │ ├── auth-routes.test.ts -│ │ ├── task-routes.test.ts -│ │ └── websocket.test.ts -│ └── hooks/ -│ ├── useTasks.test.tsx -│ └── useProjects.test.tsx -│ -├── e2e/ -│ ├── electron.setup.ts -│ ├── project-setup.spec.ts -│ ├── task-creation.spec.ts -│ ├── agent-execution.spec.ts -│ ├── hub-connection.spec.ts -│ └── settings-persistence.spec.ts -│ -├── qa-scenarios/ -│ ├── task-creation.md -│ ├── project-management.md -│ ├── agent-workflow.md -│ └── hub-sync.md -│ -└── fixtures/ - ├── projects.ts - ├── tasks.ts - └── hub-responses.ts -``` - ---- - -## Layer 1: Unit Tests - -### Configuration - -**vitest.config.ts:** -```typescript -import { defineConfig } from 'vitest/config'; -import { resolve } from 'path'; - -export default defineConfig({ - test: { - globals: true, - environment: 'node', - setupFiles: ['./tests/setup/vitest.setup.ts'], - include: ['tests/unit/**/*.test.ts'], - coverage: { - provider: 'v8', - reporter: ['text', 'html'], - include: ['src/main/services/**/*.ts'], - exclude: ['**/*.d.ts', '**/index.ts'], - }, - alias: { - '@shared': resolve(__dirname, 'src/shared'), - '@main': resolve(__dirname, 'src/main'), - electron: resolve(__dirname, 'tests/setup/mocks/electron.ts'), - }, - }, -}); -``` - -### Mocks - -**tests/setup/mocks/electron.ts:** -```typescript -import { vi } from 'vitest'; - -export const app = { - getPath: vi.fn((name: string) => `/mock/${name}`), - getName: vi.fn(() => 'claude-ui-test'), - getVersion: vi.fn(() => '1.0.0'), -}; - -export const safeStorage = { - isEncryptionAvailable: vi.fn(() => true), - encryptString: vi.fn((s: string) => Buffer.from(`enc:${s}`)), - decryptString: vi.fn((b: Buffer) => b.toString().replace('enc:', '')), -}; - -export const dialog = { - showOpenDialog: vi.fn(() => Promise.resolve({ canceled: false, filePaths: ['/mock/path'] })), - showMessageBox: vi.fn(() => Promise.resolve({ response: 0 })), -}; - -export const BrowserWindow = vi.fn(); -export const ipcMain = { handle: vi.fn(), on: vi.fn() }; - -export default { app, safeStorage, dialog, BrowserWindow, ipcMain }; -``` - -**tests/setup/mocks/node-fs.ts:** -```typescript -import { vi } from 'vitest'; -import { Volume, createFsFromVolume } from 'memfs'; - -export function createMockFs(files: Record = {}) { - const vol = Volume.fromJSON(files); - return createFsFromVolume(vol); -} - -export const mockFs = createMockFs(); -vi.mock('node:fs', () => mockFs); -vi.mock('node:fs/promises', () => mockFs.promises); -``` - -**tests/setup/mocks/node-pty.ts:** -```typescript -import { vi } from 'vitest'; -import { EventEmitter } from 'events'; - -export class MockPty extends EventEmitter { - pid = 12345; - cols = 80; - rows = 24; - - write = vi.fn(); - resize = vi.fn(); - kill = vi.fn(() => this.emit('exit', 0, 0)); - - simulateOutput(data: string) { - this.emit('data', data); - } -} - -export const spawn = vi.fn(() => new MockPty()); - -vi.mock('@lydell/node-pty', () => ({ spawn })); -``` - -### Priority Services to Test - -| Service | Complexity | Test Focus | -|---------|------------|------------| -| `project-service.ts` | Low | CRUD, file persistence | -| `task-service.ts` | Medium | File structure, status transitions | -| `hub-token-store.ts` | Low | Encryption, expiry checking | -| `hub-sync-service.ts` | High | Offline queue, conflict resolution | -| `agent-service.ts` | High | Spawn, parse output, queue management | -| `time-parser.ts` | Low | Natural language parsing | - ---- - -## Layer 2: Integration Tests - -### IPC Handler Tests - -```typescript -// tests/integration/ipc-handlers/task-handlers.test.ts -import { describe, it, expect, beforeEach } from 'vitest'; -import { createIpcRouter } from '@main/ipc/router'; -import { registerTaskHandlers } from '@main/ipc/handlers/task-handlers'; -import { createTaskService } from '@main/services/task/task-service'; - -describe('Task IPC Handlers', () => { - let router: IpcRouter; - let taskService: TaskService; - - beforeEach(() => { - taskService = createTaskService({ projectPath: '/mock/project' }); - router = createIpcRouter(); - registerTaskHandlers(router, taskService); - }); - - it('tasks.list returns array of tasks', async () => { - const result = await router.invoke('tasks.list', { projectId: 'proj-1' }); - expect(result.success).toBe(true); - expect(Array.isArray(result.data)).toBe(true); - }); - - it('tasks.create validates input with Zod', async () => { - const result = await router.invoke('tasks.create', { title: '' }); // Invalid - expect(result.success).toBe(false); - expect(result.error).toContain('validation'); - }); -}); -``` - -### Hub Server Tests - -```typescript -// tests/integration/hub-server/task-routes.test.ts -import { describe, it, expect, beforeAll, afterAll } from 'vitest'; -import { build } from '../../../hub/src/app'; -import type { FastifyInstance } from 'fastify'; - -describe('Hub Task Routes', () => { - let app: FastifyInstance; - - beforeAll(async () => { - app = await build({ testing: true }); - }); - - afterAll(async () => { - await app.close(); - }); - - it('GET /api/tasks returns task list', async () => { - const response = await app.inject({ - method: 'GET', - url: '/api/tasks', - headers: { 'x-api-key': 'test-key' }, - }); - expect(response.statusCode).toBe(200); - expect(JSON.parse(response.body)).toHaveProperty('tasks'); - }); -}); -``` - -### React Hook Tests - -```typescript -// tests/integration/hooks/useTasks.test.tsx -import { renderHook, waitFor } from '@testing-library/react'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { useTasks } from '@features/tasks/api/useTasks'; -import { vi } from 'vitest'; - -// Mock the ipc helper -vi.mock('@renderer/shared/lib/ipc', () => ({ - ipc: vi.fn((channel: string) => { - if (channel === 'tasks.list') { - return Promise.resolve({ success: true, data: [{ id: '1', title: 'Test' }] }); - } - }), -})); - -describe('useTasks', () => { - const wrapper = ({ children }) => ( - - {children} - - ); - - it('fetches tasks for project', async () => { - const { result } = renderHook(() => useTasks('proj-1'), { wrapper }); - await waitFor(() => expect(result.current.isSuccess).toBe(true)); - expect(result.current.data).toHaveLength(1); - }); -}); -``` - ---- - -## Layer 3: E2E Tests (Playwright + Electron) - -### Configuration - -**playwright.config.ts:** -```typescript -import { defineConfig } from '@playwright/test'; - -export default defineConfig({ - testDir: './tests/e2e', - timeout: 60_000, - retries: 2, - workers: 1, // Electron tests must run serially - use: { - trace: 'on-first-retry', - screenshot: 'only-on-failure', - video: 'on-first-retry', - }, - reporter: [['html', { open: 'never' }]], -}); -``` - -### Electron Setup - -**tests/e2e/electron.setup.ts:** -```typescript -import { _electron as electron, ElectronApplication, Page } from 'playwright'; -import { test as base } from '@playwright/test'; - -type TestFixtures = { - electronApp: ElectronApplication; - mainWindow: Page; -}; - -export const test = base.extend({ - electronApp: async ({}, use) => { - const app = await electron.launch({ - args: ['.'], - env: { ...process.env, NODE_ENV: 'test', ELECTRON_IS_TEST: '1' }, - }); - await use(app); - await app.close(); - }, - mainWindow: async ({ electronApp }, use) => { - const window = await electronApp.firstWindow(); - await window.waitForLoadState('domcontentloaded'); - await use(window); - }, -}); - -export { expect } from '@playwright/test'; -``` - -### Critical Journey Tests - -**tests/e2e/task-creation.spec.ts:** -```typescript -import { test, expect } from './electron.setup'; - -test.describe('Task Creation', () => { - test('creates task via task dashboard', async ({ mainWindow }) => { - // Navigate to project - await mainWindow.click('[data-testid="sidebar-projects"]'); - await mainWindow.click('[data-testid="project-card"]:first-child'); - - // Open task creation - await mainWindow.click('[data-testid="new-task-button"]'); - - // Fill form - await mainWindow.fill('[data-testid="task-title"]', 'E2E Test Task'); - await mainWindow.fill('[data-testid="task-description"]', 'Created by Playwright'); - - // Submit - await mainWindow.click('[data-testid="create-task-submit"]'); - - // Verify - await expect(mainWindow.locator('[data-testid="task-card"]').filter({ hasText: 'E2E Test Task' })).toBeVisible(); - }); - - test('validates empty title', async ({ mainWindow }) => { - await mainWindow.click('[data-testid="new-task-button"]'); - await mainWindow.click('[data-testid="create-task-submit"]'); - await expect(mainWindow.locator('[data-testid="title-error"]')).toBeVisible(); - }); -}); -``` - -### Critical Journeys Checklist - -| # | Journey | File | Priority | -|---|---------|------|----------| -| 1 | Project Setup | `project-setup.spec.ts` | P0 | -| 2 | Task Creation | `task-creation.spec.ts` | P0 | -| 3 | Task Drag & Drop | `task-dnd.spec.ts` | P0 | -| 4 | Agent Execution | `agent-execution.spec.ts` | P1 | -| 5 | Hub Connection | `hub-connection.spec.ts` | P1 | -| 6 | Settings Persistence | `settings.spec.ts` | P1 | -| 7 | Terminal Usage | `terminal.spec.ts` | P2 | -| 8 | Offline Mode | `offline-mode.spec.ts` | P2 | -| 9 | Voice Command | `voice.spec.ts` | P3 | -| 10 | Multi-Project Switch | `multi-project.spec.ts` | P2 | - ---- - -## Layer 4: AI QA Agent - -### Agent Definition - -**.claude/agents/qa-tester.md:** -```markdown -# QA Tester Agent - -You are Quinn, a veteran QA engineer with 12 years of experience testing desktop applications. - -## Philosophy - -- **Trust nothing** — Verify every claim with your own eyes -- **Edge cases are where bugs hide** — Always try boundary conditions -- **Document everything** — Screenshot before and after every action -- **Think like a user** — Not like a developer who knows the code - -## Available Tools - -You have access to the MCP Electron server tools: - -- `mcp__electron__take_screenshot` — Capture current app state -- `mcp__electron__send_command_to_electron` — Interact with UI elements -- `mcp__electron__get_electron_window_info` — Check window properties -- `mcp__electron__read_electron_logs` — Check for console errors - -## Interaction Commands - -When using `send_command_to_electron`, use these commands: - -| Command | Args | Purpose | -|---------|------|---------| -| `get_page_structure` | none | See all interactive elements | -| `click_by_text` | `{ text: "Button" }` | Click by visible text | -| `click_by_selector` | `{ selector: ".class" }` | Click by CSS selector | -| `fill_input` | `{ selector: "#id", value: "text" }` | Fill input field | -| `send_keyboard_shortcut` | `{ text: "Enter" }` | Send keypress | - -## Testing Protocol - -For each test scenario: - -1. **Baseline** — Take screenshot, note initial state -2. **Execute** — Perform each step, screenshot after each -3. **Verify** — Check expected outcomes visually -4. **Logs** — Read console logs, flag any errors -5. **Report** — Document findings in structured format - -## Report Format - -Generate reports in this structure: - -```markdown -# QA Report: [Scenario Name] - -## Summary -- **Status**: PASS / FAIL / BLOCKED -- **Date**: [timestamp] -- **Duration**: [time] - -## Test Steps -| Step | Action | Expected | Actual | Status | -|------|--------|----------|--------|--------| -| 1 | ... | ... | ... | ✅/❌ | - -## Screenshots -[Embedded screenshots with captions] - -## Console Errors -[Any errors found in logs] - -## Recommendations -[Suggested fixes or improvements] -``` - -## Edge Cases to Always Try - -- Empty inputs -- Very long strings (500+ chars) -- Special characters: `` -- **Expected**: Title displayed as literal text, no script execution - -### Rapid Creation -1. Create 5 tasks in rapid succession (< 1 second each) -- **Expected**: All 5 tasks created, no duplicates, no errors - -## Accessibility Checks -- Tab through all form fields -- Submit with Enter key -- Screen reader announces form labels -``` - -### Running QA Agent - -**NPM Script:** -```json -{ - "scripts": { - "test:qa": "npm run build && npm run start:test & sleep 5 && claude --agent qa-tester", - "test:qa:scenario": "claude --agent qa-tester --input" - } -} -``` - -**Manual Invocation:** -```bash -# Run all scenarios -npm run test:qa - -# Run specific scenario -cat tests/qa-scenarios/task-creation.md | npm run test:qa:scenario -``` - ---- - -## CI/CD Integration - -**.github/workflows/test.yml:** -```yaml -name: Test Suite - -on: - push: - branches: [master, 'feature/**'] - pull_request: - branches: [master] - -jobs: - lint-typecheck: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - run: npm ci - - run: npm run lint - - run: npm run typecheck - - unit-tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - run: npm ci - - run: npm run test:unit -- --coverage - - uses: actions/upload-artifact@v4 - with: - name: coverage-report - path: coverage/ - - integration-tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - run: npm ci - - run: npm run test:integration - - e2e-tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - run: npm ci - - run: npx playwright install --with-deps chromium - - run: xvfb-run --auto-servernum npm run test:e2e - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: playwright-report - path: playwright-report/ - - hub-tests: - runs-on: ubuntu-latest - defaults: - run: - working-directory: hub - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - run: npm ci - - run: npm test -``` - ---- - -## Package.json Scripts - -```json -{ - "scripts": { - "test": "npm run test:unit && npm run test:integration", - "test:unit": "vitest run --config vitest.config.ts", - "test:unit:watch": "vitest --config vitest.config.ts", - "test:integration": "vitest run --config vitest.integration.config.ts", - "test:e2e": "playwright test", - "test:e2e:ui": "playwright test --ui", - "test:coverage": "vitest run --coverage", - "test:qa": "npm run build && concurrently -k \"npm run start:test\" \"sleep 5 && claude --agent qa-tester\"", - "start:test": "cross-env ELECTRON_IS_TEST=1 electron ." - } -} -``` - ---- - -## Implementation Waves - -### Wave 1: Test Infrastructure (Foundation) -1. Create `vitest.config.ts` -2. Create `tests/setup/vitest.setup.ts` -3. Create mock files (electron, fs, pty) -4. Add test scripts to package.json -5. Install missing dependencies (memfs, @vitest/coverage-v8) - -### Wave 2: Unit Tests (Services) -1. `project-service.test.ts` -2. `task-service.test.ts` -3. `hub-token-store.test.ts` -4. `time-parser.test.ts` -5. `router.test.ts` (IPC validation) - -### Wave 3: Integration Tests -1. `task-handlers.test.ts` -2. `project-handlers.test.ts` -3. `hub-handlers.test.ts` -4. Hub server route tests - -### Wave 4: E2E Setup -1. Install Playwright -2. Create `playwright.config.ts` -3. Create `electron.setup.ts` -4. Add data-testid attributes to key components - -### Wave 5: E2E Tests -1. `project-setup.spec.ts` -2. `task-creation.spec.ts` -3. `task-dnd.spec.ts` -4. `hub-connection.spec.ts` - -### Wave 6: AI QA Agent -1. Create `.claude/agents/qa-tester.md` -2. Create QA scenario templates -3. Create QA report template -4. Document QA workflow - -### Wave 7: CI/CD -1. Create `.github/workflows/test.yml` -2. Add coverage badges to README -3. Set up PR checks - ---- - -## Dependencies to Add - -```bash -# Testing -npm install -D memfs @vitest/coverage-v8 - -# E2E -npm install -D @playwright/test - -# Utilities -npm install -D concurrently cross-env -``` - ---- - -## Success Metrics - -| Metric | Target | Measurement | -|--------|--------|-------------| -| Unit test coverage | 80% services | Vitest coverage report | -| Integration test pass rate | 100% | CI pipeline | -| E2E test pass rate | 95% | Playwright report | -| E2E test duration | <60s | CI timing | -| QA agent bug detection | Qualitative | PR review feedback | - ---- - -## References - -- [Playwright Electron Testing](https://playwright.dev/docs/api/class-electron) -- [Vitest Documentation](https://vitest.dev/) -- [Building AI QA Engineer with Claude](https://alexop.dev/posts/building_ai_qa_engineer_claude_code_playwright/) -- [Electron Automated Testing](https://www.electronjs.org/docs/latest/tutorial/automated-testing) diff --git a/doc-history/plans/2026-02-14-workspace-project-management.md b/doc-history/plans/2026-02-14-workspace-project-management.md deleted file mode 100644 index 8609f54..0000000 --- a/doc-history/plans/2026-02-14-workspace-project-management.md +++ /dev/null @@ -1,598 +0,0 @@ -# Workspace & Project Management - -> Tracker Key: `workspace-project` | Status: **SUPERSEDED** | Created: 2026-02-14 - -**Related**: `2026-02-13-kanban-workflow-refactor.md` (Task Dashboard & Multi-Device Workflow plan) - ---- - -## Overview - -This document defines the Workspace and Project management system, which supersedes the simpler "Computer" model from the original refactor plan. - ---- - -## Key Concept Changes - -| Original Term | New Term | Meaning | -|---------------|----------|---------| -| Computer | **Workspace** | Logical execution environment (renameable) | -| (implicit) | **Device** | Physical device (phone, laptop, desktop) | -| (implicit) | **User** | Authenticated account | -| Project | **Project** | Git repository (enhanced with multi-repo support) | -| (none) | **Sub-Project** | Child repo within a multi-repo structure | - ---- - -## Data Model - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ USER │ -│ (Authenticated account - can log in from any device) │ -└─────────────────────────────────────────────────────────────────────┘ - │ - │ owns - ▼ -┌─────────────────────────────────────────────────────────────────────┐ -│ WORKSPACES │ -│ "Work PC" "Home Desktop" "Personal Laptop" │ -│ (host: device-A) (host: device-B) (host: device-C) │ -└─────────────────────────────────────────────────────────────────────┘ - │ │ │ - │ contains │ contains │ contains - ▼ ▼ ▼ -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ PROJECTS │ │ PROJECTS │ │ PROJECTS │ -│ │ │ │ │ │ -│ • company-api │ │ • claude-ui │ │ • side-project │ -│ • company-web │ │ • blog │ │ • learning-rust │ -│ • infra-tools │ │ • dotfiles │ │ │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ - │ - │ (multi-repo example) - ▼ -┌─────────────────────────────────────────┐ -│ PROJECT: company-monolith │ -│ Type: multi-repo │ -│ Root: /work/company-monolith │ -│ │ -│ ├── /frontend (git repo) ◄─ Sub-Project│ -│ ├── /backend (git repo) ◄─ Sub-Project│ -│ └── /shared (git repo) ◄─ Sub-Project│ -└─────────────────────────────────────────┘ -``` - ---- - -## Entity Definitions - -### User - -```typescript -interface User { - id: string; - email: string; - displayName: string; - avatarUrl?: string; - createdAt: string; - lastLoginAt: string; - settings: UserSettings; -} - -interface UserSettings { - defaultWorkspaceId?: string; - theme: 'light' | 'dark' | 'system'; - notifications: NotificationPreferences; -} -``` - -### Device - -A physical device that can connect to the Hub. Any device can view/manage, but only devices with Claude CLI can execute. - -```typescript -interface Device { - id: string; // Hub-assigned - machineId: string; // Hardware fingerprint (for desktop) - userId: string; // Owner - deviceType: 'desktop' | 'mobile' | 'web'; - deviceName: string; // "Parker's iPhone", "Chrome on MacBook" - capabilities: { - canExecute: boolean; // Has Claude CLI - canHostWorkspace: boolean; // Can be a workspace host - }; - isOnline: boolean; - lastSeen: string; - appVersion?: string; - createdAt: string; -} -``` - -### Workspace - -A logical execution environment. Named by user, hosted on a specific device. - -```typescript -interface Workspace { - id: string; - userId: string; // Owner - name: string; // "Work PC", "Home Desktop" (user-editable) - description?: string; - hostDeviceId: string; // Which device runs this workspace - isOnline: boolean; // Is the host device online? - settings: WorkspaceSettings; - createdAt: string; - updatedAt: string; -} - -interface WorkspaceSettings { - autoStartTasks: boolean; // Auto-execute queued tasks - maxConcurrentAgents: number; - defaultBranch: string; - notifyOnComplete: boolean; -} -``` - -### Project - -A git repository within a workspace. Can be simple, monorepo, or multi-repo. - -```typescript -type RepoStructure = 'single' | 'monorepo' | 'multi-repo'; - -interface Project { - id: string; - workspaceId: string; - name: string; // "claude-ui", "company-api" - description?: string; - rootPath: string; // Absolute path on host device - gitUrl?: string; // Remote URL if available - repoStructure: RepoStructure; - parentProjectId?: string; // For sub-projects in multi-repo - subProjects?: SubProject[]; // Child repos (for multi-repo) - defaultBranch: string; - settings: ProjectSettings; - createdAt: string; - updatedAt: string; -} - -interface SubProject { - id: string; - projectId: string; // Parent project - name: string; // "frontend", "backend" - relativePath: string; // "/frontend", "/backend" - gitUrl?: string; - defaultBranch: string; -} - -interface ProjectSettings { - claudeModel: 'opus' | 'sonnet' | 'haiku'; - workflowSkill: string; // "/implement-feature" by default - prTemplate?: string; - branchPrefix?: string; // "feature/", "fix/" -} -``` - -### Task - -Now includes optional sub-project targeting. - -```typescript -interface Task { - id: string; - projectId: string; - subProjectId?: string; // Optional: target specific sub-repo - workspaceId: string; // Denormalized for filtering - title: string; - description: string; - status: TaskStatus; - priority: TaskPriority; - // ... rest of task fields from protocol - targetPath?: string; // Computed: project root + sub-project path -} -``` - ---- - -## User Flows - -### 1. First-Time Setup (Desktop App) - -``` -1. User opens app for first time -2. App prompts: "Create account or sign in" -3. User creates account (email/password or OAuth) -4. App detects this is a desktop with Claude CLI -5. Prompt: "Set up this computer as a Workspace?" -6. User names it: "Work Laptop" -7. Workspace created, this device is the host -8. Prompt: "Add a project?" → Project initialization flow -``` - -### 2. Adding a Device (Mobile) - -``` -1. User opens mobile app / PWA -2. Sign in with existing account -3. App registers as device (mobile, no execution capability) -4. User sees all their workspaces -5. Can view projects, tasks, progress -6. Can create/edit tasks (execution happens on workspace host) -``` - -### 3. Project Initialization - -``` -1. User clicks "Add Project" in workspace -2. Select folder (native dialog on desktop) -3. App detects git status: - - A) New folder (no .git): - - Prompt: "Initialize as new repository?" - - Ask repo type: Single | Monorepo | Multi-repo parent - - B) Existing single repo: - - Auto-detect, add as "single" type - - Read remote URL, default branch - - C) Folder with child git repos: - - Prompt: "Detected child repositories:" - ☑ /frontend (git) - ☑ /backend (git) - ☐ /docs (not a git repo) - - "Add these as sub-projects?" - - User confirms, creates Project + SubProjects - -4. Project added to workspace -5. Syncs to Hub → visible on all devices -``` - -### 4. Creating Task for Multi-Repo Project - -``` -1. User viewing project "company-monolith" (multi-repo) -2. Clicks "New Task" -3. Task form shows: - - Title: [________________] - Description: [______________] - - Target: ○ Entire project - ○ frontend (sub-project) - ○ backend (sub-project) - ○ shared (sub-project) - - Priority: [Normal ▼] - -4. User selects "frontend", creates task -5. Task created with subProjectId set -6. When executed, Claude works in /frontend directory -``` - -### 5. Workspace Settings - -``` -Settings → Workspaces - -┌─────────────────────────────────────────────────┐ -│ My Workspaces │ -├─────────────────────────────────────────────────┤ -│ 🟢 Work Laptop [Edit] [···] │ -│ Host: MacBook Pro (this device) │ -│ Projects: 5 │ -│ Status: Online │ -├─────────────────────────────────────────────────┤ -│ 🔴 Home Desktop [Edit] [···] │ -│ Host: Windows PC │ -│ Projects: 3 │ -│ Status: Offline (last seen: 2h ago) │ -├─────────────────────────────────────────────────┤ -│ [+ Add Workspace] │ -└─────────────────────────────────────────────────┘ - -Edit Workspace: -┌─────────────────────────────────────────────────┐ -│ Workspace Settings │ -├─────────────────────────────────────────────────┤ -│ Name: [Work Laptop_____________] │ -│ │ -│ Host Device: [MacBook Pro (this device) ▼] │ -│ ⚠️ Changing host will migrate projects │ -│ │ -│ Auto-start queued tasks: [✓] │ -│ Max concurrent agents: [3____] │ -│ Default branch: [main__] │ -│ Notify on completion: [✓] │ -│ │ -│ [Cancel] [Save Changes] │ -└─────────────────────────────────────────────────┘ -``` - ---- - -## Hub Database Schema - -```sql --- Users table -CREATE TABLE users ( - id TEXT PRIMARY KEY, - email TEXT UNIQUE NOT NULL, - password_hash TEXT NOT NULL, - display_name TEXT NOT NULL, - avatar_url TEXT, - settings TEXT, -- JSON: UserSettings - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - last_login_at DATETIME -); - --- Devices table (physical devices) -CREATE TABLE devices ( - id TEXT PRIMARY KEY, - machine_id TEXT, -- NULL for mobile/web - user_id TEXT NOT NULL REFERENCES users(id), - device_type TEXT NOT NULL, -- 'desktop' | 'mobile' | 'web' - device_name TEXT NOT NULL, - capabilities TEXT NOT NULL, -- JSON: { canExecute, canHostWorkspace } - is_online BOOLEAN DEFAULT FALSE, - last_seen DATETIME, - app_version TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - UNIQUE(machine_id) WHERE machine_id IS NOT NULL -); - --- Workspaces table (logical execution environments) -CREATE TABLE workspaces ( - id TEXT PRIMARY KEY, - user_id TEXT NOT NULL REFERENCES users(id), - name TEXT NOT NULL, - description TEXT, - host_device_id TEXT NOT NULL REFERENCES devices(id), - settings TEXT, -- JSON: WorkspaceSettings - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP -); - --- Projects table -CREATE TABLE projects ( - id TEXT PRIMARY KEY, - workspace_id TEXT NOT NULL REFERENCES workspaces(id), - name TEXT NOT NULL, - description TEXT, - root_path TEXT NOT NULL, - git_url TEXT, - repo_structure TEXT NOT NULL, -- 'single' | 'monorepo' | 'multi-repo' - parent_project_id TEXT REFERENCES projects(id), - default_branch TEXT DEFAULT 'main', - settings TEXT, -- JSON: ProjectSettings - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, - UNIQUE(workspace_id, root_path) -); - --- Sub-projects table (for multi-repo) -CREATE TABLE sub_projects ( - id TEXT PRIMARY KEY, - project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, - name TEXT NOT NULL, - relative_path TEXT NOT NULL, - git_url TEXT, - default_branch TEXT DEFAULT 'main', - UNIQUE(project_id, relative_path) -); - --- Tasks table (updated) -CREATE TABLE tasks ( - id TEXT PRIMARY KEY, - project_id TEXT NOT NULL REFERENCES projects(id), - sub_project_id TEXT REFERENCES sub_projects(id), - workspace_id TEXT NOT NULL REFERENCES workspaces(id), - title TEXT NOT NULL, - description TEXT, - status TEXT NOT NULL DEFAULT 'backlog', - priority TEXT NOT NULL DEFAULT 'normal', - created_by_device_id TEXT REFERENCES devices(id), - execution_session_id TEXT, - progress_data TEXT, - metadata TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP -); - --- Sessions table (for JWT management) -CREATE TABLE sessions ( - id TEXT PRIMARY KEY, - user_id TEXT NOT NULL REFERENCES users(id), - device_id TEXT NOT NULL REFERENCES devices(id), - token_hash TEXT NOT NULL, - expires_at DATETIME NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP -); -``` - ---- - -## API Endpoints (Additions to Protocol) - -### Authentication - -``` -POST /api/auth/register # Create account -POST /api/auth/login # Login (returns JWT) -POST /api/auth/logout # Invalidate session -POST /api/auth/refresh # Refresh JWT -GET /api/auth/me # Get current user -``` - -### Workspaces - -``` -GET /api/workspaces # List user's workspaces -POST /api/workspaces # Create workspace -GET /api/workspaces/:id # Get workspace -PATCH /api/workspaces/:id # Update workspace -DELETE /api/workspaces/:id # Delete workspace -POST /api/workspaces/:id/transfer-host # Change host device -``` - -### Projects - -``` -GET /api/workspaces/:wid/projects # List projects in workspace -POST /api/workspaces/:wid/projects # Create project -GET /api/projects/:id # Get project -PATCH /api/projects/:id # Update project -DELETE /api/projects/:id # Delete project - -# Sub-projects -GET /api/projects/:id/sub-projects # List sub-projects -POST /api/projects/:id/sub-projects # Add sub-project -DELETE /api/projects/:pid/sub-projects/:sid # Remove sub-project -``` - -### Project Detection (Desktop Only) - -``` -POST /api/projects/detect - Body: { path: string } - Response: { - isGitRepo: boolean; - hasChildRepos: boolean; - childRepos: Array<{ path: string; name: string; gitUrl?: string }>; - remoteUrl?: string; - defaultBranch?: string; - } -``` - ---- - -## UI Components - -### Settings → Workspaces Tab - -``` -src/renderer/features/settings/ -├── components/ -│ ├── WorkspacesTab.tsx # Main workspaces settings -│ ├── WorkspaceCard.tsx # Individual workspace in list -│ ├── WorkspaceEditor.tsx # Edit workspace modal -│ └── WorkspaceHostSelector.tsx # Device dropdown for host -``` - -### Project Initialization Flow - -``` -src/renderer/features/projects/ -├── components/ -│ ├── ProjectInitWizard.tsx # Multi-step init flow -│ ├── RepoTypeSelector.tsx # Single/Monorepo/Multi-repo picker -│ ├── SubRepoDetector.tsx # Shows detected child repos -│ └── SubRepoSelector.tsx # Checkboxes for sub-projects -``` - -### Task Creation (Updated) - -``` -src/renderer/features/tasks/ -├── components/ -│ ├── TaskCreator.tsx # Task creation form -│ └── SubProjectSelector.tsx # Target selector for multi-repo -``` - ---- - -## Edge Cases & Decisions - -### 1. Workspace Host Goes Offline - -- Workspace shows as "offline" -- Tasks can still be created/edited (queued) -- Execution blocked until host comes online -- Progress shows "last known state" - -### 2. Changing Workspace Host - -- User goes to Settings → Workspaces → Edit -- Selects new host device from dropdown -- Warning: "Projects on old host won't be accessible until synced" -- Option: "Clone projects to new host" (future) - -### 3. Project Path Changes - -- User moves folder on disk -- Desktop app detects project not found -- Prompt: "Project 'foo' not found at /old/path. Locate or remove?" -- User selects new path, project updated - -### 4. Sub-Project Added Later - -- User has existing multi-repo project -- Adds new folder with git repo -- Goes to Project Settings → Sub-projects -- "Add Sub-project" → Select folder → Added - -### 5. Authentication Token Expiry - -- JWT expires (24h default) -- App attempts refresh token -- If refresh fails, prompt re-login -- Mobile can use biometric to unlock stored credentials - ---- - -## Security Considerations - -1. **Password Storage**: Argon2 hashing on Hub -2. **JWT**: Short-lived access (1h), longer refresh (7d) -3. **Device Trust**: Desktop devices can host, mobile cannot -4. **Project Paths**: Never transmitted, only stored locally on host -5. **Workspace Isolation**: Users only see their own workspaces - ---- - -## Migration from Current System - -### Phase 0: Add User Auth -1. Add `users` and `sessions` tables -2. Create default user for existing data -3. Add login/register UI - -### Phase 1: Rename Computer → Workspace -1. Add `workspaces` table -2. Migrate `computers` data to `workspaces` -3. Add `host_device_id` concept -4. Update UI terminology - -### Phase 2: Add Devices Table -1. Create `devices` table -2. Current machines become devices + workspaces -3. Mobile app registers as device only - -### Phase 3: Project Enhancements -1. Add `repo_structure` to projects -2. Add `sub_projects` table -3. Add project initialization wizard -4. Update task creation with sub-project selector - ---- - -## Open Questions - -1. **OAuth providers**: Google, GitHub, or email-only for MVP? -2. **Workspace sharing**: Can users share workspaces? (future) -3. **Project templates**: Pre-configured project settings? (future) -4. **Offline-first**: Should mobile cache data for offline viewing? -5. **Workspace migration**: Tooling to move workspace to new host? - ---- - -## Success Criteria - -- [ ] User can register/login from any device -- [ ] User can create and name workspaces -- [ ] User can assign host device to workspace -- [ ] User can initialize projects with auto-detection -- [ ] Multi-repo projects show sub-project selector in task creation -- [ ] Settings → Workspaces tab fully functional -- [ ] All devices see same workspace/project/task data -- [ ] Workspace host executes tasks, viewers observe diff --git a/doc-history/plans/2026-02-15-gap-remediation.md b/doc-history/plans/2026-02-15-gap-remediation.md deleted file mode 100644 index 731c5e6..0000000 --- a/doc-history/plans/2026-02-15-gap-remediation.md +++ /dev/null @@ -1,395 +0,0 @@ -# Gap Remediation Plan — High & Medium Priority - -> Tracker Key: `gap-remediation` | Status: **IMPLEMENTED** | Created: 2026-02-15 - -> Fill in the gaps identified in `ai-docs/user-interface-flow.md` (G-1 through G-20). -> Focus: High and Medium severity only. Low items deferred to future sprints. - -**Source**: `ai-docs/user-interface-flow.md` Gap Analysis (20 gaps total) - ---- - -## Scope - -### In Scope (7 gaps) - -| Gap | Severity | Domain | Summary | Existing Infrastructure | -|-----|----------|--------|---------|------------------------| -| G-1 | High | Auth | No visible logout button | `useLogout()` hook, `auth.logout` IPC, `clearAuth()` store method — all exist, needs UI | -| G-2 | High | Tasks | No task creation dialog | `useCreateTask()` hook, `hub.tasks.create` IPC — all exist, needs modal + button | -| G-3 | Medium | Tasks | Duplicate task handlers | Both `hub-handlers.ts` and `task-handlers.ts` register `hub.tasks.*` channels | -| G-4 | Medium | Hub | No error UI for Hub disconnect during operation | `HubNotification.tsx` exists; mutations lack `onError` callbacks | -| G-5 | Medium | Auth | Token refresh not proactive | `useRefreshToken()` exists; no timer-based auto-refresh before expiry | -| G-15 | Medium | Projects | No project edit/settings page | `useUpdateProject()` hook, `projects.update` IPC — all exist, needs form UI | -| G-16 | Medium | Projects | No delete confirmation dialogs | No `ConfirmDialog` component; deletes fire immediately | - -### Already Resolved - -| Gap | Status | Notes | -|-----|--------|-------| -| G-20 | DONE | Profile API keys encryption implemented 2026-02-13 (Full Codebase Audit P0) | - -### Deferred (Separate Feature) - -| Gap | Notes | -|-----|-------| -| G-13 | `/assistant` route — Full feature epic. TODO: Create dedicated design doc | - -### Deferred (Low Priority) - -G-6, G-7, G-8, G-9, G-10, G-11, G-12, G-14, G-17, G-18, G-19 - ---- - -## Architecture Approach - -**Key principle**: These are all _wiring gaps_, not architectural problems. The backend infrastructure (IPC channels, services, hooks) already exists. Each gap needs a UI component or connection layer added. - -**No new IPC channels needed.** All channels exist in `ipc-contract.ts`. -**No new services needed.** All services are implemented. -**No new types needed.** All types are defined. - ---- - -## Phase 1: Shared Infrastructure (No Blockers) - -### Task 1.1: Create ConfirmDialog Component - -**Agent**: component-engineer -**Files to Create**: -- `src/renderer/shared/components/ConfirmDialog.tsx` - -**Files to Read**: -- `src/renderer/features/merge/components/MergeConfirmModal.tsx` (existing pattern) -- Radix UI AlertDialog documentation - -**Specification**: -```typescript -interface ConfirmDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - title: string; - description: string; - confirmLabel?: string; // default: "Delete" - cancelLabel?: string; // default: "Cancel" - variant?: 'destructive' | 'default'; - onConfirm: () => void; - loading?: boolean; -} -``` - -- Use Radix UI `AlertDialog` primitives (already in deps) -- Destructive variant: red confirm button -- Default variant: primary confirm button -- Focus trap, Escape to close, overlay click to close -- Accessible: proper ARIA roles, focus management - -**Acceptance Criteria**: -- [ ] Component renders with title, description, two buttons -- [ ] `onConfirm` only fires when user clicks confirm -- [ ] Escape / overlay click closes without confirming -- [ ] Destructive variant shows red button -- [ ] Loading state disables buttons + shows spinner -- [ ] Passes lint, typecheck, build - ---- - -## Phase 2: Auth Hardening (No Blockers, Parallel with Phase 1) - -### Task 2.1: Proactive Token Refresh (G-5) - -**Agent**: hook-engineer -**Files to Create**: -- `src/renderer/features/auth/hooks/useTokenRefresh.ts` - -**Files to Modify**: -- `src/renderer/features/auth/store.ts` — Add `expiresAt` field -- `src/renderer/features/auth/api/useAuth.ts` — Store `expiresAt` on login/refresh -- `src/renderer/features/auth/components/AuthGuard.tsx` — Call `useTokenRefresh()` - -**Specification**: -- On login/register response: store `expiresAt = Date.now() + (expiresIn * 1000)` in auth store -- `useTokenRefresh()` hook: - - Runs a `setTimeout` that fires 2 minutes before `expiresAt` - - Calls `useRefreshToken().mutate()` on timer - - On refresh success: update `expiresAt` with new value, reschedule timer - - On refresh failure: `clearAuth()` + redirect to login - - Cleanup on unmount (clear timeout) -- Call `useTokenRefresh()` in `AuthGuard` (runs for all authenticated pages) - -**Acceptance Criteria**: -- [ ] `expiresAt` stored in auth store on login -- [ ] Timer fires before token expires -- [ ] Successful refresh extends the timer -- [ ] Failed refresh logs out the user -- [ ] Timer cleaned up on logout/unmount -- [ ] Passes lint, typecheck, build - -### Task 2.2: Logout Button + User Menu (G-1) - -**Agent**: component-engineer -**Depends on**: Task 2.1 (auth store changes) -**Files to Create**: -- `src/renderer/app/layouts/UserMenu.tsx` - -**Files to Modify**: -- `src/renderer/app/layouts/Sidebar.tsx` — Add UserMenu above footer - -**Specification**: -- `UserMenu` component placed in Sidebar footer, above HubConnectionIndicator -- Shows user avatar (initials fallback) + display name (when expanded) -- Collapsed sidebar: avatar only -- Click opens dropdown with: - - User display name + email (header) - - "Log out" button (destructive, with `LogOut` icon) -- On logout click: call `useLogout().mutate()` -- `useLogout()` already clears auth store + query cache -- After logout: TanStack Router `redirect()` to `/login` - -**Acceptance Criteria**: -- [ ] Avatar + name visible in sidebar footer -- [ ] Dropdown opens on click -- [ ] Logout clears auth and redirects to login -- [ ] Works in both expanded and collapsed sidebar -- [ ] Keyboard accessible (Enter/Space to open, Escape to close) -- [ ] Passes lint, typecheck, build - ---- - -## Phase 3: Task Dashboard Completion (Depends on Phase 1) - -### Task 3.1: Create Task Dialog (G-2) - -**Agent**: component-engineer -**Depends on**: Task 1.1 (ConfirmDialog pattern reference, not direct dep) -**Files to Create**: -- `src/renderer/features/tasks/components/CreateTaskDialog.tsx` - -**Files to Modify**: -- `src/renderer/features/tasks/components/TaskFiltersToolbar.tsx` — Add "New Task" button -- `src/renderer/features/tasks/store.ts` — Add `createDialogOpen` state - -**Specification**: -- "New Task" button added to TaskFiltersToolbar (left of search, primary style) -- Button click opens dialog (Radix Dialog) -- Dialog form fields: - - Title (required, text input) - - Description (optional, textarea, 3 rows) - - Priority (optional, select: low/normal/high/urgent, default: normal) -- Submit calls `useCreateTask().mutate({ projectId, title, description, priority })` -- `projectId` from `useLayoutStore().activeProjectId` -- On success: close dialog, show success (task appears in grid via query invalidation) -- On error: show error message in dialog -- Keyboard: Enter submits (when not in textarea), Escape closes - -**Acceptance Criteria**: -- [ ] "New Task" button visible in toolbar -- [ ] Dialog opens with form fields -- [ ] Title validation (required, non-empty) -- [ ] Successful creation closes dialog + task appears in grid -- [ ] Error state shows message in dialog -- [ ] Keyboard accessible -- [ ] Passes lint, typecheck, build - -### Task 3.2: Consolidate Duplicate Task Handlers (G-3) - -**Agent**: service-engineer -**Files to Modify**: -- `src/main/ipc/handlers/hub-handlers.ts` — Remove `hub.tasks.*` channel registrations -- `src/main/ipc/index.ts` — Verify registration order - -**Files to Read**: -- `src/main/ipc/handlers/task-handlers.ts` — The authoritative handler file -- `src/main/ipc/handlers/hub-handlers.ts` — Find duplicates to remove - -**Specification**: -- `task-handlers.ts` is the authoritative source for ALL task channels (`hub.tasks.*` and `tasks.*`) -- Remove ALL `hub.tasks.*` handler registrations from `hub-handlers.ts` -- Keep non-task Hub handlers in `hub-handlers.ts` (connection, sync, config, auth, etc.) -- Verify `task-handlers.ts` is registered AFTER `hub-handlers.ts` in `index.ts` (or order doesn't matter after dedup) -- Run tests to confirm no breakage - -**Acceptance Criteria**: -- [ ] `hub-handlers.ts` has zero `hub.tasks.*` registrations -- [ ] `task-handlers.ts` is the single source for all task channels -- [ ] All existing task IPC calls still work -- [ ] All task-related tests pass -- [ ] Passes lint, typecheck, test, build - ---- - -## Phase 4: Project & Hub Polish (Depends on Phase 1) - -### Task 4.1: Project Edit Page (G-15) - -**Agent**: component-engineer -**Depends on**: Task 1.1 (uses ConfirmDialog for delete) -**Files to Create**: -- `src/renderer/features/projects/components/ProjectEditDialog.tsx` - -**Files to Modify**: -- `src/renderer/features/projects/components/ProjectListPage.tsx` — Add edit button per project - -**Specification**: -- Each project card in `ProjectListPage` gets an "Edit" icon button (Pencil icon) -- Click opens `ProjectEditDialog` (Radix Dialog) -- Dialog form fields (pre-filled from project data): - - Name (text input, required) - - Description (textarea, optional) - - Default Branch (text input, optional) - - Git URL (text input, optional) -- Save calls `useUpdateProject().mutate({ projectId, ...fields })` -- Delete button at bottom of dialog opens ConfirmDialog - - On confirm: calls `useRemoveProject().mutate({ projectId })` - - On success: close both dialogs, project removed from list -- On save success: close dialog, project list refreshes - -**Acceptance Criteria**: -- [ ] Edit button visible on project cards -- [ ] Dialog pre-fills current project data -- [ ] Save updates project via IPC -- [ ] Delete with confirmation removes project -- [ ] All fields optional except name -- [ ] Passes lint, typecheck, build - -### Task 4.2: Delete Confirmation Wiring (G-16) - -**Agent**: component-engineer -**Depends on**: Task 1.1 (ConfirmDialog component) -**Files to Modify**: -- `src/renderer/features/tasks/components/detail/TaskControls.tsx` — Wrap delete in confirm -- `src/renderer/features/tasks/components/cells/ActionsCell.tsx` — Wrap delete in confirm - -**Specification**: -- Task delete (both in detail panel and grid actions) now shows ConfirmDialog first -- Title: "Delete Task" -- Description: "Are you sure you want to delete '{task.title}'? This action cannot be undone." -- Variant: destructive -- On confirm: call existing `useDeleteTask().mutate()` -- Loading state while mutation is pending -- Sub-project delete (if UI exists) also uses ConfirmDialog - -**Acceptance Criteria**: -- [ ] Clicking delete shows confirmation dialog -- [ ] Task only deleted after user confirms -- [ ] Escape/cancel closes without deleting -- [ ] Loading spinner during deletion -- [ ] Works in both grid action cell and detail panel -- [ ] Passes lint, typecheck, build - -### Task 4.3: Hub Disconnect Error Handling (G-4) - -**Agent**: hook-engineer -**Files to Create**: -- `src/renderer/shared/hooks/useMutationErrorToast.ts` - -**Files to Modify**: -- `src/renderer/features/tasks/api/useTaskMutations.ts` — Add `onError` to all mutations -- `src/renderer/features/projects/api/useProjects.ts` — Add `onError` to mutations - -**Specification**: -- Create `useMutationErrorToast()` custom hook: - - Returns an `onError` callback factory - - Shows toast notification via existing notification system or simple toast state - - Message format: "Failed to {action}: {error.message}" - - Auto-dismiss after 5 seconds -- Wire into all task mutations: - - `useCreateTask` → "Failed to create task" - - `useUpdateTaskStatus` → "Failed to update task status" - - `useDeleteTask` → "Failed to delete task" - - `useExecuteTask` → "Failed to execute task" - - `useCancelTask` → "Failed to cancel task" -- Wire into project mutations: - - `useRemoveProject` → "Failed to remove project" - - `useUpdateProject` → "Failed to update project" - -**Acceptance Criteria**: -- [ ] All task/project mutations have `onError` handlers -- [ ] Error toast visible when mutation fails -- [ ] Toast auto-dismisses after 5 seconds -- [ ] Error message includes the action that failed -- [ ] No console-only errors for user-facing operations -- [ ] Passes lint, typecheck, build - ---- - -## Dependency Graph - -``` -Phase 1 Phase 2 Phase 3 Phase 4 -──────── ──────── ──────── ──────── -Task 1.1 Task 2.1 Task 3.1 Task 4.1 -ConfirmDialog ─────┐ Token Refresh Create Task Dialog Project Edit ◀── 1.1 - │ │ │ │ - │ Task 2.2 ◀── 2.1 Task 3.2 Task 4.2 ◀── 1.1 - │ User Menu Dedup Handlers Delete Confirms - │ │ - └──────────────────────────────────────────────────────────── Task 4.3 - Error Toasts -``` - -**Parallel opportunities:** -- Phase 1 and Phase 2 run simultaneously (no shared files) -- Tasks 3.1 + 3.2 can run in parallel (different files) -- Tasks 4.1 + 4.2 + 4.3 can run in parallel (different files) - ---- - -## Wave Execution Plan - -| Wave | Tasks | Agents | Est. Time | -|------|-------|--------|-----------| -| 1 | 1.1 (ConfirmDialog) + 2.1 (Token Refresh) | 2 parallel | ~1 hour | -| 2 | 2.2 (User Menu) + 3.1 (Create Task) + 3.2 (Dedup Handlers) | 3 parallel | ~1 hour | -| 3 | 4.1 (Project Edit) + 4.2 (Delete Confirms) + 4.3 (Error Toasts) | 3 parallel | ~1 hour | -| 4 | Documentation update + Integration test | 1 agent | ~30 min | - ---- - -## Files Summary - -### Files to Create (5 new) -1. `src/renderer/shared/components/ConfirmDialog.tsx` -2. `src/renderer/features/auth/hooks/useTokenRefresh.ts` -3. `src/renderer/app/layouts/UserMenu.tsx` -4. `src/renderer/features/tasks/components/CreateTaskDialog.tsx` -5. `src/renderer/features/projects/components/ProjectEditDialog.tsx` -6. `src/renderer/shared/hooks/useMutationErrorToast.ts` - -### Files to Modify (9 existing) -1. `src/renderer/features/auth/store.ts` — Add `expiresAt` -2. `src/renderer/features/auth/api/useAuth.ts` — Store expiry on login -3. `src/renderer/features/auth/components/AuthGuard.tsx` — Call `useTokenRefresh()` -4. `src/renderer/app/layouts/Sidebar.tsx` — Add UserMenu -5. `src/renderer/features/tasks/components/TaskFiltersToolbar.tsx` — Add "New Task" button -6. `src/renderer/features/tasks/store.ts` — Add dialog state -7. `src/main/ipc/handlers/hub-handlers.ts` — Remove duplicate task handlers -8. `src/renderer/features/tasks/api/useTaskMutations.ts` — Add `onError` -9. `src/renderer/features/projects/api/useProjects.ts` — Add `onError` -10. `src/renderer/features/projects/components/ProjectListPage.tsx` — Add edit button -11. `src/renderer/features/tasks/components/detail/TaskControls.tsx` — Wrap delete -12. `src/renderer/features/tasks/components/cells/ActionsCell.tsx` — Wrap delete - -### No Changes Needed -- `src/shared/ipc-contract.ts` — All channels already exist -- `src/shared/types/` — All types already defined -- `src/main/services/` — All services already implemented -- Hub backend — No backend changes - ---- - -## Test Gate - -After ALL tasks complete: -```bash -npm run lint # Zero violations -npm run typecheck # Zero errors -npm run test # All tests pass -npm run build # Builds successfully -``` - -## Post-Implementation - -1. Update `ai-docs/user-interface-flow.md` — Mark gaps as RESOLVED -2. Update `ai-docs/ARCHITECTURE.md` if new patterns introduced -3. Commit, push, create PR diff --git a/doc-history/plans/2026-02-15-task-dashboard-full-refactor.md b/doc-history/plans/2026-02-15-task-dashboard-full-refactor.md deleted file mode 100644 index eb3ad29..0000000 --- a/doc-history/plans/2026-02-15-task-dashboard-full-refactor.md +++ /dev/null @@ -1,571 +0,0 @@ -# Task Dashboard Full Refactor — Design & Implementation Plan - -> Tracker Key: `task-dashboard-full-refactor` | Status: **IMPLEMENTED** | Created: 2026-02-15 - -**Scope**: Full platform refactor — AG-Grid table, auth, workspaces, devices, Hub-first execution, progress watchers -**Dependencies**: AG-Grid Community v35.1.0 (evaluated at `docs/research/2026-02-14-ag-grid-evaluation.md`) - ---- - -## Design Decisions (Confirmed) - -| Decision | Choice | -|----------|--------| -| Auth model | Full user auth (email/password, JWT, refresh tokens) | -| Task execution | Hub dispatches to workspace host device | -| Progress tracking | File-based: `.claude/progress///` watched by chokidar | -| Row interaction | Expandable rows (DIY master/detail, full-width detail renderer) | -| Table library | AG-Grid Community (MIT, free) | -| Columns | Status, Title, Project, Workspace, Agent, Progress, Activity sparkline, PR Status, Cost, Updated, Priority, Actions | - ---- - -## Architecture Overview - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ ANY DEVICE (Client) │ -│ │ -│ AG-Grid Task Table ← WebSocket ← Hub broadcasts │ -│ ├── Custom cell renderers (progress, sparkline, status, agent) │ -│ ├── Expandable detail rows (subtasks, logs, PR, controls) │ -│ ├── applyTransactionAsync() for live streaming updates │ -│ └── Auth context (JWT in memory, refresh token in httpOnly cookie) │ -│ │ -│ User clicks "Run" → API call → Hub │ -└─────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────┐ -│ HUB SERVER │ -│ │ -│ Auth: JWT issue/verify/refresh, bcrypt passwords, sessions table │ -│ API: /auth/*, /workspaces/*, /projects/*, /tasks/*, /devices/* │ -│ WS: Broadcast task updates to all authenticated clients │ -│ DB: SQLite with migration versioning │ -│ Dispatch: Route "execute" commands to workspace host device │ -└─────────────────────────────────────────────────────────────────────┘ - │ - ▼ -┌─────────────────────────────────────────────────────────────────────┐ -│ WORKSPACE HOST (Desktop App) │ -│ │ -│ Task Launcher: Receives dispatch → spawns `claude` CLI process │ -│ Progress Watcher: chokidar watches .claude/progress/**/* │ -│ Progress Parser: Reads YAML frontmatter + markdown body │ -│ Progress Syncer: Pushes parsed updates to Hub via API │ -│ Device Heartbeat: Pings Hub every 30s with online status │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## Data Model - -### Hub Database Schema (New/Modified Tables) - -```sql --- New: User accounts -CREATE TABLE users ( - id TEXT PRIMARY KEY, - email TEXT UNIQUE NOT NULL, - password_hash TEXT NOT NULL, - display_name TEXT NOT NULL, - avatar_url TEXT, - settings TEXT DEFAULT '{}', - created_at TEXT NOT NULL DEFAULT (datetime('now')), - last_login_at TEXT -); - --- New: Auth sessions (JWT refresh tokens) -CREATE TABLE sessions ( - id TEXT PRIMARY KEY, - user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - refresh_token_hash TEXT NOT NULL, - device_id TEXT REFERENCES devices(id), - expires_at TEXT NOT NULL, - created_at TEXT NOT NULL DEFAULT (datetime('now')) -); - --- New: Physical devices -CREATE TABLE devices ( - id TEXT PRIMARY KEY, - user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - machine_id TEXT NOT NULL, - device_name TEXT NOT NULL, - device_type TEXT NOT NULL DEFAULT 'desktop', -- desktop | laptop | phone | tablet - capabilities TEXT DEFAULT '{}', -- { canExecute: true, hasClaude: true } - is_online INTEGER DEFAULT 0, - last_seen TEXT, - app_version TEXT, - created_at TEXT NOT NULL DEFAULT (datetime('now')) -); - --- New: Logical workspaces -CREATE TABLE workspaces ( - id TEXT PRIMARY KEY, - user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, - name TEXT NOT NULL, - description TEXT, - host_device_id TEXT REFERENCES devices(id), - settings TEXT DEFAULT '{}', - created_at TEXT NOT NULL DEFAULT (datetime('now')), - updated_at TEXT NOT NULL DEFAULT (datetime('now')) -); - --- Modified: Projects (now workspace-scoped) -CREATE TABLE projects ( - id TEXT PRIMARY KEY, - workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, - name TEXT NOT NULL, - description TEXT, - root_path TEXT NOT NULL, - git_url TEXT, - repo_structure TEXT DEFAULT 'single', -- single | monorepo | multi-repo - default_branch TEXT DEFAULT 'main', - settings TEXT DEFAULT '{}', - created_at TEXT NOT NULL DEFAULT (datetime('now')), - updated_at TEXT NOT NULL DEFAULT (datetime('now')) -); - --- New: Sub-projects (for monorepo/multi-repo) -CREATE TABLE sub_projects ( - id TEXT PRIMARY KEY, - project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, - name TEXT NOT NULL, - relative_path TEXT NOT NULL, - git_url TEXT, - default_branch TEXT DEFAULT 'main' -); - --- Modified: Tasks (workspace-aware, enhanced tracking) -CREATE TABLE tasks ( - id TEXT PRIMARY KEY, - project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, - workspace_id TEXT NOT NULL REFERENCES workspaces(id), - sub_project_id TEXT REFERENCES sub_projects(id), - title TEXT NOT NULL, - description TEXT, - status TEXT NOT NULL DEFAULT 'backlog', - priority TEXT NOT NULL DEFAULT 'medium', -- low | medium | high | critical - agent_name TEXT, - progress INTEGER DEFAULT 0, - phase TEXT DEFAULT 'idle', - activity_history TEXT DEFAULT '[]', -- JSON array of recent progress snapshots - cost_tokens INTEGER DEFAULT 0, - cost_usd REAL DEFAULT 0.0, - pr_number INTEGER, - pr_state TEXT, -- open | closed | merged - pr_ci_status TEXT, -- pending | success | failure - pr_url TEXT, - metadata TEXT DEFAULT '{}', - created_at TEXT NOT NULL DEFAULT (datetime('now')), - updated_at TEXT NOT NULL DEFAULT (datetime('now')), - completed_at TEXT -); - --- New: Task execution sessions -CREATE TABLE task_sessions ( - id TEXT PRIMARY KEY, - task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE, - device_id TEXT NOT NULL REFERENCES devices(id), - pid INTEGER, - status TEXT NOT NULL DEFAULT 'running', -- running | completed | failed | cancelled - started_at TEXT NOT NULL DEFAULT (datetime('now')), - ended_at TEXT, - token_usage INTEGER DEFAULT 0, - cost_usd REAL DEFAULT 0.0, - error_message TEXT -); -``` - -### Progress File Format - -```yaml ---- -task_id: abc-123 -phase: coding -progress: 45 -status: in_progress -agent: claude-opus -subtask: "Implementing user service" -tokens_used: 12500 -cost_usd: 0.38 ---- - -## Current Activity -Working on user registration endpoint. Password hashing with bcrypt. - -## Completed -- [x] Database schema migration -- [x] User model types - -## Next -- [ ] Login endpoint -- [ ] JWT token generation -``` - ---- - -## AG-Grid Table Design - -### Column Definitions - -| Column | Field | Width | Cell Renderer | Sortable | Filterable | -|--------|-------|-------|---------------|----------|------------| -| ▶ | (expand toggle) | 40px | ExpandToggleCell | No | No | -| Status | `status` | 130px | StatusBadgeCell | Yes | Multi-select | -| Title | `title` | flex | TitleCell (truncated, bold) | Yes | Text search | -| Project | `project.name` | 150px | Text | Yes | Multi-select | -| Workspace | `workspace.name` | 130px | WorkspaceCell (with online dot) | Yes | Multi-select | -| Agent | `agent_name` | 140px | AgentCell (avatar + name) | Yes | Multi-select | -| Progress | `progress` | 180px | ProgressBarCell (bar + phase label) | Yes | No | -| Activity | `activity_history` | 150px | ActivitySparklineCell (SVG) | No | No | -| Priority | `priority` | 100px | PriorityCell (icon + label) | Yes | Multi-select | -| PR | `pr_state` | 100px | PRStatusCell (badge + CI dot) | Yes | Multi-select | -| Cost | `cost_usd` | 90px | CostCell (formatted $X.XX) | Yes | No | -| Updated | `updated_at` | 110px | RelativeTimeCell ("2m ago") | Yes | No | -| Actions | — | 120px | ActionsCell (Run/Stop/Delete) | No | No | - -### Expandable Detail Row (DIY Master/Detail) - -When a row is expanded, a full-width detail row renders below it containing: - -``` -┌─────────────────────────────────────────────────────────────────────────┐ -│ ┌──────────────┐ ┌──────────────────────────────┐ ┌────────────────┐ │ -│ │ Subtasks │ │ Execution Log (scrollable) │ │ PR Status │ │ -│ │ ☑ Schema │ │ > Planning phase complete │ │ #42 Open │ │ -│ │ ☑ Types │ │ > Coding: user-service.ts │ │ CI: ✓ passing │ │ -│ │ ◻ Endpoints │ │ > Test: 3/5 passing │ │ Reviews: 0 │ │ -│ │ ◻ Tests │ │ > ... │ │ [View PR →] │ │ -│ └──────────────┘ └──────────────────────────────┘ └────────────────┘ │ -│ │ -│ ┌──────────────────────────────────────────────────────────────────┐ │ -│ │ Controls: [Pause] [Stop] [Retry] [Assign Agent ▼] [Delete] │ │ -│ └──────────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────────┘ -``` - -### Real-Time Update Flow - -```typescript -// 1. Progress watcher detects file change -chokidar.watch('.claude/progress/**/*.md') - -// 2. Parser extracts YAML frontmatter -const { taskId, phase, progress, status, tokens, cost } = parseProgress(content) - -// 3. Syncer pushes to Hub -await hubApi.post(`/tasks/${taskId}/progress`, { phase, progress, tokens, cost }) - -// 4. Hub broadcasts via WebSocket -ws.broadcast({ type: 'task:progress', taskId, data: { phase, progress, ... } }) - -// 5. Client receives, updates AG-Grid -gridApi.applyTransactionAsync({ update: [{ id: taskId, progress, phase, ... }] }) -``` - ---- - -## Implementation Phases - -### Phase 1: Auth & Database Foundation -**Scope**: User registration/login, JWT auth, database migrations, Hub API updates -**Effort**: ~8 hours - -#### Tasks -1. **Hub migration system** — Create `migration-runner.ts`, move schema to `migrations/001_initial.sql` -2. **Auth schema** — Migration `002_auth.sql`: users, sessions tables -3. **Auth service** — `hub/src/services/auth-service.ts`: register, login, verify, refresh -4. **Auth routes** — `hub/src/routes/auth.ts`: POST /register, /login, /logout, /refresh, GET /me -5. **Auth middleware** — JWT verification middleware for all protected routes -6. **Login UI** — `src/renderer/features/auth/components/LoginPage.tsx`: email/password form -7. **Auth context** — JWT storage in memory, refresh token handling, auth state in Zustand -8. **Protected routes** — Redirect to login if not authenticated - -#### Files -``` -CREATE hub/src/db/migration-runner.ts -CREATE hub/src/db/migrations/001_initial_schema.sql -CREATE hub/src/db/migrations/002_auth.sql -CREATE hub/src/services/auth-service.ts -MODIFY hub/src/routes/auth.ts (rewrite for user auth) -CREATE hub/src/middleware/auth-middleware.ts -CREATE src/renderer/features/auth/components/LoginPage.tsx -CREATE src/renderer/features/auth/components/RegisterPage.tsx -CREATE src/renderer/features/auth/store.ts -CREATE src/renderer/features/auth/api/useAuth.ts -MODIFY src/renderer/app/router.tsx (add auth routes, guards) -MODIFY src/shared/ipc-contract.ts (auth channels) -``` - ---- - -### Phase 2: Devices & Workspaces -**Scope**: Device registration, workspace CRUD, heartbeat system -**Effort**: ~8 hours - -#### Tasks -1. **Schema migration** — `003_devices_workspaces.sql`: devices, workspaces tables -2. **Device service** — `src/main/services/device/device-service.ts`: register device, generate machine ID, heartbeat -3. **Workspace service** — `src/main/services/workspace/workspace-service.ts`: CRUD, host assignment -4. **Hub API routes** — `/api/devices/*`, `/api/workspaces/*` -5. **Device heartbeat** — 30s interval ping to Hub with online status -6. **Workspace settings UI** — `WorkspacesTab.tsx` in Settings page -7. **First-run flow update** — After auth, prompt to name workspace + add first project - -#### Files -``` -CREATE hub/src/db/migrations/003_devices_workspaces.sql -CREATE hub/src/routes/devices.ts -CREATE hub/src/routes/workspaces.ts -CREATE hub/src/services/device-service.ts -CREATE hub/src/services/workspace-service.ts -CREATE src/main/services/device/device-service.ts -CREATE src/main/services/device/heartbeat.ts -CREATE src/main/services/workspace/workspace-service.ts -CREATE src/main/ipc/handlers/device-handlers.ts -CREATE src/main/ipc/handlers/workspace-handlers.ts -CREATE src/renderer/features/settings/components/WorkspacesTab.tsx -CREATE src/renderer/features/settings/components/WorkspaceCard.tsx -MODIFY src/renderer/features/onboarding/ (workspace setup step) -MODIFY src/shared/ipc-contract.ts -MODIFY src/shared/types/ (device, workspace types) -``` - ---- - -### Phase 3: Project Enhancements (Multi-Repo) -**Scope**: Project model upgrade, sub-project support, repo detection -**Effort**: ~6 hours - -#### Tasks -1. **Schema migration** — `004_projects_enhanced.sql`: update projects table, add sub_projects -2. **Project service update** — Detect repo structure (single/monorepo/multi-repo), manage sub-projects -3. **Hub API routes** — Enhanced `/api/projects/*`, `/api/projects/:id/sub-projects` -4. **Project init wizard** — Multi-step: select folder → detect git → choose structure → confirm sub-projects -5. **Sub-project selector** — Dropdown in task creation for targeting specific sub-repo - -#### Files -``` -CREATE hub/src/db/migrations/004_projects_enhanced.sql -MODIFY hub/src/routes/projects.ts -CREATE hub/src/services/project-service.ts (Hub-side) -MODIFY src/main/services/project/project-service.ts (detection logic) -CREATE src/renderer/features/projects/components/ProjectInitWizard.tsx -CREATE src/renderer/features/projects/components/RepoTypeSelector.tsx -CREATE src/renderer/features/projects/components/SubProjectSelector.tsx -MODIFY src/shared/types/project.ts -MODIFY src/shared/ipc-contract.ts -``` - ---- - -### Phase 4: AG-Grid Task Table -**Scope**: Replace hand-built TaskTable with AG-Grid, custom cell renderers, expandable detail rows -**Effort**: ~10 hours - -#### Tasks -1. **Install AG-Grid** — `ag-grid-community` + `ag-grid-react` v35.1.0 -2. **Module registration** — Selective imports for tree shaking -3. **AG-Grid theme** — Custom CSS theme using CSS custom properties (matches Tailwind v4 theme vars) -4. **Custom cell renderers** — StatusBadgeCell, ProgressBarCell, ActivitySparklineCell, AgentCell, PRStatusCell, CostCell, PriorityCell, ActionsCell, ExpandToggleCell, RelativeTimeCell, WorkspaceCell, TitleCell -5. **TaskDataGrid component** — Main AG-Grid wrapper with column definitions, getRowId, event handlers -6. **Expandable detail row** — Full-width row renderer with subtasks, logs, PR status, controls -7. **Task filters toolbar** — Search, status multi-select, workspace filter, project filter, priority filter, saved views -8. **Task creation** — Quick-create row or modal with project/sub-project/priority selection -9. **Bulk actions** — Multi-row select with bulk status change, bulk delete, bulk assign -10. **Remove old TaskTable** — Delete TaskTable, TaskTableRow, TaskTableHeader, TaskTableFilters - -#### Files -``` -npm install ag-grid-community@^35.1.0 ag-grid-react@^35.1.0 - -CREATE src/renderer/features/tasks/components/grid/TaskDataGrid.tsx -CREATE src/renderer/features/tasks/components/grid/ag-grid-modules.ts -CREATE src/renderer/features/tasks/components/grid/ag-grid-theme.css -CREATE src/renderer/features/tasks/components/cells/StatusBadgeCell.tsx -CREATE src/renderer/features/tasks/components/cells/ProgressBarCell.tsx -CREATE src/renderer/features/tasks/components/cells/ActivitySparklineCell.tsx -CREATE src/renderer/features/tasks/components/cells/AgentCell.tsx -CREATE src/renderer/features/tasks/components/cells/PRStatusCell.tsx -CREATE src/renderer/features/tasks/components/cells/CostCell.tsx -CREATE src/renderer/features/tasks/components/cells/PriorityCell.tsx -CREATE src/renderer/features/tasks/components/cells/ActionsCell.tsx -CREATE src/renderer/features/tasks/components/cells/ExpandToggleCell.tsx -CREATE src/renderer/features/tasks/components/cells/WorkspaceCell.tsx -CREATE src/renderer/features/tasks/components/cells/TitleCell.tsx -CREATE src/renderer/features/tasks/components/cells/RelativeTimeCell.tsx -CREATE src/renderer/features/tasks/components/detail/TaskDetailRow.tsx -CREATE src/renderer/features/tasks/components/detail/SubtaskList.tsx -CREATE src/renderer/features/tasks/components/detail/ExecutionLog.tsx -CREATE src/renderer/features/tasks/components/detail/PRStatusPanel.tsx -CREATE src/renderer/features/tasks/components/detail/TaskControls.tsx -CREATE src/renderer/features/tasks/components/TaskFiltersToolbar.tsx -CREATE src/renderer/features/tasks/components/TaskQuickCreate.tsx -DELETE src/renderer/features/tasks/components/TaskTable.tsx -DELETE src/renderer/features/tasks/components/TaskTableRow.tsx -DELETE src/renderer/features/tasks/components/TaskTableHeader.tsx -DELETE src/renderer/features/tasks/components/TaskTableFilters.tsx -MODIFY src/renderer/features/tasks/store.ts (add grid state, expanded rows) -MODIFY src/renderer/features/tasks/api/useTasks.ts (return data shaped for AG-Grid) -MODIFY src/renderer/features/tasks/hooks/useTaskEvents.ts (use gridApi.applyTransactionAsync) -MODIFY src/renderer/features/tasks/index.ts (update exports) -MODIFY src/renderer/app/router.tsx (TaskDataGrid as route component) -MODIFY src/renderer/styles/globals.css (AG-Grid theme overrides) -``` - ---- - -### Phase 5: Hub-First Task Operations -**Scope**: Migrate all task CRUD to Hub API, update IPC layer, enhanced task schema -**Effort**: ~6 hours - -#### Tasks -1. **Schema migration** — `005_tasks_enhanced.sql`: add workspace_id, sub_project_id, priority, activity_history, cost fields, PR fields -2. **Hub task routes update** — Full CRUD with workspace/project filtering, pagination, sorting -3. **Hub task progress endpoint** — `POST /tasks/:id/progress` for progress watcher updates -4. **IPC contract update** — All task channels point to Hub, remove local-only task channels -5. **React Query hooks update** — Point to Hub channels, add workspace/project filtering params -6. **WebSocket task events** — Hub broadcasts create/update/delete/progress to all clients - -#### Files -``` -CREATE hub/src/db/migrations/005_tasks_enhanced.sql -MODIFY hub/src/routes/tasks.ts (enhanced CRUD + progress endpoint) -MODIFY src/shared/ipc-contract.ts (consolidate task channels) -MODIFY src/renderer/features/tasks/api/useTasks.ts -MODIFY src/renderer/features/tasks/api/useTaskMutations.ts -MODIFY src/renderer/features/tasks/hooks/useTaskEvents.ts -``` - ---- - -### Phase 6: Progress Watcher & Task Launcher -**Scope**: File-based progress watching, parsing, Hub sync, task execution dispatch -**Effort**: ~8 hours - -#### Tasks -1. **Progress watcher** — `src/main/services/workflow/progress-watcher.ts`: chokidar watches `.claude/progress/**/*.md` -2. **Progress parser** — `src/main/services/workflow/progress-parser.ts`: YAML frontmatter extraction -3. **Progress syncer** — `src/main/services/workflow/progress-syncer.ts`: pushes parsed data to Hub API -4. **Task launcher** — `src/main/services/workflow/task-launcher.ts`: receives dispatch from Hub, spawns `claude` CLI with task spec -5. **Hub dispatch system** — Hub receives "execute" request, routes to workspace host via WebSocket -6. **Execution session tracking** — Track spawned processes, handle completion/failure/cancellation -7. **Cost tracking integration** — Parse token usage from Claude CLI output, include in progress updates - -#### Files -``` -CREATE src/main/services/workflow/progress-watcher.ts -CREATE src/main/services/workflow/progress-parser.ts -CREATE src/main/services/workflow/progress-syncer.ts -CREATE src/main/services/workflow/task-launcher.ts -CREATE src/main/ipc/handlers/workflow-handlers.ts -MODIFY hub/src/ws/broadcaster.ts (add dispatch routing) -CREATE hub/src/services/dispatch-service.ts -MODIFY src/shared/ipc-contract.ts (workflow channels) -MODIFY src/shared/types/task.ts (progress file types) -``` - ---- - -### Phase 7: Cleanup & Polish -**Scope**: Remove dead code, update all docs, final integration testing -**Effort**: ~4 hours - -#### Tasks -1. **Remove dead code** — Delete old agent-service.ts (PTY spawner), agent-queue.ts, token-parser.ts -2. **Remove unused IPC channels** — Clean up local-only task channels that are now Hub-only -3. **Update all documentation** — FEATURES-INDEX, ARCHITECTURE, DATA-FLOW, PROGRESS -4. **P5 polish items** — Hub connection indicator, background settings wiring (from P5 plan) -5. **Test suite updates** — Update unit/integration tests for new services and handlers - -#### Files -``` -DELETE src/main/services/agent/agent-service.ts (if PTY-based) -DELETE src/main/services/agent/agent-queue.ts (if exists) -DELETE src/main/services/agent/token-parser.ts (if exists) -MODIFY ai-docs/FEATURES-INDEX.md -MODIFY ai-docs/ARCHITECTURE.md -MODIFY ai-docs/DATA-FLOW.md -MODIFY doc-history/PROGRESS.md -CREATE tests/unit/services/workflow/*.test.ts -CREATE tests/integration/ipc-handlers/workflow-handlers.test.ts -``` - ---- - -## Phase Dependency Graph - -``` -Phase 1 (Auth + DB) ──────────────────┐ - │ -Phase 2 (Devices + Workspaces) ────────┤ (depends on Phase 1 auth) - │ -Phase 3 (Projects Enhanced) ───────────┤ (depends on Phase 2 workspaces) - │ -Phase 4 (AG-Grid Table) ──────────────┤ (can start after Phase 1, parallel with 2-3) - │ -Phase 5 (Hub-First Tasks) ────────────┤ (depends on Phases 2, 3, 4) - │ -Phase 6 (Progress Watcher + Launcher) ─┤ (depends on Phase 5) - │ -Phase 7 (Cleanup + Polish) ────────────┘ (depends on all above) -``` - -**Parallelization opportunities:** -- Phase 4 (AG-Grid) can run in parallel with Phases 2-3 (they touch different files) -- Phase 1 must complete first (everything depends on auth + migrations) - ---- - -## Estimated Total Effort - -| Phase | Effort | Parallel Group | -|-------|--------|----------------| -| 1. Auth & DB | ~8 hrs | Sequential (first) | -| 2. Devices & Workspaces | ~8 hrs | Group A | -| 3. Projects Enhanced | ~6 hrs | Group A | -| 4. AG-Grid Table | ~10 hrs | Group B (parallel with A) | -| 5. Hub-First Tasks | ~6 hrs | Sequential (after A+B) | -| 6. Progress Watcher | ~8 hrs | Sequential (after 5) | -| 7. Cleanup & Polish | ~4 hrs | Sequential (last) | -| **Total** | **~50 hrs** | **~35 hrs with parallelization** | - ---- - -## Success Criteria - -- [ ] User can register and login from any device -- [ ] Workspaces and devices are registered and show online/offline status -- [ ] Projects support single/monorepo/multi-repo structures -- [ ] AG-Grid task table with all 12 columns and custom cell renderers -- [ ] Expandable detail rows with subtasks, logs, PR status, controls -- [ ] Live streaming updates via WebSocket → AG-Grid applyTransactionAsync -- [ ] Click "Run" from any device → Hub dispatches to workspace host -- [ ] Workspace host spawns Claude CLI, writes progress files -- [ ] Progress watcher detects changes, parses, syncs to Hub -- [ ] All devices see real-time progress (bar, phase, sparkline, cost) -- [ ] PR status tracked and displayed per task -- [ ] Token/cost tracking per task execution -- [ ] Zero kanban code remaining -- [ ] Zero dead agent-service/PTY code -- [ ] `npm run lint` — 0 violations -- [ ] `npm run typecheck` — 0 errors -- [ ] `npm run test` — all passing -- [ ] `npm run build` — passes clean - ---- - -## Risk Mitigation - -| Risk | Mitigation | -|------|-----------| -| AG-Grid Community lacks master/detail | DIY full-width detail rows — proven pattern, just more code | -| AG-Grid Community lacks sparklines | DIY SVG sparkline — 30 lines, already designed | -| chokidar file watching on Windows | chokidar v4 has improved Windows support; fallback to polling mode | -| JWT security | httpOnly refresh cookies, short-lived access tokens (15min), bcrypt with cost factor 12 | -| Hub SQLite concurrent access | WAL mode enabled, write serialization via Fastify request queue | -| Large progress file writes | Debounce watcher (500ms), parse only YAML frontmatter on change | -| WebSocket reconnection | Auto-reconnect with exponential backoff (already exists in hub-connection.ts) | diff --git a/doc-history/plans/TEAM-ALPHA-HUB-CONNECTION.md b/doc-history/plans/TEAM-ALPHA-HUB-CONNECTION.md deleted file mode 100644 index 9a18bdd..0000000 --- a/doc-history/plans/TEAM-ALPHA-HUB-CONNECTION.md +++ /dev/null @@ -1,581 +0,0 @@ -# Team Alpha Playbook — Hub Connection Layer - -**Status**: READY TO START -**Branch**: `feature/alpha-hub-connection` -**Base**: `master` -**Coordination**: `docs/plans/2026-02-14-hub-frontend-integration.md` -**Progress File**: `docs/progress/alpha-hub-connection-progress.md` - ---- - -## Mission - -Build the WebSocket connection layer in main process that connects to Hub, receives real-time events, and relays them to the renderer via IPC. Expand the Hub API client with full CRUD methods. - ---- - -## Quick Start - -```bash -cd Claude-UI -git checkout master && git pull -git checkout -b feature/alpha-hub-connection -``` - ---- - -## Wave 1: WebSocket Foundation - -**Goal**: Connect to Hub WebSocket, handle auth, auto-reconnect, and relay events to renderer. - -### 1.1 Hub WebSocket Service - -**File**: `src/main/services/hub/hub-websocket.ts` - -```typescript -/** - * Hub WebSocket — Real-time connection to Hub server - * - * Features: - * - First-message auth protocol (send API key) - * - Auto-reconnect with exponential backoff - * - Parse WsBroadcastMessage and emit typed IPC events - */ - -import WebSocket from 'ws'; -import { BrowserWindow } from 'electron'; - -interface WsBroadcastMessage { - type: 'mutation'; - entity: string; - action: 'created' | 'updated' | 'deleted' | 'progress' | 'completed' | 'execute' | 'cancel'; - id: string; - data: unknown; - timestamp: string; -} - -interface HubWebSocketOptions { - hubUrl: string; - apiKey: string; - onStatusChange?: (status: 'connected' | 'disconnected' | 'connecting') => void; -} - -export class HubWebSocket { - private ws: WebSocket | null = null; - private hubUrl: string; - private apiKey: string; - private reconnectAttempts = 0; - private maxReconnectAttempts = 10; - private reconnectDelay = 1000; - private status: 'connected' | 'disconnected' | 'connecting' = 'disconnected'; - private onStatusChange?: (status: 'connected' | 'disconnected' | 'connecting') => void; - - constructor(options: HubWebSocketOptions) { - this.hubUrl = options.hubUrl.replace(/^http/, 'ws') + '/ws'; - this.apiKey = options.apiKey; - this.onStatusChange = options.onStatusChange; - } - - connect(): void { - if (this.ws) { - this.ws.close(); - } - - this.setStatus('connecting'); - this.ws = new WebSocket(this.hubUrl); - - this.ws.on('open', () => { - // Send auth message - this.ws?.send(JSON.stringify({ type: 'auth', apiKey: this.apiKey })); - this.setStatus('connected'); - this.reconnectAttempts = 0; - console.log('[HubWS] Connected'); - }); - - this.ws.on('message', (data) => { - try { - const msg = JSON.parse(String(data)) as WsBroadcastMessage; - if (msg.type === 'mutation') { - this.emitEvent(msg); - } - } catch (err) { - console.error('[HubWS] Failed to parse message:', err); - } - }); - - this.ws.on('close', (code) => { - console.log(`[HubWS] Disconnected (code: ${code})`); - this.setStatus('disconnected'); - this.scheduleReconnect(); - }); - - this.ws.on('error', (err) => { - console.error('[HubWS] Error:', err.message); - }); - } - - disconnect(): void { - this.reconnectAttempts = this.maxReconnectAttempts; // Prevent reconnect - this.ws?.close(); - this.ws = null; - this.setStatus('disconnected'); - } - - getStatus(): 'connected' | 'disconnected' | 'connecting' { - return this.status; - } - - private setStatus(status: 'connected' | 'disconnected' | 'connecting'): void { - this.status = status; - this.onStatusChange?.(status); - } - - private scheduleReconnect(): void { - if (this.reconnectAttempts >= this.maxReconnectAttempts) { - console.log('[HubWS] Max reconnect attempts reached'); - return; - } - - const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts); - this.reconnectAttempts++; - console.log(`[HubWS] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`); - - setTimeout(() => { - this.connect(); - }, delay); - } - - private emitEvent(msg: WsBroadcastMessage): void { - const channel = `event:hub.${msg.entity}.${msg.action}`; - const windows = BrowserWindow.getAllWindows(); - for (const win of windows) { - win.webContents.send(channel, msg.data); - } - } -} -``` - -### 1.2 Hub Event Types - -**File**: `src/shared/types/hub-events.ts` - -```typescript -/** - * Hub WebSocket event types - */ - -export interface HubTaskEvent { - id: string; - title: string; - status: string; - projectId: string; - workspaceId: string | null; - progress?: { - phase: string; - phaseIndex: number; - totalPhases: number; - }; -} - -export interface HubDeviceEvent { - id: string; - deviceName: string; - deviceType: 'desktop' | 'mobile' | 'web'; - isOnline: boolean; -} - -export interface HubWorkspaceEvent { - id: string; - name: string; - hostDeviceId: string | null; -} - -export interface HubProjectEvent { - id: string; - name: string; - path: string; - workspaceId: string | null; -} - -export type HubEventEntity = 'tasks' | 'devices' | 'workspaces' | 'projects' | 'sub_projects'; -export type HubEventAction = 'created' | 'updated' | 'deleted' | 'progress' | 'completed' | 'execute' | 'cancel'; - -export interface HubBroadcastMessage { - type: 'mutation'; - entity: HubEventEntity; - action: HubEventAction; - id: string; - data: unknown; - timestamp: string; -} -``` - -### 1.3 Update IPC Contract - -**File**: `src/shared/ipc-contract.ts` - -Add to `ipcEventContract`: - -```typescript -// ── Hub Events ── -'event:hub.tasks.created': { - payload: z.object({ id: z.string(), data: z.unknown() }), -}, -'event:hub.tasks.updated': { - payload: z.object({ id: z.string(), data: z.unknown() }), -}, -'event:hub.tasks.deleted': { - payload: z.object({ id: z.string() }), -}, -'event:hub.tasks.progress': { - payload: z.object({ id: z.string(), progress: z.unknown() }), -}, -'event:hub.tasks.completed': { - payload: z.object({ id: z.string(), result: z.string() }), -}, -// ... similar for devices, workspaces, projects -``` - -### 1.4 Initialize WebSocket in Main - -**File**: `src/main/index.ts` - -```typescript -import { HubWebSocket } from './services/hub/hub-websocket'; - -let hubWs: HubWebSocket | null = null; - -// When hub config is available: -function connectToHub(config: { url: string; apiKey: string }) { - hubWs = new HubWebSocket({ - hubUrl: config.url, - apiKey: config.apiKey, - onStatusChange: (status) => { - // Emit status to renderer - BrowserWindow.getAllWindows().forEach(win => { - win.webContents.send('event:hub.connection.status', { status }); - }); - }, - }); - hubWs.connect(); -} - -// Add IPC handler for status -ipcMain.handle('hub.ws.status', () => ({ - status: hubWs?.getStatus() ?? 'disconnected', -})); -``` - ---- - -## Wave 1 Checklist - -- [ ] Create `hub-websocket.ts` -- [ ] Create `hub-events.ts` types -- [ ] Update `ipc-contract.ts` with event channels -- [ ] Initialize WebSocket in main process -- [ ] Add `hub.ws.status` IPC handler -- [ ] Test: Connect to Hub, receive events -- [ ] Update progress file - -**Sync Point**: Test with Team Beta's event hooks. - ---- - -## Wave 2: Task Hub Integration - -### 2.1 Expand Hub API Client - -**File**: `src/main/services/hub/hub-api-client.ts` - -Add methods: - -```typescript -// Tasks -async createTask(data: CreateTaskInput): Promise { - return this.post('/api/tasks', data); -} - -async updateTask(id: string, data: UpdateTaskInput): Promise { - return this.put(`/api/tasks/${id}`, data); -} - -async updateTaskStatus(id: string, status: string): Promise { - return this.patch(`/api/tasks/${id}/status`, { status }); -} - -async deleteTask(id: string): Promise<{ success: boolean }> { - return this.delete(`/api/tasks/${id}`); -} - -async executeTask(id: string): Promise<{ queued: boolean; taskId: string }> { - return this.post(`/api/tasks/${id}/execute`, {}); -} - -async cancelTask(id: string): Promise<{ cancelled: boolean }> { - return this.post(`/api/tasks/${id}/cancel`, {}); -} - -async completeTask(id: string, result: { result: 'success' | 'error'; summary?: string }): Promise { - return this.post(`/api/tasks/${id}/complete`, result); -} -``` - -### 2.2 Hub Task IPC Handlers - -**File**: `src/main/ipc/handlers/hub-handlers.ts` - -```typescript -router.handle('hub.tasks.list', async ({ projectId, workspaceId }) => { - const params = new URLSearchParams(); - if (projectId) params.set('project_id', projectId); - if (workspaceId) params.set('workspace_id', workspaceId); - return hubClient.listTasks(params); -}); - -router.handle('hub.tasks.create', (data) => hubClient.createTask(data)); -router.handle('hub.tasks.update', ({ id, ...data }) => hubClient.updateTask(id, data)); -router.handle('hub.tasks.updateStatus', ({ taskId, status }) => hubClient.updateTaskStatus(taskId, status)); -router.handle('hub.tasks.delete', ({ taskId }) => hubClient.deleteTask(taskId)); -router.handle('hub.tasks.execute', ({ taskId }) => hubClient.executeTask(taskId)); -``` - -### 2.3 Update IPC Contract - -Add to `ipcInvokeContract`: - -```typescript -'hub.tasks.list': { - input: z.object({ projectId: z.string().optional(), workspaceId: z.string().optional() }), - output: z.array(TaskSchema), -}, -'hub.tasks.create': { - input: TaskCreateSchema, - output: TaskSchema, -}, -// ... etc -``` - ---- - -## Wave 2 Checklist - -- [ ] Add task methods to `hub-api-client.ts` -- [ ] Add `hub.tasks.*` IPC handlers -- [ ] Update IPC contract -- [ ] Test: Create task via IPC, verify Hub receives -- [ ] Update progress file - ---- - -## Wave 3: Auth & Token Storage - -### 3.1 Token Store - -**File**: `src/main/services/hub/hub-token-store.ts` - -```typescript -import Store from 'electron-store'; - -interface TokenData { - accessToken: string; - refreshToken: string; - expiresAt: string; -} - -const store = new Store<{ hubTokens?: TokenData }>({ - name: 'hub-auth', - encryptionKey: 'your-encryption-key', // Or use safeStorage -}); - -export const tokenStore = { - getTokens(): TokenData | null { - return store.get('hubTokens') ?? null; - }, - - setTokens(tokens: TokenData): void { - store.set('hubTokens', tokens); - }, - - clearTokens(): void { - store.delete('hubTokens'); - }, - - isExpired(): boolean { - const tokens = this.getTokens(); - if (!tokens) return true; - return new Date(tokens.expiresAt) <= new Date(); - }, -}; -``` - -### 3.2 Auth API Methods - -**File**: `src/main/services/hub/hub-api-client.ts` - -```typescript -async register(data: { email: string; password: string; displayName: string }): Promise { - const response = await this.post('/api/auth/register', data); - tokenStore.setTokens({ - accessToken: response.accessToken, - refreshToken: response.refreshToken, - expiresAt: response.expiresAt, - }); - return response; -} - -async login(data: { email: string; password: string; device?: DeviceInfo }): Promise { - const response = await this.post('/api/auth/login', data); - tokenStore.setTokens({ ... }); - return response; -} - -async logout(): Promise { - await this.post('/api/auth/logout', {}); - tokenStore.clearTokens(); -} - -async refreshToken(): Promise<{ accessToken: string }> { - const tokens = tokenStore.getTokens(); - if (!tokens) throw new Error('No tokens'); - const response = await this.post('/api/auth/refresh', { refreshToken: tokens.refreshToken }); - tokenStore.setTokens({ ...tokens, accessToken: response.accessToken, expiresAt: response.expiresAt }); - return response; -} -``` - -### 3.3 Auto-Refresh - -Add token refresh logic before API calls: - -```typescript -private async request(method: string, path: string, body?: unknown): Promise { - // Check if token needs refresh - if (tokenStore.isExpired()) { - await this.refreshToken(); - } - - const tokens = tokenStore.getTokens(); - const headers: Record = { - 'Content-Type': 'application/json', - }; - if (tokens) { - headers['Authorization'] = `Bearer ${tokens.accessToken}`; - } - - // ... make request -} -``` - -### 3.4 Auth IPC Handlers - -```typescript -router.handle('hub.auth.register', (data) => hubClient.register(data)); -router.handle('hub.auth.login', (data) => hubClient.login(data)); -router.handle('hub.auth.logout', () => hubClient.logout()); -router.handle('hub.auth.me', () => hubClient.getCurrentUser()); -``` - ---- - -## Wave 3 Checklist - -- [ ] Create `hub-token-store.ts` -- [ ] Add auth methods to API client -- [ ] Implement auto-refresh -- [ ] Add auth IPC handlers -- [ ] Test: Register → Login → Token persists → Refresh works -- [ ] Update progress file - ---- - -## Wave 4: Device & Cleanup - -### 4.1 Device Registration - -On first login, register this device: - -```typescript -async registerDevice(): Promise { - const machineId = getMachineId(); // Use node-machine-id or similar - return this.post('/api/devices', { - machineId, - deviceType: 'desktop', - deviceName: os.hostname(), - capabilities: { canExecute: true, repos: [] }, - appVersion: app.getVersion(), - }); -} -``` - -### 4.2 Device Heartbeat - -```typescript -// In main process, every 30 seconds: -setInterval(() => { - if (hubClient.isConnected()) { - void hubClient.heartbeat(deviceId); - } -}, 30000); -``` - -### 4.3 Remove Mocks - -- Delete `MOCK_USER`, `MOCK_TOKEN` from `auth-handlers.ts` -- Remove fallback mock logic - -### 4.4 Error Handling - -Standardize all API errors: - -```typescript -class HubApiError extends Error { - constructor(public status: number, message: string) { - super(message); - } -} -``` - ---- - -## Wave 4 Checklist - -- [ ] Add device registration -- [ ] Add heartbeat -- [ ] Remove all mock auth -- [ ] Standardize errors -- [ ] Full verification -- [ ] Update progress file to COMPLETE - ---- - -## Files to Create/Modify - -### New Files -- `src/main/services/hub/hub-websocket.ts` -- `src/main/services/hub/hub-token-store.ts` -- `src/shared/types/hub-events.ts` - -### Modified Files -- `src/main/services/hub/hub-api-client.ts` -- `src/main/ipc/handlers/hub-handlers.ts` -- `src/main/index.ts` -- `src/shared/ipc-contract.ts` - ---- - -## When Done - -1. Run verification: - ```bash - npm run lint && npx tsc --noEmit && npm run build - ``` - -2. Update progress file to COMPLETE - -3. Push and create PR: - ```bash - git push -u origin feature/alpha-hub-connection - ``` - -4. Coordinate with Team Beta for final merge diff --git a/doc-history/plans/TEAM-ALPHA-HUB.md b/doc-history/plans/TEAM-ALPHA-HUB.md deleted file mode 100644 index 33326ab..0000000 --- a/doc-history/plans/TEAM-ALPHA-HUB.md +++ /dev/null @@ -1,407 +0,0 @@ -# Team Alpha: Hub + Backend Implementation - -> Tracker Key: `team-alpha-hub` | Status: **IMPLEMENTED** | Created: 2026-02-14 - -**Branch**: `feature/team-alpha-hub` -**Base**: `master` -**Coordination**: `docs/plans/2026-02-14-parallel-implementation-plan.md` - ---- - -## Your Mission - -You are Team Alpha. You own the Hub server, authentication, and backend API development. Team Beta (running in another terminal) is building the frontend simultaneously. - -**Your file ownership:** -- `hub/` — Full ownership -- `src/shared/types/hub-protocol.ts` — Shared (coordinate changes) -- `src/main/services/device/` — New -- `src/main/services/workspace/` — New -- `docs/contracts/hub-device-protocol.md` — Yours to update - ---- - -## Setup - -```bash -cd Claude-UI -git checkout master && git pull origin master -git checkout -b feature/team-alpha-hub - -# Create your progress file -mkdir -p docs/progress -touch docs/progress/team-alpha-progress.md -``` - ---- - -## Wave 1: Authentication & Devices - -### 1.1 Database Schema - -Update `hub/src/db/schema.sql` with new tables: - -```sql --- Users -CREATE TABLE users ( - id TEXT PRIMARY KEY, - email TEXT UNIQUE NOT NULL, - password_hash TEXT NOT NULL, - display_name TEXT NOT NULL, - avatar_url TEXT, - settings TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - last_login_at DATETIME -); - --- Sessions -CREATE TABLE sessions ( - id TEXT PRIMARY KEY, - user_id TEXT NOT NULL REFERENCES users(id), - device_id TEXT REFERENCES devices(id), - token_hash TEXT NOT NULL, - expires_at DATETIME NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP -); - --- Devices -CREATE TABLE devices ( - id TEXT PRIMARY KEY, - machine_id TEXT, - user_id TEXT NOT NULL REFERENCES users(id), - device_type TEXT NOT NULL, - device_name TEXT NOT NULL, - capabilities TEXT NOT NULL, - is_online BOOLEAN DEFAULT FALSE, - last_seen DATETIME, - app_version TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - UNIQUE(machine_id) WHERE machine_id IS NOT NULL -); - --- Workspaces (for Wave 2) -CREATE TABLE workspaces ( - id TEXT PRIMARY KEY, - user_id TEXT NOT NULL REFERENCES users(id), - name TEXT NOT NULL, - description TEXT, - host_device_id TEXT NOT NULL REFERENCES devices(id), - settings TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP -); - --- Projects (for Wave 2) -CREATE TABLE projects ( - id TEXT PRIMARY KEY, - workspace_id TEXT NOT NULL REFERENCES workspaces(id), - name TEXT NOT NULL, - description TEXT, - root_path TEXT NOT NULL, - git_url TEXT, - repo_structure TEXT NOT NULL, - parent_project_id TEXT REFERENCES projects(id), - default_branch TEXT DEFAULT 'main', - settings TEXT, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, - UNIQUE(workspace_id, root_path) -); - --- Sub-projects (for Wave 2) -CREATE TABLE sub_projects ( - id TEXT PRIMARY KEY, - project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE, - name TEXT NOT NULL, - relative_path TEXT NOT NULL, - git_url TEXT, - default_branch TEXT DEFAULT 'main', - UNIQUE(project_id, relative_path) -); - --- Update tasks table -ALTER TABLE tasks ADD COLUMN workspace_id TEXT REFERENCES workspaces(id); -ALTER TABLE tasks ADD COLUMN sub_project_id TEXT REFERENCES sub_projects(id); -``` - -### 1.2 Authentication Routes - -Create `hub/src/routes/auth.ts`: - -```typescript -// Endpoints: -// POST /api/auth/register - Create user account -// POST /api/auth/login - Login, returns JWT -// POST /api/auth/logout - Invalidate session -// POST /api/auth/refresh - Refresh JWT -// GET /api/auth/me - Get current user - -// Use bcrypt or argon2 for password hashing -// Use jsonwebtoken for JWT -// Store session in sessions table -``` - -### 1.3 Device Routes - -Create `hub/src/routes/devices.ts`: - -```typescript -// Endpoints: -// POST /api/devices - Register device -// GET /api/devices - List user's devices -// PATCH /api/devices/:id - Update device -// DELETE /api/devices/:id - Remove device - -// Device registration should: -// 1. Validate JWT from Authorization header -// 2. Check if machine_id already registered -// 3. Create or update device record -// 4. Return device with capabilities -``` - -### 1.4 Update Protocol Types - -Update `src/shared/types/hub-protocol.ts`: - -```typescript -// Add: -export interface User { - id: string; - email: string; - displayName: string; - avatarUrl?: string; - createdAt: string; - lastLoginAt?: string; -} - -export interface AuthRegisterRequest { - email: string; - password: string; - displayName: string; -} - -export interface AuthLoginRequest { - email: string; - password: string; - deviceInfo?: { - machineId?: string; - deviceName: string; - deviceType: DeviceType; - }; -} - -export interface AuthResponse { - user: User; - token: string; - expiresAt: string; -} -``` - -### Wave 1 Checklist - -- [ ] Database schema created with all tables -- [ ] `POST /api/auth/register` works -- [ ] `POST /api/auth/login` returns JWT -- [ ] `GET /api/auth/me` returns user from JWT -- [ ] `POST /api/devices` registers device -- [ ] `GET /api/devices` lists user's devices -- [ ] Protocol types updated - -**When complete**: Update `docs/progress/team-alpha-progress.md` and notify Team Beta for Sync Point 1. - ---- - -## Sync Point 1 - -**Wait for Team Beta** before proceeding. - -Actions: -1. Share final API endpoints -2. Verify `hub-protocol.ts` types are in sync -3. Resolve any contract issues - ---- - -## Wave 2: Workspaces & Projects - -### 2.1 Workspace Routes - -Create `hub/src/routes/workspaces.ts`: - -```typescript -// Endpoints: -// GET /api/workspaces - List user's workspaces -// POST /api/workspaces - Create workspace -// GET /api/workspaces/:id - Get workspace -// PATCH /api/workspaces/:id - Update workspace -// DELETE /api/workspaces/:id - Delete workspace -// POST /api/workspaces/:id/host - Change host device -``` - -### 2.2 Project Routes - -Create `hub/src/routes/projects.ts`: - -```typescript -// Endpoints: -// GET /api/workspaces/:wid/projects - List projects -// POST /api/workspaces/:wid/projects - Create project -// POST /api/projects/detect - Detect repo type (desktop only) -// GET /api/projects/:id - Get project -// PATCH /api/projects/:id - Update project -// DELETE /api/projects/:id - Delete project - -// Sub-projects: -// GET /api/projects/:id/sub-projects -// POST /api/projects/:id/sub-projects -// DELETE /api/projects/:pid/sub-projects/:sid -``` - -### 2.3 WebSocket Events - -Update `hub/src/ws/handlers.ts`: - -```typescript -// Add broadcasts for: -// workspace:created, workspace:updated, workspace:deleted -// project:created, project:updated, project:deleted -// device:online, device:offline -``` - -### Wave 2 Checklist - -- [ ] Workspace CRUD endpoints work -- [ ] Project CRUD endpoints work -- [ ] Sub-project management works -- [ ] WebSocket broadcasts workspace changes -- [ ] Device online/offline tracked - -**When complete**: Update progress file, proceed to Sync Point 2. - ---- - -## Sync Point 2 - -**Integration test with Team Beta**: - -1. Start Hub server -2. Team Beta connects frontend -3. Test: Register → Login → Create Workspace → Create Project -4. Verify WebSocket events received -5. Fix issues before proceeding - ---- - -## Wave 3: Task Updates - -### 3.1 Update Task Endpoints - -Modify `hub/src/routes/tasks.ts`: - -```typescript -// Add workspace_id and sub_project_id to: -// - Task creation -// - Task listing (filter by workspace) -// - Task response - -// New endpoints: -// POST /api/tasks/:id/progress - Push progress update -// POST /api/tasks/:id/complete - Mark task complete -``` - -### 3.2 Progress WebSocket - -```typescript -// Broadcast on progress update: -// task:progress { taskId, progress } -// task:completed { taskId, result, prUrl? } -``` - -### Wave 3 Checklist - -- [ ] Tasks have workspace_id, sub_project_id -- [ ] Task list filters by workspace -- [ ] Progress endpoint stores and broadcasts -- [ ] Complete endpoint updates status - ---- - -## Wave 4: Execution Commands - -### 4.1 Execution Endpoints - -```typescript -// POST /api/tasks/:id/execute -// - Verify task belongs to user -// - Find workspace host device -// - Send command:execute via WebSocket to host - -// POST /api/tasks/:id/cancel -// - Send command:cancel via WebSocket to host -``` - -### 4.2 WebSocket Commands - -```typescript -// Hub → Device (to workspace host only): -// command:execute { taskId, task } -// command:cancel { taskId, reason? } - -// Device → Hub (from executing device): -// execution:started { taskId, sessionId, pid? } -// execution:ack { taskId, action, error? } -``` - -### 4.3 Finalize Protocol Documentation - -Update `docs/contracts/hub-device-protocol.md`: -- Document all endpoints -- Document all WebSocket events -- Ensure types match implementation - -### Wave 4 Checklist - -- [ ] Execute routes to workspace host -- [ ] Cancel broadcasts correctly -- [ ] Execution acks received -- [ ] Protocol documentation complete - ---- - -## Final Merge - -1. Ensure all tests pass -2. Run `npm run lint` in hub/ -3. Update progress file to COMPLETE -4. Merge to master first (before Team Beta) -5. Notify Team Beta to rebase - ---- - -## Key Files You'll Create/Modify - -``` -hub/ -├── src/ -│ ├── db/ -│ │ └── schema.sql # Updated schema -│ ├── routes/ -│ │ ├── auth.ts # NEW -│ │ ├── devices.ts # NEW -│ │ ├── workspaces.ts # NEW -│ │ ├── projects.ts # NEW -│ │ └── tasks.ts # Modified -│ ├── ws/ -│ │ └── handlers.ts # Modified -│ └── middleware/ -│ └── auth.ts # NEW - JWT validation - -src/shared/types/ -└── hub-protocol.ts # Updated types - -docs/ -├── contracts/ -│ └── hub-device-protocol.md # Updated -└── progress/ - └── team-alpha-progress.md # Your progress -``` diff --git a/doc-history/plans/TEAM-BETA-HUB-INTEGRATION.md b/doc-history/plans/TEAM-BETA-HUB-INTEGRATION.md deleted file mode 100644 index 23f661a..0000000 --- a/doc-history/plans/TEAM-BETA-HUB-INTEGRATION.md +++ /dev/null @@ -1,489 +0,0 @@ -# Team Beta Playbook — Hub Frontend Integration - -**Status**: READY TO START -**Branch**: `feature/beta-frontend-integration` -**Base**: `master` -**Coordination**: `docs/plans/2026-02-14-hub-frontend-integration.md` -**Progress File**: `docs/progress/beta-frontend-integration-progress.md` - ---- - -## Mission - -Wire the frontend to consume Hub API via WebSocket events and IPC handlers. Replace local-only operations with Hub-synced operations for real-time multi-device support. - ---- - -## Quick Start - -```bash -cd Claude-UI -git checkout master && git pull -git checkout -b feature/beta-frontend-integration -``` - ---- - -## Wave 1: Event Infrastructure - -**Goal**: Create the hooks and utilities to receive Hub WebSocket events and invalidate React Query caches. - -### 1.1 Create Hub Event Hook - -**File**: `src/renderer/shared/hooks/useHubEvents.ts` - -```typescript -/** - * useHubEvent — Subscribe to Hub WebSocket events via IPC - * - * Usage: - * useHubEvent('hub.tasks.created', (data) => { - * console.log('Task created:', data); - * }); - */ -import { useEffect } from 'react'; -import { ipcOn, ipcOff } from '@renderer/shared/lib/ipc'; - -type HubEventType = - | 'hub.tasks.created' - | 'hub.tasks.updated' - | 'hub.tasks.deleted' - | 'hub.tasks.progress' - | 'hub.tasks.completed' - | 'hub.devices.created' - | 'hub.devices.updated' - | 'hub.devices.deleted' - | 'hub.workspaces.created' - | 'hub.workspaces.updated' - | 'hub.workspaces.deleted' - | 'hub.projects.created' - | 'hub.projects.updated' - | 'hub.projects.deleted'; - -export function useHubEvent( - eventType: HubEventType, - callback: (data: T) => void, -): void { - useEffect(() => { - const channel = `event:${eventType}`; - ipcOn(channel, callback); - return () => { - ipcOff(channel, callback); - }; - }, [eventType, callback]); -} -``` - -### 1.2 Create Query Invalidation Sync - -**File**: `src/renderer/shared/lib/hub-query-sync.ts` - -```typescript -/** - * Hub Query Sync — Invalidate React Query caches on Hub events - */ -import { QueryClient } from '@tanstack/react-query'; -import { ipcOn } from '@renderer/shared/lib/ipc'; - -const EVENT_TO_QUERY_MAP: Record = { - 'hub.tasks.created': ['tasks'], - 'hub.tasks.updated': ['tasks'], - 'hub.tasks.deleted': ['tasks'], - 'hub.tasks.progress': ['tasks'], - 'hub.tasks.completed': ['tasks'], - 'hub.devices.created': ['devices'], - 'hub.devices.updated': ['devices'], - 'hub.devices.deleted': ['devices'], - 'hub.workspaces.created': ['workspaces'], - 'hub.workspaces.updated': ['workspaces'], - 'hub.workspaces.deleted': ['workspaces'], - 'hub.projects.created': ['projects'], - 'hub.projects.updated': ['projects'], - 'hub.projects.deleted': ['projects'], -}; - -export function setupHubQuerySync(queryClient: QueryClient): () => void { - const handlers: Array<{ channel: string; handler: () => void }> = []; - - for (const [event, queryKeys] of Object.entries(EVENT_TO_QUERY_MAP)) { - const channel = `event:${event}`; - const handler = () => { - for (const key of queryKeys) { - void queryClient.invalidateQueries({ queryKey: [key] }); - } - }; - ipcOn(channel, handler); - handlers.push({ channel, handler }); - } - - // Return cleanup function - return () => { - for (const { channel, handler } of handlers) { - ipcOff(channel, handler); - } - }; -} -``` - -### 1.3 Wire Into App - -**File**: `src/renderer/app/providers/QueryProvider.tsx` (or wherever QueryClient is created) - -```typescript -import { setupHubQuerySync } from '@renderer/shared/lib/hub-query-sync'; - -// In the provider component: -useEffect(() => { - const cleanup = setupHubQuerySync(queryClient); - return cleanup; -}, [queryClient]); -``` - -### 1.4 Connection Status Component - -**File**: `src/renderer/shared/components/HubStatus.tsx` - -```typescript -import { useQuery } from '@tanstack/react-query'; -import { ipc } from '@renderer/shared/lib/ipc'; -import { Wifi, WifiOff, Loader2 } from 'lucide-react'; - -export function HubStatus() { - const { data: status } = useQuery({ - queryKey: ['hub', 'status'], - queryFn: () => ipc('hub.getStatus', {}), - refetchInterval: 5000, - }); - - if (!status) return null; - - return ( -
- {status.connected ? ( - <> - - Hub - - ) : status.connecting ? ( - <> - - Connecting... - - ) : ( - <> - - Offline - - )} -
- ); -} -``` - -**Add to TopBar**: Import and add `` to the top bar. - ---- - -## Wave 1 Checklist - -- [ ] Create `useHubEvents.ts` -- [ ] Create `hub-query-sync.ts` -- [ ] Wire sync into QueryProvider -- [ ] Create `HubStatus.tsx` -- [ ] Add HubStatus to TopBar -- [ ] Test: Start app, verify no errors -- [ ] Update progress file - -**Sync Point**: Wait for Team Alpha to complete WebSocket layer, then test end-to-end. - ---- - -## Wave 2: Task Integration - -**Goal**: Route all task operations through Hub API instead of local IPC. - -### 2.1 Update Task Query - -**File**: `src/renderer/features/tasks/api/useTasks.ts` - -Change: -```typescript -// OLD -queryFn: () => ipc('tasks.list', { projectId }), - -// NEW -queryFn: () => ipc('hub.tasks.list', { projectId, workspaceId }), -``` - -Add workspaceId from settings/context. - -### 2.2 Update Task Mutations - -**File**: `src/renderer/features/tasks/api/useTaskMutations.ts` - -```typescript -// useCreateTask -mutationFn: (data) => ipc('hub.tasks.create', data), - -// useUpdateTaskStatus -mutationFn: ({ taskId, status }) => ipc('hub.tasks.updateStatus', { taskId, status }), - -// useDeleteTask -mutationFn: (taskId) => ipc('hub.tasks.delete', { taskId }), - -// useExecuteTask -mutationFn: (taskId) => ipc('hub.tasks.execute', { taskId }), -``` - -Remove optimistic updates — WebSocket events will trigger query invalidation. - -### 2.3 Update Task Event Listeners - -**File**: `src/renderer/features/tasks/hooks/useTaskEvents.ts` - -```typescript -import { useHubEvent } from '@renderer/shared/hooks/useHubEvents'; -import { useQueryClient } from '@tanstack/react-query'; -import { toast } from 'sonner'; - -export function useTaskEvents() { - const queryClient = useQueryClient(); - - useHubEvent('hub.tasks.completed', (data: { taskId: string; result: string }) => { - void queryClient.invalidateQueries({ queryKey: ['tasks'] }); - if (data.result === 'success') { - toast.success('Task completed successfully'); - } else { - toast.error('Task failed'); - } - }); - - useHubEvent('hub.tasks.progress', (data: { taskId: string; progress: unknown }) => { - // Update specific task in cache without full refetch - queryClient.setQueryData(['tasks'], (old: Task[] | undefined) => { - if (!old) return old; - return old.map(t => t.id === data.taskId ? { ...t, progress: data.progress } : t); - }); - }); -} -``` - -### 2.4 Live Progress in TaskTableRow - -Update `TaskTableRow.tsx` to show progress from WebSocket updates (already in cache via setQueryData). - ---- - -## Wave 2 Checklist - -- [ ] Update `useTasks.ts` to use `hub.tasks.list` -- [ ] Update all mutations to use `hub.tasks.*` -- [ ] Remove optimistic updates -- [ ] Update `useTaskEvents.ts` for hub events -- [ ] Add progress cache updates -- [ ] Test: Create task, verify appears on other device -- [ ] Update progress file - -**Sync Point**: Multi-device test with Team Alpha. - ---- - -## Wave 3: Auth & Workspace Integration - -### 3.1 Update Auth Store - -**File**: `src/renderer/features/auth/store.ts` - -```typescript -interface AuthState { - user: User | null; - isAuthenticated: boolean; - isLoading: boolean; - error: string | null; - - setUser: (user: User | null) => void; - setLoading: (loading: boolean) => void; - setError: (error: string | null) => void; - logout: () => void; -} -``` - -Remove any mock user references. - -### 3.2 Update Auth Hooks - -**File**: `src/renderer/features/auth/api/useAuth.ts` - -```typescript -export function useLogin() { - const setUser = useAuthStore((s) => s.setUser); - - return useMutation({ - mutationFn: (data: { email: string; password: string }) => - ipc('hub.auth.login', data), - onSuccess: (response) => { - setUser(response.user); - }, - }); -} - -export function useRegister() { - return useMutation({ - mutationFn: (data: { email: string; password: string; displayName: string }) => - ipc('hub.auth.register', data), - }); -} - -export function useLogout() { - const logout = useAuthStore((s) => s.logout); - - return useMutation({ - mutationFn: () => ipc('hub.auth.logout', {}), - onSuccess: () => { - logout(); - }, - }); -} - -export function useCurrentUser() { - const setUser = useAuthStore((s) => s.setUser); - - return useQuery({ - queryKey: ['auth', 'me'], - queryFn: () => ipc('hub.auth.me', {}), - onSuccess: (user) => { - setUser(user); - }, - }); -} -``` - -### 3.3 Auth Guard - -Create a component or hook that checks auth state and redirects to login if not authenticated. - -### 3.4 Workspace Hooks - -**File**: `src/renderer/features/settings/api/useWorkspaces.ts` - -Update to use `hub.workspaces.*` channels. - ---- - -## Wave 3 Checklist - -- [ ] Update auth store (remove mocks) -- [ ] Update `useLogin`, `useRegister`, `useLogout` -- [ ] Add `useCurrentUser` hook -- [ ] Create auth guard/redirect -- [ ] Update workspace hooks -- [ ] Test: Register → Login → Create workspace -- [ ] Update progress file - ---- - -## Wave 4: Polish - -### 4.1 Loading States - -Add skeleton loaders to: -- TaskTable (while loading) -- WorkspacesTab (while loading) -- Project list (while loading) - -### 4.2 Error States - -Show meaningful errors: -- Auth failures -- Hub connection errors -- Task operation failures - -### 4.3 Offline Banner - -When Hub disconnects, show a banner: -```typescript -{!hubStatus.connected && ( -
- Hub disconnected. Some features unavailable. -
-)} -``` - -### 4.4 Remove Dead Code - -- Find IPC handlers that are now unused -- Remove or archive them -- Clean up imports - ---- - -## Wave 4 Checklist - -- [ ] Add loading skeletons -- [ ] Add error states with retry -- [ ] Add offline banner -- [ ] Remove dead code -- [ ] Full end-to-end test -- [ ] Update progress file to COMPLETE - ---- - -## Files to Create/Modify - -### New Files -- `src/renderer/shared/hooks/useHubEvents.ts` -- `src/renderer/shared/lib/hub-query-sync.ts` -- `src/renderer/shared/components/HubStatus.tsx` - -### Modified Files -- `src/renderer/app/providers/QueryProvider.tsx` -- `src/renderer/app/layouts/TopBar.tsx` -- `src/renderer/features/tasks/api/useTasks.ts` -- `src/renderer/features/tasks/api/useTaskMutations.ts` -- `src/renderer/features/tasks/hooks/useTaskEvents.ts` -- `src/renderer/features/auth/store.ts` -- `src/renderer/features/auth/api/useAuth.ts` -- `src/renderer/features/settings/api/useWorkspaces.ts` - ---- - -## Linting Reminders - -- Use `import type { X }` for type-only imports -- No `any` — use `unknown` and narrow -- No non-null assertions `!` — use `?? fallback` -- Numbers can't be booleans: use `arr.length > 0` not `arr.length` -- Always handle promises: use `void` or await - ---- - -## Commit Message Format - -``` -feat(hub-integration): - -- Detail 1 -- Detail 2 - -Co-Authored-By: Claude Opus 4.5 -``` - ---- - -## When Done - -1. Run full verification: - ```bash - npm run lint && npx tsc --noEmit && npm run build - ``` - -2. Update progress file to COMPLETE - -3. Push branch: - ```bash - git push -u origin feature/beta-frontend-integration - ``` - -4. Create PR to master - -5. Coordinate with Team Alpha for final merge diff --git a/doc-history/plans/close-remaining-gaps-plan.md b/doc-history/plans/close-remaining-gaps-plan.md deleted file mode 100644 index bed08cc..0000000 --- a/doc-history/plans/close-remaining-gaps-plan.md +++ /dev/null @@ -1,54 +0,0 @@ -# Plan: Close Remaining Gap Analysis Items - -> Tracker Key: `close-remaining-gaps` | Status: **IMPLEMENTED** | Created: 2026-02-18 - -## Summary - -Investigation of all 9 remaining open gaps (G-6b, G-7, G-8, G-9, G-10, G-17, G-18, G-19, G-20) reveals they are **already resolved in the current codebase**. The gap analysis table in `ai-docs/user-interface-flow.md` is stale — it still lists these as open when the code already addresses them. The only work needed is a documentation update to mark all gaps as RESOLVED with evidence. - -## Investigation Results - -| Gap | Claim | Evidence | Verdict | -|-----|-------|----------|---------| -| **G-20** | Profile API keys in plaintext | `settings-encryption.ts` defines `PROFILE_SECRET_KEYS = ['apiKey', 'oauthToken']`. `settings-store.ts` encrypts all profile secrets via `safeStorage` on save, decrypts on load, and auto-migrates plaintext → encrypted. | **RESOLVED** | -| **G-6b** | Onboarding API key step disconnected | `ApiKeyStep.tsx` calls `useSettings()` + `useUpdateSettings()` mutation to save `anthropicApiKey` via `settings.update` IPC. All 5 wizard steps make real IPC calls. `OnboardingWizard` is mounted in `RootLayout.tsx`. | **RESOLVED** | -| **G-7** | Project delete confirmation not verified | `ProjectEditDialog.tsx` imports `ConfirmDialog`, renders it with `variant="destructive"`, `title="Delete Project"`, wired to `removeProject.mutate()`. | **RESOLVED** | -| **G-8** | Workspace not persisted in wizard | `StepConfigure.tsx` renders workspace `