"""Retire the sketch/doodle WIP title tier — its tags, its review flags, its toggle. Milestone 430, #4428. The soft tier (#1474) tagged `wip` on any post titled sketch / doodle / scribble. Measured on the operator's library it was 6,096 of 8,876 wip tags, and its conflict audit filled the Gallery's review strip with 2,086 cards, because most finished art scores >= 0.5 on some content head. A "sketch" is usually finished work, so the operator retired it (2026-09-25). Data: * A soft tag the operator stood behind is kept and relabelled `manual`: one they confirmed (tag_positive_confirmation), or one whose review flag they resolved while leaving the tag on (the strip's "Keep tag"). * Every other `wip_title_soft` row is deleted. * Unresolved review flags whose tag is no longer on the image are deleted: the question they ask no longer applies. That is the audit's cards, and any older orphan the same way. Then `import_settings.wip_soft_title_tagging_enabled` is dropped. The downgrade restores the column only; deleted tags are not recreated. Revision ID: 0112 Revises: 0111 Create Date: 2026-09-25 """ import sqlalchemy as sa from alembic import op revision = "0112" down_revision = "0111" branch_labels = None depends_on = None def retire_soft_wip_tags(conn) -> None: """The data half, on a plain connection, so a test can run it directly.""" conn.execute(sa.text(""" UPDATE image_tag it SET source = 'manual' WHERE it.source = 'wip_title_soft' AND ( EXISTS ( SELECT 1 FROM tag_positive_confirmation c WHERE c.image_record_id = it.image_record_id AND c.tag_id = it.tag_id ) OR EXISTS ( SELECT 1 FROM presentation_review pr WHERE pr.image_record_id = it.image_record_id AND pr.tag_id = it.tag_id AND pr.resolved_at IS NOT NULL ) ) """)) conn.execute(sa.text("DELETE FROM image_tag WHERE source = 'wip_title_soft'")) conn.execute(sa.text(""" DELETE FROM presentation_review pr WHERE pr.resolved_at IS NULL AND NOT EXISTS ( SELECT 1 FROM image_tag it WHERE it.image_record_id = pr.image_record_id AND it.tag_id = pr.tag_id ) """)) def upgrade(): retire_soft_wip_tags(op.get_bind()) op.drop_column("import_settings", "wip_soft_title_tagging_enabled") def downgrade(): op.add_column( "import_settings", sa.Column( "wip_soft_title_tagging_enabled", sa.Boolean(), nullable=False, server_default=sa.text("false"), ), )