345 Commits
Author SHA1 Message Date
Codex 2783ceff94 perf(ci): judge a witness by its anchor's neighbourhood, not the whole file
The review gate re-ran almost every selected witness on every round even
when the executor's fix was twelve lines: the ledger fingerprint and the
diff selection both worked on whole files, and the card hosts are
thirteen thousand lines each. On #500 those twelve lines in
houseplan-editor-runtime.ts pulled 53 of the 75 witnesses the third
round ran, and the gate cost 140 job-minutes and an hour of the
reviewer's wall clock across three rounds.

The patch side is now judged by the anchor's neighbourhood — the anchor
lines plus ANCHOR_RADIUS_LINES on each side — in both the ledger
fingerprint and the diff selection, which now reads hunk ranges from
git diff --unified=0. The guard side keeps whole-file granularity: a
guard has no anchor and changes as a whole. An anchor that is not found
exactly once falls back to the whole file, and so does a file whose
hunks were not read: not knowing is not proof. Same class of
approximation as the existing diff selection, with the nightly full
gate (#513) as the floor.

Two more cuts to the wall clock of a review round. The shard plan is now
computed before the environment is installed — restore the ledger,
select, split, and only then pay for npm ci, Python and Chromium; the
job still runs, so the review gate's proof (#510) is unaffected. And the
matrix goes from three shards to six: the same job-minutes, half the
wall time.

On the #500 round the selection drops 60 → 7. Four witnesses guard the
new logic, including the two unsafe defaults (ambiguous anchor, missing
hunks).

Issue: #518
User-Visible: no
2026-09-10 14:17:36 +03:00
Codex 398281a93f fix: the summary panel's first paint no longer freezes or claims the sources are gone
Two halves of the same first paint. The panel showed «Source unavailable»
in every row until the lazy metrics chunk arrived, because value() could
not tell "not loaded yet" from "source is dead"; and metrics() ran inside
render, walking the HA registry and unioning the clean floor of every
space synchronously — 11 s on the large-house fixture.

- totalCleanFloorAreaM2 computes the space's masonry and junction
  topology once per SPACE and hands them to innerContourForRoom, which
  otherwise unions the whole space again for every room: 11 045 → 1 488 ms
  on that fixture, same 306.3 m². The card has always done this through
  its own _innerContour cache; the panel now does the same.
- Aggregates leave the render path: the first frame paints skeletons and
  the work starts right after the frame is shown (timeout → rAF →
  timeout, never requestIdleCallback, which under load would leave the
  skeleton up for seconds). Stale memo keeps the previous number on
  screen instead of flashing back to a skeleton.
- valueState() separates pending from unavailable; a pending row keeps
  the same plate, grid and height and carries a pulsing rectangle the
  height of the line, replaced by the value with a short fade. Reduced
  motion keeps the rectangle and drops the pulse.
- Panel enter/exit animation (#505, 190 ms) is now actually visible —
  the main thread is free — and the smoke witnesses it.

Mutants: summary-first-paint-shows-unavailable, summary-metrics-block-first-frame,
summary-area-recomputes-walls-per-room, summary-stale-metric-falls-back-to-skeleton.

Issue: #509
User-Visible: yes
2026-09-10 11:24:10 +03:00
Codex 156835c048 ci: specs live in the issue body — body digest in review anchors, gate without a spec file
The spec file solved exactly one problem — proving that a review verdict
was passed on a given text — and created two: docs/specs/README.md
conflicted between parallel tasks and served as a second, stale status
dictionary, and every spec edit cost a commit, a push and a label. The
proof moves into the pipeline.

- review-doc-guard: normalizeIssueBody / issueBodyDigest (CRLF, trailing
  whitespace, trailing newlines), the anchor line `Тело issue: <sha256>`,
  anchorIssueBodyFrom, and issueBodyChanged — the finding "the spec
  changed after a green spec review", judged against the pipeline's own
  record in the last green SPEC-REVIEW, never against prose.
- reusableGreenVerdict takes the current digest: reuse (#499) skips the
  model entirely, so without this a spec edit between rounds would pass
  unseen. Documents without the record (the whole backlog) keep judging
  by tree.
- process.yml: the material step reads the body with `gh issue view` in
  the same run that fixes the material — the event snapshot describes a
  text the reviewer may never see; the digest goes into the anchors, into
  reuse and, when it differs, into the reviewer's prompt.
- process-gate: rule 3 judges the text (a `## ТЗ` heading or an AC1) with
  the archived file still accepted; adding a new file under docs/specs/
  warns — the directory is frozen.
- task-packet reads AC from the body first, the archived file second.
- PROCESS.md §2.3/§5/§7.1/§7.3/§10.5, AGENTS.md and docs/specs/README.md
  say so; the index table is gone with the long-standing §7.3 debt.

Mutants: review-anchor-drops-issue-body, review-ignores-changed-spec-body,
reuse-ignores-changed-issue-body, process-gate-requires-spec-file.

Issue: #517
User-Visible: no
2026-09-10 10:18:17 +03:00
Codexandclaude[bot] 3ad5d0baea ci: merge-candidate compares patch-ids without the review documents
The candidate is the branch tip, which already carries the round's
CODE-REVIEW-N-rK.md; the material the reviewer read does not. With
docs/reviews in the diff the two patch-ids never matched once dev had
moved, so every green candidate went back to review whenever another
task published its own document in the meantime — #514 looped twice on
09.09 and #508 only merged when dev happened to stand still. The
patch-id now excludes docs/reviews, exactly like `reviewedFresh` next to
it; a real change of the patch under rebase still returns the task.

Mutant: merge-rereviews-own-review-doc.

Issue: #516
User-Visible: no
2026-09-09 21:39:17 +00:00
Codexandclaude[bot] 0796a01571 ci: the E2E gate recognises its run by the suites that install the tag
Two findings from the live run on v1.73.0 (houseplan-e2e run
34393136097): the upgrade job carries the previous stable's tag in its
name, so "any job with HP <tag>" let a gate for v1.72.0 adopt the
v1.73.0 run — recognition now keys on `journeys`/`first-run`; and the
first poll after a dispatch sees only the matrix-planning job, which
marked the run as foreign forever — a run without any `· HP … ·` job is
undecided and polled again. Live: v1.73.0 → green with the run link,
v1.72.0 → no run of its own.

Issue: #514
User-Visible: no
2026-09-09 21:18:51 +00:00
Codexandclaude[bot] 57b19f9914 ci: the E2E gate upgrades from the previous stable, not from the tag under test
Live run on v1.73.0 (houseplan-e2e run 34392391382): at `release:
published` the new tag is already the newest stable, so
`upgrade_from=stable` made the upgrade suite update v1.73.0 onto itself
and fail with `Expected: not "1.73.0"`. The gate now resolves the newest
non-prerelease, non-draft release other than the tag from `gh release
list` and passes it as `upgrade_from`; the first stable ever falls back
to `stable`. Spec §4/§6 record the change and the matrix-planning job in
houseplan-e2e (a job-level `if` cannot read `matrix.*`).

Mutant: release-upgrades-stable-onto-itself.

Issue: #514
User-Visible: no
2026-09-09 21:18:51 +00:00
Codexandclaude[bot] c50458a098 ci: a stable release waits for a green E2E run on a real Home Assistant
The stable gate proved Validate and Full Performance on the exact SHA but
never ran the release in Home Assistant itself. houseplan-e2e installs
the release's houseplan.zip — the bytes HACS ships — into HA in docker
and walks the sidebar page, dashboards, roles, PDF, restart and the
stable→tag upgrade. release.yml now dispatches e2e.yml on the tag for
`!prerelease` releases and waits for it (scripts/e2e-gate.mjs, modelled
on validate-gate.mjs): the gate recognises its own run by `HP <tag>` in
the job names, ignores foreign dispatches, and reports red / missing /
cancelled / token error with the run link. Betas are untouched.

Mutants: release-ships-on-red-e2e, release-trusts-foreign-e2e-run.

Issue: #514
User-Visible: no
2026-09-09 21:18:51 +00:00
Codexandclaude[bot] e38beed796 fix: the summary panel settings dialog scrolls in Home Assistant
In HA hp-dialog renders ha-dialog, whose own `.body` is the scroller and
is not a flex container; `.summary-editor` (overflow:auto,
overscroll-behavior:contain, min-height:0) therefore grew to its content
and became a scroll container that never scrolls — Chromium stops wheel
and touch scroll chaining at such a child, so nothing moved (reproduced
on ha.jbstudio.pro, HA 2026.9.1, and in an isolated Playwright page).
hp-dialog gains an opt-in `flex-content` attribute forwarded as
ha-dialog's `flexcontent`, which lays the body out as a flex column: the
editor is height-bound again and scrolls itself, header and footer stay,
exactly as the native branch already did. Only the summary dialog opts in.

Smoke demo/smoke_summary_dialog_scroll.mjs stubs ha-dialog after the HA
2026.9 contract: wheel on desktop, touch swipe on a phone, dialog within
the viewport, and a witness that the stub reproduces the bug without
flexcontent. Docs screenshots: 11/11 pixel-identical (docs:accept
--identical, #512), fingerprint refreshed.

Mutants: summary-dialog-drops-flex-content, hp-dialog-ignores-flex-content.

Issue: #508
User-Visible: yes
2026-09-09 19:49:18 +00:00
Codex 0b9acd6382 docs: the local pre-push gate no longer calls the full mutation registry a pre-release gate
Code review r1 (M1): scripts/pre-push-gate.mjs — in its comment and in
the text every developer sees before a push — still named the full
mutation registry a pre-release gate; the same phrase lived in the
header of test/mutation-gate.test.mjs. Both now point at the nightly
schedule (#513); golden/smokes/HA harness are named as the heavy
Validate set on the candidate.

Issue: #513
User-Visible: no
2026-09-09 21:00:54 +03:00
Codex 61905bacdc ci: full mutation gate runs nightly, outside the development and release cycle
The full registry run proves that tests can fail, not that the product
works; 4 of its 5 runs since 02.09 were manual dispatches tied to
releases. Owner decision 09.09: a daily schedule (01:00 UTC, before the
02:30 nightly Validate), failures reported as an issue by the existing
#472 job, no place in the development or release flow. Docs and the
workflow comments say so; the test pins the daily cron.

Issue: #513
User-Visible: no
2026-09-09 20:49:08 +03:00
Codex b7d8b9e6ee test: displayed version through a seam; docs:accept --identical for pixel-identical screenshots
Golden frames carried the card version text (about, version banner,
support/export previews), so every beta bump re-accepted up to 20
baselines that had not visually changed. The version now reaches the DOM
and stand requests through displayVersion() (src/card-version.ts); the
golden harness pins window.__HP_VERSION_OVERRIDE__ = '0.0.0-golden'
before the card is created. CARD_VERSION literals stay where the release
contract reads them; cache-busting and the console banner keep the literal.

Docs screenshots: `npm run docs:accept -- --identical` re-captures
locally, compares decoded RGBA pixels with the committed frames inside
Chromium (scripts/png-identical.mjs) and, only when every frame is
identical, refreshes the manifest fingerprints and captureScriptSha256;
bytes stay, any difference refuses with a per-frame count. First run on
this tree: 11/11 identical, manifest refreshed.

Mutants: version-seam-ignores-override, docs-identical-accepts-any-frame.

Issue: #512
User-Visible: no
2026-09-09 18:53:38 +03:00
Codex 615181050b test: the real waitValidate is exercised against a cancelled dispatch
Code review r2 (M1): the cancelled-run filter in merge-candidate's
waitValidate had no test or mutant — every test replaced ops.waitValidate
with a fake. realOps now takes an injectable `exec` (default: the same
spawnSync wrapper) so the real implementation runs against scripted
`gh run list` answers: a cancelled dispatch is skipped and its
replacement followed; a lone cancelled run ends in `missing`, never red.

Mutant: merge-trusts-cancelled-dispatch.

Issue: #510
User-Visible: no
2026-09-09 18:45:44 +03:00
Codex 00130e08aa ci: a cancelled Validate dispatch proves nothing to the review gate
Code review r1 (M1): validate-gate.mjs and merge-candidate's waitValidate
read a `cancelled` dispatch run on the material as red, so a dispatch
replaced by the next one in the `validate-dispatch-<ref>` concurrency
group would have returned the task S7→S6 for nothing — the same class
#511 fixed in release-gate.mjs. Cancelled runs are now ignored: the gate
follows the replacement dispatch, or starts its own when there is none.

Mutant: review-returns-task-on-cancelled-dispatch.

Issue: #510
User-Visible: no
2026-09-09 18:33:24 +03:00
Codexandclaude[bot] cbece6324f test: re-anchor the review-starts-on-red-validate mutant after the r1 verdict split
The mutant registry pointed at the pre-r1 verdict helper that no longer
exists; the anchor test caught it in CI. The patch now removes the red
branch of the completed-run check.

Issue: #510
User-Visible: no
2026-09-09 15:14:20 +00:00
Codexandclaude[bot] 97dfa457a4 ci: diff mutants only on request; the review pipeline proves them on the material before reviewing
Validate ran the three "Мутанты по диффу" shards on every push of every
branch: 48 of 56 job-hours on 08–09.09, most of them cancelled by the
next push. Mutants now run when asked — pull requests, the nightly
schedule, a push carrying a `Release:` trailer, or a dispatch with
`mutants=true` (classify-changes.mjs → `mutants_requested`); an ordinary
push runs the light checks only.

The proof moves to where it is consumed. process.yml gets a gate after
the #499 reuse step: on the code stage it looks for a dispatch Validate
run on the exact material SHA whose mutant jobs executed and passed
(scripts/validate-gate.mjs); none → it dispatches one and waits; red or
missing → the task goes back S7→S6 with the run link and the review
cycle is not spent. Spec stage and the reuse fast-path skip the gate
(`proceed=true`); all later steps branch on `proceed` in place of the
old conflict conjunct only. merge-candidate.mjs dispatches Validate on
the pushed candidate and waits for that dispatch run.

PROCESS.md/AGENTS.md: review does not start on red code; one handoff —
one push.

Mutants: mutants-run-on-every-push, review-starts-on-red-validate,
review-trusts-push-run-without-mutants, merge-waits-push-run-without-mutants.

Issue: #510
User-Visible: no
2026-09-09 15:14:20 +00:00
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 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
Matysh 05778a47c0 Align summary panel with designer prototype (#505)
Issue: #505
User-Visible: yes
2026-09-09 09:32:36 +03: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
Sergey Matyunin 578cae5240 fix: harden summary panel settings and writes (#493)
Issue: #493
User-Visible: yes
2026-09-09 02:53:36 +03:00
Sergey Matyuninandclaude[bot] 1787e505a1 test: prove unresolved pair blocks following writes (#491)
Issue: #491
User-Visible: no
2026-09-08 23:01:49 +00:00
Sergey Matyuninandclaude[bot] 488f70c493 fix: make paired plan writes recover before the next edit (#491)
Issue: #491
User-Visible: yes
2026-09-08 23:01:49 +00:00
Claude e0e68f255d ci: added npm script does not select every mutant
Run 2795: changed_mutants shard 1/3 hit the 30-minute job limit with zero
failures. package.json sits in the guard-input closure of 195 of 590 mutants
(`npm run …`, `npx …`), so adding one script — toolchain:check — selected
nearly the whole registry. A guard depends only on what it calls: a changed
or removed existing script, dependencies, engines. An added script is not an
input of any earlier guard. packageJsonRelevance() decides from the base and
head package.json; unparsable or anything outside scripts still counts as
relevant. For the same range the selection drops from 209 to 38.

Issue: #496
User-Visible: no
2026-09-09 01:58:26 +03:00
Claude 71aeb86079 test: check-docs mutant guard judges docs, not screenshot freshness
Run 2793 (changed_mutants 2/3): the clean run of
`resource-docs-flatten-current-yaml` was red before any mutation because the
screenshot fingerprint is stale after #490 — strict mode, which #479 reserves
for the beta candidate. The guard now runs `--screenshots=warn`; a test keeps
every check-docs guard in that mode.

Issue: #496
User-Visible: no
2026-09-09 01:20:06 +03: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
Claude 24c1b723f9 infra: idempotent review controller, verdict reuse, single mutant build, current docs
Review pipeline (process.yml):
- concurrency moves from the workflow to the guard/review jobs and the guard
  runs only for S4-spec-review / S7-code-review. Any other label used to enter
  the issue's concurrency group and evict the pending review run (sample of
  150 runs since 2026-09-01: 92 empty guard-only runs, 30 cancelled).
- the guard reads the issue's current labels instead of the event snapshot; a
  label removed before the run starts is a withdrawn request, no comment.
- a green verdict is re-applied without calling the model when the latest
  review document carries the pipeline-recorded verdict `green`/High 0 and the
  tree differs from its anchor in nothing outside docs/reviews/** (#437 r4
  re-reviewed an unchanged tree for 7 minutes). The verdict from
  structured_output is now written into the anchor block for that purpose.
- the reviewer is pinned to the captured material SHA in the prompt; the
  broken escaping in the "merge cancelled" comment (empty SHAs) is fixed.

Mutation gate: nine browser guards started with `npm run bundle:sync` although
the runner already builds the mutant bundle — a second rollup plus a
`tsc --noEmit` that fails on a non-strict mutant before the smoke even runs.
Prefix removed; `--check` refuses guards that build the bundle themselves.

Docs: SCOPE (Project v2 dropped, three editors), STATUS (#437 merged, HACS zip
automated), USER-GUIDE ru/en (static card shows live states; kiosk double tap
on free background fits all), #34 → #425 references, #367 named as closed in
bundle-budget messages, PROCESS §10.4 and AGENTS.md describe the controller.

Issue: #499
User-Visible: no
2026-09-09 00:06:27 +03:00
Matysh e2751062dc feat: add per-room temperature thresholds
Issue: #487
User-Visible: yes
2026-09-08 10:44:13 +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
Matysh 597488f77e test: close House Plan panel acceptance gaps
Issue: #486
User-Visible: no
2026-09-08 00:55:40 +03:00
Matysh 8a97d4e30d feat: add the House Plan sidebar panel
Issue: #486
User-Visible: yes
2026-09-08 00:31:25 +03:00
Matysh e88ef93c3c fix: preserve stepped PDF dimensions
Issue: #484
User-Visible: yes
2026-09-07 21:05:57 +03:00
Matysh 7e7c9f3b49 fix: harden PDF dimension placement
Issue: #482
User-Visible: yes
2026-09-07 11:21:25 +03:00
Matysh 15b060ac38 fix: polish PDF export
Issue: #482
User-Visible: yes
2026-09-07 11:06:28 +03:00
Matysh 47951e85db test: close PDF export witness gaps
Issue: #53
User-Visible: no
2026-09-07 03:50:36 +03:00
Matysh d277eeb73b feat: export current space as architectural PDF
Issue: #53
User-Visible: yes
2026-09-07 03:47:57 +03:00
Codexandclaude[bot] 97aabddce7 ci: журнал пойманных свидетелей для changed_mutants
witnessFingerprint (файлы патча и гарда + объявление, без строки версии),
readLedger/recordCaught/splitByLedger, флаг --ledger только с --changed;
журнал пишется после каждого пойманного мутанта, в CI — cache restore по
префиксу шарда и save при любом исходе. Три свидетеля.

Issue: #481
User-Visible: no
2026-09-06 21:00:39 +00:00
Matyshandclaude[bot] ed63e4784f test: make seeded merge mutation effective
Issue: #477
User-Visible: no
2026-09-06 17:52:05 +00: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
Codex a6077ac922 ci: мутанты по диффу на каждом пуше, отбор и по файлам гарда
User-Visible: no
Issue: #475
2026-09-06 19:31:48 +03:00
Matysh 38abe78c9a fix: address room draft review findings
Issue: #478
User-Visible: no
2026-09-06 18:46:50 +03:00
Matysh 5ab41a7299 refactor: remove persisted room drafts
Issue: #478
User-Visible: yes
2026-09-06 17:38:47 +03:00
Codex 74eca9bdd1 test: мутант eager-import #474 использует привязку (Rollup выкидывает пустой импорт)
Issue: #474
User-Visible: no
2026-09-06 16:10:46 +03:00
Codex 9b4e1efb1d feat: арт мебели в ленивый чанк — стартовый граф 299 658 → 289 727 Б
Каталог (id, группа, размеры) остаётся eager; SVG-пути 44 дизайнерских
символов — отдельный чанк за FurnitureArtRuntime (ready|pending|fallback,
нонс на повторе, отпечаток сборки, осевший отказ). Запуск при приёме плана,
бут-вуаль ждёт арт в пределах BOOT_MAX_MS, редактор отдаёт арт рантайму
синхронно (adopt при загрузке чанка). Магнит проверяет каталог, не арт.
Потолок initial View 300 500 → 290 500. Семь свидетелей, смок
smoke_furniture_lazy_art, golden-harness требует все предметы после бута.
Ядро −2 строки.

Issue: #474
User-Visible: no
2026-09-06 16:10:46 +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
Codex e76f3909d9 ci: отчёт об отказе расписания мутантов — issue и Telegram
User-Visible: no
Issue: #472
2026-09-06 15:29:50 +03:00
Codex 0cf6cf4016 test: мутант AABB #473 снимает зазор по обеим осям
Issue: #473
User-Visible: no
2026-09-06 15:00:29 +03:00
Codex 49d4854221 test: свидетели на перф-дельту #160 — кэш размещений, зум внутрь, AABB
User-Visible: no
Issue: #473
2026-09-06 15:00:29 +03:00
Sergey Matyunin ee7d486924 feat: implement isometric stage 3
Issue: #160
User-Visible: no
2026-09-06 07:06:54 +03:00