Commit Graph
27 Commits
Author SHA1 Message Date
Codex 9d8f89d260 ci: release gate judges the latest non-cancelled Validate run of the SHA
The gate used to require every Validate run on the tag SHA to be green:
a cancelled duplicate or a red flake that a later re-run had fixed kept
the stable release blocked (v1.73.0, 09.09 — released by hand). Now the
verdict comes from the newest run that was not cancelled: not completed →
wait, success → pass, anything else → fail, no run → wait. The same rule
is documented for the perf workflow and the release runbook.

Mutants: release-gate-counts-cancelled-runs, release-gate-oldest-run-wins.

Issue: #511
User-Visible: no
2026-09-09 17:38:48 +03:00
Codex ceab345215 perf: give the Stage 3 dense isometric budget the same long-task count allowance (#507)
The #160 contract test keeps the dense profile's longTasks block equal to
the historical isometric one, and both profiles boot through the same lazy
iso-scene-render chunk; the accepted split applies to both. Validate
34356856702 caught the divergence.

Issue: #507
User-Visible: no
Release: v1.73.0
2026-09-09 16:30:18 +03:00
Codex d72cb704f3 perf: accept the lazy isometric chunk boot-task split in the isometric long-task count budget (#507)
Full Performance of the v1.73.0 stable candidate against the v1.72.0 product
(run 34354409872) was red on one check of the isometric profile:
longTask.countP95 16 → 20 against max(16×1.2, 16+3) = 19.2, with every
timing, longTask.totalP95Ms and longTask.maxSingleMs green. The trace behind
#506 shows why: since v1.73.0-beta.1 the isometric renderer is the lazy
iso-scene-render chunk (#160 Stage 3), so the single v1.72.0 boot task is
split in two around that import — the same work, +2 tasks.

Owner decision 2026-09-09: accept the split. countNoiseAllowance 3 → 5 for
large-house-isometric-v1 only; the ratio, the hard ceiling, total and
maximum single task keep gating real growth. The downloaded CI artefact
re-evaluated with this budget passes (limit 21, actual 20, no failures).
Documented in demo/performance/README.md; the budget test pins the
allowance and the untouched profiles.

Issue: #507
User-Visible: no
Release: v1.73.0
2026-09-09 16:24:15 +03:00
Codex 913e3187f1 Release v1.73.0
Promote the nine published v1.73.0 betas without new product behaviour:
stable version fields, synchronized generated bundles, the aggregated
bilingual release notes from v1.72.0 and status metadata only. beta.9
carried the startup-regression fix (#506) that Full Performance caught on
the first promotion attempt; the stable body keeps it out as an in-line
regression per the #328 curation rules.

Issue: #506
User-Visible: no
Release: v1.73.0
2026-09-09 15:22:01 +03:00
Codex 43809178ee test: poll smoke_preloader's reduced-motion phase from Playwright, with navigation diagnostics
The beta.9 candidate failed the same phase twice in CI with "Resulting
promise was garbage collected" (runs 34346813552, 34347910231) while it
passes locally; a timer guard did not help, which points at a destroyed
context rather than a starved animation-frame chain. The wait now runs as
page.waitForFunction with raf polling, and the smoke logs frame navigations
and page crashes as `diagnostic …` lines so the next failure names its
cause. Verdict unchanged (animationName of the boot house, or 'missed').
Pre-release gate repair per PROCESS §11.4; locally OK ×2.

Issue: #506
User-Visible: no
Release: v1.73.0-beta.9
2026-09-09 15:05:46 +03:00
Codex 581d165bda test: keep smoke_preloader's reduced-motion wait alive without animation frames
Validate 34346813552 on the beta.9 candidate failed only in browser smoke
shard 1: smoke_preloader phase 3 died with "Resulting promise was garbage
collected" — its rAF-only wait for the boot house had no other reference
while the runner withheld animation frames. A timer now bounds the wait
and keeps the promise reachable; the verdict is unchanged (animationName
of the house, or 'missed'). Pre-release gate repair per PROCESS §11.4:
locally `node demo/smoke_preloader.mjs` → OK ×2; all other heavy gates of
that run (golden, perf-smoke, backend, shards 2–3) were green.

Issue: #506
User-Visible: no
Release: v1.73.0-beta.9
2026-09-09 14:53:45 +03:00
Codex a9d0cab2dd Prepare v1.73.0-beta.9
Version fields and generated bundles move to 1.73.0-beta.9; the #506
changelog entry leaves Unreleased for the beta.9 section; release notes and
STATUS describe the startup-regression fix that unblocks the stable
promotion. No product change beyond #506, already reviewed and merged.

Issue: #506
User-Visible: no
Release: v1.73.0-beta.9
2026-09-09 14:40:28 +03:00
Codex 9d6ac98d3a fix: attach a warm summary runtime before the first render (#506)
Every card instance attached its summary-panel runtime through
import().then(), even when the chunk had loaded long ago. The first render
therefore measured a header without summary controls; the controls arrived
a beat later, the stage shrank, the deferred refit opened a `stage-resize`
continuity candidate and the first HA tick paid three extra render passes
(Full Performance: blend stateUpdate1 50 → 130 ms, overlay 217 → 809 ms;
locally 4 performUpdate per tick instead of 1).

summary-runtime-loader.ts separates the summary code from its state: the
loaded factory is cached per page, every host builds its own runtime from
it (no shared preferences, drafts, subscriptions, timers or DOM). A warm
factory yields the runtime synchronously in connectedCallback, before the
first Lit render; a cold mount still pays one lazy import, concurrent cold
mounts share the pending import, a failed import is forgotten so the next
connection retries, and a disconnect cancels the pending attachment of that
connection. SummaryRuntimeSlot owns the per-host lifecycle so the card core
stays under its line ceiling.

Witnesses: loader unit tests (distinct instances, shared pending import,
cancelled attachment, retry after failure); demo/smoke_summary_warm_attach
(warm replacement and cold-key instance on a warm page own the runtime
before the first render, header/stage stable from the first frame, no
stage-resize, one performUpdate per geometry-neutral tick, a real viewport
resize still opens stage-resize); mutant summary-runtime-attaches-after-
first-render. smoke_summary_panel waited for `_summary` as a readiness
proxy; it now waits for the server config load, which stays asynchronous.

Local paired glow benchmarks (4× CPU throttle): blend 159.7 → 49.9 ms and
overlay 326.7 → 120.4 ms at stateUpdate1 with renders 4 → 1; the isometric
load loses the three summary-owned long tasks.

Docs screenshots: all 11 frames decode pixel-identical to the committed
ones; the manifest carries only the new source fingerprint. Initial View
ceiling recentred 299 100 → 299 600 for the +299 B loader.

Issue: #506
User-Visible: yes
2026-09-09 13:57:53 +03:00
Codexandclaude[bot] 4f040c4c8e fix: exact upload quota, support palette allowlist, bounded SVG reference chains (#498)
Attachment uploads stage the body as `.upload-*` under files_root and then
asked the quota to count that file as stored usage *and* as the incoming
size, so the last file that still fit was refused at the boundary — by
bytes and by count. check_quota/dir_usage now take `exclude` for the
caller's own staged file; other staged files keep counting, so two
concurrent uploads can never both land past the limit.

The support package copied every string key of settings.fill_colors. The
schema stays open for compatibility, but the projection now keeps only the
eleven slots the card defines (SUPPORT_FILL_COLOR_KEYS, pinned to
src/logic.ts DEFAULT_FILL_COLORS by a test); an empty palette is omitted.

The SVG local-reference walk was a recursive DFS: a flat chain of a few
thousand hrefs passed every #436 bound and died with RecursionError, which
the upload view turned into a 500. The walk is iterative and measures the
longest chain through each node (memoised, order-independent); chains
deeper than MAX_SVG_REF_DEPTH = 64 are refused as too_large, cycles stay
invalid_image.

Tests: quota boundaries on the validator and the HA endpoint, a barrier
test for concurrent uploads, palette allowlist and TS parity, reference
chains (plain, hostile id order, cycle) on the validator and the endpoint;
six mutants caught by the standard runner.

Issue: #498
User-Visible: yes
2026-09-09 07:06:20 +00:00
Codexandclaude[bot] c71f21f3c9 docs: spec #498 r2 — numbered AC, longest-chain reference limit, concurrent quota semantics
Spec review r1: add the AC list with proofs and the perf/touch statement;
measure the SVG reference limit as the longest chain through a node
(memoised), not the stack height of the first traversal, so a hostile id
order cannot cut a long chain into short segments; state that two uploads
checked while both are staged are both refused (conservative), never both
stored.

Issue: #498
User-Visible: no
2026-09-09 07:06:20 +00:00
Codexandclaude[bot] ac478127d5 docs: spec for #498 — exact upload quota, support palette allowlist, bounded SVG reference chains
Issue: #498
User-Visible: no
2026-09-09 07:06:20 +00:00
Codex 2946e28352 fix: import result follows the commit; dropped route runs reach the store (#495)
Apply re-validated the preview token after both halves were durable, so a
TTL that lapsed during the write, or an eviction by a newer preview of the
same user, answered "preview expired" for a plan that was already replaced
and withheld both update events. The token is now simply spent after the
commit; validity is decided once, on entry under write_lock.

Route runs dropped by drop_unknown_routes never reached the store unless a
marker happened to be orphaned in the same pass; an idle robot kept them in
memory only and a restart brought them back. The drop now happens under
_refresh_lock, leaves with the orphan transaction or with an immediate
write of its own, and rolls back like #335 when the store refuses.

Tests: HA harness for both apply races and a live config/set route drop,
recorder stubs for the four durability cases; five mutants caught by the
standard runner.

Issue: #495
User-Visible: yes
2026-09-09 08:34:46 +03:00
Codex 70a394d228 docs: spec for #495 — import result follows the commit, dropped route runs reach the store
Issue: #495
User-Visible: no
2026-09-09 08:26:52 +03:00
Codex fff171c7dc ci: mirror process.yml from dev (#503 — deterministic Claude Code install)
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (blend) (push) Failing after 37m3s
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (large-house) (push) Failing after 40m28s
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (interaction) (push) Failing after 48m49s
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (isometric) (push) Failing after 51m39s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 1m45s
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (plan-snap) (push) Failing after 29m14s
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (space-default) (push) Failing after 26m20s
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (overlay) (push) Failing after 51m32s
Проверка (CI) / Предполётные проверки: документация, провенанс, процесс (push) Failing after 1m2s
Проверка (CI) / Классификация изменённых файлов (push) Successful in 27s
Проверка (CI) / HACS: валидация репозитория (push) Skipped
Проверка (CI) / Hassfest: манифест интеграции (push) Skipped
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Skipped
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Skipped
Полные бенчмарки производительности / Бенчмарки рендера и геометрии (space-glow) (push) Failing after 25m16s
Issue: #503
User-Visible: no
2026-09-09 02:00:55 +03:00
Codex 9bfe78850d ci: install Claude Code binary ourselves before the review action (#503)
claude-code-action v1.0.218 (Claude Code 2.1.265) runs `claude install`,
which on ubuntu-latest sometimes leaves no launcher at ~/.local/bin/claude
while still reporting success; the action trusts the exit code and the SDK
then fails with ENOENT (anthropics/claude-code-action#1817). Four review
runs in a row died this way after 22:27 UTC 08.09.

Add a step that fetches the exact version the action pins (read from its
run.ts, fallback 2.1.265) from downloads.claude.ai, verifies the sha256
from the release manifest, checks `--version`, and hands the path to the
action via `path_to_claude_code_executable`, which makes the action skip
its own installer entirely.

Issue: #503
User-Visible: no
2026-09-09 02:00:39 +03:00
Codex c5325b0a17 ci: зеркало process.yml и nightly.yml из dev — точный кандидат и ожидание Validate (#492)
Issue: #492
User-Visible: no
2026-09-09 00:57:05 +03:00
Codexandclaude[bot] 405bce42c3 docs: spec notes how the manifest categories are computed
Issue: #492
User-Visible: no
2026-09-08 21:55:07 +00:00
Codexandclaude[bot] a358ed11fd docs: input manifest and exact-candidate merge in TESTING.md and PROCESS.md
Issue: #492
User-Visible: no
2026-09-08 21:55:07 +00:00
Codexandclaude[bot] 32b1baa189 ci: merge the exact candidate; nightly waits for its Validate
scripts/merge-candidate.mjs owns the review pipeline's merge: when dev
moved during review, the rebased candidate is pushed to the issue branch,
its diff is compared to the reviewed one by patch-id, Validate on that SHA
is awaited, and only then dev is advanced with --force-with-lease on the
base the candidate was built on — a rejected lease restarts, at most three
times. Every non-merge outcome moves the label with a comment, so the
"label always changes" invariant holds. nightly.yml now finds the Validate
run it dispatched and inherits its conclusion. Three mutants guard this.

Issue: #492
User-Visible: no
2026-09-08 21:55:07 +00:00
Codexandclaude[bot] 51beeeb2c4 ci: mutant selection sees wrapper defaults, guard imports, fixtures and registry edits
guardInputs() replaces guardFiles() in selection and fingerprints: the
files named in the guard, the GUARD_INPUTS a wrapper declares (read
statically — the wrappers run on import), and the closure of imports and
path literals of every guard file, stopping at src/** which stays the
patch side. A diff that touches the registry itself selects every added or
changed definition against the base registry read from git. Five mutants
guard the manifest and this selection.

Issue: #492
User-Visible: no
2026-09-08 21:55:07 +00:00
Codexandclaude[bot] 658e395360 ci: one input manifest for job selection and reuse keys
scripts/check-inputs.mjs declares every Validate check with its roots and
entry points and computes the rest: imports and path literals of the
entries, transitively for code, as leaves for data. classify-changes and
gate-reuse both read it, so "which job runs" and "what its key hashes"
cannot disagree any more. An executable file no check knows widens the run
to the full set and is named in the summary; the coverage list makes such
a file a red unit test rather than a permanent widening. The workflow file
is a toolchain input of every job; backend no longer hashes src/**.

Issue: #492
User-Visible: no
2026-09-08 21:55:07 +00:00
Codexandclaude[bot] 227b73683e docs: AC6 gets its negative probe (spec review r1)
Issue: #492
User-Visible: no
2026-09-08 21:55:07 +00:00
Codexandclaude[bot] 6b70e5a3ad docs: spec for the exact integration candidate and the input manifest
Issue: #492
User-Visible: no
2026-09-08 21:55:07 +00:00
Codex 2b2fc94479 docs: refresh screenshot provenance for the panel mount fix
Fingerprint-only: the panel change does not alter any documented frame
(the docs harness already gave the panel host the viewport height), so the
committed images stay and only the source provenance moves.

Issue: #488
User-Visible: no
2026-09-08 10:10:20 +03:00
Codex e97e568111 docs: record the real HA panel container and mount order in the #486 spec
Issue: #488
User-Visible: no
2026-09-08 10:05:45 +03:00
Codex 2877213396 test: replace the content-slot height assumption with the #488 contract
Issue: #488
User-Visible: no
2026-09-08 10:05:45 +03:00
Codex 471527c474 fix: mount the House Plan panel the way Home Assistant does
HA assigns panel/hass/narrow/route before the top-level-await entry has
defined the element, so the values landed as own properties that shadowed
the accessors and the card never received hass. And <ha-panel-custom> has
no height, so the percentage host height collapsed the stage to 0 px.
Adopt pre-upgrade properties through the accessors and size the panel from
the viewport minus HA's safe-area padding. The smoke now reproduces HA's
real mount order and container; two mutants guard both contracts. The
bundle is rebuilt from these sources.

Issue: #488
User-Visible: yes
2026-09-08 10:05:45 +03:00