Commit Graph
4343 Commits
Author SHA1 Message Date
claude[bot] 7ea49c4c26 docs(reviews): индекс после сдвига каталога (#816)
Проверка (CI) / Предполёт: документация, провенанс, процесс (push) Canceled after 0s
Проверка (CI) / Классификация изменённых файлов (push) Canceled after 0s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Canceled after 0s
Проверка (CI) / HACS: валидация репозитория (push) Canceled after 0s
Проверка (CI) / Hassfest: манифест интеграции (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Canceled after 0s
Проверка (CI) / Бандл головы dev для стенда (push) Canceled after 0s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Canceled after 0s
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Canceled after 0s
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Canceled after 0s
Проверка (CI) / Смоки: все шарды зелёные (push) Canceled after 0s
Проверка (CI) / Golden-кадры против принятых эталонов (push) Canceled after 0s
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Canceled after 0s
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Canceled after 0s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Canceled after 0s
Проверка (CI) / Доказательство выполненных проверок (push) Canceled after 0s
Issue: #816
User-Visible: no
2026-10-07 14:03:09 +00:00
claude[bot] a80aefa028 docs: review document for #816
Issue: #816
User-Visible: no
2026-10-07 14:03:08 +00:00
Matyshandclaude[bot] 1a0024ea2b test(zigbee): explain incomplete-caption mutation guards (#816)
Issue: #816
User-Visible: no
2026-10-07 14:03:08 +00:00
Matyshandclaude[bot] 2e0f1a17a4 fix(zigbee): scope incomplete caption to unknown non-root uplinks (#816)
Issue: #816
User-Visible: yes
2026-10-07 14:03:08 +00:00
claude[bot] 98f3ab0c00 docs: review document for #819
Issue: #819
User-Visible: no
2026-10-07 13:23:31 +00:00
claude[bot] 98108151c1 docs(reviews): индекс после сдвига каталога (#813)
Issue: #813
User-Visible: no
2026-10-07 12:37:54 +00:00
claude[bot] b8a39efaa9 docs: review document for #813
Issue: #813
User-Visible: no
2026-10-07 12:37:54 +00:00
Claudeandclaude[bot] dd5e1b809b refactor: drop the dead kiosk dialog copy and dead dialog CSS (#813)
F12: the editor runtime still carried _saveKioskScale/_renderKioskDialog,
which wrote the pre-summary key houseplan_card_kiosk_v1 directly. Since #763
the core card draws the kiosk scale dialog and saves through the summary
runtime, and nothing called the runtime copy. The copy, its LS_KIOSK
constant and the port member _kioskDialog (read only by that copy) are gone;
the legacy key is still read once for migration and never rewritten. The
kiosk smoke now also checks that key stays unwritten.

F18: dialogs.styles.ts kept rules no markup ever matched: .curbind,
.btn.alignall, .backupactions (and its 520 px twin), .help-inline-label and
hp-dialog .body .temprange .tempin (the room dialog renders hpf-temprange;
the bare .tempin stays). No source, demo, test or doc builds these class
names dynamically. With the dead .backupactions gone, the .backupcounts pair
became editor-only, so the #805 ownership ratchet moves it to the lazy
editor sheet. The overridden supportbody gap was already removed by #805;
the effective gap stays 6 px. Computed styles of the View, the static card
and the settings, support, backup, rules and room dialogs are identical to
dev at 1100 and 360 px in both themes (scripts/dev/editor-styles-equivalence).

Issue: #813
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 12:37:54 +00:00
Claudeandclaude[bot] c46ccc506e fix(iso): keyboard focus lifts a marker over its 2.5D neighbours (#813)
The 2.5D View lays every marker on z-index 2 with a (0,4,0) selector
(plan.styles.ts); the focus layer `.dev:focus-visible { z-index: 5 }` is
(0,2,0), so a keyboard-focused marker stayed under the markers it overlaps
while Flat lifted it. Focus now repeats its layer at (0,5,0) for that View.
The rule sits before the #809 endpoint rules of the same weight, so a
focused Zigbee endpoint (the unhovered neighbour included) stays on 8; hover
and Flat are untouched, and focusing calls nothing.

Witnesses: smoke_iso_tiles moves real Shift+Tab focus onto the lower of two
overlapping ordinary markers and checks the computed layers and a
differential raster probe of the overlap in both themes, with hover and Flat
as controls; smoke_device_battery_zigbee checks focus with a hovered Zigbee
link (endpoint stays 8, an ordinary focused marker 5) and that focus starts
no scan, service or dialog. Two registry mutants. ISOMETRIC.md states the
layer.

Issue: #813
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 12:37:54 +00:00
Claudeandclaude[bot] 418b10e59b fix(continuity): paint a new opening with the projection of its own plan (#813)
Both cards keep the device projection of the last complete frame while a
candidate waits for its paint barrier, but adopt the new config at once. The
first frame after another client adds a door therefore painted the new door
with the projection captured for the OLD plan, which never held its contact:
a missing door state draws an open door, and the 0.6 s leaf transition then
"closed" a door nobody touched. The full card had the same defect, so the
shared code changes, not the space card alone.

A RenderDeviceSnapshot now records the geometry it was captured for (the
config fingerprint and space of the static card, the config epoch of the
full card), and selectRenderDeviceSnapshot paints the projection that
matches the frame's geometry; the held projection is still painted with the
old geometry, the staged/committed lifecycle and the token barrier are
unchanged, and the active-registry projection is still the only HA source.

Witnesses: smoke_visual_continuity samples every presented frame and the
transition events of both cards for a new closed door, new open, missing,
unknown and unavailable contacts, a real open/close (still animated), the
door already on the plan, a static-card space switch, a newer event inside
the waiting candidate and a warm remount; unit tests cover the selection.
Three registry mutants.

Issue: #813
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 12:37:54 +00:00
Claudeandclaude[bot] 107491d7ad fix(kiosk): end the stage gesture when the scale dialog takes over (#813)
The 3 s hold on an empty kiosk stage opened the scale dialog from a timer,
but the press stayed in the stage pointer map: a mouse has no implicit
capture, so its release is delivered to the modal dialog and the stage never
sees it. The next hold then read as a second finger (no dialog, and the
release became a room tap that zoomed the plan), and the live runtime kept
deferring every Home Assistant state change while a pointer looked active.

The hold now lives in a small controller (src/kiosk-hold.ts) that owns the
one timer and the pointer that armed it. Firing ends the whole stage gesture
through _interruptViewGesture before the dialog opens; release, pointercancel
(the cold kiosk has no editor runtime to clear the timer there), a lost
capture of the holding pointer, window blur and disconnect all end it as
well. No synthetic pointerup is created.

Witnesses: smoke_kiosk_scale_no_editor gains three real mouse holds in a
row (the release is observed on the dialog) and the presses that must not
open the dialog (tap, cancelled touch, lost capture, window blur, a press
across detach/reattach, pinch), with no service call and no editor request;
test/kiosk-hold.test.mjs covers the controller. Six registry mutants.

Issue: #813
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 12:37:54 +00:00
claude[bot] 9c86e62093 docs: review document for #820
Issue: #820
User-Visible: no
2026-10-07 12:35:27 +00:00
claude[bot] 8f11c9e90a docs: review document for #819
Issue: #819
User-Visible: no
2026-10-07 12:29:41 +00:00
claude[bot] 4789c3f636 docs(reviews): индекс после сдвига каталога (#805)
Issue: #805
User-Visible: no
2026-10-07 09:41:11 +00:00
claude[bot] 5e4cbf5bbf docs: review document for #805
Issue: #805
User-Visible: no
2026-10-07 09:41:08 +00:00
Claudeandclaude[bot] 3149a3d7f4 test(smoke): judge the first editor frame once the control is in the flat tree (#805)
Validate (Chromium 151) failed six first-frame checks of
smoke_editor_styles_lazy with an empty computed `display` while both editor
sheets were already adopted. The MutationObserver callback runs in the
microtask right after the card renders a fresh hp-dialog, before that dialog's
own first update renders its <slot>: the control is an unslotted light-DOM
child, outside the flat tree, and Chromium 151 gives such an element no
computed style at all (141, used locally, still computed one). An empty value
was taken for a verdict.

The judgment now waits for the element to take part in rendering: connected
and slotted by every shadow host on its way up, with a non-empty value. It is
taken at the update boundary - after updateComplete of the card and of every
Lit host above the element - which is still before any task, so an adoption
deferred to a setTimeout stays red; only if that is not enough it falls back
to the next animation frames. Every check reports the phase it was judged in.

The verdicts are parked in a page slot and polled with waitForFunction:
awaiting a long-pending promise inside page.evaluate was intermittently
reported by CDP as "Resulting promise was garbage collected" under CPU
throttling. The image-palette opener now waits for the render that shows the
image tool before using it (a plain capability field triggers no render).

Issue: #805
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 09:20:42 +00:00
Claudeandclaude[bot] 2f03167c30 docs(styles): computed-style equivalence probe and the lazy editor sheets (#805)
scripts/dev/editor-styles-equivalence.mjs is the reproducible AC4(b) proof:
it opens the same surfaces in the bundle of this tree and of a base tree and
compares every computed property (custom properties included) of every
element of the card root, the host and nested hp-device-preview roots - warm
editor surfaces and View at 1100/360 px in light and dark, plus cold View,
space card and onboarding. A rule multiset diff (styles-diff.mjs) cannot see
a winner flipping between two equally weighted rules; this can, and it is
how the three never-applied support declarations were found.

ARCHITECTURE §Styles names the lazy sheets, their adoption and guards.

Issue: #805
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 09:20:42 +00:00
Claudeandclaude[bot] e785b88a23 test(smoke): editor-only CSS stays off the cold View and styles the first editor frame (#805)
demo/smoke_editor_styles_lazy.mjs exercises the production bundle:

- AC2: a cold View at 1100 px and 360 px, a kiosk card, a space card and the
  onboarding form hold no editor sheet and no --hp-editor-tray-* on the host,
  request no editor chunk, and onboarding's shared rows keep their layout;
- AC3: on cold tabs every surface family (settings, support, plan tray,
  optimize, backup, room, wall thickness, catalog, rules, device dialog with
  radar and vacuum sections, radar wizard, vacuum fit, furniture and image
  palettes) is observed by a MutationObserver in the very first frame its
  control element exists - already styled, editor sheets in the canonical
  slots exactly once; back in View the editor sheets change no element;
- AC5: a second card adopts into its own root with the shared sheet objects,
  a warm remount revives the dialog styled, a disconnect during import and a
  failed first attempt adopt once, a module of another build adopts nothing;
- AC7: opening the editor requests only chunks of known graphs.

smoke-links ties the sheets and the adoption to it; the minifier witness now
names the lazy sheet. Mutants: the adoption call dropped from the runtime
constructor and a page-wide "adopted" flag (browser guards, inventory
updated), .btn moved into the lazy sheet (unit).

Issue: #805
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 09:20:42 +00:00
Claudeandclaude[bot] 2003959700 test(styles): guard ownership of editor-only CSS and its adoption (#805)
The move is only worth something while it holds. Two guards keep it:

- scripts/bundle-budget.mjs judges the built graphs by content
  (EDITOR_STYLE_MARKERS, after SUPPORT_LAZY_MARKERS): moved selectors and the
  tray's --hp-editor-tray-* are absent from initial View and onboarding and
  present in the lazy editor graph; .btn, .editorloading, .recoveryoverlay,
  .vaccalbar and .floorrow stay in the first frame. A rule back in the eager
  sheet, the tray back in static styles or the sheet behind its own import()
  turns the budget red; bundle-assets pins each of those.
- test/editor-dialog-styles.test.mjs judges the source tree with the spec's
  selection rule on a TypeScript import graph (import type and import() do
  not count): every lazy selector belongs to the editor runtime alone, also
  with hp-device-preview counted as View (own root with cardStyles); the
  tray sheet styles only the tray its renderer draws; no lazy selector
  exists in an eager sheet in or out of its at-rule; the reverse ratchet
  keeps any editor-only rule out of dialogs.styles.ts. Adoption runs on fake
  roots, with adoptedStyleSheets and through Lit's <style> fallback: canonical
  slots, once per root, one sheet per document, nothing without a root.

Issue: #805
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 09:20:42 +00:00
Claudeandclaude[bot] 19153ce4b1 perf(styles): adopt editor-only dialog CSS with the lazy editor runtime (#805)
The card's static styles carried 233 rules of dialogs.styles.ts and the
whole contextual-tray sheet that only the lazy editor runtime ever renders:
every cold View downloaded, parsed and matched about 25 KB of CSS it never
applies. By the selection rule of the spec (each selector carries a class
used in the editor runtime graph and in no source of the View graph or of
another lazy graph; rules shared with onboarding, backdrop-pick or the panel,
dynamic and dead classes stay eager; a selector moves with all its at-rule
twins or not at all) those rules now live in src/styles/editor-dialogs.styles.ts.

HouseplanEditorRuntime's constructor - the loader's create() step, after the
exact-build fingerprint check and before install - adopts that sheet right
after the eager dialogs sheet and the tray sheet right after cardStyles, the
slots they held before, once per shadow root, one sheet object per document,
with Lit's <style> fallback in the same order. No new loader, chunk or request.

Three declarations that an equally weighted later eager rule always overrode
are dropped instead of moved, so they cannot start winning from the later
sheet: gap of hp-dialog .supportbody and, at 520 px, padding-inline of
.supportbody and .supportfooter. Accepted frames stay as they are.

Measured on one toolchain, base a106b717 vs this tree: initial View
303 046 -> 298 552 B gzip (-4 494, -24 690 B raw), lazy editor 245 076 ->
250 460 B gzip (+5 384, owner-accepted). LAZY_EDITOR_GZIP_CEILING is
recalculated once to fact + 1 000; initial ceilings and budget unchanged.

Issue: #805
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 09:20:42 +00:00
claude[bot] a55085831f docs: review document for #803
Issue: #803
User-Visible: no
2026-10-07 09:20:29 +00:00
claude[bot] 60e03bd342 docs: review document for #803
Issue: #803
User-Visible: no
2026-10-07 09:10:21 +00:00
claude[bot] 11db092982 docs(reviews): индекс после сдвига каталога (#815)
Issue: #815
User-Visible: no
2026-10-07 08:18:08 +00:00
claude[bot] a92cf7b645 docs: review document for #815
Issue: #815
User-Visible: no
2026-10-07 08:18:04 +00:00
Matysh 6636328402 Strengthen battery pointer passivity witness
Issue: #815
User-Visible: no
2026-10-07 11:01:14 +03:00
claude[bot] 7661133f12 docs(reviews): индекс после сдвига каталога (#812)
Issue: #812
User-Visible: no
2026-10-07 07:54:14 +00:00
claude[bot] bafb6bce1c docs: review document for #812
Issue: #812
User-Visible: no
2026-10-07 07:54:10 +00:00
Matysh f01e627292 Fix dependency and regression-test reliability
Issue: #812
User-Visible: no
2026-10-07 10:33:11 +03:00
claude[bot] fd95054999 docs(reviews): индекс после сдвига каталога (#811)
Issue: #811
User-Visible: no
2026-10-07 07:22:59 +00:00
claude[bot] 083a491fb8 docs(reviews): индекс после сдвига каталога (#811)
Issue: #811
User-Visible: no
2026-10-07 07:10:19 +00:00
claude[bot] 3df9933efe docs: review document for #811
Issue: #811
User-Visible: no
2026-10-07 07:10:16 +00:00
Matysh 588ea8b27b fix(process): make review ranges and derived data reproducible
Validate rebased issue history without importing unrelated dev commits.
Keep verdicts, counts and findings inside the document's own review round.
Generate the final review index with the accepted tree while retaining the
trusted integration controller and its Git/CI policy. Reconcile only derived
browser-inventory numeric cells and share structural checks with the cheap gate.
Record the full catalogue audit and the bounded F30 acceptance investigation.

Issue: #811
User-Visible: no
2026-10-07 09:56:00 +03:00
claude[bot] 20b69d872c docs: review document for #814
Проверка (CI) / Предполёт: документация, провенанс, процесс (push) Canceled after 0s
Проверка (CI) / Классификация изменённых файлов (push) Canceled after 0s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Canceled after 0s
Проверка (CI) / HACS: валидация репозитория (push) Canceled after 0s
Проверка (CI) / Hassfest: манифест интеграции (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Canceled after 0s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Canceled after 0s
Проверка (CI) / Бандл головы dev для стенда (push) Canceled after 0s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Canceled after 0s
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Canceled after 0s
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Canceled after 0s
Проверка (CI) / Доказательство выполненных проверок (push) Canceled after 0s
Проверка (CI) / Смоки: все шарды зелёные (push) Canceled after 0s
Проверка (CI) / Golden-кадры против принятых эталонов (push) Canceled after 0s
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Canceled after 0s
Проверка (CI) / Геометрия: TS/Python parity исполнена (push) Canceled after 0s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Canceled after 0s
Issue: #814
User-Visible: no
2026-10-07 05:59:44 +00:00
claude[bot] a07f7493e2 docs: review document for #811
Issue: #811
User-Visible: no
2026-10-07 05:59:38 +00:00
claude[bot] 9628640a50 docs: review document for #813
Issue: #813
User-Visible: no
2026-10-07 05:58:56 +00:00
claude[bot] 42960896d4 docs: review document for #812
Issue: #812
User-Visible: no
2026-10-07 05:58:14 +00:00
Claude a106b71762 Release v1.80.0-beta.7 candidate
Ship the reviewed wave of 2026-10-06/07: Zigbee link snapshots turn stale
after an hour and link lines pass over battery indicators, with the far
endpoint lifted above the line in 2.5D (#808, #809); the radar on-plan setup
shows the room outline again (#774); the kiosk scale dialog opens without the
editor runtime (#763); space-card markers and opening symbols keep their own
drawing (#764); the summary panel recomputes the total area only for changed
floors (#769); plus the process, review and performance-harness fixes (#766,
#768, #770, #777, #778, #779, #810). Rebuild the committed bundle and tighten
the beta ratchets to the candidate's facts.

Issue: #763
Issue: #764
Issue: #766
Issue: #768
Issue: #769
Issue: #770
Issue: #774
Issue: #777
Issue: #778
Issue: #779
Issue: #808
Issue: #809
Issue: #810
User-Visible: yes
Release: v1.80.0-beta.7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
v1.80.0-beta.7
2026-10-07 07:56:24 +03:00
claude[bot] df69718cec docs: review document for #805
Issue: #805
User-Visible: no
2026-10-07 04:51:34 +00:00
claude[bot] 150b5a166b docs: accept derived artifacts on dev for v1.80.0-beta.7
Производные артефакты беты — одним коммитом на dev (PROCESS.md §8, §11.4, #697).
Прогон: https://github.com/Matysh/houseplan-card/actions/runs/37573076137
Скриншоты документации: отпечаток исходников; изменённые кадры: device-display-preview.

Issue: #697
User-Visible: no
2026-10-07 04:48:45 +00:00
claude[bot] aca88acf4d docs: ship review for v1.80.0-beta.7
Пакетное ревью задач track:ship перед бетой (PROCESS.md §11.7).
Задачи: 763. Итог: High 0 · Medium 0 · Low 0.

Issue: #696
User-Visible: no
2026-10-07 03:15:47 +00:00
claude[bot] 34a428711e docs(reviews): индекс после сдвига каталога (#769)
Issue: #769
User-Visible: no
2026-10-07 02:53:01 +00:00
claude[bot] 11ed68e4ba docs: review document for #769
Issue: #769
User-Visible: no
2026-10-07 02:52:56 +00:00
Claude d7b6bdfbf2 chore(monolith): raise bundleBytes for the per-floor area memo and build counters (#769)
bundleBytes 2 715 446 → 2 718 072 (+2 626, over the 2 000 band). The branch
base (dev f19087bf) already builds 2 717 213 (+1 767 over the baseline,
inside the band, from tasks merged since #807 raised it); #769 adds +859 by
measured rollup builds of each commit: +651 for the per-floor clean-area
memo of the summary panel and the shared floor record key, +546 for the
floor-cache build counters the #735 guard judges (nine miss branches and the
clean-floor build hook), −338 for the single key module that replaces the
copies in the resize runtime and drops its dead union seed. hostRefs 5 067
and portMembers 354 stay inside their bands and are not touched.

Issue: #769
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 05:21:53 +03:00
Claude 5a1b0c20d4 refactor(cache): one source for the wall-union and bodies keys and pool entry (#769)
The #744 key formats were copied: the wall-union key `${floorKey}|${rooms}`
in the card's miss branch and three times in the resize runtime, the
physical-bodies key `${floorKey}|${cellCm}|${gridPitch}` in the card, the
runtime twice and the LED editor, the pool bound 8 as a literal three times
and the `sourceFingerprint` attachment twice. A copy that drifts makes the
resize lookup and the cancel alias stop hitting without any error.

src/floor-geometry-key.ts now owns `wallUnionKey`, `physicalBodiesKey`,
`WALL_UNION_POOL_LIMIT`, the entry factory `wallUnionPoolEntry` (it attaches
`lightGeometryFingerprint` of the record the union was built from) and
`writeWallUnionPool`. The card's miss branch, `_rszEdgeDown`, the
`_rszCancelDrag` alias and both bodies re-keys use only them; the LED editor
keys its own bodies with the same helper. `_rszEdgeDown` now reads the key
of the shown floor's model, as the card does, instead of its own room list.

The union seed in `_rszAcceptPreview` is removed, not moved: since #451 the
live preflight publishes no artifact (`artifact: null`), so the seed never
ran. A host render mid-drag builds the preview union once through the card's
miss branch and every later render hits it. The bodies re-key stays: a
resize never moves partitions, columns or a partition opening's host, and
the smoke proves the re-keyed bodies equal a fresh card's on the preview
record, a door cut into a partition next to the moving wall included.

AC8 in demo/smoke_floor_geometry_cache.mjs on the held AC2c drag: (a) host
renders mid-drag build no union and the drawn union equals a fresh card's on
the preview record, paths and `sourceFingerprint`; (b) cancel and the way back
to View build no union, bodies, contours or clean floors, and the union and
bodies equal a fresh card's on the stored record; (c) the drag never rebuilds
the bodies. Unit: the key formats, the bound and the entry
(test/floor-geometry-key.test.mjs) and a source contract that no copy of the
formats, the pool write or the fingerprint attachment is left outside the
module (test/performance-contract.test.mjs, red on dev). Two registry mutants
(bodies re-key in its own format, union fingerprint from the stored record),
caught by the smoke and checked by hand, as were the two #744 mutants whose
anchor moved; browser inventory 247/200.

Budgets: initial View 303032 B gzip (ceiling 302803 + 2000), lazy editor
245094 B (ceiling 244872 + 2000); monolith ratchet unchanged.

Issue: #769
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 05:21:52 +03:00
Claude ff4c69ac28 test(perf): judge the #735 switch cycle by floor-cache build counters (#769)
The #735 guard compared cache sizes around the warmed twelve-switch cycle.
Once an LRU is full a cold build evicts one entry and every size stays: a
union planted cold in the full pool (8/8) changed no field of the snapshot and
the guard stayed green. Its `openingWallIndex` field read
`card._openingWallIndexCache ? 1 : 0` of a Map and was always 1.

The card now counts real builds of each floor-geometry cache in its miss
branch (`_floorCacheBuilds`: wall union, inner contours, clean floors via a
`cleanFloorForRoom` hook, opening wall index, light barriers, Glow clips,
physical bodies, opening tunnels, light physical bodies) — never on a hit, a
recency refresh, a resize seed or alias, or a clear. One pure decision
(demo/performance/switch-cycle-guard.mjs) judges the window for the benchmark,
the floor-cache smoke and the unit tests: any build of a pooled family fails
and names the family and its growth; the single-slot families may rebuild once
per switch; 2.5D keeps `_isoStructuralBuildCount`. A base bundle without the
counters reads null and is not judged; a candidate must expose them. Each row
reports `switchCycleBuilds` with the size snapshot as a diagnostic (the real
index size there). The budgeted cacheEntries/cacheGrowth keep the index as the
presence flag their `openingWallIndex: 1` ceilings were set on: no budget moves.

Counted run, one sample per profile on the dev base with the counters: every
large-house* profile and isometric-stage3-dense-v1 build 0 in every judged
family, 12/12 physical bodies and opening tunnels, nothing in 2.5D; no family
moved to the reported list. The same runner against a dev bundle reports
`supported: false` and passes.

AC7: demo/smoke_floor_geometry_cache.mjs fills the pool to 8 and drops one
floor's union; a four-switch cycle builds exactly that union (+1, an eviction,
every size the same) and the decision names "wall union" — the old size
comparison sees nothing. AC1 of the smoke also reads the counters. Registry
mutant: a counter that skips the evicting miss (caught by the smoke, checked
by hand); browser inventory 245/200.

Issue: #769
User-Visible: no
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 05:21:45 +03:00
Claude bf771c320b perf(summary): memoise the total area per floor by its record content (#769)
The summary panel's Total room area was memoised on the global config epoch:
any `_saveConfig()` or adopted server config — a rename on one floor, a
device or a setting — made the memo stale and the next View render ran
`cleanFloorAreaSteps` over every floor again (71 portions on large-house).

The area of a floor reads only its stored record, the model built from its
own record and constants, so each floor's value is now memoised by the
content key of those records. The key comes from the helper extracted out of
the #744 reader (`floorRecordKeyMemo`, src/floor-geometry-key.ts): one
fingerprint per floor and epoch, both records when a preview or a duplicate
id makes them differ, and independent of the shown floor. The total is the
sum of the floor values in `models` order, summed anew on every pass, so it
stays bitwise equal to a fresh `totalCleanFloorAreaM2`. A failed floor is
memoised as `null` until its record changes; the freshness check stays one
epoch comparison; the #509 portions, skeleton and the old value on screen
during a recomputation are unchanged; a lifecycle reset clears the memo.

The furniture and stairs magnet keeps its epoch key by measurement (its own
edits change the floor record anyway); the decision is recorded at the key.

Unit: test/summary-panel-area-memo.test.mjs (AC1–AC3 on a three-floor fixture
with walls, a door, a partition, a column and a stair; floors counted through
the injected geometry and portions through the step generator), and
test/floor-geometry-key.test.mjs for the shared key helper, now in the test
build. Two registry mutants (epoch key, rooms-only key); the #744 and #509
anchors follow the moved lines.

Issue: #769
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 05:21:35 +03:00
claude[bot] 805b435a04 docs(reviews): индекс после сдвига каталога (#809)
Issue: #809
User-Visible: no
2026-10-07 02:08:24 +00:00
claude[bot] 2c38e546e5 docs: review document for #809
Issue: #809
User-Visible: no
2026-10-07 02:08:21 +00:00
Claude 7fb609e48a fix(zigbee): keep the neighbour endpoint core above routes in 2.5D (#809)
In the 2.5D View every marker sits on z-index 2 through
`.stage.projection-iso.mode-view .dev` (0,4,0), which beats the #464
endpoint lift `.dev[data-hp-zigbee-topology-endpoint]` (0,2,0). The
hovered endpoint survived only through its higher-specificity hover
duplicate, so the unhovered neighbour endpoint stayed under the route
layer (z 7) and the line crossed its face. Flat was unaffected.

The endpoint contract is repeated for the 2.5D View at (0,5,0), next to
the #464 rules. Narrowing the 2.5D rule with :not(endpoint) was rejected:
it would reach (0,5,0) and beat the hovered non-endpoint's z-index 5.
No stylesheet order or new file changes; .oplock is untouched.

Witnesses in demo/smoke_device_battery_zigbee.mjs:
- {flat,iso}_neighbourCorePaintsOverRoutes: along the drawn local route,
  inside the neighbour core (outside its battery frame) the route layers
  change no pixels, outside both cores they do. Red on dev in 2.5D
  (16 of 16 core samples changed), green here (0 of 16).
- iso_nonEndpointKeepsBaseLayer / iso_hoveredNonEndpointKeepsHoverLayer:
  computed z-index 2 for unlinked markers and 5 for a hovered marker
  outside the topology; the :not(endpoint) variant turns the latter red.

Mutant zigbee-iso-neighbour-endpoint-under-routes removes the new rule;
the browser guard is listed in the inventory (paint 44, total 248).

Issue: #809
User-Visible: yes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
2026-10-07 04:51:20 +03:00
claude[bot] 53d3c79065 docs(reviews): индекс после сдвига каталога (#778)
Issue: #778
User-Visible: no
2026-10-07 01:21:40 +00:00