feat: cue-phrase candidate extraction + testable extract.js (task/smarter-candidate-extraction)

Catch artist names written in lowercase right after a cue phrase ("check out devourment",
"by cattle decapitation", "fan of ...") — the Title-Case/ALL-CAPS pass missed those.

- extension/extract.js (new): pure extraction (matchesIn + new cueMatchesIn + allMatchesIn),
  UMD so it loads as a content script AND require()s in node for tests. The cue pass uses the
  regex `d` flag to map matches back to positions for in-place wrapping; a small cue-stoplist
  drops "the/this/new/..." right after the cue.
- extension/content.js: extraction now comes from globalThis.RSLExtract.allMatchesIn
  (Title-Case + cue union), keeping the existing position-based wrapping.
- extension/manifest.json: load extract.js before content.js.
- extension/extract.test.cjs (new) + scripts/check.sh: 6 node:test cases for the extraction
  logic; check.sh now runs the extension tests too (16 total, green).
- README: updated the detection limitation note.

Deferred (design item 2): merging names split across inline formatting (cross-node) — more
involved; left as a follow-up.

Verified: scripts/check.sh green (16 tests). In-browser behavior is logic-verified only (no
headless Firefox); additive to the pending background-fix re-test — the [rsl] logs distinguish
"candidates found" from "resolve failed".

Source: task/smarter-candidate-extraction (objective/linker-improvements).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
paul
2026-06-17 06:36:28 +00:00
co-authored by Claude Opus 4.8
parent 607a4ab45e
commit c2618ce0ea
6 changed files with 144 additions and 44 deletions
+4 -4
View File
@@ -124,10 +124,10 @@ let the content script reach it).
## Limitations (MVP)
- **Detection is capitalization-based.** Names written in lowercase, or split
across formatting (e.g. **bold** in the middle of a name), can be missed. The
resolver's exact-name match keeps false *positives* low; the trade-off is some
false *negatives*.
- **Detection is mostly capitalization-based**, with a cue-phrase pass that also catches
lowercase names right after "check out / by / fan of / recommend …". Names split across
inline formatting (e.g. **bold** mid-name) can still be missed. The resolver's
exact-name match keeps false *positives* low; the trade-off is some false *negatives*.
- **Links are direct when MusicBrainz has the artist's `url-relations`** (official
Bandcamp / Spotify pages); otherwise they fall back to a search URL. (Each
confirmed artist costs one extra throttled MusicBrainz lookup, cached after.)