fix: rebalance album cue recall — admit number/lowercase-led + abbreviation-period titles, bound 'the album X', strip curly quote (closes task/album-cue-recall-rebalance)
Source: task/album-cue-recall-rebalance (plan/steward-linker-design) — the a35dd95 precision tightening over-corrected, dropping real number/lowercase-led and abbreviation-period album titles.
- Loosen the album-cue lead token to admit a DIGIT (and, after an explicit
"the album X" cue, a lowercase-styled run), so number-led ("the album 1989",
"1989 LP", "36 Chambers") and lowercase-styled ("good kid maad city") titles
survive; ALBUM_LEAD_STOP still rejects an is/was/by/the/a/an lead.
- Narrow QUOTED_RE's mid-span reject to SENTENCE-ENDING punctuation only (a .!?
before whitespace/EOL, abbreviation periods exempted), so "M.A.A.D City",
"Mr. Bungle", "Sgt. Pepper's" survive while prose quotes still reject; raise
the word cap 6 → 8.
- Add the curly quotes ”“ (U+201D/U+201C) to TRAILING_PUNCT so an LP/EP run that
grabbed a trailing curly quote ("Reek of Putrefaction”") is trimmed, with the
span index/length kept so text.substr(index,length)===name still holds.
- Bound the "the album X" branch to the same 1-4-token run as the LP/EP branch,
so "the album Money Store dropped" yields "Money Store", not the sentence tail.
- Tests assert BOTH directions: recovered recall AND retained precision, plus the
curly-quote-trim position-mapping invariant.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,78 @@ test("albumMatchesIn: tightened cues still map positions back to the text", () =
|
||||
}
|
||||
});
|
||||
|
||||
// --- Recall rebalance: the a35dd95 precision tightening over-corrected. These assert the recovered
|
||||
// recall (number/lowercase-led + abbreviation-period titles, bounded "the album X", no curly-quote
|
||||
// leak) AND that the precision floor still holds (album path emits nothing on prose/filler). ---
|
||||
|
||||
test("albumMatchesIn: recall — number-led titles via an explicit album cue", () => {
|
||||
// The cue ("the album" / "LP") is the precision signal that justifies a number as a title.
|
||||
assert.ok(albumMatchesIn("the album 1989").map((m) => m.name).includes("1989"));
|
||||
assert.ok(albumMatchesIn("1989 LP").map((m) => m.name).includes("1989"));
|
||||
assert.ok(albumMatchesIn("the album 36 Chambers").map((m) => m.name).includes("36 Chambers"));
|
||||
});
|
||||
|
||||
test("albumMatchesIn: recall — lowercase-styled titles after a cue", () => {
|
||||
// good kid maad city is fully lowercase — a stylized title, not prose; the cue admits it.
|
||||
assert.ok(
|
||||
albumMatchesIn("the album good kid maad city").map((m) => m.name).includes("good kid maad city")
|
||||
);
|
||||
});
|
||||
|
||||
test("albumMatchesIn: recall — internal abbreviation periods survive in a quoted title", () => {
|
||||
// A `.` mid-span is only sentence-ending when it follows a long word; "M.A.A.D"/"Mr."/"Sgt." abbreviate.
|
||||
assert.ok(albumMatchesIn('"M.A.A.D City"').map((m) => m.name).includes("M.A.A.D City"));
|
||||
assert.ok(albumMatchesIn('"Mr. Bungle"').map((m) => m.name).includes("Mr. Bungle"));
|
||||
assert.ok(
|
||||
albumMatchesIn('"Sgt. Pepper\'s Lonely Hearts Club Band"')
|
||||
.map((m) => m.name)
|
||||
.includes("Sgt. Pepper's Lonely Hearts Club Band")
|
||||
);
|
||||
});
|
||||
|
||||
test("albumMatchesIn: recall — curly close-quote is trimmed off an LP/EP title run", () => {
|
||||
// Separate the title from the “…” so the trailing curly quote, not an artist possessive, is the target.
|
||||
const text = "their “Reek of Putrefaction” LP";
|
||||
const ms = albumMatchesIn(text);
|
||||
const names = ms.map((m) => m.name);
|
||||
assert.ok(names.includes("Reek of Putrefaction")); // exact string — no trailing ”
|
||||
assert.ok(!names.some((n) => /[“”]/.test(n))); // no curly quote leaked into any candidate
|
||||
// position mapping holds even after the leading-/trailing-quote trim shifts the span
|
||||
for (const m of ms) assert.equal(text.substr(m.index, m.length), m.name);
|
||||
});
|
||||
|
||||
test("albumMatchesIn: recall — 'the album X' is bounded to the title, not the trailing prose", () => {
|
||||
// a35dd95 left "the album X" an unbounded lazy run; it now reuses the 1-4-token bound.
|
||||
const names = albumMatchesIn("the album Money Store dropped").map((m) => m.name);
|
||||
assert.ok(names.includes("Money Store")); // the title
|
||||
assert.ok(!names.includes("Money Store dropped")); // not the title + trailing verb
|
||||
});
|
||||
|
||||
test("albumMatchesIn: precision — album path still emits nothing on prose / filler", () => {
|
||||
// Each of these must yield NO album candidate (the precision guards a35dd95 added must survive).
|
||||
assert.equal(albumMatchesIn("I think their new LP is amazing").length, 0); // lowercase filler before LP
|
||||
assert.equal(albumMatchesIn("the album by Carcass").length, 0); // verb/article left edge
|
||||
assert.equal(albumMatchesIn("the album is great but I forgot the name").length, 0); // "is" lead
|
||||
assert.equal(albumMatchesIn('"We hold these truths to be self-evident."').length, 0); // prose quote
|
||||
assert.equal(albumMatchesIn('"lol"').length, 0); // lone interjection
|
||||
});
|
||||
|
||||
test("albumMatchesIn: every rebalance candidate maps back to the source text", () => {
|
||||
// Position-mapping invariant across the recall cases, including the curly-quote-trim shift.
|
||||
const texts = [
|
||||
"the album 1989",
|
||||
"1989 LP",
|
||||
"the album good kid maad city",
|
||||
'"M.A.A.D City"',
|
||||
'"Mr. Bungle"',
|
||||
"their “Reek of Putrefaction” LP",
|
||||
"the album Money Store dropped",
|
||||
];
|
||||
for (const text of texts) {
|
||||
for (const m of albumMatchesIn(text)) assert.equal(text.substr(m.index, m.length), m.name);
|
||||
}
|
||||
});
|
||||
|
||||
test("isSafeHttpUrl accepts http/https and rejects javascript/data/garbage/empty", () => {
|
||||
// accepted: the only schemes a resolver link may inject as an href
|
||||
assert.ok(isSafeHttpUrl("https://open.spotify.com/artist/abc"));
|
||||
|
||||
Reference in New Issue
Block a user