"""Cumulative curation coverage marks and model fallback candidates.""" from collections.abc import Sequence import sqlalchemy as sa from alembic import op revision: str = "20260808_0014" down_revision: str | Sequence[str] | None = "20260806_0013" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None def upgrade() -> None: with op.batch_alter_table("memory_references") as batch: batch.add_column(sa.Column("covered_reason", sa.String(length=16), nullable=True)) batch.add_column(sa.Column("reviewed_revision", sa.Integer(), nullable=True)) batch.add_column(sa.Column("reviewed_job_id", sa.String(length=36), nullable=True)) with op.batch_alter_table("curation_model_configs") as batch: batch.add_column( sa.Column("candidates_json", sa.Text(), nullable=False, server_default="[]") ) batch.add_column( sa.Column( "candidate_cooldown_seconds", sa.Integer(), nullable=False, server_default="600", ) ) op.create_table( "curation_model_candidate_states", sa.Column("model_name", sa.String(length=300), primary_key=True), sa.Column("cooling_until", sa.DateTime(timezone=True), nullable=True), sa.Column("last_error_code", sa.String(length=100), nullable=True), sa.Column("last_error_message", sa.Text(), nullable=True), sa.Column("last_success_at", sa.DateTime(timezone=True), nullable=True), sa.Column("last_failure_at", sa.DateTime(timezone=True), nullable=True), sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False), ) op.create_index( "ix_curation_model_candidate_states_cooling_until", "curation_model_candidate_states", ["cooling_until"], ) # Existing covered memories were all covered through citation; backfill the reason so # the UI does not show them as unexplained. op.execute( "UPDATE memory_references SET covered_reason = 'cited' " "WHERE curation_status = 'covered' AND covered_reason IS NULL" ) def downgrade() -> None: op.drop_index( "ix_curation_model_candidate_states_cooling_until", table_name="curation_model_candidate_states", ) op.drop_table("curation_model_candidate_states") with op.batch_alter_table("curation_model_configs") as batch: batch.drop_column("candidate_cooldown_seconds") batch.drop_column("candidates_json") with op.batch_alter_table("memory_references") as batch: batch.drop_column("reviewed_job_id") batch.drop_column("reviewed_revision") batch.drop_column("covered_reason")