Files
houseplan-card/docs/specs/448-alpha-switch.md
T
2026-09-04 16:20:34 +03:00

21 KiB
Raw Blame History

#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 в новый переключатель.

Контракт поведения

Единый внешний переключатель

  1. ?hp_alpha=1 включает alpha для текущего browser/HA-origin и запоминает включение.
  2. #hp_alpha=1&space=<id> делает то же, не ломая существующий выбор пространства из hash.
  3. hp_alpha=0 в query или hash выключает alpha и запоминает выключение.
  4. URL не переписывается после чтения параметра.
  5. Если параметр указан и в query, и в hash, операции применяются в порядке query → hash: последнее распознанное значение в hash сильнее query. Внутри одной части URL последнее распознанное значение сильнее предыдущего.
  6. Только точные строки 1 и 0 распознаются. Явное иное значение не может включить alpha: для текущего разрешения оно даёт выключенное состояние и не перезаписывает storage. Отсутствие параметра читает сохранённое состояние.
  7. Отсутствующие или повреждённые persisted-данные дают выключенное состояние.
  8. Версия карточки не участвует в решении. Нет since, expires и автоматического выключения после beta/stable update.

Доступные эксперименты

  1. При включённом alpha внутренний runtime активирует весь известный этой сборке экспериментальный набор. В первой поставке набора ровно одна функция: iso.
  2. Потребители могут продолжать различать функции внутренними id, но URL, storage и пользовательская документация не позволяют выбирать их по одной.
  3. При выключенном alpha effective projection всегда Flat, даже если per-space preference хранит iso.
  4. Выключение alpha не стирает houseplan_card_view_v1: повторное включение возвращает ранее выбранную проекцию пространства. Это состояние вида, а не второй экспериментальный ключ.
  5. В полной карточке View включённый alpha возвращает существующий переключатель Flat ↔ 3-D. В kiosk применяется сохранённая проекция, но новый служебный контрол не появляется. В любом редакторе и houseplan-space-card объёмная проекция отсутствует.
  6. Любой сбой разрешения 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.