mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 06:59:46 +00:00
@@ -20,6 +20,8 @@ import { readFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { checkOptimizeGeometry } from '../test-build/plan-geometry-preflight.js';
|
||||
import { classifyNearAxisSegment } from '../test-build/near-axis.js';
|
||||
import { checkWallRecordsPreserved } from '../test-build/wall-record-preservation.js';
|
||||
export { checkWallRecordsPreserved } from '../test-build/wall-record-preservation.js';
|
||||
import {
|
||||
LATTICE_GRID_N as GRID_N,
|
||||
LATTICE_NOISE_STEPS as NOISE_STEPS,
|
||||
@@ -287,42 +289,6 @@ export function checkReferences({ config, layout = {} } = {}, { notes = [] } = {
|
||||
return violations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Инвариант 1: запись толщины не исчезает.
|
||||
*
|
||||
* Сравнивается мультимножество значений `cm`, а не суммарная длина: ресайз
|
||||
* законно укорачивает стены, а склейка двух одинаковых записей законно
|
||||
* уменьшает их число. Незаконно ровно одно — исчезновение значения целиком,
|
||||
* как в #253, где 33 см пропали вместе с кладкой соседних комнат.
|
||||
*
|
||||
* `allowClear` — единственное исключение, и оно объявляется вызывающим:
|
||||
* пользователь очистил толщину явно.
|
||||
*/
|
||||
export function checkWallRecordsPreserved(before, after, { allowClear = false } = {}) {
|
||||
if (allowClear) return [];
|
||||
const counts = (walls) => {
|
||||
const map = new Map();
|
||||
for (const wall of walls || []) {
|
||||
if (!isFiniteNumber(wall?.cm) || !(wall.cm > 0)) continue;
|
||||
const key = String(wall.cm);
|
||||
map.set(key, (map.get(key) || 0) + 1);
|
||||
}
|
||||
return map;
|
||||
};
|
||||
const from = counts(before), to = counts(after);
|
||||
const violations = [];
|
||||
for (const [cm, was] of from) {
|
||||
const now = to.get(cm) || 0;
|
||||
if (now === 0) {
|
||||
violations.push({
|
||||
invariant: 'wall_records', kind: 'lost', owner: `${cm} см`,
|
||||
reference: `было ${was}`, detail: 'записи этой толщины исчезли целиком',
|
||||
});
|
||||
}
|
||||
}
|
||||
return violations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Копия ключа отрезка из `src/wall-thickness.ts`.
|
||||
*
|
||||
|
||||
@@ -431,9 +431,9 @@ export const MUTANTS = [
|
||||
because: 'a candidate rejected by the exact production wall/floor preflight must create '
|
||||
+ 'neither preview nor commit; polygon-only success previously persisted disappearing walls',
|
||||
patches: [{
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: ' const candidateValid = this._rszCandidateRenderable(preview);',
|
||||
replace: ' const candidateValid = !!preview;',
|
||||
file: 'src/resize-controller.ts',
|
||||
find: ' try { valid = input.validatePreview(accepted.preview); } catch { valid = false; }',
|
||||
replace: ' try { valid = true; } catch { valid = false; }',
|
||||
}, {
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: ' if (!legacySafe) {',
|
||||
@@ -753,12 +753,13 @@ export const MUTANTS = [
|
||||
},
|
||||
{
|
||||
id: 'invariant-loses-wall-record',
|
||||
guard: 'node --test --test-name-pattern="исчезнувшая запись толщины" '
|
||||
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
|
||||
+ '&& node --test --test-name-pattern="исчезнувшая запись толщины" '
|
||||
+ 'test/model-invariants.test.mjs',
|
||||
because: 'потеря записи толщины — это дефект #253, найденный человеком глазами; если '
|
||||
+ 'инвариант перестанет её замечать, класс вернётся в продукт незамеченным (#254)',
|
||||
patches: [{
|
||||
file: 'scripts/model-invariants.mjs',
|
||||
file: 'src/wall-record-preservation.ts',
|
||||
find: ' if (now === 0) {',
|
||||
replace: ' if (false) {',
|
||||
}],
|
||||
|
||||
Reference in New Issue
Block a user