Soft auto-apply (retract + confirm, no self-training) + tagging UX (reject-rest, tag-input race, modal playlist) #197

Merged
bvandeusen merged 12 commits from dev into main 2026-07-06 21:03:30 -04:00
3 changed files with 61 additions and 4 deletions
Showing only changes of commit cbc3e11a53 - Show all commits
@@ -0,0 +1,50 @@
"""stricter auto-apply defaults (milestone 139) — cut graduate/auto-apply misfires
head_auto_apply_precision 0.97→0.98, head_auto_apply_min_positives 30→50,
ccip_auto_apply_threshold 0.92→0.95 (operator-asked 2026-07-06). The model
defaults change for fresh installs; here we bump the existing singleton row IFF
it is still at the previous default, so a deliberate operator change is NOT
clobbered.
Revision ID: 0081
Revises: 0080
Create Date: 2026-07-06
"""
from typing import Sequence, Union
from alembic import op
revision: str = "0081"
down_revision: Union[str, None] = "0080"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.execute(
"UPDATE ml_settings SET head_auto_apply_precision = 0.98 "
"WHERE head_auto_apply_precision = 0.97"
)
op.execute(
"UPDATE ml_settings SET head_auto_apply_min_positives = 50 "
"WHERE head_auto_apply_min_positives = 30"
)
op.execute(
"UPDATE ml_settings SET ccip_auto_apply_threshold = 0.95 "
"WHERE ccip_auto_apply_threshold = 0.92"
)
def downgrade() -> None:
op.execute(
"UPDATE ml_settings SET head_auto_apply_precision = 0.97 "
"WHERE head_auto_apply_precision = 0.98"
)
op.execute(
"UPDATE ml_settings SET head_auto_apply_min_positives = 30 "
"WHERE head_auto_apply_min_positives = 50"
)
op.execute(
"UPDATE ml_settings SET ccip_auto_apply_threshold = 0.92 "
"WHERE ccip_auto_apply_threshold = 0.95"
)
+10 -3
View File
@@ -51,7 +51,10 @@ class MLSettings(Base):
Integer, nullable=False, default=8
)
head_auto_apply_precision: Mapped[float] = mapped_column(
Float, nullable=False, default=0.97
# Stricter graduation bar (was 0.97) to cut auto-apply misfires
# (operator-asked 2026-07-06): a higher precision target → fewer heads
# graduate and those that do get a higher per-head auto_apply_threshold.
Float, nullable=False, default=0.98
)
# Earned auto-apply (#114). A graduated head fires (tags images without a
# human) when this master switch is on AND the head has at least
@@ -63,7 +66,9 @@ class MLSettings(Base):
Boolean, nullable=False, default=True
)
head_auto_apply_min_positives: Mapped[int] = mapped_column(
Integer, nullable=False, default=30
# Support floor raised 30→50 (operator-asked 2026-07-06): a head needs
# more human labels before it may fire without a human.
Integer, nullable=False, default=50
)
# CCIP character-match cosine cut (#114). 0.85 default — the v1 flat 0.75
# over-fired (high-reference characters matched a scatter of images); 0.85
@@ -78,7 +83,9 @@ class MLSettings(Base):
Boolean, nullable=False, default=True
)
ccip_auto_apply_threshold: Mapped[float] = mapped_column(
Float, nullable=False, default=0.92
# Raised 0.92→0.95 (operator-asked 2026-07-06) so only very confident
# character matches auto-tag.
Float, nullable=False, default=0.95
)
# Default = SigLIP 2 (so400m, 512px) for new installs (migration 0069);
# existing libraries keep their stored value until the operator re-embeds.
+1 -1
View File
@@ -88,7 +88,7 @@ def test_sweep_dry_run_counts_but_writes_nothing(db_sync):
def test_sweep_skips_under_supported_head(db_sync):
# n_pos below head_auto_apply_min_positives (default 30) → a precise-looking
# n_pos below head_auto_apply_min_positives (default 50) → a precise-looking
# but under-supported head never fires.
img = _img(db_sync, "c" * 64, _emb(0))
tag = Tag(name="weaktag", kind=TagKind.general)