mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-02 21:01:21 +00:00
Validate / docs (push) Failing after 24s
Validate / changes (push) Successful in 1m10s
Validate / process-gate (push) Failing after 1m14s
Validate / provenance (push) Successful in 1m16s
Validate / reuse (push) Successful in 52s
Validate / hassfest (push) Failing after 33s
Validate / hacs (push) Failing after 47s
Validate / frontend (push) Successful in 7m12s
Validate / backend (push) Failing after 16m13s
Validate / golden (push) Failing after 11m40s
Validate / performance_smoke (push) Failing after 14m46s
Validate / smoke (push) Failing after 32m43s
Issue: #229 User-Visible: no
163 lines
14 KiB
Markdown
163 lines
14 KiB
Markdown
# Код-ревью #229 · заход r3
|
||
|
||
Вердикт: **зелёный** · заход r3 · блокирующих циклов 2/4 · High: 0 · Medium: 0
|
||
|
||
## Скоуп разбора
|
||
|
||
Разбор — по дельте, правило §2.9/§2.10. Предыдущий раунд (r2) получен на SHA
|
||
`ed13b4a` (документ `docs/reviews/CODE-REVIEW-229-r2.md`; SHA в самом тексте
|
||
вердикта не назван — восстановлен по `git log` и по фразе автора «Коммит
|
||
`ed13b4a`» в хендоффе, предшествующем вердикту). Правка по r2 — один коммит
|
||
`fab0c38` («refactor: one function owns the junction geometry of a space»).
|
||
|
||
Дельта: `git diff ed13b4a..HEAD` — 11 файлов, из них содержательные
|
||
`src/wall-merge.ts` (+33/-0), `src/houseplan-card.ts` (-16 строк локально,
|
||
вызов геометрии заменён на одну строчку), `src/plan-optimizer.ts` (аналогично
|
||
-13), `scripts/mutation-gate.mjs` (2 мутанта перенацелены), `test/wall-merge.test.mjs`
|
||
(+3 юнита). Остальное — `docs/images/screenshots.json` (только `sourceFingerprint`,
|
||
автоматически из-за изменившегося бандла; `imageSha256` не менялся, кадры те же)
|
||
и коммит с документом ревью r2 (`fe2fcef`, не код).
|
||
|
||
Дельта локальна: одна находка (Medium-1 r2), один модуль, ни новая
|
||
подсистема, ни смена контракта поведения не затронуты — `User-Visible: no`
|
||
в коммите верен, продуктовое поведение не менялось ни на шаг, только
|
||
внутренняя организация кода и тестов. Полный повторный разбор не требуется;
|
||
объём проверки — сама правка плюс всё, до чего она дотягивается (оба
|
||
вызывающих места и мутационное покрытие обоих путей).
|
||
|
||
## Находка r2 и её закрытие
|
||
|
||
**Medium-1 (r2, в скоупе, возвращена в задачу):** дефект High-1 (двойное
|
||
масштабирование `roomPolygons`, из-за которого T-стык партиции к середине
|
||
комнатной стены не находился) был идентичен в двух местах —
|
||
`_mergeSpacePartitions` (карта) и `optimizePlans` («Оптимизировать планы») —
|
||
потому что каждый вызывающий строил геометрию примыканий самостоятельно.
|
||
Регрессионное покрытие защищало только путь оптимизатора; путь карты, который
|
||
r1 воспроизвёл вторым способом («в браузере через реальные клики»), не имел ни
|
||
юнита, ни мутанта.
|
||
|
||
| находка | чем закрыта | где это видно |
|
||
|---|---|---|
|
||
| Medium-1: однобокое покрытие двойного масштабирования room-полигонов, защищён только `plan-optimizer.ts` | Геометрия примыканий (комнаты, колонны, концы черновиков) вынесена в одну функцию `spaceMergeGeometry(space, { excludeDraftId })`; оба вызывающих теперь однострочный вызов — масштаб можно ошибиться ровно в одном месте | `src/wall-merge.ts:278-295` (новая функция); `src/houseplan-card.ts:6551-6557` и `src/plan-optimizer.ts:503-506` (оба вызывающих — по одной строке, без собственного построения геометрии) |
|
||
| — регрессия для обоих путей | Мутанты `partition-merge-rescales-rooms` и `chain-merge-sees-own-draft` перенацелены с `plan-optimizer.test.mjs`/смока на общий `test/wall-merge.test.mjs`, патчат теперь сам `spaceMergeGeometry` | `scripts/mutation-gate.mjs:721-741`; юниты `test/wall-merge.test.mjs:214-262` |
|
||
|
||
Закрытие проверено не по заявлению автора, а исполнением (см. «Как
|
||
проверялось»): оба мутанта, применённые к текущему коду, красят гвард, а не
|
||
только исходный.
|
||
|
||
## Как проверялось
|
||
|
||
Материал: `git diff ed13b4a..HEAD` и `git diff origin/dev...HEAD` (полный
|
||
диапазон issue). Ручного тестирования в цикле нет — далее только то, что
|
||
исполнено или разобрано по коду с явной пометкой.
|
||
|
||
**Прочитано и разобрано по коду:**
|
||
- `src/wall-merge.ts:278-295` (`spaceMergeGeometry`) — сопоставлено построчно
|
||
со старыми телами обоих вызывающих (см. `git diff` выше): семантика
|
||
идентична, включая то, что `plan-optimizer.ts` не передаёт
|
||
`excludeDraftId` — как и раньше, там исключения черновика не было и не
|
||
нужно (оптимизатор не выполняется во время активного рисования).
|
||
- Проверено отсутствие циклического импорта: `wall-merge.ts` теперь импортирует
|
||
`roomPoly` из `./logic`; `logic.ts` не импортирует `wall-merge.ts` (grep — 0
|
||
совпадений). Компилируется без ошибок (см. ниже) — само по себе уже
|
||
доказательство при бандлинге через rollup/tsc.
|
||
|
||
**Проверено исполнением:**
|
||
- `npx tsc --noEmit` — чисто.
|
||
- `npm test` — 1007/1007, без изменений к количеству от заявленного автором.
|
||
- `npm run build` + сверка трёх копий бандла (`dist/houseplan-card.js`,
|
||
`custom_components/houseplan/frontend/houseplan-card.js`,
|
||
`demo/srv/assets/houseplan-card.js`) — идентичны побайтово
|
||
(`sha256 9dd1ec1a…`), `git status` после сборки чист — закоммиченный бандл
|
||
соответствует исходникам.
|
||
- `node scripts/check-docs.mjs` — passed (7 файлов, 10 внешних ссылок);
|
||
подтверждает, что изменение `sourceFingerprint` в `screenshots.json`
|
||
легитимно и не требует новых кадров (`imageSha256` не менялся).
|
||
- `node scripts/process-gate.mjs` — гейт пройден, предупреждений 0.
|
||
- `node demo/smoke_wall_chain_merge.mjs` — OK, все 9 проверок, включая
|
||
`chainMergesIntoTheWallItTouches`, `draftIsGone` (путь §8.6 через реальные
|
||
клики).
|
||
- `node demo/smoke_wall_junctions.mjs` — OK, все 12 проверок (соседняя
|
||
поверхность — T-стыки и геометрия примыканий).
|
||
- `node demo/smoke_optimize_coordinate_canonicalization.mjs` — OK, все 13
|
||
проверок (путь «Оптимизировать планы»).
|
||
- **Дисциплина «тест умеет падать» — оба перенацеленных мутанта проверены
|
||
вручную** (штатный харнесс `mutation-gate.mjs` непригоден для юнит-гвардов
|
||
до #235, независимо от этой задачи):
|
||
- `partition-merge-rescales-rooms` (патч возвращает лишнее деление на 1000
|
||
внутри `spaceMergeGeometry`): наложен на `src/wall-merge.ts`, пересобран
|
||
`test-build` (`tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs`),
|
||
`node --test --test-name-pattern="issue 229" test/wall-merge.test.mjs` дал
|
||
**2 падения** (`space geometry keeps rooms in the coordinates…` и `a
|
||
junction on a room side survives…`, `1 !== 0`). Патч снят, повторный
|
||
прогон — 19/19 зелёных.
|
||
- `chain-merge-sees-own-draft` (патч заменяет исключение черновика на
|
||
`void exclude`): тем же способом — **1 падение** (`the chain being
|
||
finished is not its own junction`). Патч снят, 19/19 зелёных.
|
||
- После снятия обоих патчей полный `npm test` — 1007/1007, `git status`
|
||
чист (никаких временных правок не осталось).
|
||
|
||
**Не прогонялось и почему:** полный набор из 127 смоков, `golden:verify`,
|
||
`pytest tests_backend`, performance-профили — дельта этого раунда не задевает
|
||
рендер, backend или перф-пути; полные наборы — предрелизный гейт (§8), не гейт
|
||
ревью соразмерного изменения. Задетые поверхности (карта, оптимизатор,
|
||
T-стыки, слияние цепочки) покрыты смоками выше и юнитами.
|
||
|
||
## Унаследовано из r1/r2
|
||
|
||
Без повторной проверки в этом раунде, дельта не касается их доказательной
|
||
поверхности:
|
||
|
||
- **AC1, AC3-AC7, AC9** — наследованы уже в r2 из документа
|
||
`docs/reviews/CODE-REVIEW-229-r1.md` (SHA `50a00e4`); дельта r2→r3 не
|
||
затрагивает пересчёт `host.t`, материализацию `x/y/angle`, допуски,
|
||
канонизацию направления, транзитивность/порядконезависимость слияния — их
|
||
код не менялся.
|
||
- **AC8 (§8.6, слияние ограничено компонентой связности новой цепочки)** —
|
||
проверено в r1/r2 чтением и смоком; в r3 логика `seedIds` в
|
||
`mergeCollinearPartitions` не менялась, изменился только источник геометрии
|
||
примыканий, который `seedIds` не касается. Перепроверено попутно смоком
|
||
`smoke_wall_chain_merge.mjs` (`chainMergesIntoTheWallItTouches`) в этом
|
||
раунде — совпадает.
|
||
- **AC2 (T-стык партиции к середине комнатной стены)** — критерий из
|
||
документа `docs/reviews/CODE-REVIEW-229-r2.md` (SHA `ed13b4a`) не наследован
|
||
вслепую: это и есть предмет дельты r3, перепроверено заново в этом раунде
|
||
(юнит «a junction on a room side survives, through the shared geometry»,
|
||
исполнен, зелёный; мутант, умеет падать — см. выше).
|
||
|
||
## Что проверено и корректно
|
||
|
||
- `spaceMergeGeometry` — единственный источник геометрии примыканий для обоих
|
||
путей; масштаб координат общий с партициями (без лишнего деления),
|
||
исключение активного черновика — опционально и по умолчанию отключено
|
||
(важно для пути оптимизатора, где активного черновика не бывает).
|
||
- Новые юниты (`test/wall-merge.test.mjs:214-262`) покрывают три вещи по
|
||
отдельности: масштаб полигонов (включая `x/y/w/h`-комнату и комнату без
|
||
геометрии), исключение черновика (обе ветки), сам T-стык — и делают это на
|
||
уровне модуля, не дублируя мутационное покрытие смоком.
|
||
- Трейлеры коммита `fab0c38`: `Issue: #229`, `User-Visible: no` — верно,
|
||
поведение продукта не меняется, правка рефакторит внутреннюю организацию;
|
||
changelog не требуется и не тронут.
|
||
- Импорт `roomPoly` из `./logic` в `wall-merge.ts` не создаёт цикла зависимостей.
|
||
|
||
## Чего не проверял
|
||
|
||
- Полный набор смоков (127), `npm run golden:verify`, `python -m pytest
|
||
tests_backend`, performance-профили — не задеты дельтой этого раунда (см.
|
||
«Как проверялось»).
|
||
- Сценарий «комната через реальные клики» в смоке — автор honestly сообщил,
|
||
что не взлетел (`_offerWallFaces` не даёт цепочке завершиться штатно) и
|
||
оставил покрытие на юнитах общего модуля. Не блокирует: AC2 доказан юнитом
|
||
на уровне `mergeCollinearPartitions`/`spaceMergeGeometry`, что достаточно —
|
||
геометрия примыканий и механика предложения стен (`_offerWallFaces`) —
|
||
разные слои, и дефект r1/r2 жил именно в геометрии. Если понадобится
|
||
клик-путь через реальную комнату — отдельная работа поверх
|
||
`_offerWallFaces`, не предмет этой задачи.
|
||
|
||
## Итог
|
||
|
||
Обе High из r1 и единственная Medium из r2 закрыты по существу и
|
||
перепроверены исполнением. Дефект устранён на уровне причины (общая функция
|
||
геометрии), а не симптома — оба мутанта краснеют для обоих путей из одного
|
||
патча. Задача готова к выходу из цикла ревью.
|