Files
settled-reach/db/schema.sql
T
jpmschweitzerandClaude Opus 4.6 63bb6ff7c7 chore(db): replace Commonwealth with Settled Reach in tooling and server
Updated docstrings in sqlite_connector, qdrant_connector,
decisions_sync, schema.sql, and two doc comments in generator.rs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:26:59 +01:00

96 lines
3.9 KiB
SQL

-- Settled Reach Project Ticketing Database Schema
-- Access via: python3 tooling/db/sqlite_connector.py <command>
-- DO NOT use sqlite3 CLI (crashes in Claude Code due to std::bad_alloc bug)
PRAGMA journal_mode=WAL;
PRAGMA foreign_keys=ON;
CREATE TABLE IF NOT EXISTS tickets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL CHECK(type IN ('initiative', 'epic', 'story', 'task', 'bug')),
parent_id INTEGER REFERENCES tickets(id),
title TEXT NOT NULL,
description TEXT,
status TEXT NOT NULL DEFAULT 'backlog' CHECK(status IN ('backlog', 'ready', 'in_progress', 'review', 'done', 'cancelled')),
priority TEXT DEFAULT 'medium' CHECK(priority IN ('critical', 'high', 'medium', 'low')),
assigned_to TEXT,
team TEXT, -- comma-separated team names, e.g. 'server', 'client,server'
decision_ref TEXT, -- e.g. 'D-010' or 'Q-001'
sprint_id INTEGER REFERENCES sprints(id),
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS sprints (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
goal TEXT,
start_date TEXT,
end_date TEXT,
status TEXT NOT NULL DEFAULT 'planning' CHECK(status IN ('planning', 'active', 'completed', 'cancelled')),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS ticket_deps (
blocker_id INTEGER NOT NULL REFERENCES tickets(id),
blocked_id INTEGER NOT NULL REFERENCES tickets(id),
PRIMARY KEY (blocker_id, blocked_id)
);
CREATE TABLE IF NOT EXISTS ticket_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ticket_id INTEGER NOT NULL REFERENCES tickets(id),
field TEXT NOT NULL,
old_value TEXT,
new_value TEXT,
changed_by TEXT,
changed_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS ticket_labels (
ticket_id INTEGER NOT NULL REFERENCES tickets(id),
label TEXT NOT NULL,
PRIMARY KEY (ticket_id, label)
);
CREATE INDEX IF NOT EXISTS idx_tickets_status ON tickets(status);
CREATE INDEX IF NOT EXISTS idx_tickets_type ON tickets(type);
CREATE INDEX IF NOT EXISTS idx_tickets_parent ON tickets(parent_id);
CREATE INDEX IF NOT EXISTS idx_tickets_sprint ON tickets(sprint_id);
CREATE INDEX IF NOT EXISTS idx_tickets_assigned ON tickets(assigned_to);
CREATE INDEX IF NOT EXISTS idx_tickets_decision ON tickets(decision_ref);
CREATE INDEX IF NOT EXISTS idx_tickets_team ON tickets(team);
CREATE INDEX IF NOT EXISTS idx_history_ticket ON ticket_history(ticket_id);
-- ---------------------------------------------------------------------------
-- Decision Sync Tables
-- Populated by: python3 tooling/db/decisions_sync.py
-- Source: decisions/*.md domain files
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS decisions (
id TEXT PRIMARY KEY,
type TEXT NOT NULL CHECK(type IN ('confirmed', 'question', 'rejected')),
domain TEXT NOT NULL,
title TEXT NOT NULL,
status TEXT DEFAULT 'active' CHECK(status IN ('active', 'superseded', 'resolved', 'open')),
round INTEGER,
date TEXT,
file_path TEXT NOT NULL,
synced_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS decision_refs (
source_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
target_id TEXT NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
ref_type TEXT NOT NULL CHECK(ref_type IN ('supersedes', 'references', 'resolves', 'depends_on')),
note TEXT,
PRIMARY KEY (source_id, target_id, ref_type)
);
CREATE INDEX IF NOT EXISTS idx_decisions_type ON decisions(type);
CREATE INDEX IF NOT EXISTS idx_decisions_domain ON decisions(domain);
CREATE INDEX IF NOT EXISTS idx_decisions_status ON decisions(status);
CREATE INDEX IF NOT EXISTS idx_decision_refs_source ON decision_refs(source_id);
CREATE INDEX IF NOT EXISTS idx_decision_refs_target ON decision_refs(target_id);