# Copilot Instructions for TJWaterAgent ## Overview - TJWaterAgent is a Bun + TypeScript backend service. - Main entrypoint: `src/server.ts` - Chat API base path: `/api/v1/agent/chat` - Persistent storage is **PostgreSQL-first**. Historical file storage only remains for one-time migration and external result payload files. ## Core identity model - `sessionId` = durable chat thread identifier exposed to clients and used for persistence. - `runtimeSessionId` = temporary opencode runtime execution identifier for a single active request. - Do **not** reintroduce `conversationId` / `clientSessionId` naming for the durable thread id. Use `sessionId`. ## Persistence design Canonical PostgreSQL tables: - `conversations` - `conversation_states` - `conversation_turns` - `runtime_sessions` - `learning_states` - `result_refs` - `memories` ### conversations Stores durable thread metadata: - `session_id` - actor / owner / project fields - `parent_session_id` - `title` - `status` - streaming lifecycle fields: - `is_streaming` - `active_runtime_session_id` - `streaming_started_at` `is_streaming` is persisted so the frontend can recover streaming state after refresh. Stream cleanup must be guarded by `active_runtime_session_id` so an old stream cannot clear a newer one. ### conversation_states Stores frontend-facing session UI state: - `messages` - `branch_groups` - `is_title_manually_edited` ### conversation_turns Stores transcript turns as one row per turn: - keyed by `turn_id` - linked by `session_id` - ordered by deterministic `turn_index` Do not fall back to legacy transcript files in runtime code. ### runtime_sessions Stores runtime binding context for internal tools and learning review/gate flows: - `runtime_session_id` - `session_id` - actor / project / trace fields - `allow_learning_write` - `learning_mode` - `released_at` This replaces the old alias-based `tool_session_contexts` model. ### result_refs `result_refs` is **metadata-only in PostgreSQL**: - metadata lives in PG - payload body lives outside PG via `payload_path` or future `object_key` Most payloads are large, so do not inline them into PostgreSQL. ### memories Durable memory is stored in PG, not markdown files. ## Runtime flow 1. Client sends/loads a `session_id`. 2. `ChatSessionBridge` binds that durable `sessionId` to a fresh `runtimeSessionId`. 3. Internal tools call back into the server using `runtimeSessionId`. 4. Transcript, memory, learning state, and result refs persist against `sessionId`. 5. Stream start sets `conversations.is_streaming = true`; stream completion clears it only if the runtime id still matches. ## Important files - `src/server.ts` - bootstrap, internal tool endpoints, app wiring - `src/chat/sessionBridge.ts` - `sessionId` vs `runtimeSessionId` binding - `src/db/index.ts` - PostgreSQL bootstrap and schema migration/cleanup - `src/conversations/store.ts` - durable session metadata + streaming state - `src/conversations/stateStore.ts` - UI state persistence - `src/history/store.ts` - transcript persistence - `src/session/runtimeSessionStore.ts` - runtime session persistence - `src/results/store.ts` - metadata-only result refs + external payload files - `src/results/resolver.ts` - result ref normalization and retrieval - `src/learning/orchestrator.ts` / `src/learning/stateStore.ts` - learning review pipeline - `src/memory/store.ts` - persistent memory store - `scripts/migrate-file-storage-to-postgres.ts` - one-time migration from legacy file storage ## Compatibility rules - Runtime code should target the canonical schema only. - Legacy column/table handling belongs only in `src/db/index.ts` bootstrap migration or `scripts/migrate-file-storage-to-postgres.ts`. - Do not add back file-based runtime persistence or compatibility reads unless a migration explicitly requires it. ## Validation Useful commands: ```bash bun run check PGHOST=... PGPORT=... PGUSER=... PGPASSWORD=... PGDATABASE=agent PGSSLMODE=disable bun test tests/conversations/store.test.ts tests/history/store.test.ts tests/session/runtimeSessionStore.test.ts tests/results/store.test.ts tests/routes/chatSession.test.ts ```