Files
houseplan-card/docs/reviews/SPEC-REVIEW-431-r1.md
T
Codex d4dd027b0a build: prepare v1.71.0-beta.2 candidate
Issue: #426
Issue: #427
Issue: #428
Issue: #431
Issue: #432
Issue: #434
User-Visible: no
2026-09-03 15:23:40 +03:00

181 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` в этом же коммите.
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `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
```