Files
kebab/migrations/V005__chat_sessions.sql
altair823 6ca089286c review(p9-fb-18): 회차 1 nit 반영
- `App::build_retriever(mode) -> Result<Arc<dyn Retriever>>` 추출.
  `ask` 와 `ask_with_session` 모두 사용. 35+ 줄 retriever stack 중복
  제거 — 미래 retriever 변경이 한 곳만.
- V005 migration `chat_sessions.sql` 의 `citations_json` doc 수정:
  `Vec<Citation>` → `Vec<AnswerCitation>` (실제 stored type 과 일치).
  AnswerCitation 가 marker + Citation 등 포함하므로 deserialize 시
  type mismatch 회피.

15 app lib + 9 store chat_sessions + clippy 통과.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 06:25:13 +00:00

56 lines
2.3 KiB
SQL

-- V005__chat_sessions.sql — multi-turn conversation persistence.
--
-- p9-fb-17 introduces session-level storage for the multi-turn `Ask`
-- conversation primitive (p9-fb-15 facade, p9-fb-16 TUI). Each session
-- groups N consecutive Q/A turns under one `session_id`; the TUI
-- "이전 대화 이어가기" + the future `kebab ask --session foo` flag
-- (p9-fb-18) read+append against these tables.
--
-- Schema notes:
--
-- * `session_id` is user-supplied (`--session foo`) or auto-derived
-- from `blake3(first_question || first_ts)` as a 32-hex string. No
-- foreign-key into another table — sessions are sovereign.
--
-- * `chat_turns.turn_index` is monotonic per session (0-based). The
-- `UNIQUE(session_id, turn_index)` pair enforces the invariant on
-- the storage side so a buggy caller cannot double-append turn 3.
--
-- * `ON DELETE CASCADE` so `kebab reset --data-only` (p9-fb-06)
-- wipes both tables together — orphan turns can never outlive
-- their session.
--
-- * `config_snapshot_json` mirrors `eval_runs.config_snapshot_json`
-- (P5-1) — captures the prompt_template_version, llm.model, and
-- max_context_tokens that produced the session so a retroactive
-- answer-quality regression can be re-traced.
--
-- * `citations_json` carries `Vec<AnswerCitation>` (per p9-fb-18) —
-- each AnswerCitation holds a `Citation` plus `marker`, so the
-- answer can be redisplayed with the same citation markers a
-- future session sees on resume.
--
-- * `INTEGER` timestamps (unix epoch seconds) — same convention the
-- rest of the schema uses (P1-7 baselines this).
CREATE TABLE chat_sessions (
session_id TEXT PRIMARY KEY NOT NULL,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
title TEXT,
config_snapshot_json TEXT NOT NULL
) STRICT;
CREATE TABLE chat_turns (
turn_id TEXT PRIMARY KEY NOT NULL,
session_id TEXT NOT NULL REFERENCES chat_sessions(session_id) ON DELETE CASCADE,
turn_index INTEGER NOT NULL,
question TEXT NOT NULL,
answer TEXT NOT NULL,
citations_json TEXT NOT NULL,
created_at INTEGER NOT NULL,
UNIQUE(session_id, turn_index)
) STRICT;
CREATE INDEX idx_chat_turns_session ON chat_turns(session_id, turn_index);