Add core/db.py — SQLite schema with all 9 tables from DESIGN.md 3.5
Tables: projects, tasks, decisions, agent_logs, modules, pipelines, project_links, support_tickets, support_bot_config. WAL mode, foreign keys enabled, idempotent init. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bdb9fb4a65
commit
d7491705d9
2 changed files with 181 additions and 0 deletions
0
core/__init__.py
Normal file
0
core/__init__.py
Normal file
181
core/db.py
Normal file
181
core/db.py
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
"""
|
||||||
|
Kin — SQLite database schema and connection management.
|
||||||
|
All tables from DESIGN.md section 3.5 State Management.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
DB_PATH = Path(__file__).parent.parent / "kin.db"
|
||||||
|
|
||||||
|
SCHEMA = """
|
||||||
|
-- Проекты (центральный реестр)
|
||||||
|
CREATE TABLE IF NOT EXISTS projects (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
path TEXT NOT NULL,
|
||||||
|
tech_stack JSON,
|
||||||
|
status TEXT DEFAULT 'active',
|
||||||
|
priority INTEGER DEFAULT 5,
|
||||||
|
pm_prompt TEXT,
|
||||||
|
claude_md_path TEXT,
|
||||||
|
forgejo_repo TEXT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Задачи (привязаны к проекту)
|
||||||
|
CREATE TABLE IF NOT EXISTS tasks (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
project_id TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
status TEXT DEFAULT 'pending',
|
||||||
|
priority INTEGER DEFAULT 5,
|
||||||
|
assigned_role TEXT,
|
||||||
|
parent_task_id TEXT REFERENCES tasks(id),
|
||||||
|
brief JSON,
|
||||||
|
spec JSON,
|
||||||
|
review JSON,
|
||||||
|
test_result JSON,
|
||||||
|
security_result JSON,
|
||||||
|
forgejo_issue_id INTEGER,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Решения и грабли (внешняя память PM-агента)
|
||||||
|
CREATE TABLE IF NOT EXISTS decisions (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
project_id TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
task_id TEXT REFERENCES tasks(id),
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
category TEXT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT NOT NULL,
|
||||||
|
tags JSON,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Логи агентов (дебаг, обучение, cost tracking)
|
||||||
|
CREATE TABLE IF NOT EXISTS agent_logs (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
project_id TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
task_id TEXT REFERENCES tasks(id),
|
||||||
|
agent_role TEXT NOT NULL,
|
||||||
|
session_id TEXT,
|
||||||
|
action TEXT NOT NULL,
|
||||||
|
input_summary TEXT,
|
||||||
|
output_summary TEXT,
|
||||||
|
tokens_used INTEGER,
|
||||||
|
model TEXT,
|
||||||
|
cost_usd REAL,
|
||||||
|
success BOOLEAN,
|
||||||
|
error_message TEXT,
|
||||||
|
duration_seconds INTEGER,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Модули проекта (карта для PM)
|
||||||
|
CREATE TABLE IF NOT EXISTS modules (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
project_id TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
path TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
owner_role TEXT,
|
||||||
|
dependencies JSON,
|
||||||
|
UNIQUE(project_id, name)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Pipelines (история запусков)
|
||||||
|
CREATE TABLE IF NOT EXISTS pipelines (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
task_id TEXT NOT NULL REFERENCES tasks(id),
|
||||||
|
project_id TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
route_type TEXT NOT NULL,
|
||||||
|
steps JSON NOT NULL,
|
||||||
|
status TEXT DEFAULT 'running',
|
||||||
|
total_cost_usd REAL,
|
||||||
|
total_tokens INTEGER,
|
||||||
|
total_duration_seconds INTEGER,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
completed_at DATETIME
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Кросс-проектные зависимости
|
||||||
|
CREATE TABLE IF NOT EXISTS project_links (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
from_project TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
to_project TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Тикеты от пользователей
|
||||||
|
CREATE TABLE IF NOT EXISTS support_tickets (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
project_id TEXT NOT NULL REFERENCES projects(id),
|
||||||
|
source TEXT NOT NULL,
|
||||||
|
client_id TEXT,
|
||||||
|
client_message TEXT NOT NULL,
|
||||||
|
classification TEXT,
|
||||||
|
guard_result TEXT,
|
||||||
|
guard_reason TEXT,
|
||||||
|
anamnesis JSON,
|
||||||
|
task_id TEXT REFERENCES tasks(id),
|
||||||
|
response TEXT,
|
||||||
|
response_approved BOOLEAN DEFAULT FALSE,
|
||||||
|
status TEXT DEFAULT 'new',
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
resolved_at DATETIME
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Настройки бота для каждого проекта
|
||||||
|
CREATE TABLE IF NOT EXISTS support_bot_config (
|
||||||
|
project_id TEXT PRIMARY KEY REFERENCES projects(id),
|
||||||
|
telegram_bot_token TEXT,
|
||||||
|
welcome_message TEXT,
|
||||||
|
faq JSON,
|
||||||
|
auto_reply BOOLEAN DEFAULT FALSE,
|
||||||
|
require_approval BOOLEAN DEFAULT TRUE,
|
||||||
|
brand_voice TEXT,
|
||||||
|
forbidden_topics JSON,
|
||||||
|
escalation_keywords JSON
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Индексы
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tasks_project_status ON tasks(project_id, status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_project ON decisions(project_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_decisions_tags ON decisions(tags);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_logs_project ON agent_logs(project_id, created_at);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_agent_logs_cost ON agent_logs(project_id, cost_usd);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_project ON support_tickets(project_id, status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_tickets_client ON support_tickets(client_id);
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_connection(db_path: Path = DB_PATH) -> sqlite3.Connection:
|
||||||
|
conn = sqlite3.connect(str(db_path))
|
||||||
|
conn.execute("PRAGMA journal_mode=WAL")
|
||||||
|
conn.execute("PRAGMA foreign_keys=ON")
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
def init_db(db_path: Path = DB_PATH) -> sqlite3.Connection:
|
||||||
|
conn = get_connection(db_path)
|
||||||
|
conn.executescript(SCHEMA)
|
||||||
|
conn.commit()
|
||||||
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
conn = init_db()
|
||||||
|
tables = conn.execute(
|
||||||
|
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
|
||||||
|
).fetchall()
|
||||||
|
print(f"Initialized {len(tables)} tables:")
|
||||||
|
for t in tables:
|
||||||
|
print(f" - {t['name']}")
|
||||||
|
conn.close()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue