"""add retrieval_logs.suppressed_count — tell a ranker decline from a repeat (#3497) Revision ID: 0095 Revises: 0094 Create Date: 2026-09-03 `result_count == 0` has always meant "this surface said nothing", which is the right number for "was the hint any use" and the wrong one for tuning a threshold. It folds together two unrelated events: - the ranker found nothing above the bar — the ONLY evidence a threshold is set too high; and - the ranker found something the session had already been shown — a decline that says nothing whatever about the bar. The rule arms filter in Python after the search, so they can count the second kind exactly. The note arms pass `exclude_ids` INTO semantic_search_notes, so the dropped rows never come back and there is nothing to count. NULLABLE, AND THE NULL IS THE POINT. A surface that does not measure suppression stores NULL, not 0, and the readout renders it as "not measured" rather than "none". Defaulting to 0 would make an unmeasured surface look like a perfectly clean one — the exact substitution of an artifact for a measurement that #3311 made and that #3497 exists to correct. Doing it again, in the migration that fixes it, would be its own small joke. No backfill for the same reason: existing rows genuinely do not know, and saying so is the honest state. `retrieval_logs` is not restored from backup, so no importer changes. Downgrade drops the column. Purely observational — nothing reads it for correctness. """ from alembic import op import sqlalchemy as sa revision = "0095" down_revision = "0094" branch_labels = None depends_on = None def upgrade() -> None: op.add_column( "retrieval_logs", sa.Column("suppressed_count", sa.Integer(), nullable=True), ) def downgrade() -> None: op.drop_column("retrieval_logs", "suppressed_count")