mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-04 05:41:34 +00:00
129 lines
12 KiB
Markdown
129 lines
12 KiB
Markdown
# 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-находок нет.
|