# SPEC-REVIEW-594-r2 Issue: https://github.com/Matysh/houseplan-card/issues/594 Этап: ревью ТЗ (PROCESS.md §2.4), заход r2, лимит циклов 4 (полный трек — меток `small`/`trivial` на issue нет). ## Материал раунда - Тело issue #594 в текущем виде (создано 2026-09-18T19:37:30Z комментарием-заведением, далее **ни разу не редактировалось** — в `gh api .../issues/594/events` нет ни одного события `edited`; единственные события — labeled/unlabeled и два `commented`). - `sha256` нормализованного тела на этом прогоне (из `review-prepared/prepared.json`, сгенерировано конвейером при применении текущей метки `S4-spec-review` в 19:43:22): `material_issue_body = 97f5a0277d2aee81abd986c24d874aa94949902428cc33bd2eb845990d48b37b`, `material_sha = 7ce9e6437f2584198fef3e3618173a885e825044` (рабочая копия репозитория), run_id `35387520162`, `cycle: "2"` — совпадает с заходом r2 в заголовке задачи. - **Ключевой факт раунда: дельты с материалом r1 нет.** Комментарий Matysh 19:43:19 ("Редакция ТЗ по уточнению владельца 18.09... Возвращаю на ревью ТЗ") текстуально описывает содержимое, которое уже присутствует в теле issue с момента его создания (К5, К6, AC11 и т. д. — сверено построчно), а не отдельную правку тела: событий `edited` после создания нет. Значит вердикт r1 (комментарий ниже) и этот раунд разбирают **один и тот же байт-в-байт текст**. ## Вердикт предыдущего раунда (r1) — как он найден `docs/reviews/SPEC-REVIEW-594-r1.md` в репозитории не найден ни в одной ветке (`git log --all --diff-filter=A -- '*SPEC-REVIEW-594*'` — пусто) и не найден на диске CI-раннера: это ожидаемо и не является дефектом (см. преамбулу задачи — документ некоммитнутого раунда живёт вне репозитория и не обязан переживать раунд). Материалом для сверки служит вердикт-комментарий: > **Вердикт: жёлтый · заход r1 · блокирующих циклов 0/4 · High: 0 · Medium: 1 → в задаче** > (комментарий `github-actions[bot]`, 2026-09-18T19:48:40Z, > https://github.com/Matysh/houseplan-card/issues/594#issuecomment-5735359281) **Находка процесса (не блокирует, фиксирую по инструкции раунда):** этот комментарий не называет ни SHA материала, ни blob тела issue, ни ссылку на артефакт с анкорным блоком из PROCESS.md §2.10 п.1 ("блок дописывает SHA ветки, дерево материала и блоб ТЗ"). Материал пришлось восстанавливать косвенно — через отсутствие `edited`-событий в таймлайне issue и через `prepared.json` текущего запуска. Для ревью ТЗ (в отличие от код-ревью) SHA ветки в принципе неприменим, но blob тела — применим и его стоило бы называть в самом вердикт-комментарии, а не только в служебном JSON конвейера. ## Закрытие раунда r1 | # | Находка r1 | Чем закрыта | Где это видно | |---|---|---|---| | Medium (в скоупе) | Раздел «i18n» называет только 4 новых `*.help`-ключа для подсказок групп, но не называет ключи для текста самих заголовков групп («Основное», «Заливка», «Источники», «Размеры») — а это такой же пользовательский текст через `_t()`, как и всё остальное; ни один существующий `room.*` ключ не совпадает текстом ни с одним из четырёх заголовков | **Не закрыта.** Тело issue не редактировалось ни разу с момента создания (см. «Материал раунда» выше) | Раздел `### i18n` тела issue #594, текущий текст: *«Новые ключи только на справку заголовков групп: `room.basics.help`, `room.fill.help`, `room.sources.help`, `room.sizes.help`… Существующие ключи не трогаются»* — дословно тот же текст, который цитировал r1 | | Low: раздел «Release-артефакты» ссылается на кадр `room-card` (View), а не на диалог настроек | Снята r1 решением ревьюера с записью, повторной проверки не требует | комментарий r1 | | Low: раздел «Проблема» не выделен явным заголовком | Снята r1 решением ревьюера с записью («закрыт предшествующим `## Аналитика`») | комментарий r1 | Раз тело не менялось, Medium-находка объективно не может быть закрыта в этом раунде — это не новая находка, а тот же дефект ТЗ, ещё не исправленный автором. Верификация собственным чтением (ниже) подтверждает: находка обоснована. ### Независимая проверка находки r1 (не просто доверие) Прочитал текущую структуру диалога, чтобы находка не осталась голословной цитатой: - `src/editors/room-settings-dialog.ts:60` — `room.settings_section` = «Настройки комнаты (переопределяют пространство)» сейчас заголовком накрывает **весь** блок: заливку **и** оба источника (temp/hum). ТЗ делит этот блок на два новых заголовка «Заливка» и «Источники» — прямой реюз `room.settings_section` для одного из двух новых заголовков без явного решения невозможен, нужен минимум один новый ключ. - `src/editors/room-settings-dialog.ts:93` — `room.sizes_section` = «Размеры шрифтов» (en: «Font sizes») — по смыслу близко к предложенному заголовку «Размеры» и мог бы быть переиспользован **явным решением**, но ТЗ этого решения не фиксирует. - Блок «Основное» (имя + область) сегодня заголовка вообще не имеет — это четвёртый ключ, которого нет ни в существующем коде, ни в разделе i18n ТЗ. - Итого: минимум 1, вероятно 3–4 новых `*_title`-ключа (плюс сопутствующие `en/ru/fr/de`, как и у `.help`), которых в разделе i18n нет ни явно, ни как решение «переиспользовать Х». DoR §2.5 требует «i18n: ключи en + ru перечислены» — список неполон, точно так же, как записал r1. Вывод: находка r1 не просто актуальна, а её независимая перепроверка кода только усиливает — реального готового реюза на 3 из 4 заголовков нет, значит это не забытая формальность, а недостающая проектная развилка, которая по DoR обязана быть решена до `S5-ready`. ## Унаследовано из r1 (без повторной проверки состава, только точечная сверка) Материал идентичен, поэтому эти пункты не разбираю заново по существу — я лишь выборочно перепроверил чтением кода несколько наиболее рискованных, чтобы не просто доверять чужому выводу (список ниже помечен, что именно сверено сейчас): - К1 (ключи черновика `_nameSel`, `_areaSel`, `_roomFill`, `_roomCustomFill`, `_roomTempMin/Max`, `_roomTempSrc/_roomHumSrc`, `_roomNameScale`, `_roomLabelScale`) — унаследовано с r1, **не сверял повторно** (не риск для i18n-находки). - `_renderRoomSource` — единственный потребитель — унаследовано с r1. - К3 (`hp-color-opacity`, событие `hp-color-opacity-change`) — **сверено повторно**: `grep` подтверждает событие и его контракт `{color, opacity}` используется тем же образом в `room-settings-dialog.ts:80` и в остальных потребителях компонента (`decor-image-editor.ts`, `houseplan-editor-runtime.ts`). Совпадает с выводом r1. - Шесть вариантов заливки (АС/UX) — **сверено повторно**: `ROOM_FILL_MODES` в `src/logic.ts:932` содержит 5 значений (`none, lqi, light, temp, custom`), плюс код диалога добавляет вариант `''`/`fill.inherit` первым (`room-settings-dialog.ts:62`) — итого 6, как заявляет ТЗ. Подтверждено. - AC7: golden-сцены `room-temperature-dialog-{desktop-en,mobile-ru}` — **сверено повторно**: `demo/golden/matrix.mjs:1016-1021` объявляет обе сцены с `dialog: 'room-temperature'`, а `demo/golden/harness.mjs:1740-1767` для этого типа сценария вызывает `card._openRoomEdit(room)` и ищет `hp-dialog.roomdialog` — это ровно тот же диалог, который рендерит `renderRoomSettingsDialog` (класс `roomdialog`, `room-settings-dialog.ts:34`). Заявленные эталоны действительно покрывают редактируемую форму, а не отдельный мини-диалог с похожим именем. - AC8/тест `editor-dialog-modules.test.mjs` — файл существует (`test/editor-dialog-modules.test.mjs`), `INITIAL_VIEW_GZIP_CEILING` определён в `scripts/bundle-budget.mjs:294` — **сверено повторно**, унаследованный вывод r1 верен. - `hp-help` и паттерн `.help(.aria)` — унаследовано с r1, **не сверял повторно**. - Техническая развилка стилей панель-строка / карточка-теги (К5, `cardStyles` как синхронный граф, `houseplan-card.ts:13711`) — унаследовано с r1, не риск для i18n-находки, не пересматриваю. - Согласие ТЗ с обоими решениями владельца от 18.09 (набор+диалог одним issue; стили панели не трогаются в этом шаге) — унаследовано с r1. - Обе Low-находки r1 (снятые с записью) — унаследованы как закрытые, не пересматриваю. Источник наследования: комментарий-вердикт r1, https://github.com/Matysh/houseplan-card/issues/594#issuecomment-5735359281, материал — тело issue #594, идентичное текущему (см. «Материал раунда»). ## Находки этого раунда ### Medium (в скоупе задачи, унаследована из r1, не закрыта) **Раздел «i18n» ТЗ не называет ключи для текста заголовков четырёх новых карточек-групп** («Основное», «Заливка», «Источники», «Размеры»), хотя раздел «Что человек увидит» и «UX» прямо вводят эти подписи как видимый пользователю текст, идущий, как и всё остальное в диалоге, через `_t()`. Ни один существующий ключ `room.*` не покрывает все четыре напрямую (см. «Независимая проверка находки r1» выше — `room.settings_section` накрывает сразу два новых заголовка, `room.sizes_section` близок к одному, у «Основное» реюза нет вовсе). DoR §2.5 требует полный список i18n-ключей en+ru до перехода в `S5-ready` — список сейчас неполон. **Воспроизведение:** открыть раздел `### i18n` тела issue #594 — там 4 ключа `*.help` (+ `.aria`), и не более. Раздел `### Контракт поведения`, пункт «После:» и раздел `### UX` называют четыре подписи групп текстом, которого в i18n-разделе нет. **Правка (описана уже r1, повторяю, так как не выполнена):** добавить в раздел i18n явный список из 4 ключей заголовков (например `room.basics_title`/`room.fill_title`/ `room.sources_title`/`room.sizes_title`) для en/ru/fr/de **или** явно решить для каждого заголовка «переиспользуем ключ X» — в том числе зафиксировать, что `room.settings_section` для двух новых заголовков не подходит без переименования/расщепления, а `room.sizes_section` можно оставить как есть только если текст «Размеры шрифтов» устраивает как заголовок карточки «Размеры» (сейчас это не решено явно). ## Что проверено и корректно - Материал раунда установлен точно (пустая дельта подтверждена таймлайном issue, а не предположением). - Находка r1 перепроверена независимым чтением кода, а не просто процитирована. - Пять пунктов из унаследованного списка r1 сверены повторно точечно (см. выше) и подтвердились без расхождений. - ТЗ по-прежнему формально полно по остальным разделам §7.1 (сценарий, что человек увидит, скоуп/не-скоуп, контракт К1–К7, UX, модель данных, AC1–AC11 с доказательством, план автотестов, риски, откат, release-артефакты) — здесь не пересматриваю состав, так как дельта их не касается и r1 их уже принял. ## Чего не проверял - Полный повторный аудит AC1–AC11, К1–К7, рисков и release-артефактов «с нуля» — дельта нулевая, они наследуются из r1 согласно PROCESS.md §2.10 п.4 (перепроверяются только AC, которые задевает дельта; дельты нет, кроме отсутствия правки самой находки). - Гейты кода (typecheck/test/build/golden/смоки) — этап spec, кода ещё нет, они неприменимы к ревью ТЗ. - Не связывался с владельцем и не запрашивал новых продуктовых уточнений: находка этого раунда техническая (список i18n-ключей — «то, чего пользователь не наблюдает» до факта показа формы; сами названия групп уже зафиксированы в ТЗ как факт, не как открытый продуктовый вопрос), значит она решается автором и ревьюером, не владельцем. ## Вывод Дельты со времени r1 нет: находка Medium не закрыта, потому что тело issue не редактировалось. Верхнеуровневый разбор ТЗ сокращён по PROCESS.md §2.10 (дельта пуста), но находка перепроверена по существу, а не унаследована слепо. Возврат автору для правки раздела i18n; при следующем заходе ревью снова ограничится дельтой, если правка не заденет ничего кроме этого раздела. **Вердикт: жёлтый · заход r2 · блокирующих циклов 2/4 · High: 0 · Medium: 1 → в задаче** --- ## Материал раунда - Ветка: `dev`, коммит `7ce9e6437f25` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала: `257277214219bb8aac1bf3546c47cebe7615b709` ``` git log --all --format='%H %T' | grep 257277214219 ``` - Тело issue: `97f5a0277d2aee81abd986c24d874aa94949902428cc33bd2eb845990d48b37b` - Вердикт конвейера: `yellow` · High 0