Files
houseplan-card/docs/reviews/SPEC-REVIEW-29-r2.md
T
2026-08-27 23:17:52 +00:00

15 KiB
Raw Blame History

SPEC-REVIEW-29-r2

  • Issue: https://github.com/Matysh/houseplan-card/issues/29
  • Этап: spec (PROCESS.md §2.4)
  • Заход: r2 · блокирующих циклов израсходовано 1 из 4
  • ТЗ: docs/specs/029-device-inbox-lifecycle.md
  • SHA предыдущего вердикта (r1): a6ce1ae7e534fa4b41fcc0ab93e5ed95a693c4c1
  • SHA материала этого раунда: 375b402d940a0ea30f23becef95f9755212ecbd9 (ветка issue/29-device-inbox-lifecycle, коммит «docs: preserve hidden device ghost mode»)
  • Трек: обычный, лимит циклов ревью ТЗ — 4.

Скоуп разбора (по дельте, PROCESS.md §2.10)

Предыдущий вердикт (r1, документ docs/reviews/SPEC-REVIEW-29-r1.md) — жёлтый, две находки Medium в скоупе (M1, M2), High нет. Автор ответил комментарием в issue со ссылкой на коммит 375b402b (фактический SHA — 375b402d, см. выше) и заявил закрытие обеих находок.

Дельта — git diff a6ce1ae7e534fa4b41fcc0ab93e5ed95a693c4c1..HEAD по файлу ТЗ: 36 добавленных / 11 удалённых строк, все — в §10.1, §10.2, §10.3, §10.4, §14, AC1, AC4, AC6, §18 (риски). Дельта локальна: один документ, правки адресуют ровно M1 и M2, новая подсистема не затронута, поведенческий контракт вне уже согласованных Q1/AC не меняется, объём дельты не сопоставим с объёмом исходного ТЗ (548 строк). Условия «разбор остаётся полным» (ребейз на ушедший вперёд dev, смена контракта, новая подсистема, сопоставимый объём) не выполнены — сокращаю объём разбора до дельты и её последствий для AC1, AC4, AC6, §14, §18.

Продуктового кода на этом этапе нет, гейты §8 к ревью ТЗ не относятся (как и в r1).

Закрытие раунда r1

Находка r1 Чем закрыта Где это видно
M1 (Medium, в скоупе) — §10.1 убирал существующий режим просмотра скрытых/HA-disabled маркеров призраками на плане, не давая эквивалента в каталоге (Find работал только для реально отрисованного marker) Автор не выбрал ни один из трёх предложенных путей закрытия буквально, а снял противоречие в корне: существующий локальный ghost-режим сохранён целиком (позиция, выбор, настройка, drag), его переключатель просто переносится с панели внутрь каталога как новый switch «Показывать скрытые на плане», доступный во всех вкладках. Find для скрытых/HA-disabled строк теперь доступен при включённом ghost-режиме (было — недоступен вовсе) docs/specs/029-device-inbox-lifecycle.md §10.1 (новый абзац «Существующий локальный режим… сохраняется»), §10.2 п.6 (новый switch), §10.3 (столбец «Дополнительные действия» для трёх категорий — «Найти призрак при включённом ghost-режиме»), §10.4 (переписанное условие доступности Find), AC1 («Локальный ghost-toggle доступен внутри каталога, а его активность видна на кнопке «Устройства»»), AC4 (переписан), AC6 (добавлен абзац с явным описанием эквивалентности старому поведению), §18 (новая строка риска с защитой)
M2 (Medium, в скоупе) — marker.hide_tip (ru/en) ссылался на удаляемую кнопку «Скрытые и деактивированные» / «Hidden and disabled», §14 не включал обновление существующих строк §14 получил новый абзац: marker.hide_tip обновляется на обеих языках, чтобы вести в каталог «Устройства», плюс явное требование поиска прочих ссылок на старые названия кнопок перед реализацией docs/specs/029-device-inbox-lifecycle.md §14, новый абзац сразу после списка тестируемых строк i18n

Обе находки закрыты по существу, а не декларативно: текст, который был предметом претензии (удаление режима просмотра позиции; необновлённая подсказка), в текущей редакции отсутствует, проверено чтением файла целиком, а не поиском одной фразы.

Проверка дельты

  • AC1 (golden + smoke): формулировка «активность видна на кнопке «Устройства»» — проверяемое поведение (класс/атрибут кнопки для smoke, визуальное состояние для golden), метод доказательства не изменился и остаётся адекватным.
  • AC4 (unit): новая формулировка «Show недоступен, а Find доступен только для призрака при включённом ghost-режиме» согласована с §10.3/§10.4 той же дельты — противоречий нет.
  • AC6 (smoke): добавленный абзац описывает переключатель ghost-режима как воспроизводящий текущее поведение 1:1 (позиция/выбор/настройка/drag, без изменения marker.hidden, сброс при выходе из редактора) — это то же утверждение, что и в §10.1, не новое обязательство.
  • §14 (i18n): новый пункт обязывает обновить marker.hide_tip в обоих языках и найти прочие ссылки на старые названия кнопок. Точечно перепроверено по коду (не только по тексту ТЗ): src/i18n/ru.json:673 и src/i18n/en.json:673 — единственная пара строк с буквальной ссылкой на удаляемую кнопку (тот же результат, что и в r1); title.show_all и devbar.show_all и так входят в объём замены по §10.1 и отдельного упоминания не требуют.
  • §18 (риски): новая строка «Перенос ghost-toggle делает активный режим незаметным после закрытия каталога» ссылается на AC6 как на защиту, но видимое active-state кнопки описано в AC1, а не в AC6 — см. находку L1 ниже.

