fix: the model-invariants CLI accepts the unhosted degraded opening of model v9 (#316, review r3 M1)

Since #316 §3.3 an unhosted contour opening is a valid v9 state — the
migration keeps an opening with no in-place carrier as data. The CLI still
reported it as an opening_host violation for every model_version >= 8; the
requirement now applies to model v8 documents only. The regression test is
proven able to fail on the old comparison (executed red), and the reviewer's
CLI reproduction now finishes clean.

Issue: #316
User-Visible: no
This commit is contained in:
Codex
2026-08-27 00:08:15 +03:00
parent b29472a887
commit 05ec0a1de8
2 changed files with 33 additions and 2 deletions
+6 -2
View File
@@ -225,7 +225,7 @@ export function checkReferences({ config, layout = {} } = {}, { notes = [] } = {
'комнаты назначения не существует в том же пространстве');
}
}
if (Number(config?.model_version || 0) >= 8) {
if (Number(config?.model_version || 0) === 8) {
const wallIds = Array.isArray(room?.wall_ids) ? room.wall_ids : [];
const poly = roomPolygon(room) || [];
if (wallIds.length !== poly.length) {
@@ -246,7 +246,11 @@ export function checkReferences({ config, layout = {} } = {}, { notes = [] } = {
for (const opening of space?.openings || []) {
const host = opening?.host;
if (!host) {
if (Number(config?.model_version || 0) >= 8) {
// #316 §3.3: since model v9 an unhosted contour opening is a valid
// degraded state (the migration keeps an opening with no in-place
// carrier as data, inert until re-placed). Only model v8 documents
// still require an explicit host on every opening.
if (Number(config?.model_version || 0) === 8) {
add('opening_host', `${spaceId}:${opening?.id ?? '?'}`, '?',
'в model v8 у проёма нет явной стены-хоста');
}
+27
View File
@@ -688,3 +688,30 @@ test('реальный план: перегородка поверх наруж
assert.equal(checkHiddenObstacles(config).length, expected, file);
}
});
test('#316: непривязанный контурный проём — валидное состояние v9, но не v8', () => {
const base = () => ({
config: {
model_version: 9,
spaces: [{
id: 'sp316', title: 'S', view_box: [0, 0, 1, 1],
rooms: [], openings: [{
id: 'orphan', type: 'door', x: 0.9, y: 0.65, angle: 90, length: 0.05,
}],
}],
markers: [], settings: {},
},
layout: {},
});
const v9 = base();
assert.deepEqual(
checkReferences(v9).filter((item) => item.kind === 'opening_host'), [],
'model v9 keeps the unhosted degraded state of #316 §3.3 without a violation',
);
const v8 = base();
v8.config.model_version = 8;
assert.equal(
checkReferences(v8).filter((item) => item.kind === 'opening_host').length, 1,
'model v8 still requires an explicit host on every opening',
);
});