-- Dual-path convergence (Gate B): apply the unified task system that -- Alembic migrations 0124 (columns/indexes/FK) and 0127 (drop legacy FK) -- create on the core path. Idempotent so both install paths converge to -- the identical schema. The end state has NO foreign key on contact_id. ALTER TABLE tasks ADD COLUMN IF NOT EXISTS assignee_type VARCHAR(20) NOT NULL DEFAULT 'user'; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS assignee_id UUID; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS entity_type VARCHAR(80); ALTER TABLE tasks ADD COLUMN IF NOT EXISTS entity_id UUID; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS creator_type VARCHAR(20) NOT NULL DEFAULT 'user'; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS creator_id UUID; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS parent_task_id UUID; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS depends_on JSONB NOT NULL DEFAULT '[]'::jsonb; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS task_type VARCHAR(30) NOT NULL DEFAULT 'todo'; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS success_criteria JSONB; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS target_date TIMESTAMPTZ; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS progress INTEGER NOT NULL DEFAULT 0; CREATE INDEX IF NOT EXISTS ix_tasks_tenant_entity ON tasks(tenant_id, entity_type, entity_id); CREATE INDEX IF NOT EXISTS ix_tasks_tenant_assignee ON tasks(tenant_id, assignee_type, assignee_id); CREATE INDEX IF NOT EXISTS ix_tasks_tenant_parent ON tasks(tenant_id, parent_task_id); CREATE INDEX IF NOT EXISTS ix_tasks_tenant_type ON tasks(tenant_id, task_type); DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'fk_tasks_parent_task_id' ) THEN ALTER TABLE tasks ADD CONSTRAINT fk_tasks_parent_task_id FOREIGN KEY (parent_task_id) REFERENCES tasks(id) ON DELETE CASCADE; END IF; END $$;