22 KiB
SPEC-REVIEW-598-r2
Issue: https://github.com/Matysh/houseplan-card/issues/598
Заголовок: Три оставшихся диалога настроек на общий набор контролов: Пространство, Общие,
Устройство (шаг 3 эпика #591)
Этап: ревью ТЗ (PROCESS.md §2.4)
Заход: r2 · блокирующих циклов израсходовано 1 из 4
Материал: тело issue #598, раздел ## ТЗ, снято gh issue view 598 --json body на момент
чтения 2026-09-19 (редакция текста — r3 по собственной нумерации автора; раунд ревью — r2, так
как редакции r2→r3 прошли под blocked без нового ревью). Комментариев к issue — 4: вердикт
конвейера r1, ответ автора на M1 (с открытым вопросом), ответ владельца, финальный ответ автора
со снятием blocked и заявкой S4-spec-review.
Скоуп ревью r2
По PROCESS.md §2.10 предмет повторного раунда — дельта, а не задача целиком. Прежний вердикт
(SPEC-REVIEW-598-r1.md, docs/reviews/) — единственная находка M1, Medium, в скоупе. Материал
того раунда объявлен в его блоке «Материал раунда»: ветка dev@958ab36652eb, дерево
232dd22abb22fc04ea01c124ac4332a6060a4fc8, блоб тела issue
aee54691f0fa3651f53c32dcb2934b5d0ebb983714e8c297783696b476976331. Код по issue не писался
(веток issue/598-* нет, git branch -a | grep 598 — пусто, HEAD на ac1d25a0 — это как раз
коммит публикации SPEC-REVIEW-598-r1.md, git status чист), поэтому дельта — только текст
тела issue между r1 и текущей редакцией.
Готового постраничного диффа тела issue GitHub не отдаёт (правки — не отдельные ревизии API, а
редактирование одного и того же issue body), поэтому дельта восстановлена по авторской записи:
комментарий «Ответ на жёлтый вердикт r1» построчно называет, что изменилось (М1, вторая находка
про словарь gs.hint, пересчёт счётчиков), а текущее тело issue сверено с этим перечнем построчно
— см. «Как проверялось» ниже. Это тот же метод доказательства, что использует сам конвейер для
git-дельты: не гадание, а сверка заявленного изменения с итоговым текстом.
Разбор остаётся по дельте: рёбейз/смена контракта/новая подсистема неприменимы к текстовому ТЗ, объём дельты (одна находка + одно сопутствующее наблюдение автора) несравним с объёмом всего ТЗ. Проверке заново подлежат ровно те разделы, которых касается дельта: К4, К5, УX-таблицы «Общие» и «Устройство», раздел i18n со счётчиками, риск №4, AC4, AC5. Остальные разделы (§7.1 полностью, К1–К3/К6–К8, AC1–AC3/AC6–AC11, скоуп/не-скоуп, классы риска §2.6, план автотестов, откат, release-артефакты) дельта не трогает — они наследуются из r1 (раздел ниже).
Как проверялось
- Прочитано текущее тело issue #598 целиком (
gh issue view 598 --json body, 312 строк) и все 4 комментария (gh issue view 598 --json comments). - Открыт архивный
docs/reviews/SPEC-REVIEW-598-r1.md— проверено, что находка M1 сформулирована именно так, как её описывает текущий раздел «Закрытие раунда r1» ниже (сверка дословная). - Построчно сверены места, где дельта обязана была появиться, с текущим текстом ТЗ:
- К5 (новый контракт) присутствует и называет оба сообщения о состоянии поимённо со ссылкой на решение владельца;
- УX-таблица «Общие настройки», строка «Солнце», явно оставляет
gs.sun_missingcallout'ом; УX «Устройство на плане» явно называет карточку («Действие по нажатию»), где остаётся callout'омmarker.run_target_gone, — то есть седьмое пояснение из r1-находки больше не висит без места; - раздел i18n предметно: «Итого 24 ключа, 96 строк» вместо прежних 26/104; таблица разбивки 12+12 ключей × 4 языка = 48+48 строк сходится арифметически (проверено умножением, не переписано на слово);
- список «переиспользуются и не удаляются» в i18n явно включает и
gs.sun_missing, иmarker.run_target_gone— они не попадают ни в один список переносимых ключей; - AC5 добавлен, доказательство — блок в смоках «Общих» и «Устройства» с фикстурой без
sun.sunи черновиком с несуществующей целью, страж — новый мутантstate-callout-hidden-under-help; - риск №4 переписан под этот же риск явно («соблазн спрятать предупреждение заодно... запрещено К5 и сторожится мутантом»);
- нумерация AC — пересчитана таблица ТЗ: AC1…AC11, встроен новый AC5, дальше сдвинуто на один без пропусков и дублей (сверено построчно, не на слово автора).
- Отдельно проверено новое наблюдение автора, не бывшее находкой r1: перенос
gs.hintизsrc/i18n/support/*.jsonв основной каталог какgs.card_fills.help.grep -rn "gs.hint\|gs\\.hint" src/и чтениеsrc/editors/general-settings-dialog.ts/src/i18n/support/*.jsonподтверждают заявленное — ключ реально живёт вsupport/*.jsonи читается черезsupportT(...), а_help()действительно резолвит${string}.helpчерез основной_t. Значит перенос текста между словарями, который называет ТЗ, — не выдумка, а реальное расхождение путей чтения;test/i18n-dead-keys.test.mjsреально существует и действительно сливает оба словаря (файл присутствует в дереве), так что заявление «оставленная копия покраснит его» проверяемо, а не голословно. - Терминология «карточки-группы» — уже используется
docs/USER-GUIDE.ru.md:572для диалога комнаты (#594); r1 это подтвердил, дельта термин не меняет — унаследовано. git branch -a,git log --oneline -3,git status— подтверждают отсутствие кода и то, что HEAD стоит ровно на коммите публикации r1-документа; материал для код-ревью по этому issue не существует, гейты (typecheck/test/build) неприменимы на этапе ревью ТЗ, как и в r1.
Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
M1 (Medium) — судьба marker.run_target_gone не решена; счётчик i18n «7 пояснений» расходится с 6 явно поимёнными парами «карточка → текст» |
Автор задал продуктовый вопрос владельцу (обязателен, т.к. решение 18.09 «под «?» уезжает всё» — продуктовое, распространять ли его на предупреждения — тоже продуктовый вопрос, а не только технический выбор варианта а/б, которые оба предложил r1); владелец ответил в комментарии: оба сообщения остаются видимыми callout'ами. ТЗ переписано: добавлен К5, AC5, УX-таблицы обеих форм явно называют карточку/место, где остаётся callout, риск №4 и мутант state-callout-hidden-under-help добавлены, счётчик i18n пересчитан на 24 ключа/96 строк |
К5 (строка «Сообщения о состоянии остаются на виду»); AC5 в таблице критериев; УX-таблица «Общие настройки» строка «Солнце» и «Устройство на плане» строка «Действие по нажатию»; раздел i18n «Итого 24 ключа, 96 строк»; раздел «Риски» пункт 4 |
Сопутствующее наблюдение автора (не было находкой r1, вскрыто при разборе M1) — gs.hint читается из support/*.json, а не из основного словаря; перенос под «?» — это перенос ключа между словарями, а не только разметки |
Явно описано отдельным разделом «gs.hint лежит в другом словаре»; в i18n-разделе прямо сказано: переезжает как gs.card_fills.help, копия в support удаляется во всех четырёх локалях, test/i18n-dead-keys.test.mjs покраснит при забытой копии |
Раздел «gs.hint лежит в другом словаре» в «Аналитике»; раздел i18n, абзац «Отдельно: gs.hint переезжает...» |
Оба пункта закрыты текстом ТЗ, а не заявлением «сделано»: место, счётчик и страж названы конкретно и проверяемы по самому тексту, без необходимости угадывать поведение реализации (ровно то, чего не хватало для AC4 в r1).
Унаследовано из r1
Без повторной проверки приняты выводы docs/reviews/SPEC-REVIEW-598-r1.md (материал: dev@
958ab36652eb, дерево 232dd22abb22fc04ea01c124ac4332a6060a4fc8), поскольку дельта r1→r2 их не
затрагивает:
- полнота обязательных разделов §7.1 (сценарий, что человек увидит, проблема, скоуп/не-скоуп, контракт поведения, УX, модель данных и миграция, i18n, AC, план автотестов, риски, откат, release-артефакты) — дельта не удаляла и не переименовывала ни один раздел, только правила К4, добавила К5 и AC5, пересчитала i18n;
- К1–К3, К6–К8 — запись в те же ключи, поведение сохранения/отмены,
hp-color-opacity, классы-опоры.srcrow/.dispsection/пр., клавиатура/44px, граф загрузки — не упомянуты дельтой, текст не менялся; - AC1–AC3, AC6–AC11 (нумерация до AC5 не сдвигается, после — сдвигается на один без потери содержания, проверено построчно в п.3 «Как проверялось») — доказательства и способы покраснения идентичны r1;
- скоуп/не-скоуп — идентичен, сверен построчно на этапе r1 с архивным
SPEC.mdэпика #591 и с #594 — дельта эту границу не трогает; - 11 golden-сцен AC8 (было AC7 в r1) — тот же список имён, дельта не добавляла и не убирала сцены;
- классы риска §2.6 — не переписывались;
- терминология «карточки-группы» (USER-GUIDE.ru.md:572) и минимум 44 px (TOUCH-SUPPORT.md) — не переписывались;
- существование примитивов набора (
form-kit.ts:formCard,formRow,segmented,colorRow) и факт, чтоhpf-switchв коде не существует и правильно помечен «принято предположительно», — дельта эти утверждения не касается.
Находки
Не найдено. Дельта закрывает M1 полностью и по существу (не декларативно): продуктовая часть вопроса ушла владельцу и получила прямой ответ, техническая часть (счётчики, место словаря) решена автором самостоятельно и корректно, с проверяемыми доказательствами. Новых догадок, выданных за факт, дельта не вносит — оба новых утверждения (перенос словаря, арифметика счётчиков) проверены по коду и по самому тексту таблиц, а не приняты на слово.
Что проверено и признано корректным
- М1 закрыт:
marker.run_target_goneявно назван callout'ом карточки «Действие по нажатию»,gs.sun_missing— callout'ом карточки «Солнце»; ни один не участвует в переносе под «?»; AC4 («абзацев-пояснений... не осталось») теперь непротиворечив относительно AC5 («сообщения о состоянии остались видимыми»), поскольку ТЗ явно развело термины «пояснение» и «сообщение о состоянии» и использует слово «callout» только для второго — код-ревьюеру не придётся гадать, что считается нарушением AC4. - Продуктовый вопрос действительно был продуктовым (что человек видит — предупреждение или скрытая подсказка) и действительно ушёл владельцу, а не решён автором за него; технический побочный вопрос (словарь) автор решил сам, как и предписывает §7.1 — граница между двумя видами вопросов соблюдена корректно.
- Счётчики i18n пересчитаны верно и согласуются с комментарием автора «было 26/104, стало 24/96» — проверено умножением по таблице, а не переписано на слово.
gs.hint/supportT/_help()/test/i18n-dead-keys.test.mjs— реальные пути в коде, наблюдение автора не является отвлечённым утверждением.- Материал раунда r1 (SHA
958ab36652eb, дерево, блоб тела issue) не осиротел:devне двигался вперёд относительно r1 непредвиденным образом, HEAD рабочей копии — коммит публикации того же документа; отдельная реставрация по дереву/блобу не потребовалась.
Чего не проверял
- Не проверял
fr-локаль на реальные значения строк (унаследовано из r1 — там же не проверялось предметно, только совпадение счётчика «4 языка» с существующими словарямиen/ru/de/fr). - Не сверял архивный
SPEC.mdэпика #591 построчно — он не входит в это репо (не найден ни поfind . -iname "SPEC.md", ни в файловой системе с иным путём), это внешний присланный документ; ТЗ и r1, и текущая редакция сознательно берут из него только раскладку, отклонённые части (смена поведения, компас, инлайн-цвет и т.д.) не входят в скоуп и не требуют сверки. - Не запускал
npm test/npm run typecheck/npm run build— кода по issue нет (веткиissue/ 598-*не существует), гейты неприменимы на этапе ревью ТЗ; они станут предметом код-ревью. - Не оценивал будущую формулировку
docs/USER-GUIDE.ru.mdдля новой раскладки трёх диалогов — этот документ обновляется на этапе кода (Release-артефакты ТЗ это явно называют), сейчас сверялась только терминологическая преемственность («карточки-группы»), не текст будущей правки.
Вердикт
Единственная находка предыдущего раунда закрыта по существу: продуктовый вопрос решён владельцем, техническое наблюдение — автором, оба с явными, проверяемыми следами в тексте ТЗ (К5, AC5, УX-таблицы, счётчики i18n, риск №4, новый мутант). Дельта не вносит новых High или Medium находок и не разрушает ни один вывод r1: наследуемые разделы не затронуты, а точки соприкосновения с дельтой (AC4/AC5, i18n-таблица) проверены заново и непротиворечивы. ТЗ готово к разработке.
Вердикт: зелёный · заход r2 · блокирующих циклов 1/4 · High: 0 · Medium: 0
Материал раунда
- Ветка:
dev, тот же коммит, что и в r1 —958ab36652eb(кода по issue #598 не появлялось между раундами); рабочая копия ревью —ac1d25a08cb6da1e4154e857df761504a7f79d1d(коммит публикацииSPEC-REVIEW-598-r1.md). - Тело issue снято
gh issue view 598 --repo Matysh/houseplan-card --json body2026-09-19, 312 строк — предмет этого раунда; официальный sha256 нормализованного тела для якоря пишет конвейер публикации, как и в r1 (issue #414), самостоятельный расчёт здесь не приводится во избежание расхождения метода нормализации с конвейером. - Комментарии issue на момент ревью: 4 (
gh issue view 598 --json comments→length: 4) — вердикт r1, ответ автора (M1 + открытый вопрос), ответ владельца, финальный ответ автора.
Материал раунда
- Ветка:
dev, коммитac1d25a08cb6— ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет. - Дерево материала:
d80ad22ec697829c20bd27b1a0cd5bda4d600e55git log --all --format='%H %T' | grep d80ad22ec697 - Тело issue:
a81e7c46b347ae3eb2a0de35e30606c335c901733d52a04e1019a937a6d737fb - Вердикт конвейера:
green· High 0