21 KiB
#448 — Единый бессрочный переключатель hp_alpha
- Issue: #448
- Приоритет: P1
- Тип: feature
- Решения владельца: 2026-09-04, Q1 — default; Q2 — без миграции прежнего
iso
Сценарий
Продвинутый пользователь или тестировщик House Plan открывает полную карточку на своём обычном Home Assistant origin и один раз включает скрытый alpha-режим через URL. После перезагрузок, перезапусков Home Assistant и обновлений House Plan ему по-прежнему доступны все экспериментальные функции этой сборки. Сейчас такой функцией является существующий объёмный вид плана.
Что человек увидит до и после
До изменения прежний ключ iso истёк на версии 1.65, поэтому в актуальной
сборке объёмный вид невозможно включить. После изменения hp_alpha=1 один раз
возвращает существующий переключатель «Плоский / 3-D» без срока действия;
hp_alpha=0 выключает весь экспериментальный набор. Старое включение iso
автоматически не переносится — режим нужно активировать заново.
Проблема
src/labs.ts сейчас предоставляет внешний реестр отдельных feature-id с
since/expires, читает операции hp-labs=iso и хранит массив id в
houseplan_card_labs_v1. Единственный зарегистрированный iso истекает перед
версией 1.65.0, поэтому на линии 1.71 он всегда отфильтровывается, хотя
изометрический renderer, выбор вида по пространству и его тестовые сценарии
остались в продукте.
Такой контракт также требует придумывать пользователю новый внешний ключ и продлевать окно при каждой следующей экспериментальной функции. Решение владельца заменяет его одним browser-local переключателем способности.
Скоуп
- Один внешний URL-параметр
hp_alphaсо значениями1и0. - Один бессрочный persisted switch на текущем browser/HA-origin.
- Включение одним switch всех экспериментальных функций, присутствующих в текущей сборке; внутренние идентификаторы функций допустимы только как деталь реализации и диагностики.
- Возврат существующего объёмного вида и его переключателя в полной карточке.
- Сохранение текущих ограничений объёмного вида: редакторы и
houseplan-space-cardостаются плоскими, публичного UI включения нет. - Адаптация unit, browser smoke, golden и performance fixtures к новому внешнему контракту.
- Актуализация документации Labs/изометрии и двух changelog.
Не-скоуп
- Публичный запуск 3-D или обычная настройка alpha в интерфейсе.
- Реализация Stage 3 из #160 либо изменение визуального результата Stage 1/2.
- Отдельные пользовательские ключи для
isoили будущих экспериментов. - Серверное хранение, синхронизация между браузерами или HA-пользователями.
- Изменение схемы плана, backend API, HA-запросов, сохранения конфигурации, действий устройств или статической карточки пространства.
- Перенос ранее сохранённого
isoв новый переключатель.
Контракт поведения
Единый внешний переключатель
?hp_alpha=1включает alpha для текущего browser/HA-origin и запоминает включение.#hp_alpha=1&space=<id>делает то же, не ломая существующий выбор пространства из hash.hp_alpha=0в query или hash выключает alpha и запоминает выключение.- URL не переписывается после чтения параметра.
- Если параметр указан и в query, и в hash, операции применяются в порядке query → hash: последнее распознанное значение в hash сильнее query. Внутри одной части URL последнее распознанное значение сильнее предыдущего.
- Только точные строки
1и0распознаются. Явное иное значение не может включить alpha: для текущего разрешения оно даёт выключенное состояние и не перезаписывает storage. Отсутствие параметра читает сохранённое состояние. - Отсутствующие или повреждённые persisted-данные дают выключенное состояние.
- Версия карточки не участвует в решении. Нет
since,expiresи автоматического выключения после beta/stable update.
Доступные эксперименты
- При включённом alpha внутренний runtime активирует весь известный этой
сборке экспериментальный набор. В первой поставке набора ровно одна функция:
iso. - Потребители могут продолжать различать функции внутренними id, но URL, storage и пользовательская документация не позволяют выбирать их по одной.
- При выключенном alpha effective projection всегда Flat, даже если
per-space preference хранит
iso. - Выключение alpha не стирает
houseplan_card_view_v1: повторное включение возвращает ранее выбранную проекцию пространства. Это состояние вида, а не второй экспериментальный ключ. - В полной карточке View включённый alpha возвращает существующий
переключатель Flat ↔ 3-D. В kiosk применяется сохранённая проекция, но новый
служебный контрол не появляется. В любом редакторе и
houseplan-space-cardобъёмная проекция отсутствует. - Любой сбой разрешения alpha безопасно оставляет публичный Flat и не влияет на данные или HA-команды.
URL, storage и совместимость
- Новый storage key:
houseplan_card_alpha_v1. - Канонические значения storage: строка
1для enabled и строка0для disabled. Любое другое содержимое считается выключенным. - Legacy URL
hp-labs=iso,hp-labs=-iso,hp-labs=offбольше не управляет функциями. - Legacy key
houseplan_card_labs_v1не читается, не мигрируется и сам по себе не удаляется. Даже точное прежнее значение["iso"]не включает alpha. - Старому тестировщику необходимо один раз открыть карточку с
hp_alpha=1. - Per-space preference
houseplan_card_view_v1сохраняет существующий формат и не мигрируется. - Состояние локально для origin и профиля браузера; private mode/quota ошибки не роняют карточку, но сохранение между сессиями в таком окружении не гарантируется.
UX и диагностика
- Обычный пользователь не видит новой настройки, баннера или подсказки.
- Способ включения остаётся намеренно скрытым и документируется только в материалах разработчика/изометрии.
- Когда alpha включён и экспериментальный кадр действительно отрисован,
dev-console один раз на фактический набор сообщает, что активен
hp_alpha, и перечисляет внутренние функции с issue, но без срока истечения. - Когда alpha выключен либо не удалось разобрать, служебный лог не обещает активный эксперимент.
- Диагностический browser hook должен однозначно позволять smoke-тесту отличить alpha enabled от disabled и увидеть фактически активный внутренний набор.
Модель данных и миграция
План, backend и пользовательская конфигурация не меняются. Новое состояние —
один локальный boolean-like переключатель браузера. Автоматической миграции нет
по прямому решению владельца: legacy storage остаётся неактивным входом, а
пользователь заново подтверждает участие явным hp_alpha=1.
Внутренняя модель может сохранить snapshot со списком активных возможностей, если это уменьшает дифф потребителей. Его источник обязан быть один: при alpha off список пуст, при alpha on он равен полному набору сборки. Внутренний список не является persisted или URL API.
i18n и accessibility
Новых публичных строк и интерактивных элементов нет. Существующие
локализованные названия Flat/3-D, aria-label и keyboard contract
переключателя сохраняются без изменений. Kiosk и static card не получают новых
focus targets.
Влияния на touch-контракт нет: в полном View снова становится достижимой уже
принятая в #89/#122 кнопка projection-toggle, и её существующие tap,
keyboard и focus-поведение не меняются. Kiosk по-прежнему не получает ни эту
кнопку, ни новую touch-цель; для View и kiosk не допускается деградация
требований docs/TOUCH-SUPPORT.md.
Критерии приёмки
- AC1.
hp_alpha=1в query и hash включает alpha, сохраняет1и не переписывает URL. Доказательство: unit resolver/storage + browser smoke после reload. - AC2.
hp_alpha=0выключает alpha, сохраняет0, немедленно возвращает Flat и убирает переключатель 3-D. Доказательство: unit + browser smoke. - AC3. Query применяется раньше hash; последнее распознанное значение детерминированно побеждает. Доказательство: табличный unit-тест конфликтов.
- AC4. Отсутствующий storage, повреждённый storage и явное неизвестное значение не включают alpha и не вызывают исключений. Доказательство: unit.
- AC5. Поведение одинаково на текущей beta, stable и произвольной будущей
semver: version expiry отсутствует. Доказательство: unit с несколькими
версиями и source-contract без
since/expiresв решении. - AC6.
houseplan_card_labs_v1: ["iso"]и любойhp-labs=...не включают alpha и не переносятся. Доказательство: unit + browser smoke чистого профиля. - AC7. При alpha on существующий полный View предлагает Flat ↔ 3-D и отображает Stage 2; при alpha off публичный View остаётся Flat. Доказательство: targeted isometric smoke и существующие golden.
- AC8. Сохранённая per-space проекция переживает alpha off/on, но без alpha никогда не отрисовывается. Доказательство: unit/browser smoke.
- AC9. Редакторы и
houseplan-space-cardостаются плоскими, kiosk не получает служебный контрол. Доказательство: contract unit + smoke. - AC10. Все isometric golden-сценарии явно включают общий alpha и падают,
если фактически получили Flat. Доказательство: matrix unit +
npm run golden:verify. - AC11. Isometric performance profile включает alpha новым контрактом и не использует legacy storage/URL. Доказательство: source-contract + профильный запуск.
- AC12. Диагностика однозначно показывает switch и активный набор без
expires; повторный одинаковый кадр не спамит console. Доказательство: unit или targeted browser smoke. - AC13. Alpha не участвует в HA data/request paths, schema и writes. Доказательство: static contract tests и чтение границ импорта.
План автотестов
Unit и contract
- Переписать таблицу
test/labs.test.mjs:1/0, query/hash precedence, повторные значения, storage persistence, corruption, future versions, private-storage failures и отсутствие legacy migration. - Зафиксировать один внешний URL/storage contract; запретить возвращение
hp-labs, persisted массива и expiry как активирующих входов. - Обновить
test/isometric-contract.test.mjsи golden-matrix contract: full card использует alpha, secondary card не знает про него, isometric scenarios объявляют его явно.
Browser и visual
- Обновить
demo/smoke_isometric_contract.mjs: clean off → URL on → reload → 3-D → URL off → Flat → повторное on восстанавливает preference. - Обновить
demo/smoke_isometric_live_touch.mjsи все fixtures, которые сейчас подменяютhp-labs/legacy storage напрямую. - Прогнать выбранные
smoke-selectсценарии и весь isometric smoke-контракт. - Прогнать
npm run golden:verify; новые эталоны не принимаются, если пиксели Stage 1/2 не изменились.
Производительность и основные гейты
npm run benchmark:large-house-isometricс alpha fixture и существующим бюджетом; задача меняет gate, а не геометрию/рендер, поэтому новый бюджет не вводится.- Перед код-ревью: typecheck, unit, build + bundle-tree/budget,
check-docs,no-new-any, выбранные smokes и golden.
Затронутые файлы и модули
Ожидаемо: src/labs.ts, потребители Labs в src/houseplan-card.ts, unit и
isometric browser/golden/performance harnesses, docs/DEVELOPMENT.md,
docs/ISOMETRIC.md, архитектурные/ADR ссылки при необходимости, оба changelog.
Backend, schema плана и secondary-card renderer изменяться не должны.
Риски
- Legacy фикстура может продолжить принудительно подставлять
['iso']и дать ложнозелёный тест, не проверяющий новый пользовательский вход. - Стирание projection preference при
hp_alpha=0превратит временное выключение экспериментов в потерю пользовательского выбора. - Параллельные module instances могут зарегистрировать несколько listeners; существующий single-listener contract нужно сохранить.
- Ошибка precedence query/hash сделает включение зависимым от порядка роутера HA.
- Слишком широкая замена термина
isoможет затронуть внутренний renderer; меняется capability gate, а не имя проекции.
Откат
Откат изменения возвращает старый истёкший Labs resolver; публичный Flat при
этом остаётся безопасным. Новый storage key можно оставить неиспользуемым: он
не является данными плана и не требует destructive cleanup. Нельзя откатывать
через продление iso expiry или возвращение нескольких внешних ключей — это
восстановит проблему задачи.
Release-артефакты
- Записи со ссылкой на #448 в
docs/CHANGELOG.ru.mdиdocs/CHANGELOG.mdв коммите пользовательского изменения. - Актуальные
docs/DEVELOPMENT.mdиdocs/ISOMETRIC.md; при изменении архитектурной границы — соответствующие ADR/docs/ARCHITECTURE.md. - Обновлённые unit, smoke, golden matrix и isometric performance fixtures.
- Обычные синхронные release bundles; новая картинка документации или новый golden baseline не ожидаются, пока пиксельный результат Stage 1/2 не менялся.
Принятые предположения — можно менять на ревью без решения владельца
- Storage key —
houseplan_card_alpha_v1, значения — строки1/0. - Явное неизвестное URL-значение выключает alpha только для текущего разрешения
и не портит ранее сохранённое значение; распознанные
1/0записываются. - Legacy storage не удаляется автоматически: он просто перестаёт быть входом.
- Внутренние feature-id можно сохранить для маршрутизации и диагностики, если снаружи существует только один alpha switch.
- Отключение alpha скрывает эксперимент, но не стирает per-space projection preference.