Commit Graph
77 Commits
Author SHA1 Message Date
Matysh 50b163c60c fix(ci): close smoke selection and persisted-type risk blind spots
Issue: #772
User-Visible: no
2026-10-01 19:05:09 +03:00
Claudeandclaude[bot] f0e1c0b8cc fix(warm): revive the editor draft when write access arrives late (#756)
A same-route remount that cannot edit yet - hass arrives after the
element is inserted (the demo's own order), or a non-admin waits for the
server's can_write - keeps the editor in _pendingNavMode and enters it
later through _resumePendingNavMode -> _setMode. The draft revival was
wired only into the immediate warm adoption (_requestMode(..., adopt)):
on the pending path the draft was lost, _warmRevivePending stayed up for
the instance's life, _warmSnapshot stopped writing dlg, and the next
remount brought back the predecessor's stale draft.

The adoption tail (draft revival once under a held refit, then the
settled stage as the refit baseline) is shared by both paths: the
sequencing lives in src/warm-mode-adoption.ts, the refit bookkeeping in
the card's _holdWarmRefit/_releaseWarmRefit. The pending mode still enters through _setMode, the transition
authority smoke_nav_persist holds it to; resumeWarmMode then settles the
revival. _setMode ends the passive boot grace and refits the camera to
a header measured before the editor chrome rendered, so a camera the
pending window left untouched is put back and held exactly as an
immediate adoption holds it; a camera that has already moved on (View
refit, the user's pan, another space) is left to the ordinary refit. A
mode that did not commit, an explicit mode command in the pending window
and a route departure settle the revival too: no outcome leaves
_warmRevivePending up. The core file gives back 4 lines.

smoke_warm_dialogs gains section H through the UI: the three late-write
orders keep mode, draft, dirty baseline and a frame-by-frame identical
viewport; the chain carries this instance's draft, not the predecessor's;
a space switch in the pending window eats the draft. 14 checks are red
on dev. The mutant warm-pending-mode-leaves-revive-waiting is guarded by
the smoke; docs/WARM-REMOUNT.md §2 describes the pending editor.

Issue: #756
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-01 13:56:37 +00:00
Claudeandclaude[bot] 9324d81b5f perf(iso): keep the theme paper across floor switches in 2.5D (#739)
In 2.5D with a backdrop image every floor switch rendered the card twice
before the first frame. The paper key of the first-frame state (#654)
held the space id, so each switch cleared the ready paper: the first
render inserted the loading veil, updated() probed the computed card
background with a temporary span and asked for a second full update,
which removed the veil again. The colour itself never changed: it is the
theme card background, and no space sets those variables. Locally this
second pass was about 50 ms per warm switch on the large house.

The paper under a backdrop is now resolved once per theme identity
(dark mode, default and dark default theme, theme) and card mode. The
state keeps the resolved paper of the current theme and mode beside the
current paper, so a floor with a backdrop is ready in prepare() when that
paper is known -- also after a drawn floor in between -- and the switch
renders once: no veil, no probe, no second update. A drawn plan keeps its
white paper without the DOM. Any change of the theme identity or the
mode, also one made in Flat or in an editor, drops the kept paper, so the
first backdrop floor after load, a theme change and a trip to an editor
take the #654 path unchanged. isoPaperContext still takes the floor; it
deliberately leaves it out of the identity.

Witnesses: the #739 unit test is red on dev at "a floor switch shows no
veil" and on a key-only variant (space dropped, no theme cache) at
"drawn -> backdrop keeps the known theme paper"; the new
smoke_iso_floor_switch is red on dev (2 updates, 1 colour probe and a
veil insertion in every click task). The iso-paper-resolved-per-floor
mutant puts the floor back into the theme identity.

Issue: #739
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-01 10:06:38 +00:00
Claudeandclaude[bot] 36ebabaaec fix(moon): the status line after a warm revive of General settings (#731)
#718 K7 takes the moon status once per opening of General settings,
outside the draft. A warm remount revives the open dialog on a new card
instance, but `_warmReviveDialog` restored only the draft: the new
instance had no opening of its own, so the "Now: ..." line never came
back.

A revive is an opening too. The `settings` branch now asks for the
status the way `_openSettingsDialog` does - through the lazy editor
runtime (`_openMoonStatus` -> `openMoonStatus`): at once when the
runtime is there (an editor revives after `_requestMode(..., adopt)`
has installed it), after it loads in View; once per revive and only
while that revived dialog is still open. The snapshot of now,
`hass.config` and `sun.sun` is the revive's own, nothing of the dead
instance's opening is carried over, the draft key and the dirty flag do
not change. The View graph gets no static moon-status import; other
dialog kinds never ask for the moon chunk.

demo/smoke_moon_status.mjs gains the revive scenarios - View, the plan
editor, a revive while the chunk is still loading, a space-dialog
revive that must not load the chunk; the first three are red on dev.
test/moon-settings.test.mjs executes the revive as a new opening; the
wiring itself is proven by the smoke, not by reading the monolith as
text (#624). docs/SUN.md and docs/WARM-REMOUNT.md say a revive is an
opening; scripts/smoke-links.mjs links the two new symbols to the smoke.

Issue: #731
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-01 06:47:05 +00:00
Claudeandclaude[bot] b998b0b34a feat(moon): the moon with any background, and its status in General settings (#718)
The owner decided on 30.09 that the moon is not part of the "Follow the Sun"
environment but a switch of its own: with a static background (global or a
space's own) the card showed no moon even with the switch on, and the switch
said nothing about why the moon was missing right now.

With a static background there is no environment, so the moon stands in its
own layer, `.hp-moon-sky`: the first child of `.stage` / `.hp-static-stage`,
the whole scene, no z-index, filter or will-change, under the plan by DOM
order, fading with the #101 View weight. Inside is the very #661 element, so
place, size, art and fades are unchanged, and a background switch moves it to
its new parent in the same render without a flicker. The phase comes from the
same `resolveDayCycle`, computed only while the moon is on and on View; without
`sun.sun` both cards keep their 30 s clock ticker and re-render only when the
phase changes (the environment is still compared by its whole fingerprint).

General settings get a second caption line under the moon switch
(`data-moon-status`): one snapshot per opening, judged by the lazy chunk as if
the switch were on, first reason wins (no home, day, below 3°, under 3 %),
numbers rounded and clamped below the threshold they missed. `moonStatus`
decides "shown" with the same `moonShownAt` as the element. It lives in a
WeakMap beside the draft, so it never makes the dialog dirty; a closed
opening's result is dropped. The dialog loads the chunk through the gate's
loader (`withMoon`), now shared by every caller while a load is in flight, so
there is still one fingerprint check and one retry token.

Bundle (same build, against origin/dev): initial View 300 072 -> 300 248 B gzip
(+176 B, under the 500 B of the spec; budget and ceiling not raised); lazy
editor 238 558 -> 238 991 B (+433 B, the line and English strings); lazy moon
11 385 -> 11 712 B (+327 B, layer CSS and status). `src/moon.ts` stays out of
the initial and the editor graph; bundle-budget now refuses an editor/moon
overlap. Monolith metrics: hostRefs 4 885 -> 4 888 — the three `host.` reads of
`src/editors/moon-status.ts` (hass, `_settingsDialog`, requestUpdate) through
its own three-member interface, not the editor port; the other five metrics
are unchanged. houseplan-editor-runtime.ts grows by two lines (import, call).

Tests: AC9/AC10/AC15 and the sky layer in test/moon.test.mjs (the #661
"static -> nothing" check inverted), AC14 and the opening lifecycle in
test/moon-settings.test.mjs, smokes demo/smoke_moon_static.mjs (AC1-AC6; AC1
and AC3 were red on dev) and demo/smoke_moon_status.mjs (AC11/AC12), AC7 in
smoke_daycycle_layer_budget. Golden: two new scenes
(static-bg-moon-gibbous-white-light, static-bg-moon-crescent-south-dark,
matrix v70), the harness checks the moon's parent by background and waits for
the status line in the General settings frames. Four new mutants; the clock
ticker one is a browser guard (201 at the guideline of 200).

Issue: #718
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-01 05:25:21 +00:00
Claude 0d641ffbfd feat(iso): the 2.5D floor is the Flat plane, one wall-top rise for tiles (#713)
- Vertical oblique projection: the floor matrix is the identity and a height
  rises straight up by z·sin 20°, so the on-screen wall height is unchanged
  and the cos 20° foreshortening of the plan, decor and anchors is gone.
- Device tiles and lock badges stand on the wall-top plane with one common
  shift; the #651 placement search no longer runs in the live scene (its
  removal is #714). Room names keep their Flat floor point.
- The 2.5D fit no longer reserves the 48 CSS px nudge budget.
- Switching projection keeps the camera when the previous projection was on
  screen: saving the setting, entering an editor from 2.5D and adopting a warm
  memo from the other projection re-read only the scalar zoom. A cold 2.5D
  start still opens the 2.5D home.
- Opening faces are ordered along the oblique projector (s·y + z).

Witness: demo/smoke_iso_flat_parity.mjs (AC2–AC5, AC11) is red on the old code.

Issue: #713
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-09-30 15:18:00 +03:00
Sergey MatyuninandClaude Opus 5.5 c8c470ed57 feat(view): the moon in its phase over the "Follow the Sun" background (#661)
At dawn, dusk and night the environment shows the moon in the top-left
corner of the scene, behind the plan: computed in the card from the home
coordinates and the browser clock (short Meeus series + topocentric
parallax, within 1.4° / 1.8 pp of JPL Horizons), one designer image under
a continuous phase mask with the lit side always on the left (owner
2026-09-29), a feathered terminator, 3°/3 % thresholds and the 2 s fade of
the window rays. Everything but a small gate lives in the lazy
moon-runtime chunk, with its own 30 s ticker. General settings: "Sun"
becomes "Sun and Moon" with one switch, on for new installations
(DEFAULT_CONFIG), off for existing ones.

The initial View graph sat 728 B under its budget: the gate is paid for by
moving fifteen dialog-only strings of General settings into the lazy
settings dictionary (#459) and by one build fingerprint literal instead of
three, so the graph ends 4 B above dev. Golden: two new moon scenes, and
the two General settings help frames show «Sun and Moon»; the WSL artifact
test fixture now models scenes whose first capture awaits acceptance.

Issue: #661
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-09-30 12:25:46 +03:00
Sergey Matyunin f5c6d70b7c fix: stabilize cold 2.5D first frame
Issue: #654
User-Visible: yes
2026-09-26 09:05:20 +03:00
Sergey Matyuninandclaude[bot] 2452c51d00 feat: вертикальный resize карточки в Sections (#648)
Issue: #648
User-Visible: yes
2026-09-25 13:11:44 +00:00
Claude 255330b9bc Шапка на телефоне: одна строка — вкладки, масштаб и шестерёнка с меню остального (#616)
На окне не шире 480 px шапка карточки и страницы бокового меню занимает одну
строку ≤ 56 px: вкладки пространств (без шестерёнок и «+», прокрутка вбок,
текущая вкладка докручивается в видимую область), масштаб, одна шестерёнка
«Действия и настройки» и у админа слот крестика #647. Заголовок скрыт.

Меню шестерёнки (src/header-menu.ts): редакторы, настройки и добавление
пространства, общие настройки, PDF, помощь, сводная панель и объёмный вид
(alpha) — в фиксированном порядке и с теми же условиями и действиями, что у
прежних кнопок. Пункт закрывает меню; Escape возвращает фокус на шестерёнку;
касание вне меню поглощается прозрачной подложкой. На > 480 px шапка прежняя,
в киоске меню нет.

- три кнопки шапки вынесены в renderHeaderActions — шапка карточки не растёт;
- сводная панель отдаёт свои пункты методом menuItems();
- i18n: title.header_menu (en/ru/de/fr);
- потолок initial View 291 000 → 292 600 (замер 291 635), база bundleBytes;
- смок smoke_mobile_view_header, юнит header-menu, 10 мутантов; смоки
  support_feedback, gear_tabs, modes, toolbar_stable_width переведены на
  меню на ≤ 480 px; подпись вкладки в span.tabtitle без pointer-events;
- USER-GUIDE.ru, UX-MODES, TOUCH-SUPPORT, STYLING-HOOKS, data-hp-contract,
  оба changelog.

Issue: #616
User-Visible: yes
2026-09-25 14:22:36 +03:00
Claudeandclaude[bot] f0ba7c5da9 Основная панель: без счётчика устройств, × редактора в своём слоте — ширина шапки не меняется (#647)
Счётчик «N устр.» и ключ count.devices удалены вместе с правилом
`.head .count` (скрывало счётчик на ≤1100 px). Крестик закрытия редактора
вынесен из активной кнопки режима в отдельный слот `.editor-close-slot`
сразу после группы кнопок режимов: 24 × 24 px (--hp-editor-close-size),
одинаковый в редакторе и вне его; вне редактора слот пуст, aria-hidden,
без фокуса и pointer-events. Кликабельная зона × — весь слот (≥24×24, #195),
глиф 13 px; × виден на любой ширине, где видны кнопки режимов.

Смок smoke_toolbar_stable_width (1400/1000/768/390 px, en/ru): ширина
шапки и отступы кнопок стабильны во всех переходах, × виден, попадание
в край зоны закрывает редактор, нет нового overflow. smoke_editor_tabs,
smoke_edge_cases, smoke_hidden_flag переведены на слот/список устройств.
6 мутантов. docs: UX-MODES.md, STYLING-HOOKS.md, data-hp-contract.json.

Issue: #647
User-Visible: yes
2026-09-25 08:35:57 +00:00
Sergey Matyunin 62d0f50593 feat(editor): перетаскивание кнопки настроек комнаты (#645)
Кнопка сохраняет положение в пределах комнаты только на время сессии редактора,
корректно отменяется при pinch/cancel и учитывается подписями Resize.

Issue: #645
User-Visible: yes
2026-09-25 08:33:07 +03:00
Claude 857369b18b fix(plans): загрузка плана по HTTP, предел 8 МБ проверяется до отправки (#617)
План уходил base64 в WebSocket-кадре: файл больше ~3 МиБ давал кадр больше
4 МиБ, HA закрывал сокет до обработчика, и обещанные 8 МБ были недостижимы.

- бэкенд: HouseplanPlanUploadView (POST /api/houseplan/plans/upload), потоковый
  предел MAX_PLAN_BYTES (read_bounded), общий writer store_plan_upload для view
  и ws_plan_set (контракт WS без изменений);
- карточка: stagePlanFile/uploadPlanFile/renderPlanBackdropGuard в
  backdrop-pick.ts для обоих рантаймов; PlanFilePayload хранит Blob вместо b64;
  SVG больше предела — тост при выборе, растр — диалог #39 только с уменьшенной
  копией, копия больше предела не попадает в staging, 413 называет предел;
- i18n toast.plan_too_large, backdrop.over_limit_body (en/ru/de/fr);
  USER-GUIDE ru/en, CHANGELOG ru/en, docs/testing-notes (#617);
- тесты: test/plan-upload-limit.test.mjs, tests_backend/test_plan_upload.py,
  test_ha_upload.py (#617), smoke_plan_upload_limit.mjs; три смока переведены
  с b64/plan/set на blob/fetchWithAuth; мутанты plan-upload-*;
- база монолита: hostRefs +3 (общий хелпер плана вместо двух копий в рантаймах,
  новый тост уменьшенной копии).

Issue: #617
User-Visible: yes
2026-09-24 19:57:41 +03:00
Claude 82a48ee0ce perf(i18n): словари settings/support/topology — ru/de/fr ленивыми чанками; потолок онбординга (#627)
- ru/de/fr трёх словарей пространств — девять ленивых чанков (по одному на
  пару «пространство × язык»), английский статически как слой отката;
  рантайм — тот же LanguageRuntime (две попытки, отпечаток сборки, fallback,
  общий тост отказа), src/i18n/namespace-language.ts.
- Загрузчики рантаймов онбординга и редактора отдают поверхность в рендер
  только после того, как словарь текущего языка осел; гейт хоста учитывает
  словари загруженной на нём поверхности (смена языка на лету — ветка warm).
  Оверлей Zigbee ждёт topology до первой отрисовки.
- bundle-manifest: граф lazyNamespaceLocaleFiles, девять retry-токенов со
  строгим счётом «ровно один». bundle-budget: потолок онбординга 28 500
  (замер 27 470), редактор 245 400 → 228 900 (замер 227 869), проверки
  ленивости и владения по содержимому.
- Смок smoke_lazy_admin_locale (AC4–AC7); регресс-смоки, переключавшие язык
  синхронно, ждут гейт вместо ослабления проверок; пять мутантов.
- monolith-baseline bundleBytes 2 500 387 → 2 508 676: +10 чанков (rollup intro
  и export на каждый) и записи манифеста; gzip каждой поверхности при этом
  уменьшился.

Issue: #627
User-Visible: no
2026-09-24 14:51:18 +03:00
Claude 9cf848c143 test(smoke-links): правка range-line/unitInput выбирает три смока форм настроек (#639)
#608 поменял событие коммита числа в form-kit, а смоки форм комнаты и
устройства красными увидел только ночной реестр: smoke-select связывал
form-kit лишь с новым smoke_range_line_draft. Явная связь rangeLine/unitInput →
три смока форм, чтобы правка набора контролов гонялась на кандидате ревью.

Issue: #639
User-Visible: no
2026-09-23 12:04:17 +03:00
Claudeandclaude[bot] 1dba818581 fix: clarify unsaved-settings confirmation (#610)
Issue: #610
User-Visible: yes
2026-09-23 06:36:39 +00:00
Claude 8a4ecdea63 fix: commit slider-number input atomically (#608)
Issue: #608
User-Visible: yes
2026-09-23 07:37:30 +03:00
Claude 4c9e013276 fix(dialog): align HA settings form shell (#609)
Use Home Assistant's public dialog tokens for the reviewed 560 px canvas, height cap, single scroller and mobile fullscreen layout. Keep generic dialogs and the native fallback unchanged, with authentic-HA evidence and mutation witnesses.

Issue: #609
User-Visible: yes
2026-09-23 03:18:37 +03:00
Claude 748ebe86b9 test(furniture): link alias browser smoke (#606)
Issue: #606
User-Visible: no
2026-09-21 15:01:18 +03:00
Claude 551d4782fe test: rely on direct smoke selection for #605
The new smoke already names the changed color-picker symbols; an explicit registry link would duplicate the selector's direct evidence.

Issue: #605
User-Visible: no
2026-09-21 13:14:36 +03:00
Claude 08a56953cc fix(settings): polish dialog colours and actions (#605)
Make colour tiles solid, readable and fully clickable; align Data actions and device icon field with the form kit. Cover narrow Windows layouts and both icon-picker branches with a focused browser smoke.

Issue: #605
User-Visible: yes
2026-09-21 13:13:50 +03:00
Claude 0a3e0674cc fix(dialogs): finish discard, switch and room polish (#603)
Issue: #603
User-Visible: yes
2026-09-21 08:53:05 +03:00
Claude e2c0c7ed81 feat(room): «Настройки комнаты» по референсу — серия 3 из четырёх (#600)
§6 SPEC.md референса. Четыре карточки #594 остались, менялось содержимое:

- Basics — Display name и Home Assistant area в одну строку из двух полей
  (#room-name, #room-area — контролы набора); подстановка имени из зоны при
  пустом имени прежняя;
- Fill — «Как у пространства» стала строкой-тумблером (#room-fill-inherit,
  решение владельца Q4): включена — подсказка «Следует за пространством:
  режим»; выключена — сегмент из пяти режимов, который стартует с
  действующего режима пространства, а не с «None». «Свой цвет» — плашка
  вокруг прежнего hp-color-opacity (Q5): свотч, hex, число прозрачности,
  Reset у своего цвета. Границы комфорта при эффективной «Температуре» —
  два поля с единицей °C (#room-temp-min/-max) с плейсхолдерами границ
  пространства, легендой Cold / Comfort / Hot, ошибкой под полями и ссылкой
  «Как у пространства». Модуль room-temperature-controls.ts удалён — его
  разметку заменили поля набора;
- Sensor sources — подзаголовки, прежний сегмент «среднее / конкретный», при
  конкретном — кнопка выбора в стиле селекта и панель с поиском в потоке
  карточки (sourcePicker набора, роль listbox/option; общая с диалогом
  устройства в серии 4). Кандидаты и запись прежние;
- Font sizes — две строки «слайдер + число % + Reset to 100%» с концами шкалы,
  подсказка про размер карточек пространства, образец карточки сохранён
  внутри .hpf-tint (решение владельца Q2).

Футер: Cancel | статус | Save; в create — Keep as walls слева. К10: снимок
черновика при _openRoomEdit (room-form-state.ts поверх dialog-baseline),
в edit Save только при изменениях, закрытие с изменениями спрашивает через
_confirmDanger; в create Save по прежнему условию (имя или зона), отмена без
вопроса — она и раньше значила «не создавать» и возвращала контур на план.
Ошибки черновика: имя (edit) / имя-или-зона (create), нечисло в границах —
подпись под полем, «Review N fields» в футере ведёт к первому полю.

Из eager-листа dialogs.styles.ts удалены .roomtemprange*, .roomdialog .srcrow
и .dropbtn; `overflow-x: hidden` у .body убран — скроллер один (К3).

Смоки переписаны осознанно, с пометкой #600: smoke_room_settings (тумблер
вместо радио, #room-name/#room-area, .hpf-panel .hpf-cand, старт сегмента с
режима пространства), smoke_room_temperature_thresholds (.hpf-temprange,
ссылка сброса). Golden-harness room-temperature — те же селекторы. Новый
фокусный свидетель demo/smoke_room_settings_form.mjs: четыре карточки без
старой разметки, имя и зона в одну строку, оболочка 560 и один скроллер,
тумблер/сегмент/плашка/границы/источники/размеры пишут в свои ключи, Save и
вопрос при закрытии, create-режим, семь полос экранов.

Мутанты: room-save-enabled-without-changes, room-discard-without-asking,
room-fill-segment-starts-at-none, room-temp-min-writes-max. Якорь
form-kit-writes-to-a-neighbour-key прежний. smoke-links: символ
roomTemperatureControls заменён на renderRoomSettingsDialog.

Словарь i18n/settings: девять ключей room.* на четыре локали; в основном
каталоге room.area_label без «(unassigned)». Фикстуры листа диалогов набора
пересняты намеренно (панель — байт в байт, AC11).

Бюджет: стартовый граф 290 575 — потолок ОПУЩЕН 292 200 → 291 600 (ушли CSS
диалога комнаты и модуль границ); ленивый редакторский 239 391 — потолок
238 600 → 240 100 с разбором в bundle-budget.mjs.

Гейты: typecheck, build, bundle:sync (три копии байт в байт), npm test
2790+ pass по четырём частям, mutation-gate --check, смоки: room_settings,
room_settings_form, room_temperature_thresholds, editor_tabs, font_scales,
resize_labels, room_autoclose, binding_ui, color_picker_consumers,
lazy_editor_chunk, space_settings_form, general_settings_form, ux_fixes,
settings_dialog_cards, dialog_footer_width.

Issue: #600
User-Visible: no
2026-09-20 11:39:46 +03:00
Claude 9b0855b3c0 test: связать предикаты режима со смоками (#588)
`smoke-select` на диффе задачи назвал `displayIsNeutral` и `displayWantsValue`
символами, которых нет ни в одном смоке: смок работает через DOM и по имени
предикаты не находит. Запись в реестре связывает их со свидетелями, которые
проверяют следствия — значение внутри маркера, отсутствие классов состояния и
пульсации, подавленный живой слой пылесоса, поля диалога устройства.

Issue: #588
User-Visible: no
2026-09-18 13:47:16 +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 216990e469 fix: keep SVG compositor stable during pinch (#579)
Issue: #579
User-Visible: yes
2026-09-14 22:28:09 +03:00
Claudeandclaude[bot] ab296302d1 test: register the space-switch witness for the two renderers (#525)
`smoke-select` answered НЕОПРЕДЕЛЁННОСТЬ on this diff: the smoke does not
name `_renderDevice` or `_renderOpenings` anywhere — it switches spaces the
ordinary way and reads running transitions off the nodes those renderers
produced. That is exactly the case `scripts/smoke-links.mjs` exists for, and
without the record the next edit to either renderer selects no witness at all.

Issue: #525
User-Visible: no
2026-09-11 01:42:46 +00:00
claude[bot] 2f41c0b29e test(adoption): ownership lint, post-write smoke, harness seam and docs (#500)
`test/config-adoption-ownership.test.mjs` pins identity writes to the owner
and ratchets body staging (AC1/AC2). `demo/smoke_post_write_adoption.mjs`
drives space/delete (both runtimes), Optimize Undo and Import apply with a
concurrent backdrop change between the write and the re-read (AC4). Smokes
that seed revisions from outside the card keep working through the
`seedIdentity` harness seam behind the card's delegate setters. The initial
View ceiling is re-centred with the measured fact; ARCHITECTURE.md gets the
boundary paragraph.

Issue: #500
User-Visible: no
2026-09-10 11:41:16 +00:00
Matysh 05778a47c0 Align summary panel with designer prototype (#505)
Issue: #505
User-Visible: yes
2026-09-09 09:32:36 +03:00
Sergey Matyunin a43bc3eb27 fix: keep summary recovery and live state current (#490)
Issue: #490
User-Visible: yes
2026-09-09 00:10:16 +03:00
Matysh e2751062dc feat: add per-room temperature thresholds
Issue: #487
User-Visible: yes
2026-09-08 10:44:13 +03:00
Matysh 66a2996a65 test: link PDF collision changes to browser smoke
Issue: #484
User-Visible: no
2026-09-07 21:10:03 +03:00
Matysh d277eeb73b feat: export current space as architectural PDF
Issue: #53
User-Visible: yes
2026-09-07 03:47:57 +03:00
Matyshandclaude[bot] a979699a57 fix: keep editor writers at optimizer fixed point
Issue: #477
User-Visible: yes
2026-09-06 17:52:05 +00:00
Matysh 5ab41a7299 refactor: remove persisted room drafts
Issue: #478
User-Visible: yes
2026-09-06 17:38:47 +03:00
Sergey Matyuninandclaude[bot] 28c653991a test: harden color picker confirmation guards
Issue: #476
User-Visible: no
2026-09-06 12:56:14 +00:00
Sergey Matyuninandclaude[bot] 194df5251a test: register color picker browser coverage
Issue: #476
User-Visible: no
2026-09-06 12:56:14 +00:00
Matysh 1856302cd3 fix: recover native dialog modal placement
Issue: #463
User-Visible: yes
2026-09-05 17:53:16 +03:00
Matysh fcf0ce80eb fix: make card resource recovery observable
Issue: #462
User-Visible: yes
2026-09-05 16:04:54 +03:00
Sergey Matyunin 04a1de091c fix: speed up intermediate wall-chain commits
Issue: #461
User-Visible: yes
2026-09-05 14:04:26 +03:00
Sergey Matyunin 5d09e722e4 test: link live editor contract to browser smokes
Issue: #460
User-Visible: no
2026-09-05 12:10:26 +03:00
Sergey Matyunin 85702afc0c feat: add contextual Zigbee topology hover
Issue: #54
User-Visible: yes
2026-09-04 14:40:09 +03:00
Sergey Matyuninandclaude[bot] fa41d2981c fix: keep vacuum routes pending until a floor is chosen
Issue: #441
User-Visible: yes
2026-09-03 19:22:55 +00:00
Codex d4dd027b0a build: prepare v1.71.0-beta.2 candidate
Issue: #426
Issue: #427
Issue: #428
Issue: #431
Issue: #432
Issue: #434
User-Visible: no
2026-09-03 15:23:40 +03:00
Matyshandclaude[bot] bdf81fad58 feat: add device position undo history
Issue: #74
User-Visible: yes
2026-08-30 13:16:27 +00:00
Sergey Matyuninandclaude[bot] c1f2d36267 test: register no-op tap review evidence
Issue: #381
User-Visible: no
2026-08-30 07:48:16 +00:00
Sergey Matyunin 591f8f6ac9 Add selectable value face sources
Issue: #378
User-Visible: yes
2026-08-29 22:20:18 +03:00