mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
@@ -0,0 +1,128 @@
|
||||
# SPEC-REVIEW-304-r1
|
||||
|
||||
Issue: #304 «Редактор плана: режим «Толщина» скрывает часть осевых линий и узлов стен»
|
||||
Этап: spec (лёгкий трек, метка `small`)
|
||||
Заход: r1 · блокирующих циклов израсходовано 0 из 2 (лимит лёгкого трека — 2)
|
||||
Ревьюер: Claude (сессия ревью ТЗ), артефакт — комментарий в issue + этот документ (по правилу §5 документ не обязателен, но публикуется для трассируемости).
|
||||
|
||||
## Скоуп
|
||||
|
||||
ТЗ живёт в теле issue #304 (комментарий владельца от 2026-08-25 подтверждает `small`).
|
||||
Задача: unify статический слой архитектурных осей/узлов Plan editor (`plan-snap-overlay`)
|
||||
так, чтобы он не зависел от активного `MarkupTool` — сейчас полный слой рендерится
|
||||
только для `draw`, а в остальных девяти инструментах его подменяет
|
||||
`hidden-wall-diagnostic-overlay`, который по контракту показывает только скрытые
|
||||
перекрывающиеся *независимые* источники (draft/partition), а не полную геометрию
|
||||
комнат. AC1–AC7, план проверок, риски, откат и release-артефакты присутствуют.
|
||||
|
||||
Продуктовая рамка: J6 SCOPE.md — «Keep the plan true as the home evolves», конкретно
|
||||
«достоверная топология при поддержании плана». Owner-комментарий явно ссылается на J6.
|
||||
Соответствие подтверждаю: задача не расширяет и не меняет ни один Core user job,
|
||||
чинит расхождение представления внутри уже принятого поведения инструмента «Стены».
|
||||
|
||||
## Как проверялось
|
||||
|
||||
Ревью ТЗ выполнялось не на веру автору, а с чтением текущего кода — задача описывает
|
||||
конкретный технический механизм бага, и его нужно было заземлить, а не принять как
|
||||
заявление:
|
||||
|
||||
1. `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` §2.4/§2.10/§5/§7.1/§7.2/§12 — рамка процесса
|
||||
и лёгкого трека.
|
||||
2. Тело issue #304 и оба комментария владельца (аналитика + передача на ревью).
|
||||
3. `docs/USER-GUIDE.ru.md:373-379` — подтверждает, что текущая документация уже
|
||||
фиксирует осевые линии как поведение именно инструмента «Стены»; после фикса это
|
||||
предложение придётся расширить на все инструменты Plan editor, что ТЗ и заявляет
|
||||
в Release-артефактах.
|
||||
4. `src/houseplan-card.ts`:
|
||||
- `588` — `type MarkupTool = 'select' | 'draw' | 'column' | 'merge' | 'split' |
|
||||
'resize' | 'opening' | 'boundary' | 'wallthick' | 'delroom'` — ровно десять
|
||||
значений, как в AC2, не выдумка;
|
||||
- `1524-1526` — `get _markup(): boolean { return this._mode === 'plan'; }` — статический
|
||||
слой физически не может просочиться в View/Device/Backdrop-editor, потому что все
|
||||
точки рендера overlay обёрнуты в `this._markup ? … : nothing`; AC5 — не гипотеза, а
|
||||
прямое следствие текущей структуры кода;
|
||||
- `17565` `_renderWallBodies`, `17572-17573` `_renderHiddenWallDiagnosticOverlay`
|
||||
(без условия на `_tool`, то есть рендерится во всех markup-инструментах),
|
||||
`17578-17579` `${this._markup && this._tool === 'draw' ? … this._renderPlanSnapOverlay()
|
||||
… : nothing}` — это буквальное подтверждение корневой причины из issue: полный
|
||||
`plan-snap-overlay` гейтится на `draw`, diagnostic-слой остаётся один во всех
|
||||
остальных.
|
||||
5. `src/plan-snap-overlay.ts`:
|
||||
- `166-215` `buildHiddenWallDiagnosticGeometry` — `hidden = sources.filter(source =>
|
||||
source.kind !== 'room' && sources.some(other => other !== source &&
|
||||
positiveCollinearOverlap(...)))` — буквально подтверждает контракт «показывает
|
||||
только скрытые перекрывающиеся независимые источники», room-only рёбра без партнёра
|
||||
по перекрытию никогда сюда не попадают. Это и есть причина «части осей нет в
|
||||
Толщина» — не домысел автора ТЗ, а прочитанный код;
|
||||
- `228` `buildPlanSnapGeometry` — существующая каноническая геометрия, которую фикс
|
||||
предлагает переиспользовать для статического слоя во всех инструментах (contract p.3);
|
||||
6. `demo/smoke_plan_snap_overlay.mjs:236-239` — `result.otherPlanToolsHaveHiddenDiagnostic =
|
||||
!overlay() && !!diagnostic && …` — буквально закрепляет `!overlay()` (полного слоя нет)
|
||||
для инструмента `select` как ожидаемое поведение. Это подтверждает заявление issue
|
||||
«smoke сейчас закрепляет это расхождение вместо проверки межинструментального
|
||||
инварианта» — не голословно, а строкой теста.
|
||||
7. `demo/golden/matrix.mjs`, `demo/golden/harness.mjs` — существуют, ссылка в скоупе ТЗ
|
||||
не на вымышленную инфраструктуру.
|
||||
8. `docs/TOUCH-SUPPORT.md` — grep по overlay/snap не дал контрактных ограничений на этот
|
||||
слой; заявление «touch-контракт не расширяется» не противоречит канону (слой был и
|
||||
остаётся `pointer-events: none`, десктоп-first редактор не меняется).
|
||||
9. `docs/WALL-THICKNESS.md`, `docs/CANVAS.md`, `docs/UX-MODES.md` — grep по overlay/wallthick
|
||||
не нашёл предписаний, которым ТЗ противоречило бы.
|
||||
|
||||
## Находки
|
||||
|
||||
Нет находок уровня High или Medium. Задача полностью укладывается в лёгкий трек:
|
||||
сложность/риск, заявленные владельцем (3/10 и 3/10), подтверждаются техническим
|
||||
разбором — правка изолирована в рендер-гейтинге одного файла плюс возможное
|
||||
разделение геометрии в `plan-snap-overlay.ts`, без миграции, новых i18n-ключей,
|
||||
нового UX-контракта (видимое поведение просто перестаёт зависеть от инструмента —
|
||||
это и есть заявленный "после") и без touch-влияния.
|
||||
|
||||
Low, не блокирует, не требует правки:
|
||||
- AC1 фиксирует магическое число «шесть узлов» для контрольного участка. Это не
|
||||
домысел: число заземлено в приложенных к issue скриншотах (`2026-08-25_15-46-52.png`
|
||||
— полный вид «Стены») и будет закреплено unit-фикстурой на этапе реализации (план
|
||||
проверок, п.1). Претензий к формулировке нет, отмечаю для полноты «чего не проверял».
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- Обязательные разделы §7.1 (для лёгкого трека — §5: проблема, контракт, AC1…ACn с
|
||||
доказательством, откат) присутствуют, ТЗ фактически даёт больше, чем требует лёгкий
|
||||
трек (сценарий, эдж-кейсы, риски, release-артефакты).
|
||||
- Каждый AC (1–7) однозначен, имеет способ доказательства (`unit`/`smoke`/`golden`/
|
||||
«ревью кода») и указывает конкретный наблюдаемый инвариант, а не реализацию.
|
||||
- Корневая причина бага, названная в issue, дословно подтверждается кодом — это не
|
||||
«догадка, выданная за решение»: технический механизм проверен построчно (см. выше).
|
||||
- Контракт поведения (пп.1–7) полон: перечисляет все 10 инструментов, явно разделяет
|
||||
статическую топологию и transient-состояния инструмента «Стены», фиксирует
|
||||
presentation-only и `pointer-events: none`, границы режимов (View/Device/Backdrop) и
|
||||
отсутствие промежуточного пустого кадра при переключении.
|
||||
- Скоуп/не-скоуп корректно исключают алгоритмы привязки/записи толщины и построения
|
||||
стен — фикс ограничен представлением, не моделью.
|
||||
- Совместимость, миграция, i18n, touch, performance разобраны и обоснованы отсутствием
|
||||
влияния, а не пропущены молчанием.
|
||||
- Риски (двойная отрисовка, порядок рендера, случайная утечка transient-маркеров,
|
||||
инвалидация кэша на pointermove) названы предметно и совпадают с зонами, которые я
|
||||
сам выявил бы при чтении кода рендер-конвейера — заявка не занижает риск.
|
||||
- Откат тривиален и реалистичен (revert рендер-гейтинга, схема/данные не меняются).
|
||||
- Owner-аналитика подтверждает соответствие job J6, дубликаты проверены и отклонены
|
||||
предметно (#232 — про другое: hover при рисовании).
|
||||
|
||||
## Чего не проверял
|
||||
|
||||
- Не проверял на глаз итоговое число узлов/сегментов для контрольной fixture построчным
|
||||
выполнением `buildPlanSnapGeometry`/`buildHiddenWallDiagnosticGeometry` — это задача
|
||||
unit-теста на этапе реализации, а не спецификации; на этапе ТЗ важно было убедиться,
|
||||
что функции и семантика существуют и соответствуют описанному контракту, что сделано.
|
||||
- Не запускал `npm test`/`npm run build`/`typecheck` — на этапе ревью ТЗ гейты кода не
|
||||
прогоняются (нечего собирать, код не менялся), это относится к этапу код-ревью (§2.7).
|
||||
- Не проверял golden/смоук-набор целиком — задача их ещё не создала (в скоупе только
|
||||
план их появления), это тоже предмет код-ревью.
|
||||
- Не оценивал реальный экспорт `houseplan-space-convergence-test-...json`, приложенный к
|
||||
issue (файл не запрашивался и не был нужен: код уже подтверждает механизм независимо
|
||||
от конкретного экспорта).
|
||||
|
||||
## Вердикт
|
||||
|
||||
Зелёный. ТЗ проверяемо, однозначно, технически заземлено чтением кода, укладывается в
|
||||
лёгкий трек и закрывает продуктовую строку J6. High/Medium-находок нет.
|
||||
Reference in New Issue
Block a user