From 1e0e7ccf21441cbb522706e8209ac34d8c18299b Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 09:33:39 +0000 Subject: [PATCH] docs: review document for #33 Issue: #33 User-Visible: no --- docs/reviews/SPEC-REVIEW-33-r2.md | 184 ++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 docs/reviews/SPEC-REVIEW-33-r2.md diff --git a/docs/reviews/SPEC-REVIEW-33-r2.md b/docs/reviews/SPEC-REVIEW-33-r2.md new file mode 100644 index 00000000..26f40a48 --- /dev/null +++ b/docs/reviews/SPEC-REVIEW-33-r2.md @@ -0,0 +1,184 @@ +# SPEC-REVIEW #33 — r2 + +- Issue: https://github.com/Matysh/houseplan-card/issues/33 +- Этап: ревью ТЗ (PROCESS.md §2.4) +- ТЗ: `docs/specs/033-config-schema-lifecycle.md`, ревизия 3 +- SHA материала: `1c1f9d8ea4a3e2f32c5cd6150dde5e08bdfc280b` +- Заход: r2 · блокирующих циклов израсходовано 1 из 4 (r1 — жёлтый, потратил + цикл; зелёный вердикт этого раунда цикла не образует, #227) +- Вердикт: **зелёный** + +## Скоуп + +Ревизия 3 — точечный ответ на три Medium-находки и два Low прошлого раунда +(SPEC-REVIEW-33-r1, SHA `8335191b`), ничего сверх этого. Продуктовая рамка, +класс задачи (A, schema-потребители), трек (полный) и оценка аналитики не +пересматриваются — они не были предметом находок r1 и делта их не задевает. + +Дельта — ровно один файл, `docs/specs/033-config-schema-lifecycle.md`, +53 изменённые строки (34 добавлено / 19 удалено), подтверждено +`git diff 8335191b..1c1f9d8e --stat`. Рядом в дереве `src/**` и +`custom_components/**` не менялись с базового SHA r1 (`git diff --stat +8335191b..HEAD -- src/ custom_components/ package.json` пуст) — значит, +ничего из подтверждённого чтением кода в r1 не могло протухнуть за это +время. Делта локальна по критерию §2.10: не ребейз (HEAD ровно на один +docs-коммит впереди материала r1), не смена контракта поведения (контракт +поведения — «ничего в рантайме не меняется» — не тронут), не задета новая +подсистема, объём сопоставим с тремя находками, которые он закрывает. +Полный повторный разбор не требуется; ниже — разбор по дельте плюс +целевая перепроверка того, до чего дельта дотягивается. + +## Как проверялось + +1. Найден вердикт r1 и SHA материала — оба названы в шапке + `docs/reviews/SPEC-REVIEW-33-r1.md` (`8335191b`), спорить не пришлось. +2. Объявлена дельта: `git diff 8335191b..1c1f9d8e -- docs/specs/033-config-schema-lifecycle.md` + (полный текст сверен построчно). +3. По каждой находке r1 (M1, M2, M3, L1, L2) — отдельная проверка чтением + текущего дерева, что предложенное в ревизии 3 решение не просто иначе + сформулировано, а технически состоятельно (не только «текст ТЗ звучит + иначе», а «то, что он теперь обещает, совместимо с кодом, которого + касается»): + - `scripts/config-field-registry.mjs` — прочитан целиком; подтверждено, + что поля `enforcedBy` и `schema: 'allow-extra'` в текущей форме записей + нет (свободны для добавления), что `CONFIG_FIELD_STATUSES` остался + тем же перечислением из 6 значений (ревизия 3 их не трогает — точно + то, что требовало M1), что записей сейчас 27 + (`node --input-type=module` импорт и `.length`), и что ни одна из + четырёх «новых» ID-записей (`decor_default_style`, `furniture`, + `host=partition`) ещё не существует в registry — делта не дублирует; + - `src/logic.ts:898-919` — `SPACE_FILL_MODES`/`ROOM_FILL_MODES`/ + `DISPLAY_MODES`/`TAP_ACTIONS` существуют и экспортируются, как и + утверждает исправленный текст (только 3 из 7 пар); + - `src/types.ts:212`, `src/plan-optimizer.ts:285`, + `src/zero-walls.ts`/`houseplan-editor-runtime.ts`/ + `houseplan-onboarding-runtime.ts` (литералы `'dashed'`/`'solid'`), + `custom_components/houseplan/validation.py:1254` (`_BG_MODE`) — + подтверждено, что для `opening.type`, `vacuum.trail_mode`, + `zero_wall_style`, `bg_mode` сегодня нет ни одной именованной + экспортируемой frontend-константы (ровно то, что M2 требовал признать + явно) и что предложенные имена `OPENING_TYPES`, `VACUUM_TRAIL_MODES`, + `ZERO_WALL_STYLES`, `BG_MODES` не заняты (`grep` по `src/*.ts` — пусто), + то есть план не столкнётся с коллизией имён при реализации; + - `scripts/config-audit.mjs` (всё, 103 строки) — подтверждено, что + `process.exitCode` сегодня выставляется только на ветках ошибок + разбора (74/79/102), никогда от найденных полей; что код `1` нигде не + занят и не проверяется ни одним потребителем (`grep` по `package.json` + и `.github/workflows/*.yml` на `audit:config`/`config-audit` — только + объявление npm-скрипта, никакого CI-потребления exit-кода), то есть + новый контракт `0/3/2` ревизии 3 не конфликтует с существующим + поведением или скрытым потребителем; заодно перечитан сам факт: `2` + сегодня — единственный ненулевой код, значит выбор `3` для нового + смысла действительно не сталкивается с ним, как и заявляет текст; + - `package.json:19` — `"audit:config": "node scripts/config-audit.mjs"`, + текст ТЗ теперь везде цитирует именно эту команду (L1 закрыт); + - весь файл ТЗ ревизии 3 — построчный поиск «24» не находит ни одного + оставшегося упоминания старого числа, все вхождения — «27» (L2 закрыт + полностью, не только в шапке). +4. Перечитаны критерии приёмки AC1–AC7 целиком — ни один не ссылается на + статус `implemented` или на старый контракт exit-кода: правка текста + Блока 2/3 синхронизирована с разделом AC, который сам по себе делту не + зафиксировал (он и не должен был — AC6 уже был сформулирован достаточно + абстрактно, «различает exit-codes», и лишь уточнён числами 0/3/2). +5. Перечитан документ ревью r1 целиком (не только раздел «Находки») — + сверено, что раздел «Что проверено и корректно» r1 не полагался ни на + один факт, который ревизия 3 меняет (архитектура манифеста, `docs/SCOPE.md`, + §7.1-разделы, «уже реализовано жизнью» для show_all/weather_entity/ + aspect/segments — ревизия 3 их не трогает, только меняет способ их + фиксации в registry с несуществующего статуса на поле `enforcedBy`). +6. Дешёвые гейты: `npx tsc --noEmit` на HEAD (`1c1f9d8e`) — чисто, 0 ошибок. + +## Закрытие раунда r1 + +| Находка r1 | Чем закрыта | Где видно | +|---|---|---| +| **M1** — статус `implemented` не существует ни в перечислении, ни в `CONFIG_COMPATIBILITY.md` | Статусная модель не меняется; вместо нового статуса — опциональное поле `enforcedBy` (ссылка на кодовую точку/тест), новые паспорта получают существующий статус `current` | `docs/specs/033-config-schema-lifecycle.md:80-90` (Блок 2, абзац «Актуализация registry как данных»); подтверждено чтением, что `CONFIG_FIELD_STATUSES` (`scripts/config-field-registry.mjs:362-369`) и поле `enforcedBy` совместимы (поля с таким именем в записях сегодня нет) | +| **M2** — 4 из 7 frontend-констант для parity-теста не существуют | Текст явно называет 3 готовые пары отдельно от 4 отсутствующих и описывает их как новую работу этого issue: экспортируемые `as const`-массивы `OPENING_TYPES`/`VACUUM_TRAIL_MODES`/`ZERO_WALL_STYLES`/`BG_MODES`, из которых выводятся существующие union-типы | `docs/specs/033-config-schema-lifecycle.md:59-68` (Блок 2, первый абзац); подтверждено, что ни одно из четырёх имён не занято в `src/*.ts` | +| **M3** — AC6/Блок 3 описывали несуществующее поведение `config-audit.mjs` как «расширение теста» | Явно зафиксирован новый контракт exit-кодов: `0` clean, `3` migration available, `2` invalid (без изменений), с обоснованием выбора `3`, чтобы не конфликтовать с текущим `2`; AC6 переформулирован под тот же контракт | `docs/specs/033-config-schema-lifecycle.md:101-107` (Блок 3, последний абзац) и `:147-148` (AC6); подтверждено чтением `scripts/config-audit.mjs`, что код `1` сегодня свободен и не потребляется CI | +| **L1** — команда в «Что человек увидит» названа неверно (`config:audit` вместо `audit:config`) | Текст исправлен на точное имя npm-скрипта | `docs/specs/033-config-schema-lifecycle.md:22`; сверено с `package.json:19` | +| **L2** — «registry = 24 записи» разошлось с фактическим размером массива (27) | Все вхождения числа в шапке и в разделе «Проблема» заменены на 27 | `docs/specs/033-config-schema-lifecycle.md:8,27`; сверено подсчётом `CONFIG_FIELD_REGISTRY.length` на HEAD — 27; поиском по файлу подтверждено отсутствие оставшихся «24» | + +Все пять находок закрыты правкой текста в пределах ревизии 3, без изменения +архитектуры Блока 1 и без обращения к владельцу — как и предполагал вердикт +r1. + +## Унаследовано из r1 + +Следующее принято без повторной проверки — делта его не задевает, и ничего +в дереве (src/**, custom_components/**) с SHA `8335191b` не изменилось: + +- соответствие `docs/SCOPE.md` (задача — защитная инфраструктура под J6, не + претендует на пользовательскую ценность) — `SPEC-REVIEW-33-r1.md`, раздел + «Скоуп», SHA `8335191b`; +- присутствие и полнота всех обязательных разделов §7.1 (сценарий, что + человек увидит, проблема, скоуп/не-скоуп, контракт, UX/i18n, модель + данных, AC, план тестов, риски, откат, release-артефакты, принятые + предположения) — `SPEC-REVIEW-33-r1.md`, раздел «Что проверено и + корректно», SHA `8335191b`; ревизия 3 не удалила и не переименовала ни + один раздел (структура файла сверена при чтении ревизии 3 целиком в этом + раунде, см. «Как проверялось» п.4–5, поэтому это скорее переподтверждено, + чем чисто унаследовано); +- архитектурное решение Блока 1 (манифест схемы генерируется из Voluptuous, + а не пишется руками на 212 путей) — не тронуто делтой, корректность + подтверждена в r1 чтением `scripts/config-field-registry.mjs` и + `custom_components/houseplan/validation.py` на SHA `8335191b`; +- факты «show_all/weather_entity/aspect/segments уже реализованы кодом» — + подтверждены в r1 чтением `houseplan-card.ts:3895`, + `houseplan-editor-runtime.ts:9618`, `validation.py:1590,1670` на SHA + `8335191b`; ревизия 3 меняет только способ их фиксации в данных + (`enforcedBy` вместо статуса), не сам факт; +- необходимость заглушек родительских пакетов для импорта `validation.py` + без `homeassistant` — воспроизведено в r1 (`ModuleNotFoundError`), делта + этого блока не касается; +- формулировка не-скоупа (`group_lights`/`exclude_integrations` → #44) — + не менялась. + +## Что проверено и корректно + +- Все пять находок r1 закрыты по существу, а не только по формулировке: + каждое новое обещание текста (поле `enforcedBy`, четыре новых экспорта, + контракт exit-кодов 0/3/2, точное имя npm-скрипта, число 27) сверено с + текущим деревом и не встречает коллизии имён, полей или уже занятого + значения. +- AC1–AC7 остаются согласованными с телом ТЗ после правки: ни один AC не + ссылается на отменённый статус `implemented` или на прежний + недоопределённый контракт exit-кода; AC6 обновлён в паре с текстом Блока 3. +- Числа в шапке (`212`, `2`, `27`) внутренне согласованы по всему файлу — + расхождений вида «одно число, два значения» не осталось (единственная + такая находка прошлого раунда, L2, закрыта полностью). +- Делта не расширяет скоуп: три новых абзаца — это уточнение уже + анонсированных в ревизии 2 блоков, а не новая работа сверх исходного ТЗ. + +## Чего не проверял + +- Не проверял по существу архитектурные решения, не затронутые находками + r1 (Блок 1 целиком, фикстуры Блока 3 кроме контракта exit-кода, раздел + «Риски») — они не входят в дельту и не изменились со SHA `8335191b`; + доверие — по разделу «Унаследовано из r1» выше, не молчаливое. +- Не гонял `npm test`, `npm run build`, `node scripts/check-docs.mjs` — + diff раунда docs-only (подтверждено `git diff --stat`), `src/**` не + тронут, эти гейты не сказали бы ничего нового о ревизии ТЗ (то же + основание, что в r1). +- Не гонял смоки, golden, инварианты модели, performance — этап ТЗ, кода + ещё нет, ни один из этих гейтов не применим. +- Не проверял заново оценки сложности/риска и продуктовую ценность из + комментариев аналитики — не предмет ревью ТЗ, не изменились в этом + раунде. + +## Гейты — сводка + +| Гейт | Прогнан | Результат | +|---|---|---| +| `npx tsc --noEmit` | да, на SHA `1c1f9d8e` | чисто, 0 ошибок | +| `npm test` | нет | diff docs-only, src/** не тронут | +| `npm run build` | нет | то же | +| `node scripts/check-docs.mjs` | нет | diff не касается `src/**` | +| смоки / golden / инварианты / perf | нет | этап ТЗ, продукт не меняется | + +## Итог + +0 High, 0 Medium, 0 Low. Все пять находок r1 закрыты состоятельно — +проверено не только чтение нового текста, но и совместимость каждого +нового обещания (поле `enforcedBy`, четыре новых frontend-константы, +контракт exit-кодов, точные имена команды и числа) с текущим деревом. +Новых находок делта не создала. Вердикт зелёный, ТЗ готово к разработке.