Commit Graph
870 Commits
Author SHA1 Message Date
Claude 99e1765d22 feat: режим «Значение + статичный значок» (#588)
Пятый вариант «Отображение»: маркер показывает выбранное значение и при этом
никогда не меняет цвет — ни по состоянию, ни по тревоге, ни по недоступности,
ни под цвет RGB-света, ни по активности.

Четыре прежних режима задавали одним выбором две независимые вещи: что
нарисовано внутри маркера и красится ли он состоянием. Поэтому вместо
сравнения с одним токеном появились два производных предиката рядом с
`normalizeDeviceDisplay` — `displayWantsValue` и `displayIsNeutral`, — и их
спрашивают политика, слой пульсации, внешний бейдж, редактор и три ветки
живого слоя пылесоса.

Две ловушки, из-за которых режим не сводится к одной строке в словаре:

- быстрый путь «статичному маркеру источники не нужны» (`sourceDetails: false`)
  — это основной путь рендера плана, карточки пространства и PDF. Он оставлен
  только режиму без значения: иначе число пропало бы именно на плане и
  осталось в предпросмотре редактора;
- три ветки живого пылесоса сравнивают режим строкой и не читают политику,
  поэтому зелёная политика их не гарантирует. Свидетель держит две
  конфигурации карты: сопоставленная доказывает puck и след, несопоставленная
  — бейдж маршрута (при совпадающей калибровке маршрут `ready`, и бейджа не
  было бы ни в одном режиме). Бейдж проверяется при наполненном буфере
  позиций, иначе его отсутствие объяснялось бы первой веткой.

Потолок initial View перецентрирован 291_700 → 292_400 без изменения общего
бюджета: измеренный факт 291 346 Б оставлял под прежним центром 354 Б —
внутри шумовой полосы метрики.

Эталон: в `device-icon-state-table-{light,dark}` включённая RGB-лампа
переведена в новый режим. Кадры обязаны разойтись; приёмка — отдельным
коммитом класса D с полного линуксового артефакта Validate.

Issue: #588
User-Visible: yes
2026-09-18 13:40:57 +03:00
Claude a6185e295d Prepare v1.77.0-beta.1
Package the reviewed furniture footprint fix with synchronized release metadata; the golden-manifest platform, composite CI proof, strict screenshot-freshness switch and stable Full Performance base ride along internally.

Release: v1.77.0-beta.1
Issue: #571
Issue: #573
Issue: #584
Issue: #586
Issue: #587
User-Visible: yes
2026-09-18 09:32:55 +03:00
Codex 3f95dac451 fix: индекс эталонов хранит платформу съёмки, а не платформу приёмки (#571)
Аудит 14.09, §4 и §9. `golden-report.json` не нёс платформу вовсе, поэтому
приёмщик вызывал `captureEnvironment()` у себя и записывал СВОЮ платформу как
платформу кадров. На `ad4000f9` это дало `"platform": "win32"` у кадров,
снятых Linux-прогоном 34853080375, а причина осознанного обхода осталась в
stdout и в индекс не попала — хотя `AGENTS.md` обещает след в обоих местах.
Сами PNG были и остаются целы: 101 свидетель совпал байт-в-байт. Врал
провенанс.

Что сделано:

- отчёт съёмки получил раздел `capture`: платформа, архитектура, сборка
  Chromium, отпечаток материала и — в CI — прогон с попыткой и SHA. Схема
  отчёта поднята до 2;
- приёмка читает среду съёмки из отчёта. Гейт чужой среды теперь судит обе
  стороны: съёмку (из отчёта) и приёмку (свою). Отказ — до единой записи;
- индекс эталонов поднят до схемы 2 и различает `capturedOn` и `acceptedOn`,
  несёт раздел `capture` и причину осознанного обхода в `foreignCapture`;
- отчёт схемы 1 платформы съёмки не несёт физически: это отдельная явная
  ветка, `capturedOn` уезжает `null`. Выдумывать платформу нельзя — ровно этим
  задача и вызвана;
- `--baselines=<dir>` у приёмки: без него проверить «отказ произошёл ДО
  записи» можно было бы только порчей рабочего дерева, то есть никак (#556).

Осознанно отменено решение #455 «не трогать run.mjs»: ради ГЕЙТА цена
фингерпринта не окупалась, ради ПРОВЕНАНСА окупилась — платформу кадров знает
только тот, кто их снял. Плата разовая: пересобран бандл, индекс скриншотов
документации переснят отдельным коммитом. Тест #455 переписан под новый
инвариант, а не удалён.

Свидетели: `test/golden-capture-provenance.test.mjs` — семь проверок, все пять
сценариев приёмки из issue, включая «отказ до записи» и «подмена PNG и неполный
артефакт по-прежнему fail-closed». Мутанты `golden-index-invents-capture-platform`
(возвращает платформу приёмщика) и `golden-report-provenance-optional`
(разрешает отчёт схемы 2 без провенанса) прогнаны лично: оба краснеют.

npm test 2762/2761/0 fail, typecheck чистый.

Issue: #571
User-Visible: no
2026-09-17 23:19:56 +03:00
Codex ef3bc6d133 fix: габарит мебели равен заявленным размерам (#584)
Указанные ширина и глубина теперь совпадают с видимым габаритом предмета.
Раньше рисунок занимал внутри своего бокса около 88 % стороны, поэтому
«Кухонный напольный модуль» 60 × 60 выглядел меньше «Посудомоечной машины»
60 × 60 примерно на 14 % по стороне и на 30 % по площади: цифры совпадали,
картинка врала.

Пак `fix-584-1` от дизайнера (issue, комментарий от 16.09) проверен исполнением
своей метрикой, а не его отчётом: границы считаются аналитически по той же
математике, что у продакшен-экспорта в PDF. Все 44 плановых SVG заполняют
`viewBox` с худшим отклонением 0.000000 при допуске ТЗ 0,1; `pack.json` и 33
иконки меню побайтно прежние. Для сравнения, прежний набор в `dev` давал 65
нарушений того же контракта.

Что сделано в коде:

- `scripts/svg-path-bounds.mjs` — границы рисунка по настоящим экстремумам
  кривых (дуги приводятся к кубикам). Контрольные точки в габарит не входят:
  иначе «заполняет бокс» проверялось бы по выпуклой оболочке и поля проходили
  бы мимо. Генератор — `.mjs` и обязан работать без сборки TypeScript, поэтому
  разбор здесь свой; тест сверяет его с `parseSvgPath` продакшена на всей
  библиотеке, чтобы реализации не разъехались молча.
- `scripts/furniture-path-join.mjs` — склейка нескольких `<path>` с
  канонизацией только начального `moveto`. Приём подсказан патчем в поставке
  дизайнера; реализация и свидетели свои. Прежний `paths.join(' ')` продолжал
  координаты предыдущего пути: замер показал, что у иконок меню `stairs` и `tv`
  части рисунка уезжали за `viewBox` 110 × 110 — до 119. Теперь склейка
  побайтно воспроизводит «каждый путь из своего нуля».
- генератор проверяет плановый символ по контракту: один путь, подконтуры с
  абсолютной `M`, рисунок заполняет `viewBox` (допуск 0,1).
- `src/furniture.ts` — legacy `plant` растянут от центра в 1/0.96. Это
  единственный из двенадцати retained-примитивов с полями (0.02…0.98 unit box);
  форма прежняя, габарит стал заявленным.

Свидетели: `test/furniture-visual-bounds.test.mjs` (AC1–AC3, AC5 и сверка двух
реализаций границ) и `test/furniture-path-join.test.mjs` (AC4, включая реальные
`stairs`/`tv`). У AC1 есть положительный контроль: та же функция обязана видеть
поля на геометрии из шапки issue — утверждение «полей нет» стоит ровно столько,
сколько стоит измерение. Мутанты `furniture-symbol-may-keep-inner-padding` и
`furniture-paths-joined-without-reset` возвращают прежнее поведение и краснеют;
прогнаны лично через `mutation-gate --id=`.

Миграции пользовательских данных нет: координаты, размеры, поворот и
зеркалирование сохраняются.

npm test 2743/2742/0 fail, typecheck чистый, furniture:check зелёный.

Issue: #584
User-Visible: yes
2026-09-16 23:02:11 +03:00
Codex ca74a5c2ee Release v1.76.0
Promotion-only на вершине v1.76.0-beta.5: семь источников версии, снимки
собранного бандла и релизные метаданные. Продуктовый код в этом коммите не
двигается.

Линейка агрегируется от стабильной v1.75.0. Пользователю: щипковое
масштабирование в приложении Home Assistant больше не рвёт картинку — на
больших планах с фоном «Следует за Солнцем» пропали фиксированные белые
провалы (#582), план перестал переключаться между режимами композитинга
посреди жеста (#579), а щипок, начатый на значке устройства, не запускает его
действие и не открывает два окна сразу (#578, #563). Появился выбор источника
солнечных лучей — от внутренних или внешних углов окна (#577). «Как у
пространства» снова возвращает комнате цвет пространства и лечит застрявшие
(#581). Близко стоящие значки не перехватывают нажатие друг у друга, а
клавиатурный фокус получает ту же подсказку, что и мышь (#564, #565). План,
изменённый в другом браузере, не откатывается (#543), и при перетаскивании у
края не появляется пустая полоса (#544). Мельче: #561, #554, #545, #580.
Внутреннее в линейке: #583, #547, #556, #560, #566, #567, #568, #569.

Из тела исключён #580: этот дефект жил только внутри бета-линейки — режим
внешних углов окна (#577) не выходил ни в одном стабильном релизе, поэтому
пользователю он «исправлением» не является. В ченджлоге он остаётся.

Записано, а не замолчано: индекс свежести скриншотов документации устарел с
коммита 699ab471, а гейт Validate, который обязан был это поймать, лишь
предупреждает — режим выбирается сравнением с многострочным выводом CLI
(#586). Одиннадцать кадров документации от той правки измениться не могли: ни
одна из сцен не рисует скрытый 2.5D-вид, а отпечаток считается по всему
`src/**`. Пересъёмка требует Chromium, которого в этой песочнице нет.

npm test 2720/2719/1 fail (только bundle-tree до этого коммита), typecheck
чистый, контракт релиза зелёный на всех семи источниках, тело проходит #328
(`release:notes --verify`), check-docs зелёный кроме отпечатка скриншотов.

Issue: #582
User-Visible: yes
Release: v1.76.0
2026-09-16 15:34:35 +03:00
Codex 699ab4710f perf: coarse lattice with refinement for isometric overlay placement (#583)
Разрешение коллизий 2.5D-подписей сканировало диск смещений с шагом 1 px и
для каждого кандидата спрашивало пространственный хэш и все стены. Замер
показал: на large-house-isometric-v1 580 размещений дают 2 523 652 смещения и
1 742 740 проверок отпечатка против стен, 98 % позиций отвергают стены.

Поиск переведён на решётку 4 px с уточнением 1 px вокруг найденного места
(и вокруг лучшего конфликтующего кандидата — без второго уточнения качество
разрешения падало с 308 до 304). Дешёвая часть кандидата (позиция, габариты,
конфликты, штраф) отделена от дорогой (комната-владелец, непрерывность
сегмента, зазор до стены); соседи считаются один раз на элемент; расстояния
таблицы смещений предвычислены; добавлены AABB комнаты-владельца и широкая
фаза по стенам.

Групповой проход 9584 → 839 мс, смещений 2 523 652 → 157 618, разрешено
308 / остаток 272 — как до правки.

Issue: #583
User-Visible: no
2026-09-16 13:58:31 +03:00
Claude 1734b077af Prepare v1.76.0-beta.5
Package the reviewed sun-ray occlusion, room-colour inheritance and HA Companion day-cycle compositor fixes with synchronized release metadata; the hidden 2.5D refinement rides along internally.

Release: v1.76.0-beta.5
Issue: #580
Issue: #581
Issue: #582
Issue: #583
User-Visible: yes
2026-09-16 10:25:10 +03:00
Sergey Matyunin 85a5c7387e test: repair isometric golden host-face contract (#583)
Issue: #583
User-Visible: no
2026-09-16 09:29:25 +03:00
Sergey Matyunin 5cae93501c fix: refine hidden 2.5D presentation (#583)
Issue: #583
User-Visible: no
2026-09-16 02:57:47 +03:00
Sergey Matyunin 54dc836dee fix: закрыть compositor-пути day-cycle (#582)
Issue: #582
User-Visible: no
2026-09-15 13:41:51 +03:00
Sergey Matyunin 2a8b5f1dcf fix: стабилизировать day-cycle при pinch в HA Companion (#582)
После первого движения камеры переносит фильтр контура на ограниченный размером viewport слой, сохраняя исходный статичный рендер без изменений.

Issue: #582
User-Visible: no
2026-09-15 12:20:44 +03:00
Sergey Matyunin a68e4c6b80 fix: ограничить дневной контур размером экрана (#582)
Issue: #582
User-Visible: yes
2026-09-15 12:17:27 +03:00
Claude 2bec03e6fa fix: «Как у пространства» забывает свой цвет комнаты (#581)
Режим заливки комнаты и её цвет — два поля конфига под одним переключателем.
«Как у пространства» снимало только режим; цвет оставался и продолжал
применяться, потому что `roomCustomFillOf` отдавал цвет комнаты независимо от
того, чей режим `custom` действует. Так возникало безымянное состояние «режим
наследую, цвет свой» — Cabinet на даче.

Теперь цвет комнаты участвует в раскраске только вместе с её собственным
`fill_mode: 'custom'` (одна функция — все поверхности: карточка, space-card,
PDF, черновик диалога). Диалог загружает цвет в черновик только при своём
режиме, обнуляет его при уходе с «Свой цвет» и показывает строку цвета только
под этим радио; сохранение пишет `custom_fill` только с `fill_mode: 'custom'`,
иначе удаляет — включая сироту от прежнего редактора. Чтение конфиг не
переписывает: застрявшие комнаты выздоравливают обновлением.

- `test/logic.test.mjs`: AC1 — сирота и любой чужой режим → цвет пространства
- `demo/smoke_room_settings.mjs` шаг 7: свой цвет → «Как у пространства» →
  ни режима, ни цвета, во View цвет пространства; сирота открывается как
  наследование, сохранение её удаляет (проверено красным на базе: 9 фактов)
- `demo/smoke_space_settings.mjs`: override с собственным режимом + сирота
- `demo/golden/harness.mjs`: `roomCustomFill` ставит комнате её режим —
  кадры `lighting-custom-glow-*` не меняются
- мутант `room-orphan-colour-wins-again`
- docs: ARCHITECTURE (#56), CONFIG-COMPATIBILITY, USER-GUIDE ru/en, TESTING;
  отпечаток скриншотов принят попиксельно (11 кадров)

Issue: #581
User-Visible: yes
2026-09-15 09:48:37 +03:00
Sergey Matyunin a32b280be8 fix: типизировать геометрию солнечных лучей (#580)
Issue: #580
User-Visible: no
2026-09-15 09:05:58 +03:00
Sergey Matyunin d2c7e6f701 fix: учитывать откосы для внешних солнечных лучей (#580)
Issue: #580
User-Visible: yes
2026-09-15 09:05:58 +03:00
Sergey Matyunin d37b2c9f8a Prepare v1.76.0-beta.4
Проверка (CI) / Классификация изменённых файлов (push) Successful in 25s
Проверка (CI) / Предполёт: документация, провенанс, процесс (push) Failing after 44s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 22s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 20s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 39s
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Failing after 2m3s
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Failing after 2m7s
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Failing after 3m31s
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Failing after 1m39s
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Failing after 1m37s
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Successful in 2m32s
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Failing after 10m11s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Failing after 7m10s
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Доказательство выполненных проверок (push) Failing after 15s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 9m6s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Package the reviewed sunlight-origin option and Home Assistant touch-pinch fixes with synchronized release metadata.

Release: v1.76.0-beta.4
Issue: #577
Issue: #578
Issue: #579
User-Visible: yes
2026-09-15 01:58:45 +03:00
Sergey Matyunin 0d1df78f5d test: применять внешний луч как глобальную настройку (#577)
Issue: #577
User-Visible: no
2026-09-15 00:58:06 +03:00
Sergey Matyunin a0e5fb1b3b test: закрепить внешний луч на толстой стене (#577)
Issue: #577
User-Visible: no
2026-09-15 00:47:40 +03:00
Sergey Matyunin 6f6a85a116 fix: типизировать настройку граней окна (#577)
Issue: #577
User-Visible: no
2026-09-15 00:17:41 +03:00
Sergey Matyunin db4b397e2e feat: выбор граней окон для солнечных лучей (#577)
Issue: #577
User-Visible: yes
2026-09-15 00:16:35 +03:00
Sergey Matyunin 216990e469 fix: keep SVG compositor stable during pinch (#579)
Issue: #579
User-Visible: yes
2026-09-14 22:28:09 +03:00
Sergey Matyunin 5790abaa1f fix: suppress device activation during touch pinch (#578)
Issue: #578
User-Visible: yes
2026-09-14 21:23:58 +03:00
Sergey Matyunin e5fe4364dc Prepare v1.76.0-beta.3
Package the validated Stage 4 candidate while keeping the isometric experiment hidden and the default Flat experience unchanged.

Release: v1.76.0-beta.3
Issue: #570
User-Visible: yes
2026-09-14 17:02:49 +03:00
Sergey Matyunin 258896cb6f feat: refine hidden isometric Stage 4 (#570)
Issue: #570
User-Visible: no
2026-09-14 15:29:57 +03:00
Sergey Matyunin c22c04d647 Prepare v1.76.0-beta.2
Проверка (CI) / Классификация изменённых файлов (push) Successful in 1m20s
Проверка (CI) / Предполёт: документация, провенанс, процесс (push) Failing after 1m54s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 25s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 25s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 1m28s
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Failing after 2m19s
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Failing after 3m22s
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Failing after 3m45s
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Failing after 1m36s
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Failing after 38s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Failing after 21s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 2m36s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Failing after 2m40s
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Failing after 14m19s
Проверка (CI) / Доказательство выполненных проверок (push) Failing after 15s
Package the validated beta candidate with the current S8 membership and synchronized release metadata.

Release: v1.76.0-beta.2
Issue: #556
Issue: #558
Issue: #560
Issue: #563
Issue: #564
Issue: #565
Issue: #566
Issue: #567
Issue: #568
Issue: #569
User-Visible: yes
2026-09-14 10:34:03 +03:00
Sergey Matyuninandclaude[bot] dded4fbd5c fix: сохранить клавиатурную подсказку (#565)
Issue: #565
User-Visible: yes
2026-09-14 07:06:16 +00:00
Sergey Matyuninandclaude[bot] 6aca447fa0 fix: улучшить доступность View (#565)
Issue: #565
User-Visible: yes
2026-09-14 07:06:16 +00:00
Sergey Matyunin f9ed9d2ae8 fix: сохранить точную активацию маркера (#564)
Issue: #564
User-Visible: yes
2026-09-14 02:57:50 +03:00
Sergey Matyunin 6de854a03d fix: разрешить перекрытия целей маркеров (#564)
Issue: #564
User-Visible: yes
2026-09-14 02:57:50 +03:00
Codex 03983946c5 Источники радара сравниваются по смыслу, а не по тексту
Гард `keepTwoPoint` решал, сохранять ли двухточечную калибровку, сравнением
`JSON.stringify`, то есть текста. Порядок ключей `sources` при этом меняет сам
билдер: `slots`/`ranges`/`zones`/`occupancy_entity`/`count_entity` он удаляет и
дописывает заново, а `availability_entity` остаётся на месте и уезжает в начало.
Конфиг, только что записанный этим же билдером, при следующем открытии
сравнивался неравным — и радар с `availability_entity` терял `refs` и `rms_cm`,
получая `method: manual`, при первом же обычном сохранении.

Сравнение стало каноничным по порядку ключей объектов и осталось чувствительным
к порядку элементов массивов: позиция слота — это его `target_N`. Проекция не
затронута — она считается от `mount`, `cell_cm` и `mirror`.

Issue: #567
User-Visible: no
2026-09-13 23:23:30 +03:00
Sergey Matyunin cc0b41ba61 test: восстановить запас bundle-ratchet для #563
Issue: #563
User-Visible: no
2026-09-13 18:53:06 +03:00
Sergey Matyunin aa13e2264e fix: блокировать нажатия устройств после pinch (#563)
Issue: #563
User-Visible: yes
2026-09-13 18:44:07 +03:00
Sergey Matyunin 66bf277da2 Prepare v1.76.0-beta.1
Prepare the first beta after stable v1.75.0 from the exact integrated dev
tree. Version sources, bilingual changelogs, release notes, status and both
committed bundle snapshots move together.

Pinned local proof: Node 22.23.2 and Python 3.14.7; npm test 2618 passed,
0 failed, 1 skipped; production bundle sync and budget passed; config reload,
pan coverage, post-write adoption and summary-panel browser smokes passed;
targeted pure backend 197 passed. Bundle headroom is 12,830 B, below the
warning threshold but inside the enforced ceiling.

Issue: #541
Issue: #542
Issue: #543
Issue: #544
Issue: #545
Issue: #546
Issue: #547
Issue: #548
Issue: #549
Issue: #550
Issue: #551
Issue: #553
Issue: #554
Issue: #555
Issue: #557
Issue: #561
Issue: #562
User-Visible: yes
Release: v1.76.0-beta.1
2026-09-13 16:15:37 +03:00
Sergey Matyunin bb35af993a fix: сохранить identity карточек Masonry после reload (#561)
Сводная панель теперь использует канонический порядок карточек Home Assistant и не переносит локальные настройки между визуальными колонками после remount.

Issue: #561
User-Visible: yes
2026-09-13 02:04:45 +03:00
Sergey Matyuninandclaude[bot] 51ead265f0 fix: avoid double disk reserve for staged uploads (#554)
Issue: #554
User-Visible: yes
2026-09-12 20:56:45 +00:00
Sergey Matyunin 81daebd788 fix: complete radar source inventory (#545)
Issue: #545
User-Visible: yes
2026-09-12 23:19:16 +03:00
Sergey Matyunin a1fac44d72 fix: не откатывать конфигурацию поздним reload (#543)
Issue: #543
User-Visible: yes
2026-09-12 22:29:16 +03:00
Sergey Matyunin 6502f516f9 fix: keep live pan edges covered (#544)
Issue: #544
User-Visible: yes
2026-09-12 20:44:05 +03:00
Claude 2c6410bb87 Release v1.75.0
Promotion-only on top of v1.75.0-beta.1: seven version sources, the
generated bundle snapshots and the release metadata. No product source
code moves in this commit.

The line aggregates from the stable v1.74.0 and carries one user-visible
fix. The House Plan sidebar page could serve a previous version of the
card for hours: the panel entry fetched it through `./houseplan-card.js`,
a relative specifier, and relative resolution does not inherit the `?v=`
a dashboard gets from its Lovelace resource, while the entry files carry
no Cache-Control at all. The panel now imports the implementation by its
content-hashed name, so either the matching card arrives or the panel
says out loud that the page is stale (#535). Internal in the line: #536.

Known contradiction, recorded rather than silenced: the release contract
in scripts/release-contract.mjs requires the grouped "small fixes"
bullet unconditionally, while `npm run release:notes -- v1.75.0
--verify` rejects it because every user-visible issue of the range is
already itemised. The two rules deadlock any stable with a single
user-visible issue. The bullet stays, because the contract is the
automated gate that Validate enforces; the verifier's objection is
written down in STATUS and will get its own issue.

npm test 2532/2531/0 fail, release contract green on all seven sources,
docs strict green.

Issue: #535
User-Visible: yes
Release: v1.75.0
2026-09-12 09:02:29 +03:00
Claude e921d5906d Prepare v1.75.0-beta.1
Seven version sources move together to 1.75.0-beta.1, both changelogs
close their section over what has landed since the stable v1.74.0, the
release notes carry the one shipped bullet on each side with the grouped
small-fixes bullet last, and STATUS says what this beta is.

What the user gets: the House Plan sidebar page can no longer serve a
previous version of the card. The panel entry fetched it through
`./houseplan-card.js` — a relative specifier, and relative resolution
does not inherit the `?v=` a dashboard gets from its Lovelace resource,
while the entry files carry no Cache-Control at all. A browser was free
to answer from its own heuristic cache for hours, and a stale loader
named a stale immutable chunk, so the panel ran an old card against the
current backend with nothing but the version banner to show for it —
and reloading could not help, because the address never changed (#535).

Internal in the line: #536 — the version banner now asks the host to
repaint when it drops the notice on disconnect, instead of leaving its
removal to whatever unrelated update happened to run next.

npm test 2532/2530/0 fail (the #349 manifest-tracking check goes green
with this commit), release contract green on all seven sources, bundle
287 323 B gzip inside the ceiling, docs strict green.

The `Release:` trailer is what asks CI for the heavy gates — smokes,
golden and the full performance comparison — on this exact SHA (#479).

Issue: #535
User-Visible: yes
Release: v1.75.0-beta.1
2026-09-12 07:18:21 +03:00
Claudeandclaude[bot] 1e1880f010 Tell the host when the version notice goes away with the element
The controller dropped its banner on disconnect without asking the host
to repaint. Lit renders neither on disconnect nor on reconnect, so the
markup produced before the detach outlived it: the notice stayed on
screen while the controller no longer owned one, and it left only when
some unrelated update happened to run. Correctness rested on a
coincidence.

Measured on the built module with a counter: the sequence mismatch ->
disconnect -> versions agree -> connect asked for exactly one repaint,
the one that showed the notice. It now asks for two, and the second is
the one that takes the notice away.

Nothing else about the teardown changes. The field is still cleared
because a detached element cannot deliver animationend, reconnect still
rebuilds the notice from the retained input, and a disconnect with no
notice still asks for nothing.

Issue: #536
User-Visible: no
2026-09-12 03:49:46 +00:00
Claudeandclaude[bot] 063de0eef4 Let the panel reach the card by its hashed name, not by the one address without a version
The sidebar page could serve a previous card for hours. It imported the
card through the stable facade, `./houseplan-card.js` — a relative
specifier, and relative resolution does not inherit a query. A dashboard
reaches the same file as `houseplan-card.js?v=1.74.0`, so an upgrade
changes its URL and the browser must refetch. The panel always asked for
the same address, and entries are served with no Cache-Control at all —
only ETag and Last-Modified — so the browser applies heuristic freshness
and may answer from cache without asking. A stale 1164-byte loader names
a stale chunk, chunks are immutable for a year, and the panel then ran a
previous card against the current backend without a single error. The
version banner was telling the truth; reloading could not help, because
the address never changed.

Rollup already emits the right edge: the panel's side-effect import
points straight at the shared implementation. The rewrite in
entryFallbackPlugin replaced it with the facade for a fallback that the
hashed name gives anyway — and better: a chunk the manifest no longer
serves now raises the panel's own "House Plan was updated" notice
instead of silently working on old code.

Two #486 assertions change meaning and are rewritten, not adjusted: the
panel no longer routes through the facade, and its initial graph no
longer contains it. The invariant they defended — the panel reuses the
exact card graph, never a second copy — is now stated over the
implementation, and a new test pins that no built entry reaches the card
by an address without a version.

Issue: #535
User-Visible: yes
2026-09-11 22:12:11 +00:00
Codex 5afdb644c7 Смена пространства выбрасывает слой, а не сверяет его поэлементно
#525 увёл оба списка сцены с `map()` на `repeat(items, (item) => item.id, …)`,
чтобы Lit не переиспользовал узлы по позиции и не проигрывал анимацию двери,
которой не было. Правка верная, но на плане с двумя сотнями маркеров она
оказалась дорогой ровно там, где пользы не приносит: при смене пространства
ключи не пересекаются вовсе, и `repeat` строит две карты ключей и обходит оба
списка, чтобы затем всё равно выбросить всё и создать заново.

Бисект по медиане `switchCycleMs` на `large-house`: 871,2 перед #525 → 953,5
после. На раннере эти 80 мс распадаются на шесть-девять дополнительных длинных
задач, и `longTask.countP95` вышел за порог стабильного гейта.

Теперь оба списка рендерятся как `keyed(space.id, repeat(…))`. Внешний ключ
делает смену пространства: поддерево выбрасывается целиком, дифа нет. Внутренний
остаётся, потому что состав списков едет и внутри пространства — у маркеров от
призраков редактора и живого синка, у проёмов от записи с нерешённым хостом,
которая живёт только в режиме plan, — а переходы на `.device-shell-frame`,
`.op-leaf` и `.op-arc` никуда не делись.

Замер после правки: `switchCycleMs` 889,1 против 936,0 на `main` и 871,2 до
#525. Потолок карточки поднят на одну строку — на `import { keyed }`;
переносить нечего, сам рендер не вырос ни на символ.

Issue: #534
User-Visible: yes
2026-09-11 22:30:11 +03:00
Claudeandclaude[bot] ced9b41642 Keep the day-cycle outline on its own compositing layer
The "Follows the sun" background made the plan crawl in Firefox: 23 MB of
textures per frame, sixteen of about twenty picture-cache tiles thrown
away every frame, nine frames per second. The card's own JavaScript was
idle for 89 % of that.

The cost is the outer outline. It is a triple drop-shadow over the
grouped paper footprint, and although the group holds paper silhouettes
only and never changes on hover or pan, the filter lived in the plan's
own layer — so every repaint of the plan re-ran three blur passes over
the whole sheet. One hint moves the filtered paper into its own layer
and unhooks it from the plan's repaints.

Measured on a demo-stand pan (Chromium, CDP, summed RasterTask): 1456.6
ms against a static background's 96.7 ms before, 84.7 ms against 103.2
ms after. The new smoke measures that ratio and fails above two.

The picture does not change: the outline outside the plan matches byte
for byte and the frame's mean colour moves from 176.59 to 176.66 of 255.
Splitting the layer does move the remaining content onto a different
sub-pixel grid, so the diagonal wall hatch anti-aliases differently and
the four day-cycle baselines are re-taken on the beta candidate.

Issue: #532
User-Visible: yes
2026-09-11 17:01:04 +00:00
Codex 116cfd5fef Prepare v1.74.0
Seven version sources move together to 1.74.0; both changelogs gain the
stable section aggregated from the previous stable v1.73.0, the release
notes carry three itemised bullets on each side plus the grouped
small-fixes bullet, and STATUS says what this release is.

What the user gets since v1.73.0: the plan is noticeably smoother and in
Firefox dramatically so — a pan frame now moves what is already drawn by
a composited transform with the scene re-rasterizing on a budget (#531),
and a marker shadow sized in container units no longer restarts a
non-composited animation on every marker at once (#524); the printed plan
is about a third larger, because the in-plan dimension labels shrank and
the separate column of external dimensions is gone (#530); a plan left
over from the era of rooms without walls can be edited again, the
leftover cleaned up on the first save instead of refusing every change
(#529, reported in #527). Grouped under small fixes: alignment guides
follow the gesture again (#521), the summary panel neither freezes the
first frame nor claims an unavailable source (#509) and its settings
dialog scrolls again (#508), a space switch no longer replays a
neighbouring door's leaf (#525), and the card downloads 12.8 KB less on a
cold start (#526).

The speed verdict for #531 is deliberately not claimed here: headless
Firefox and Chromium hold 60 fps on both the old and the new path, so it
is owed by a profile from the owner's machine on the same pan.

`npm test` 2528/0/1 skip, `pytest tests_backend` 467 passed, release
notes pass the #328 verifier against v1.73.0..HEAD, bundle 287 242 B gzip
inside the ceiling, docs strict green.

Issue: #531
User-Visible: yes
Release: v1.74.0
2026-09-11 17:25:52 +03:00
Codex 45d44608a1 Prepare v1.74.0-beta.3
Seven version sources move together to 1.74.0-beta.3; the changelog
sections in both languages close over what has landed since beta.2, the
release notes carry the two shipped bullets on each side with the grouped
small-fixes bullet last, and STATUS says what this beta is.

What the user gets: dragging the plan is smooth again — a gesture frame
now moves what is already drawn by a composited transform, and the scene
re-rasterizes on a budget (100 ms, or a 15 % shift) instead of on every
frame, which on the owner's 144 Hz Firefox cost 200 ms per frame with the
refresh driver skipping 124-144 ticks a second waiting for paint (#531);
and the printed plan is about a third larger, because the in-plan
dimension labels shrank by a quarter and the separate column of external
dimensions is gone, so the drawing keeps a whole scale step (#530).

The speed verdict for #531 is deliberately not claimed here: headless
Firefox and Chromium hold 60 fps on both the old and the new path, so it
is owed by a profile from the owner's machine on the same pan.

`npm test` 2528/0/1 skip, release contract green on all seven sources,
bundle 287 238 B gzip inside the ceiling, docs strict green.

The `Release:` trailer is what asks CI for the heavy gates — smokes,
golden and the full performance comparison — on this exact SHA (#479).

Issue: #531
User-Visible: yes
Release: v1.74.0-beta.3
2026-09-11 15:06:32 +03:00
Codex 77a3d2607c Пересборка бандла и отпечатка доков после ребейза на dev
Ребейз на `dev` (#530) обнулил обе производные копии: хэши чанков считаются от
содержимого, а отпечаток скриншотов — от `src/**`. Пересобрано, отпечаток
принят с `--identical`: все 11 кадров попиксельно совпали.

Issue: #531
User-Visible: no
2026-09-11 14:25:35 +03:00
Codex 58e31668c9 Панорама двигает сцену трансформом, viewBox пишется по бюджету
Перезапись `viewBox` — это не сдвиг, а инвалидация растеризации всей сцены.
Кадр жеста делал её каждый раз: в профиле владельца (Firefox 155, 144 Гц) кадр
доезжал до экрана 200 мс, а драйвер пропускал 124–144 тика в секунду с пометкой
«ждём краску».

Теперь `paintLiveViewport` держит якорь — кадр, чей `viewBox` записан в DOM, и
момент записи. Кадр жеста двигает узлы сцены тем же проективным преобразованием,
которым уже двигались HTML-слои, а `viewBox` переписывается по бюджету: 100 мс
либо 15 % сдвига/масштаба. Ни атрибут, ни стиль не пишутся, если строка не
изменилась.

Issue: #531
User-Visible: yes
2026-09-11 14:23:48 +03:00
Claudeandclaude[bot] 2e26116bbb Print the plan a third larger and drop the numbered dimension column
The A4 export spent a whole step of the scale series on the "Internal
dimensions" column beside the drawing: a ten-metre house printed 1:100
landscape on a quarter of the sheet while the same plan fits 1:75
upright. The column bought little — "R1" takes as much room beside the
wall as "2.31m" does — and it was read separately from the drawing.

The column is gone. A value with no free lane beside its own wall is
simply not printed; the rectangular rule became the general one. In-plan
type drops to three quarters of its former size (dimensions 5.25 pt,
areas 6 pt, names 6.75/5.25 pt) so the larger drawing is not crowded by
labels that do not scale with it.

On the owner's file the sheet goes from 1:100 landscape to 1:75 upright
and prints 37 values inside the plan against 35 before; the cost is
about seven short values (0.41-1.13 m) that no longer appear anywhere.

Issue: #530
User-Visible: yes
2026-09-11 10:40:05 +00:00
Codex 8f5a08a609 Prepare v1.74.0-beta.2
Seven version sources move together to 1.74.0-beta.2; the changelog
sections in both languages close over what has landed since beta.1, the
release notes carry four bullets on each side with the grouped
small-fixes bullet last, and STATUS says what this beta is.

What the user gets: a plan left over from the era of rooms without walls
can be edited again — the leftover is cleaned up on the first save
instead of refusing every change, pointing at an Optimize that cannot
help and blocking the export too (#529, reported in #527); the plan is
smooth again in Firefox, where a marker shadow sized in container units
restarted a non-composited animation on all markers at once and cost 9.4
frames per second (#524); switching spaces no longer replays a
neighbouring door or marker (#525); and the card downloads 12.8 KB less
on a cold start, because the stylesheet minifier had never actually run
(#526).

Internal in the same line: the space-switch witness judges node identity
instead of a transition that #524 removed (#528), and the review gate
charges a round only for what the round changed (#518).

`npm test` 2520/0/1 skip, `pytest tests_backend` 467 passed, release
contract green on all seven sources, bundle 287 286 B gzip inside the
ceiling, docs strict green.

The `Release:` trailer is what asks CI for the heavy gates — smokes,
golden and the full performance comparison — on this exact SHA (#479).

Issue: #529
User-Visible: yes
Release: v1.74.0-beta.2
2026-09-11 11:49:16 +03:00