mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 23:19:14 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac2bd86166 |
@@ -0,0 +1,433 @@
|
|||||||
|
# Issue #148 — Tool-first редактирование комнаты в Plan Editor
|
||||||
|
|
||||||
|
- **Issue:** https://github.com/Matysh/houseplan-card/issues/148
|
||||||
|
- **Редакция:** первая редакция для независимого ревью; статус задачи определяется
|
||||||
|
только метками issue
|
||||||
|
- **Тип / приоритет:** feature + polish / P2
|
||||||
|
- **Оценка:** пользовательская ценность 8/10; ценность для разработки 7/10;
|
||||||
|
сложность и риск 8/10
|
||||||
|
- **Область:** нижняя панель Plan Editor, шесть инструментов редактирования
|
||||||
|
комнаты, выбор целей, локальные параметры, Undo/Redo, keyboard и accessibility
|
||||||
|
- **Модель данных:** сохранённый формат плана не меняется; `ToolSession` — только
|
||||||
|
runtime-состояние редактора
|
||||||
|
- **Связано:** `docs/UX-MODES.md`, `docs/CANVAS.md`, `docs/RESIZE.md`,
|
||||||
|
`docs/WALL-THICKNESS.md`, `docs/TOUCH-SUPPORT.md`
|
||||||
|
|
||||||
|
## 1. Сценарий и продуктовый контекст
|
||||||
|
|
||||||
|
**Персона:** администратор дома, который строит и исправляет план в
|
||||||
|
desktop-браузере.
|
||||||
|
|
||||||
|
**Поверхность и момент:** пользователь открывает Plan Editor и хочет выполнить
|
||||||
|
операцию над комнатой, ещё не выбрав комнату или стену.
|
||||||
|
|
||||||
|
**До → после, без терминов реализации:** сейчас состав нижней панели зависит от
|
||||||
|
того, сколько комнат уже выбрано, и заставляет сначала угадывать нужное
|
||||||
|
выделение; после изменения пользователь одним и тем же способом сначала
|
||||||
|
выбирает действие, затем требуемые объекты и только после валидного выбора
|
||||||
|
настраивает и применяет результат.
|
||||||
|
|
||||||
|
Это поддерживает J4 и J6 из `docs/SCOPE.md`: встроенный редактор становится
|
||||||
|
предсказуемым инструментом построения и последующего исправления плана.
|
||||||
|
|
||||||
|
## 2. Решение владельца и источник UX-контракта
|
||||||
|
|
||||||
|
Владелец 15.08.2026 отклонил предложенное разбиение на этапы: общий framework и
|
||||||
|
все шесть действий поставляются **одним релизом**. Каноническая запись:
|
||||||
|
https://github.com/Matysh/houseplan-card/issues/148#issuecomment-5301106841
|
||||||
|
|
||||||
|
Приложенный к issue архив `Plan Editor.zip` является UX-референсом. Его
|
||||||
|
`DECISION.md`, `UX-SPECIFICATION.md`, `WIREFRAMES.md`,
|
||||||
|
`interactive-prototype.html` и `states.html` уточняют поведение, но не являются
|
||||||
|
готовым кодом или отдельной системой стилей. При расхождении приоритет таков:
|
||||||
|
|
||||||
|
1. решения владельца в issue;
|
||||||
|
2. это ТЗ;
|
||||||
|
3. текстовые документы архива;
|
||||||
|
4. визуальная реализация прототипа.
|
||||||
|
|
||||||
|
## 3. Скоуп одного релиза
|
||||||
|
|
||||||
|
В задачу входят:
|
||||||
|
|
||||||
|
1. единый runtime lifecycle сессии инструмента;
|
||||||
|
2. стабильная группа «Редактировать комнату» с действиями «Объединить»,
|
||||||
|
«Разделить», «Размер», «Граница», «Толщина», «Удалить»;
|
||||||
|
3. перевод на tool-first контракт всех шести действий без сохранения скрытого
|
||||||
|
preselection-зависимого маршрута;
|
||||||
|
4. инструкции, счётчики, validation errors и визуальные состояния active,
|
||||||
|
hover, selected и invalid;
|
||||||
|
5. локальная панель толщины и контекстные настройки остальных инструментов;
|
||||||
|
6. единые правила отмены, переключения, фокуса, клавиатуры и Undo/Redo;
|
||||||
|
7. сохранение верхней навигации и занимаемой нижней панелью геометрии;
|
||||||
|
8. unit, browser smoke, visual golden, документация и RU/EN changelog.
|
||||||
|
|
||||||
|
Поставка только framework, Merge или Thickness при незавершённых остальных
|
||||||
|
четырёх инструментах не выполняет задачу.
|
||||||
|
|
||||||
|
## 4. Не входит в задачу
|
||||||
|
|
||||||
|
- новая верхняя навигация, постоянный правый inspector или перенос редактора в
|
||||||
|
отдельную страницу;
|
||||||
|
- новые архитектурные операции, которых сейчас нет в Plan Editor;
|
||||||
|
- изменение результата Merge/Split/Resize/Boundary/Thickness/Delete после
|
||||||
|
подтверждения, кроме необходимого выравнивания их UX lifecycle;
|
||||||
|
- изменение моделей комнат, стен, проёмов, перегородок, колонн и HA Areas;
|
||||||
|
- миграция, schema version или backend API;
|
||||||
|
- переход Devices/Background editor на новый lifecycle;
|
||||||
|
- полноценный touch-first Plan Editor: редактор остаётся desktop-first, при
|
||||||
|
обязательном safety floor из раздела 11;
|
||||||
|
- изменение View, киоска и верхней segmented navigation;
|
||||||
|
- новый верхнеуровневый режим «Удаление».
|
||||||
|
|
||||||
|
## 5. Информационная архитектура нижней панели
|
||||||
|
|
||||||
|
### 5.1. Стабильные группы
|
||||||
|
|
||||||
|
В Plan сохраняются существующая верхняя навигация и общий каркас нижней панели.
|
||||||
|
Панель предоставляет стабильные группы:
|
||||||
|
|
||||||
|
- «Выбрать»;
|
||||||
|
- «Редактировать комнату»;
|
||||||
|
- «Контур комнаты»;
|
||||||
|
- «Конструкции»;
|
||||||
|
- «Проём».
|
||||||
|
|
||||||
|
Внутри «Редактировать комнату» состав не меняется от выделения на холсте:
|
||||||
|
|
||||||
|
1. Объединить;
|
||||||
|
2. Разделить;
|
||||||
|
3. Размер;
|
||||||
|
4. Граница;
|
||||||
|
5. Толщина;
|
||||||
|
6. Удалить.
|
||||||
|
|
||||||
|
Группа доступна без предварительного выбора комнаты. Условия конкретной
|
||||||
|
операции показывает активная сессия, а не disabled-состав подпанели.
|
||||||
|
|
||||||
|
### 5.2. Шесть обзорных состояний
|
||||||
|
|
||||||
|
Требуемый комплект продуктовых состояний/скриншотов:
|
||||||
|
|
||||||
|
1. без выбора;
|
||||||
|
2. редактирование комнаты;
|
||||||
|
3. контур комнаты;
|
||||||
|
4. конструкции;
|
||||||
|
5. проём;
|
||||||
|
6. подтверждение удаления.
|
||||||
|
|
||||||
|
«Подтверждение удаления» — временное destructive-состояние внутри группы
|
||||||
|
«Редактировать комнату». Оно не добавляет шестую постоянную группу или вкладку.
|
||||||
|
|
||||||
|
### 5.3. Геометрия панели
|
||||||
|
|
||||||
|
- раскрытие группы и смена фазы не меняют размеры stage и не сдвигают холст;
|
||||||
|
- содержимое остаётся в выделенной нижней области и использует существующий
|
||||||
|
shared secondary controller;
|
||||||
|
- overflow прокручивается внутри панели; кнопка подтверждения и текущая
|
||||||
|
инструкция не уходят за viewport;
|
||||||
|
- локальная плавающая панель может перекрывать stage, но не участвует в layout.
|
||||||
|
|
||||||
|
## 6. Каноническая сессия инструмента
|
||||||
|
|
||||||
|
Реализация может уточнить имена типов, но обязана иметь один явный источник
|
||||||
|
runtime-истины со следующим смыслом:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface ToolSession {
|
||||||
|
tool: 'merge' | 'split' | 'resize' | 'boundary' | 'wallthick' | 'delete' | null;
|
||||||
|
phase: 'idle' | 'selecting_targets' | 'validating_targets' | 'configuring' | 'applying';
|
||||||
|
targets: ToolTarget[];
|
||||||
|
anchor?: { x: number; y: number };
|
||||||
|
draft: Record<string, unknown>;
|
||||||
|
validationError?: { key: string; targetId?: string };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Обязательные инварианты:
|
||||||
|
|
||||||
|
1. `tool === null` означает отсутствие незавершённой операции;
|
||||||
|
2. тип, количество, порядок и совместимость целей задаёт активный инструмент;
|
||||||
|
3. `selectedRooms.length` и другие глобальные selection counts не определяют
|
||||||
|
состав подпанели;
|
||||||
|
4. hover не является target и не меняет конфигурацию;
|
||||||
|
5. invalid target не добавляется в `targets`;
|
||||||
|
6. `draft` и targets не пишутся в server config, localStorage или history;
|
||||||
|
7. единственная граница Undo/Redo — успешно применённая команда;
|
||||||
|
8. после apply сессия завершается и очищается до `idle`; повтор операции
|
||||||
|
требует нового явного выбора инструмента;
|
||||||
|
9. переключение space/mode, закрытие редактора и потеря актуальной цели
|
||||||
|
безопасно отменяют незавершённую сессию;
|
||||||
|
10. asynchronous validation/apply проверяют revision сессии: запоздалый ответ
|
||||||
|
отменённого или заменённого инструмента не меняет UI и конфигурацию.
|
||||||
|
|
||||||
|
Существующие разрозненные поля допустимы как внутренние детали перехода, но не
|
||||||
|
могут оставаться конкурирующими источниками lifecycle.
|
||||||
|
|
||||||
|
## 7. Контракты шести инструментов
|
||||||
|
|
||||||
|
### 7.1. Объединить
|
||||||
|
|
||||||
|
1. Клик по «Объединить» включает инструмент и показывает «Выберите две
|
||||||
|
смежные комнаты», счётчик `0 из 2`.
|
||||||
|
2. Первая валидная комната получает selected-state, счётчик становится
|
||||||
|
`1 из 2`.
|
||||||
|
3. Повторный клик по уже выбранной комнате снимает её; порядок остальных целей
|
||||||
|
сохраняется.
|
||||||
|
4. Вторая кандидатура валидируется до добавления: это другая существующая
|
||||||
|
комната того же space/floor с подходящей общей границей, не занятая
|
||||||
|
конфликтующей операцией.
|
||||||
|
5. Невалидная комната не заменяет первую и не становится третьей целью. Рядом
|
||||||
|
с подпанелью показывается конкретная причина, а кандидат получает временный
|
||||||
|
invalid-state.
|
||||||
|
6. После второй валидной комнаты автоматически открываются действующие
|
||||||
|
настройки Merge. Фокус переходит на их заголовок/первое поле.
|
||||||
|
7. Пользователь может применить, отменить всю сессию или вернуться к выбору
|
||||||
|
комнат, сохранив первую/обе валидные цели согласно явной кнопке «Назад».
|
||||||
|
8. Конфигурация и history меняются только после подтверждения.
|
||||||
|
|
||||||
|
### 7.2. Разделить
|
||||||
|
|
||||||
|
1. Инструмент просит выбрать одну существующую комнату.
|
||||||
|
2. После валидного выбора начинается действующий маршрут задания линии Split;
|
||||||
|
незавершённые точки являются `draft`, а не history-командами.
|
||||||
|
3. Начальная/конечная точки, пересечения и результирующие полигоны валидируются
|
||||||
|
по текущим правилам Split; invalid click не повреждает уже валидный draft.
|
||||||
|
4. Настройки новой комнаты открываются только после законченной валидной линии.
|
||||||
|
5. «Назад» из настроек возвращает к редактированию линии; подтверждение
|
||||||
|
применяет Split атомарно, cancel очищает его полностью.
|
||||||
|
|
||||||
|
### 7.3. Размер
|
||||||
|
|
||||||
|
1. Инструмент просит выбрать одну комнату либо допустимый её сегмент.
|
||||||
|
2. Первый валидный target включает существующие resize handles и preview.
|
||||||
|
3. Live preview хранится только в сессии; server config и соседние render paths
|
||||||
|
не видят частично применённую геометрию.
|
||||||
|
4. Настройки/контролы показываются после валидного target, а apply фиксирует
|
||||||
|
одну атомарную history-команду.
|
||||||
|
5. Cancel восстанавливает точную исходную геометрию без записи и без Undo item.
|
||||||
|
|
||||||
|
### 7.4. Граница
|
||||||
|
|
||||||
|
1. Инструмент объясняет требуемую текущей операцией цель и принимает только
|
||||||
|
допустимую общую границу/её endpoints.
|
||||||
|
2. Первая точка или boundary target переводит сессию в выбор следующей цели;
|
||||||
|
pan/pinch не подтверждает точку.
|
||||||
|
3. Невалидная цель не заменяет валидный anchor и сопровождается конкретной
|
||||||
|
причиной.
|
||||||
|
4. Конфигурация границы применяется одной подтверждённой командой. Esc во
|
||||||
|
время двухточечного выбора сначала возвращает к выбору целей по правилам
|
||||||
|
раздела 9, не создавая history.
|
||||||
|
|
||||||
|
### 7.5. Толщина
|
||||||
|
|
||||||
|
1. Инструмент показывает «Выберите стену или несколько стен».
|
||||||
|
2. Доступный atomic wall segment получает hover-state; клик добавляет/снимает
|
||||||
|
его из набора targets. Открытый span и другой невалидный объект не
|
||||||
|
добавляются.
|
||||||
|
3. После первого выбранного сегмента появляется локальная панель рядом с ним:
|
||||||
|
поле «Толщина», диапазон `1–100 см` (с действующим imperial-equivalent),
|
||||||
|
«Применить ко всем стенам комнаты» и кнопка подтверждения с галочкой.
|
||||||
|
4. При нескольких targets anchor панели — общий bbox выбранных сегментов либо
|
||||||
|
последний выбранный сегмент; выбор должен быть детерминирован.
|
||||||
|
5. Предпочтительное положение — под anchor с отступом 8–12 px. Панель
|
||||||
|
переворачивается/сдвигается, чтобы целиком остаться в card viewport, не
|
||||||
|
закрывать выбранный сегмент и критичные handles.
|
||||||
|
6. Поле может содержать draft, но стены не меняются до подтверждения. Ошибка
|
||||||
|
диапазона показывается рядом с полем и блокирует apply.
|
||||||
|
7. «Ко всем стенам комнаты» вычисляет цели от комнаты выбранного anchor в
|
||||||
|
момент подтверждения; неоднозначность shared wall решается действующим
|
||||||
|
владельцем atomic interval и не распространяется на соседнюю комнату
|
||||||
|
скрыто.
|
||||||
|
8. Одна галочка создаёт одну атомарную history-команду для всех targets.
|
||||||
|
|
||||||
|
### 7.6. Удалить
|
||||||
|
|
||||||
|
1. Инструмент просит выбрать одну комнату; hover/selected не удаляют данные.
|
||||||
|
2. После валидного target открывается встроенное состояние подтверждения с
|
||||||
|
именем комнаты и явным destructive action.
|
||||||
|
3. Красный цвет используется для финальной destructive-кнопки и invalid/error,
|
||||||
|
но не как постоянная окраска всей группы.
|
||||||
|
4. «Назад» возвращает к выбору комнаты; cancel не создаёт history.
|
||||||
|
5. Подтверждение удаляет только явно выбранную комнату существующей атомарной
|
||||||
|
командой и затем очищает сессию.
|
||||||
|
|
||||||
|
## 8. Визуальные состояния и обратная связь
|
||||||
|
|
||||||
|
- **active tool:** постоянный cyan/accent state кнопки и текстовая инструкция;
|
||||||
|
- **hover target:** лёгкий контур без изменения target count;
|
||||||
|
- **selected target:** стабильный заметный контур/заливка и текстовый счётчик;
|
||||||
|
- **invalid target:** краткий красный/not-allowed state вместе с текстовой
|
||||||
|
причиной; цвет не является единственным каналом;
|
||||||
|
- **applying:** повторное подтверждение блокируется, но отменённый устаревший
|
||||||
|
completion не может завершить новую сессию;
|
||||||
|
- status/instruction использует `aria-live="polite"`, validation error —
|
||||||
|
`aria-live="assertive"` или эквивалентный alert.
|
||||||
|
|
||||||
|
Стили берутся из текущих токенов редактора. Прототип определяет иерархию и
|
||||||
|
состояния, но не разрешает вводить параллельную палитру.
|
||||||
|
|
||||||
|
## 9. Отмена, keyboard и focus
|
||||||
|
|
||||||
|
1. Повторный клик по активному инструменту отменяет всю незавершённую сессию.
|
||||||
|
2. Переключение инструмента атомарно очищает targets, anchors, draft, preview,
|
||||||
|
validation error и локальную панель предыдущего.
|
||||||
|
3. Esc в `configuring` закрывает настройки и возвращает к `selecting_targets`
|
||||||
|
с последним валидным набором targets.
|
||||||
|
4. Esc в `selecting_targets` очищает targets и выключает инструмент.
|
||||||
|
5. Для многошагового Split/Boundary первый Esc может снять последнюю
|
||||||
|
незавершённую точку только если это явно показано пользователю; следующий
|
||||||
|
следует общему правилу отмены сессии.
|
||||||
|
6. Enter применяет только валидную configuring-фазу и никогда не подтверждает
|
||||||
|
destructive Delete без фокуса на явной кнопке.
|
||||||
|
7. После автоматического открытия настроек фокус переходит на их heading или
|
||||||
|
первое поле; после «Назад» — на active tool/instruction; после apply/cancel
|
||||||
|
— на кнопку запуска инструмента.
|
||||||
|
8. Кнопки имеют `aria-pressed`, локализованное имя и понятный disabled reason.
|
||||||
|
|
||||||
|
## 10. Модель данных, persistence и compatibility
|
||||||
|
|
||||||
|
- форматы `spaces`, `rooms`, `walls`, `open_spans`, openings и физических
|
||||||
|
объектов не меняются;
|
||||||
|
- `ToolSession`, targets, anchors и drafts не сериализуются;
|
||||||
|
- миграции, backfill и schema version нет;
|
||||||
|
- открытие и отмена любого инструмента не вызывает `_saveConfig()`;
|
||||||
|
- применённые команды используют действующий config/write contract и остаются
|
||||||
|
читаемыми предыдущей версией;
|
||||||
|
- import/export не получает новых полей;
|
||||||
|
- текущие планы открываются без materialisation и побайтовых изменений.
|
||||||
|
|
||||||
|
## 11. Touch, zoom, resilience и performance
|
||||||
|
|
||||||
|
Plan Editor остаётся desktop-first. На coarse pointer полный ergonomic parity
|
||||||
|
не требуется, но:
|
||||||
|
|
||||||
|
- второй палец, pan, pinch и pointercancel не могут подтвердить цель или apply;
|
||||||
|
- touch target controls не меньше действующего minimum;
|
||||||
|
- cancel/switch/space change не оставляет preview или заблокированный stage;
|
||||||
|
- zoom между выбором targets не меняет их identity и корректно перепривязывает
|
||||||
|
локальную панель;
|
||||||
|
- удаление target внешним config update переводит сессию в безопасную отмену с
|
||||||
|
сообщением, а не применяет операцию к другому объекту.
|
||||||
|
|
||||||
|
Hover/pointermove меняют только дешёвый preview. Полная геометрия, render model
|
||||||
|
и secondary-panel composition не пересчитываются на каждый pixel движения.
|
||||||
|
Target validation и локальная раскладка входят в существующие bounded caches;
|
||||||
|
HA state ticks не перестраивают tool session без структурной причины.
|
||||||
|
|
||||||
|
## 12. i18n
|
||||||
|
|
||||||
|
Все новые пользовательские строки добавляются одновременно в RU и EN:
|
||||||
|
|
||||||
|
- название группы и шести действий, если действующие ключи не подходят;
|
||||||
|
- инструкции каждой фазы;
|
||||||
|
- счётчики целей (`0 из 2`, `1 из 2`, `2 из 2`) через plural/parameter contract;
|
||||||
|
- конкретные validation reasons Merge и остальных инструментов;
|
||||||
|
- «Назад», «Применить», «Применить ко всем стенам комнаты»;
|
||||||
|
- accessible labels/status для панели и targets.
|
||||||
|
|
||||||
|
Нельзя собирать предложения конкатенацией или оставлять prototype-only English.
|
||||||
|
Термины сверяются с `docs/USER-GUIDE.ru.md`.
|
||||||
|
|
||||||
|
## 13. Acceptance criteria
|
||||||
|
|
||||||
|
1. «Редактировать комнату» доступно без preselection и всегда показывает все
|
||||||
|
шесть действий в заданном порядке.
|
||||||
|
2. В основной панели нет компоновок «выбрана 1 комната»/«выбраны 2 комнаты» и
|
||||||
|
ветвления состава от `selectedRooms.length`.
|
||||||
|
3. Каждое из шести действий следует фазам tool → targets → validation →
|
||||||
|
configuring → apply и не пишет draft в config/history.
|
||||||
|
4. Merge показывает `0/2` и `1/2`, не принимает третью/невалидную комнату и
|
||||||
|
автоматически открывает настройки после второй валидной.
|
||||||
|
5. Thickness допускает один/несколько atomic segments, открывает рядом панель,
|
||||||
|
валидирует `1–100 см`, поддерживает all-room и применяет только по галочке.
|
||||||
|
6. Split, Resize и Boundary сохраняют действующую геометрическую семантику, но
|
||||||
|
получают единые выбор, отмену, настройки и apply boundary.
|
||||||
|
7. Delete сначала выбирает одну комнату и показывает отдельное подтверждение;
|
||||||
|
до финальной кнопки данные не меняются.
|
||||||
|
8. Active, hover, selected и invalid различимы визуально и доступны без цвета.
|
||||||
|
9. Esc, повторный tool click, смена tool/mode/space и stale target очищают
|
||||||
|
незавершённое состояние по разделам 6 и 9.
|
||||||
|
10. Undo/Redo содержит только подтверждённые операции — ровно одну запись на
|
||||||
|
один apply независимо от числа targets.
|
||||||
|
11. Верхняя navigation не меняется, secondary content не сдвигает stage, а
|
||||||
|
локальная панель целиком остаётся в viewport при zoom и у всех краёв.
|
||||||
|
12. RU/EN, keyboard, focus, ARIA status/error и reduced-motion проходят
|
||||||
|
проверки; destructive Enter не срабатывает неявно.
|
||||||
|
13. Существующие планы и wire format не меняются; cancel не вызывает save.
|
||||||
|
14. Все шесть состояний раздела 5.2 обновлены и приняты visual review.
|
||||||
|
|
||||||
|
## 14. Проверки и доказательства
|
||||||
|
|
||||||
|
### Unit
|
||||||
|
|
||||||
|
- переходы state machine для каждого инструмента, повторного клика, switch,
|
||||||
|
Esc, apply, stale async completion и external target removal;
|
||||||
|
- target cardinality/identity и invalid-target exclusion;
|
||||||
|
- Merge same floor/shared boundary и автоматический configuring transition;
|
||||||
|
- Thickness multi-select, `1–100`, all-room и одна history-команда;
|
||||||
|
- отсутствие save/history для всех cancel paths.
|
||||||
|
|
||||||
|
### Browser smoke
|
||||||
|
|
||||||
|
- полный happy path и cancel/back path всех шести инструментов мышью;
|
||||||
|
- keyboard-only Merge, Thickness и Delete safety;
|
||||||
|
- zoom/pan во время выбора и позиционирование локальной панели у четырёх краёв;
|
||||||
|
- mode/space switch, pointercancel и structural config update;
|
||||||
|
- верхняя навигация и размеры stage до/после раскрытия групп.
|
||||||
|
|
||||||
|
### Golden
|
||||||
|
|
||||||
|
Обновляется и reviewится комплект из шести состояний раздела 5.2 минимум в
|
||||||
|
desktop theme light/dark, плюс узкие golden для:
|
||||||
|
|
||||||
|
- Merge `1 из 2`, invalid second target и configuring;
|
||||||
|
- Thickness hover, multi-selected и local panel у края;
|
||||||
|
- Delete confirmation.
|
||||||
|
|
||||||
|
Baseline меняется только после проверки, что diff соответствует ТЗ. Golden,
|
||||||
|
smoke и performance запускаются в release gate перед бетой; цикл реализации —
|
||||||
|
`typecheck`, `unit`, `build` по процессу.
|
||||||
|
|
||||||
|
## 15. Release-артефакты
|
||||||
|
|
||||||
|
В том же user-visible коммите реализации обязательны:
|
||||||
|
|
||||||
|
- `docs/CHANGELOG.md` и `docs/CHANGELOG.ru.md`;
|
||||||
|
- `docs/USER-GUIDE.ru.md` — новый порядок редактирования всех шести операций;
|
||||||
|
- `docs/UX-MODES.md` — стабильные группы и tool-first lifecycle;
|
||||||
|
- при необходимости `docs/CANVAS.md`, `docs/RESIZE.md` и
|
||||||
|
`docs/WALL-THICKNESS.md`, если реализация уточнит их взаимодействие;
|
||||||
|
- RU/EN locale files;
|
||||||
|
- принятые golden/baseline и smoke scenario либо ссылка на канонический
|
||||||
|
артефакт CI по правилам репозитория;
|
||||||
|
- `docs/TESTING.md`, если добавлен новый сценарий/gate.
|
||||||
|
|
||||||
|
Security и backend release artifacts не требуются, пока реализация не меняет
|
||||||
|
права или wire format. Если такой change окажется необходим, задача должна
|
||||||
|
вернуться к владельцу до кода.
|
||||||
|
|
||||||
|
## 16. Риски и rollback
|
||||||
|
|
||||||
|
Основные риски: два конкурирующих источника selection state, применение stale
|
||||||
|
draft, потеря Undo boundary, недоступный focus и floating panel вне viewport.
|
||||||
|
Они закрываются единой сессией, revision guard и проверками раздела 14.
|
||||||
|
|
||||||
|
Rollback — возврат UI/runtime-кода и locale/docs без миграции данных. Уже
|
||||||
|
сохранённые планы остаются совместимыми.
|
||||||
|
|
||||||
|
## 17. Принятые технические предположения
|
||||||
|
|
||||||
|
1. Shared secondary controller остаётся хозяином нижней contextual surface;
|
||||||
|
новый lifecycle расширяет его, а не создаёт второй overlay stack.
|
||||||
|
2. Existing domain helpers Merge/Split/Resize/Boundary/Thickness/Delete
|
||||||
|
сохраняются; задача унифицирует orchestration и transaction boundaries.
|
||||||
|
3. Для multi-select Thickness стабильная identity — нормализованный atomic wall
|
||||||
|
interval вместе с room/space context, а не DOM element или экранные
|
||||||
|
координаты.
|
||||||
|
4. «Заблокирована другим процессом» на первом этапе означает локальную
|
||||||
|
конфликтующую сессию/структурно устаревшую цель; новая distributed locking
|
||||||
|
модель не вводится.
|
||||||
|
5. Overview prototype state «Удаление» трактуется как подтверждение внутри
|
||||||
|
«Редактировать комнату», поскольку это одновременно сохраняет заявленную
|
||||||
|
стабильную иерархию и шесть продуктовых скриншотов.
|
||||||
@@ -86,6 +86,7 @@ GitHub Issues и GitHub Projects (v2) остаются единственным
|
|||||||
| [#123](https://github.com/Matysh/houseplan-card/issues/123) Split из вершины не меняет наружную геометрию стен | [123-corner-split-wall.md](123-corner-split-wall.md) |
|
| [#123](https://github.com/Matysh/houseplan-card/issues/123) Split из вершины не меняет наружную геометрию стен | [123-corner-split-wall.md](123-corner-split-wall.md) |
|
||||||
| [#137](https://github.com/Matysh/houseplan-card/issues/137) Узлы и линии привязки в редакторе Плана | [137-plan-snap-overlay.md](137-plan-snap-overlay.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) |
|
| [#141](https://github.com/Matysh/houseplan-card/issues/141) Бесшовные стыки перегородок и открытых контуров | [141-wall-junctions.md](141-wall-junctions.md) |
|
||||||
|
| [#148](https://github.com/Matysh/houseplan-card/issues/148) Tool-first редактирование комнаты | [148-tool-first-plan-editor.md](148-tool-first-plan-editor.md) |
|
||||||
|
|
||||||
## Правило актуализации
|
## Правило актуализации
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user