"""git_sources.branch: per-source branch to mirror (phase 135, task 01) Revision ID: 0024 Revises: 0023 Create Date: 2026-09-27 Phase 135 (a git source can pin the branch it mirrors — task 01, storage only): * ``git_sources.branch`` — TEXT NULLABLE, no server default: the branch the owner specifies for a git source (TODO-derived phase). NULL = the repo's DEFAULT branch — every pre-phase-135 row and every env-fallback synthetic row is a default-branch source by definition, so no row is touched and no backfill runs. A non-NULL value is validated at the API boundary (``app.rag.git_sources.validate_branch_name`` — task 02); the column itself is plain ``Text`` (the ``git_sources.token`` (0021) precedent: the column stores, the boundary validates). One additive, fully reversible migration (A13); no other schema change. The branch-aware clone/pull wiring (``clone_or_pull(…, branch)`` — task 03) and the API tri-state (task 02) are code — this revision only carries the column. """ from __future__ import annotations import sqlalchemy as sa from alembic import op revision = "0024" down_revision = "0023" branch_labels = None depends_on = None def upgrade() -> None: op.add_column("git_sources", sa.Column("branch", sa.Text(), nullable=True)) def downgrade() -> None: # The branch column is the only 0024 artefact — dropping it leaves # 0023's schema byte-identical (A13, fully reversible). NULL = # default branch, so no data migration in either direction. op.drop_column("git_sources", "branch")