chore: complete v1.1 milestone — Fixes & Polish
Archive v1.1 artifacts (roadmap, requirements, phases) to milestones/. Evolve PROJECT.md with shipped requirements and new key decisions. Reorganize ROADMAP.md with collapsed milestone groupings. Update retrospective with v1.1 lessons. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
---
|
||||
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"
|
||||
---
|
||||
|
||||
<objective>
|
||||
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.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/04-database-planning-fixes/04-CONTEXT.md
|
||||
|
||||
<interfaces>
|
||||
<!-- Key types and contracts the executor needs -->
|
||||
|
||||
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
|
||||
}
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add categoryId to threads schema, Zod schemas, types, and test helper</name>
|
||||
<files>src/db/schema.ts, src/shared/schemas.ts, src/shared/types.ts, tests/helpers/db.ts</files>
|
||||
<action>
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/jean-luc-makiola/Development/projects/GearBox && bun run db:push 2>&1 | tail -5</automated>
|
||||
</verify>
|
||||
<done>threads table in schema.ts has categoryId with FK to categories, createThreadSchema requires categoryId, test helper CREATE TABLE matches, db:push succeeds</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Update thread service and routes to handle categoryId, update hook types</name>
|
||||
<files>src/server/services/thread.service.ts, src/server/routes/threads.ts, src/client/hooks/useThreads.ts</files>
|
||||
<action>
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/jean-luc-makiola/Development/projects/GearBox && bun test 2>&1 | tail -20</automated>
|
||||
</verify>
|
||||
<done>Thread creation accepts categoryId, getAllThreads returns category name and emoji for each thread, existing tests pass, useCreateThread hook sends categoryId</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `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)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 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
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/04-database-planning-fixes/04-01-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user