fix: close code-review 330-r1 — budgets from the slowest machine, the bench in Validate, AC1 through the execution thread (#330)

H2: the benchmark budgets were calibrated on the author's sandbox with a
1.14x margin — the review runner measured tsFullCandidateMs at 169-171 ms
against a 100 ms ceiling. Budgets now keep the spec's 2-3x allowance over
the SLOWEST observed machine, and the benchmark runs as a step of the
Validate perf job on every push (it needs no browser and no bundle), not
only inside the weekly mutation gate.

M1: the promised AC1 backend test exists now and does what AC1 means: it
patches validate_junction_limits with a thread-recording wrapper inside the
real HA harness — on the event loop that would be MainThread — and proves
the verdicts survived the move (a clean write is accepted, a write adding a
spike is refused with junction_limit_angle). Spec revision 4 rewrites AC1
around this invariant instead of a fragile millisecond assertion.

M2: §4.6 equivalence is now behavioural on both sides (three boundary
fixtures each: as-is counts equal through-migration counts, TS and python),
and the parity suite gained the §7 boundary fixtures (exact 15°, exact
20 cm, the thickness-step filler run, exact 5 cm).

H1 was already closed by 7513f93d (the review ran on the previous HEAD):
check-docs is green on this tree — the screenshots and their manifest come
from one capture run.

Issue: #330
User-Visible: no
This commit is contained in:
Codex
2026-08-28 03:07:44 +03:00
parent 4e8e00fa73
commit ddfca3a865
6 changed files with 170 additions and 17 deletions
+39
View File
@@ -397,3 +397,42 @@ test('#330 AC4: кэш baseline инвалидируется по конфиг-
assert.match(method, />= WALL_SEGMENT_MODEL_VERSION\s*\n?\s*\? previousConfig/,
'документ текущей версии используется как есть (#330 §4.6)');
});
test('#330 M2: §4.6 на границах — v9 как есть == v9 через миграцию (TS)', async () => {
const { commitWallSegmentModel } = await import('../test-build/wall-segment-model.js');
const { checkNodes, checkSegmentLengths, checkNodeDistances } =
await import('../test-build/junction-limits.js');
const countsOf = (space) => {
const segments = (space.wall_segments || []).map((item) => ({
id: item.id, a: item.a, b: item.b, cm: Number(item.cm),
}));
const all = [
...checkNodes(segments),
...checkSegmentLengths(segments, Number(space.cell_cm) || 1, PITCH),
...checkNodeDistances(segments, Number(space.cell_cm) || 1, PITCH),
];
const counts = {};
for (const item of all) counts[item.rule] = (counts[item.rule] || 0) + 1;
return counts;
};
const polys = {
spike: [[0.30, 0.70], [0.3167, 0.24], [0.36, 0.68]],
box: [[0.60, 0.60], [0.80, 0.60], [0.80, 0.80], [0.60, 0.80]],
narrow: [[0.30, 0.70], [0.32, 0.24], [0.36, 0.68]],
};
for (const [name, poly] of Object.entries(polys)) {
const legacy = { spaces: [{
id: 's', title: 's', cell_cm: CELL, view_box: [0, 0, 1, 1],
rooms: [{ id: 'r1', name, area: null, poly }],
walls: poly.map((point, index) => ({
key: `w${index}`, a: point, b: poly[(index + 1) % poly.length], cm: 15,
})),
openings: [], room_drafts: [], partitions: [], wall_columns: [],
}], markers: [], settings: {} };
const v9 = commitWallSegmentModel(JSON.parse(JSON.stringify(legacy))).config;
const asIs = countsOf(v9.spaces[0]);
const through = commitWallSegmentModel(JSON.parse(JSON.stringify(v9))).config;
assert.deepEqual(asIs, countsOf(through.spaces[0]),
`${name}: вердикт «как есть» разошёлся с «через миграцию»`);
}
});