nexus/.planning/phases/24-search-history-branching/24-00-SUMMARY.md
Nexus Dev d78bdad0a9 docs(24-00): complete foundation plan — migrations, schema, types, test stubs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 15:08:51 +00:00

6.5 KiB

phase plan subsystem tags dependency_graph tech_stack key_files decisions completed_date duration tasks files
24-search-history-branching 00 db-schema-shared-types
migrations
drizzle
types
validators
test-stubs
requires provides affects
0050_add_branch_columns migration
0051_add_message_search_vector migration
0052_create_chat_message_bookmarks migration
chatMessageBookmarks Drizzle schema
ChatMessageSearchResult shared type
ChatBookmark shared type
searchMessagesSchema validator
branchConversationSchema validator
Wave 0 test stubs for searchMessages, toggleBookmark, branchConversation, exportConversation
packages/db
packages/shared
server/src/__tests__
added patterns
AnyPgColumn type annotation for self-referential FK (matches issues.ts, goals.ts pattern)
it.todo() for Wave 0 test scaffolding (matches Phase 21 convention)
created modified
packages/db/src/migrations/0050_add_branch_columns.sql
packages/db/src/migrations/0051_add_message_search_vector.sql
packages/db/src/migrations/0052_create_chat_message_bookmarks.sql
packages/db/src/schema/chat_message_bookmarks.ts
packages/db/src/migrations/meta/_journal.json
packages/db/src/schema/chat_conversations.ts
packages/db/src/schema/chat_messages.ts
packages/db/src/schema/index.ts
packages/shared/src/types/chat.ts
packages/shared/src/validators/chat.ts
packages/shared/src/index.ts
server/src/__tests__/chat-service.test.ts
server/src/__tests__/chat-routes.test.ts
Used AnyPgColumn type annotation for parentConversationId self-referential FK to resolve TypeScript circular reference — matches existing pattern in issues.ts, goals.ts, execution_workspaces.ts
content_search tsvector column intentionally omitted from Drizzle schema — it is a Postgres generated stored column queried via raw sql`` only
2026-04-01 ~5min 2 9

Phase 24 Plan 00: DB Migrations, Schema, Types, and Test Stubs Summary

One-liner: Three SQL migrations (branch columns, tsvector search, bookmarks table), Drizzle schema updates, and shared TypeScript types/validators for chat search, bookmarks, and branching with Wave 0 it.todo test stubs.

Tasks Completed

Task Name Commit Key Files
1 DB migrations and Drizzle schema updates 430bbbb8 0050-0052 SQL files, chat_conversations.ts, chat_message_bookmarks.ts, schema/index.ts
2 Shared types, validators, and Wave 0 test stubs e881270c types/chat.ts, validators/chat.ts, shared/index.ts, chat-service.test.ts, chat-routes.test.ts

What Was Built

Task 1: DB Migrations and Drizzle Schema

Migration 0050_add_branch_columns.sql: Adds parent_conversation_id (self-referential UUID FK with ON DELETE SET NULL) and branch_from_message_id to chat_conversations, plus a GIN-style index for parent lookups.

Migration 0051_add_message_search_vector.sql: Adds content_search as a Postgres-generated STORED tsvector column (using to_tsvector('english', content)) with a GIN index for full-text search.

Migration 0052_create_chat_message_bookmarks.sql: Creates the chat_message_bookmarks table with company_id, message_id (ON DELETE CASCADE), conversation_id (ON DELETE CASCADE), plus compound indexes for efficient per-company lookups.

Drizzle schema changes:

  • chat_conversations.ts: Added parentConversationId and branchFromMessageId columns with AnyPgColumn type annotation to resolve TypeScript circular reference. Added parentIdx to index object.
  • chat_messages.ts: Added comment noting the generated tsvector column — it is intentionally absent from the Drizzle schema.
  • chat_message_bookmarks.ts: New schema file with two compound indexes.
  • schema/index.ts: Added chatMessageBookmarks re-export.

Task 2: Shared Types, Validators, and Test Stubs

New types in packages/shared/src/types/chat.ts:

  • ChatMessageSearchResult — ranked search result with message, conversation, role, and rank fields
  • ChatMessageSearchResponse — list wrapper
  • ChatBookmark — bookmark record shape
  • ChatBookmarkWithMessage — bookmark with embedded ChatMessage and conversation title
  • ChatBookmarkListResponse — list wrapper
  • ChatBookmarkToggleResponse{ bookmarked: boolean } for toggle endpoint

Extended existing types:

  • ChatConversation — added parentConversationId: string | null and branchFromMessageId: string | null
  • ChatConversationListItem — same two fields added

New validators in packages/shared/src/validators/chat.ts:

  • searchMessagesSchemaq (min 2, max 200) + optional limit (1-50, coerced)
  • branchConversationSchemabranchFromMessageId as UUID string
  • Inferred types: SearchMessages, BranchConversation

Wave 0 test stubs (chat-service.test.ts):

  • describe("searchMessages") — 3 it.todo entries
  • describe("toggleBookmark") — 2 it.todo entries
  • describe("branchConversation") — 2 it.todo entries
  • describe("exportConversation") — 2 it.todo entries

Wave 0 test stubs (chat-routes.test.ts):

  • describe("GET /companies/:id/messages/search") — 2 it.todo entries
  • describe("POST /conversations/:id/bookmarks") — 1 it.todo entry
  • describe("POST /conversations/:id/branch") — 1 it.todo entry
  • describe("GET /conversations/:id/export") — 2 it.todo entries

Verification

  • pnpm --filter @paperclipai/db build — PASSED
  • pnpm --filter @paperclipai/shared build — PASSED
  • All 7 acceptance criteria for Task 1 — PASSED
  • All 10 acceptance criteria for Task 2 — PASSED

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] Self-referential FK causes TypeScript circular reference

  • Found during: Task 1 verification (db build)
  • Issue: TypeScript error TS7022/TS7024: chatConversations implicitly has type any because parentConversationId references the table being defined
  • Fix: Import AnyPgColumn from drizzle-orm/pg-core and annotate the reference callback as (): AnyPgColumn => chatConversations.id — matches the existing pattern in issues.ts, goals.ts, execution_workspaces.ts, and heartbeat_runs.ts
  • Files modified: packages/db/src/schema/chat_conversations.ts
  • Commit: 430bbbb8

Known Stubs

None — all Wave 0 test stubs are intentional it.todo() scaffolding per plan specification. They are placeholders for Plans 01-03 to implement.

Self-Check: PASSED