16 KiB
SPEC-REVIEW-317-r1
- Issue: #317 — «Метрики под названием комнаты и тултип комнаты не показывают температуру и влажность, хотя датчики в комнате есть»
- Этап: spec (S4-spec-review)
- Заход: r1 · блокирующих циклов израсходовано 0 из 4
- Трек: полный (аналитик сам назвал критерий, который задача не проходит: «изменение затрагивает единый контракт данных сразу для подписи комнаты, тултипа и температурной заливки»)
- Артефакт ТЗ:
docs/specs/317-room-climate-placement.mdна SHAf19ed10f(веткаissue/317-room-climate-placement) - Ревьюер: Claude (сессия ревью ТЗ), состязательно, без пояснений автора
Скоуп ревью
Issue #317 — баг: _roomTemp/_roomHum, общие для подписи комнаты, tooltip и
температурной заливки, читают климат только из areaClimateMap(), которая
группирует сенсоры исключительно по HA registry area_id. Ручное размещение
маркера датчика в комнате House Plan (marker.area/marker.room_id) в
климатический агрегат не попадает, а у комнаты без HA Area автоматического
среднего нет вовсе. Владелец уже принял продуктовое решение по единственному
открытому вопросу (комнаты без HA Area — да, правило распространяется), поэтому
на входе в ревью открытых продуктовых вопросов не осталось.
Разбирался только этот документ: файла предыдущего раунда нет, дельта не считается (§2.10 к первому заходу не применяется).
Как проверялось
Ревью читает ТЗ состязательно: каждое утверждение о текущем поведении и о существующей инфраструктуре сверено с кодом на дереве этого SHA, а не принято на слово автора.
- Прочитаны
docs/SCOPE.md,AGENTS.md,PROCESS.md— трек, разделы §7.1, лимит циклов и формат вердикта. - Прочитаны тело issue #317 и все комментарии, включая явное решение владельца («да, распространяем автоматическое правило также на комнаты без HA Area», 2026-08-28).
- Прочитан
docs/specs/317-room-climate-placement.mdцеликом. - Диагноз ТЗ сверен построчно с кодом:
src/houseplan-card.ts:11956-11968(_roomTemp/_roomHum, gater.area ? this._climate().get(r.area) : null) — подтверждает §3;src/houseplan-card.ts:12093(внешний gate_renderRoomLabel, блокирует метрики area-less комнаты безtemp_source/hum_source/labelLight) — подтверждает §3 и требование §8;src/houseplan-card.ts:11058-11068(tooltip вызывает_roomTemp/_roomHumбез gate) — подтверждает диагноз «дефект воспроизводится сразу на трёх поверхностях»;src/houseplan-card.ts:8502(fill_mode: tempчитает тот же_roomTemp) — подтверждает единственность резолвера;src/devices.ts:1394-1478(areaClimateMap) — подтверждает группировку только поreg.area_id || dev?.area_id, существующий tombstone/use_climate_tempмеханизм,NON_AIR_RE,entity_categorygate — контракт §6.3 списывает их как «сохраняются», а не выдумывает заново;src/devices.ts:1056-1076(resolveExplicitMarkerPlacement) иsrc/devices.ts:350-357(lightSourceBelongsToRoom) — подтверждают, что приоритет «явный marker →room_id+area:null→ registry» уже существует как паттерн для визуального размещения и света; ТЗ не изобретает новый контракт, а переносит существующий на климат;src/logic.ts:2016-2030(parseRoomRef) — подтверждает форматspace#area/space#@roomId, на который ссылается §9;docs/ARCHITECTURE.md:1148-1153— текущее описание one-pass climate совпадает с диагнозом дословно;docs/USER-GUIDE.ru.md:468и:1194— подтверждают, что документация уже фиксирует нынешнее (дефектное) поведение и уже содержит прецедент «room_idточнее HA-зоны» для света, на который ТЗ ссылается по аналогии.
- Проверено существование целевой тестовой/гейт-инфраструктуры, названной в
критериях приёмки, а не выдуманной:
test/devices.test.mjsуже содержит матрицуareaClimateMap(one-pass, tombstone,use_climate_temp) — AC1 расширяет реальный файл;demo/smoke_climate_once.mjsсуществует и уже фиксирует «44/60 rooms» — число в AC9 не с потолка;demo/smoke_climate_temp.mjsсуществует — задел для AC7;scripts/mutation-gate.mjsсуществует и поддерживает--id=<mutant>— механизм AC10 реален;docs/specs/262-readd-child-entity-after-device-delete.mdдействительно фиксирует binding-scoped tombstone contract, на который ссылается §6.2.
- Проверены обязательные разделы ТЗ по §7.1 — все на месте (см. таблицу ниже).
- Проверена трассируемость: issue ↔ ТЗ ссылки в обе стороны,
docs/specs/README.mdобновлён той же строкой, ветка/трейлеры коммита (Issue: #317,User-Visible: no) корректны для чисто документационного коммита.
Гейты (typecheck/test/build) на этом шаге не прогонялись и не должны: стадия —
ревью ТЗ, продуктовый код не менялся (коммит f19ed10f — только
docs/specs/**), unit/build ничего нового не проверили бы. Это соответствует
«гейты соразмерны задаче»: полный набор гейтов относится к код-ревью, не к
ревью ТЗ.
Обязательные разделы §7.1
| Раздел | Есть | Где |
|---|---|---|
| Сценарий (персона, поверхность, момент) | ✅ | §1, ссылается на J1/J5 SCOPE.md |
| Что человек увидит до/после | ✅ | §2, без терминов реализации |
| Проблема | ✅ | §3 (подтверждённый диагноз) |
| Скоуп и не-скоуп | ✅ | §5 |
| Контракт поведения | ✅ | §§6-7 |
| UX | ✅ | §8 |
| Модель данных и миграция | ✅ | §9 (миграции нет, обосновано) |
| i18n | ✅ | §11 (новых строк нет, обосновано) |
| AC1…ACn с доказательством | ✅ | §12, для каждого назван unit/smoke/mutation/review |
| План автотестов | ✅ | §13 |
| Риски | ✅ | §14 |
| Откат | ✅ | §16 |
| Release-артефакты | ✅ | §16 |
Плюс дополнительные разделы сверх минимума (архитектура/perf §10, security/privacy §15, явный блок принятых технических предположений §17) — это хорошо документированное ТЗ для полного трека с реальным риском перфоманса.
Находки
Blocking (High): нет. В скоупе (Medium): нет. Вне скоупа (Medium → issue): нет.
Low (снято ревьюером с записью, правки не требуют)
- Терминология HA Area/HA-зона в плане документации. ТЗ систематически
использует «HA Area», тогда как
docs/USER-GUIDE.ru.mdв основном пишет «HA-зона» и лишь один раз (строка 1194) — «HA Area». Несогласованность уже существует в каноне до этого ТЗ (не внесена им), новых UI-строк ТЗ не добавляет, и §11 прямо поручает автору синхронизировать формулировку при правкеUSER-GUIDE.ru.mdв реализации. Снимаю без правки ТЗ — это редакторская забота реализации, не пробел контракта. - AC8 называет доказательством «diff audit», а не один из канонических
unit/backend/smoke/golden. По содержанию это ревью кода («проверено чтением, не исполнением»): совпадение snapshot/resolver между View и hosted Static и отсутствие мутации config естественно проверяются чтением диффа, а не отдельным раннером. Не считаю это находкой, требующей правки текста ТЗ — отмечаю для код-ревьюера следующего этапа: при проверке AC8 явно указать, что это чтение, а не автотест.
Что проверено и корректно
- Диагноз в §3 воспроизведён по коду один в один, включая три точки отказа
(label gate,
_roomTemp/_roomHum,areaClimateMap) — не разошёлся ни в одной детали с деревом на SHAf19ed10f. - Решение владельца по единственному продуктовому вопросу зафиксировано в issue и корректно перенесено в §4 ТЗ дословно по смыслу.
- Контракт приоритета источников (§6.2, §7) не изобретает новый паттерн, а
переносит уже существующий в проекте прецедент точного/родительского marker
(
resolveExplicitMarkerPlacement,lightSourceBelongsToRoom) на климат — ни одно утверждение о поведении не помечено как факт без опоры на код или канон, а там, где авторы вводят технические решения, они явно вынесены в §17 «принято предположительно, поменять свободно» и открыты для оспаривания. Единственный продуктовый вопрос (комнаты без HA Area) был задан владельцу именно как продуктовый вопрос — не технический вопрос, замаскированный под продуктовый. - Каждый AC (1–11) однозначен и указывает способ доказательства; для AC1, AC7, AC9, AC10 целевые файлы/скрипты уже существуют в дереве, значит критерии не ссылаются на несуществующую инфраструктуру.
- Не-скоуп (§5) явно исключает эвристику air-sensor, миграцию, новый UI,
use_climate_tempsemantics кроме placement — граница с соседними задачами проведена, а не подразумевается. - Откат, release-артефакты, security/privacy покрыты и согласуются с
«никогда не удалять файл пользователя на догадке» и «одно число — один
источник» (§6, §8: label/tooltip/fill читают один и тот же
_roomTemp/_roomHum, что и есть образцовое соблюдение принципа единственного источника числа). - Трейлеры коммита (
Issue: #317,User-Visible: no) корректны для docs-only коммита;docs/specs/README.mdобновлён той же строкой.
Чего не проверял
- Не прогонял
npm run typecheck/npm test/npm run build— на этом шаге нет продуктового кода для проверки (коммит правит толькоdocs/specs/**); прогон ничего не доказал бы и не входит в объём ревью ТЗ. - Не проверял поведение реального HA-инстанса и golden/browser smokes — они
относятся к код-ревью следующего этапа, когда появится код и заявленные в
§13 команды (
node demo/smoke_climate_once.mjsи т.д.). - Не проверял
docs/ARCHITECTURE.md,docs/USER-GUIDE(.ru).md,docs/TESTING.md, оба changelog на предмет уже внесённых правок — по плану реализации (§13, §11) они меняются в коде, а не в этом ТЗ-коммите, и их редактирование — предмет DoD код-ревью, а не спецификации. - Не проверял корректность будущего мутанта
--id=<new-room-climate-placement-mutant>— он ещё не существует, ТЗ лишь называет обязательство его завести.
Вердикт
ТЗ технически обосновано, каждое фактическое утверждение о текущем коде и существующей инфраструктуре подтверждено чтением дерева, единственный продуктовый вопрос уже решён владельцем, все обязательные разделы §7.1 на месте, критерии приёмки пронумерованы и проверяемы. Blocking-находок нет, Medium нет ни в скоупе, ни вне скоупа. Задача может переходить в «Готово к разработке».
Вердикт: зелёный · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 0 · Документ: docs/reviews/SPEC-REVIEW-317-r1.md