From 93fad8cfb400e11ddf4a0a44886a03d45bf160f5 Mon Sep 17 00:00:00 2001 From: Sergey Matyunin Date: Mon, 24 Aug 2026 10:28:59 +0300 Subject: [PATCH] docs: specify optimize rehost validation Issue: #280 User-Visible: no --- docs/specs/280-optimize-rehost-validation.md | 102 +++++++++++++++++++ docs/specs/README.md | 1 + 2 files changed, 103 insertions(+) create mode 100644 docs/specs/280-optimize-rehost-validation.md diff --git a/docs/specs/280-optimize-rehost-validation.md b/docs/specs/280-optimize-rehost-validation.md new file mode 100644 index 00000000..7f751ace --- /dev/null +++ b/docs/specs/280-optimize-rehost-validation.md @@ -0,0 +1,102 @@ +# Issue #280 — backend принимает доказанный Optimize rehost + +- Дата: 2026-08-24 +- Тип: regression bug · приоритет P1 +- Issue: [#280](https://github.com/Matysh/houseplan-card/issues/280) +- Ветка: `issue/280-optimize-rehost-backend` +- Статус ТЗ: одобрено self-review по решению владельца + +Связанные контракты: #132, #186, #199, #224 и #276; +`docs/CONFIG-COMPATIBILITY.md`, `docs/WALL-THICKNESS.md`, `docs/TESTING.md`. + +## 1. Проблема + +#276 намеренно удаляет exact coincident partition и материализует её hosted +opening как ordinary room-wall opening. Backend при любом surviving opening +безусловно запрещает `host != null → host == null`, поэтому preview beta.8 +успешен, а единственный Optimize write отклоняется как `host removed`. + +Frontend mock не является доказательством server acceptance. Исправление +должно сохранить общий запрет и дать исключение только специальному WS Optimize, +если backend самостоятельно доказывает тот же безопасный переход. + +## 2. Пользовательский результат + +Apply для exact reconciliation #276 атомарно сохраняет candidate. Дверь/окно/ +ворота не двигаются, partition исчезает, reload видит обычный room-wall +opening, а одноразовый Undo возвращает прежний partition и explicit host. +Обычный config/set и crafted Optimize без полного доказательства остаются +fail-closed с `invalid_partition_opening_host`. + +## 3. Backend-контракт доказательства + +`validate_partition_opening_hosts()` получает keyword-only capability, +включаемую только `ws_plan_optimize`. Capability не является доверием клиенту: +каждый снятый host должен пройти все проверки. + +Для одного surviving opening backend требует: + +1. предыдущий host имеет `kind: partition`, а предыдущий partition существует; +2. partition с этим id отсутствует в candidate; +3. его полный отрезок является однозначной solid shared boundary ровно двух + разных candidate rooms: оба endpoints лежат на collinear room edges; +4. candidate physical wall envelope на всём отрезке не уже удалённого тела: + covering exact wall record имеет достаточный `cm`, либо действующий default + `15 cm` уже достаточен; +5. candidate `x/y` равны точке `a + t × (b-a)`, angle совпадает с осью modulo + 180°, length полностью помещается в отрезок; +6. все поля, кроме `host` и материализуемых `x/y/angle`, byte-semantically + равны предыдущему opening; +7. новый slot не перекрывает другой candidate opening на той же физической + оси; every removed host в batch проходит проверку. + +Coordinate tolerance — `1e-8` normalized units для девятизначной storage +канонизации. Он не используется для near/partial wall matching: collinearity и +coverage всё равно должны доказать полный исходный segment. + +## 4. Scope + +Входит: + +- pure backend delta-proof и узкий Optimize-only call site; +- exact shared fixture, ordinary-write и crafted-candidate negative matrix; +- HA websocket success/atomic failure/Undo regression для Linux CI; +- cross-stack fixture: результат настоящего `optimizePlans()` равен candidate, + который принимает Python validator; +- backend/config compatibility docs и оба changelog. + +Не входит: общий отказ от host guard, доверие frontend counters, nearest-wall +эвристика, изменение schema/model version или геометрии #276. + +## 5. Acceptance criteria + +1. Privacy-minimized #276 fixture проходит frontend optimizer и backend + Optimize-validation; второй Optimize — no-op. +2. Тот же host removal при capability=false отклоняется. +3. Отклоняются: partition остался; partial/non-shared/ambiguous wall; более + узкий envelope; сдвиг/поворот/длина/тип/id/связи; overlap; unsafe второй + opening в batch. +4. `ws_plan_optimize` передаёт capability, `config/set` — нет; validation + завершается до первого store write. +5. Linux HA integration доказывает save/reload/Undo и неизменность revisions/ + backup при failure. +6. Pure backend, frontend unit, typecheck/build и targeted smoke зелёные. + +## 6. Совместимость, security и performance + +Schema и stored result уже поддерживаются старыми версиями: ordinary opening +и room wall. Новый capability недоступен из payload и не расширяет права WS. +Proof линейно обходит rooms/walls/openings только при явном Optimize и только +для реально снятых hosts; render и обычные state updates не затрагиваются. + +## 7. Self-review ТЗ + +- Исключение привязано к server command, но не доверяет его происхождению. +- Доказательство покрывает identity, geometry, envelope и conflicts, а не + только факт удаления partition. +- Позитивный cross-stack fixture закрывает точный разрыв тестов beta.8. +- Негативный ordinary config/set сохраняет прежнюю security/compat guarantee. + +Вердикт: **approved**. Внешнее spec-review пропущено по прямому решению +владельца. + diff --git a/docs/specs/README.md b/docs/specs/README.md index a78b3b1f..949f5095 100644 --- a/docs/specs/README.md +++ b/docs/specs/README.md @@ -74,6 +74,7 @@ GitHub Issues и GitHub Projects (v2) остаются единственным | [#277](https://github.com/Matysh/houseplan-card/issues/277) Безопасный Resize без изменения топологии | [277-safe-resize.md](277-safe-resize.md) | | [#278](https://github.com/Matysh/houseplan-card/issues/278) Локальный сбой extra-body union не гасит всю кладку | [278-wall-union-isolation.md](278-wall-union-isolation.md) | | [#279](https://github.com/Matysh/houseplan-card/issues/279) Сплошной почти ортогональный T-стык | [279-near-orthogonal-junction.md](279-near-orthogonal-junction.md) | +| [#280](https://github.com/Matysh/houseplan-card/issues/280) Backend принимает доказанный Optimize rehost | [280-optimize-rehost-validation.md](280-optimize-rehost-validation.md) | ## P2