Files
houseplan-card/docs/reviews/SPEC-REVIEW-447-r2.md
T
2026-09-04 05:48:58 +00:00

11 KiB
Raw Blame History

SPEC-REVIEW-447-r2

Материал: docs/specs/447-exterior-furniture-snap-keyboard-nudge.md на коммите 818ad2d2 (docs-only, класс C).

Скоуп разбора

Заход r2. Предыдущий вердикт — красный, r1, на коммите a1fbea07, единственная находка H1 (смешение render-масштаба gridPitch и normalised-масштаба GRID_STEP_N в §3/AC4 части 2). SHA r1 назван и в комментарии владельца, и в блоке «Материал раунда» самого документа r1 — резолвится, живой.

Дельта раунда — git diff a1fbea07..818ad2d2, единственный тронутый файл: сам ТЗ (37 строк, только §3 «Сдвиг выбранного декора стрелками» и AC4). Часть 1 (наружная поверхность стены, §1–2, AC1–AC3) правка не касается совсем.

Разбор сокращён до дельты: правка локальна (одна формула в одном разделе), не меняет контракт поведения (видимый шаг остаётся «одна клетка», меняется только описание внутреннего преобразования в persisted-поля), не задевает новую подсистему и не сопоставима по объёму с исходной задачей — критерии «разбирать полностью» (§2.9 PROCESS.md) не выполнены.

Как проверялось

  • Построчно сверил новый текст §3 и AC4 с кодом, который он описывает: src/space-geometry.ts (NORM_W, GRID_N, GRID_PITCH, GRID_STEP_N, CANVAS_LIMIT, clampCanvasN) и src/houseplan-editor-runtime.ts (_decorMoveUpdate, строки 4336–4376) — существующий pointer-move путь, на соответствие которому ТЗ теперь прямо ссылается.
  • Проверил происхождение символа decorH, который правка вводит в текст: src/houseplan-card.ts:8329 — приватный geттер _decorH возвращает ровно NORM_W, то есть равенство gridPitch / decorH == gridPitch / NORM_W == GRID_STEP_N не оценочное, а тождество на текущем коде.
  • Пересчитал арифметику из примера r1 (x = 0.4) по новой формуле, чтобы убедиться, что она даёт GRID_STEP_N ≈ 0.0041667, а не порядок gridPitch (≈4.1667).
  • Проверил, что правка не тронула ничего вне §3/AC4 (git diff --stat показывает только docs/specs/447-…md и публикацию docs/reviews/ SPEC-REVIEW-447-r1.md — артефакт шага публикации, не автора).
  • Проверил, что AC6 (bounds/CANVAS_LIMIT), которую делта не редактирует текстуально, остаётся корректной после фикса: CANVAS_LIMIT и clampCanvasN работают в нормализованных единицах (SANE_LIMIT = CANVAS_LIMIT * NORM_W, src/space-geometry.ts:205,207,240-241), то есть клэмп по-прежнему применяется к величине того же масштаба, что теперь корректно производит §3. Раньше (до фикса r1) это было тем же скрытым разрывом на один шаг дальше по цепочке — теперь согласовано.

Закрытие раунда r1

Находка Чем закрыта Где это видно
H1 — AC4/§3 требовали прибавлять render-gridPitch (≈4.1667) напрямую к нормализованным x/y/x1/y1/x2/y2, что уводит объект на ~4 ширины холста за одно нажатие Текст переписан: пользовательский шаг остаётся gridPitch в render-координатах, но перед записью в persisted-поля явно делится на NORM_W (X) и decorH (Y) — то же преобразование, что уже использует _decorMoveUpdate для мыши. AC4 отдельно требует, чтобы mutation «прибавляющая gridPitch прямо к persisted-полю» красила тест docs/specs/447-exterior-furniture-snap-keyboard-nudge.md:142-154 (§3) и :256-262 (AC4), коммит 818ad2d2; проверено построчным сопоставлением с src/houseplan-editor-runtime.ts:4353-4354 (dx = (anchor[0]-ax0)/NORM_W, dy = (anchor[1]-ay0)/this.host._decorH)

