Files
houseplan-card/docs/reviews/SPEC-REVIEW-226-r2.md
T
2026-08-20 18:48:01 +00:00

155 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-REVIEW — issue #226, цикл r2
- **Issue:** https://github.com/Matysh/houseplan-card/issues/226
- **ТЗ:** `docs/specs/226-entity-parent-dedup.md`, коммит `6162da8` (ветка
`issue/226-entity-parent-dedup`)
- **Предыдущий раунд:** r1, вердикт жёлтый, получен на коммите `5feabed`
(`docs/reviews/SPEC-REVIEW-226-r1.md`, назван явно в шапке документа — SHA
не пришлось искать отдельной находкой).
- **Трек:** обычный полный (не `small`), лимит циклов ревью ТЗ — 4
- **Ревьюер:** Claude (роль «Ревьюер ТЗ», отдельная сессия от автора)
- **Вердикт:** зелёный · цикл r2/4 · High: 0 · Medium: 0
## Скоуп проверки
Это второй цикл — по §2.10 PROCESS.md разбор ведётся по дельте, а не заново.
Дельта объявлена: `git diff 5feabed..6162da8`. Затронут ровно один файл
предмета ревью — `docs/specs/226-entity-parent-dedup.md`, плюс сам r1-документ
(не часть ТЗ). Дельта в ТЗ:
- §3.3 — одно уточняющее предложение о следствии правила «hidden sibling не
удерживает остаток»;
- §8 — одно уточняющее предложение о том же следствии применительно к
сценарию #94, плюс явное «это ожидаемое следствие Q2, а не обход
cover-first»;
- §12 — новый тест-кейс 14 (граница #94: видимая `entity:switch.reverse_direction`
+ hidden-only `cover.curtain`), старый кейс 14 (Switch as X browser fixture)
сдвинут на 15;
- AC4 — добавлена ссылка на новый кейс 14;
- AC7 — обновлена ссылка со старого номера 14 на новый номер 15.
Дельта локальна: не меняет контракт поведения (текст фиксирует то же решение
Q2, которое уже было принято владельцем в r1), не задевает новую подсистему,
не связана с ребейзом (`origin/dev` здесь не участвует, история линейная —
`3af0484 → a20dd54 → 5feabed → ecf9473 → 6162da8`). Полный разбор всего ТЗ не
требуется; проверке подлежит закрытие находки M1 и любые AC, чьё доказательство
эта дельта задевает — то есть только AC4 и AC7 (по номеру ссылки на тест-кейс,
без изменения самого доказательства AC7).
## Как проверялось
- `git diff 5feabed..6162da8` — построчно, весь diff (см. выше состав).
- Перечитаны актуальные редакции §3.3, §8, §12 (кейсы 12-15), AC4, AC7 в
`docs/specs/226-entity-parent-dedup.md` на коммите `6162da8` целиком, не
только diff-хунки — чтобы увидеть новый текст в контексте всего раздела, а не
выдернутым из соседних решений.
- `git log --oneline -5` — подтверждён линейный путь от `5feabed` (SHA r1) до
текущего HEAD `6162da8`, без ребейза и посторонних коммитов.
- Прочитаны все комментарии issue #226 после публикации r1: комментарий
вердикта r1 (жёлтый, M1) и ответный комментарий автора «Исправил
SPEC-REVIEW r1, M1 в `6162da8`» с перечислением четырёх правок — сверено
построчно с фактическим diff, расхождений нет.
- `grep` по всему файлу ТЗ на предмет устаревших ссылок на старую нумерацию
тест-кейсов после сдвига 14→15 — не найдено (AC4/AC7/§14 мутационного гейта
ссылаются на кейсы по номеру и/или по существу корректно, других мест,
ссылающихся на «кейс 14» в старом смысле, нет).
- Независимо (не по заявлению автора) перезапущены оба гейта документации,
которые автор указал в хендоффе: `git diff --check 5feabed..6162da8` → exit
0, чисто; `node scripts/check-docs.mjs --external` → `Documentation checks
passed (7 files, 10 external links)`, exit 0.
- Код гейты (`npx tsc --noEmit`, `npm test`, `npm run build`) не запускались:
стадия по-прежнему `S4-spec-review` (метки issue: `bug`, `P1`,
`S4-spec-review`), продуктовый код не существует — их предмет отсутствует, а
не отложен.
- Остальные разделы ТЗ (§1-2, §4-7 кроме дельты, §9-11, §13 кроме AC4/AC7,
§15-19) не перечитывались построчно повторно — их проверка унаследована из
r1 (см. раздел ниже), т.к. дельта их текст не меняет.
## Находки
Новых находок нет. Единственная находка r1 (M1) закрыта дельтой этого раунда
— см. таблицу ниже.
## Закрытие раунда r1
| Находка r1 | Чем закрыта | Где это видно |
|---|---|---|
| **M1** — комбинация «явный marker на видимую вспомогательную сущность + единственный оставшийся сиблинг скрыт HA и функционально первичен (сценарий #94)» не имела ни AC, ни теста, исход был неочевиден | (а) §3.3 получил явное предложение, фиксирующее исход: «если пользователь вынес видимую вспомогательную entity, а у родителя остался только HA-hidden функциональный sibling, auto-marker родителя исчезает»; (б) §8 получил зеркальное явное предложение применительно к #94 с явной пометкой «это ожидаемое следствие Q2, а не обход cover-first»; (в) §12 получил новый тест-кейс 14 с точным сценарием (видимый `switch.reverse_direction` + hidden-only `cover.curtain` → только entity-marker; явный `device:D` восстанавливает полную штору); (г) AC4 теперь явно ссылается на кейс 14 | `docs/specs/226-entity-parent-dedup.md:53-57` (§3.3), `:162-166` (§8), `:238-241` (§12, кейс 14), `:258-260` (AC4) на коммите `6162da8`; `git diff 5feabed..6162da8` показывает все четыре правки одним связным diff-хунком по каждому разделу |
Автор выбрал именно ту из двух альтернатив, что была предложена в r1 как
«если это осознанно принимается»: auto-marker исчезает, а не «cover-first
защита переживает это состояние». Это техническое решение автора о
формулировке правила (`PROCESS.md` §7.1 — решается вердиктом ревьюера, не
владельцем), и выбор согласуется с уже принятым default Q2 и с текстом,
который сам владелец одобрил в r1. Ревьюер согласен: решение сформулировано
явно, не как недосказанность, снабжено собственным тестом и не противоречит
ничему из принятых владельцем решений Q1-Q3.
## Что проверено и корректно (дельта этого раунда)
- Новый текст §3.3/§8 не вводит догадку, выданную за факт: оба предложения
прямо помечены как «следствие принято осознанно» / «ожидаемое следствие
Q2», то есть явно относятся к уже принятому владельцем решению, а не
изобретают новое продуктовое правило без него.
- Новый тест-кейс 14 однозначен и доказуем: два состояния (только
entity-marker после размещения; полная штора после добавления явного
`device:D`) с конкретными сущностями (`switch.reverse_direction`,
`cover.curtain`), не оставляет свободы трактовки.
- Ссылки AC4→кейс14 и AC7→кейс15 (после сдвига) корректны, других мест с
устаревшей нумерацией не осталось (проверено `grep`).
- Оба гейта документации, заявленные автором в хендоффе, воспроизведены
независимо и оба зелёные.
## Чего не проверял
- Полный текст ТЗ вне дельты (§1-2, §4-7 кроме тронутых предложений, §9-11,
§13 кроме AC4/AC7-ссылок, §15-19) — не перечитывался заново; принят
унаследованным из r1 (см. ниже), поскольку дельта этого текста не касается.
- Код `buildDevices()`/`seedHiddenBindings()` реализации по-прежнему не
существует — `npx tsc --noEmit`, `npm test`, `npm run build`, golden,
browser smoke, performance, mutation-gate не запускались: предмет код-ревью
(§2.7), не ревью ТЗ (§2.4), стадия не менялась.
- `docs/USER-GUIDE.ru.md`/`docs/USER-GUIDE.md`/`docs/FILTERING.md` как
release-артефакты будущей реализации — не проверялись повторно, дельта их
не трогает (это по-прежнему только план в §16 ТЗ).
## Унаследовано из r1
Документ: `docs/reviews/SPEC-REVIEW-226-r1.md`, SHA `5feabed`.
Принято без повторной проверки в этом раунде, так как дельта `5feabed..6162da8`
этого текста и вывода не касается:
- Соответствие ТЗ обязательным разделам §7.1 PROCESS.md (сценарий/персона,
что человек увидит, скоуп/не-скоуп, контракт поведения, модель данных и
совместимость, i18n, AC1…AC10 с доказательством, план автотестов, риски,
откат, release-артефакты) — все присутствуют по существу, отдельного
дефекта не найдено.
- Три продуктовых вопроса владельцу (Q1 partial ownership, Q2 `hidden_by`/#94,
Q3 асимметрия `device:D`/`entity:X`) заданы пачкой с default и получили явные
ответы до написания ТЗ — процесс §7.1 соблюдён.
- Причина дефекта в §3 ТЗ соответствует коду `src/devices.ts`
(`claimed.add(m.binding)` :1032, цикл авто-устройств :1039) и
`src/ha-binding-status.ts` (`hidden_by` не участвует ни в одной активной
проекции) — подтверждено построчным чтением в r1.
- Защита #94 сформулирована дословной цитатой канона `docs/FILTERING.md:190-217`
и получила отдельный регрессионный тест (кейс 8, нетронутое устройство).
- AC1…AC3, AC5, AC6, AC8, AC9, AC10 прослежены до конкретных тест-кейсов без
пропусков — вывод r1 остаётся в силе, дельта этих AC не касается.
- Алгоритм §6 (линейная сложность, запрет вложенного поиска), compatibility
§9 (нет миграции/схемы/wire protocol), touch/kiosk §17 (release-blocking по
`docs/TOUCH-SUPPORT.md`), track (обычный, не `small`) — выводы r1 остаются в
силе без повторной проверки.
- Раздел «Принятые предположения» §19 — признан техническими допущениями, не
подменой продуктового решения; дельта этого раздела не трогает.
- Mutation-gate §14 (два id вместо трёх из issue) — признан техническим
решением автора о стратегии тестов, не продуктовой догадкой; дельта этого
раздела не трогает.
## Вывод
M1 закрыт по существу, новых находок дельта не создала. ТЗ готово к статусу
«Готово к разработке» с точки зрения ревью ТЗ (формальный перевод статуса —
не предмет этого документа).