# История изменений > Русская версия [docs/CHANGELOG.md](CHANGELOG.md). Переведены записи начиная > с v1.42.0 (2026-07-26); более ранние доступны только в английском файле. > > **Правило проекта:** оба файла пополняются в одном коммите с самим > изменением — как и остальная документация (см. docs/STATUS.md). ## 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, и `