Files
arah2/search/test/distance.test.mjs
T
araharah-executor 25ee1e9c61 test(04-01): RED — OSA distance vectors (D1-D9) + disjoint-tier scorer suite (S1-S7)
- 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.
2026-10-24 00:25:19 +08:00

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);
});