mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-04 05:41:34 +00:00
Issue: #426 Issue: #427 Issue: #428 Issue: #431 Issue: #432 Issue: #434 User-Visible: no
181 lines
15 KiB
Markdown
181 lines
15 KiB
Markdown
# 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
|
||
```
|