mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 13:18:58 +00:00
140 lines
13 KiB
Markdown
140 lines
13 KiB
Markdown
# SPEC-REVIEW-307-r1
|
|
|
|
Issue: #307 · Этап: ТЗ (spec) · Трек: `small` · Заход: r1 · Вердикт: **зелёный**
|
|
Блокирующих циклов израсходовано: 0/2 (лимит лёгкого трека, §4)
|
|
|
|
## Скоуп
|
|
|
|
ТЗ (в теле issue #307, small-трек, шаблон §5: проблема · контракт · AC · откат)
|
|
на исправление визуального дефекта инструмента «Стены» в редакторе плана: во
|
|
время рисования цепочки уже поставленные (персистнутые) сегменты теряют
|
|
осевую линию `.pathline` и узлы `.vertex`, потому что тело стены рисуется
|
|
поверх них, а снап-оверлей намеренно исключает активный драфт из своей
|
|
геометрии. Решение — вынести ось/узлы/rubber-band активной цепочки
|
|
(`.pathline`, `.vertex`, `.active-axis`, `.active-vertex`) из
|
|
`_renderMarkupLayer` в отдельный editor-слой между `_renderWallBodies` и
|
|
`_renderPlanSnapOverlay`, ничего не меняя в геометрии снапа.
|
|
|
|
Затронутая поверхность — Plan editor (`src/houseplan-card.ts`, один модуль),
|
|
только режим `_markup`/`_editing`; View не затрагивается. Персона — Home admin
|
|
(единственная, кто пользуется редакторами, `docs/SCOPE.md`), контекст —
|
|
задача J4/J6 («от нуля до плана» и «поддерживать план актуальным», два
|
|
встроенных редактора). Изменение чисто композиционное (порядок отрисовки уже
|
|
существующих DOM-узлов), без новых полей конфига, миграций, i18n-ключей.
|
|
|
|
## Как проверялось
|
|
|
|
Ревью читал ТЗ и тело/комментарий issue без устных пояснений автора,
|
|
состязательно — искал, где контракт невыполним или непроверяем, а не
|
|
соглашался с текстом. Каждое фактическое утверждение о коде и документации
|
|
проверено чтением, а не принято на веру:
|
|
|
|
1. `docs/SCOPE.md` — подтвердил, что задача обслуживает J4/J6 и не задевает
|
|
инвариант View/lock; продуктового конфликта нет.
|
|
2. `docs/USER-GUIDE.ru.md:372-375` — дословно подтверждает цитату ТЗ: «поверх
|
|
уже нарисованных стен видны тонкие осевые линии и точки их концов». Значит
|
|
ожидаемое поведение — не догадка автора, а уже зафиксированный контракт;
|
|
исключение для «ещё не завершённой цепочки» нигде не оговорено.
|
|
3. `src/houseplan-card.ts` — построчно сверил все технические утверждения ТЗ:
|
|
- `_renderMarkupLayer` (:19960) действительно эмитит `.pathline` (:20029),
|
|
`.active-axis`/`.active-vertex` (:20032-20036) и `.vertex` (:20038);
|
|
- вызов `_renderMarkupLayer` (:17553) стоит **до** `_renderWallBodies`
|
|
(:17565), которая, в свою очередь, стоит **до** `_renderPlanSnapOverlay`
|
|
(:17582) — ровно та последовательность, что и в ТЗ;
|
|
- `_renderPlanSnapOverlay` (:19843) и геометрия `buildPlanSnapGeometry`
|
|
(`src/plan-snap-overlay.ts:253`) действительно пропускают активный драфт
|
|
(`if (draft.id === options.activeDraftId) continue`) — второй заявленный
|
|
механизм подтверждён, не выдумка;
|
|
- `physical-geometry.ts:210-221` подтверждает, что каждый персистнутый
|
|
сегмент `room_drafts` немедленно попадает в непрозрачные тела
|
|
(`draftSegments`/`drafts`) без исключения активного драфта — то самое
|
|
тело, которое перекрывает ось;
|
|
- «hit-слой», упомянутый в контракте как остающийся на месте элемент
|
|
`_renderMarkupLayer`, — реален: `_renderPhysicalEditorLayer()` (:19711,
|
|
вызывается на :20008) рисует `.physical-hit` (прозрачные линии/пути для
|
|
перетаскивания драфтов/перегородок/колонн, `pointer-events: none` вне
|
|
инструмента «Выбор», `src/styles.ts:2256-2264`) — контракт не подменяет
|
|
несуществующим термином существующий механизм;
|
|
- цвет `#ffc14d` из AC1 подтверждён как реальный `stroke`/`fill` `.pathline`
|
|
и `.vertex` (`src/styles.ts:1803-1857`) — пиксельная проба технически
|
|
осмысленна и отличима от штриховки масонри;
|
|
- AC3 ссылается на существующий `demo/smoke_plan_snap_overlay.mjs` — файл
|
|
существует.
|
|
4. `docs/specs/228-plan-drawing-problems.md` — беглая проверка, что
|
|
`active-axis`/`active-vertex` действительно история #228 (проекция оси
|
|
активного отрезка), заявленная в issue как смежная, не пересекающаяся
|
|
работа — согласуется, конфликта скоупа нет.
|
|
5. Сверил критерии лёгкого трека (§5 PROCESS.md) построчно: сложность/риск
|
|
≤3 (аналитика — 2/10), одна поверхность, без миграции конфига, поведение
|
|
уже описано в USER-GUIDE (не новый UX-контракт), перф/touch не задеты
|
|
(перестановка существующих DOM-узлов, ни одного нового элемента). Шаблон
|
|
ТЗ соответствует §5 буквально: проблема · контракт · AC · откат, файла в
|
|
`docs/specs/` нет — верно для `small`.
|
|
6. Комментарии issue — один, аналитика владельца (S2→S4, метка `small`
|
|
поставлена и объяснена). Прежнего вердикта ревью ТЗ нет — это первый заход,
|
|
раздел «Унаследовано из r0» не применяется.
|
|
|
|
## Находки
|
|
|
|
Блокирующих (High/Medium) не найдено.
|
|
|
|
Один пограничный момент, не тянущий на находку, а не пропущенный молча:
|
|
контракт не называет позицию нового слоя относительно
|
|
`_renderResizeMeasurements`/`_renderRoomHoverOutline`/диагностического
|
|
оверлея скрытых стен/превью размещения проёма — всех элементов, которые
|
|
сейчас лежат между `_renderWallBodies` и `_renderPlanSnapOverlay`. Это не
|
|
продуктовый вопрос: перечисленные оверлеи активны для других инструментов
|
|
(resize/двери-окна) и не пересекаются по времени с активной цепочкой «Стены»,
|
|
кроме, возможно, подсветки наведённой комнаты (`roomHover`), которая может
|
|
сработать параллельно с рисованием. AC2 не требует конкретной позиции внутри
|
|
этого промежутка — только «тела → слой цепочки → снап-оверлей», и это
|
|
достаточно проверяемо смоком. Оставляю как техническую деталь на усмотрение
|
|
реализации, как и позволяет §7.1 («всё, чего пользователь не наблюдает,
|
|
агенты решают сами»); не блокирует и не снижает вердикт.
|
|
|
|
## Что проверено и корректно
|
|
|
|
- Оба продуктовых вопроса (что видит пользователь, какой объём входит в
|
|
задачу) не требуют обращения к владельцу: ожидаемое поведение уже
|
|
зафиксировано в USER-GUIDE.ru.md, объём — один модуль, одна визуальная
|
|
причина с двумя техническими механизмами, обе описаны и обе имеют решение.
|
|
Владельцу вопросов не задавалось — и это оправдано, а не пропущено.
|
|
- Причина дефекта — не догадка, выданная за факт: каждое утверждение о коде
|
|
(номера строк, имена классов/функций, порядок вызовов, поведение
|
|
`buildPlanSnapGeometry`) подтверждено чтением текущего `dev` (см. выше).
|
|
- Контракт однозначен: что именно переносится (`.pathline`, `.vertex`,
|
|
`.active-axis`, `.active-vertex`), откуда, куда (между конкретными двумя
|
|
существующими вызовами), что не меняется (геометрия/резолвер снапа,
|
|
жёлтая стилистика, всё остальное содержимое markup-слоя).
|
|
- AC1-AC3 — каждый проверяем и указывает способ доказательства (`smoke`
|
|
новый/существующий, ревью кода). AC1 задаёт конкретные пиксельные точки
|
|
(середина оси первого сегмента, центр промежуточного узла) и конкретный
|
|
ожидаемый цвет, отличимый от штриховки — тест способен упасть на текущем
|
|
`dev`, что и заявлено явно («падает на текущем dev»). AC3 явно фиксирует
|
|
границу: `plan-snap-overlay.ts` не входит в дифф.
|
|
- Откат тривиален и назван верно: одиночный revert, ни новых полей, ни
|
|
миграций, ни persisted-состояний — соответствует характеру чисто
|
|
композиционного изменения.
|
|
- Критерии лёгкого трека выполнены все одновременно, метка `small` не
|
|
оспаривается.
|
|
- Не найдено расхождений ТЗ с `docs/SCOPE.md`, `docs/USER-GUIDE.ru.md`,
|
|
`docs/UX-MODES.md`: изменение целиком внутри `hp-editor-only-layer`,
|
|
гейтится `this._markup`, View не задет, инвариант блокировок (SCOPE.md,
|
|
«The lock invariant») не касается геометрии стен.
|
|
|
|
## Чего не проверял
|
|
|
|
- Не запускал код и не собирал бандл — на этапе ревью ТЗ кода ещё нет,
|
|
проверка была по чтению текущего `dev` (`git log` показывает `dev` на
|
|
`489f68ee`, что совпадает с SHA, названным в аналитике owner).
|
|
`typecheck`/`test`/`build` к этому этапу не относятся (это гейты
|
|
код-ревью, §2.7).
|
|
- Не проверял, как новый слой будет вести себя при одновременной подсветке
|
|
наведённой комнаты (`roomHover`) во время рисования цепочки — отмечено выше
|
|
как техническая деталь реализации, не блокирующая ТЗ.
|
|
- Не оценивал производительность численно — оценка «перестановка тех же
|
|
DOM-узлов» правдоподобна на глаз и совпадает с заявлением owner в
|
|
аналитике, но замер не проводился (задача не требует его: §2.5 требует
|
|
«влияние на производительность названо», а не измерено, когда оно
|
|
очевидно нулевое).
|