Files
ss-tools/backend/alembic/versions/d2e3f4a5b6c7_add_scenario_artifact_attempt_projection.py

51 lines
2.9 KiB
Python

# #region Alembic.ScenarioArtifactAttemptProjection [C:3] [TYPE Module] [SEMANTICS alembic,scenario,artifact,retry,provenance]
# @ingroup Alembic
# @BRIEF Add additive retry-attempt projection fields without rewriting historical artifact rows.
# @RELATION DEPENDS_ON -> [Models.ScenarioExecution.Artifact]
# @INVARIANT Existing evidence defaults to active and remains inspectable; retries retire only
# future step-bound projections, never content/digest audit data.
# @REJECTED Deleting or backfilling artifact content for retry provenance was rejected — legacy
# rows remain valid historical evidence with nullable step/attempt linkage.
"""add active ScenarioArtifact attempt projection for retry closure (044)"""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
revision: str = "d2e3f4a5b6c7"
down_revision: str | Sequence[str] | None = "c1d2e3f4a5b6"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
# #region Alembic.ScenarioArtifactAttemptProjection.Upgrade [C:4] [TYPE Function] [SEMANTICS alembic,scenario,artifact,retry,additive]
# @BRIEF Add nullable producer linkage and an active projection flag for durable retry evidence.
# @POST Legacy rows are active=true; no historical SHA/ref is changed or removed.
# @SIDE_EFFECT Schema mutation: two nullable provenance columns, active projection flag, invalidation timestamp, and lookup indexes.
def upgrade() -> None:
op.add_column("scenario_artifacts", sa.Column("logical_step_id", sa.String(128), nullable=True))
op.add_column("scenario_artifacts", sa.Column("attempt", sa.Integer(), nullable=True))
op.add_column(
"scenario_artifacts",
sa.Column("is_active", sa.Boolean(), nullable=False, server_default=sa.true()),
)
op.add_column("scenario_artifacts", sa.Column("invalidated_at", sa.DateTime(), nullable=True))
op.create_index("ix_scenario_artifacts_logical_step_id", "scenario_artifacts", ["logical_step_id"])
op.create_index("ix_scenario_artifacts_is_active", "scenario_artifacts", ["is_active"])
# #endregion Alembic.ScenarioArtifactAttemptProjection.Upgrade
# #region Alembic.ScenarioArtifactAttemptProjection.Downgrade [C:3] [TYPE Function] [SEMANTICS alembic,scenario,artifact,retry,rollback]
# @BRIEF Remove only additive projection metadata; retained evidence rows and digests are untouched.
def downgrade() -> None:
op.drop_index("ix_scenario_artifacts_is_active", table_name="scenario_artifacts")
op.drop_index("ix_scenario_artifacts_logical_step_id", table_name="scenario_artifacts")
op.drop_column("scenario_artifacts", "invalidated_at")
op.drop_column("scenario_artifacts", "is_active")
op.drop_column("scenario_artifacts", "attempt")
op.drop_column("scenario_artifacts", "logical_step_id")
# #endregion Alembic.ScenarioArtifactAttemptProjection.Downgrade
# #endregion Alembic.ScenarioArtifactAttemptProjection