docs: review document for #448

Issue: #448
User-Visible: no
This commit is contained in:
claude[bot]
2026-09-04 16:20:34 +03:00
committed by Sergey Matyunin
parent ed0fdd4859
commit e846833ed6
+181
View File
@@ -0,0 +1,181 @@
# SPEC-REVIEW-448-r1
- Issue: [#448](https://github.com/Matysh/houseplan-card/issues/448) — Labs: единый бессрочный переключатель `hp_alpha` для экспериментальных функций
- ТЗ: `docs/specs/448-alpha-switch.md` (SHA `aa72704a`)
- Трек: полный (лёгкий явно отклонён аналитикой: «меняются долговременный compatibility-контракт и несколько runtime/test/documentation поверхностей»)
- Этап: `S4-spec-review` · заход r1 · блокирующих циклов израсходовано 0 из 4 (до этого вердикта)
- Ревьюер ≠ автор ТЗ (Codex); эта сессия не участвовала в написании ТЗ.
## Скоуп
Диапазон, вынесенный на ревью, — только документация: `git diff origin/dev...HEAD`
даёт два файла, `docs/specs/448-alpha-switch.md` (новый, 260 строк) и одну
строку в `docs/specs/README.md` (реестр ссылок issue↔ТЗ). Продуктовый код не
менялся — верно для стадии `S4-spec-review`, где менять `src/**`/
`custom_components/**` запрещено правилом №1 до `S5-ready`. Коммит `aa72704a`
несёт трейлеры `Issue: #448` и `User-Visible: no` — корректно, поведение ещё не
изменилось.
Задача продолжает прямо одобренное узкое 2.5D-исключение из `docs/SCOPE.md`
(единственный прецедент `#89`) и служит J1: она не строит новую функцию, а
чинит контракт включения уже принятого Stage 1/2 изометрического View,
испорченный version-expiry в `src/labs.ts`. Из «не-скоуп» разделов SCOPE.md
задача не задевает ничего — доступ к experimental-переключателю остаётся
скрытым, публичного 3-D запуска и новых редакторов ТЗ не вводит.
## Как проверялось
1. Прочитаны `docs/SCOPE.md`, `AGENTS.md`, `PROCESS.md` (§1–§10.4 включительно).
2. Прочитаны тело issue #448 и все три комментария (аналитика, вопросы
владельцу, решения владельца со ссылкой на ТЗ).
3. Прочитан канонический `docs/ISOMETRIC.md` (текущий контракт `iso`/Labs,
which `hp_alpha` заменяет) и `docs/UX-MODES.md` (раздел Kiosk mode) —
подсистема, которую задевает пункт «full-card View и kiosk gate».
4. Прочитан действующий `src/labs.ts` целиком и потребители Labs в
`src/houseplan-card.ts` (grep по `iso|Labs|labs`, ~40 точек использования:
`_labsIso`, `_desiredProjection`, `_setProjection`, `_effectiveProjection`,
projection-toggle кнопка, `noteLabsRender`) — чтобы отличить утверждения ТЗ
о текущем поведении от догадок.
5. Сверены i18n-ключи `view.flat`/`view.volumetric` в `src/i18n/{ru,en}.json`
с прозой ТЗ («Плоский / 3-D»).
6. Проверено `docs/CONFIG-COMPATIBILITY.md` (сфера действия — persisted-поля
схемы плана, не browser-local Labs storage) — подтверждено, что раздел
«Модель данных и миграция» ТЗ корректно объявляет её вне применимости этого
реестра.
7. Проверено `docs/TOUCH-SUPPORT.md` (product contract: View — touch-first,
kiosk — primary supported environment) на предмет обязательного пункта DoR
§2.5 «влияние на touch… View и киоск — блокирующие».
8. Проверены обязательные разделы §7.1 построчно по тексту ТЗ.
9. `git show aa72704a --stat` и `-s --format=full` — трейлеры и состав коммита.
Гейты кода (`typecheck`/`test`/`build`/`check-docs`) не прогонялись: диапазон
не касается `src/**` и `custom_components/**`, только `docs/**`; на этой
стадии они не гейт ревью ТЗ. `check-docs.mjs`, о котором автор отчитался в
issue, тоже не относится к «правкам src» — но и не вредит, лишний прогон.
## Находки
### Medium (в скоупе задачи — правится в текущем ТЗ)
**M1. ТЗ не закрывает обязательный пункт DoR «влияние на touch» (`docs/TOUCH-SUPPORT.md`).**
- Файл: `docs/specs/448-alpha-switch.md`
- PROCESS.md §2.5 требует для перехода в «Готово к разработке»: «влияние на
touch по `docs/TOUCH-SUPPORT.md` (View и киоск — блокирующие)», названо явно
или явным «нет». `docs/TOUCH-SUPPORT.md` фиксирует View как **touch-first,
обязательный к полной поддержке**, а kiosk — как «primary supported
environment»: любой тач-дефект в этих поверхностях — не допустимая
деградация, а дефект продукта.
- В тексте ТЗ (проверено построчным поиском `touch|Touch|сенсор` —
ноль совпадений) нет ни одной строки о touch. Задача прямо называет
затронутой поверхностью «full-card View и kiosk gate» (аналитика) и пункт 13
контракта возвращает в View именно интерактивный контрол — существующую
кнопку `projection-toggle` (`src/houseplan-card.ts:11501-11507`), которая
сейчас недостижима из-за `expires: 1.65.0` и станет достижимой снова.
- Это не открытый продуктовый вопрос владельцу: сама кнопка и её
touch-поведение уже прошли ревью в #89/#122 и код не меняется — задача лишь
восстанавливает достижимость уже принятого контрола через новый резолвер.
Достаточно одной явной строки в ТЗ (например, в «UX и диагностика» или
отдельным подпунктом «Touch»), фиксирующей это рассуждение как решение
ревью, а не оставляющей пункт чек-листа непроверенным. Без такой строки
раздел DoR формально не закрыт, и это факт, а не стилистика: чек-лист §2.5
зовёт этот пункт поимённо и отмечает его блокирующим для View/kiosk.
- Воспроизведение: `grep -inE "touch|Touch|сенсор" docs/specs/448-alpha-switch.md` → нет совпадений.
- Не блокирует переход High-порогом, чинится добавлением строки в этом же ТЗ,
отдельный цикл не обязателен по существу (это не смена контракта), но по
процессу возврат один — правка ТЗ и повторный (лёгкий) заход.
## Что проверено и корректно
- **Обязательные разделы §7.1** все присутствуют и в правильном порядке:
сценарий, что человек увидит до/после, проблема, скоуп/не-скоуп, контракт
поведения, UX и диагностика, модель данных и миграция, i18n и accessibility,
критерии приёмки AC1–AC13 с доказательством, план автотестов, риски, откат,
release-артефакты, плюс необязательный, но полезный блок «Принятые
предположения».
- **AC1–AC13** пронумерованы, взаимно не пересекаются и у каждого указан явный
способ доказательства (unit / unit+smoke / source-contract / targeted smoke +
golden / performance profile / static contract). Ни один AC не сформулирован
как «работает корректно» без проверяемого критерия.
- **Ни одной непомеченной догадки о существующем поведении не найдено.**
Каждое фактическое утверждение о текущей системе сверено с кодом/каноном и
подтвердилось: version-expiry `1.65.0` действительно отфильтровывает `iso` на
линии 1.71 (`liveLabsFlags` + `LABS_FLAGS[0].expires`); переключатель Flat↔3-D
уже существует в full-card View и уже скрыт в kiosk (`!this._kiosk`) —
`src/houseplan-card.ts:11501`; per-space preference `houseplan_card_view_v1`
используется как заявлено (`LS_VIEW` в `houseplan-card.ts:489`); редакторы и
`houseplan-space-card` не проецируют iso — подтверждено `docs/ISOMETRIC.md`
(«Editors and houseplan-space-card are always flat»). Единственная
content-догадка о будущем поведении («явное неизвестное URL-значение не
портит сохранённое значение») корректно вынесена в блок «Принятые
предположения», как и требует PROCESS.md §7.1.
- **Продуктовые вопросы владельцу заданы по существу**, каждый с предложенным
default (способ включения/выключения `hp_alpha`; судьба legacy `iso`), ответ
получен и зафиксирован явным решением в третьем комментарии issue —
процессуально верно (§3.7.1: только «что видит/делает человек» и «объём
видимых изменений», без технических вопросов владельцу).
- **Скоуп/не-скоуп** точно очерчивают границу: явно исключены публичный запуск
3-D, Stage 3 (#160), серверное хранение/синхронизация, миграция старого
`iso`. Соответствует ответу владельца на Q2 (без миграции).
- **Откат** описан содержательно — включает явный запрет «плохого» отката
(продление `iso`-expiry, возврат нескольких внешних ключей), что и было
первоисточником проблемы.
- **Компат-модель**: раздел корректно утверждает, что схема плана/backend/HA-
запросы не меняются — проверено по `docs/CONFIG-COMPATIBILITY.md`, чья
область действия — persisted-поля конфигурации плана, а не browser-local
Labs-хранилище; обращение к этому реестру здесь действительно не требуется.
- **i18n**: заявлено «новых публичных строк нет» — проверено, `view.flat` /
`view.volumetric` уже существуют в `ru.json`/`en.json`; прозаические «Плоский
/ 3-D» в тексте ТЗ — не заявка на новую строку, а неформальный пересказ
существующих меток, реальный текст меток задачей не меняется.
- **Класс изменений и трейлеры коммита** верны: только `docs/**` (класс C),
`Issue: #448`, `User-Visible: no` — корректно для стадии, где поведение ещё
не менялось; продуктовый код не тронут ни одним файлом (правило №1 не
нарушено).
- **Персона/повод**: аналитика прямо связывает задачу с J1 SCOPE.md и с уже
одобренным исключением #89; формулировка «продвинутый
пользователь/тестировщик» в разделе «Сценарий» не совпадает дословно ни с
одной строкой таблицы персон SCOPE.md (`Home admin`/`Household
members`/`Guests`), но по контексту (URL-флаг, desktop) однозначно про Home
admin — рассмотрено, не поднято до отдельной находки: не создаёт
двусмысленности для реализации или проверки AC, чисто формальная
формулировка. Low, не фиксирую отдельно.
## Чего не проверял
- Не прогонял `npx tsc --noEmit` / `npm test` / `npm run build` — диапазон не
содержит кода класса A/B, эти гейты не гейтуют ревью ТЗ.
- Не прогонял `node scripts/check-docs.mjs` — диапазон не касается `src/**`
(отпечаток скриншотов документации), автор уже привёл `passed` в issue, но
это не обязательный гейт для docs-only диффа.
- Не проверял golden/smoke/performance-фикстуры буквально (их ещё нет — они
появятся в реализации, план автотестов на этой стадии оценивается как план,
а не как прогон).
- Не оценивал техническую реализуемость внутреннего резолвера построчно (не
моя роль на этой стадии и не предмет спор ТЗ↔код) — только соответствие
контракта существующему коду и канону.
## Вердикт
`hp_alpha` заменяет version-expiry контракт корректно очерченным,
непротиворечивым и полностью доказуемым ТЗ; единственная находка — реальный,
но локально устранимый пробел DoR по touch-влиянию, входящий в скоуп этой же
задачи.
Вердикт: жёлтый · заход r1 · блокирующих циклов 1/4 · High: 0 · Medium: 1 → в задаче
---
<!-- material-anchors: сгенерировано конвейером (#414) -->
## Материал раунда
- Ветка: `issue/448-alpha-switch`, коммит `aa72704aacce` — ребейз его осиротит, и это нормально: ниже якоря, которые ребейз не меняет.
- Дерево материала: `4bea42cb1c9dc9c0fc49c8de4005942035e965d1`
```
git log --all --format='%H %T' | grep 4bea42cb1c9d
```
- ТЗ `docs/specs/448-alpha-switch.md`, блоб `ba9b8e5f621f5ad8ecb881e1cbf40d3cc24573ef`
```
git log --all --find-object=ba9b8e5f621f5ad8ecb881e1cbf40d3cc24573ef -- docs/specs/448-alpha-switch.md
```