/** * Preview Seed Script * * Populates the database with demo data for preview deployments. * Run with: CW_DB_PATH=/workspace/.cw/cw.db node /app/apps/server/dist/preview-seed.js * * Prints the project ID to stdout so the calling shell script * can derive the clone path. */ import { createDatabase, ensureSchema } from './db/index.js'; import { createRepositories } from './container.js'; const dbPath = process.env.CW_DB_PATH; if (!dbPath) { console.error('CW_DB_PATH environment variable is required'); process.exit(1); } const db = createDatabase(dbPath); ensureSchema(db); const repos = createRepositories(db); // ─── Project ─── const project = await repos.projectRepository.create({ name: 'demo-app', url: 'file:///workspace/demo-repo.git', defaultBranch: 'main', }); // ─── Initiative ─── const initiative = await repos.initiativeRepository.create({ name: 'Task Manager Redesign', status: 'active', branch: 'cw/task-manager-redesign', executionMode: 'review_per_phase', }); await repos.projectRepository.setInitiativeProjects(initiative.id, [project.id]); // ─── Phases ─── const phase1 = await repos.phaseRepository.create({ initiativeId: initiative.id, name: 'Backend API', status: 'completed', }); const phase2 = await repos.phaseRepository.create({ initiativeId: initiative.id, name: 'UI Overhaul', status: 'pending_review', }); const phase3 = await repos.phaseRepository.create({ initiativeId: initiative.id, name: 'Testing & Polish', status: 'in_progress', }); // ─── Tasks ─── // Phase 1: Backend API (all completed) const task1a = await repos.taskRepository.create({ phaseId: phase1.id, initiativeId: initiative.id, name: 'Research REST vs GraphQL patterns', category: 'research', status: 'completed', description: 'Evaluate REST and GraphQL approaches for the task management API. Consider developer experience, caching, and real-time requirements.', order: 0, summary: 'Recommended REST with WebSocket subscriptions for real-time. GraphQL adds complexity without clear benefit for this domain.', }); const task1b = await repos.taskRepository.create({ phaseId: phase1.id, initiativeId: initiative.id, name: 'Implement task CRUD endpoints', category: 'execute', status: 'completed', description: 'Build the core CRUD API for tasks with proper validation and error handling.', order: 1, summary: 'Implemented GET/POST/PUT/DELETE /api/tasks with Zod validation, proper HTTP status codes, and pagination support.', }); const task1c = await repos.taskRepository.create({ phaseId: phase1.id, initiativeId: initiative.id, name: 'Add input validation middleware', category: 'execute', status: 'completed', description: 'Create reusable validation middleware using Zod schemas for all API endpoints.', order: 2, summary: 'Added validateBody() and validateQuery() middleware with typed error responses.', }); // Phase 2: UI Overhaul (all completed) const task2a = await repos.taskRepository.create({ phaseId: phase2.id, initiativeId: initiative.id, name: 'Design component hierarchy', category: 'plan', status: 'completed', description: 'Plan the component architecture for the redesigned UI, focusing on reusability and maintainability.', order: 0, summary: 'Designed 3-level hierarchy: Layout (Header, Sidebar) → Views (TaskList, TaskDetail) → Primitives (StatusBadge, PriorityTag).', }); const task2b = await repos.taskRepository.create({ phaseId: phase2.id, initiativeId: initiative.id, name: 'Implement responsive header', category: 'execute', status: 'completed', description: 'Build the responsive header component with search functionality and notification bell.', order: 1, summary: 'Created Header.tsx with search input, notification dropdown (3 mock items), and user avatar. Fully responsive with mobile hamburger menu.', }); const task2c = await repos.taskRepository.create({ phaseId: phase2.id, initiativeId: initiative.id, name: 'Refactor task list with filters', category: 'execute', status: 'completed', description: 'Rewrite the task list component with status icons, priority badges, and filter controls.', order: 2, summary: 'Refactored TaskList.tsx with table layout, status icons, priority badges, assignee avatars, and due dates. Added TaskFilters.tsx with status/priority filter buttons.', }); // Phase 3: Testing & Polish (mixed statuses) const task3a = await repos.taskRepository.create({ phaseId: phase3.id, initiativeId: initiative.id, name: 'Plan test strategy', category: 'plan', status: 'completed', description: 'Define the testing strategy: unit tests, integration tests, and E2E test coverage targets.', order: 0, summary: 'Defined 3-tier strategy: Vitest unit tests (80% coverage), API integration tests with supertest, and Playwright E2E for critical flows.', }); const task3b = await repos.taskRepository.create({ phaseId: phase3.id, initiativeId: initiative.id, name: 'Write integration tests', category: 'execute', status: 'in_progress', description: 'Write integration tests for all API endpoints using supertest.', order: 1, }); const task3c = await repos.taskRepository.create({ phaseId: phase3.id, initiativeId: initiative.id, name: 'Add error handling', category: 'execute', status: 'pending', description: 'Add global error boundary, API error toasts, and retry logic for failed requests.', order: 2, }); // ─── Agents ─── const agent1 = await repos.agentRepository.create({ name: 'keen-falcon', worktreeId: 'worktrees/keen-falcon', taskId: task1b.id, initiativeId: initiative.id, status: 'stopped', mode: 'execute', provider: 'claude', }); const agent2 = await repos.agentRepository.create({ name: 'swift-otter', worktreeId: 'worktrees/swift-otter', taskId: task2c.id, initiativeId: initiative.id, status: 'stopped', mode: 'execute', provider: 'claude', }); const agent3 = await repos.agentRepository.create({ name: 'bright-heron', worktreeId: 'worktrees/bright-heron', taskId: task3b.id, initiativeId: initiative.id, status: 'running', mode: 'execute', provider: 'claude', }); // ─── Agent Log Chunks ─── // Agent 1: keen-falcon (completed backend work) await repos.logChunkRepository.insertChunk({ agentId: agent1.id, agentName: 'keen-falcon', sessionNumber: 1, content: [ JSON.stringify({ type: 'system', session_id: 'session-kf-001' }), JSON.stringify({ type: 'assistant', message: { content: [ { type: 'text', text: "I'll start by reading the existing API structure to understand the current patterns." }, { type: 'tool_use', id: 'toolu_kf1', name: 'Read', input: { file_path: '/app/src/lib/api.ts' } }, ], }, }), JSON.stringify({ type: 'user', message: { content: [{ type: 'tool_result', content: "const API_URL = '/api';\n\nexport async function fetchTasks(filter: string) {\n const res = await fetch(`${API_URL}/tasks?filter=${filter}`);\n return res.json();\n}" }] }, tool_use_result: { stdout: "const API_URL = '/api';\n\nexport async function fetchTasks(filter: string) {\n const res = await fetch(`${API_URL}/tasks?filter=${filter}`);\n return res.json();\n}" }, }), JSON.stringify({ type: 'assistant', message: { content: [ { type: 'text', text: "Now I'll implement the task CRUD endpoints with proper validation. I'll create a structured API client with error handling." }, { type: 'tool_use', id: 'toolu_kf2', name: 'Write', input: { file_path: '/app/src/server/routes/tasks.ts', content: '// CRUD endpoints implementation...' } }, ], }, }), JSON.stringify({ type: 'user', message: { content: [{ type: 'tool_result', content: 'File written successfully' }] }, tool_use_result: { stdout: 'File written successfully' }, }), JSON.stringify({ type: 'assistant', message: { content: [ { type: 'text', text: "Let me also add the Zod validation schemas and middleware." }, { type: 'tool_use', id: 'toolu_kf3', name: 'Write', input: { file_path: '/app/src/server/middleware/validate.ts', content: '// Validation middleware...' } }, ], }, }), JSON.stringify({ type: 'user', message: { content: [{ type: 'tool_result', content: 'File written successfully' }] }, tool_use_result: { stdout: 'File written successfully' }, }), JSON.stringify({ type: 'result', is_error: false, total_cost_usd: 0.0847, duration_ms: 32000 }), ].join('\n'), }); // Agent 2: swift-otter (completed UI overhaul) await repos.logChunkRepository.insertChunk({ agentId: agent2.id, agentName: 'swift-otter', sessionNumber: 1, content: [ JSON.stringify({ type: 'system', session_id: 'session-so-001' }), JSON.stringify({ type: 'assistant', message: { content: [ { type: 'text', text: "I'll start by reading the current TaskList component to understand what needs to be refactored." }, { type: 'tool_use', id: 'toolu_so1', name: 'Read', input: { file_path: '/app/src/components/TaskList.tsx' } }, ], }, }), JSON.stringify({ type: 'user', message: { content: [{ type: 'tool_result', content: "import { useTasks } from '../hooks/useTasks';\n\nexport function TaskList({ filter }) {\n const { tasks, loading } = useTasks(filter);\n if (loading) return