"""Add provenance + lifecycle fields to musehub_proposal_comments. author_user_id VARCHAR(128) nullable — content-addressed identity ID; enables sigil without extra DB lookup and survives handle changes. Backfill via backfill_comment_author_user_ids. agent_id VARCHAR(255) nullable — AI agent identifier (empty = human) model_id VARCHAR(255) nullable — model that authored the comment updated_at TIMESTAMPTZ nullable — set on edit; NULL = never edited is_deleted BOOLEAN NOT NULL — soft-delete (consistent with issue comments) DEFAULT FALSE Revision ID: 0069 Revises: 0068 """ from __future__ import annotations import sqlalchemy as sa from alembic import op revision = "0069" down_revision = "0068" branch_labels = None depends_on = None def upgrade() -> None: op.add_column("musehub_proposal_comments", sa.Column("author_user_id", sa.String(128), nullable=True)) op.add_column("musehub_proposal_comments", sa.Column("agent_id", sa.String(255), nullable=True)) op.add_column("musehub_proposal_comments", sa.Column("model_id", sa.String(255), nullable=True)) op.add_column("musehub_proposal_comments", sa.Column("updated_at", sa.DateTime(timezone=True), nullable=True)) op.add_column("musehub_proposal_comments", sa.Column("is_deleted", sa.Boolean(), nullable=False, server_default=sa.text("false"))) op.create_index("ix_musehub_proposal_comments_author_user_id", "musehub_proposal_comments", ["author_user_id"]) def downgrade() -> None: op.execute("DROP INDEX IF EXISTS ix_musehub_proposal_comments_author_user_id") op.drop_column("musehub_proposal_comments", "is_deleted") op.drop_column("musehub_proposal_comments", "updated_at") op.drop_column("musehub_proposal_comments", "model_id") op.drop_column("musehub_proposal_comments", "agent_id") op.drop_column("musehub_proposal_comments", "author_user_id")