Files
2026-10-01 13:56:37 +00:00

17 KiB
Raw Permalink Blame History

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 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: 68e83216547a523438980ca3d253889e6d0279ce
    git log --all --format='%H %T' | grep 68e83216547a
    
  • Тело issue: ba4c5568a2f2b4280acbd5dda51e7bbfe8e2d797f4de12ef083b16502198e57a
  • Вердикт конвейера: green · High 0 · маршрут fix