From 0cdf85d9e2b30dfac4732922cbfdd57358dfe5bb Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 28 Aug 2026 04:42:07 +0300 Subject: [PATCH] test: the key-precision and dropped-branch mutants actually bite (#331) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running the mutants exposed two toothless guards before review did: - reverting the keys to toFixed(6) no longer produced false П4 refusals because the new 2e-7 incidence absorbed the debris pair — the REAL harm of coarse keys is the opposite direction: nodes 4e-7 apart merged into one key and П4 went blind to a genuine near-miss. AC1 now pins that case. - the `break` patch failed to reproduce the old first-branch-only loss (the frontier re-visits the node through the pushed endpoints); the patch now truncates the node's candidate list to one entry, which loses forks the way `.find` did — both the fork unit and the 10 000-atom run turn red. Issue: #331 User-Visible: no --- scripts/mutation-gate.mjs | 9 ++------- test/junction-limits.test.mjs | 8 ++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/scripts/mutation-gate.mjs b/scripts/mutation-gate.mjs index 66956786..f564c657 100644 --- a/scripts/mutation-gate.mjs +++ b/scripts/mutation-gate.mjs @@ -569,13 +569,8 @@ export const MUTANTS = [ + 'understates the wall run — a legitimate thickness-step filler gets refused (#331 §2.3)', patches: [{ file: 'src/junction-limits.ts', - find: ' visited.add(candidate);\n' - + ' total += length(candidate.a, candidate.b);\n' - + ' frontier.push(candidate.a, candidate.b);', - replace: ' visited.add(candidate);\n' - + ' total += length(candidate.a, candidate.b);\n' - + ' frontier.push(candidate.a, candidate.b);\n' - + ' break;', + find: ' for (const candidate of byNode.get(key(node)) || []) {', + replace: ' for (const candidate of (byNode.get(key(node)) || []).slice(0, 1)) {', }], }, { diff --git a/test/junction-limits.test.mjs b/test/junction-limits.test.mjs index cfdd3f98..c9ab095d 100644 --- a/test/junction-limits.test.mjs +++ b/test/junction-limits.test.mjs @@ -466,6 +466,14 @@ test('#331 AC1: плавающий мусор — один узел, реаль { id: 'b', a: [0, cm(5)], b: [cm(300), cm(5)], cm: 15 }, ]; assert.equal(checkNodeDistances(five, CELL, PITCH).length, 0); + // Реальное сближение 4e-7 (> инцидентности 2e-7, но < полушага toFixed(6)) + // обязано быть ВИДНО: грубые ключи сливали такие узлы в один и П4 слеп. + const subQuantum = [ + { id: 'a', a: [0, 0], b: [cm(300), 0], cm: 15 }, + { id: 'b', a: [4e-7, 0], b: [4e-7, cm(300)], cm: 15 }, + ]; + assert.ok(checkNodeDistances(subQuantum, CELL, PITCH).length > 0, + 'узлы на 4e-7 — два узла и честное П4, а не слияние ключей'); }); test('#331 AC2: дубль стены — нарушение угла 0°; 180°-пара и T-стык чисты', async () => {