"""GEMS Pass 2: add repo_id FK to workstreams (ADR-001 alignment) Revision ID: f2a3b4c5d6e7 Revises: e1f2a3b4c5d6 Create Date: 2026-03-02 00:00:00.000000 """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql revision: str = "f2a3b4c5d6e7" down_revision: Union[str, None] = "e1f2a3b4c5d6" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.add_column( "workstreams", sa.Column("repo_id", postgresql.UUID(as_uuid=True), nullable=True), ) op.create_foreign_key( "fk_workstream_repo_id", "workstreams", "managed_repos", ["repo_id"], ["id"], ondelete="SET NULL", ) op.create_index("ix_workstreams_repo_id", "workstreams", ["repo_id"]) # Best-effort backfill: topic → domain → first repo (by created_at) # Records with no repo in their domain remain NULL (requires manual resolution) op.execute(""" UPDATE workstreams ws SET repo_id = sub.repo_id FROM ( SELECT DISTINCT ON (ws.id) ws.id AS ws_id, mr.id AS repo_id FROM workstreams ws JOIN topics t ON t.id = ws.topic_id JOIN managed_repos mr ON mr.domain_id = t.domain_id WHERE mr.status = 'active' ORDER BY ws.id, mr.created_at ) sub WHERE ws.id = sub.ws_id """) def downgrade() -> None: op.drop_index("ix_workstreams_repo_id", table_name="workstreams") op.drop_constraint("fk_workstream_repo_id", "workstreams", type_="foreignkey") op.drop_column("workstreams", "repo_id")