11 KiB
CODE-REVIEW-196-r1
Issue: #196 — «Тултип комнаты: показывать влажность рядом с температурой»
Трек: small (лёгкий), ТЗ — тело issue, ревью ТЗ — SPEC-REVIEW-196-r1 (зелёный, r1/2).
Диапазон: origin/dev..HEAD, один коммит d01d092 («feat: show humidity in room tooltips»).
Ревьюер: Claude, код-ревью. Автор реализации: Codex (см. хендофф в issue).
Скоуп
Один коммит класса A+B+C+D:
src/houseplan-card.ts—_tip/_showTipполучаютhum?, room hover передаёт_roomHum(r), рендер тултипа добавляет строкуtip.hum_avgмежду температурой и LQI.src/i18n/en.json,src/i18n/ru.json— ключtip.hum_avg.demo/smoke_ux_fixes.mjs,demo/smoke_room_settings.mjs— расширены под AC1–AC3.docs/USER-GUIDE.ru.md,docs/TESTING.md,docs/STATUS.md,docs/CHANGELOG.md,docs/CHANGELOG.ru.md— обновлены в том же коммите.dist/houseplan-card.js,custom_components/houseplan/frontend/houseplan-card.js,demo/srv/assets/houseplan-card.js— три копии сгенерированного бандла.
Трейлеры коммита: Issue: #196, User-Visible: yes; оба changelog правлены в этом же коммите — соответствует §7.1/§10.2 PROCESS.md. Соответствует классам файлов из AGENTS.md (A/C/D в одном коммите допустимо, документация — часть DoD).
Скоуп не расширен: device tooltip и room label (уже показывают влажность) не тронуты, что и требовало ТЗ («не входит в задачу»).
Как проверялось
| Гейт | Команда | Результат |
|---|---|---|
| typecheck | npx tsc --noEmit |
зелёный, без вывода |
| unit | npm test |
900/900 pass |
| build + сверка бандлов | npm run build && cmp dist/houseplan-card.js custom_components/houseplan/frontend/houseplan-card.js && cmp dist/houseplan-card.js demo/srv/assets/houseplan-card.js |
зелёный, три копии побайтно идентичны; git status --porcelain после сборки пуст — закоммиченный бандл уже соответствует источнику |
| целевой смок AC1–AC3 | node demo/smoke_ux_fixes.mjs |
OK, все поля включая новые (tipHum, tipHasHumLine, tipMetricOrder, tipPositionUnchanged, noHumidityOmitted, deviceTooltipHasNoHumidity, noHoverSuppressesTooltip) — true/ожидаемые значения |
| целевой смок AC1–AC2 (override без HA-зоны) | node demo/smoke_room_settings.mjs |
OK, включая tooltipShowsHumiditySource, invalidHumiditySourceIsOmitted, humFromSourceAreaLess |
| дисциплина «тест умеет падать» | пересборка origin/dev (без правки тултипа) во временном git worktree с теми же файлами смоков из HEAD, повторный прогон |
оба смока падают предсказуемо: smoke_ux_fixes → tipHum: expected 48, got undefined, tipHasHumLine/tipMetricOrder → false; smoke_room_settings → tooltipShowsHumiditySource: expected true, got false. Подтверждает, что новые проверки не тавтологичны |
Гейты не прогонялись, и почему:
- Полный набор
demo/smoke_*.mjs(127 файлов) — не прогонялся. Diff меняет ровно одну текстовую строку в одной существующей UI-поверхности (room hover tooltip); AC называют толькоsmoke_ux_fixes/smoke_room_settings, оба прогнаны целевым образом. Остальные смоки не имеют отношения к тултипу комнат. npm run golden:verify— не прогонялся. Проверено чтением: единственные golden-сценарии, трогающие тултип-подсистему (hover-over-glow-dark,hover-nested-room-darkвdemo/golden/matrix.mjs:246-249), реализованы вdemo/golden/harness.mjs:563-569через прямую установкуcard._hoverRoom = {...}— это state оверлея подсветки периметра комнаты, а неcard._tip. Реальныйmousemoveтам не диспатчится,_showTip()/_tipне участвуют, значит новая строка влажности эти эталоны не задевает. Само ТЗ также утверждает «новый golden не требуется» — проверено, а не принято на веру.python -m pytest tests_backend -q— не прогонялся: ни один файлcustom_components/**/*.pyне изменён.- performance-профили — не прогонялись: AC не называют перф-влияние,
_roomHum()/_climate()— уже существующий кеш, новых подписок/сканов registry нет (см. ниже).
Находки
Нет. High: 0, Medium: 0, Low: 0.
Что проверено и корректно
- AC1 (
tip.hum_avgпосле температуры, до LQI, при валидной средней влажности зоны) — доказано смокомsmoke_ux_fixes(tipHasHumLine,tipMetricOrder,tipHum: 48) и подтверждено регрессионным прогоном на немодифицированномdev(тест падает без правки). - AC2 (override
hum_sourceбез HA-зоны, без дублирования резолвера) — доказано смокомsmoke_room_settings(humFromSourceAreaLess,tooltipShowsHumiditySource) и чтением кода:_roomHum()(houseplan-card.ts:16796-16800) — единственный резолвер,_showTipвызывает только его, никакой inline-логики источника в месте вызова (:15645-15649) нет. - AC3 (null/невалидный источник — строки нет; device tooltip без ложной влажности;
_noHoverне создаёт тултип) — доказано смоками (noHumidityOmitted,invalidHumiditySourceIsOmitted,deviceTooltipHasNoHumidity,noHoverSuppressesTooltip) и чтением: второй вызов_showTip(device tooltip,:16749) передаёт только(e, d.name, metrics)— три аргумента,lqi/temp/humостаютсяundefined, регрессии в существующем контракте нет; guardif (this._noHover) return;(:5766, начало_showTip) не тронут. - AC4 (i18n-паритет EN/RU, typecheck/unit/build, три копии бандла) — доказано прогоном
npm test(включаетtest/i18n.test.mjs, парность ключей),npx tsc --noEmit,npm run build+cmpтрёх копий. - AC5 (нет новых HA-подписок/registry-обходов/config-writes/schema/backend изменений, скоуп не расширен) — проверено чтением: единственные изменения в
houseplan-card.ts— тип_tip, сигнатура_showTip(новый последний опциональный параметр), один вызов_roomHum(r)в существующем hover-обработчике и два новых template-условия рендера._roomHum/_climate()не изменены (не в diff), кеш_climateCacheтот же.custom_components/**не тронут. - Позиционирование тултипа и существующие строки (площадь, температура, LQI, цвет LQI) не изменились —
tipPositionUnchanged,tipHasArea,tipHasAreaLine,tipHasTempLineзелёные. - Touch/View-контракт:
docs/TOUCH-SUPPORT.mdне применяется — hover tooltip остаётся View-поверхностью без изменения touch-контракта; влажность и так видна в подписи комнаты без hover. - Документация:
docs/USER-GUIDE.ru.md:173— таблица режимов теперь перечисляет влажность в подсказке Просмотра, терминология («средняя влажность») совпадает с i18n-ключом и не изобретена заново.docs/TESTING.md— обе строки обновлены и помечены[auto: smoke_...]вместо прежнего[manual], соответствует фактическому покрытию.docs/CHANGELOG.md/docs/CHANGELOG.ru.md— по одной записи, ссылка на #196, формулировка соответствует контракту (источник/зона, скрытие при отсутствии данных).docs/STATUS.md— строка текущего цикла включает #196. - Трейлеры и changelog-дисциплина: единственный коммит несёт
Issue: #196иUser-Visible: yes; оба changelog правлены в нём же — выполнено §10.2/AGENTS.md.
Чего не проверял
- Полный набор из 127 браузерных смоков — обоснование выше (диффу и AC достаточно двух целевых).
npm run golden:verify— не прогонялся; замена — чтениеdemo/golden/harness.mjs/matrix.mjs, подтвердившее отсутствие пересечения сценариев с_tip.- Бэкенд (
pytest tests_backend) — не затронут диффом. - Ручной просмотр в браузере (в цикле нет фазы ручного тестирования; целевые смоки и чтение кода отвечают на вопрос «оно работает»).
- Производительность — вне AC, изменение не касается путей рендера, чувствительных к перфу.
Вердикт
Зелёный. Все AC1–AC5 доказаны — либо целевым автотестом с подтверждённой способностью падать, либо чтением кода с явной пометкой. High/Medium/Low находок нет. Задача готова к слиянию в dev.