feat(db): add decisions sync script and schema tables

Add decisions_sync.py that parses decisions/*.md markdown headings,
extracts metadata (type, domain, status, round, date), and upserts
into SQLite. Two-pass approach: decisions first, then cross-references
to avoid FK violations on forward references.

Schema adds decisions table (52 rows) and decision_refs table (29 rows)
with cascading deletes. Makefile gains decisions-sync, decisions-coverage,
decisions-active, and decisions-orphan targets. Sync runs as part of
make setup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 09:29:48 +01:00
co-authored by Claude Opus 4.6
parent 4f5ee0274b
commit 485b02db67
4 changed files with 472 additions and 2 deletions
+32
View File
@@ -59,3 +59,35 @@ 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_history_ticket ON ticket_history(ticket_id);
-- ---------------------------------------------------------------------------
-- Decision Sync Tables
-- Populated by: python3 db/connectors/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);