"""retrieval_tuning_events — why a floor is where it is (#4102) Revision ID: 0103 Revises: 0102 Create Date: 2026-09-17 Milestone 416 stops shipping similarity thresholds as values somebody has to defend, and hands the adjustment to the model that reads the surface's own telemetry. The operator's decision: "the floor should be chosen and adjusted by the model using it… the user should be able to touch it but the model should be the thing handling it 9 times out of 10." The number itself already has a home — the generic settings table. What has no home is the ARGUMENT, and once the values move on their own the argument is the part an operator needs: what changed, from what to what, who moved it, and on what evidence. This table is that trail, and it is what makes the delegation reviewable rather than merely automatic. Nothing is backfilled. A surface with no rows here is sitting on its shipped starting point, which is a true and useful thing for the history to say. """ import sqlalchemy as sa from alembic import op revision = "0103" down_revision = "0102" branch_labels = None depends_on = None def upgrade() -> None: op.create_table( "retrieval_tuning_events", sa.Column("id", sa.Integer(), primary_key=True), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), # FK-free, like retrieval_logs and app_logs: the record of why a number # is where it is must outlive the account that moved it. sa.Column("user_id", sa.Integer(), nullable=True), # Also the surface's `retrieval_logs.source`, so a change can be read # next to what the change did. sa.Column("surface", sa.Text(), nullable=False), sa.Column("dial", sa.Text(), nullable=False), # Nullable: the first change to a surface has no stored predecessor. It # moved off the shipped starting point, which is a different event from # moving off a value somebody chose. sa.Column("old_value", sa.Float(), nullable=True), sa.Column("new_value", sa.Float(), nullable=False), sa.Column( "actor", sa.Text(), nullable=False, server_default=sa.text("'model'") ), # Non-null here; non-BLANK is enforced at the service boundary, because # a column that merely forbids NULL is satisfied by "" and a required # field that accepts "" is a formality. sa.Column("reason", sa.Text(), nullable=False), ) # The only read this table has: one surface's history, newest first. op.create_index( "ix_retrieval_tuning_surface_created", "retrieval_tuning_events", ["surface", sa.text("created_at DESC")], ) def downgrade() -> None: op.drop_index( "ix_retrieval_tuning_surface_created", table_name="retrieval_tuning_events" ) op.drop_table("retrieval_tuning_events")