@@ -38,7 +38,20 @@ CREATE TABLE IF NOT EXISTS gitmem_learnings (
3838 updated_at TIMESTAMPTZ DEFAULT NOW()
3939);
4040
41- -- Index for faster vector search
41+ -- Migration: ensure all columns exist (idempotent for upgrades)
42+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS embedding vector(1536 );
43+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS source_linear_issue TEXT ;
44+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS persona_name TEXT ;
45+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS why_this_matters TEXT ;
46+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS action_protocol TEXT ;
47+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS self_check_criteria TEXT ;
48+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS is_active BOOLEAN DEFAULT true;
49+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS decay_multiplier FLOAT DEFAULT 1 .0 ;
50+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS repeat_mistake BOOLEAN DEFAULT false;
51+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS related_scar_id UUID;
52+ ALTER TABLE gitmem_learnings ADD COLUMN IF NOT EXISTS repeat_mistake_details JSONB;
53+
54+ -- Indexes (created after migration ensures columns exist)
4255CREATE INDEX IF NOT EXISTS idx_gitmem_learnings_embedding
4356 ON gitmem_learnings USING ivfflat (embedding vector_cosine_ops)
4457 WITH (lists = 10 );
@@ -71,6 +84,14 @@ CREATE TABLE IF NOT EXISTS gitmem_sessions (
7184 updated_at TIMESTAMPTZ DEFAULT NOW()
7285);
7386
87+ -- Migration: ensure all columns exist
88+ ALTER TABLE gitmem_sessions ADD COLUMN IF NOT EXISTS embedding vector(1536 );
89+ ALTER TABLE gitmem_sessions ADD COLUMN IF NOT EXISTS linear_issue TEXT ;
90+ ALTER TABLE gitmem_sessions ADD COLUMN IF NOT EXISTS recording_path TEXT ;
91+ ALTER TABLE gitmem_sessions ADD COLUMN IF NOT EXISTS transcript_path TEXT ;
92+ ALTER TABLE gitmem_sessions ADD COLUMN IF NOT EXISTS close_compliance JSONB;
93+ ALTER TABLE gitmem_sessions ADD COLUMN IF NOT EXISTS rapport_summary TEXT ;
94+
7495CREATE INDEX IF NOT EXISTS idx_gitmem_sessions_agent
7596 ON gitmem_sessions (agent);
7697
@@ -96,6 +117,12 @@ CREATE TABLE IF NOT EXISTS gitmem_decisions (
96117 created_at TIMESTAMPTZ DEFAULT NOW()
97118);
98119
120+ -- Migration: ensure all columns exist
121+ ALTER TABLE gitmem_decisions ADD COLUMN IF NOT EXISTS embedding vector(1536 );
122+ ALTER TABLE gitmem_decisions ADD COLUMN IF NOT EXISTS personas_involved TEXT [] DEFAULT ' {}' ;
123+ ALTER TABLE gitmem_decisions ADD COLUMN IF NOT EXISTS docs_affected TEXT [] DEFAULT ' {}' ;
124+ ALTER TABLE gitmem_decisions ADD COLUMN IF NOT EXISTS linear_issue TEXT ;
125+
99126CREATE INDEX IF NOT EXISTS idx_gitmem_decisions_session
100127 ON gitmem_decisions (session_id);
101128
@@ -125,6 +152,13 @@ CREATE INDEX IF NOT EXISTS idx_gitmem_scar_usage_scar
125152CREATE INDEX IF NOT EXISTS idx_gitmem_scar_usage_session
126153 ON gitmem_scar_usage (session_id);
127154
155+ -- Migration: add columns for older installs
156+ ALTER TABLE gitmem_scar_usage ADD COLUMN IF NOT EXISTS issue_id TEXT ;
157+ ALTER TABLE gitmem_scar_usage ADD COLUMN IF NOT EXISTS issue_identifier TEXT ;
158+ ALTER TABLE gitmem_scar_usage ADD COLUMN IF NOT EXISTS acknowledged_at TIMESTAMPTZ ;
159+ ALTER TABLE gitmem_scar_usage ADD COLUMN IF NOT EXISTS referenced BOOLEAN ;
160+ ALTER TABLE gitmem_scar_usage ADD COLUMN IF NOT EXISTS variant_id UUID;
161+
128162-- ============================================================================
129163-- Threads table (cross-session work tracking)
130164-- ============================================================================
@@ -397,54 +431,49 @@ ALTER TABLE gitmem_query_metrics ENABLE ROW LEVEL SECURITY;
397431ALTER TABLE scar_enforcement_variants ENABLE ROW LEVEL SECURITY;
398432
399433-- Service role has full access (used by the MCP server)
400- CREATE POLICY " Service role full access" ON gitmem_learnings
401- FOR ALL USING (auth .role () = ' service_role' );
402-
403- CREATE POLICY " Service role full access" ON gitmem_sessions
404- FOR ALL USING (auth .role () = ' service_role' );
405-
406- CREATE POLICY " Service role full access" ON gitmem_decisions
407- FOR ALL USING (auth .role () = ' service_role' );
408-
409- CREATE POLICY " Service role full access" ON gitmem_scar_usage
410- FOR ALL USING (auth .role () = ' service_role' );
411-
412- CREATE POLICY " Service role full access" ON gitmem_threads
413- FOR ALL USING (auth .role () = ' service_role' );
414-
415- CREATE POLICY " Service role full access" ON knowledge_triples
416- FOR ALL USING (auth .role () = ' service_role' );
417-
418- CREATE POLICY " Service role full access" ON gitmem_query_metrics
419- FOR ALL USING (auth .role () = ' service_role' );
420-
421- CREATE POLICY " Service role full access" ON scar_enforcement_variants
422- FOR ALL USING (auth .role () = ' service_role' );
423-
424- -- Block anonymous access
425- CREATE POLICY " Block anonymous access" ON gitmem_learnings
426- FOR ALL USING (auth .role () != ' anon' );
427-
428- CREATE POLICY " Block anonymous access" ON gitmem_sessions
429- FOR ALL USING (auth .role () != ' anon' );
430-
431- CREATE POLICY " Block anonymous access" ON gitmem_decisions
432- FOR ALL USING (auth .role () != ' anon' );
433-
434- CREATE POLICY " Block anonymous access" ON gitmem_scar_usage
435- FOR ALL USING (auth .role () != ' anon' );
436-
437- CREATE POLICY " Block anonymous access" ON gitmem_threads
438- FOR ALL USING (auth .role () != ' anon' );
439-
440- CREATE POLICY " Block anonymous access" ON knowledge_triples
441- FOR ALL USING (auth .role () != ' anon' );
442-
443- CREATE POLICY " Block anonymous access" ON gitmem_query_metrics
444- FOR ALL USING (auth .role () != ' anon' );
445-
446- CREATE POLICY " Block anonymous access" ON scar_enforcement_variants
447- FOR ALL USING (auth .role () != ' anon' );
434+ -- Drop-then-create for idempotency (CREATE POLICY has no IF NOT EXISTS)
435+ DO $$ BEGIN
436+ -- gitmem_learnings
437+ DROP POLICY IF EXISTS " Service role full access" ON gitmem_learnings;
438+ CREATE POLICY " Service role full access" ON gitmem_learnings FOR ALL USING (auth .role () = ' service_role' );
439+ DROP POLICY IF EXISTS " Block anonymous access" ON gitmem_learnings;
440+ CREATE POLICY " Block anonymous access" ON gitmem_learnings FOR ALL USING (auth .role () != ' anon' );
441+ -- gitmem_sessions
442+ DROP POLICY IF EXISTS " Service role full access" ON gitmem_sessions;
443+ CREATE POLICY " Service role full access" ON gitmem_sessions FOR ALL USING (auth .role () = ' service_role' );
444+ DROP POLICY IF EXISTS " Block anonymous access" ON gitmem_sessions;
445+ CREATE POLICY " Block anonymous access" ON gitmem_sessions FOR ALL USING (auth .role () != ' anon' );
446+ -- gitmem_decisions
447+ DROP POLICY IF EXISTS " Service role full access" ON gitmem_decisions;
448+ CREATE POLICY " Service role full access" ON gitmem_decisions FOR ALL USING (auth .role () = ' service_role' );
449+ DROP POLICY IF EXISTS " Block anonymous access" ON gitmem_decisions;
450+ CREATE POLICY " Block anonymous access" ON gitmem_decisions FOR ALL USING (auth .role () != ' anon' );
451+ -- gitmem_scar_usage
452+ DROP POLICY IF EXISTS " Service role full access" ON gitmem_scar_usage;
453+ CREATE POLICY " Service role full access" ON gitmem_scar_usage FOR ALL USING (auth .role () = ' service_role' );
454+ DROP POLICY IF EXISTS " Block anonymous access" ON gitmem_scar_usage;
455+ CREATE POLICY " Block anonymous access" ON gitmem_scar_usage FOR ALL USING (auth .role () != ' anon' );
456+ -- gitmem_threads
457+ DROP POLICY IF EXISTS " Service role full access" ON gitmem_threads;
458+ CREATE POLICY " Service role full access" ON gitmem_threads FOR ALL USING (auth .role () = ' service_role' );
459+ DROP POLICY IF EXISTS " Block anonymous access" ON gitmem_threads;
460+ CREATE POLICY " Block anonymous access" ON gitmem_threads FOR ALL USING (auth .role () != ' anon' );
461+ -- knowledge_triples
462+ DROP POLICY IF EXISTS " Service role full access" ON knowledge_triples;
463+ CREATE POLICY " Service role full access" ON knowledge_triples FOR ALL USING (auth .role () = ' service_role' );
464+ DROP POLICY IF EXISTS " Block anonymous access" ON knowledge_triples;
465+ CREATE POLICY " Block anonymous access" ON knowledge_triples FOR ALL USING (auth .role () != ' anon' );
466+ -- gitmem_query_metrics
467+ DROP POLICY IF EXISTS " Service role full access" ON gitmem_query_metrics;
468+ CREATE POLICY " Service role full access" ON gitmem_query_metrics FOR ALL USING (auth .role () = ' service_role' );
469+ DROP POLICY IF EXISTS " Block anonymous access" ON gitmem_query_metrics;
470+ CREATE POLICY " Block anonymous access" ON gitmem_query_metrics FOR ALL USING (auth .role () != ' anon' );
471+ -- scar_enforcement_variants
472+ DROP POLICY IF EXISTS " Service role full access" ON scar_enforcement_variants;
473+ CREATE POLICY " Service role full access" ON scar_enforcement_variants FOR ALL USING (auth .role () = ' service_role' );
474+ DROP POLICY IF EXISTS " Block anonymous access" ON scar_enforcement_variants;
475+ CREATE POLICY " Block anonymous access" ON scar_enforcement_variants FOR ALL USING (auth .role () != ' anon' );
476+ END $$;
448477
449478-- ============================================================================
450479-- Auto-update timestamps
@@ -457,10 +486,12 @@ BEGIN
457486END;
458487$$ LANGUAGE plpgsql;
459488
489+ DROP TRIGGER IF EXISTS gitmem_learnings_updated ON gitmem_learnings;
460490CREATE TRIGGER gitmem_learnings_updated
461491 BEFORE UPDATE ON gitmem_learnings
462492 FOR EACH ROW EXECUTE FUNCTION gitmem_update_timestamp();
463493
494+ DROP TRIGGER IF EXISTS gitmem_sessions_updated ON gitmem_sessions;
464495CREATE TRIGGER gitmem_sessions_updated
465496 BEFORE UPDATE ON gitmem_sessions
466497 FOR EACH ROW EXECUTE FUNCTION gitmem_update_timestamp();
0 commit comments