"""trade_setup scan_run_id — identity of the producing scan run Revision ID: 025 Revises: 024 Create Date: 2026-07-21 00:00:00.000000 The shadow book must select the exact batch produced by its pipeline's scan. Matching the scan-completion marker's run id proves which scan wrote last, but setup selection was still a detected_at window that a concurrent manual scan could write rows into. Stamping each row with its scan's run id lets the shadow book select by identity instead. Existing rows are null (they predate the column and are never traded by the shadow book). """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = "025" down_revision: Union[str, None] = "024" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.add_column( "trade_setups", sa.Column("scan_run_id", sa.String(length=32), nullable=True), ) op.create_index( "ix_trade_setups_scan_run_id", "trade_setups", ["scan_run_id"] ) def downgrade() -> None: op.drop_index("ix_trade_setups_scan_run_id", table_name="trade_setups") op.drop_column("trade_setups", "scan_run_id")