# История изменений > Русская версия [docs/CHANGELOG.md](CHANGELOG.md). Переведены записи начиная > с v1.42.0 (2026-07-26); более ранние доступны только в английском файле. > > **Правило проекта:** оба файла пополняются в одном коммите с самим > изменением — как и остальная документация (см. docs/STATUS.md). ## v1.56.0 — 2026-08-03 Минорный релиз: на план приходит солнце — компас, фон «день/ночь» и настоящий свет из окон — плюс температура с климатических устройств, дизайн-токены в UI, живые линейки при перетаскивании проёмов и фикс кэша солнечных лучей. - **Солнце на плане дома** (docs/SUN.md). Скажите плану, где север — круговой компас в общих настройках с переопределением в каждом пространстве — и карточка начинает жить по `sun.sun` самого Home Assistant: - *Фон «день/ночь»* (`bg_mode: daynight`): сцена за планом следует за высотой солнца — белый ясный день, тёплое золото золотого часа, остывающие сумерки, глубокая ночь. Сам план ночью приглушается лишь на ~10%, комнаты остаются читаемыми. - *Свет из окон* (`sun_rays`): каждое окно на внешней стене пускает в свою комнату мягкий клин света — обрезанный контуром комнаты, теплее у горизонта, длинный на рассвете и закате, короткий в полдень и гаснущий ночью. - *Облачность — по желанию* (`weather_entity`): укажите weather-сущность, и пасмурное небо приглушит клинья, а дождь или снег погасит совсем. Мёртвый датчик солнце не выключает. - План теперь лежит на *непрозрачном листе бумаги*, повторяющем контуры комнат: фон сцены — `bg_color` или небо «дня/ночи» — виден только вокруг стен и не просвечивает сквозь комнаты; в режиме «день/ночь» у листа мягкая тень. - Пока компас не задан, фича полностью молчит; без `sun.sun` диалог настроек объясняет, почему. - **Температура с климатических устройств.** Новый чекбокс в диалоге устройства выводит `current_temperature` кондиционера или термостата на плашку у значка и учитывает её в средней температуре комнаты. - **Модернизация UI.** Токен-проход по `styles.ts` — 209 «зашитых» значений сведены в шкалы отступов/радиусов/шрифтов/теней — и родные `ha-switch` / `ha-slider` в диалогах с жёстким фолбэком на старые инпуты там, где компоненты HA недоступны. - **Живые линейки проёмов.** При перетаскивании двери или окна теперь видны живые расстояния до обоих концов стены — по ребру своей комнаты; пунктирная направляющая и мягкий магнит центрируют проём на стене (Shift отключает магнит). - **Фикс DEV-B701-01** — кэш солнечных лучей теперь сбрасывается и локальными правками геометрии: клин больше не «застревает», если подвинуть стену до подтверждения сервера. ## v1.55.3 — 2026-08-02 Патч-релиз: два исправления вуали первого открытия из v1.55.2, найденные adversarial-аудитом жизненного цикла (AUD-1552-01/02). - **Пересборка дашборда во время первого открытия больше не оставляет план скрытым навсегда** (AUD-1552-01). Отключение карточки при поднятой вуали (Lovelace пересоздаёт DOM, переключение вью перемонтирует карточку) убивало таймеры стабилизации, но сохраняло их id — и вуаль уже никогда не снималась. Теперь жизненный цикл вуали перезапускается при каждом повторном подключении — с новым отсчётом и безусловным жёстким таймаутом; затухание тоже переживает размонтирование посреди fade. - **Вуаль больше не открывается рано, прямо перед поздней панелью** (AUD-1552-02). Два одинаковых замера высоты на 200/400 мс открывали план уже на ~400 мс, и хром Home Assistant, пришедший на 450+ мс, прыгал на видимом плане — ровно то, от чего вуаль должна защищать. Теперь вуаль держится полное защитное окно с trailing quiescence (изменения высоты у края окна продлевают ожидание), а короткое время после открытия поздний сдвиг применяется плавно (transition высоты), а не скачком. Намеренные изменения высоты (вход в редактор) по-прежнему применяются мгновенно. ## v1.55.2 — 2026-08-02 Патч-релиз: спокойное первое открытие — без вспышки зума и прыжков макета, пока Home Assistant догружается, — плюс новая настройка цвета фона и две полировки редактора. - **План больше не мигает видом по умолчанию перед сохранённым зумом** (HP-1551). Сохранённый зум применялся на такт позже первого рендера: карточка на кадр рисовала стандартную подгонку и лишь потом прыгала к вашей позиции. Теперь он применяется синхронно, до первой отрисовки — план появляется ровно там, где вы его оставили. - **Вуаль первого открытия прячет план, пока макет не устаканится** (HP-1552). Пока Home Assistant догружает свои панели, высота сцены может меняться несколько раз, и план заметно прыгал вместе с ней. Теперь карточка ждёт под тёмной вуалью с пульсирующим контуром домика, пока высота не перестанет меняться, и показывает план уже на месте. В режиме киоска вуаль не показывается вовсе. - **Новая настройка: цвет фона вокруг плана** (HP-1554). Области вокруг плана теперь можно задать любой цвет — в общих настройках для всей карточки или отдельно для каждого пространства. Бэкенд проверяет значение как hex-цвет #rrggbb. - **Круглые концы и стыки линий в редакторе подложки** (HP-1553). Штрихи обрывались и стыковались квадратными срезами; теперь концы линий и углы скруглены — обведённые стены и контуры выглядят аккуратно. - **Ручки стен в инструменте Resize теперь выглядят по делу.** Они вдвое меньше прежних, несут значок «стенка со стрелочками», повёрнутый вдоль своей стены, и показывают курсор grab — при этом зона клика осталась прежней, большой. ## v1.55.1 — 2026-08-01 Патч-релиз: четыре находки аудита v1.55.0, все — в новом инструменте ресайза комнат (HP-1550-01..04). - **Отложенное сохранение больше не утаскивает живое перетаскивание на сервер** (HP-1550-01). Превью ресайза писалось прямо в общий объект конфигурации, и отложенная запись, оставшаяся в очереди от прошлой правки, могла сфотографировать его посреди перетаскивания — ресайз, который вы затем отменили по Esc, тихо оставался на сервере и возвращался после перезагрузки. Теперь живая геометрия живёт в отдельном слое, который видит только отрисовка; в конфигурацию она попадает ровно один раз — при отпускании ручки. - **Прерванное перетаскивание отменяется, а не сохраняется** (HP-1550-03). Когда систему прерывает сам поток ввода — переключение приложения, ладонь на планшете — инструмент считал это отпусканием и сохранял недоделанную геометрию. Теперь такие прерывания идут тем же путём, что и Esc: исходная геометрия возвращается, без шага отмены и без записи. - **Дверь посреди стены больше не мешает менять её размер** (HP-1550-04). Невидимая зона клика двери ложилась поверх ручки стены, и такую стену нельзя было схватить ни у одной из комнат. В инструменте ресайза ручки теперь главные в hit-тесте (проёмы там всё равно не редактируются — они просто едут вместе со стеной), а во всех остальных инструментах редактора проёмы кликаются как раньше. - **Минимум ~30 см теперь держится для комнаты любой формы** (HP-1550-02). Старая проверка мерила только параллельные противоположные стены: треугольную комнату можно было сплющить в щепку, а повёрнутая комната при масштабировании незаметно уводила свою реальную короткую сторону ниже порога. Обе меры теперь не зависят от ориентации: перетаскивание стены упирается в любое препятствие на её пути (вершину треугольника, косую стену), а рамка масштабирования использует истинную минимальную ширину комнаты. Комнаты, уже более тонкие, по-прежнему можно улучшать, но не ухудшать. ## v1.55.0 — 2026-08-01 Минорный релиз: комнаты больше не высечены в камне — новый инструмент «Размер» в редакторе плана меняет их габариты перетаскиванием стен; плюс обе находки аудита v1.54.3 (HP-1543-01/02). - **Ресайз комнат — новый инструмент «Размер» в редакторе плана** (спека: docs/RESIZE.md). У каждой стены появляется ручка в середине; тяните её — и стена едет целиком, оставаясь параллельной себе, с привязкой к сетке. Работает и для полигонов (включая Г-образные), и для старых прямоугольников. - **Общие стены всегда двигаются вместе.** Если перетаскиваемая стена совпадает с границей соседа, сосед следует за ней: ваша комната растёт — соседняя сжимается, щели и наложения не появляются по построению. На Т-стыках следует только совпадающий отрезок, при необходимости в контур соседа вставляются новые вершины. - **Живые цифры во время перетаскивания.** Перетаскиваемая стена и две смежные показывают длины в реальных метрах/футах, а площадь комнаты в м² обновляется в центре комнаты вживую — для общей стены — площади обеих комнат. - **Стена упирается там, где должна.** Комната не может стать тоньше ~30 см (ни своя, ни соседская), контур не пересекает сам себя, растущая стена останавливается о чужие комнаты и острова, а двери и окна — якоря: проём едет вместе со стеной, и стена с проёмами не может стать для них слишком короткой. - **Рамка масштабирования всей комнаты.** Клик по комнате в инструменте выбирает её: перетаскивание уголка пунктирной рамки пропорционально масштабирует контур — с теми же упорами. - **Esc и Ctrl+Z.** Esc отменяет текущее перетаскивание и возвращает исходную геометрию; одно отпускание ручки — один шаг отмены, Ctrl+Z откатывает до 30 шагов, пока инструмент активен. - **Исправлено: детекция наложения комнат пропускала равновысокие прямоугольники, надвинутые друг на друга.** Найдено при постройке упоров ресайза; slide-over теперь считается наложением везде, где используется эта проверка, включая инструмент рисования. - **Исправлено (HP-1543-01): редакторский зум оставался на экране после смены этажа внутри редактора.** Выход из редактора на другом этаже, чем тот, где начинали, пропускал восстановление вьюпорта и оставлял рабочий зум редактора в режиме просмотра. Теперь такой выход откатывается к сохранённому view-зуму текущего этажа. - **Исправлено (HP-1543-02): датчик движения, сработавший повторно посреди вспышки, оставался невидимым.** Быстрое off→on до конца текущей вспышки не перезапускало CSS-анимацию — второе срабатывание ничего не проигрывало. Теперь каждый зафиксированный trip получает новую идентичность анимации, и вспышка стартует заново; при prefers-reduced-motion остаётся статичное кольцо, как и раньше. ## v1.54.3 — 2026-08-01 Патч-релиз: три раунда качества жизни — спутники значка теперь слушаются пер-девайсного множителя размера, редакторский зум перестал протекать в режим просмотра, а датчики движения получили собственный визуальный язык. - **Пер-девайсный множитель размера теперь масштабирует и спутники значка.** Репорт владельца со скриншотом: у уменьшенного устройства бейдж значения, плашки температуры и влажности, подпись LQI, точка «new» и кольцо тревоги оставались полноразмерными и нависали над крошечным значком. Теперь все спутники следуют за множителем вместе со значком. - **Редакторский зум — рабочий инструмент, а не сохранённая настройка.** Приблизить до 500%, чтобы точно поставить маркер, и закрыть редактор раньше означало оказаться в режиме просмотра на тех же 500%. Выход из любого редактора теперь восстанавливает тот вид, который был в режиме просмотра до начала правок. - **Исправлено: редакторский зум всё ещё «воскресал» при переключении этажей.** Редакторский вьюпорт гонялся с пер-этажным хранилищем вида и побеждал: переключите этаж во время правок — и 500% записывались как сохранённый вид этого этажа и встречали вас в следующий раз (шаги воспроизведения — от владельца). Теперь редакторский зум в хранилище не пишется никогда. - **Сработавшие датчики движения и присутствия сигнализируют жёлтым кольцом.** Правило прежнее — «подложка = включено»: движение — разовая вспышка, три удара в момент обнаружения, без пульсации на хвосте cool-down; occupancy/presence держат статичное кольцо, пока докладывают о присутствии. - Только для стенда: `services.yaml` для стендового `demo_guard`, чтобы hassfest оставался зелёным; в саму интеграцию это не попадает. ## v1.54.2 — 2026-07-31 Патч-релиз: единственная оставшаяся находка повторного аудита v1.54.1 (HP-1541-01), закреплена регрессиями с обеих сторон контракта. - **Исправлено: пылесос с собственным `selected_map: 0` делил калибровку и след между двумя id карты.** Контракт map id из v1.54.1 («побеждает первое существующее значение, и ноль — значение») был применён к source-сущности, но не к фолбэку карточки на `selected_map` самого пылесоса: фронтенд по-прежнему судил по «истинности» и превращал `0` в `default`, тогда как серверный рекордер писал уборку под `0`. Калибровка сохранялась под ключом, которого рекордер не использовал, а записанный след после перезагрузки не отображался. Теперь фолбэк живёт по тому же правилу «не-null» с обеих сторон (`vacMapIdWithFallback` в карточке, `resolve_map_id` на сервере), с кросс-регрессиями для `selected_map` = `0`, `"0"` и `""`. ## v1.54.1 — 2026-07-31 Патч-релиз: всё, что нашёл adversarial-аудит v1.54.0 (HP-1540-01..06), каждый фикс закреплён регрессией, падающей на старом коде. - **Исправлено: первая калибровка только что обнаруженного пылесоса молча ничего не делала.** Пока диалог устройства ни разу не сохранён, у робота нет маркера в конфиге — а раздел «Живая позиция» уже полностью интерактивен: каждый обработчик тихо выходил, но автокалибровка всё равно объявляла успех. Теперь любая правка пылесоса сама создаёт маркер, а тост успеха появляется только после того, как матрица действительно легла в конфиг. - **Исправлено: робот с первой картой `map_index: 0` терял серверный след.** Бэкенд выбирал id карты по «истинности» и выбрасывал ноль, так что записанная уборка хранилась под ключом, который карточка не искала. Теперь обе стороны живут по одному явному правилу: побеждает первое существующее значение, и ноль — значение. - **Исправлено: один робот на двух этажах писал историю только для последнего этажа.** Рекордер держал по одному маркеру на источник, и второе размещение молча вытесняло первое. Теперь каждый маркер источника получает свою копию уборки. - **Исправлено: автокалибровка не видела планы из прямоугольных комнат.** Сопоставление принимало только полигоны, а потом сваливало вину на имена комнат. Старые прямоугольники считаются, как и во всей остальной карточке. - **Исправлено: пересекающиеся обновления рекордера текли подписками.** Два одновременных сохранения конфига могли подписаться оба и бросить один callback до перезапуска; обновления теперь сериализованы, а teardown выигрывает у любого ещё летящего обновления. - Тосты «нет комнат» / «имена не совпали» и docs/VACUUM.md больше не отправляют к несуществующей калибровке по трём точкам — они ведут к «Подогнать вручную», которая существует. ## v1.54.0 — 2026-07-31 ### Роботы-пылесосы вживую План теперь показывает робота за работой. Маркер устройства остаётся там, куда вы его поставили — это база, — а по плану в реальном времени едет круглая шайба, «выливая» путь из-под себя. Только отображение: карточка ничего роботу не командует. - **Калибровка без арифметики.** «Настроить автоматически» сопоставляет комнаты робота с вашими по именам и решает привязку в один клик. Если имена не совпали, панель подгонки кладёт комнаты робота на план пунктирным призраком: перетащите на место, растяните за уголки, поворот на 90° и зеркало — двумя кнопками. Зеркало включено по умолчанию: у всех измеренных нами роботов ось Y перевёрнута относительно экрана. Своя калибровка на каждую карту робота, поэтому два этажа не мешают друг другу. - **Путь пишется на сервере.** Интеграция следит за роботом сама, поэтому след записывается даже без открытой карточки, переживает перезагрузку страницы, и все экраны видят одну и ту же линию. Хранятся текущая уборка и одна предыдущая — сразу видно, где робот уже прошёл, а где ещё нет. - **«Показывать путь робота»**: никогда / во время уборки (по умолчанию) / всегда. Прошлая уборка бледной линией рисуется только в последнем режиме. - След никогда не обгоняет иконку: отрисованные отрезки отстают на точку, а растущий кончик каждый кадр приклеен к центру едущей шайбы. Рисуется тёмным ореолом со светлой сердцевиной — читается на любой заливке комнат. При смене вида (зум, этаж, возврат на вкладку) шайба телепортируется, а не едет через весь план. - Поддержаны Xiaomi Cloud Map Extractor, dreame-vacuum (Tasshack) и Valetudo. Проверено на живом Dreame X50 Master. ### Кроме того - **«Свет по источникам» — режим по умолчанию для новых пространств** и первый в списке. Существующие планы не трогаем: пространство, где режим не выбирали, выглядит как раньше. - **Исправлено: поиск «что запускать» не показывал результатов.** Список — прокручиваемый блок, и как flex-элемент он схлопывался в полоску 1px: совпадения были, но отрисовывались в ничто. ## v1.53.1 — 2026-07-30 - **Фикс: поиск «что запускать» не показывал результатов.** Результаты были — список это прокручиваемый блок, и как flex-элемент внутри тела диалога он схлопывался в полоску 1px: 26 подходящих автоматизаций отрисовывались в ничто. Найдено владельцем через минуты после v1.53.0. Теперь список держит высоту; смок измеряет эту высоту, а не просто считает строки в DOM — именно поэтому он и пропустил сломанную сборку. ## v1.53.0 — 2026-07-30 **Нажатие может запускать вашу автоматизацию** (ТЗ владельца) - **Новое действие по нажатию: «Запустить автоматизацию/скрипт/сцену».** Мы не можем знать каждое экзотическое устройство, но вы знаете, что должен делать тап по нему: выберите любую автоматизацию, скрипт или сцену из списка с поиском — тап её запустит (`automation.trigger`, `script.turn_on` или `scene.turn_on` по типу цели, с тостом «Запущено»). Скрипт — идиоматичное «действие» HA, поэтому предлагаются все три запускаемых типа: не нужны автоматизации-пустышки без триггера. Сохранение без цели блокируется; удалённая позже цель подсвечивается в диалоге и безопасно отвечает тостом при тапе. - **Чекбокс «Спрашивать подтверждение»** — защита от случайных нажатий для любого действия, меняющего состояние: и toggle, и запуск, включая настенные выключатели с привязанными целями. Диалог собственный (Esc, клик мимо или «Отмена» — ничего не происходит), поэтому работает и на настенном планшете. - **Шторы переключаются нативно:** cover и valve добавлены в домены card-wide toggle — с одним осознанным исключением: гаражные ворота, двери и калитки (классы garage/door/gate) остаются ВНЕ дефолтного переключения — случайный тап не должен открыть гараж. Явный per-device toggle остаётся осознанным выбором владельца, а замки и охранные панели, как и всегда, с плана неприкосновенны. ## v1.52.2 — 2026-07-29 **По ревью v1.52.1** (рантайм не менялся — качество теста и формулировок) - Проверка регресса в редакторе плана целится ИМЕННО в лампу (HP-1521-01): старый ассерт принимал любой жёлтый значок, и горящая розетка из той же фикстуры прошла бы его даже без фикса лампы. Проверено мутацией: откат гейта v1.52.1 валит смок. - Последняя формулировка «жёлтый в любом режиме» — пункт чек-листа и комментарий в _stateClass — приведена к фактическому контракту: состояние источника считается условием glow-пула, а жёлтая подложка показывается только там, где пятно не рисуется (HP-1521-02). ## v1.52.1 — 2026-07-29 **По ревью v1.52.0** - **У горящей лампы всегда ровно один индикатор (HP-1520-01).** В редакторе плана glow-слой скрыт, но подавление жёлтого там всё равно действовало — горящая лампа не показывала ни пятна, ни подложки. Гейт подавления теперь равен фактической видимости слоя: где пятно не рисуется, жёлтая подложка возвращается. - **Статичная карточка уважает размер и поворот маркера (HP-1513-01).** Один и тот же маркер рендерился на read-only карточке базовым и неповёрнутым. Теперь она зеркалит --dev-scale и угол полной карточки — только геометрия, по-прежнему схема. - Документация догнала цветовой контракт v1.52.0 (HP-1520-02): ожидания RGB-окраски в TESTING/UX-MODES и устаревший комментарий в коде. ## v1.52.0 — 2026-07-29 **Один вид источников света, чем бы их ни переключали** (правило владельца) - **Цвет лампы живёт только в её свечении.** RGB-окраска иконки, рамки и тени убрана: в зависимости от того, пришли ли с состоянием данные о цвете, одна и та же лампа попадала то в ветку «цветная иконка на тёмной подложке», то в «жёлтая подложка» — выключение одной лампы тапом и остальных выключателем выглядело по-разному. Ветки больше нет. - **В режиме glow индикатор — само пятно света.** Подложка источника всегда стандартная, горит он или нет — всё говорит свет вокруг. Розетка, вентилятор или чайник остаются жёлтыми и в glow: они не светят, правило — только для источников. - **В остальных режимах горящий источник — просто жёлтый**, как греющая термоголовка; RGB и обычные лампы одинаково. - Морфинг иконки (контур «лампа с лучами») остаётся во всех режимах, а цвет пульсации по-прежнему берёт фолбэком цвет свечения лампы. ## v1.51.3 — 2026-07-29 - **Множитель «размер значка» масштабирует и сам глиф, а не только подложку.** Изменение размера устройства растило подложку, пульсацию и бейджи значений, но иконка внутри оставалась дефолтной — большая пустая рамка вокруг маленького глифа (репорт пользователя). Теперь глиф считается от того же поустройственного размера, что и всё остальное, и держит пропорцию при любом множителе и зуме. ## v1.51.2 — 2026-07-29 **По ревью v1.51.1** - **Авто-сетка одинакова на обеих карточках (HP-1511-01).** Полная карточка резервирует клетки сетки за скрытыми устройствами (их призраки держат место в редакторе); статичная уплотняла сетку по одним видимым — свежее устройство без сохранённой позиции вставало на разных местах двух карточек. Теперь статичная передаёт сетке полный список и по-прежнему рисует только видимых. - **Ripple-призрак сохраняет базовую иконку (HP-1511-02).** Скрытый маркер с отображением «пульсация» рендерился безликим неподвижным пульсом — в редакторе его нельзя было узнать. Призрак теперь полностью снимает «одежду» отображения: базовая иконка и имя, каким бы ни был режим. ## v1.51.1 — 2026-07-29 **По ревью v1.51.0** - **Статичная карточка снова учитывает скрытые устройства в LQI комнаты (HP-1510-01).** Её фильтр видимости незаметно стал фильтром агрегации: одна и та же комната показывала разное Zigbee-здоровье на двух карточках. Теперь агрегация и отрисовка используют разные списки — скрытые устройства считаются в сигнале на обеих карточках, не рисуются ни на одной и по-прежнему не дают света. - **Призрак не показывает живых чисел (HP-1510-02).** Скрытое устройство в «Показать скрытые» подавляло цвета состояний, но по-прежнему рисовало значение, температуру, влажность, бейдж LQI и морф иконки. Всё это убрано: у призрака только базовая иконка и имя — достаточно, чтобы узнать устройство и открыть диалог. ## v1.51.0 — 2026-07-29 **Скрытие — теперь явная галка** (docs/FILTERING.md) - **В диалоге каждого устройства — включая виртуальные — есть галка «Скрыть устройство с плана».** Старый фильтр «на лету» остался только сеятелем этих галок: при первом открытии редактором конфиг один раз материализуется — нефизические устройства (мосты, сцены, служебные интеграции, лампы, свёрнутые в световую группу) получают галку, и дальше она принадлежит вам. Снятая галка — навсегда: сеятель не возвращается к устройству, о котором вы уже решили. Новые нефизические прячутся молча; физические — с красной точкой, как раньше. - **«Показать все» стала «Показать скрытые»** — локальный инструмент редактора устройств (на настенных планшетах ничего не мигает): скрытые рисуются полупрозрачными СИНИМИ пунктирными призраками — не спутать с серым недоступным — и совсем без живой индикации: призрак — это конфигурация, а не статус. Клик — и галку можно снять. «Удалить с плана» у привязанных устройств убрана (галка — единственный путь); «Удалить» у виртуального по-прежнему удаляет. - Скрытые устройства учитываются в Zigbee-сигнале комнаты, но не дают ни пятна света, ни заливки — не видно устройства, не видно и света. Климат комнат без изменений. Старые конфиги ведут себя по-старому, пока их не материализует клиент с правом записи. **Жёлтый значит «работает прямо сейчас»** - Один принцип для светящегося значка: лампа светит, розетка подаёт, вентилятор крутится, медиа играет, пылесос убирает — или термоголовка РЕАЛЬНО греет (hvac_action), а не просто включена на зиму. Раньше термоголовка могла светиться жёлтым из-за включённой защиты от накипи, а реально греющая оставалась тёмной: выбор главной сущности пропускал служебный свитч производителя вперёд видимого climate. Исправлено — служебная сущность больше никогда не побеждает видимую основную функцию (это чинит и tap-переключение, и морфинг иконок у таких устройств). - Пятно света и цвет значка задают один и тот же вопрос: горящая лампа желтит значок в любом режиме заливки ровно тем условием, что зажигает её пятно. README (en+ru) описывает язык цветов. **Редакторы на телефоне** - Пинч-зум и панорамирование жестами работают во всех редакторах: рисование кликовое, так что они совместимы — палец с движением панорамирует, два пальца зумируют, отпускание после жеста не ставит точку, чистый тап — ставит. **Кнопка настроек комнаты** - Отвязана от (передвигаемого) названия: стоит в ВИЗУАЛЬНОМ центре комнаты — центр наибольшей вписанной окружности с тяготением к центроиду площади, поэтому вытянутая комната центрирует её по обеим осям, а Г-образная держит в середине широкой части и не утаскивает в узкую. - Вдвое меньше прежней, размер от иконки устройства (70% бокса) и зумится ВМЕСТЕ с планом, а не держит постоянный экранный размер. - Мелкие подписи под названием комнаты (температура, влажность, сигнал, свет) теперь видны и в редакторе плана, а название рендерится ровно в том же месте в просмотре и в редакторе. ## v1.50.4 — 2026-07-29 **По ревью v1.50.3** - **Обе карточки строят модель одним кодом (HP-1503-01).** Полная карточка носила рукописную копию общего построителя модели, и копия не получила фолбэки для legacy-store из v1.50.3 — один и тот же битый store в статической карточке рендерился починенным, а в основной — пустым `viewBox="0 0 0 0"`. Дубликат удалён: полная карточка вызывает общий построитель и лишь подменяет сырой url плана, который нужен её подписи. Новый смок прогоняет точный вектор аудита через обе модели и оба DOM-дерева и проверяет паритет. ## v1.50.3 — 2026-07-29 **По ревью v1.50.2** - **Размер — не координата (HP-1502-01).** Граница ±4 из v1.50.2 мерила все четыре элемента view_box и w/h комнат одинаково, поэтому `[0, 0, 0, 0]` и отрицательные размеры всё ещё проходили — а нулевая ось сериализуется в `viewBox="0 0 0 0"`: пустой план у всех клиентов, и `aspect-ratio: 0 / 0` у статичной карточки сверху. У размеров теперь свой validator: строго положительные, пол — одна тысячная холста; координаты по-прежнему могут быть отрицательными — начало кропа законно выходит за край. А поскольку в сторе битый viewport может уже лежать, обе карточки падают на полный холст вместо пустого экрана, и legacy-прямоугольник с отрицательным размером читается как тот же прямоугольник, нарисованный из другого угла. **Также в этом релизе** - Кнопка настроек комнаты переехала в самый низ карточки комнаты, а имя комнаты отображается ровно в одном и том же месте в просмотре и в редакторе плана — кнопка и метрики больше не участвуют в центрировании. ## v1.50.2 — 2026-07-29 **По ревью v1.50.1** - **Величины геометрии ограничены на обоих слоях (HP-1501-01).** v1.50.1 ограничила позиции устройств, но прямоугольники комнат, вершины полигонов, view_box и координаты проёмов всё ещё принимали любое конечное число — одна проходящая схему вершина 1e100 растягивала кадр так, что план становился точкой у всех клиентов, и сервер хранил это как вполне корректную конфигурацию. Теперь схема конфига ограничивает геометрию ±4 (углы ±360°), а рамка содержимого применяет к вершинам комнат тот же конверт холста, что уже применяла к позициям устройств — конфиг, где абсурдная координата уже лежит с прежних времён, всё равно рендерится: точка рисуется, где стоит, просто кадром больше не командует. Вершина чуть за краём холста работает как раньше. - **Пустой repair больше не съедает бэкап (HP-1501-02).** Опечатка в space_id «успешно» отвечала moved: 0 — и её пустой результат заменял бэкап глубиной один, уничтожая единственный путь назад ровно тогда, когда он нужнее всего: сразу после починки не того пространства. Теперь «нечего чинить» — ошибка (`nothing_to_repair`): ничего не пишется, ревизия не растёт, предыдущий repair по-прежнему отменяем. ## v1.50.1 — 2026-07-29 **По ревью v1.50.0** - **Карточка ниже другого контента дашборда снова получает сцену (HP-1500-02).** Замер высоты в v1.50.0 брал абсолютную координату документа: высокая карточка перед этой записывалась в «шапку», и сцена схлопывалась в ноль. Теперь меряется только собственная обвязка плюс ограниченная поправка на то, что дашборд держит сверху; перемер — по resize окна, слушатель снимается при демонтаже. - **Рамка содержимого больше не бывает вырожденной или абсурдной (HP-1500-03).** Одинокий значок в пустом пространстве давал viewBox нулевой площади — пустую сцену; одна сохранённая координата вида 1e100 (любое конечное число проходило проверку) растягивала рамку так, что план становился точкой — у всех зрителей пространства. Почти нулевая ось теперь раскрывается до минимального кадра вокруг значка, точки далеко за холстом рамкой не командуют (рисуются, где стоят), а сервер отклоняет координаты вне ±4 — щедрый запас для значка, утащенного за край, но не для абсурда. Узкая комната сохраняет тесный кадр, датчик калитки чуть за краём по-прежнему учитывается. - **Путь восстановления для установок, застрявших в окне миграции v1.48 (HP-1500-01).** Если старая миграция упала между двумя записями, значки пространства остаются в старых координатах, и по данным это недоказуемо — а повторное преобразование правильных координат их испортит, поэтому ничего автоматического тут быть не может. Явный ответ — `houseplan/geometry/repair {space_id, aspect}`: `dry_run` показывает точные перемещения, прежние позиции уезжают той же записью хранилища как резервная копия глубиной один, `undo` их возвращает, и обычные перетаскивания эту копию больше не затирают. Протокол `geom_pending` из v1.50.0 уже защищает все будущие миграции; это — для тех, кому он опоздал. ## v1.50.0 — 2026-07-28 **Задачи владельца** - **Масштаб по умолчанию считает устройства содержимым.** Им можно стоять вне комнат — датчик калитки у забора, камера на столбе — и стартовый вид теперь включает их, даже в пространстве совсем без комнат. - **Вход в редактор больше не сдвигает план.** Высота сцены считалась как «экран минус 118px шапки», а шапка редактора выше: сцена уезжала вниз на разницу, низ пропадал за краём. Карточка измеряет, где сцена начинается на самом деле, и отдаёт ей остаток экрана. - **Масштаб теперь и отдаляется.** До 0.4×; в отдалении план висит по центру, а не прилипает к углу. **По ревью v1.49.0** - **Миграция на квадратный холст переживает сбой между двумя записями (HP-1490-01).** Конфиг и позиции живут в разных хранилищах, пишутся по очереди, и первая запись удаляла именно те поля, которые нужны второй — сбой между ними навсегда оставлял значки в старых координатах. Теперь намерение миграции сохраняется до того, как что-либо меняется, и снимается той же записью, что сохраняет позиции: какая половина не успела — ту следующий запуск и доделает, ровно один раз. - **Параллельные загрузки не проскакивают квоту вместе (HP-1490-02).** N загрузок мерили хранилище до того, как любая из них записала файл, и все проходили предел, под который помещалась одна. Замер и запись — один атомарный шаг под отдельным замком; отдельным — чтобы медленный обход папки не тормозил сохранения конфига. - **Редакторы снова видят весь холст (HP-1490-03).** Рамка содержимого ограничивала и панорамирование, и координаты указателя, так что после первой комнаты рисовать вторую было негде. Режимы редактирования меряют от полного квадрата; просмотр остаётся по содержимому, а смена режима пересчитывает вид, вместо того чтобы тащить его прижатым не к той основе. - **Сохранение ждёт пропорции выбранного плана (HP-1490-04).** Save до ответа картинки записывал пропорции ПРЕДЫДУЩЕГО файла, и новый план навсегда оставался в чужой форме. Выбор плана сразу стирает старое значение, Save дожидается ограниченного по времени чтения; не дождался — записывается «неизвестно»: честный квадрат лучше унаследованной формы. - Гигиена релиза из §5: package-lock.json догнал версию пакета, задвоенный комментарий в space-geometry.ts убран. ## v1.49.0 — 2026-07-28 **Холст стал квадратным** (см. v1.48.0, выпущена вместе с этой). - **Масштаб открывается по нарисованному, а не по всему холсту.** Пространство без подложки теперь вписывается по границам своих комнат с полями 5%: маленький план на большом холсте заполняет экран, а не сидит посередине точкой. С подложкой ничего не меняется — картинка и есть план, и обрезать её по комнатам значило бы спрятать то, что ещё не обведено. - **Переключение пространств свайпом и в киоске стало с анимацией.** План уезжает туда, куда пошёл палец, следующий приходит с другой стороны. Уважает системную настройку «уменьшить движение». - Кнопка настроек комнаты подписана «Настройки комнаты», а не просто «Комната», и слегка светлеет под курсором. - Слово «курирование» заменено на «фильтрацию» — в интерфейсе, документации и коде. **По ревью v1.47.0** - **Только что выбранный план больше нельзя удалить из того же диалога (HP-1470-02).** Он ещё не сохранён, поэтому сервер справедливо считал его свободным — а сохранение потом записывало ссылку, за которой нет файла. Кнопка заблокирована, и, поскольку два клиента могут сделать это в любом порядке, сервер сверяет с диском каждую внутреннюю ссылку, которую конфигурация добавляет, и отказывает, если файла нет. Ссылку, уже записанную в конфигурации, он пропускает: файл может исчезнуть и мимо Home Assistant, а отказ заблокировал бы ровно ту правку, которая его отцепляет. Чужие ссылки не трогаются. - **Загрузки ограничены (HP-1470-01).** По возрасту не удаляется ничего — это дважды стоило настоящих планов, — поэтому предел стоит там, где решение и так принимается: загрузка отклоняется, если хранилище перевалит за 256 МБ или 200 планов (1 ГБ и 1000 для вложений) либо если на диске останется меньше 512 МБ. Список планов отдаётся по 60 самых свежих, миниатюры грузятся лениво. - **Выбор сохранённого плана читает его настоящие пропорции (HP-1470-03).** Карточка ничего не ждала и, если подпись для защищённой ссылки ещё не пришла, записывала пропорции «по умолчанию» — квадратный план получался растянутым. Теперь она дожидается подписи, привязывает результат к тому диалогу, который спрашивал, а превью в диалоге подписывается, как и всё остальное. ## v1.48.0 — 2026-07-28 (холст всегда квадратный) - **У пространства больше нет собственных пропорций.** Область рисования — квадрат, а картинка плана сохраняет свою форму и вписывается в него по центру: у широкого плана появляются поля сверху и снизу, у вытянутого — по бокам. Выбирать нечего, поэтому настройка ориентации холста для пространств без картинки убрана. - **Существующие планы переносятся один раз, при обновлении.** В самом рисунке ничего не меняется: коробка дополняется до квадрата, и все координаты пересчитываются относительно неё — комнаты, двери и окна, декор, позиции значков и сохранённая область просмотра. Углы, пропорции комнат и взаимное расположение сохраняются точно. Для вытянутых планов заодно пересчитывается масштаб в сантиметрах на клетку: сетка привязана к ширине, и без этого стены молча стали бы короче. ## v1.47.0 — 2026-07-28 (выбор из уже загруженных планов) - **Диалог пространства показывает планы, сохранённые на сервере.** Отцепление плана оставляет картинку на диске — так с v1.46.4, но вернуть её можно было только найдя исходный файл у себя и загрузив заново. «Уже загруженные» показывают, что есть: миниатюра, размер файла и то, какое пространство его использует. Клик прикрепляет, пропорции читаются из самой картинки — так же, как при загрузке. - **Там же план и удаляется.** Файл плана никогда не удаляется автоматически — ни за отцепление, ни за возраст, — и это разумная политика ровно до тех пор, пока видно, что именно хранится, и есть способ убрать это осознанно. Кнопка корзины делает это и отказывает, пока план используется пространством: ответ на вопрос «можно ли удалить» даёт сохранённая конфигурация, а не браузер. - Документация догнала код: несколько комментариев всё ещё описывали удаление по возрасту, убранное в v1.46.6. ## v1.46.6 — 2026-07-28 (обещание про отцепление, теперь выполненное) - **Переключение пространства в «нарисовать» больше не удаляет его картинку.** v1.46.4 и v1.46.5 утверждали, что не удаляет, и плановая уборка действительно отцеплённые планы не трогала — но само сохранение удаляло файл в тот момент, когда снималась ссылка, ещё до всех этих проверок. Причина: файл, покинувший конфигурацию, считался «заменённым», а по одной этой разнице замену плана, отцепление и удаление пространства различить невозможно. Удалением, о котором просили, является только первое. Теперь переход классифицируется по пространству-владельцу, и та же разница применяется к вложениям: убрали файл у существующего устройства — он удаляется, удалили устройство — его инструкции остаются. - **План удалённого пространства сохраняется**, а не тридцать дней, как обещала v1.46.5: тридцать дней по возрасту файла всё равно бессмысленны — обычно он загружен месяцы назад. - **По возрасту больше не удаляется ничего**, кроме промежуточной папки диалога. Правило, которое вычищало «отвергнутые загрузки», оказалось в гонке с повторной попыткой: уборка удаляла файл неудавшегося сохранения ровно тогда, когда следующая попытка коммитила ссылку на него. Правило, способное удалить файл, на который кто-то вот-вот сошлётся, не стоит освобождаемого места. Файлы уходят по действию, в остальных случаях остаются. ## v1.46.5 — 2026-07-28 (ревизия всех автоматических удалений) - **Отцеплённый план не удаляется никогда, ни в каком возрасте.** В v1.46.4 ему давался месяц; теперь это навсегда, и причина записана там, где её увидит следующая правка. Правило, оно же в docs/SCOPE.md: компонент вправе удалить файл только тогда, когда об этом говорит действие пользователя — замена плана, удаление вложения, удаление устройства. «На это больше никто не ссылается» таким действием не является. Ошибки несимметричны: занятое зря место видно, стоит копейки и обратимо; удалённый файл — ничего из этого. - **`houseplan/files/cleanup` больше не сносит папку по слову клиента.** После перепривязки устройства файлы копируются под новый id, а старая папка удалялась — через `rmtree`, по тому id, который прислала карточка. Два плохих исхода: при частичном копировании часть ссылок продолжает указывать внутрь этой папки (миграция намеренно их не переписывает — то есть это были живые ссылки на удаляемые файлы), а неверный или устаревший id от любого клиента уничтожил бы инструкции существующего устройства. Теперь сервер сам сверяется с сохранённой конфигурацией, под её блокировкой, и удаляет только то, на что никто не ссылается. - **План удалённого пространства ждёт тридцать дней вместо часа.** Удаление пространства осознанно, но час — короткое окно, чтобы заметить промах. ## v1.46.4 — 2026-07-28 (потеря данных: отцеплённые планы убирались как мусор) - **Отцеплённый план больше не удаляется через час.** Переключение пространства в режим «нарисовать» снимает ссылку и, как редактор всегда и говорил, оставляет картинку на диске, чтобы её можно было вернуть. Уборка, добавленная в v1.46.0, этой разницы не делала: считала «на файл сейчас никто не ссылается» синонимом «файл брошен» и применяла часовое правило. На установке автора плановый проход в итоге удалил два плана этажей, отцеплённых несколькими неделями раньше, — восстановить их было нечем. Если вы отцепляли план после v1.46.0 и инстанс перезапускался или проработал сутки — загляните в `config/houseplan/plans/` и напишите в Telegram-чат, если файла нет. Правило теперь такое: **коммит по-прежнему удаляет ровно то, что заменил**, — это он знает наверняка. Дальше вопрос в том, означает ли «непривязан» «брошен», и ответ зависит от случая. У пространства, у которого плана нет вовсе, его отцепили — и, возможно, вернут: его файлы не удаляются никогда. У пространства, у которого план есть, лишние файлы могут быть только его же отвергнутыми загрузками — они по-прежнему уходят через час. Вложения вне промежуточной папки диалога ждут месяц; сама промежуточная папка, где по построению лежит только загрузка из несохранённого диалога, сохраняет часовое правило. ## v1.46.3 — 2026-07-28 (перепроверка v1.46.2: HP-1462-01) - **Уборка при старте действительно убирает.** Она искала свои же runtime-данные по домену, а во время запуска Home Assistant ещё не считает интеграцию загруженной — поэтому поиск возвращал пустоту, и проход тихо вырождался в удаление незавершённых передач, оставляя настоящую работу таймеру через 24 часа. При перезапусках чаще, чем раз в сутки, она не выполнялась вообще. Теперь используется объект, который у неё и так был на руках. - **Тест, который должен был это доказать, проходил по неверной причине.** Он создавал лишние файлы *до* сохранения конфигурации, а сохранение тоже собирает мусор — так что к моменту перезапуска убирать было уже нечего. Переписан: файлы создаются после сохранения; добавлен второй тест, который дёргает плановый таймер отдельно, и третий, который запускает перезапуск и сохранение одновременно и проверяет, что принятая конфигурация никогда не ссылается на удалённый уборкой файл. ## v1.46.2 — 2026-07-28 (перепроверка v1.46.1: HP-1461-01, -02) - **Файл, который в итоге никому не понадобился, убирается, даже если больше ничего не сохраняют (HP-1461-01).** Сборка привязана к записи конфигурации — это верно для того, что запись вытесняет, но оставляет зазор: отмените диалог после того, как файл уже загрузился, потеряйте связь сразу после, или вызовите API загрузки напрямую — и на файл никто не ссылается, а будущей записи, которая бы это заметила, нет. Добавленное в v1.46.1 ежедневное подметание убирало только незавершённые передачи, поэтому обещание «отменённое вложение исчезнет через час» не выполнялось там, где никто ничего не правит. Теперь подметание сверяется с сохранённой конфигурацией — под той же блокировкой, что и запись, — и собирает устаревшие непривязанные вложения и планы тоже. - **Перетаскивание больше не отменяется чужим перемещением (HP-1461-02).** Когда в v1.46.1 полная карточка научилась следить за позициями, она защищала те, что вы подвинули, но ещё не отправили, — вот только читала этот список *после* сброса отложенной записи, а сброс его первым делом опустошает. При настоящем перетаскивании, когда запись уже запланирована, список оказывался пустым, и старая серверная позиция закрашивала ваше движение. Теперь снимок снимается до сброса, и вдобавок удерживаются позиции, отправленные, но ещё не подтверждённые: пока сервер не подтвердил позицию, авторитет по ней — та карточка, которая её подвинула. - Два теста доросли до своих же описаний: тест загрузки теперь действительно отменяет задачу запроса, а не только проходит по путям ошибок, а смоук синхронизации позиций планирует настоящую отложенную запись и задерживает её — именно этот порядок и терял перетаскивание. ## v1.46.1 — 2026-07-28 (перепроверка v1.46.0: HP-1460-01 … -03) - **Две загрузки с одинаковым именем больше не сталкиваются (HP-1460-01).** v1.46.0 перестала затирать вложения, но выбор свободного имени и его занятие были двумя шагами: две загрузки, попавшие между ними, сходились на одном имени, обе рапортовали успех, и одни байты заменяли другие. Теперь имя занимается атомарно в момент выбора — двадцать одновременных загрузок `manual.pdf` дают двадцать файлов. Тот же механизм используется при переносе файлов на перепривязке, где был ровно такой же зазор. Заодно там же: имя предельной длины теряло расширение, а суффикс коллизии выталкивал его за предел, и вложение сохранялось под именем, которое сервер обратно не отдаёт — вечный 404 на файл, который интерфейс считал прикреплённым. - **Прерванная загрузка больше не оставляет временный файл навсегда (HP-1460-02).** Уборка стояла в `except Exception`, мимо которого отменённый запрос проходит насквозь, а сборщик заглядывает только в папки маркеров — поэтому оборванная передача оставляла `.upload-*`, и убрать его было некому. Теперь убирает любой путь выхода, запрос с двумя файлами отклоняется сразу, а брошенные временные подметаются при старте и раз в сутки. Запись идёт порциями по мегабайту, а не отдельной задачей на каждые 64 КБ. - **Две полные карточки рядом держат одинаковые позиции (HP-1460-03).** v1.46.0 научила следить за перемещениями статическую карточку и оставила позади полную, поэтому перетаскивание иконки в одном окне не двигало её в другом до перезагрузки. Теперь следит — и не мешает собственному перетаскиванию: чужая ревизия, пришедшая в его разгар, сливается, а не накатывается сверху, и карточка не перечитывает то, что записала сама. ## v1.46.0 — 2026-07-28 (полный внешний аудит v1.45.4: HP-1454-01 … -10) **Безопасность** - **Загруженный SVG-план больше не является живым документом origin вашего Home Assistant (HP-1454-01, high — блокер релиза).** Внутри карточки план подключён через ``, где скрипты не выполняются; но тот же URL, открытый напрямую, становился документом верхнего уровня в origin самого HA, и `