"""change_proposals (AI propose-then-confirm) Revision ID: a1b2c3d4e5f6 Revises: d4a9c1e7b2f3 Create Date: 2026-06-09 """ from collections.abc import Sequence import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql revision: str = "a1b2c3d4e5f6" down_revision: str | None = "d4a9c1e7b2f3" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None def upgrade() -> None: op.create_table( "change_proposals", sa.Column("id", sa.Uuid(), nullable=False), sa.Column("tree_id", sa.Uuid(), nullable=False), sa.Column( "status", sa.Enum("pending", "applied", "rejected", name="change_proposal_status"), server_default="pending", nullable=False, ), sa.Column( "origin", sa.Enum("assistant", "contributor", name="change_proposal_origin"), server_default="assistant", nullable=False, ), sa.Column("created_by_user_id", sa.Uuid(), nullable=True), sa.Column("summary", sa.String(length=512), nullable=False), sa.Column("rationale", sa.Text(), nullable=True), sa.Column("operations", postgresql.JSONB(astext_type=sa.Text()), nullable=False), sa.Column("reviewed_by_user_id", sa.Uuid(), nullable=True), sa.Column("reviewed_at", sa.DateTime(timezone=True), nullable=True), sa.Column("review_note", sa.String(length=512), nullable=True), sa.Column("apply_error", sa.Text(), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True), sa.ForeignKeyConstraint(["tree_id"], ["trees.id"], ondelete="CASCADE"), sa.ForeignKeyConstraint(["created_by_user_id"], ["users.id"], ondelete="SET NULL"), sa.ForeignKeyConstraint(["reviewed_by_user_id"], ["users.id"], ondelete="SET NULL"), sa.PrimaryKeyConstraint("id"), ) op.create_index("ix_change_proposals_tree_id", "change_proposals", ["tree_id"]) op.create_index("ix_change_proposals_status", "change_proposals", ["status"]) def downgrade() -> None: op.drop_index("ix_change_proposals_status", table_name="change_proposals") op.drop_index("ix_change_proposals_tree_id", table_name="change_proposals") op.drop_table("change_proposals") sa.Enum(name="change_proposal_status").drop(op.get_bind()) sa.Enum(name="change_proposal_origin").drop(op.get_bind())