18 KiB
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), не смена контракта поведения (контракт
поведения — «ничего в рантайме не меняется» — не тронут), не задета новая
подсистема, объём сопоставим с тремя находками, которые он закрывает.
Полный повторный разбор не требуется; ниже — разбор по дельте плюс
целевая перепроверка того, до чего дельта дотягивается.
Как проверялось
- Найден вердикт r1 и SHA материала — оба названы в шапке
docs/reviews/SPEC-REVIEW-33-r1.md(8335191b), спорить не пришлось. - Объявлена дельта:
git diff 8335191b..1c1f9d8e -- docs/specs/033-config-schema-lifecycle.md(полный текст сверен построчно). - По каждой находке 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 закрыт полностью, не только в шапке).
- Перечитаны критерии приёмки AC1–AC7 целиком — ни один не ссылается на
статус
implementedили на старый контракт exit-кода: правка текста Блока 2/3 синхронизирована с разделом AC, который сам по себе делту не зафиксировал (он и не должен был — AC6 уже был сформулирован достаточно абстрактно, «различает exit-codes», и лишь уточнён числами 0/3/2). - Перечитан документ ревью r1 целиком (не только раздел «Находки») —
сверено, что раздел «Что проверено и корректно» r1 не полагался ни на
один факт, который ревизия 3 меняет (архитектура манифеста,
docs/SCOPE.md, §7.1-разделы, «уже реализовано жизнью» для show_all/weather_entity/ aspect/segments — ревизия 3 их не трогает, только меняет способ их фиксации в registry с несуществующего статуса на полеenforcedBy). - Дешёвые гейты:
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, раздел «Скоуп», SHA8335191b; - присутствие и полнота всех обязательных разделов §7.1 (сценарий, что
человек увидит, проблема, скоуп/не-скоуп, контракт, UX/i18n, модель
данных, AC, план тестов, риски, откат, release-артефакты, принятые
предположения) —
SPEC-REVIEW-33-r1.md, раздел «Что проверено и корректно», SHA8335191b; ревизия 3 не удалила и не переименовала ни один раздел (структура файла сверена при чтении ревизии 3 целиком в этом раунде, см. «Как проверялось» п.4–5, поэтому это скорее переподтверждено, чем чисто унаследовано); - архитектурное решение Блока 1 (манифест схемы генерируется из Voluptuous,
а не пишется руками на 212 путей) — не тронуто делтой, корректность
подтверждена в r1 чтением
scripts/config-field-registry.mjsиcustom_components/houseplan/validation.pyна SHA8335191b; - факты «show_all/weather_entity/aspect/segments уже реализованы кодом» —
подтверждены в r1 чтением
houseplan-card.ts:3895,houseplan-editor-runtime.ts:9618,validation.py:1590,1670на SHA8335191b; ревизия 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-кодов, точные имена команды и числа) с текущим деревом.
Новых находок делта не создала. Вердикт зелёный, ТЗ готово к разработке.