--- phase: 04-database-planning-fixes plan: 01 type: execute wave: 1 depends_on: [] files_modified: - src/db/schema.ts - src/shared/schemas.ts - src/shared/types.ts - src/server/services/thread.service.ts - src/server/routes/threads.ts - src/client/hooks/useThreads.ts - tests/helpers/db.ts autonomous: true requirements: [DB-01, PLAN-01] must_haves: truths: - "Database schema push creates threads and thread_candidates tables without errors" - "Threads table includes category_id column with foreign key to categories" - "Creating a thread with name and categoryId succeeds via API" - "getAllThreads returns categoryName and categoryEmoji for each thread" artifacts: - path: "src/db/schema.ts" provides: "threads table with categoryId column" contains: "categoryId.*references.*categories" - path: "src/shared/schemas.ts" provides: "createThreadSchema with categoryId field" contains: "categoryId.*z.number" - path: "src/server/services/thread.service.ts" provides: "Thread CRUD with category join" exports: ["createThread", "getAllThreads"] - path: "tests/helpers/db.ts" provides: "Test DB with category_id on threads" contains: "category_id.*REFERENCES categories" key_links: - from: "src/server/routes/threads.ts" to: "src/server/services/thread.service.ts" via: "createThread(db, data) with categoryId" pattern: "createThread.*data" - from: "src/server/services/thread.service.ts" to: "src/db/schema.ts" via: "Drizzle insert/select on threads with categoryId" pattern: "threads.*categoryId" --- Fix the missing threads table in the database and add categoryId to threads so thread creation works end-to-end. Purpose: DB-01 (threads table exists) and the backend half of PLAN-01 (thread creation works with category). Without this, the planning tab crashes on any thread operation. Output: Working database schema, updated API that accepts categoryId on thread creation, and thread list returns category info. @/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md @/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md @.planning/ROADMAP.md @.planning/phases/04-database-planning-fixes/04-CONTEXT.md From src/db/schema.ts (threads table -- needs categoryId added): ```typescript export const threads = sqliteTable("threads", { id: integer("id").primaryKey({ autoIncrement: true }), name: text("name").notNull(), status: text("status").notNull().default("active"), resolvedCandidateId: integer("resolved_candidate_id"), // MISSING: categoryId column createdAt: integer("created_at", { mode: "timestamp" }).notNull().$defaultFn(() => new Date()), updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().$defaultFn(() => new Date()), }); ``` From src/shared/schemas.ts (createThreadSchema -- needs categoryId): ```typescript export const createThreadSchema = z.object({ name: z.string().min(1, "Thread name is required"), // MISSING: categoryId }); ``` From src/client/hooks/useThreads.ts (ThreadListItem -- needs category fields): ```typescript interface ThreadListItem { id: number; name: string; status: "active" | "resolved"; resolvedCandidateId: number | null; createdAt: string; updatedAt: string; candidateCount: number; minPriceCents: number | null; maxPriceCents: number | null; // MISSING: categoryId, categoryName, categoryEmoji } ``` Task 1: Add categoryId to threads schema, Zod schemas, types, and test helper src/db/schema.ts, src/shared/schemas.ts, src/shared/types.ts, tests/helpers/db.ts 1. In `src/db/schema.ts`, add `categoryId` column to the `threads` table: ``` categoryId: integer("category_id").notNull().references(() => categories.id), ``` Place it after the `resolvedCandidateId` field. 2. In `src/shared/schemas.ts`, update `createThreadSchema` to require categoryId: ``` export const createThreadSchema = z.object({ name: z.string().min(1, "Thread name is required"), categoryId: z.number().int().positive(), }); ``` Also update `updateThreadSchema` to allow optional categoryId: ``` export const updateThreadSchema = z.object({ name: z.string().min(1).optional(), categoryId: z.number().int().positive().optional(), }); ``` 3. In `tests/helpers/db.ts`, update the threads CREATE TABLE to include `category_id`: ```sql CREATE TABLE threads ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'active', resolved_candidate_id INTEGER, category_id INTEGER NOT NULL REFERENCES categories(id), created_at INTEGER NOT NULL DEFAULT (unixepoch()), updated_at INTEGER NOT NULL DEFAULT (unixepoch()) ) ``` 4. Run `bun run db:generate` to generate the migration for adding category_id to threads. 5. Run `bun run db:push` to apply the migration. cd /home/jean-luc-makiola/Development/projects/GearBox && bun run db:push 2>&1 | tail -5 threads table in schema.ts has categoryId with FK to categories, createThreadSchema requires categoryId, test helper CREATE TABLE matches, db:push succeeds Task 2: Update thread service and routes to handle categoryId, update hook types src/server/services/thread.service.ts, src/server/routes/threads.ts, src/client/hooks/useThreads.ts 1. In `src/server/services/thread.service.ts`: - Update `createThread` to insert `categoryId` from data: `.values({ name: data.name, categoryId: data.categoryId })` - Update `getAllThreads` to join with categories table and return `categoryId`, `categoryName`, `categoryEmoji` in the select: ``` categoryId: threads.categoryId, categoryName: categories.name, categoryEmoji: categories.emoji, ``` Add `.innerJoin(categories, eq(threads.categoryId, categories.id))` to the query. - Update `updateThread` data type to include optional `categoryId: number`. 2. In `src/server/routes/threads.ts`: - The route handlers already pass `data` through from Zod validation, so createThread and updateThread should work with the updated schemas. Verify the PUT handler passes categoryId if present. 3. In `src/client/hooks/useThreads.ts`: - Add `categoryId: number`, `categoryName: string`, `categoryEmoji: string` to the `ThreadListItem` interface. - Update `useCreateThread` mutationFn type to `{ name: string; categoryId: number }`. 4. Run existing tests to confirm nothing breaks. cd /home/jean-luc-makiola/Development/projects/GearBox && bun test 2>&1 | tail -20 Thread creation accepts categoryId, getAllThreads returns category name and emoji for each thread, existing tests pass, useCreateThread hook sends categoryId - `bun run db:push` completes without errors - `bun test` passes all existing tests - Start dev server (`bun run dev:server`) and confirm `curl http://localhost:3000/api/threads` returns 200 (empty array is fine) - threads table exists in database with category_id column - POST /api/threads requires { name, categoryId } and creates a thread - GET /api/threads returns threads with categoryName and categoryEmoji - All existing tests pass After completion, create `.planning/phases/04-database-planning-fixes/04-01-SUMMARY.md`