mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 19:58:50 +00:00
docs: review document for #233
Validate / docs (push) Failing after 23s
Validate / provenance (push) Successful in 1m15s
Validate / process-gate (push) Failing after 1m14s
Validate / changes (push) Successful in 1m0s
Validate / hacs (push) Skipped
Validate / hassfest (push) Skipped
Validate / reuse (push) Successful in 47s
Validate / backend (push) Skipped
Validate / frontend (push) Successful in 8m16s
Validate / golden (push) Failing after 13m4s
Validate / performance_smoke (push) Failing after 13m7s
Validate / smoke (push) Failing after 34m13s
Validate / docs (push) Failing after 23s
Validate / provenance (push) Successful in 1m15s
Validate / process-gate (push) Failing after 1m14s
Validate / changes (push) Successful in 1m0s
Validate / hacs (push) Skipped
Validate / hassfest (push) Skipped
Validate / reuse (push) Successful in 47s
Validate / backend (push) Skipped
Validate / frontend (push) Successful in 8m16s
Validate / golden (push) Failing after 13m4s
Validate / performance_smoke (push) Failing after 13m7s
Validate / smoke (push) Failing after 34m13s
Issue: #233 User-Visible: no
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
# CODE-REVIEW — issue #233, заход r2
|
||||
|
||||
- Issue: [#233](https://github.com/Matysh/houseplan-card/issues/233) — «Резайз показывает внутренние размеры, а не осевые»
|
||||
- ТЗ: `docs/specs/233-resize-inner-dimensions.md`, принят зелёным на r2 (`docs/reviews/SPEC-REVIEW-233-r2.md`)
|
||||
- Предыдущий раунд кода: r1, вердикт **жёлтый**, документ `docs/reviews/CODE-REVIEW-233-r1.md` (коммит `bff47f5`),
|
||||
проверенный коммит **`abfaae3`** — feat: measure resize labels between wall faces
|
||||
- Заход: r2 (код), блокирующих циклов израсходовано 1 из 4 (потрачено на r1; зелёный этого раунда цикл не тратит)
|
||||
|
||||
## Скоуп ревью
|
||||
|
||||
Это возврат по находкам M1/M2 предыдущего раунда, не новый заход задачи. Дельта
|
||||
локальна: `git diff abfaae3..HEAD` (= коммит `81f3868`) трогает ровно три файла —
|
||||
`test/wall-thickness.test.mjs`, `scripts/mutation-gate.mjs` и сам документ r1-ревью.
|
||||
Продуктовый код (`src/wall-thickness.ts`, `src/houseplan-card.ts`) не тронут —
|
||||
это подтверждено не только диффом, но и байт-в-байт совпадением бандла (см.
|
||||
«Как проверялось», п.2). Никаких признаков «ребейз на ушедший вперёд dev»,
|
||||
смены контракта поведения или новой подсистемы нет — `origin/dev...HEAD`
|
||||
идентичен тому, что видел r1, плюс этот один коммит. Поэтому разбор сокращён
|
||||
до дельты и наследования, а не полного прогона AC1–AC9.
|
||||
|
||||
## Закрытие раунда r1
|
||||
|
||||
| Находка r1 | Чем закрыта | Где это видно |
|
||||
|---|---|---|
|
||||
| **M1** — тест AC6b (`test/wall-thickness.test.mjs:1533-1552` на `abfaae3`) не создавал настоящий сплит-разрыв: `setWallThickness` писал толщину на **весь** осевой отрезок ребра, поэтому `thicknessCmAt` по целому ребру совпадал с профилем, и тест не отличал бы исправленный код от регресса к H2 | Тест переписан на реальный сплит: `setWallThickness([], [0,0], [0.6,0], 20, pitch)` при ребре комнаты `[0,0]–[1,0]` | `test/wall-thickness.test.mjs:1533-1571` (коммит `81f3868`). Явные assert'ы: `thicknessCmAt(split, [0,0], [1,0], pitch) === 0` (это и есть H2), `thicknessCmAt(split, [0,0], [0.6,0], pitch) === 20`, `ownEdgeOffsets(...)[0] === halfDepth` (не 0), плюс `assert.notEqual(viaProfile[0], thicknessCmAt(...))` — тест теперь явно фиксирует расхождение источников, а не совпадение |
|
||||
| **M2** — `scripts/mutation-gate.mjs` (диф `abfaae3`) содержал три мутанта из четырёх, названных в принятом §11 ТЗ; `inner-span-ignores-neighbour-thickness` (страж AC2) отсутствовал | Добавлена запись мутанта, патчащая `cutAt` в `innerEdgeSpan` (`const o = Math.max(0, Number(offsets[edge]) \|\| 0);` → `const o = own;`), привязанная к тесту `innerEdgeSpan measures between wall faces` | `scripts/mutation-gate.mjs:111-125` (коммит `81f3868`). Независимо прогнан: `node scripts/mutation-gate.mjs --id=inner-span-ignores-neighbour-thickness` → «поймано 1 из 1» |
|
||||
|
||||
Обе находки были про доказательную базу, не про поведение продукта (r1 это
|
||||
установил независимым исполнением сценария сплит-ребра вне репозитория) — и
|
||||
продуктовый код в этом раунде действительно не менялся, значит поведение,
|
||||
подтверждённое в r1, не могло сломаться этой правкой.
|
||||
|
||||
## Как проверялось
|
||||
|
||||
1. Построчно сверен диф `81f3868` с рецептами правок из документа r1 (см.
|
||||
таблицу выше) — обе правки текстуально соответствуют тому, что r1 просил
|
||||
исправить, а не что-то похожее.
|
||||
2. Проверено, что продуктовый код не менялся: `git diff abfaae3..HEAD -- src/`
|
||||
пуст; после `npm run build` все три копии бандла дают тот же md5, что
|
||||
заявляли и автор, и r1-ревью — `5ffd65073d92c4845aecb1a4145f0948`
|
||||
(`dist/houseplan-card.js`, `demo/srv/assets/houseplan-card.js`,
|
||||
`custom_components/houseplan/frontend/houseplan-card.js`). Это делает
|
||||
независимую повторную проверку поведения продукта (AC1–AC9) избыточной —
|
||||
она физически не могла измениться.
|
||||
3. Гейты прогнаны заново на дереве `81f3868` (не унаследованы из r1, так как
|
||||
код тестов/гейта изменился):
|
||||
- `npx tsc --noEmit` — чисто;
|
||||
- `npx tsc -p tsconfig.test.json` — чисто (это конфиг, которым фактически
|
||||
компилируются тесты и мутационный гейд);
|
||||
- `npm test` — **1026/1026**, включая переписанный тест M1;
|
||||
- `node scripts/mutation-gate.mjs --check` — **88/88 `ok`**, exit 0
|
||||
(было 87 на r1, теперь на один больше — учтён новый мутант M2);
|
||||
- адресный прогон всех четырёх мутантов задачи по одному, чтобы не
|
||||
доверять агрегату:
|
||||
- `--id=inner-span-ignores-neighbour-thickness` → поймано 1 из 1 (новый, M2);
|
||||
- `--id=inner-span-reads-whole-edge-thickness` → поймано 1 из 1
|
||||
(переписанный тест M1 всё ещё ловит его, но теперь по правильной
|
||||
причине — падает конкретно на сплит-ребре, а не потому что путь через
|
||||
профиль не исполнился);
|
||||
- `--id=inner-span-shortens-a-passage` → поймано 1 из 1;
|
||||
- `--id=resize-labels-show-centreline` → поймано 1 из 1.
|
||||
4. Прочитан патч M2 в контексте реального `src/wall-thickness.ts:898`
|
||||
(`cutAt`, внутри `innerEdgeSpan`) — строка `find` мутанта текстуально
|
||||
совпадает с текущим кодом, мутация подставляет собственную толщину `own`
|
||||
вместо толщины соседнего ребра `offsets[edge]`, что и есть штраф AC2
|
||||
(«сокращение считается только по своей толщине, соседи игнорируются»).
|
||||
Патч не «на что-то похожее», а именно на тот код, который правка защищает.
|
||||
5. Проверено, что дифф `81f3868` не трогает `docs/CHANGELOG*.md` и
|
||||
`docs/USER-GUIDE*.md` — ожидаемо, коммит несёт `Issue: #233`,
|
||||
`User-Visible: no` (тестовый коммит класса B), changelog не требуется.
|
||||
|
||||
## Находки
|
||||
|
||||
Нет новых находок. Обе находки r1 закрыты доказательно (см. таблицу выше и
|
||||
«Как проверялось», пп. 1, 3, 4), High: 0, Medium: 0.
|
||||
|
||||
Отдельно отмечаю: в предпоследнем комментарии автор сообщил про красный job
|
||||
`docs` в `validate.yml` (несвежий `sourceFingerprint` в
|
||||
`docs/images/screenshots.json` из-за слияния #234 без пересъёмки) и завёл под
|
||||
это отдельный issue. Это не находка этого ревью — дефект не в ветке #233, не
|
||||
в скоупе задачи, и уже обслуживается отдельно самим автором, значит нового
|
||||
issue от ревьюера не требуется (правило дублирования наблюдений, §12: не
|
||||
заводить второй issue на то же наблюдение).
|
||||
|
||||
## Что проверено и корректно
|
||||
|
||||
- **M1, M2** — закрыты, доказано исполнением, не только чтением коммит-сообщения
|
||||
(см. «Как проверялось»).
|
||||
- **Продуктовое поведение (AC1–AC9)** — не могло измениться этой правкой:
|
||||
бандл байт-в-байт идентичен версии, которую r1 уже проверил чтением,
|
||||
исполнением гейтов и независимым ручным сценарием сплит-толщины (H2).
|
||||
- **Трейлеры** `81f3868`: `Issue: #233`, `User-Visible: no` — корректны для
|
||||
тест-only правки; changelog не трогается, как и должно быть при
|
||||
`User-Visible: no`.
|
||||
- **Формальный контракт §11 ТЗ** (четыре мутационных стража) — теперь
|
||||
выполнен полностью: все четыре присутствуют в `scripts/mutation-gate.mjs`
|
||||
и каждый independently подтверждён «1 из 1».
|
||||
|
||||
## Унаследовано из r1
|
||||
|
||||
Без повторной проверки в этом раунде принято из `docs/reviews/CODE-REVIEW-233-r1.md`
|
||||
(документ на коммите `bff47f5`, проверенный коммит продукта `abfaae3`):
|
||||
|
||||
- **AC1–AC5** — численно сверенные длины (285/385 см на 300×400 при стенах 15 см),
|
||||
диагональные рёбра, случай «стены толще комнаты» → 0.
|
||||
- **AC6a (H1, правило нуля для проёмов)** — `if (!(own > 0)) return centre;`
|
||||
идёт первым в `innerEdgeSpan`, перепроверено математически на кейсе H1.
|
||||
- **AC6b (H2, источник толщин)** — механизм `ownEdgeOffsets` → `roomWallProfile`
|
||||
→ `atomicPolyForRoom` подтверждён независимым исполнением сценария сплит-ребра
|
||||
вне репозитория (не тем тестом, который чинит M1, — отдельным ручным прогоном
|
||||
r1). В этом раунде довеском стало то, что теперь и сам юнит-тест воспроизводит
|
||||
этот же сценарий (закрытие M1 выше).
|
||||
- **AC7** — три подписи `_rszEdgeLabels` и габарит `_rszScaleLabels` внутренние;
|
||||
подтверждено прогоном `demo/smoke_resize_inner_dimensions.mjs` (OK) на дереве
|
||||
`abfaae3`. Не перепрогонялось в r2, так как бандл (см. п.2 выше) идентичен —
|
||||
прогон на неизменившемся артефакте не может дать другой результат.
|
||||
- **AC8** — площадь не менялась (`innerContourForRoom` + `floorMinusBodies`),
|
||||
подтверждено тем же смоком (`dragAreaStillInner`, `frameAreaAgreesWithSize`).
|
||||
- **AC9** — трейлеры и changelog для продуктового коммита `abfaae3` (`Issue: #233`,
|
||||
`User-Visible: yes`, `docs/CHANGELOG.md`/`.ru.md` и `docs/USER-GUIDE*.md`
|
||||
правлены в нём же).
|
||||
- **i18n** — диф `abfaae3` не трогает `src/i18n/*.json`.
|
||||
- **Golden** — вне риска по построению (`_rszLive` живёт только на время жеста
|
||||
ресайза, обнуляется на `pointerup`); проверено r1 чтением, не исполнением
|
||||
`golden:verify`.
|
||||
- **Регрессия толщины стен** — `smoke_draw_wall_thickness.mjs`,
|
||||
`smoke_wall_thickness_transition.mjs` зелёные на дереве `abfaae3`.
|
||||
- **Touch** — диф не трогает pointer-пути, `docs/TOUCH-SUPPORT.md` не затронут.
|
||||
|
||||
Все эти пункты наследуются с уверенностью, потому что предмет наследования —
|
||||
поведение бандла, а бандл в r2 не пересобран из другого исходника: он тот же
|
||||
файл, что и на момент r1-вывода (совпадение md5 подтверждено заново в этом
|
||||
раунде, не взято на веру).
|
||||
|
||||
## Чего не проверял и почему
|
||||
|
||||
- **`demo/smoke_resize_inner_dimensions.mjs` и регрессионные смоки повторно** —
|
||||
не перепрогонял: продуктовый код не менялся (бандл идентичен), результат
|
||||
прогона на неизменившемся артефакте не может отличаться от того, что уже
|
||||
зафиксировал r1. Перепрогон был бы тратой минут без шанса найти что-то новое.
|
||||
- **`npm run golden:verify`** — не гонял, по той же причине плюс аргумент r1
|
||||
(оверлей `_rszLive` вне активного жеста не рендерится, статический golden
|
||||
его не видит); дифф этого раунда вообще не в `src/**`.
|
||||
- **`python -m pytest tests_backend`** — не гонял, диф не трогает
|
||||
`custom_components/**/*.py`.
|
||||
- **performance-профили** — не гонял, не названы в AC, диф не в горячих путях
|
||||
рендера и вообще не в продуктовом коде.
|
||||
- **`demo/smoke_*.mjs` вне названных в AC/§12** — не прогонял весь набор из
|
||||
127: дифф ограничен тестовым файлом и мутационным гейтом, у которых нет
|
||||
браузерной поверхности вовсе.
|
||||
|
||||
## Вердикт
|
||||
|
||||
Обе находки r1 (M1, M2) закрыты именно так, как требовал документ r1: тест
|
||||
теперь строит настоящий сплит-разрыв и различает исправленный код от
|
||||
регресса к H2, мутационный гейт получил четвёртый страж контракта §11 и
|
||||
независимо подтверждён «1 из 1» по каждому из четырёх мутантов задачи.
|
||||
Продуктовый код не менялся — бандл байт-в-байт идентичен версии, которую r1
|
||||
уже проверил чтением, гейтами и ручным сценарием, так что AC1–AC9 наследуются
|
||||
без риска регрессии из этой правки. Новых находок нет.
|
||||
|
||||
**Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0**
|
||||
Reference in New Issue
Block a user