docs: review document for #329
Проверка (CI) / Процесс: process.yml идентичен в main и dev (push) Successful in 2m48s
Проверка (CI) / Провенанс коммитов: трейлеры и эталоны (push) Successful in 2m31s
Проверка (CI) / Процессный гейт: диапазон, трейлеры, статусы issue (push) Successful in 2m30s
Проверка (CI) / Классификация изменённых файлов (push) Successful in 36s
Проверка (CI) / HACS: валидация репозитория (push) Skipped
Проверка (CI) / Hassfest: манифест интеграции (push) Skipped
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Skipped
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 38s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Skipped
Проверка (CI) / Документация: гайды, ченджлоги, скриншот-индекс (push) Failing after 47s

Issue: #329
User-Visible: no
This commit is contained in:
claude[bot]
2026-08-27 21:49:59 +00:00
parent 273b0d5ecb
commit 2c4b505f1a
+157
View File
@@ -0,0 +1,157 @@
# CODE-REVIEW-329-r3
Этап: code · заход r3 · блокирующих циклов израсходовано 2 из 4
## Скоуп раунда
Предыдущий вердикт (code r2, `226`-й комментарий issue) — красный,
единственная находка **r2-H1**: мутант `junction-limit-backend-raw-baseline`
в `scripts/mutation-gate.mjs` был добавлен с `guard: 'python3 -m pytest
tests_backend/test_junction_limits.py -q'`, в обход конвенции ВСЕХ прочих
бэкенд-мутантов реестра (`node scripts/backend-test-guard.mjs <pattern>
<file>`), из-за чего `test/mutation-gate.test.mjs` красился на CI.
Вердикт r2 получен на SHA `26c6e870` (Matysh: «Актуальный HEAD ветки для
ревью — `26c6e870`», непосредственно перед вердиктом). Автор закрыл
находку коммитом `273b0d5e`, текущий HEAD.
Дельта этого раунда:
```
git diff 26c6e870..HEAD --stat (без docs/reviews/*)
scripts/mutation-gate.mjs | 4 ++--
test/mutation-gate.test.mjs | 6 +-----
2 files changed, 3 insertions(+), 7 deletions(-)
```
Дельта не затрагивает `src/**`, бэкенд-продакшен-код, геометрию, документацию
пользователя — только реестр мутантов и его контрактный тест. Это ровно то,
что запрошено находкой r2-H1, без побочных правок. Разбор по дельте признан
достаточным: изменение локально, не является ребейзом, не меняет контракт
поведения продукта и по объёму несопоставимо мало относительно исходной
задачи (две строки правки guard + возврат теста к исходному виду).
## Что проверено (дельта)
1. **Форма guard соответствует конвенции.** Новый guard —
`node scripts/backend-test-guard.mjs
test_legacy_baseline_is_judged_after_the_same_migration
tests_backend/test_junction_limits.py` — совпадает по форме со всеми
остальными записями реестра, использующими бэкенд-хелпер (проверено
`grep -n "backend-test-guard" scripts/mutation-gate.mjs` — 16 вхождений,
новое неотличимо от прочих).
2. **Контракт теста возвращён к исходному виду.**
`test/mutation-gate.test.mjs` снова требует, чтобы guard называл `.mjs`
(убрана временная ветка `.py`, убран комментарий-объяснение, который её
оправдывал). `grep` подтвердил: других мутантов, называющих `.py`
напрямую (в обход хелпера), в реестре нет — правка не откроет дыру для
будущих аналогичных случаев.
3. **Мутант по-прежнему ловит регрессию.** Прогнан НЕ ТОЛЬКО `--check`
(проверяет только уникальность якоря патча), а полный цикл конкретного
мутанта:
`node scripts/mutation-gate.mjs --id=junction-limit-backend-raw-baseline`
→
```
ok чистый прогон: node scripts/backend-test-guard.mjs test_legacy_baseline_is_judged_after_the_same_migration tests_backend/test_junction_limits.py
ok junction-limit-backend-raw-baseline: тест покраснел, как обязан
поймано 1 из 1
```
То есть подтверждено обеими половинами: код без мутации проходит целевой
тест, а с применённым патчем (`migrated = config` вместо прогона через
`commit_wall_segment_model`) целевой тест красится. Это и есть доказательство
«тест умеет падать» для данной находки.
4. **pytest напрямую.** `python3 -m pytest tests_backend/test_junction_limits.py -q`
→ `8 passed`. (pytest в песочнице ревью отсутствовал изначально, установлен
`pip3 install --user pytest` — тот же шаг, что r2 констатировал как разовую
особенность окружения, не продукта.)
5. **`npm test`** → `# tests 1391 / # pass 1390 / # fail 0 / # skipped 1`,
совпадает с итогом, который автор указал в коммите `273b0d5e`.
6. **`npx tsc --noEmit`** — чисто (дельта не трогает `.ts`, но прогнан по
правилу «всегда»).
7. **`npm run build`** — собрался, `dist/houseplan-card.js` создан.
Сверка бандла: `cmp dist/houseplan-card.js
custom_components/houseplan/frontend/houseplan-card.js` — совпадает
побайтово. Третья копия, `demo/srv/assets/houseplan-card.js`, в дереве
отсутствует (она untracked рабочая копия demo-стенда, `bundle-sync.mjs`
создаёт её по требованию) — отсутствие ожидаемо и не связано с этой
правкой, дельта фронтенд не трогает.
8. **`node scripts/check-docs.mjs`** → `Documentation checks passed (7 files,
10 external links)`. Формально необязателен (дельта не в `src/**`), прогнан
по инерции — зелёный.
9. **`node scripts/smoke-select.mjs --base 26c6e870 --head HEAD`** →
«Исполняемого frontend-диффа нет (`src/**/*.ts` не тронут). Browser-smoke
этим диффом не выбираются — выбирать нечего». Полный прогон смоков не
делал — инструмент прямо говорит, что выбирать нечего, а не «неопределённость».
## Закрытие раунда r2
| Находка | Чем закрыта | Где это видно |
|---|---|---|
| r2-H1: guard бэкенд-мутанта в обход конвенции `.mjs`-хелпера, контрактный тест красный на CI | `scripts/mutation-gate.mjs`: guard мутанта `junction-limit-backend-raw-baseline` переписан на `node scripts/backend-test-guard.mjs test_legacy_baseline_is_judged_after_the_same_migration tests_backend/test_junction_limits.py`; `test/mutation-gate.test.mjs`: контракт `every guard command points at a file that exists` возвращён к проверке только `.mjs`, временная ветка для `.py` и оправдывающий её комментарий убраны | Коммит `273b0d5e`; `npm test` 1390/0 (было 1389 passed/1 failed на `0824e510`); точечный прогон `node scripts/mutation-gate.mjs --id=junction-limit-backend-raw-baseline` — «поймано 1 из 1» |
## Унаследовано из r2 (и, транзитивно, из r1)
Без повторной проверки исполнением приняты — дельта r3 их не касается кодом,
которого они доказывают:
- **H1 (бэкенд мигрирует обе стороны перед сравнением)** — доказано в r1,
подтверждено закрытым в r2 тестом `test_legacy_baseline_is_judged_after_the_same_migration`
и мутантом. Документ: `docs/reviews/CODE-REVIEW-329-r2.md`, раздел
«Закрытие раунда r1», SHA `26c6e870`.
- **M1 (мёртвый код `apexCaps`/`clipPolygonOutsideCap`/`degenerateApexCaps`
удалён)** — `docs/reviews/CODE-REVIEW-329-r2.md`, SHA `26c6e870`.
- **M2/M3 (дубль раздела USER-GUIDE устранён, канал Resize описан верно)** —
там же, SHA `26c6e870`.
- **M4 (AC10, Optimize не создаёт новых нарушений, доказан двумя юнитами)** —
там же, SHA `26c6e870`.
- **Остальные AC (П1–П5 юниты и границы, §4 честная вершина + golden, AC5a/b,
AC7a через реальный pointer-жест, AC7b, паритет AC9, скоуп применения AC8)** —
впервые проверены и признаны корректными в `docs/reviews/CODE-REVIEW-329-r1.md`,
подтверждены неизменными в r2 (дельта r1→r2 их не трогала за вычетом
перечисленных выше M1–M4 и H1); дельта r2→r3 тем более их не трогает
(единственные изменённые файлы — `scripts/mutation-gate.mjs` и
`test/mutation-gate.test.mjs`, не пересекающиеся с производственным кодом
junction-limits, рендером или бэкендом). Документ: `docs/reviews/CODE-REVIEW-329-r1.md`,
SHA `e1df015d`; golden/invariants/мутанты для этих AC — из отчёта r1
(«что прогнано»).
- **Полный HA-harness backend не прогоняется** — унаследованный пробел
окружения, констатирован ещё в r1 (недоступны `homeassistant`/`voluptuous`),
подтверждён в r2, в r3 не переоценивался — дельта его не касается.
## Чего не проверял в этом раунде и почему
- **`npm run golden:verify`** — не прогонял. Дельта не трогает рендер,
геометрию, стили, слои; полная матрица (~80 сцен) уже прогнана и зелёная
в r2 на коде, который в r3 не менялся.
- **`npm run invariants`** — не прогонял. Дельта не трогает рёбра комнат,
записи толщины, `layout`, `marker.space`, `open_spans` — инварианты модели
здесь неприменимы.
- **Браузерные смоки** — не прогонял ни одного. `smoke-select.mjs` для
диапазона `26c6e870..HEAD` прямо сообщает «выбирать нечего»: единственные
изменённые файлы — `scripts/mutation-gate.mjs` и `test/mutation-gate.test.mjs`,
оба вне `src/**`, ни один смок такой диапазон не оценивает даже как слабую
связь.
- **`python -m pytest tests_backend -q` (полный набор)** — прогнал только
файл `test_junction_limits.py`, целевой для находки; полный бэкенд-набор
не запускал, так как дельта не трогает бэкенд-продакшен-код (только тест
и реестр мутантов на фронтенде/CI), а `test_junction_limits.py` — тот файл,
контракт которого проверяет закрытие r2-H1.
- **Performance-профили** — не прогонял, в AC не названы и дельта их не
задевает.
- **Полный `.github/workflows/mutation-gate.yml` (пересборка бандла на
каждого мутанта)** — не прогонял; это предрелизный гейт (PROCESS.md §8),
несоразмерен точечной правке одной записи реестра. Точечный прогон именно
этого мутанта сделан отдельно (см. выше) и достаточен как доказательство.
## Вывод
Единственная находка r2 (High) закрыта по существу и подтверждена
исполнением: guard мутанта следует конвенции, контракт реестра не ослаблен,
мутант по-прежнему доказанно ловит регрессию H1 (1/1), `npm test` и
`pytest tests_backend/test_junction_limits.py` зелёные. Новых находок delta
не создаёт — правка изолирована в тестовой инфраструктуре, не пересекается
с продакшен-кодом или пользовательским поведением. Trailer коммита
(`Issue: #329`, `User-Visible: no`) корректен для чисто тестового изменения;
changelog не тронут — верно, правок не требовалось.
Вердикт: зелёный.