- 9 hand-computed Damerau-Levenshtein vectors (transpositions, empties, kitten/sitting sanity, the corpus's klcc/kclc + sunway/sunwya typos) - 7 scorer laws: tier literals + disjointness, min-length guard before exact, exact-outranks-fuzzy, mid-word PREFIX vs token-boundary TOKEN_SET, fuzzy residual 0.75*0.60 arithmetic, the 0.72 admission boundary (Penang/Padang 0.667 refuses), matchedAlias raw provenance All 16 new cases fail while src/distance.ts + src/score.ts are absent.
81 lines
2.9 KiB
JavaScript
81 lines
2.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/*
|
|
* distance.test.mjs — OSA Damerau-Levenshtein vector suite (SRCH-02).
|
|
* -------------------------------------------------------------------
|
|
* RED phase (plan 04-01 task 2): every case fails while
|
|
* ../src/distance.ts does not exist (lazy import => per-case FAIL).
|
|
*
|
|
* The vectors are the hand-computed ones the plan pins (RESEARCH
|
|
* §"The Damerau-Levenshtein (OSA) distance"). The 3-band row rotation
|
|
* is the classic implementation trap — these vectors are written FIRST
|
|
* so a wrong rotation shows up as a red suite, not a silent mis-rank.
|
|
*
|
|
* D1 adjacent transposition ab -> ba = 1
|
|
* D2 two transpositions a cat -> an act = 2
|
|
* D3 empty vs empty = 0
|
|
* D4 empty vs abc = 3
|
|
* D5 abc vs empty = 3
|
|
* D6 identical strings = 0
|
|
* D7 KLCC transposition typo klcc -> kclc = 1
|
|
* D8 real corpus typo sunway -> sunwya = 1
|
|
* D9 classic Levenshtein sanity kitten -> sitting = 3
|
|
*
|
|
* Run: npm run search:test (exit 0 = all green)
|
|
*/
|
|
import { strict as assert } from "node:assert";
|
|
import { test } from "./harness.mjs";
|
|
|
|
// Lazy distance load — missing module => per-case ERR_MODULE_NOT_FOUND (the RED state).
|
|
let distancePromise = null;
|
|
function loadDamerau() {
|
|
if (!distancePromise) {
|
|
distancePromise = import("../src/distance.ts").then((m) => m.damerau);
|
|
}
|
|
return distancePromise;
|
|
}
|
|
|
|
test("D1 adjacent transposition: damerau('ab', 'ba') === 1", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("ab", "ba"), 1);
|
|
});
|
|
|
|
test("D2 two transpositions: damerau('a cat', 'an act') === 2", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("a cat", "an act"), 2);
|
|
});
|
|
|
|
test("D3 damerau('', '') === 0", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("", ""), 0);
|
|
});
|
|
|
|
test("D4 damerau('', 'abc') === 3", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("", "abc"), 3);
|
|
});
|
|
|
|
test("D5 damerau('abc', '') === 3", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("abc", ""), 3);
|
|
});
|
|
|
|
test("D6 identical strings: damerau('same', 'same') === 0", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("same", "same"), 0);
|
|
});
|
|
|
|
test("D7 KLCC transposition typo: damerau('klcc', 'kclc') === 1", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("klcc", "kclc"), 1);
|
|
});
|
|
|
|
test("D8 real corpus typo: damerau('sunway', 'sunwya') === 1", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("sunway", "sunwya"), 1);
|
|
});
|
|
|
|
test("D9 classic Levenshtein sanity: damerau('kitten', 'sitting') === 3", async () => {
|
|
const damerau = await loadDamerau();
|
|
assert.equal(damerau("kitten", "sitting"), 3);
|
|
});
|