r1 M5: the runtime and field chunks release a card's frame and field cache
on disconnect (ledRelease from disconnectedCallback), never cache for a
disconnected card, and a chunk that lands after disconnect renders nothing
(the card's LED hook is connected-only). The profile now reports the three
caches of the shown space separately (shapes ≤ 50, visibility ≤ 50, retained
per-emitter fans ≤ 2500) through the runtime's ledStats, asserts 0 retained
entries and 0 live LED timers/frames/observers after every disconnect,
judges the Long Tasks of a 100-step camera series as well as the interaction
profile's camera scenario, runs one extra cold mount whose runtime response
is held while the card is removed, and enforces ≥ 7 samples after ≥ 1
warm-up — also on reports merged from parts (--warmup-only, --merge).
Issue: #780
User-Visible: no
r1 of the code review:
- M1: a strip keeps its marker's value badge, passive, at the half-length
anchor on the card and on the static card (no icon core, pulse or slot).
- M2: one room resolver for the strip's Glow — an explicit valid room_id of
the marker wins over the anchor room; a stale one falls back (stripRoom).
- M3: the chain remembers the space it is drawn in; a space switch finishes
it there, never in the space shown next, and opens no picker over it.
- M4: visibility is decided before import(): a hidden marker or an
HA-disabled device loads no LED chunk (ledVisible, also checks the stored
marker so a just-hidden one does not slip through a stale device list).
- M6: the static card is a full light_pools × live_states browser matrix.
Unit tests for M2/M3, smokes for M1/M3/M4/M6, five registered mutants.
Issue: #780
User-Visible: yes
Stage 5 of #780.
- Import summary: «Strips left unbound after import: {n}» from the backend
`unbound_led_strips` count; «Optimize plans» reports strips passing
through walls per space and edits none (AC16).
- Linear field for long strips (ТЗ §13.2): pieces of at most the radius
along the polyline, emitters thinned to r/4, each piece clipped to the
visibility fans of its own emitters as separate clipPath children (no
boolean pass per piece), one floor clip for the whole layer, no fan at
all where nothing blocks within the radius; a grid index of body faces
and boxed inside tests; unchanged fields skip re-diffing. 50×50 on the
large house: first stable frame ~1.4 s, warm space ~1.1 s locally.
- led-strips-v1 profile: demo/benchmark_led_strips.mjs with the derived
large-house fixture (10×5, 50×50, none), absolute limits of the ТЗ table
in demo/performance/budgets-led-strips.json, exact counters (zero
recomputes on HA ticks/camera/colour, ≤50 cache entries, no growth over
20 cycles); added to the full performance workflow.
- Bundle: LAZY_LED_GZIP_CEILING 10 KiB, LAZY_LED_EDITOR_GZIP_CEILING 11 KiB
(measured + 10 %, rounded up); overlaps with the initial and editor
graphs refused; the lazy editor graph stays inside its ceiling.
- Smokes smoke_led_strip_draw/bind/glow, linked in smoke-links; 13 mutants
in the registry (7 browser guards in the inventory); config field registry
entry `spaces[].led_strips`.
- Golden: five new scenes on the `golden-led` space of the visual fixture
(`ledStrips` option, the designer's four strips on #868D94), matrix v71.
- Docs: LIGHT, DEVICE-PRESENTATION, USER-GUIDE (en/ru), UX-MODES,
ARCHITECTURE, ISOMETRIC, CONFIG-COMPATIBILITY, TOUCH-SUPPORT, demo/stand
README, performance README; docs/design/led-strips with the unchanged
designer archive, two paired frames and ACCEPTANCE.md; both changelogs.
Issue: #780
User-Visible: yes
Волна 2 эпика #674 — у каждого правила один дом, остальные места ссылаются.
DECOR-EDITOR.md ← BACKDROP.md + LIVE-TEXT.md: один документ с нумерованными
разделами (§3 подложка, §5 текст с живыми значениями), на которые теперь
указывают комментарии кода вместо несуществовавших «BACKDROP §2/§3»;
исправлено утверждение, что space-card не рисует декор (он рисует подложку
и картинки декора, но не фигуры, мебель и текст). LIGHT.md ← матрица
настроек света (перевод, тест назван явно: test/devices.test.mjs «issues
84/88»). DEVICE-PRESENTATION.md ← правила «что показывает маркер» из
FILTERING.md (порядок cover → light sources → device role, шторы,
медиаплееры); «в одном pull request» → «в одном коммите». CANVAS.md: §9.5
«Оптимизировать планы» → CONFIG-COMPATIBILITY.md, overlay и планарные грани
Walls → WALL-THICKNESS.md §10–11, таблицы «было/стало» сняты. TESTING-DEMO.md
→ demo/stand/README.md: карта демо-дома и «чего на стенде нет», ручной
чек-лист снят (ручной фазы в процессе нет). ISOMETRIC.md — только текущее;
история Stage 2/4 — docs/adr/570-isometric-stage4-visual-handoff.md.
SUN.md: удалённый контракт фона снят, правило бумаги — в текущем разделе.
UX-MODES.md: декор над заливками, а не «под комнатами»; «hidden isometric»;
follow-up из #3 — все выпущены. Шапки VACUUM, WARM-REMOUNT («Выровнять всё
по сетке» → «Оптимизировать планы»), WALL-THICKNESS, STYLING-HOOKS,
CONFIG-COMPATIBILITY (#33), PDF-EXPORT — без устаревших статусов и планов.
README EN/RU: абзац про пересъёмку скриншотов → CONTRIBUTING.md, RADAR и
PDF-EXPORT в списке документации, RU догнал EN (2.5D, повторное
использование загруженного изображения, STAIRS). Один список канонических
документов подсистем в AGENTS.md и промпте ревьюера (_process.yml).
WALL-THICKNESS.md ссылается на ADR 282.
Правки src/** и validation.py — только пути документов в комментариях.
Issue: #679
User-Visible: no
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
Внешний пользователь завёл #370 как баг: в houseplan-space-card нет теней от
стен, хотя в houseplan-card они есть. Разбор показал, что кода это не касается —
ограничение намеренное и записано в src/space-render.ts:353 («the compact card
intentionally has no live radial pools»). visibilityPolygon из
src/light-visibility.ts импортируют ровно два файла, houseplan-card.ts и
houseplan-editor-runtime.ts; space-render.ts не импортирует его вовсе. Пулов нет,
а тень существует только как форма пула — затенять нечего.
Но претензия справедлива, просто адресована не туда. Единственная запись о
намеренности жила в комментарии исходника, которого пользователь видеть не может,
а руководство обещало обратное: «маркеры используют те же состояния, значения,
тревоги и эффекты, что полный план» — про свет ни слова. В LIGHT.md про
компактную карточку тоже не было ничего. Человек полез в код именно потому, что
документация молчала, и сам корректно предположил, что это может быть намеренно.
Теперь сказано в трёх местах: оба руководства и LIGHT.md, с причиной — пулы это
самая дорогая часть отрисовки, у неё свой перф-воркфлоу и бюджеты, и компактная
карточка платит за дешевизну именно ими.
Issue: #370
User-Visible: no
A gate or door bound to a position-reporting cover fed current_position
into the light-barrier signature at toFixed(3) precision: every percent of
movement produced a new fingerprint, a full physicalBodyParts recompute
and a recut — up to ~100 heavy passes per gate cycle, plus LRU churn.
The light pipeline now consumes one quantised amount
(OPENING_LIGHT_AMOUNT_QUANTUM = 0.05, exact 0 and 1 nodes) at the single
point that feeds BOTH the signature and the cut geometry, so the cache key
and the drawn aperture agree by construction and a full sweep costs at
most 21 recomputes. The door LEAF animation stays smooth — _openingAmt is
quantised only for the light pipeline, nowhere else. Binary contact doors
are byte-identical to the previous behaviour (pinned by unit).
Assumption recorded in the spec: the 5% visual step of the light cut is
indistinguishable on real plans; if field impressions disagree, the
quantum is a one-constant change (0.02 => <=51 recomputes) or the decision
falls back to a debounce. LIGHT.md §Caching documents the grid.
Issue: #366
User-Visible: yes