docs: review document for #520
Проверка (CI) / Предполётные проверки: документация, провенанс, процесс (push) Successful in 2m16s
Проверка (CI) / Классификация изменённых файлов (push) Successful in 1m55s
Проверка (CI) / HACS: валидация репозитория (push) Skipped
Проверка (CI) / Hassfest: манифест интеграции (push) Skipped
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Skipped
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 52s
Проверка (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

Issue: #520
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-10 18:26:40 +00:00
parent a325294d7a
commit b2346eaac3
+230
View File
@@ -0,0 +1,230 @@
# CODE-REVIEW-520-r3
Issue: #520 · Этап: code · Заход: r3 · Материал: `a325294d7a9d8ef4ecfeab2ed3e248318a650ab5`
Вердикт: **зелёный** · High: 0 · Medium: 0
## Скоуп
Третий заход код-ревью после жёлтого r2 (`docs/reviews/CODE-REVIEW-520-r2.md`,
единственная находка Medium-1: `node scripts/check-docs.mjs` красный на материале
ревью — диф трогает `src/houseplan-card.ts` и `src/config-adoption.ts`, что
инвалидирует отпечаток скриншотов документации, а ветка не привезла свой коммит
обновления).
Дельта r2→r3 — ровно один коммит правки `a325294d` поверх материала r2
(`462b5645`) плюс публикационный коммит документа r2 (`3066fec1`, без кода):
```
$ git diff --stat 462b5645..a325294d
docs/images/screenshots.json | 24 +--
docs/reviews/CODE-REVIEW-520-r2.md | 358 +++++++++
2 files changed, 370 insertions(+), 12 deletions(-)
```
Дельта **локальна** в смысле §2.9/§2.10: только `docs/images/screenshots.json`
(класс C, отпечаток + 11 `sourceSha256`), ни одного файла класса A/B, `dist/**`
и `custom_components/houseplan/frontend/**` не тронуты, продуктовый код между
r2 и r3 не менялся вовсе (`git diff 462b5645..a325294d -- src test scripts
custom_components` — пусто). Разбор в этом раунде сужен до дельты и до находки
r2 — остальное наследуется из r2 без повторной проверки (раздел ниже).
## Как проверялось
1. Найден вердикт предыдущего раунда (комментарий issue #11, 2026-09-10
17:47:34) и материал, на котором он получен: `462b56453cd6948c083e62ad8c92ec29aeb022b2`,
зафиксирован в `docs/reviews/CODE-REVIEW-520-r2.md` блоком «Материал раунда».
`git diff 462b5645..a325294d` — предмет этого раунда (см. «Скоуп»).
2. По единственной находке r2 показано, чем именно она закрыта — не заявлением
автора: `git diff 462b5645..a325294d -- docs/images/screenshots.json`
меняет ровно `sourceFingerprint` и 11 полей `sourceSha256`
(`ccbbfb4e5aa1… → c615d58061456…`), ни один `imageSha256` не изменился —
то есть ни один PNG не поменялся, менялся только отпечаток источников.
Прогнал сам:
```
$ node scripts/check-docs.mjs
Documentation checks passed (7 files, 12 external links).
```
Красный до фикса зафиксирован в документе r2 буквальным выводом той же
команды («ERROR screenshot source fingerprint is stale…») — «умеет падать»
доказано предыдущим раундом, здесь показан переход в зелёное на исправленном
материале.
3. Трейлеры коммита `a325294d`: `Issue: #520`, `User-Visible: no` — корректно,
диф не меняет ничего, что видит пользователь дома (только служебный
отпечаток документации); changelog не тронут — соответствует.
4. `dist/**` и `custom_components/houseplan/frontend/**` не входят в диф этого
коммита (`git show --stat a325294d`) — ожидаемо для чисто документационной
правки; сверил, что три копии бандла всё ещё совпадают побайтово:
`cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js`
— молча (совпадают).
5. `node scripts/process-gate.mjs` на диапазоне `origin/dev..HEAD` — «гейт
пройден, предупреждений 2» (те же WARN про `node_modules` вне классов
A/B/C/D на исторических коммитах `37ef970d`/`e181b08f`, уже закрыты и
разобраны в r1/r2 как гигиена ветки, не влияющая на финальное дерево).
6. Дешёвые гейты (`typecheck`, `npm test`, `npm run build` со сверкой копий
бандла) на точном материале `a325294d` подтверждены зелёным Validate:
https://github.com/Matysh/houseplan-card/actions/runs/34513504274
(`headSha` сверен через `gh run view --json headSha` — совпадает с
материалом раунда). Не перегонял третьей парой глаз — принято по инструкции
ревью, это не новый код с прошлого раунда (продуктовый код между r2 и r3
не менялся).
7. **Тело issue менялось повторно после r2.** Ревью r2 уже зафиксировало
расхождение с записанным хешем SPEC-REVIEW-520-r3 (#517: `60492a3aec5f…`
против тогдашнего `4524f04412...`). Между вердиктом r2 (17:47:34) и
материалом r3 тело изменилось **ещё раз** — автор сам называет это в
хендоффе (комментарий issue #12): добавлены AC7 и пункт риска про отпечаток
скриншотов, по прямому требованию находки Medium-1 r2. Текущий хеш тела:
`sha256sum` по тексту, полученному `gh issue view 520 --json body -q .body`
→ `f318b25f5815fa66aeaa7cbc5ce1d63e23fab0a8e50493962634b01e0ca86e96` —
отличается от обоих предыдущих записанных значений. Сверено построчно:
правка аддитивна — AC1–AC6, «Причина», «Контракт», «Риски» (кроме одного
нового пункта) не тронуты; новый AC7 («`check-docs` зелёный на материале
ревью») и новый риск-пункт об отпечатке скриншотов дословно описывают
именно то, что закрывает коммит `a325294d`, и ничего сверх этого. Новых
продуктовых развилок текст не вводит, `User-Visible: no` не меняется.
Возврата в `S4-spec-review` не требую — та же логика, что применил r2 к
первому расхождению (дисциплинированное обновление ТЗ вслед за находкой
кода, не смена скоупа).
## Закрытие раунда r2
| Находка r2 | Чем закрыта | Где это видно |
|---|---|---|
| Medium-1 — `node scripts/check-docs.mjs` красный на материале ревью: отпечаток скриншотов документации устарел (диф трогает `src/houseplan-card.ts`, `src/config-adoption.ts`) | Коммит `a325294d`: отпечаток обновлён через `npm run docs:accept -- --identical` (#512) — все 11 кадров пересняты и совпали с закоммиченными побайтово (ни один `imageSha256` не изменился), обновился только `sourceFingerprint` и 11 `sourceSha256` | Прогнал `node scripts/check-docs.mjs` на материале `a325294d` сам — «Documentation checks passed (7 files, 12 external links)»; `git diff 462b5645..a325294d -- docs/images/screenshots.json` показывает ровно 12 изменённых полей, ноль изменённых `imageSha256` |
Находка r2 закрыта полностью и минимально — правка не расширилась за пределы
её предмета.
## Унаследовано из r2 (без повторной проверки)
Продуктовый код между материалом r2 (`462b5645`) и материалом r3 (`a325294d`)
не менялся — дельта чисто документационная (см. «Скоуп»), поэтому из
`docs/reviews/CODE-REVIEW-520-r2.md` наследуется всё содержательное:
- **Находка r1 (High) и её закрытие.** Механизм регрессии (микрозадача после
`await` в `adoptAuthoritativeGated`, а не Lit `wrapped`) и хук `afterAdopt` —
r2 перепроверил независимым измерением на изолированном `git worktree`
(база `a44fbd37` vs `462b5645`), оба профиля (`interaction`, `isometric`),
`benchmark:compare` — все строки бюджета зелёные. Код с тех пор не менялся,
повторное измерение в этом раунде избыточно.
- **AC1, AC2, AC6** — тесты и все четыре мутанта (`adoption-bodies-declared-reactive`,
`adoption-notifies-no-host-on-config-replacement`, `adoption-tail-defers-caller-hook`,
`authoritative-load-seeds-devices-after-the-await`) перепрогнаны r2 лично,
«поймано 1 из 1» каждый; код, которого это касается, в дельте r2→r3
отсутствует.
- **AC3, AC4, AC5** — измерены r2 независимо (не на слово автора): 18 циклов /
3 сборки / 3 эпохи на обоих деревьях и обоих профилях, `benchmark:compare`
— 0 красных строк, `cache.entries.cleanFloor` 100 (interaction) / 60
(isometric). Перф-путь этой дельтой не задет.
- **Бюджет бандла** (потолок 300 300 → 300 400, +40 Б) и `test/bundle-assets.test.mjs`
(26/26 pass) — не тронуты дельтой.
- **17 из 17 «прямых совпадений» `smoke-select`** плюс 3 названных автором
сверх выборки — прогнаны r2 лично, все `OK`; исходный код, который они
проверяют, в этой дельте не менялся.
- **Гигиена ветки** (симлинк `node_modules`, исправление `.gitignore`) —
зафиксирована в r1, не менялась.
- **Первое расхождение тела issue с хешем SPEC-REVIEW-520-r3** (#517) —
разобрано r2, решение «возврата в spec не требую» подтверждено тем же
рассуждением и в этом раунде (см. п.7 «Как проверялось» — уже про второе,
новое расхождение).
- **Откат** — «один revert» из ТЗ технически устарел (теперь три файла, не
один), это отмечено уже r2 как факт вне AC; не предмет этого раунда.
Материал: `docs/reviews/CODE-REVIEW-520-r2.md`, SHA `462b56453cd6948c083e62ad8c92ec29aeb022b2`.
## Что проверено и корректно
- **AC7** (новый в теле issue, добавлен вслед за находкой Medium-1 r2) —
`node scripts/check-docs.mjs` зелёный на материале `a325294d`, прогнан
лично: «Documentation checks passed (7 files, 12 external links)».
«Чем краснеет» — устаревший `sourceFingerprint`, продемонстрировано самим
переходом красный (документ r2) → зелёный (этот документ) на одном и том же
коде отпечатка.
- Ни один `imageSha256` не изменился в диффе r2→r3 — визуальный контент
скриншотов не менялся, обновление чисто механическое (отпечаток источников).
- Три копии бандла (`dist/houseplan-card.js`,
`custom_components/houseplan/frontend/houseplan-card.js`, стендовая не
коммитится) совпадают побайтово — сверено `cmp`.
- Трейлеры `a325294d` — `Issue: #520`, `User-Visible: no`, корректно для
чисто документационной правки.
- `node scripts/process-gate.mjs` — гейт пройден, предупреждения те же, что
и в r1/r2 (гигиена исторических коммитов, не влияет на финальное дерево).
- Validate зелёный на точном материале раунда (`headSha` сверен явно, не
принят на слово) — typecheck/test/build подтверждены этим прогоном.
- Второе расхождение тела issue с записанным хешем ревью ТЗ — названо,
разобрано построчно (аддитивно, соответствует коммиту `a325294d`), решение
«без возврата в spec» обосновано.
## Чего не проверял
- **`npx tsc --noEmit`, `npm test` (весь набор), `npm run build` третьим
прогоном** — Validate зелёный на точном материале `a325294d`
(headSha сверен), продуктовый код между r2 и r3 не менялся; перегон дал бы
тот же результат, что уже подтверждён r2 и Validate.
- **Полное измерение перф-профилей (`benchmark:compare`)** — не перегонял: код
пути загрузки не менялся между r2 и r3, r2 уже воспроизвёл результат
независимо на изолированном `git worktree`, эта дельта его не касается.
- **Смоки `demo/smoke_*.mjs`** — не перегонял ни одного: диф r2→r3 не
затрагивает `src/**`/`demo/**`, `smoke-select` на этой дельте не даёт ни
одного совпадения (проверил: диф ограничен `docs/**`, инструмент по
символам кода не находит кандидатов).
- **`npm run golden:verify`** — не запускал: диф не меняет рендер ни байтом,
визуальная приёмка `--identical` уже доказала попиксельное совпадение всех
11 кадров с закоммиченными PNG.
- **`npm run invariants`, `python -m pytest tests_backend`** — geometry и
Python-бэкенд этой дельтой не затронуты (не были затронуты и всей веткой,
подтверждено r2).
## Гейты: что прогнал сам и почему
| Гейт | Прогнан | Результат |
|---|---|---|
| `node scripts/check-docs.mjs` | да (предмет находки r2, обязателен) | зелёный: «Documentation checks passed (7 files, 12 external links)» |
| `git diff 462b5645..a325294d` (полный, не только имена файлов) | да | 2 файла: отпечаток + публикационный документ r2 |
| `cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js` | да | совпадают побайтово |
| `node scripts/process-gate.mjs` | да | пройден, 2 предупреждения (унаследованы, не новые) |
| `gh run view 34513504274 --json headSha,conclusion` | да | `headSha` = материал раунда, `conclusion: success` |
| `sha256sum` тела issue | да | отличается от обеих предыдущих записей — находка по #517, разобрана в тексте (не блокирует) |
| `npx tsc --noEmit`, `npm test`, `npm run build` (свежий прогон) | нет | Validate зелёный на точном SHA, продуктовый код с r2 не менялся |
| Perf `benchmark:compare` (оба профиля) | нет | код пути загрузки не менялся с r2, где уже измерено независимо |
| `demo/smoke_*.mjs` | нет | дельта не касается `src/**`/`demo/**`, кандидатов ноль |
| `npm run golden:verify` | нет | визуальный контент не менялся, доказано `--identical` |
| `npm run invariants`, `pytest tests_backend` | нет | geometry/backend вне диапазона всей ветки |
## Вердикт
Зелёный. High: 0, Medium: 0. Единственная находка r2 (Medium-1, `check-docs`
красный из-за устаревшего отпечатка скриншотов) закрыта минимальной и точной
правкой — один файл, только отпечаток, ни одного изменённого PNG; перепроверено
прямым прогоном гейта на материале раунда, не на слово автора. Продуктовый код
не менялся с r2, чья находка High (регрессия первого кадра) и все AC1–AC6 уже
были независимо перепроверены измерением и остаются в силе. Новое, второе
расхождение тела issue с зафиксированным хешем ревью ТЗ (#517) названо и
разобрано — аддитивно, соответствует коду, возврата в spec не требует. Задача
готова к пре-релизной очереди.
---
## Материал раунда
- Ветка: `issue/520-first-frame`, коммит `a325294d7a9d8ef4ecfeab2ed3e248318a650ab5`.
- Родитель материала r2: `462b56453cd6948c083e62ad8c92ec29aeb022b2` (`docs/reviews/CODE-REVIEW-520-r2.md`).
- Тело issue на момент ревью: sha256 `f318b25f5815fa66aeaa7cbc5ce1d63e23fab0a8e50493962634b01e0ca86e96`
(получено `gh issue view 520 --json body -q .body | sha256sum`), отличается от
записанного в SPEC-REVIEW-520-r3 (`60492a3aec5f…`) и от значения, названного
в CODE-REVIEW-520-r2 (`4524f04412...`) — разобрано в тексте, возврата в spec
не требует.
- Вердикт этого документа: зелёный · High 0 · Medium 0
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/520-first-frame`, коммит `a325294d7a9d` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `f7b30b932911c9f15765594194a6a0b7852d9f1c`
```
git log --all --format='%H %T' | grep f7b30b932911
```
- Тело issue: `80073dd20133cdbba0bc717c7996f490c2d9010734fecedc11fcf8f894190143`
- Вердикт конвейера: `green` · High 0