Files
houseplan-card/docs/reviews/SPEC-REVIEW-598-r2.md
T
2026-09-19 14:19:13 +00:00

22 KiB
Raw Blame History

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 (раздел ниже).

Как проверялось

  1. Прочитано текущее тело issue #598 целиком (gh issue view 598 --json body, 312 строк) и все 4 комментария (gh issue view 598 --json comments).
  2. Открыт архивный docs/reviews/SPEC-REVIEW-598-r1.md — проверено, что находка M1 сформулирована именно так, как её описывает текущий раздел «Закрытие раунда r1» ниже (сверка дословная).
  3. Построчно сверены места, где дельта обязана была появиться, с текущим текстом ТЗ:
    • К5 (новый контракт) присутствует и называет оба сообщения о состоянии поимённо со ссылкой на решение владельца;
    • УX-таблица «Общие настройки», строка «Солнце», явно оставляет gs.sun_missing callout'ом; У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, дальше сдвинуто на один без пропусков и дублей (сверено построчно, не на слово автора).
  4. Отдельно проверено новое наблюдение автора, не бывшее находкой 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 реально существует и действительно сливает оба словаря (файл присутствует в дереве), так что заявление «оставленная копия покраснит его» проверяемо, а не голословно.
  5. Терминология «карточки-группы» — уже используется docs/USER-GUIDE.ru.md:572 для диалога комнаты (#594); r1 это подтвердил, дельта термин не меняет — унаследовано.
  6. 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 body 2026-09-19, 312 строк — предмет этого раунда; официальный sha256 нормализованного тела для якоря пишет конвейер публикации, как и в r1 (issue #414), самостоятельный расчёт здесь не приводится во избежание расхождения метода нормализации с конвейером.
  • Комментарии issue на момент ревью: 4 (gh issue view 598 --json comments → length: 4) — вердикт r1, ответ автора (M1 + открытый вопрос), ответ владельца, финальный ответ автора.

Материал раунда

  • Ветка: dev, коммит ac1d25a08cb6 — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
  • Дерево материала: d80ad22ec697829c20bd27b1a0cd5bda4d600e55
    git log --all --format='%H %T' | grep d80ad22ec697
    
  • Тело issue: a81e7c46b347ae3eb2a0de35e30606c335c901733d52a04e1019a937a6d737fb
  • Вердикт конвейера: green · High 0