mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 21:28:59 +00:00
155 lines
14 KiB
Markdown
155 lines
14 KiB
Markdown
# 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 закрыт по существу, новых находок дельта не создала. ТЗ готово к статусу
|
||
«Готово к разработке» с точки зрения ревью ТЗ (формальный перевод статуса —
|
||
не предмет этого документа).
|