-- Migration 006: Merge Requests, MR Labels, Assignees, Reviewers -- Schema version: 6 -- Adds CP2 MR ingestion support -- Merge requests table CREATE TABLE merge_requests ( id INTEGER PRIMARY KEY, gitlab_id INTEGER UNIQUE NOT NULL, project_id INTEGER NOT NULL REFERENCES projects(id), iid INTEGER NOT NULL, title TEXT, description TEXT, state TEXT, -- 'opened' | 'merged' | 'closed' | 'locked' draft INTEGER NOT NULL DEFAULT 0, -- 0/1 (SQLite boolean) - work-in-progress status author_username TEXT, source_branch TEXT, target_branch TEXT, head_sha TEXT, -- Current commit SHA at head of source branch (CP3-ready) references_short TEXT, -- Short reference e.g. "!123" (CP3-ready for display) references_full TEXT, -- Full reference e.g. "group/project!123" (CP3-ready for cross-project) detailed_merge_status TEXT, -- preferred, non-deprecated (replaces merge_status) merge_user_username TEXT, -- preferred over deprecated merged_by created_at INTEGER, -- ms epoch UTC updated_at INTEGER, -- ms epoch UTC merged_at INTEGER, -- ms epoch UTC (NULL if not merged) closed_at INTEGER, -- ms epoch UTC (NULL if not closed) last_seen_at INTEGER NOT NULL, -- ms epoch UTC, updated on every upsert -- Prevents re-fetching discussions on cursor rewind / reruns unless MR changed. discussions_synced_for_updated_at INTEGER, -- Sync health telemetry for debuggability discussions_sync_last_attempt_at INTEGER, -- ms epoch UTC of last sync attempt discussions_sync_attempts INTEGER DEFAULT 0, -- count of sync attempts for this MR version discussions_sync_last_error TEXT, -- last error message if sync failed web_url TEXT, raw_payload_id INTEGER REFERENCES raw_payloads(id) ); CREATE INDEX idx_mrs_project_updated ON merge_requests(project_id, updated_at); CREATE INDEX idx_mrs_author ON merge_requests(author_username); CREATE INDEX idx_mrs_target_branch ON merge_requests(project_id, target_branch); CREATE INDEX idx_mrs_source_branch ON merge_requests(project_id, source_branch); CREATE INDEX idx_mrs_state ON merge_requests(project_id, state); CREATE INDEX idx_mrs_detailed_merge_status ON merge_requests(project_id, detailed_merge_status); CREATE INDEX idx_mrs_draft ON merge_requests(project_id, draft); CREATE INDEX idx_mrs_discussions_sync ON merge_requests(project_id, discussions_synced_for_updated_at); CREATE UNIQUE INDEX uq_mrs_project_iid ON merge_requests(project_id, iid); -- MR-Label junction (reuses labels table from CP1) CREATE TABLE mr_labels ( merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE, label_id INTEGER REFERENCES labels(id) ON DELETE CASCADE, PRIMARY KEY(merge_request_id, label_id) ); CREATE INDEX idx_mr_labels_label ON mr_labels(label_id); -- MR assignees (same pattern as issue_assignees) CREATE TABLE mr_assignees ( merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE, username TEXT NOT NULL, PRIMARY KEY(merge_request_id, username) ); CREATE INDEX idx_mr_assignees_username ON mr_assignees(username); -- MR reviewers (MR-specific, not applicable to issues) CREATE TABLE mr_reviewers ( merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE, username TEXT NOT NULL, PRIMARY KEY(merge_request_id, username) ); CREATE INDEX idx_mr_reviewers_username ON mr_reviewers(username); -- Add FK constraint to discussions table for merge_request_id -- Note: SQLite doesn't support ADD CONSTRAINT, the FK was defined in CP1 but nullable -- We just need to add an index if not already present CREATE INDEX IF NOT EXISTS idx_discussions_mr_id ON discussions(merge_request_id); CREATE INDEX IF NOT EXISTS idx_discussions_mr_resolved ON discussions(merge_request_id, resolved, resolvable); -- Additional indexes for DiffNote queries (notes table from CP1) -- These composite indexes enable efficient file-context queries for CP3 CREATE INDEX IF NOT EXISTS idx_notes_type ON notes(note_type); CREATE INDEX IF NOT EXISTS idx_notes_new_path ON notes(position_new_path); CREATE INDEX IF NOT EXISTS idx_notes_new_path_line ON notes(position_new_path, position_new_line); CREATE INDEX IF NOT EXISTS idx_notes_old_path_line ON notes(position_old_path, position_old_line); -- CP2: capture richer diff note position shapes (minimal, still MVP) -- These fields support modern GitLab diff note semantics without full diff reconstruction ALTER TABLE notes ADD COLUMN position_type TEXT; -- 'text' | 'image' | 'file' ALTER TABLE notes ADD COLUMN position_line_range_start INTEGER; -- multi-line comment start ALTER TABLE notes ADD COLUMN position_line_range_end INTEGER; -- multi-line comment end -- DiffNote SHA triplet for commit context (CP3-ready, zero extra API cost) ALTER TABLE notes ADD COLUMN position_base_sha TEXT; -- Base commit SHA for diff ALTER TABLE notes ADD COLUMN position_start_sha TEXT; -- Start commit SHA for diff ALTER TABLE notes ADD COLUMN position_head_sha TEXT; -- Head commit SHA for diff -- Update schema version INSERT INTO schema_version (version, applied_at, description) VALUES (6, strftime('%s', 'now') * 1000, 'Merge requests, MR labels, assignees, reviewers');