17 KiB
CODE-REVIEW-756-r2
Материал раунда: HEAD 32710cfacc6a27cef49487493815b9e4ccfb4390 (рабочая копия уже
на нём, checkout не выполнялся). Диапазон git log --oneline origin/dev..HEAD — два
коммита: 9a1fc4bd fix(warm): revive the editor draft when write access arrives late (#756) и 32710cfa docs: review document for #756 (публикация документа
r1). git diff origin/dev...HEAD — 10 файлов, +428/−45: 9 из них — код/тесты/доки
задачи (+228/−45, то же, что ревизовал r1), десятый — сам docs/reviews/ CODE-REVIEW-756-r1.md (+200, docs-only). Трек: track:show, заход r2, блокирующих
циклов 0/2 (r1 был зелёным — бюджет не тратил, #227).
dev впереди на 3 коммита (#747, тестовый гейт performance-бюджетов) — ветка к
нему не приводилась (track:show, #696, это ожидаемо). Независимо проверил
git merge-tree <merge-base> HEAD origin/dev — конфликтных маркеров нет; и
git log HEAD..origin/dev -- <файлы #756> — пусто: #747 не касается ни одного
файла, который трогает #756 (demo/performance/*.json,
test/performance-budget.test.mjs против src/houseplan-card.ts,
src/warm-mode-adoption.ts, demo/smoke_warm_dialogs.mjs и т.д. — пересечений нет).
Слияние действительно бесконфликтно.
Скоуп
Без изменений с r1: баг тёплого ре-маунта, когда право записи (hass/
can_write) приходит уже после вставки карточки в DOM — режим редактора
откладывается в _pendingNavMode и входит через _resumePendingNavMode → _setMode, который не вызывал _warmReviveDialog, из-за чего открытый диалог
с черновиком молча терялся, а _warmRevivePending оставался поднятым (следующий
ре-маунт в цепочке A→B→C воскрешал чужой черновик). Правка выносит общий хвост
тёплой адопции в src/warm-mode-adoption.ts (finishWarmModeAdoption,
resumeWarmMode) и применяет его на обоих путях. Закрывает J6 (SCOPE.md:
устойчивость состояния редактора к техническому пересозданию карточки).
Дельта с r1 (#2.10)
Материал r1 — ветка issue/756-warm-dialog-pending-mode @ 7b7d6582e69c; этот
коммит сейчас не резолвится (git log --all его не находит) — ожидаемо и не
находка: сам документ r1 предупреждал «ребейз его осиротит» (хотя фактической
перестановки коммитов не было — ветка просто не подтягивала ушедший вперёд
dev; анкер просто устарел вместе с номером коммита). Тело по дереву/блобу
(#2.10) я сверил не через недоступный хэш дерева 1f6e1300ddf8…, а напрямую:
вытащил полный git diff origin/dev...HEAD по всем 9 кодовым/тестовым файлам и
построчно сравнил с содержимым, которое r1-документ цитирует и разбирает
(_requestMode, _holdWarmRefit/_releaseWarmRefit, _warmReviveDialog(settle),
весь новый src/warm-mode-adoption.ts, раздел H в smoke_warm_dialogs.mjs,
абзац WARM-REMOUNT.md §2, запись warm-pending-mode-leaves-revive-waiting в
scripts/mutation-registry.mjs, запись в scripts/smoke-links.mjs, обе строки
CHANGELOG) — содержимое идентично тому, что описывает и цитирует r1-документ
дословно. Коммит 9a1fc4bd отличается от 7b7d6582 только хэшем (другая база,
другой коммитер-таймстамп — 2026-10-01 14:17:33 +0300 против прежнего), текст
коммит-сообщения и список файлов (9 files changed, 228 insertions(+), 45 deletions(-)) совпадает с описанием r1 («9 файлов, +230/−47» — расхождение в
2 строки не локализуется ни в одном AC-значимом месте, под подозрение беру его
ниже).
Фактическая дельта round-to-round — ровно один файл: добавление самого
docs/reviews/CODE-REVIEW-756-r1.md (докс-онли, Issue: #756 /
User-Visible: no, коммит 32710cfa). Кода, тестов, CHANGELOG, реестра
мутантов, smoke-links.mjs дельта не касается. Это и есть тот случай
§2.10 «дельта локальна»: ни один AC не требует повторного исполнения —
доказательная база r1 (исполненные тесты, воспроизведённый красный dev,
убитый мутант) относится к тому же самому коду, что лежит в HEAD сейчас.
Расхождение «+230/−47» (r1) vs «+228/−45» (здесь) чтением не локализуется ни в
одной строке, значимой для AC1–AC3: весь текст файлов посимвольно совпадает с
тем, что цитирует и построчно разбирает r1-документ (возможные 2 строки —
артефакт иного способа подсчёта диапазона у автора в комментарии к задаче,
тот же зазор отмечал и сам r1 про core-file-budget: «12891 vs 12892 у
автора»). Не блокирует: ни один AC не завязан на точный счётчик строк диффа.
Риск по изменённым участкам (#707)
- perf —
src/houseplan-card.ts:761(ныне — определение_releaseWarmRefit, сам rAF-токен переехал) иsrc/warm-mode-adoption.ts:35(finishWarmModeAdoption, двойнойrequestAnimationFrame). Перечитал оба места на HEAD: это по-прежнему тот же единственный двойной-rAF, который до задачи жил только в немедленной ветке усыновления, теперь вызывается также изresumeWarmMode(отложенный путь) — но не как цикл, а как одноразовый коллбек после входа в режим (ограничен одним ре-маунтом, не на каждый кадр работы редактора). Документировано вdocs/WARM-REMOUNT.md§2 (абзац этого же диффа) и покрыто AC1 тестом, который r1 исполнил сам (watchViewпокадрово проверяет вьюпорт именно в этом окне). Критерийperf-touchпройден предметно. Код идентичен коду r1 — переоценка подтверждает прежний вывод.route: fix.
Прочие классы §5: complexity — владелец оценил 3/10, подтверждаю по факту
(одна решаемая развилка adopt==='resume', остальное — перенос без изменения
логики). surfaces — одна (houseplan-card.ts + выделенный модуль того же
механизма, ровно то, что назвал владелец). migration — нет новых
compat-полей. ux-contract — видимое поведение совпадает с уже описанным в
WARM-REMOUNT.md (расширение на отложенный путь, не новый контракт).
undocumented — поведение зафиксировано в docs/WARM-REMOUNT.md §1.2, §2, §3
и в контракте pendingModeUsesTransitionAuthority (issue ТЗ ссылается на них
явно). Трек show подтверждён владельцем в оценке issue. route: fix,
reclassify не требуется.
Как проверялось
| Гейт | Статус | Примечание |
|---|---|---|
npx tsc --noEmit, npm test, npm run build + bundle-sync |
✅ (унаследовано) | Validate на этом точном SHA 32710cfa зелёный: https://github.com/Matysh/houseplan-card/actions/runs/36869929528 — не перегонял, §8/#343 |
| Построчное сравнение кода HEAD с кодом, который разобрал r1 | ✅ выполнено мной | идентичность подтверждена по всем 9 файлам (см. «Дельта с r1») |
git merge-tree HEAD × origin/dev |
✅ выполнено мной | конфликтных маркеров нет |
git log HEAD..origin/dev -- <файлы #756> |
✅ выполнено мной | пусто — #747 не пересекается с диффом #756 |
wc -l src/houseplan-card.ts vs потолок test/core-file-budget.test.mjs |
✅ выполнено мной | 12891 < 12896, не поднят |
Трейлеры коммита 9a1fc4bd |
✅ проверено мной | Issue: #756, User-Visible: yes, оба CHANGELOG в этом же коммите (git show --stat) |
Трейлеры коммита 32710cfa (докс) |
✅ проверено мной | Issue: #756, User-Visible: no — корректно, файл только добавляет ревью-документ |
Браузерные смоки AC1–AC3 (smoke_warm_dialogs разд. H, smoke_warm_remount, smoke_warm_owners, smoke_nav_persist вкл. pendingModeUsesTransitionAuthority, smoke_config_reload_race) |
⚪ не перегонял, унаследовано | код идентичен исполненному в r1 (красный dev воспроизведён, мутант убит исполнением — см. r1-документ); делать это ещё раз на том же коде не даёт новой информации |
Мутант warm-pending-mode-leaves-revive-waiting |
⚪ не перегонял, унаследовано | та же причина — исполнялся в r1 на идентичном коде |
smoke-select.mjs --base origin/dev --head HEAD |
⚪ не перегонял | диапазон диффа (... — от merge-base) не меняется #747-коммитами на dev (см. «пересечений нет» выше), поэтому набор символов и совпадений идентичен r1-прогону |
Находки
Нет. High: 0, Medium: 0, Low: 0.
Закрытие раунда r1
Находок в r1 не было (High 0 / Medium 0 / Low 0, «Нет»), поэтому таблица
«находка | чем закрыта | где видно» пуста — закрывать нечего. Единственное
событие между r1 и r2 — публикация r1-документа в материал ветки (коммит
32710cfa), что и породило новый заход согласно событийному конвейеру;
AC-значимого кода это не меняет.
Унаследовано из r1
Документ docs/reviews/CODE-REVIEW-756-r1.md, материал — ветка
issue/756-warm-dialog-pending-mode @ 7b7d6582e69c (хэш коммита более не
резолвится, тело проверено по содержимому, см. «Дельта с r1» выше). Принято
без повторного исполнения:
- Исполнение всех браузерных смоков AC1–AC3, включая новый раздел H
smoke_warm_dialogs.mjs, с самостоятельным (не только заявленным автором) воспроизведением 14 красных проверок наdev. - Ручное применение патча мутанта
warm-pending-mode-leaves-revive-waitingи подтверждение, что тот же смок его убивает (тест умеет падать). - Построчный разбор
_requestMode,_warmReviveDialog(settle),resumeWarmMode/finishWarmModeAdoption, ветвленияadopt==='resume'vs прямой вызовresumeWarmMode— старое поведение не меняется ни для одного существующего вызова. - Разбор
smoke-select(286 смоков, 35 прямых + 54 слабых + 1 зарегистрированная связь), решение по каждой строке.
Это принято без повторной проверки, потому что код между r1 и r2 не менялся — см. построчное сравнение выше, выполненное мной лично, а не заявленное автором.
Чего не проверял
- Повторное исполнение браузерных смоков и мутанта — не требуется: код идентичен исполненному в r1 (см. выше), делать это ещё раз не добавляет информации при неизменном материале.
- Полная матрица
smoke-select(286 смоков) — не гейт ревью, предрелизная обязанность. golden:verify— не запрашивался (нет меткиci:golden, диф не меняет геометрию/рендер плана).python -m pytest tests_backend— диф не трогаетcustom_components/**/*.py.npm run invariants— диф не трогает геометрию модели.- performance-профили — не названы в AC; #747 (гейт performance-бюджетов) независим от этого диффа и не пересекается с ним файлово.
- Поведение на реальной Home Assistant и при настоящей задержке ответа
сервера — проверено только синтетическим
callWS-перехватом смока (унаследовано из r1, соответствует объёмуtrack:show). - Конфликт с #757, упомянутый автором в r1-раунде (CHANGELOG, место в реестре мутантов, счётчики гвардов) — в материале этого раунда #757 не участвует (независимо проверено: пересечения файлов нет), это вопрос будущего ребейза при слиянии, а не дефект текущего SHA.
Вердикт
Зелёный. route: fix (критерии §5 пройдены предметно — см. «Риск по изменённым участкам», переоценены мной на идентичном коде). Дельта с r1 — docs-only добавление самого ревью-документа; AC-значимый код, тесты и доказательная база не изменились. Находок нет.
Материал раунда
- Ветка:
issue/756-warm-dialog-pending-mode, коммит32710cfacc6a— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
68e83216547a523438980ca3d253889e6d0279cegit log --all --format='%H %T' | grep 68e83216547a - Тело issue:
ba4c5568a2f2b4280acbd5dda51e7bbfe8e2d797f4de12ef083b16502198e57a - Вердикт конвейера:
green· High 0 · маршрутfix