571938781a
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>
50 lines
1.6 KiB
Python
50 lines
1.6 KiB
Python
"""Title-based WIP matcher (task #1458) — pure unit tests for
|
|
``matches_wip_title``, the precision-first heuristic that decides whether a post
|
|
title explicitly declares work-in-progress. No DB, no network.
|
|
|
|
Precision matters more than recall here: a false positive applies the ``wip``
|
|
system tag, which HIDES a finished post from the Explore browse — so the
|
|
negative cases (substrings like ``swipe`` / ``wiped``) are the load-bearing ones.
|
|
"""
|
|
import pytest
|
|
|
|
from backend.app.services.wip_title import matches_wip_title
|
|
|
|
|
|
@pytest.mark.parametrize("title", [
|
|
"WIP",
|
|
"wip",
|
|
"WiP",
|
|
"Nami Heroines - WIP Part 1", # the real-world example from the gate work
|
|
"sketch (WIP)",
|
|
"[WIP] new piece",
|
|
"WIP: colour test",
|
|
"cool art WIP2", # trailing digit = "WIP part 2", still WIP
|
|
"W.I.P.",
|
|
"W.I.P",
|
|
"work in progress",
|
|
"Work In Progress",
|
|
"commission work-in-progress",
|
|
"big_project_work_in_progress",
|
|
"final touches, wip",
|
|
])
|
|
def test_matches_positive(title):
|
|
assert matches_wip_title(title) is True
|
|
|
|
|
|
@pytest.mark.parametrize("title", [
|
|
None,
|
|
"",
|
|
"a quick swipe left", # 'wip' inside swipe — must NOT match
|
|
"she wiped the counter", # wiped
|
|
"wiping down the desk", # wiping
|
|
"unwiped surface",
|
|
"progressive rock cover", # 'progress' inside progressive, no 'work in'
|
|
"workin on it", # not the full phrase
|
|
"finished at last",
|
|
"Kawips diner", # 'wip' mid-word
|
|
"swipright",
|
|
])
|
|
def test_matches_negative(title):
|
|
assert matches_wip_title(title) is False
|