-- Migration 019: Pipeline-System - Konfigurierbare mehrstufige Analysen -- Ermöglicht Admin-Verwaltung von Pipeline-Konfigurationen (Issue #28) -- Created: 2026-03-25 -- ======================================== -- 1. Erweitere ai_prompts für Reset-Feature -- ======================================== ALTER TABLE ai_prompts ADD COLUMN IF NOT EXISTS is_system_default BOOLEAN DEFAULT FALSE, ADD COLUMN IF NOT EXISTS default_template TEXT; COMMENT ON COLUMN ai_prompts.is_system_default IS 'true = System-Prompt mit Reset-Funktion'; COMMENT ON COLUMN ai_prompts.default_template IS 'Original-Template für Reset-to-Default'; -- Markiere bestehende Pipeline-Prompts als System-Defaults UPDATE ai_prompts SET is_system_default = true, default_template = template WHERE slug LIKE 'pipeline_%'; -- ======================================== -- 2. Create pipeline_configs table -- ======================================== CREATE TABLE IF NOT EXISTS pipeline_configs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(255) NOT NULL UNIQUE, description TEXT, is_default BOOLEAN DEFAULT FALSE, active BOOLEAN DEFAULT TRUE, -- Module configuration: which data sources to include modules JSONB NOT NULL DEFAULT '{}'::jsonb, -- Example: {"körper": true, "ernährung": true, "training": true, "schlaf": false} -- Timeframes per module (days) timeframes JSONB NOT NULL DEFAULT '{}'::jsonb, -- Example: {"körper": 30, "ernährung": 30, "training": 14} -- Stage 1 prompts (parallel execution) stage1_prompts TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[], -- Example: ARRAY['pipeline_body', 'pipeline_nutrition', 'pipeline_activity'] -- Stage 2 prompt (synthesis) stage2_prompt VARCHAR(100) NOT NULL, -- Example: 'pipeline_synthesis' -- Stage 3 prompt (optional, e.g., goals) stage3_prompt VARCHAR(100), -- Example: 'pipeline_goals' created TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); -- ======================================== -- 3. Create indexes -- ======================================== CREATE INDEX IF NOT EXISTS idx_pipeline_configs_default ON pipeline_configs(is_default) WHERE is_default = true; CREATE INDEX IF NOT EXISTS idx_pipeline_configs_active ON pipeline_configs(active); -- ======================================== -- 4. Seed: Standard-Pipeline "Alltags-Check" -- ======================================== INSERT INTO pipeline_configs ( name, description, is_default, modules, timeframes, stage1_prompts, stage2_prompt, stage3_prompt ) VALUES ( 'Alltags-Check', 'Standard-Analyse: Körper, Ernährung, Training über die letzten 2-4 Wochen', true, '{"körper": true, "ernährung": true, "training": true, "schlaf": false, "vitalwerte": false, "mentales": false, "ziele": false}'::jsonb, '{"körper": 30, "ernährung": 30, "training": 14}'::jsonb, ARRAY['pipeline_body', 'pipeline_nutrition', 'pipeline_activity'], 'pipeline_synthesis', 'pipeline_goals' ) ON CONFLICT (name) DO NOTHING; -- ======================================== -- 5. Seed: Erweiterte Pipelines (optional) -- ======================================== -- Schlaf-Fokus Pipeline (wenn Schlaf-Prompts existieren) INSERT INTO pipeline_configs ( name, description, is_default, modules, timeframes, stage1_prompts, stage2_prompt, stage3_prompt ) VALUES ( 'Schlaf & Erholung', 'Analyse von Schlaf, Vitalwerten und Erholungsstatus', false, '{"schlaf": true, "vitalwerte": true, "training": true, "körper": false, "ernährung": false, "mentales": false, "ziele": false}'::jsonb, '{"schlaf": 14, "vitalwerte": 7, "training": 14}'::jsonb, ARRAY['pipeline_sleep', 'pipeline_vitals', 'pipeline_activity'], 'pipeline_synthesis', NULL ) ON CONFLICT (name) DO NOTHING; -- Wettkampf-Analyse (langfristiger Trend) INSERT INTO pipeline_configs ( name, description, is_default, modules, timeframes, stage1_prompts, stage2_prompt, stage3_prompt ) VALUES ( 'Wettkampf-Analyse', 'Langfristige Analyse für Wettkampfvorbereitung (90 Tage)', false, '{"körper": true, "training": true, "vitalwerte": true, "ernährung": true, "schlaf": false, "mentales": false, "ziele": true}'::jsonb, '{"körper": 90, "training": 90, "vitalwerte": 30, "ernährung": 60}'::jsonb, ARRAY['pipeline_body', 'pipeline_activity', 'pipeline_vitals', 'pipeline_nutrition'], 'pipeline_synthesis', 'pipeline_goals' ) ON CONFLICT (name) DO NOTHING; -- ======================================== -- 6. Trigger für updated timestamp -- ======================================== DROP TRIGGER IF EXISTS trigger_pipeline_configs_updated ON pipeline_configs; CREATE TRIGGER trigger_pipeline_configs_updated BEFORE UPDATE ON pipeline_configs FOR EACH ROW EXECUTE FUNCTION update_updated_timestamp(); -- ======================================== -- 7. Constraints & Validation -- ======================================== -- Only one default config allowed (enforced via partial unique index) CREATE UNIQUE INDEX IF NOT EXISTS idx_pipeline_configs_single_default ON pipeline_configs(is_default) WHERE is_default = true; -- ======================================== -- 8. Comments (Documentation) -- ======================================== COMMENT ON TABLE pipeline_configs IS 'v9f Issue #28: Konfigurierbare Pipeline-Analysen. Admins können mehrere Pipeline-Configs erstellen mit unterschiedlichen Modulen und Zeiträumen.'; COMMENT ON COLUMN pipeline_configs.modules IS 'JSONB: Welche Module aktiv sind (boolean flags)'; COMMENT ON COLUMN pipeline_configs.timeframes IS 'JSONB: Zeiträume pro Modul in Tagen'; COMMENT ON COLUMN pipeline_configs.stage1_prompts IS 'Array von slug-Werten für parallele Stage-1-Prompts'; COMMENT ON COLUMN pipeline_configs.stage2_prompt IS 'Slug des Synthese-Prompts (kombiniert Stage-1-Ergebnisse)'; COMMENT ON COLUMN pipeline_configs.stage3_prompt IS 'Optionaler Slug für Stage-3-Prompt (z.B. Zielabgleich)';