feat(tagging): title-based WIP auto-tagging (#1458)
Auto-apply the `wip` system tag to posts whose TITLE explicitly declares
work-in-progress ("WIP" / "work in progress") — a deterministic, high-precision
complement to the image-based ML `wip` head. WIP images are excluded from the
Explore/gallery browse, so honouring the artist's own label keeps unfinished
pieces out of the main browse.
- services/wip_title.py: precision-first token-anchored matcher (swipe/wiped
never trip it) + sync apply helpers (source='wip_title', ON CONFLICT DO
NOTHING, chunked under the psycopg param ceiling).
- importer: live hook on FRESH import only (never on deep-scan/supersede), so a
manually-removed WIP tag is never re-applied by a routine re-scan.
- maintenance.backfill_wip_title_tags: operator-triggered back-catalogue sweep
(coarse SQL prefilter + regex confirm, keyset-paginated). Deliberately NOT a
beat — a periodic re-run would silently undo manual removals.
- ImportSettings.wip_title_tagging_enabled (default ON, migration 0085) gating
the live hook; GET/PATCH + POST /settings/wip-title/scan.
- Settings UI: toggle + "Scan existing posts" button.
- Tests: pure matcher unit tests + integration (apply idempotency, backfill
precision).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -116,6 +116,17 @@ class ImportSettings(Base):
|
||||
Float, nullable=False, default=0.9, server_default="0.9",
|
||||
)
|
||||
|
||||
# Title-based WIP auto-tagging (task #1458). When a freshly-imported post's
|
||||
# TITLE explicitly declares work-in-progress ("WIP" / "work in progress"),
|
||||
# the importer applies the `wip` system tag to its images — the artist's own
|
||||
# label, used to keep unfinished pieces out of the Explore/gallery browse. ON
|
||||
# by default (rule 26 — the feature works out of the box). Gates only the
|
||||
# LIVE import hook; the existing catalogue is caught by the operator-triggered
|
||||
# "Scan existing posts" backfill (which runs regardless of this flag).
|
||||
wip_title_tagging_enabled: Mapped[bool] = mapped_column(
|
||||
Boolean, nullable=False, default=True, server_default="true",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def load(cls, session) -> ImportSettings:
|
||||
"""The singleton settings row (id=1), via an async session."""
|
||||
|
||||
Reference in New Issue
Block a user