feature/better-normalization #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/better-normalization"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Getting workflow into main so version bumps will auto-update instances of the plugin
Adversarial live-Steam verification (226 filenames) surfaced 17 real false SSOT maps in the prior confidence logic; all fixed: meetsConfidence (delicate core): - Screen the CANDIDATE's extra tokens too, not just the query's — rejects a base name grabbing a different specific entry: Devil May Cry->DMC5, Sid Meiers Civilization->Civ VII, Crash and Burn->...Racing, Fire and Ice->Beyond:..., Wolf Among Us->...2, Command and Conquer Red Alert->...3. - Require >= 2 query tokens: single-token titles are too generic to fuzzy-claim (Okami->Ookami Okami clone). - Remove the prefix ("Path B") acceptance entirely — proven unable to tell a unique game's edition subtitle from a franchise entry (Tomb Raider: Anniversary, Silent Hill f, Tales of Berseria Remastered; an edition word IS often a distinct game). Tradeoff: short filename -> subtitled store title (e.g. "Boobs saga" -> "BOOBS SAGA: ... Edition") no longer auto-maps — use [steamid=] tag or rename. name-normalizer: - foldToAscii (fullwidth, Unicode Roman numerals, accents via canonical NFD so fractions/superscripts are NOT expanded to digits, & -> and), applied symmetrically in toAlphaLower + confidenceTokens. - Guarded destructive strips: junk brackets/parens (keeps a bare year), Build/r#### version tags, curated scene groups ONLY after a '-' separator (Portal.Reloaded keeps its real title word). - confidenceTokens: apostrophe-join (Jerez's->jerezs) + guarded leading-"The" drop. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ChjiJZ7fLwNZBFZziKUkEGClaude adversarial workflow (4 dimensions) confirmed two real wrong-SSOT claims: 1. Censorship-marker strip over-reached. `/\b(Uncensored|Adult|NSFW|...)\b.*$/` deleted the marker AND every word after it, so a MID-title marker collapsed a distinctive title to a generic word: "Love Adult Adventure" -> "Love", which then exact-matched the unrelated Steam game "LOVE" and claimed SSOT. Critical for the *unfiltered* (adult) plugin whose titles legitimately contain Adult/Uncensored. Fix: strip only a TRAILING run of marker/edition/junk words (CENSOR_TRAILING); a real word after the marker cancels the strip. Trailing tags still strip ("Adorable Witch Uncensored" -> "Adorable Witch"). 2. foldToAscii "&"->"and" collided distinct titles in the EXACT-alpha gate: toAlphaLower("s&box")="sandbox"==toAlphaLower("Sandbox") -> a library "Sandbox" claimed Facepunch's s&box (590830). REGRESSION introduced by routing toAlphaLower through foldToAscii. Fix: drop "&"->"and" from foldToAscii; the fuzzy path still treats them as equivalent because "and" is an EDITION_WORD. Also (Codex): \b-word-boundary the bracket junk regex + hard/soft scene-group split (prev commit) so "(Goggles)"/"(Prophet)" keep their text. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ChjiJZ7fLwNZBFZziKUkEGThe "-1" no-match sentinel is a sticky mapping — once Steam-Unfiltered "owns" a game (even as a failure), getBestMatch isn't re-run, so a transient web-search outage (SearXNG engines rate-limited/CAPTCHA'd) got baked in permanently. Now the web-search client distinguishes an OUTAGE from a genuine miss and the game is left UNMAPPED to retry. websearch-client.ts: - searchWith/providers return {results, ok} — ok = the engine actually responded (vs blocked/CAPTCHA/errored). SearXNG: 0 results + non-empty unresponsive_engines = not ok. DDG: 0 result URLs after both endpoints = soft-blocked = not ok. - findSteamAppId throws WebSearchUnavailableError when NO appid was found AND any preferred engine was unavailable (the weak fallback's miss isn't authoritative when the reliable engine is down). A genuine miss (all engines responded, nothing found) still returns undefined. service: - getBestMatch step 3 catches WebSearchUnavailableError -> throws NotFoundException (no sentinel) so the game stays unmapped and re-discovers next scan/recache. - search() catches it -> shows storefront candidates only (never errors the remap UI). Verified live against the currently-rate-limited SearXNG: findSteamAppId now throws WebSearchUnavailableError instead of returning undefined. BACKLOG: Mojeek needs its own result parser (plain anchors, not DDG uddg redirects). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ChjiJZ7fLwNZBFZziKUkEGThree new acceptance paths, each verified live against Steam: - corroboratedAcronym gains a minLetters tier: >=4-letter acronyms may match raw storefront candidates (YBFON -> 'One Night ~Young Bride for One Night~'); 3-letter stays web-corroborated-only. DLC/demo/soundtrack words can never supply acronym initials. - corroboratedSubtitle + uniqueExpansionAppId: single-brand subtitle expansions ('Menherarium' -> 'Menherarium: Deadly Dice') accepted only when web-search resolved the same appid AND the storefront census is unambiguous (at-cap pages refused, sequel/year shadows count as franchise evidence). - confidenceTokens folds multi-char roman numerals (II..XX) to digits so 'Mount & Blade 2 - Bannerlord' == 'Mount & Blade II: Bannerlord'; single-letter romans excluded (Mega Man X != Mega Man 10), and confidentStorefrontClaim vetoes fold-only matches when a year-disambiguated reboot sibling exists (MW2 2009 must not claim MW2 2022). - foldToAscii range extended through precomposed XI/XII (U+216A/B) — 'Final Fantasy XI' no longer collapses to 'FINAL FANTASY'. Every finding from the adversarial review pass is fixed and pinned with mutation-killing fixtures (25 matching tests). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011DL9ooECq5YjPm98QhdDow