# SPEC-REVIEW-594-r3 Issue: https://github.com/Matysh/houseplan-card/issues/594 Этап: ревью ТЗ (PROCESS.md §2.4), заход r3, блокирующих циклов израсходовано 2 из 4 (полный трек — меток `small`/`trivial` на issue нет). ## Материал раунда - Тело issue #594 в текущем виде (снято через `gh issue view 594 --json body`), `sha256` нормализованного тела (LF, UTF-8): `594c7771e678dae203db75069c75806da3eec9c1d9b155a3d7ba2236d338052a`, длина 18279 байт. Ветка/дерево репозитория для сверки кода: `df7a62c82ef0f320ac1367a1272761f479af2612` (рабочая копия), код в `src/**` относительно материала r2 (`7ce9e6437f25`) не менялся — этап spec, диффа кода нет и быть не должно. - Найден комментарий-редакция Matysh, id `5735598406`, 2026-09-18T20:10:18Z: «Редакция r3: Medium закрыта, обе Low тоже» — заявляет правку раздела i18n, раздела «Release-артефакты» и явный заголовок «Проблема». - **Важная деталь материала, которую сам автор указал в этом же комментарии:** REST API issue-таймлайна не отдаёт событие `edited` (это подтвердил и вывод `gh api .../events` в этом раунде — типы событий только `labeled/unlabeled/parent_issue_added/referenced`), из-за чего r2 ошибочно заключил «тело не редактировалось». Автор утверждает, что правка **была** (в 16:11, до заведения issue в его нынешнем виде). Для целей этого раунда это не имеет значения: важен не факт прошлой правки, а то, что **текущее** тело отличается от текста, который цитировал/пересказывал r2, — и это подтверждено прямым построчным сравнением ниже, а не косвенным признаком «есть ли `edited` в таймлайне». Фиксирую как находку процесса (не блокирует): вывод «дельты нет» нельзя делать по отсутствию `edited`-события — нужно сравнивать сам текст (blob/sha256), как и предлагал сам r2 в своей находке процесса. ## Закрытие раунда r2 | # | Находка r2 | Чем закрыта | Где это видно | |---|---|---|---| | Medium (в скоупе): раздел i18n не называет ключи заголовков четырёх групп («Основное», «Заливка», «Источники», «Размеры») | **Закрыта.** Раздел `### i18n` переписан: явная таблица решений по каждому из четырёх заголовков | Тело issue, раздел `### i18n` (строки 83–102 текущего тела): `room.group_basics` / `room.group_fill` / `room.group_sources` — новые ключи; `room.sizes_section` — переиспользуется как есть; `room.settings_section` — удаляется из кода и всех 4 локалей; плюс 4 пары `*.help`/`*.help.aria`. Итог посчитан явно: «11 новых × 4 локали минус 1 удалённый × 4» | | Low: «Release-артефакты» ссылаются на кадр `room-card` (View), а не на диалог настроек | **Закрыта.** Раздел переписан: указано, что ни один из 10 сценариев `demo/docs` диалог не открывает, приёмка — `npm run docs:accept -- --identical` на полном наборе | Тело issue, раздел `### Release-артефакты` (строки 143–147) | | Low: раздел «Проблема» не выделен явным заголовком | **Закрыта.** Добавлен явный `### Проблема` | Тело issue, строка 53 | ## Независимая проверка находок (не просто цитирование заявления автора) Каждое фактическое утверждение новой редакции сверено чтением кода/скриптов, а не принято на слово: - `src/editors/room-settings-dialog.ts:60` и `:93` — подтверждено: `room.settings_section` сегодня один заголовок покрывает и блок заливки, и блок источников (радиосписок заливки, `hp-color-opacity`, `roomTemperatureControls`, оба `_renderRoomSource`), а `room.sizes_section` стоит перед блоком масштабов — ровно то разбиение, которое описывает новая таблица. - `src/i18n/{en,ru,fr,de}.json:774` — `room.settings_section` = «Room settings (override the space)» / «Настройки комнаты (переопределяют пространство)» — текст совпадает с тем, что цитирует ТЗ. - `src/i18n/{en,ru,fr,de}.json:792` — `room.sizes_section` = «Font sizes» / «Размеры шрифтов» — совпадает с ТЗ, ключ обоснованно переиспользуется без нового. - `src/i18n/en.json:783-784` — `room.temp_range.help` / `room.temp_range.help.aria` существуют, подтверждает строку «переиспользуется без правок». - `src/houseplan-editor-runtime.ts:1263-1268` (`_help`) — контракт подтверждён дословно: сигнатура принимает `Extract`, сама строит `${key}.aria`, и при отсутствии перевода любой из двух возвращает `nothing` (ничего не рисует) — ровно то, что заявляет новый абзац про парность `.help`/`.help.aria`. - `test/i18n-dead-keys.test.mjs` — существует, сканирует только `src/**/*.ts` и красит тест на любом ключе словаря без потребителя в `src`; после удаления `room.settings_section` из `room-settings-dialog.ts` (единственного консьюмера в `src`) он должен быть удалён и из всех локалей, иначе именно этот тест покраснеет — заявление ТЗ подтверждено чтением реализации теста. - `demo/smoke_room_settings.mjs:72` — подтверждена точная строка: `c._t('room.settings_section')` используется как ожидаемый текст подписи. ТЗ явно объявляет, что эта строка будет заменена на проверку «четырёх заголовков групп» — то есть смок расширяется, а не просто перестаёт видеть удалённый ключ по случайности. Согласовано. - Арифметика раздела i18n перепроверена построчно: 3 новых заголовка (`group_basics/fill/sources`) + 4 новые пары `.help`/`.help.aria` (`group_basics`, `group_fill`, `group_sources`, `sizes_section`) = 3 + 8 = 11 новых ключей; минус `room.settings_section` (1 ключ) — итог, который называет ТЗ, сходится. - `demo/docs/screenshots.mjs` — подтверждено ровно 10 записей `id:` (`view-desktop`, `view-touch`, `space-create`, `room-contour-close`, `plan-context-tray`, `device-editor`, `device-display-preview`, `background-editor`, `room-card`, `device-info`, `pdf-export`), и сцена `room-card` использует `mode: 'view'` без `dialog` — диалог настроек комнаты она не открывает. Подтверждает и число «10», и заявление «не открывает ни один сценарий». - `scripts/check-docs.mjs:209` — отпечаток документации (`visualFingerprint`) считается от корня репозитория (включает `src/**`), что подтверждает переписанный вывод раздела «Release-артефакты» про полный, а не выборочный отпечаток. - Все файлы, перечисленные в «Плане автотестов» и AC как «без правок», существуют: `demo/smoke_room_settings.mjs`, `demo/smoke_help_affordance.mjs`, `demo/smoke_color_picker_consumers.mjs`, `demo/smoke_room_temperature_thresholds.mjs`, `demo/smoke_font_scales.mjs`, `demo/smoke_editor_tabs.mjs`, `demo/smoke_summary_panel.mjs`, `demo/smoke_summary_panel_polish.mjs`, `test/bundle-assets.test.mjs`, `test/editor-dialog-modules.test.mjs`; `INITIAL_VIEW_GZIP_CEILING` определена (`scripts/bundle-budget.mjs:294`). - `docs/TOUCH-SUPPORT.md:9-25` — подтверждает независимо унаследованное (не новое в этом раунде) заявление ТЗ «редактор desktop-first, деградация допустима»: Plan editor поимённо отнесён к «Reference editing environment / Best effort». Новых дефектов в переписанных фрагментах (i18n, Проблема, Release-артефакты) не найдено — ни одно фактическое утверждение не разошлось с кодом, арифметика ключей и подсчёт сценариев сошлись. ## Унаследовано из r2 (дельта их не касается) Дельта этого раунда локальна: три раздела текста (i18n, Release-артефакты, явный заголовок Проблема), без изменения контракта К1–К7, скоупа/не-скоупа, AC1–AC11 (кроме текстовой связки AC6 с новой i18n-таблицей — сверено выше, содержательно не изменилась), плана рисков и отката. Полный повторный аудит этих разделов не требуется по PROCESS.md §2.10 п.4, ниже — что именно наследуется и откуда: - К1 (ключи черновика), К2 (условия «Сохранить»), К3 (`hp-color-opacity`/событие), К4 (переезд пояснений под «?»), К5 (генератор со скоупом/префиксом), К6 (панель не рендерится в этом шаге), К7 (клавиатура сегментированного переключателя) — унаследованы из r1/r2, текст этих пунктов не менялся между материалом r2 и текущим телом. - Скоуп/не-скоуп, UX (группы и порядок полей), «Модель данных и миграция: нет» — унаследованы, без изменений текста. - AC1–AC5, AC7–AC11 — унаследованы; доказательства (`test/form-kit.test.mjs`, `smoke_room_settings.mjs`, `golden:verify`, `bundle:budget`, замороженная фикстура AC11) проверены r2 чтением кода и не затронуты правкой этого раунда. AC6 текстуально сверен заново (см. «Независимая проверка» выше), так как он напрямую ссылается на i18n-раздел. - Golden-сцены `room-temperature-dialog-{desktop-en,mobile-ru}` и соответствие диалога классу `roomdialog` — унаследовано из r2, повторно не перепроверялось (дельта не про golden). - Шесть вариантов заливки (`ROOM_FILL_MODES` + `fill.inherit`) — унаследовано из r2. - Согласие ТЗ с решениями владельца от 18.09 (набор+диалог одним issue; правка стилей панели разрешена, но перенос — следующим issue) — унаследовано, текст этих разделов не менялся. Источник наследования: `docs/reviews/SPEC-REVIEW-594-r2.md` (в репозитории, коммит `df7a62c8`), материал r2 — тело issue на момент `material_issue_body = 97f5a0277d2aee81abd986c24d874aa94949902428cc33bd2eb845990d48b37b`, дерево кода `7ce9e6437f25`. ## Находки этого раунда Нет. Единственная Medium-находка (i18n) закрыта содержательно, обе Low-находки закрыты. Новых дефектов в изменённых фрагментах не выявлено (см. «Независимая проверка» выше). ## Что проверено и корректно - Дельта установлена прямым сравнением текста (а не по признаку `edited` в таймлайне, который, как выяснилось в этом раунде, ненадёжен для issue). - Все фактические утверждения новой редакции i18n-раздела (имена ключей, тексты переводов, номера строк кода, поведение `_help()`, поведение `i18n-dead-keys.test.mjs`, номер строки смока) проверены самостоятельным чтением кода и совпали. - Арифметика счётчика ключей (11 новых × 4 локали минус 1 удалённый × 4) пересчитана и верна. - Число и состав сценариев `demo/docs` (10, без диалога комнаты) пересчитаны и верны. - ТЗ по-прежнему формально полно по всем обязательным разделам §7.1 и DoR §2.5: сценарий, что человек увидит, явная «Проблема», скоуп/не-скоуп, контракт К1–К7, UX, модель данных, i18n (полный список), AC1–AC11 с доказательством, план автотестов, риски, откат, release-артефакты, раздел принятых предположений. Открытых продуктовых вопросов к владельцу нет. ## Чего не проверял - Гейты кода (typecheck/test/build/golden/смоки) — этап spec, реализации ещё нет, гейты неприменимы к ревью ТЗ. - Полный повторный аудит K1–K7, AC1–AC5/AC7–AC11, скоупа, рисков «с нуля» — дельта их не касается, см. «Унаследовано из r2». - Не связывался с владельцем: находки этого раунда и предыдущих были техническими (полнота списка i18n-ключей, корректность ссылки на скриншот), решались автором и ревьюером без продуктовых вопросов. ## Вывод Дельта r3 — три локальных текстовых правки (i18n, Release-артефакты, заголовок «Проблема»), адресующие ровно находки r1/r2. Все три закрыты содержательно и подтверждены независимым чтением кода, а не приняты на слово. Новых находок правка не внесла. ТЗ формально полно, открытых продуктовых вопросов нет — задача готова к переходу в «Готово к разработке». **Вердикт: зелёный · заход r3 · блокирующих циклов 2/4 · High: 0 · Medium: 0** --- ## Материал раунда - Ветка: `dev`, коммит `df7a62c82ef0` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала: `88a9dda26ca79ae183fd194a408b9421b2eb9a24` ``` git log --all --format='%H %T' | grep 88a9dda26ca7 ``` - Тело issue: `594c7771e678dae203db75069c75806da3eec9c1d9b155a3d7ba2236d338052a` - Вердикт конвейера: `green` · High 0