From d97bf63feb4f8d5a89e914a5f702e381411fc222 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 08:21:10 +0000 Subject: [PATCH] docs: review document for #431 Issue: #431 User-Visible: no --- docs/reviews/SPEC-REVIEW-431-r1.md | 180 +++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 docs/reviews/SPEC-REVIEW-431-r1.md diff --git a/docs/reviews/SPEC-REVIEW-431-r1.md b/docs/reviews/SPEC-REVIEW-431-r1.md new file mode 100644 index 00000000..1bd6aee8 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-431-r1.md @@ -0,0 +1,180 @@ +# SPEC-REVIEW #431 · r1 + +Issue: [#431](https://github.com/Matysh/houseplan-card/issues/431) — `kind:'image'` выпал из +канонизации координат. +Документ ТЗ: `docs/specs/431-image-coordinate-canonicalization.md` +Материал: коммит `260af7bfd200bb40beb2323af2ad5232e2686325` (`docs(spec): define image +coordinate canonicalization`, `Issue: #431 · User-Visible: no`), совпадает с `HEAD`. +Трек: полный (не `small`) — причина названа автором в S2-analysis и в ТЗ и подтверждена +ниже. + +## Скоуп ревью + +Первый заход. Проверено: соответствие продуктовой рамке `docs/SCOPE.md`, полнота +разделов §7.1, однозначность и доказуемость AC1–AC8, отсутствие непомеченных догадок, +корректность трек-классификации (полный vs `small`), трассируемость issue ↔ ТЗ. + +## Как проверялось + +Ревью читало ТЗ состязательно, без пояснений автора, и сверяло каждое фактическое +утверждение с текущим деревом (не с описанием ТЗ): + +- прочитаны `docs/SCOPE.md`, `PROCESS.md` (§1–§10.4), `AGENTS.md` целиком; +- прочитан текст issue #431 и все три комментария (аналитика, занятие, «ТЗ готово»); +- сверены `src/coordinate-canonicalization.ts` (обе точки: `visitLatticeCoordinates` + строка 158 и `canonicalizeConfigGeometryInPlace` строка 338) и + `custom_components/houseplan/coordinate_canonicalization.py` строка 153 — оба + действительно перечисляют `("rect", "ellipse", "furniture")` без `image`, как + заявлено в issue и ТЗ; +- сверен `src/editors/decor/types.ts` — `DecorImage extends DecorBoxBase` с полями + `x/y/w/h/angle` подтверждён, `DecorKind` содержит `'image'`; +- сверена `test/fixtures/coordinate-canonicalization.json` и + `test/coordinate-canonicalization.test.mjs` — фикстура содержит `line/rect/ + ellipse/text/furniture`, `image` действительно отсутствует; +- проверено, что `custom_components/houseplan/validation.py:1909` (`CONFIG_SCHEMA`) + вызывает тот же `canonicalize_config_geometry` внутри `vol.All(...)`, то есть + Python не имеет отдельной ветки для схемы — правка одной функции закрывает оба + пути, как утверждает AC3; +- проверено, что все вызовы `canonicalizeConfigGeometry(InPlace)` / + `latticeCanonicalizationReport` во фронтенде (`houseplan-card.ts`, + `houseplan-editor-runtime.ts`, `plan-optimizer.ts`, `wall-segment-model.ts`) идут + через единый модуль — второй путь канонизации, которого ТЗ могло бы не заметить, + отсутствует; +- проверено, что перечисления `rect/ellipse/furniture` в `houseplan-editor-runtime.ts` + и `houseplan-card.ts` относятся к UI-логике редактора (заливка, диалоги), не к + канонизации, и там `image` уже присутствует, где это нужно — подтверждает, что + ТЗ верно провело границу не-скоупа; +- проверено, что `tests_backend/test_coordinate_canonicalization.py` требует + `pytest.importorskip("homeassistant")`, то есть локально без HA-харнесса тихо + скипается — подтверждает, что заявленный в AC4 backend-mutation-gate witness + оправдан правилом §2.7 («дорогой гейт, ревьюер не воспроизведёт отрицательный + прогон второй раз»), а не избыточная предосторожность; +- проверено наличие существующих записей `coordinate_canonicalization.py` / + `coordinate-canonicalization.test.mjs` в `scripts/mutation-gate.mjs` (строки + 2276–2430) — механизм добавления нового witness-мутанта в этот файл уже + существует и используется для смежных контрактов, расширение реалистично; +- сверен `docs/CONFIG-COMPATIBILITY.md` (раздел «Custom decor images and export v2 + (#51)») — `image` там не упомянут как часть box-контракта канонизации, что + подтверждает необходимость правки AC7; +- сверена трассируемость: коммит `260af7bf` правит и сам файл ТЗ, и + `docs/specs/README.md` (новая строка со ссылкой на issue и файл) в одном + коммите с верными трейлерами. + +Гейты не гонялись: класса A/B изменений на этом SHA нет (только `docs/specs/**`, +класс C), а полный `typecheck`/`test`/`build` уже зелёный на этом же SHA +(`https://github.com/Matysh/houseplan-card/actions/runs/33732448117`). Продуктового +кода к ревью нет — оценивать нечего гейтами. + +## Проверка трек-классификации + +Автор в S2-analysis назвал критерий §5, который задача не проходит: «одна +поверхность (один диалог, один модуль, один эндпоинт)» — нарушен, потому что +исправление обязано синхронно и доказуемо менять TypeScript-модуль и Python-зеркало. +Это соответствует факту: правка действительно охватывает два независимых рантайма на +разных языках с раздельными тестовыми наборами (`test/` и `tests_backend/`) плюс +`scripts/mutation-gate.mjs`. Классификация «полный трек» обоснована корректно, файл +`docs/specs/NN-*.md` создан, как и требуется вне `small`. + +## Проверка §7.1 + +Все обязательные разделы присутствуют по содержанию (частично объединены заголовками, +что не является нарушением — угроза объёма шаблона не в счёт): сценарий; что человек +увидит до/после; проблема («Подтверждённая причина»); скоуп/не-скоуп; контракт +поведения; UX/touch/i18n/производительность; модель данных и миграция +(«Совместимость и миграция»); AC1–AC8 с методом доказательства у каждого; план +автотестов, включая таблицу защитных свидетелей в формате §2.7 (три столбца: AC · +чем доказан · чем обязан краснеть) — авторское решение оформить её уже на этапе ТЗ +облегчает будущее код-ревью и не требуется, но полезно; риски; откат; +release-артефакты. + +## Проверка AC на однозначность и доказуемость + +AC1–AC8 пронумерованы, у каждого указан способ доказательства +(unit/backend/mutation/review-code/gates), формулировки конкретны (какие именно +поля, какие функции, какой ожидаемый результат). AC4 и AC5 явно требуют прогона +каждого вида через контракт, а не сравнения списков строк — учтён риск №4, +названный автором самим же («тест проверяет список, но не поведение»). AC6 явно +фиксирует границы не-скоупа (формула, пороги, версии, writer inventory, UI, i18n не +меняются) и требует зелёности регрессионных наборов #224/#248/#291 — это защищает +именно тот класс регрессии, которого стоит опасаться при трогании общего модуля. + +## Проверка на непомеченные догадки + +Утверждения о поведении (девять знаков после запятой для `angle`, точка отсечения +lattice-шума, что `latticeCanonicalizationReport` считает near-node как +`canonicalized`, что `CONFIG_SCHEMA` пропускает конфиг через `canonicalize_config_ +geometry`) все сверены с действующим кодом и не являются догадками — это описание +существующего контракта, который расширяется на новый вид, а не изобретается заново. + +Раздел «Принятые предположения» корректно маркирует то, что реально является +техническим решением автора (расположение единого каталога, трактовка `flip_h/ +flip_v`, независимость fixture от рантайма). Единственный пункт на грани +продукт/техника — квалификация коммита как `User-Visible: yes` при отсутствии +видимого визуального кадра. Оценка: это не продуктовый вопрос из списка §7.1 +(«что человек видит или делает», «объём видимого изменения в issue») — объём +изменения уже зафиксирован issue целиком, а `User-Visible` лишь описывает, что +фикс меняет наблюдаемое поведение конфига (частота ревизий/диффов), что описано в +таблице «Что человек увидит до и после». Решение разумное и не создаёт риска даже +если бы было неверным (худший случай — лишняя запись в changelog, не блокирующая +задачу). Эскалации не требует. + +## Находки + +Нет ни High, ни Medium, ни Low. Задача демонстрирует образцовую точность: каждое +фактическое утверждение о коде проверяется прямым чтением исходников, границы +скоупа проведены по реальным точкам вызова, а не по предположению, риски названы +автором заранее и закрыты соответствующими AC. + +## Что проверено и корректно + +- Соответствие `docs/SCOPE.md`: попадает в J6 («Keep the plan true as the home + evolves») — устранение шумовых диффов персистентной геометрии. +- Классификация полного трека обоснована названным критерием §5. +- Все §7.1-разделы присутствуют по содержанию. +- AC1–AC8 однозначны, каждому назначен метод доказательства. +- Защитные AC (AC4) уже содержат таблицу «чем доказан / чем краснеет» с корректным + выбором mutation-gate именно там, где гейт дорогой (backend требует HA). +- Фактические утверждения о коде (номера строк, сигнатуры функций, поведение + `CONFIG_SCHEMA`, состав фикстуры) подтверждены чтением текущего дерева. +- Трассируемость issue ↔ ТЗ ↔ `docs/specs/README.md` в одном коммите с верными + трейлерами (`Issue: #431 · User-Visible: no`, коммит только класса C). +- Продуктовых вопросов владельцу нет, и это верно: контракт box-геометрии уже + зафиксирован #223/#224/#291/#51, добавление `image` — не новое решение, а + возврат к уже принятому контракту. + +## Чего не проверял + +- Гейты `typecheck`/`test`/`build`/`check-docs` не перегонялись самостоятельно: + на этом SHA нет продуктового кода (только `docs/specs/**`), а зелёный Validate + на этом же SHA уже подтверждён ссылкой в задании ревью. +- Реализация (код, тесты, mutation-gate witness) не существует и не проверялась — + предмет этого этапа только ТЗ. +- Не проверялось поведение редактора/рендера изображений в браузере — вне скоупа + задачи и вне этапа spec. + +## Вердикт + +Зелёный. ТЗ выполнимо, каждый AC проверяем и снабжён способом доказательства, +догадок под видом фактов не найдено, трек-классификация обоснована. + +--- + +**Материал раунда:** SHA `260af7bfd200bb40beb2323af2ad5232e2686325`, дерево — +рабочая копия на момент ревью, blob ТЗ — +`docs/specs/431-image-coordinate-canonicalization.md` в этом же коммите. + +--- + + + +## Материал раунда + +- Ветка: `issue/431-image-coordinate-canonicalization`, коммит `260af7bfd200` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. +- Дерево материала: `00fc18d8eda6f680117f99866f8e4063cdbb200c` + ``` + git log --all --format='%H %T' | grep 00fc18d8eda6 + ``` +- ТЗ `docs/specs/431-image-coordinate-canonicalization.md`, блоб `664b75d910be1fcf8ddf2034daec437b2c05430f` + ``` + git log --all --find-object=664b75d910be1fcf8ddf2034daec437b2c05430f -- docs/specs/431-image-coordinate-canonicalization.md + ```