-- Additive, rebuildable BLIF Flow v2 projection scaffolding. -- This migration does not alter opportunities.stage or activate Flow v2. CREATE TABLE IF NOT EXISTS opportunity_flow_state_v2 ( opportunity_id UUID PRIMARY KEY REFERENCES opportunities(id) ON DELETE CASCADE, material_process_key TEXT NOT NULL, canonical_opportunity_id UUID NOT NULL REFERENCES opportunities(id) ON DELETE CASCADE, is_duplicate_representation BOOLEAN NOT NULL DEFAULT FALSE, business_state TEXT NOT NULL, business_next_action TEXT, diagnostic_status TEXT NOT NULL DEFAULT 'clear', confidence TEXT NOT NULL DEFAULT 'low', reason_code TEXT NOT NULL, reason_text TEXT NOT NULL, evidence_refs JSONB NOT NULL DEFAULT '[]'::jsonb, flow_version TEXT NOT NULL, source_fingerprint TEXT NOT NULL, derived_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS ix_opportunity_flow_state_v2_material_process_key ON opportunity_flow_state_v2(material_process_key); CREATE INDEX IF NOT EXISTS ix_opportunity_flow_state_v2_canonical ON opportunity_flow_state_v2(canonical_opportunity_id); CREATE INDEX IF NOT EXISTS ix_opportunity_flow_state_v2_business_state ON opportunity_flow_state_v2(business_state); ALTER TABLE tasks ADD COLUMN IF NOT EXISTS resolution_code TEXT; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS resolved_at TIMESTAMPTZ; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS resolved_by_event_id UUID REFERENCES opportunity_events(id) ON DELETE SET NULL; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS superseded_by_task_id UUID REFERENCES tasks(id) ON DELETE SET NULL; CREATE INDEX IF NOT EXISTS ix_tasks_resolved_by_event_id ON tasks(resolved_by_event_id); CREATE INDEX IF NOT EXISTS ix_tasks_superseded_by_task_id ON tasks(superseded_by_task_id); CREATE TABLE IF NOT EXISTS opportunity_flow_transitions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), opportunity_id UUID NOT NULL REFERENCES opportunities(id) ON DELETE CASCADE, from_state TEXT, to_state TEXT NOT NULL, reason_code TEXT NOT NULL, reason_text TEXT NOT NULL, evidence_refs JSONB NOT NULL DEFAULT '[]'::jsonb, flow_version TEXT NOT NULL, source_fingerprint TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (opportunity_id, from_state, to_state, flow_version, source_fingerprint) ); CREATE INDEX IF NOT EXISTS ix_opportunity_flow_transitions_opportunity_created ON opportunity_flow_transitions(opportunity_id, created_at DESC);