fix(tag-prefix): drop artist/meta/rating from KNOWN_KINDS — artist tags retired in FC-2d-vii-c (provenance is its own axis), meta/rating retired by operator 2026-05-26. User-typeable prefixes now just character/fandom/series. Frontend placeholder + icon map + client-side mirror updated; new test confirms retired prefixes parse as literal text.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 21:00:12 -04:00
parent 3b1e2f1ceb
commit 42b1340324
3 changed files with 26 additions and 14 deletions
+8 -5
View File
@@ -10,15 +10,18 @@ KNOWN_KINDS keeps its colon as literal text.
from __future__ import annotations
# Kinds the user can type as a prefix at the input boundary.
# `general` is intentionally excluded — it's the default for un-prefixed
# input. `archive` and `post` are system-managed and never user-typed.
# Exclusions:
# - `general` is the default for un-prefixed input (never typed as prefix)
# - `archive`, `post` are system-managed
# - `artist` was retired in FC-2d-vii-c — artists are first-class
# entities (Artist row + ImageRecord.artist_id), browsed via the
# provenance axis rather than as tags. See project_provenance_separation.
# - `meta`, `rating` retired as user-typeable per operator 2026-05-26 —
# content classification only needs character/fandom/series.
KNOWN_KINDS: frozenset[str] = frozenset({
"artist",
"character",
"fandom",
"series",
"meta",
"rating",
})
@@ -2,7 +2,7 @@
<div class="fc-tag-autocomplete">
<v-text-field
v-model="query"
placeholder="Add tag (or kind:name — artist/character/fandom/series/meta/rating)"
placeholder="Add tag (or kind:name — character/fandom/series)"
density="compact" hide-details
@keydown.down.prevent="moveHighlight(1)"
@keydown.up.prevent="moveHighlight(-1)"
@@ -71,12 +71,11 @@ const fandomDialog = ref(false)
let pendingNewName = null
const KNOWN_KINDS = new Set([
'artist', 'character', 'fandom', 'series', 'meta', 'rating',
'character', 'fandom', 'series',
])
const KIND_ICONS = {
general: 'mdi-tag', artist: 'mdi-palette', character: 'mdi-account-circle',
general: 'mdi-tag', character: 'mdi-account-circle',
fandom: 'mdi-book-open-page-variant', series: 'mdi-bookshelf',
meta: 'mdi-cog-outline', rating: 'mdi-shield-check-outline',
}
function iconFor (k) { return KIND_ICONS[k] || 'mdi-tag' }
+15 -5
View File
@@ -4,11 +4,12 @@ from backend.app.utils.tag_prefix import KNOWN_KINDS, parse_kind_prefix
def test_recognized_kinds_match_user_input_set():
# System-managed kinds (archive, post) and the default (general)
# are intentionally excluded — the user can't type those at the
# input boundary.
# Excluded: archive + post (system-managed), general (default for
# un-prefixed input), artist (retired in FC-2d-vii-c — first-class
# entities now), meta + rating (retired as user-typeable per
# operator 2026-05-26).
assert KNOWN_KINDS == frozenset({
"artist", "character", "fandom", "series", "meta", "rating",
"character", "fandom", "series",
})
@@ -30,8 +31,17 @@ def test_unknown_prefix_kept_as_literal():
assert parse_kind_prefix("http://example.com") == (None, "http://example.com")
def test_retired_prefixes_kept_as_literal():
# `artist:`, `meta:`, `rating:` are no longer recognized — they
# parse as literal text so the operator's input is preserved (and
# serves as a nudge to use the appropriate dedicated UI instead).
assert parse_kind_prefix("artist:Eric") == (None, "artist:Eric")
assert parse_kind_prefix("meta:wide") == (None, "meta:wide")
assert parse_kind_prefix("rating:safe") == (None, "rating:safe")
def test_whitespace_stripped():
assert parse_kind_prefix("artist: Eric ") == ("artist", "Eric")
assert parse_kind_prefix("series: Bleach ") == ("series", "Bleach")
assert parse_kind_prefix(" sunset ") == (None, "sunset")