Унаследовано из r1

Принято без повторной проверки в этом раунде — дельта их не задевает:

  • Диагноз и контракт части 1 (наружная поверхность внешней стены): построчная сверка roomFurnitureWallSurfaces/snapFurnitureToWall, инварианты общей/ нулевой/independent стены (AC1–AC3). См. docs/reviews/SPEC-REVIEW-447-r1.md, раздел «Проверено и корректно», на SHA a1fbea07.
  • Соответствие 6 видов decor (line/rect/ellipse/text/furniture/image) DecorKind в коде — там же, на a1fbea07; правка r1→r2 не меняла список видов, только формулу дельты для всех них одинаково.
  • Guard-условия Arrow (AC8, focus/dialog/toolbar) и переиспользование паттерна _keyHandler — там же, на a1fbea07.
  • Полнота обязательных разделов §7.1 и обоснование full track (критерии small не выполнены) — там же, на a1fbea07; правка не добавляла и не убирала разделы.
  • Терминология «Редактор подложки» сверена с docs/USER-GUIDE.ru.md — там же, на a1fbea07.
  • Отсутствие продуктовых вопросов к владельцу (владелец закрыл Shift-шаг, подложку и формулировку шага решениями от 04.09.2026 до старта ревью) — подтверждено в аналитике issue, без изменений в r2.

Находки текущего раунда

Новых High/Medium в скоупе задачи не найдено. Правка r1→r2 сама по себе не вносит новых противоречий: формула симметрична по X/Y, использует только существующие именованные константы кода (NORM_W, decorH, GRID_STEP_N), и явно называет запрещённую mutation для AC4.

Проверено и корректно (по дельте)

  • Новая формула §3/AC4 даёт identical результат для X и Y на текущем квадратном холсте (decorH === NORM_W тождественно, не приближённо) — повторное расхождение render/normalised исключено для обеих осей.
  • AC6 (bounds/CANVAS_LIMIT) остаётся согласованной с обновлённой §3: обе оперируют нормализованным масштабом.
  • Правка не расширила и не сузила скоуп (видимый пользователю шаг — та же «одна клетка», раздел «Скоуп» получил только уточнение «с явным переводом в нормализованные persisted-поля», не новый пункт).
  • Диф не тронул файлы вне docs/specs/… (кроме публикации r1-документа конвейером).

Не проверял

  • Часть 1 (наружная поверхность стены) — не открывал заново, дельта её не касается; см. «Унаследовано из r1».
  • typecheck/test/build/check-docs/model-invariants/смоки — диапазон этого раунда docs-only, src/** не тронут, дешёвые гейты неприменимы к этому диффу (нечего собирать/тестировать — ТЗ ещё не реализовано). Это же относилось к r1 на docs-only материале.
  • Реализуемость owner-группировки атома «ровно одной комнате» и точную структуру будущего pure-модуля src/editors/decor/geometry.ts — предмет код-ревью, не спек-ревью.

Вердикт

Единственная находка r1 закрыта по существу и проверяемо: формула теперь воспроизводит уже существующий в коде путь пересчёта render→normalised для decor-координат, а не изобретает новую арифметику. Новых находок дельта не вносит. Часть 1 не менялась и наследуется из r1 без повторной проверки.

Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0

Документ: docs/reviews/SPEC-REVIEW-447-r2.md


Материал раунда

  • Ветка: issue/447-exterior-snap-keyboard, коммит 818ad2d2bb2f — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 12298423bb5c53540ed321ce11084c908fbd682f
    git log --all --format='%H %T' | grep 12298423bb5c
    
  • ТЗ docs/specs/447-exterior-furniture-snap-keyboard-nudge.md, блоб 5c0036470b3bd675147ad5dc308b8d760be18b9c
    git log --all --find-object=5c0036470b3bd675147ad5dc308b8d760be18b9c -- docs/specs/447-exterior-furniture-snap-keyboard-nudge.md