Остальные AC (AC2, AC3, AC5, AC7–AC11) дельтой не задеты текстуально и не зависят по доказательству от изменённых разделов — наследую вывод r1 без повторной проверки (см. «Унаследовано»).

Находки

L1 (Low) — риск в §18 ссылается не на тот AC

Файл: docs/specs/029-device-inbox-lifecycle.md, §18, строка риска «Перенос ghost-toggle делает активный режим незаметным после закрытия каталога».

Защита названа как «Активное состояние кнопки «Устройства» и сброс при выходе из редактора; AC6». Однако видимое active-state кнопки «Устройства» описано в AC1 («его активность видна на кнопке «Устройства»»), а не в AC6 (AC6 — про воспроизведение самого ghost-поведения: позиция/выбор/drag). Сброс режима при выходе из редактора действительно упомянут в AC6 — ссылка верна только для половины защиты.

Не создаёт двусмысленности AC и не блокирует реализацию: оба AC (AC1 и AC6) существуют, проверяемы и в сумме покрывают заявленную защиту — перепутана только адресация в таблице рисков.

Решение ревьюера: снимается без правки текста ТЗ. Основание — PROCESS.md §2.4 «Low либо правится, либо снимается решением ревьюера с записью»: неверная перекрёстная ссылка в информационной таблице рисков не меняет ни один AC, не вводит в заблуждение исполнителя относительно того, что защищает риск (только относительно того, под каким номером это искать), и правка не стоит очередного цикла ревью на light-независимой задаче с уже потраченным одним из четырёх циклов.

Унаследовано из r1

Документ: docs/reviews/SPEC-REVIEW-29-r1.md, SHA a6ce1ae7e534fa4b41fcc0ab93e5ed95a693c4c1. Принято без повторной проверки в r2, поскольку дельта их не касается:

  • Соответствие docs/SCOPE.md (job J4/J6, персона Home admin, отсутствие выхода за продуктовую рамку, Не входит §6).
  • Формальная полнота §7.1 (все обязательные разделы присутствуют).
  • AC1–AC11 однозначны, у каждого назван способ доказательства (кроме точечных правок AC1/AC4/AC6, разобранных выше в этом раунде).
  • Корректность отражения решения владельца по Q1 в §7.2 и AC3.
  • Проверка фактических утверждений о текущем поведении кодом и каноном: _bindingCandidates, HaBindingStatus.kind, marker.hidden/marker.removed, .slice(0, 200) кап, duplicate_name_area устарела, фильтрация new_device_ids от уже скрытых id, терминология «Добавить»/«Правила иконок».
  • §21 «Принятые технические предположения» — маркировка предположений корректна и отделена от продуктовых решений (кроме пробела M1, который в r2 закрыт не через §21, а прямым сохранением поведения — что делает сам вопрос неактуальным: решать стало нечего, поведение не меняется).
  • Существование тестовых артефактов: test/devices.test.mjs, test/ha-binding-status.test.mjs, test/device-presentation*.test.mjs, demo/smoke_hidden_flag.mjs, demo/smoke_binding_picker.mjs, scripts/smoke-select.mjs.
  • Откат (§19) реалистичен, обратно совместим.

Что проверено и признано корректным (в этом раунде)

  • M1 и M2 закрыты по существу — см. таблицу выше.
  • Новый текст §10.1–§10.4 и AC1/AC4/AC6 внутренне непротиворечив: описание условия доступности Find (§10.4) совпадает с формулировками в таблице действий (§10.3) и в AC4.
  • Новая формулировка marker.hide_tip (замена ссылки на кнопку) не создаёт нового расхождения с src/i18n/*.json — единственная затронутая пара строк подтверждена прямым чтением файлов.
  • Старый (ошибочный) текст §10.1 «Скрытые markers больше не рисуются…» и «устраняет состояние панели» полностью удалён из документа — проверено grep по всему файлу, совпадений нет.
  • Терминология не расходится с docs/USER-GUIDE.ru.md/FILTERING.md: старое «Скрытые и деактивированные» (панель) и новое «Показывать скрытые на плане» (switch внутри каталога) — разные элементы UI с разной областью действия, противоречия нет; обновление USER-GUIDE уже стоит в §20 Release-артефакты.

Чего не проверял

  • Не повторял полную сверку §7.1/AC1–AC11 с кодом — она выполнена в r1 и дельта её не аннулирует (см. «Унаследовано»).
  • Не запускал никакие гейты (typecheck/test/build/смоки/check-docs) — на этапе ТЗ продуктового кода нет, диф не затрагивает src/**, гейты §8 относятся к код-ревью.
  • Не проверял docs/ARCHITECTURE.md/docs/CANVAS.md — дельта их не касается.
  • Не оценивал заново перформанс (§17 дельтой не затронут).

Вердикт

High-находок нет. Обе Medium-находки r1 закрыты по существу и подтверждены чтением текущего файла, а не заявлением автора. Единственная новая находка этого раунда — Low, снята решением ревьюера с записью, без возврата на правку.

Вердикт: зелёный. ТЗ переходит в «Готово к разработке».