mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-02 04:38:55 +00:00
185 lines
18 KiB
Markdown
185 lines
18 KiB
Markdown
# 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-кодов, точные имена команды и числа) с текущим деревом.
|
||
Новых находок делта не создала. Вердикт зелёный, ТЗ готово к разработке.
|