mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-06 14:39:22 +00:00
docs: update partition openings spec after unified walls
Issue: #132 User-Visible: no
This commit is contained in:
@@ -1,23 +1,27 @@
|
||||
# Issue #132 — проёмы в независимых перегородках
|
||||
# Issue #132 — проёмы в независимых стенах
|
||||
|
||||
- **Issue:** https://github.com/Matysh/houseplan-card/issues/132
|
||||
- **Статус документа:** готово к будущей реализации; issue остаётся на `S3-spec`
|
||||
- **Связанный bug в том же scope:** https://github.com/Matysh/houseplan-card/issues/185
|
||||
- **Статус документа:** актуализировано после #173 и #157; готово к ревью ТЗ
|
||||
- **Приоритет:** P2
|
||||
- **Тип:** feature, обычный трек
|
||||
- **Пользовательское изменение:** да
|
||||
|
||||
## 1. Сценарий
|
||||
|
||||
Администратор рисует независимую перегородку в Plan editor и размещает в ней
|
||||
реальную дверь, окно или ворота тем же инструментом «Проём», которым работает со
|
||||
стенами комнат. Домочадцы затем видят корректный разрыв, live state и действия в
|
||||
View/kiosk.
|
||||
Администратор рисует незамкнутую цепочку инструментом «Стены», завершает её
|
||||
сменой инструмента, редактора или этажа и размещает в одном сохранённом сегменте
|
||||
дверь, окно, ворота либо открытый проём тем же инструментом «Проём», которым
|
||||
работает со стенами комнат. Домочадцы затем видят корректный разрыв, а для
|
||||
stateful-типов — тот же live state и действия в View/kiosk.
|
||||
|
||||
## 2. Что человек увидит до и после
|
||||
|
||||
До изменения перегородка остаётся сплошной и не принимает проём; после изменения
|
||||
выбранный door/window/gate вырезает её тело, следует за перегородкой и ведёт себя
|
||||
как тот же тип проёма в обычной стене.
|
||||
До изменения завершённая независимая стена остаётся сплошной и не принимает
|
||||
проём; после изменения выбранный door/window/gate/passage вырезает её тело,
|
||||
следует за конкретным host-сегментом и ведёт себя как тот же тип проёма в обычной
|
||||
стене. При этом стена с проёмом по #185 остаётся полноценным ребром для
|
||||
распознавания замкнутой комнаты.
|
||||
|
||||
## 3. Проблема и связь со scope
|
||||
|
||||
@@ -25,14 +29,27 @@ View/kiosk.
|
||||
placement/index принимает только derived room walls. Physical union специально
|
||||
добавляет partitions после opening cuts, поэтому проём не может вырезать их.
|
||||
|
||||
#173 заменил отдельный публичный инструмент «Перегородка» одной непрерывной
|
||||
цепочкой «Стены». Активные сегменты crash-safe живут в `room_drafts`; явное
|
||||
завершение превращает каждый сегмент в отдельный `partition` со stable `id`.
|
||||
Face graph использует сохранённые partitions и может создать room wall на той же
|
||||
оси, не удаляя исходный объект. Это делает composite room-wall/partition overlap
|
||||
штатным, а не ошибочным случаем.
|
||||
|
||||
#185 фиксирует более новый продуктовый контракт: проём является свойством стены,
|
||||
а не разрывом её структурного ребра. Поэтому opening cuts влияют на физическую и
|
||||
световую геометрию, но room-face detection должен уметь замыкать область через
|
||||
room wall или partition с любым поддержанным проёмом. `open_spans` остаются
|
||||
реальным отсутствием стены и в topology не возвращаются.
|
||||
|
||||
Функция закрывает J4: администратор может без внешнего SVG точно воспроизвести
|
||||
план. Правильный итоговый View также поддерживает J1/J2/J3: физическая геометрия,
|
||||
contact/lock status и безопасные actions не расходятся с домом.
|
||||
|
||||
## 4. Решения владельца
|
||||
|
||||
1. На перегородке разрешены существующие `door`, `window`, `gate`; новый тип
|
||||
«открытый проход» не добавляется.
|
||||
1. На независимой стене разрешены все существующие типы: `door`, `window`,
|
||||
`gate`, `passage`. #132 не добавляет новый opening type.
|
||||
2. Проём следует за host при движении перегородки.
|
||||
3. Удаление перегородки с проёмами требует confirmation со списком и удаляет их
|
||||
только после явного согласия.
|
||||
@@ -40,13 +57,25 @@ contact/lock status и безопасные actions не расходятся с
|
||||
меняется только host geometry.
|
||||
5. Физический passage в перегородке участвует в световой геометрии по тем же
|
||||
type-specific правилам, что passage в стене.
|
||||
6. При точном совпадении saved partition со стеной комнаты они считаются одним
|
||||
составным физическим барьером без дополнительного host chooser. Explicit host
|
||||
остаётся partition; hosted interval прорезает оба совпадающих тела. После
|
||||
движения partition вычисляемый room-wall cut исчезает, room config не
|
||||
переписывается.
|
||||
7. По #185 проём любого поддержанного типа не разрывает структурное ребро для
|
||||
room-face detection. Контур через стену с проёмом замыкается, а проём и его
|
||||
host сохраняются.
|
||||
|
||||
## 5. Scope
|
||||
|
||||
- явная persisted host identity для partition opening;
|
||||
- placement/hover/drag/edit/delete door, window и gate на partition;
|
||||
- placement/hover/drag/edit/delete door, window, gate и passage на partition;
|
||||
- full-depth cut, jamb/tunnel/symbol geometry с толщиной partition;
|
||||
- composite cut совпадающих partition + derived room wall без persisted room
|
||||
provenance;
|
||||
- движение/удаление host и единая Undo/Redo команда;
|
||||
- structural wall axes для #185 отдельно от physical opening gaps; regression
|
||||
контракта #173 для endpoint/T/X/collinear faces и реальных `open_spans`;
|
||||
- Flat Plan/View/kiosk/static и hidden Isometric renderers;
|
||||
- clean floor, Glow barrier/source guard и действующие sun semantics;
|
||||
- existing opening HA state/actions/security;
|
||||
@@ -55,11 +84,11 @@ contact/lock status и безопасные actions не расходятся с
|
||||
|
||||
## 6. Не входит в задачу
|
||||
|
||||
- новый тип «открытый проход» без door/window/gate symbol;
|
||||
- новый opening type или новая семантика существующего `passage`;
|
||||
- проёмы в unfinished room drafts или columns;
|
||||
- несколько host segments на один opening;
|
||||
- автоматическая конверсия старого room-wall opening в partition opening;
|
||||
- создание room/Area из partition;
|
||||
- новый способ завершения Walls chain либо auto-resume finished partition;
|
||||
- новая light model либо изменение window/door/gate semantics;
|
||||
- sun rays, источником которых становится внутреннее partition window;
|
||||
- полная touch parity Plan editor;
|
||||
@@ -80,6 +109,9 @@ host?: {
|
||||
- `host` отсутствует — current legacy/current room-wall association по `x/y/
|
||||
angle/length`; старые конфиги не мигрируют.
|
||||
- `kind='partition'` — `id` обязан ссылаться на partition того же space.
|
||||
- Один finished Walls segment создаёт один partition id. Бывшая multi-segment
|
||||
chain не становится составным host: соседние segments двигаются и удаляются
|
||||
независимо.
|
||||
- `t` — нормализованное положение центра вдоль направленного `a→b`, `[0,1]`.
|
||||
- `x`, `y`, `angle` остаются materialized compatibility projection и обновляются
|
||||
атомарно из host; новый frontend считает valid host+t authority.
|
||||
@@ -104,12 +136,15 @@ opening.
|
||||
- center from `a + t(b-a)`;
|
||||
- angle modulo current opening convention;
|
||||
- full length and host depth from partition `cm`;
|
||||
- derived room-wall intervals, collinear with and covering the hosted opening
|
||||
interval within the canonical wall epsilon;
|
||||
- validity/orphan reason;
|
||||
- adjacent floor samples/type-specific passage policy.
|
||||
|
||||
Placement preview, symbol, body cut, tunnel, hit test, light barriers, Iso panel,
|
||||
move/delete и tests используют этот resolver. Запрещён render-only nearest-wall
|
||||
fallback для explicit partition host.
|
||||
Placement preview, symbol, body/composite cut, tunnel, hit test, light barriers,
|
||||
Iso panel, move/delete и tests используют этот resolver. Запрещён render-only
|
||||
nearest-wall fallback для explicit partition host. Coincident room-wall coverage
|
||||
— вычисляемая projection valid partition host, а не второй persisted host.
|
||||
|
||||
Если endpoints хоста представлены в обратном порядке при canonical rewrite,
|
||||
rewrite одновременно заменяет `t → 1-t`, сохраняя physical center и hinge/flip
|
||||
@@ -123,14 +158,17 @@ orientation. Простое rigid translation сохраняет `t`, length и
|
||||
- saved independent partition segments.
|
||||
|
||||
Hover preview показывает тот же translucent door/window/gate и привязывается к
|
||||
partition axis. Center квантуется по действующему wall-bound grid step, length
|
||||
целиком помещается между endpoints. Click повторно разрешает candidate и открывает
|
||||
существующий opening dialog.
|
||||
partition axis; `passage` использует свою действующую symbol-less preview. Center
|
||||
квантуется по действующему wall-bound grid step, length целиком помещается между
|
||||
endpoints. Click повторно разрешает candidate и открывает существующий opening
|
||||
dialog.
|
||||
|
||||
При близких candidates выбирается минимальная perpendicular distance, затем
|
||||
полное покрытие opening length; точная неразрешимая tie room-wall/partition
|
||||
отклоняется с локализованной причиной вместо скрытого выбора другого host.
|
||||
Existing opening hit имеет приоритет над placement.
|
||||
полное покрытие opening length. Точное collinear overlap room-wall/partition,
|
||||
покрывающее reserved interval, считается одним composite barrier и выбирает
|
||||
explicit partition host без дополнительного dialog. Не совпадающая геометрически
|
||||
tie остаётся неразрешимой и отклоняется с локализованной причиной. Existing
|
||||
opening hit имеет приоритет над placement.
|
||||
|
||||
Toast `opening_no_wall` обновляется до «стены или перегородки». Virtual room span,
|
||||
room draft и column остаются невалидными host. Touch placement — best effort;
|
||||
@@ -146,15 +184,40 @@ Hosted opening:
|
||||
- door swing начинается с выбранной face по `flip_v`;
|
||||
- window glass располагается в середине partition depth;
|
||||
- gate leaves используют current compact gate geometry;
|
||||
- passage остаётся symbol-less full-depth cut по контракту #157;
|
||||
- overlapping hosted openings не могут резервировать один interval дважды;
|
||||
- junction patches после cut не должны заново закрыть passage.
|
||||
|
||||
Для zero/invalid thickness new partition невозможна по current validation
|
||||
(1–100 cm). Malformed legacy host fail-dark: cut не применяется. Room-wall and
|
||||
partition cuts выполняются по host identity до единого physical union; случайное
|
||||
совпадение осей не позволяет opening прорезать второй независимый body.
|
||||
(1–100 cm). Malformed legacy host fail-dark: cut не применяется. Partition cut
|
||||
выполняется по explicit host identity до единого physical union. Он дополнительно
|
||||
вырезает только derived room-wall bodies, которые collinear и покрывают тот же
|
||||
hosted interval в пределах canonical epsilon. Случайное пересечение, nearby
|
||||
parallel wall или второй independent body не прорезаются.
|
||||
|
||||
## 11. Floor fill и tunnel
|
||||
## 11. Room topology и bug #185
|
||||
|
||||
Room-face graph получает два разных представления одной архитектуры:
|
||||
|
||||
- **physical/presentation:** opening interval вырезан из кладки и остаётся
|
||||
проходом для изображения, hit geometry и type-specific света;
|
||||
- **structural room topology:** axis валидной стены непрерывен через
|
||||
door/window/gate/passage, потому что проём не отменяет принадлежность стены
|
||||
контуру комнаты.
|
||||
|
||||
`buildPlanSnapGeometry()` либо следующий pure collector обязан сохранить
|
||||
structural room/partition segment через opening interval для face traversal, не
|
||||
возвращая этот interval в physical body. Действующий opening cut может оставаться
|
||||
snap boundary/measure input, но не удаляет connectivity для room detection.
|
||||
|
||||
Контракт применяется одинаково к legacy room-wall opening и новому
|
||||
partition-hosted opening. Контур, который последним segment опирается на такую
|
||||
стену endpoint/T/X/collinear-примыканием, предлагает room по обычному #173 flow;
|
||||
opening config, host, entities и materialized geometry не мутируют. `open_spans`
|
||||
и отсутствующий/invalid host остаются настоящими gaps. Пассивные HA state ticks,
|
||||
редактирование opening state и render не запускают room dialog.
|
||||
|
||||
## 12. Floor fill и tunnel
|
||||
|
||||
Partition не является границей room ownership. После вычитания hosted opening
|
||||
видна уже существующая clean-floor/fill geometry под body. Дополнительный
|
||||
@@ -165,24 +228,25 @@ fill ownership; cut не смешивает alpha и не создаёт нов
|
||||
остаются выше base fill. Opening symbol скрывается по `hide_openings`, но physical
|
||||
cut, HA state и barrier semantics остаются активны, как у room-wall opening.
|
||||
|
||||
## 12. Glow и light barriers
|
||||
## 13. Glow и light barriers
|
||||
|
||||
Решение владельца «проём пропускает свет» реализуется через type-specific
|
||||
существующий контракт:
|
||||
|
||||
- door/gate — transparent passage только там, где по обе стороны host есть floor;
|
||||
- door/gate/passage — transparent passage только там, где по обе стороны host
|
||||
есть floor; `passage` не получает state или створку;
|
||||
- exterior/no-floor с одной стороны остаётся opaque, чтобы Glow не уходил наружу;
|
||||
- window сохраняет текущую политику: glass виден, но indoor Glow через него не
|
||||
проходит;
|
||||
- virtual boundary к partition не относится;
|
||||
- source внутри valid interior door/gate passage допустим; source внутри window
|
||||
- source внутри valid interior door/gate/passage допустим; source внутри window
|
||||
tunnel или invalid/orphan cut fail-dark.
|
||||
|
||||
Barrier geometry получает joined partition body **после вычитания только его
|
||||
hosted passages**. Cache fingerprint включает host id/t, partition endpoints/cm,
|
||||
opening length/type и geometry validity. HA-only state tick не rebuild-ит barriers.
|
||||
|
||||
## 13. Sun semantics
|
||||
## 14. Sun semantics
|
||||
|
||||
Partition window не является exterior room-boundary window и не создаёт новый
|
||||
sun wedge. Existing exterior windows и their wedges сохраняются. Если canonical
|
||||
@@ -190,7 +254,7 @@ sun/physical clipping использует independent body set, hosted cut не
|
||||
восстанавливать opaque partition поверх уже разрешённого passage; никаких новых
|
||||
direction/source rules #132 не вводит.
|
||||
|
||||
## 14. HA state, actions и security
|
||||
## 15. HA state, actions и security
|
||||
|
||||
Contact/invert, lock, badges, open amount, info card, lock/unlock confirmation и
|
||||
`resolveHaBindingStatus()` не зависят от host kind.
|
||||
@@ -199,17 +263,21 @@ Contact/invert, lock, badges, open amount, info card, lock/unlock confirmation
|
||||
- Marker tombstone не отключает exact opening entity reference.
|
||||
- Disabled/orphaned/unverified entity не выполняет service call.
|
||||
- Window не получает lock control, если current type contract его не допускает.
|
||||
- Passage остаётся inert: без contact/lock/invert/flip, badge, info card и service
|
||||
call, по тому же контракту #157 на room wall.
|
||||
- Перемещение host не меняет entity ids и runtime state.
|
||||
|
||||
Новый action resolver или отдельный partition status model запрещён.
|
||||
|
||||
## 15. Move, edit, delete и Undo
|
||||
## 16. Move, edit, delete и Undo
|
||||
|
||||
### Move/edit
|
||||
|
||||
Rigid partition drag обновляет endpoints и materialized `x/y/angle` всех hosted
|
||||
openings в одном preview/commit. `t`, length, entities and flips сохраняются.
|
||||
Одна Undo/Redo command восстанавливает partition и все hosted projections.
|
||||
Rigid drag одного partition segment обновляет endpoints и materialized
|
||||
`x/y/angle` всех его hosted openings в одном preview/commit. `t`, length,
|
||||
entities and flips сохраняются. Соседние segments бывшей Walls chain не
|
||||
двигаются. Одна Undo/Redo command восстанавливает partition и все hosted
|
||||
projections, включая computed composite cut.
|
||||
|
||||
Editor operation, которая сократила бы host меньше opening+jamb margin, блокирует
|
||||
commit с причиной. Import/legacy invalid geometry не clamped молча.
|
||||
@@ -226,7 +294,7 @@ commit с причиной. Import/legacy invalid geometry не clamped молч
|
||||
|
||||
Удалять hosted openings без confirmation через generic cleanup запрещено.
|
||||
|
||||
## 16. Orphan и failure policy
|
||||
## 17. Orphan и failure policy
|
||||
|
||||
Explicit partition opening с отсутствующим/invalid host:
|
||||
|
||||
@@ -240,10 +308,12 @@ Explicit partition opening с отсутствующим/invalid host:
|
||||
Boolean failure по одному cut возвращает непрорезанный opaque partition
|
||||
(fail-dark), не удаляет config и не делает все independent bodies прозрачными.
|
||||
|
||||
## 17. Migration и compatibility
|
||||
## 18. Migration и compatibility
|
||||
|
||||
- Старые openings без `host` читаются и пишутся по current room-wall contract.
|
||||
- Existing room-wall opening около partition не начинает прорезать partition.
|
||||
- Room-wall opening, существовавший до #132, сохраняет implicit host и участвует
|
||||
в structural room topology по #185 без migration/write-on-read.
|
||||
- New optional fields добавляются в frontend/backend schema и
|
||||
`docs/CONFIG-COMPATIBILITY.md`/field registry.
|
||||
- Export/import/backup сохраняют host object и referential order; counts остаются
|
||||
@@ -257,60 +327,82 @@ Boolean failure по одному cut возвращает непрорезан
|
||||
Schema migration существующих данных не нужна: capability появляется только у
|
||||
новых/явно перепривязанных openings.
|
||||
|
||||
## 18. i18n и accessibility
|
||||
## 19. i18n и accessibility
|
||||
|
||||
Новые en/ru strings:
|
||||
|
||||
- «Стена или перегородка» в placement guidance/error;
|
||||
- host kind «Перегородка» в properties/diagnostic;
|
||||
- confirmation title/body и строки списка hosted openings;
|
||||
- orphan reason/rebind action, если affordance нужен по §16.
|
||||
- orphan reason/rebind action, если affordance нужен по §17.
|
||||
|
||||
Opening dialog, list и confirmation используют существующий `hp-dialog`, focus
|
||||
trap, Escape и restore focus. List доступен screen reader; confirmation сообщает
|
||||
точное количество. Canvas preview не является единственным объяснением host:
|
||||
properties/diagnostic имеет текстовое accessible name.
|
||||
|
||||
## 19. Acceptance criteria
|
||||
## 20. Acceptance criteria
|
||||
|
||||
1. **AC1 — placement.** Door/window/gate размещаются на partition canonical
|
||||
wall-bound workflow; draft/column/virtual span не принимаются.
|
||||
**Доказательство:** resolver unit + desktop browser smoke.
|
||||
2. **AC2 — geometry.** Opening cut full-depth с корректными jamb/symbol для
|
||||
1/15/100 cm и diagonal partition, без прорезания coincident other body.
|
||||
1. **AC1 — Walls workflow и placement.** После завершения multi-segment цепочки
|
||||
«Стены» каждый saved segment является отдельным candidate host. На partition
|
||||
размещаются door/window/gate/passage; active draft, column и virtual span не
|
||||
принимаются. **Доказательство:** resolver/lifecycle unit + desktop smoke.
|
||||
2. **AC2 — geometry и composite overlap.** Opening cut full-depth с корректными
|
||||
jamb/symbol для 1/15/100 cm и diagonal partition. При точном покрывающем
|
||||
room-wall overlap partition выбирается explicit host и весь composite barrier
|
||||
прорезается; crossing/nearby/второй independent body не затрагиваются.
|
||||
**Доказательство:** geometry units + reviewed golden.
|
||||
3. **AC3 — host lifecycle.** Rigid move переносит opening; delete показывает
|
||||
список и атомарно удаляет после Confirm; Undo/Redo восстанавливает всё.
|
||||
3. **AC3 — host lifecycle.** Rigid move одного segment переносит его openings и
|
||||
убирает computed room-wall cut; delete показывает точный список и атомарно
|
||||
удаляет после Confirm; Undo/Redo восстанавливает host/openings/composite.
|
||||
**Доказательство:** command units + browser smoke.
|
||||
4. **AC4 — light.** Interior door/gate пропускают Glow через cut, exterior
|
||||
passage и window остаются opaque по current policy; failure fail-dark.
|
||||
**Доказательство:** light visibility units + smoke/golden.
|
||||
5. **AC5 — render parity.** Plan/View/kiosk/static/Iso используют один resolved
|
||||
host и не расходятся по center/angle/depth/open state.
|
||||
**Доказательство:** cross-render smoke + golden.
|
||||
6. **AC6 — HA/security parity.** Contact/lock/badge/actions совпадают с room-wall
|
||||
opening, secure/disabled guards не меняются. **Доказательство:** unit matrix + smoke.
|
||||
7. **AC7 — compatibility.** Legacy openings unchanged; host fields survive
|
||||
save/export/import/optimize; invalid reference rejected or fail-dark.
|
||||
**Доказательство:** frontend/backend round-trip tests.
|
||||
8. **AC8 — accessibility/touch safety.** Dialog/confirmation keyboard доступны,
|
||||
touch cancel/multi-touch не создают opening. **Доказательство:** browser smoke.
|
||||
9. **AC9 — cache/performance.** HA tick не rebuild-ит structural geometry;
|
||||
cache bounded and invalidated by host geometry. **Доказательство:** counters +
|
||||
performance smoke.
|
||||
10. **AC10 — no new type.** Config/UI допускает только door/window/gate.
|
||||
**Доказательство:** schema/source contract.
|
||||
4. **AC4 — light.** Interior door/gate/passage пропускают Glow через полный
|
||||
composite cut; exterior/no-floor варианты и window остаются opaque по current
|
||||
policy; invalid host/boolean failure fail-dark. **Доказательство:** light
|
||||
visibility units + smoke/golden.
|
||||
5. **AC5 — #185 room closure.** Room-face detection считает wall axis
|
||||
непрерывным через door/window/gate/passage как на legacy room wall, так и на
|
||||
partition host. Endpoint/T/X/collinear closure предлагает room и сохраняет
|
||||
opening bit-equivalent; `open_span` остаётся gap. **Доказательство:** pure
|
||||
topology unit + production-bundle smoke, который краснеет на `origin/dev`.
|
||||
6. **AC6 — no passive topology mutation.** HA state, opening edit/render,
|
||||
reload и existing closed face не показывают room dialog и не меняют geometry;
|
||||
только последний accepted Walls segment может инициировать предложение по
|
||||
#173. **Доказательство:** wall-face graph unit + smoke.
|
||||
7. **AC7 — render parity.** Plan/View/kiosk/static/Iso используют один resolved
|
||||
host и не расходятся по center/angle/depth/open state; passage остаётся
|
||||
symbol-less. **Доказательство:** cross-render smoke + golden.
|
||||
8. **AC8 — HA/security parity.** Door/window/gate contact/lock/badge/actions
|
||||
совпадают с room-wall contract, secure/disabled guards не меняются; passage
|
||||
остаётся inert. **Доказательство:** unit matrix + smoke.
|
||||
9. **AC9 — compatibility.** Legacy openings unchanged; host fields survive
|
||||
save/export/import/optimize; invalid reference rejected or fail-dark; schema
|
||||
принимает ровно четыре уже существующих type. **Доказательство:**
|
||||
frontend/backend round-trip tests.
|
||||
10. **AC10 — accessibility/touch safety.** Dialog/confirmation keyboard
|
||||
доступны, touch cancel/multi-touch не создают opening и не завершают Walls
|
||||
chain. **Доказательство:** browser smoke.
|
||||
11. **AC11 — cache/performance.** HA tick и pointermove не rebuild-ят host,
|
||||
composite или face topology; caches bounded и инвалидируются geometry host /
|
||||
opening type/length. **Доказательство:** counters + performance smoke.
|
||||
12. **AC12 — regression #173/#157.** Walls finish/no-auto-resume, room queue,
|
||||
passage field restrictions, room-wall opening placement и планы без hosted
|
||||
openings остаются совместимыми. **Доказательство:** existing targeted suites
|
||||
+ named #132 smoke.
|
||||
|
||||
## 20. План автотестов
|
||||
## 21. План автотестов
|
||||
|
||||
### Unit
|
||||
|
||||
- host serialization/resolution, t and reversed endpoints;
|
||||
- room-wall vs partition candidate/tie/length fit;
|
||||
- room-wall vs partition candidate, composite/non-composite tie and length fit;
|
||||
- horizontal/vertical/diagonal, 1/15/100 cm cut and jambs;
|
||||
- overlap reservation, junction patch, coincident independent body;
|
||||
- overlap reservation, junction patch, coincident derived wall vs independent body;
|
||||
- move/delete/Undo atomic snapshots;
|
||||
- interior/exterior/window light policy and fail-dark;
|
||||
- interior/exterior/window/passage light policy and fail-dark;
|
||||
- structural-vs-physical collector: all four openings preserve room-face axes,
|
||||
while `open_span` remains a gap; endpoint/T/X/collinear #185 matrix;
|
||||
- only the latest accepted segment may cause room proposal; opening/HA updates do not;
|
||||
- orphan, missing host and cache fingerprint;
|
||||
- HA state/action host-kind parity.
|
||||
|
||||
@@ -318,22 +410,30 @@ properties/diagnostic имеет текстовое accessible name.
|
||||
|
||||
- host discriminator/id/t and referential validation;
|
||||
- config size/count limits, export/import/unknown fields;
|
||||
- canonical `passage` field restrictions from #157 with partition host present;
|
||||
- malformed/missing partition rejection;
|
||||
- full HA harness authority — Linux CI/WSL.
|
||||
|
||||
### Browser smoke
|
||||
|
||||
- place/edit/drag door, window, gate on partition;
|
||||
- finish multi-segment Walls chain; place/edit/drag door, window, gate and passage
|
||||
on one resulting partition without resuming the chain;
|
||||
- host move, delete Cancel/Confirm and Undo/Redo;
|
||||
- contact opens, lock confirmation/action, hide_openings;
|
||||
- Glow across interior passage and blocked by window/exterior passage;
|
||||
- reproduce #185 on legacy room wall and hosted partition for all four types,
|
||||
including T closure; verify `open_span` still blocks closure and opening config
|
||||
is unchanged;
|
||||
- exact composite overlap selects partition host without an extra chooser and
|
||||
leaves no opaque wall layer across the opening;
|
||||
- Plan/View/kiosk/static/Iso parity;
|
||||
- touch cancel/pinch safety and keyboard confirmation;
|
||||
- import/optimize round trip.
|
||||
|
||||
### Golden
|
||||
|
||||
- thick/diagonal partition with all three types, light/dark;
|
||||
- thick/diagonal partition with all four types, light/dark;
|
||||
- coincident room-wall/partition composite before and after hosted cut;
|
||||
- Glow before/after door passage and opaque window;
|
||||
- hidden Iso panels/cuts and static-card parity;
|
||||
- expected diffs accepted only from reviewed full Linux artifact.
|
||||
@@ -345,23 +445,28 @@ properties/diagnostic имеет текстовое accessible name.
|
||||
- repeated render cache growth 0/bounded caps;
|
||||
- no per-opening repeated full wall index build.
|
||||
|
||||
## 21. Затронутые поверхности
|
||||
## 22. Затронутые поверхности
|
||||
|
||||
- `OpeningCfg`, backend validation and config compatibility registry;
|
||||
- opening placement/resolver, wall-thickness/physical geometry and command stack;
|
||||
- `plan-snap-overlay`/wall-face structural collector and #173 room queue;
|
||||
- Flat/static/Iso opening renderers;
|
||||
- Glow/light and current sun physical consumers;
|
||||
- Plan dialog/i18n, import/export/align/optimize;
|
||||
- unit/backend/smoke/golden/performance fixtures;
|
||||
- `docs/ARCHITECTURE.md`, `docs/CANVAS.md`, `docs/WALL-THICKNESS.md`,
|
||||
`docs/LIGHT.md`, `docs/SUN.md`, `docs/USER-GUIDE.ru.md`, `docs/TESTING.md`.
|
||||
- `docs/ARCHITECTURE.md`, `docs/CANVAS.md`, `docs/UX-MODES.md`,
|
||||
`docs/WALL-THICKNESS.md`, `docs/LIGHT.md`, `docs/SUN.md`,
|
||||
`docs/USER-GUIDE.ru.md`, `docs/TESTING.md`.
|
||||
|
||||
## 22. Риски и откат
|
||||
## 23. Риски и откат
|
||||
|
||||
| Риск | Мера |
|
||||
| --- | --- |
|
||||
| Host inference режет не ту стену | explicit partition id+t |
|
||||
| Composite overlap режет nearby/crossing body | collinear full-interval coverage + negative units |
|
||||
| Junction union закрывает passage | cut-aware physical union tests |
|
||||
| #185 возвращает физическую кладку в проём | отдельные structural и physical projections |
|
||||
| Opening начинает пассивно открывать room dialog | topology-delta и no-passive smoke #173 |
|
||||
| Delete теряет entities | atomic command snapshot + confirmation |
|
||||
| Light проходит через window/outside | existing type/floor-side policy |
|
||||
| Older writer оставляет orphan | backend referential validation |
|
||||
@@ -372,25 +477,31 @@ after room cuts. Уже сохранённые host objects должны либ
|
||||
read-preserved/diagnostic, либо требовать downgrade warning; автоматически
|
||||
преобразовывать их в room-wall openings нельзя.
|
||||
|
||||
## 23. Release-артефакты
|
||||
## 24. Release-артефакты
|
||||
|
||||
Implementation commit имеет `User-Visible: yes` и одновременно обновляет:
|
||||
|
||||
- `docs/CHANGELOG.md` и `docs/CHANGELOG.ru.md`;
|
||||
- `docs/USER-GUIDE.ru.md` — placement/types/move/delete/light;
|
||||
- `docs/ARCHITECTURE.md`, `docs/CANVAS.md`, `docs/WALL-THICKNESS.md`,
|
||||
`docs/LIGHT.md`, `docs/SUN.md`, `docs/CONFIG-COMPATIBILITY.md`;
|
||||
- `docs/USER-GUIDE.ru.md` — Walls finish, placement/types/move/delete/light и
|
||||
closure через стену с проёмом;
|
||||
- `docs/ARCHITECTURE.md`, `docs/CANVAS.md`, `docs/UX-MODES.md`,
|
||||
`docs/WALL-THICKNESS.md`, `docs/LIGHT.md`, `docs/SUN.md`,
|
||||
`docs/CONFIG-COMPATIBILITY.md`;
|
||||
- `docs/TESTING.md`.
|
||||
|
||||
Нужны reviewed Flat/Iso/Glow golden artifacts, targeted browser/performance
|
||||
reports and exact Linux backend evidence. Visual baselines принимаются только
|
||||
через `golden:accept -- --reviewed` по полному Linux artifact.
|
||||
|
||||
## 24. Принятые технические предположения
|
||||
## 25. Принятые технические предположения
|
||||
|
||||
- partition host хранится explicit id+t, materialized x/y/angle сохраняются;
|
||||
- room-wall openings остаются implicit для backward compatibility;
|
||||
- ambiguous exact placement tie отклоняется вместо скрытого host выбора;
|
||||
- exact covering room-wall/partition overlap выбирает partition host как
|
||||
owner-approved composite; прочие ambiguous ties отклоняются;
|
||||
- structural room topology may use uncut wall axes, while all physical/light
|
||||
consumers continue using type-specific cuts; shared persisted geometry не
|
||||
создаётся;
|
||||
- partition window не становится exterior sun source;
|
||||
- invalid host/cut fail-dark and hidden from ordinary View;
|
||||
- точная форма discriminator fields может меняться на ревью без изменения
|
||||
|
||||
@@ -88,7 +88,7 @@ GitHub Issues и GitHub Projects (v2) остаются единственным
|
||||
| [#107](https://github.com/Matysh/houseplan-card/issues/107) Переключение виртуального источника света «Всегда» | [107-virtual-light-toggle.md](107-virtual-light-toggle.md) |
|
||||
| [#122](https://github.com/Matysh/houseplan-card/issues/122) Изометрический режим Stage 2: скрытый режим и визуальная полировка | [122-isometric-stage2.md](122-isometric-stage2.md) |
|
||||
| [#123](https://github.com/Matysh/houseplan-card/issues/123) Split из вершины не меняет наружную геометрию стен | [123-corner-split-wall.md](123-corner-split-wall.md) |
|
||||
| [#132](https://github.com/Matysh/houseplan-card/issues/132) Проёмы в независимых перегородках | [132-partition-openings.md](132-partition-openings.md) |
|
||||
| [#132](https://github.com/Matysh/houseplan-card/issues/132) Проёмы в независимых стенах (+ bug [#185](https://github.com/Matysh/houseplan-card/issues/185)) | [132-partition-openings.md](132-partition-openings.md) |
|
||||
| [#137](https://github.com/Matysh/houseplan-card/issues/137) Узлы и линии привязки в редакторе Плана | [137-plan-snap-overlay.md](137-plan-snap-overlay.md) |
|
||||
| [#141](https://github.com/Matysh/houseplan-card/issues/141) Бесшовные стыки перегородок и открытых контуров | [141-wall-junctions.md](141-wall-junctions.md) |
|
||||
| [#157](https://github.com/Matysh/houseplan-card/issues/157) Тип проёма «Открытый проём» | [157-open-passage.md](157-open-passage.md) |
|
||||
|
||||
Reference in New Issue
Block a user