diff --git a/docs/reviews/SPEC-REVIEW-594-r3.md b/docs/reviews/SPEC-REVIEW-594-r3.md new file mode 100644 index 00000000..6fca18b2 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-594-r3.md @@ -0,0 +1,167 @@ +# 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