65f2fd8cdd
Reliability patch covering startup path resolution, install marker compatibility, export CLI request contracts, schema repair safety, hard-stop retry-loop handling, and the PR babysit status helper.
186 lines
11 KiB
SQL
186 lines
11 KiB
SQL
-- claude-mem SQLite schema
|
|
--
|
|
-- Authoritative shape of the database after all migrations through
|
|
-- runner.ts have been applied (current runner tip = migration 31;
|
|
-- SessionStore boot repair records migration 32). Fresh
|
|
-- databases boot directly into this shape; existing databases reach
|
|
-- it via the migration runner.
|
|
--
|
|
-- Source of truth: src/services/sqlite/migrations/runner.ts
|
|
-- Regenerated from the migration runner and current schema invariants.
|
|
--
|
|
-- Invariants enforced here (Plan 01):
|
|
-- * pending_messages.UNIQUE(content_session_id, tool_use_id) — replaces
|
|
-- in-memory pendingTools Map for ingestion pairing (Plan 03 also depends).
|
|
-- * pending_messages only needs pending/processing status for current
|
|
-- claim handling; worker_pid and stale-reset epoch columns are legacy.
|
|
-- * observations.UNIQUE(memory_session_id, content_hash) — replaces the
|
|
-- legacy dedup window; ON CONFLICT DO NOTHING absorbs duplicates.
|
|
|
|
CREATE TABLE IF NOT EXISTS schema_versions (
|
|
id INTEGER PRIMARY KEY,
|
|
version INTEGER UNIQUE NOT NULL,
|
|
applied_at TEXT NOT NULL
|
|
);
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
-- sdk_sessions: one row per Claude/Codex session observed by claude-mem.
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS sdk_sessions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
content_session_id TEXT UNIQUE NOT NULL,
|
|
memory_session_id TEXT UNIQUE,
|
|
project TEXT NOT NULL,
|
|
platform_source TEXT NOT NULL DEFAULT 'claude',
|
|
user_prompt TEXT,
|
|
started_at TEXT NOT NULL,
|
|
started_at_epoch INTEGER NOT NULL,
|
|
completed_at TEXT,
|
|
completed_at_epoch INTEGER,
|
|
status TEXT NOT NULL DEFAULT 'active'
|
|
CHECK(status IN ('active', 'completed', 'failed')),
|
|
worker_port INTEGER,
|
|
prompt_counter INTEGER DEFAULT 0,
|
|
custom_title TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_sdk_sessions_claude_id ON sdk_sessions(content_session_id);
|
|
CREATE INDEX IF NOT EXISTS idx_sdk_sessions_sdk_id ON sdk_sessions(memory_session_id);
|
|
CREATE INDEX IF NOT EXISTS idx_sdk_sessions_project ON sdk_sessions(project);
|
|
CREATE INDEX IF NOT EXISTS idx_sdk_sessions_status ON sdk_sessions(status);
|
|
CREATE INDEX IF NOT EXISTS idx_sdk_sessions_started ON sdk_sessions(started_at_epoch DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_sdk_sessions_platform_source ON sdk_sessions(platform_source);
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
-- observations: structured memory rows extracted from SDK output.
|
|
-- UNIQUE(memory_session_id, content_hash) replaces the legacy dedup window;
|
|
-- writes use INSERT … ON CONFLICT DO NOTHING.
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS observations (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
memory_session_id TEXT NOT NULL,
|
|
project TEXT NOT NULL,
|
|
text TEXT,
|
|
type TEXT NOT NULL,
|
|
title TEXT,
|
|
subtitle TEXT,
|
|
facts TEXT,
|
|
narrative TEXT,
|
|
concepts TEXT,
|
|
files_read TEXT,
|
|
files_modified TEXT,
|
|
prompt_number INTEGER,
|
|
discovery_tokens INTEGER DEFAULT 0,
|
|
content_hash TEXT,
|
|
agent_type TEXT,
|
|
agent_id TEXT,
|
|
merged_into_project TEXT,
|
|
generated_by_model TEXT,
|
|
metadata TEXT,
|
|
created_at TEXT NOT NULL,
|
|
created_at_epoch INTEGER NOT NULL,
|
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id)
|
|
ON DELETE CASCADE ON UPDATE CASCADE,
|
|
UNIQUE(memory_session_id, content_hash)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_sdk_session ON observations(memory_session_id);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_project ON observations(project);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_type ON observations(type);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_created ON observations(created_at_epoch DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_content_hash ON observations(content_hash, created_at_epoch);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_agent_type ON observations(agent_type);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_agent_id ON observations(agent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_observations_merged_into ON observations(merged_into_project);
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
-- session_summaries: one summary row per memory session.
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS session_summaries (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
memory_session_id TEXT NOT NULL,
|
|
project TEXT NOT NULL,
|
|
request TEXT,
|
|
investigated TEXT,
|
|
learned TEXT,
|
|
completed TEXT,
|
|
next_steps TEXT,
|
|
files_read TEXT,
|
|
files_edited TEXT,
|
|
notes TEXT,
|
|
prompt_number INTEGER,
|
|
discovery_tokens INTEGER DEFAULT 0,
|
|
merged_into_project TEXT,
|
|
created_at TEXT NOT NULL,
|
|
created_at_epoch INTEGER NOT NULL,
|
|
FOREIGN KEY(memory_session_id) REFERENCES sdk_sessions(memory_session_id)
|
|
ON DELETE CASCADE ON UPDATE CASCADE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_sdk_session ON session_summaries(memory_session_id);
|
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_project ON session_summaries(project);
|
|
CREATE INDEX IF NOT EXISTS idx_session_summaries_created ON session_summaries(created_at_epoch DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_summaries_merged_into ON session_summaries(merged_into_project);
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
-- pending_messages: persistent work queue for SDK messages.
|
|
-- UNIQUE(content_session_id, tool_use_id) preserves ingestion pairing without
|
|
-- any legacy worker_pid or stale-reset epoch column.
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS pending_messages (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_db_id INTEGER NOT NULL,
|
|
content_session_id TEXT NOT NULL,
|
|
tool_use_id TEXT,
|
|
message_type TEXT NOT NULL
|
|
CHECK(message_type IN ('observation', 'summarize')),
|
|
tool_name TEXT,
|
|
tool_input TEXT,
|
|
tool_response TEXT,
|
|
cwd TEXT,
|
|
last_user_message TEXT,
|
|
last_assistant_message TEXT,
|
|
prompt_number INTEGER,
|
|
status TEXT NOT NULL DEFAULT 'pending'
|
|
CHECK(status IN ('pending', 'processing')),
|
|
created_at_epoch INTEGER NOT NULL,
|
|
agent_type TEXT,
|
|
agent_id TEXT,
|
|
FOREIGN KEY (session_db_id) REFERENCES sdk_sessions(id) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_pending_messages_session ON pending_messages(session_db_id);
|
|
CREATE INDEX IF NOT EXISTS idx_pending_messages_status ON pending_messages(status);
|
|
CREATE INDEX IF NOT EXISTS idx_pending_messages_claude_session ON pending_messages(content_session_id);
|
|
CREATE UNIQUE INDEX IF NOT EXISTS ux_pending_session_tool
|
|
ON pending_messages(content_session_id, tool_use_id)
|
|
WHERE tool_use_id IS NOT NULL;
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
-- user_prompts: per-prompt history (UI + FTS search).
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS user_prompts (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
content_session_id TEXT NOT NULL,
|
|
prompt_number INTEGER NOT NULL,
|
|
prompt_text TEXT NOT NULL,
|
|
created_at TEXT NOT NULL,
|
|
created_at_epoch INTEGER NOT NULL,
|
|
FOREIGN KEY(content_session_id) REFERENCES sdk_sessions(content_session_id) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_user_prompts_claude_session ON user_prompts(content_session_id);
|
|
CREATE INDEX IF NOT EXISTS idx_user_prompts_created ON user_prompts(created_at_epoch DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_user_prompts_prompt_number ON user_prompts(prompt_number);
|
|
CREATE INDEX IF NOT EXISTS idx_user_prompts_lookup ON user_prompts(content_session_id, prompt_number);
|
|
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
-- observation_feedback: usage-signal tracking for tier routing.
|
|
-- ─────────────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS observation_feedback (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
observation_id INTEGER NOT NULL,
|
|
signal_type TEXT NOT NULL,
|
|
session_db_id INTEGER,
|
|
created_at_epoch INTEGER NOT NULL,
|
|
metadata TEXT,
|
|
FOREIGN KEY (observation_id) REFERENCES observations(id) ON DELETE CASCADE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_feedback_observation ON observation_feedback(observation_id);
|
|
CREATE INDEX IF NOT EXISTS idx_feedback_signal ON observation_feedback(signal_type);
|