diff --git a/docs/specs/132-partition-openings.md b/docs/specs/132-partition-openings.md index aaf75f75..cb0d0cb9 100644 --- a/docs/specs/132-partition-openings.md +++ b/docs/specs/132-partition-openings.md @@ -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 может меняться на ревью без изменения diff --git a/docs/specs/README.md b/docs/specs/README.md index 470e5372..219f26f3 100644 --- a/docs/specs/README.md +++ b/docs/specs/README.md @@ -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) |