"""documents image columns: is_image + image_path (phase 122, task 02) Revision ID: 0022 Revises: 0021 Create Date: 2026-09-24 Phase 122 (standalone images become first-class documents — task 02, storage only): * ``documents.is_image`` — BOOLEAN NOT NULL, server default ``false``: True iff the doc is a standalone image (LOCKED A3) whose ``content``/``summary`` is the CHAT model's vision description — the ONLY embedded text (the embedding model never sees pixels). The server default makes EVERY pre-phase-122 row a text doc without a backfill. * ``documents.image_path`` — TEXT NULLABLE: the absolute path of the image's persistent copy in ``settings.image_dir`` (``.`` — the copy must outlive the source file: uploads are replaced on every upload, git checkouts are re-cloned). NULL for text docs. One additive, fully reversible migration (A13); no other schema change. The walk filter, the binary index path, and the prune guard are importer code (task 02) — this revision only carries the columns. """ from __future__ import annotations import sqlalchemy as sa from alembic import op revision = "0022" down_revision = "0021" branch_labels = None depends_on = None def upgrade() -> None: op.add_column( "documents", sa.Column( "is_image", sa.Boolean(), server_default=sa.text("false"), nullable=False, ), ) op.add_column("documents", sa.Column("image_path", sa.Text(), nullable=True)) def downgrade() -> None: # Both columns are the only 0022 artefacts — dropping them leaves # 0021's schema byte-identical (A13, fully reversible). op.drop_column("documents", "image_path") op.drop_column("documents", "is_image")