Commit Graph
695 Commits
Author SHA1 Message Date
Sergey Matyunin 5790abaa1f fix: suppress device activation during touch pinch (#578)
Issue: #578
User-Visible: yes
2026-09-14 21:23:58 +03:00
Sergey Matyunin 258896cb6f feat: refine hidden isometric Stage 4 (#570)
Issue: #570
User-Visible: no
2026-09-14 15:29:57 +03:00
Sergey Matyuninandclaude[bot] 6aca447fa0 fix: улучшить доступность View (#565)
Issue: #565
User-Visible: yes
2026-09-14 07:06:16 +00:00
CodexandCodex 264fba0902 Отказ подготовки называет виновника
Свидетель, который не готовится к прогону, краснил гейт той задачи, чей дифф его
выбрал, даже когда причина лежала в чужом коммите: на #566 это стоило двух
кругов. Теперь при исходе `setup-failure` в дифф-режиме прогоняется ОПРЕДЕЛЕНИЕ
БАЗЫ на дереве базы, и раннер говорит прямо — отказ предсуществующий или внесён
этим диффом. Сравнение подобного с подобным здесь принципиально: с определением
из головы собственная сломанная правка реестра выглядела бы предсуществующей.

Предсуществующий гейт задачи не красит (решение владельца 14.09) и не теряется:
он назван машиночитаемой строкой и обязан покраснеть в ночном полном прогоне, у
которого есть адресат (#472). Мутанта, которого в базе нет, оправдывать нечем по
построению.

Композиция чтения реестра базы и запуска мутанта живёт отдельным модулем:
границу «запуск не зависит от отбора» держит тест #558, и CLI обязан остаться
тонким.

Issue: #568
User-Visible: no
2026-09-14 08:55:17 +03:00
Sergey Matyunin 0af582daa5 test: защитить hover-gate маркеров (#564)
Issue: #564
User-Visible: no
2026-09-14 03:16:00 +03:00
Sergey Matyunin f9ed9d2ae8 fix: сохранить точную активацию маркера (#564)
Issue: #564
User-Visible: yes
2026-09-14 02:57:50 +03:00
Sergey Matyunin 6de854a03d fix: разрешить перекрытия целей маркеров (#564)
Issue: #564
User-Visible: yes
2026-09-14 02:57:50 +03:00
CodexandCodex 733cd5b86b Три состояния владельца позиции вместо двух
Ревью r1, Medium: наблюдение о записи на удалённом пространстве говорило
«владелец жив» и про ключ, который ни во что не резолвится. Это заявление о
доказанности там, где её нет: продукт в этом состоянии ничего не удаляет не
потому, что владелец жив, а потому, что не знает — `space-reference-repair`
ведёт `live`, `absent` и `unverified`, три состояния, а не два.

Проверка ведёт те же три. Нерезолвящийся ключ получает наблюдение
`unknown_owner` с той же формулировкой, что и в живом пространстве: «владелец не
найден в конфигурации (возможно устройство HA)». Тест сверяет теперь и ТЕКСТ
причины — вид наблюдения без текста эту асимметрию пропускал, ровно так она и
проехала.

Issue: #566
User-Visible: no
2026-09-14 02:28:50 +03:00
Codex dedcedc8cc Позиция на удалённом пространстве судится по владельцу
Инварианты объявляли нарушением ЛЮБУЮ запись layout, чьё пространство удалено.
Продукт так не считает: `space-reference-repair` удаляет такую запись только
когда может доказать, что владелец тоже исчез, и сознательно хранит её, когда
владелец жив или доказательств нет — удаление уносит расстановку пользователя.
Конфиг сразу после Optimize законно содержит такие записи, и проверка называла
нарушением штатное состояние.

Теперь правило то же, что у продукта: нарушение — только когда владельца нет по
самой конфигурации (комната, область или снятый маркер). Остальное —
наблюдение, как у ветки `unknown_owner` рядом.

Issue: #566
User-Visible: no
2026-09-14 01:27:58 +03:00
Codex 03983946c5 Источники радара сравниваются по смыслу, а не по тексту
Гард `keepTwoPoint` решал, сохранять ли двухточечную калибровку, сравнением
`JSON.stringify`, то есть текста. Порядок ключей `sources` при этом меняет сам
билдер: `slots`/`ranges`/`zones`/`occupancy_entity`/`count_entity` он удаляет и
дописывает заново, а `availability_entity` остаётся на месте и уезжает в начало.
Конфиг, только что записанный этим же билдером, при следующем открытии
сравнивался неравным — и радар с `availability_entity` терял `refs` и `rms_cm`,
получая `method: manual`, при первом же обычном сохранении.

Сравнение стало каноничным по порядку ключей объектов и осталось чувствительным
к порядку элементов массивов: позиция слота — это его `target_N`. Проекция не
затронута — она считается от `mount`, `cell_cm` и `mirror`.

Issue: #567
User-Visible: no
2026-09-13 23:23:30 +03:00
Codex db7eef5306 Корпус геометрий, household-сценарии и аудит доступности View
Полевая проверка основного View по #560: шесть обезличенных планов корпуса и
цепочка import → Optimize → Optimize → Resize → сохранение с численными
оракулами, семь household-путей с независимыми оракулами в двух ширинах
карточки, аудит доступности с измеренными числами. Продуктовых правок нет:
находки заведены отдельно (#564, #565, #566).

Issue: #560
User-Visible: no
2026-09-13 21:05:28 +03:00
Sergey Matyunin c53fd1a54f refactor: split mutation gate modules (#558)
Issue: #558
User-Visible: no
2026-09-13 20:29:35 +03:00
CodexandCodex e0098c8d00 Права модели в ревью держит job-scoped токен, а не App-обмен
Объявленные `permissions:` у `model_review` не были потолком: без переданного
`github_token` claude-code-action меняет OIDC на собственный App-токен, дефолт
которого — contents/issues/pull_requests: write, и `ghs_…` от claude[bot]
оказывался прямо в окружении Bash-инструмента модели. Ревью r1 показало это
живым доказательством в собственной же сессии.

Теперь шагу Review передан ambient `secrets.GITHUB_TOKEN`: обмена не происходит,
`id-token` не нужен, список прав становится настоящим. У модели остаётся ровно
одно право записи — `issues: write` под комментарий вердикта (§7.2) и issue по
§12; записи в репозиторий у неё больше нет.

Issue: #556
User-Visible: no
2026-09-13 19:59:59 +03:00
Codexandclaude[bot] b35551884f Сторонние Actions закреплены SHA, права выданы по job, граница проверяется фикстурами
Три вещи, которые аудит 12.09 назвал в §10.

**Перемещаемые ссылки.** `home-assistant/actions/hassfest@master` и
`hacs/action@main` — это произвольный будущий коммит чужой ветки, а ревьюера с
Read/Write/Bash запускал перемещаемый major `anthropics/claude-code-action@v1`.
Все 116 `uses:` в девяти воркфлоу закреплены полным SHA с комментарием-версией;
`scripts/action-pins.mjs` это проверяет, а предполётный вердикт Validate —
исполняет. Локальная переиспользуемая workflow пина не требует и исключена
явно.

**Права.** Один блок `permissions` на весь конвейер выдавал `issues: write` и
OIDC каждой стадии, включая единственную недоверенную — работу модели. Теперь
права выдаются по job: модели только чтение и OIDC для самой
`claude-code-action`, писать в issue умеют детерминированные стадии.

**Граница.** Разбор запечатанного результата переехал из inline-shell в
`scripts/review-result-gate.mjs` — не ради красоты, а потому что в YAML его
нельзя прогнать ни одним отрицательным случаем. Проверяются те же вещи, что и
раньше, и в том же объёме: точный набор файлов, контрольные суммы, схема
паспорта и совпадение КАЖДОГО из семнадцати полей с тем, что посчитала
детерминированная стадия. Сверху — пятнадцать враждебных фикстур: неполный
набор, лишний файл, подменённое содержимое, чужой run и попытка, устаревший
material_sha и tree, чужие задача, этап, раунд и ветка, вердикт вне словаря,
пустой документ, manifest не о тех файлах, неразбираемый JSON.

Настоящих секретов и привилегированных операций фикстуры не трогают.

Issue: #556
User-Visible: no
2026-09-13 16:24:10 +00:00
Sergey Matyunin cc0b41ba61 test: восстановить запас bundle-ratchet для #563
Issue: #563
User-Visible: no
2026-09-13 18:53:06 +03:00
Sergey Matyunin aa13e2264e fix: блокировать нажатия устройств после pinch (#563)
Issue: #563
User-Visible: yes
2026-09-13 18:44:07 +03:00
Sergey Matyunin e36767773a test: make mutation oracles explicit before v1.76.0-beta.1
Run 34760156615 exposed stale registry witnesses under the honest #550 outcome taxonomy. Keep behavioural checks out of setup chains, retarget the preflight mutation to the editor host, and make the junction cache smoke exercise same-object in-place geometry changes.

Release: v1.76.0-beta.1
Issue: #550
User-Visible: no
2026-09-13 17:06:24 +03:00
Sergey Matyunin d0ecd53831 fix: сохранять диагностику при сбое восстановления review-метки (#555)
Issue: #555
User-Visible: no
2026-09-13 15:47:50 +03:00
Sergey Matyunin e3bf893e3d ci: восстанавливать потерянные запросы ревью (#555)
Issue: #555
User-Visible: no
2026-09-13 15:26:13 +03:00
Sergey Matyunin f601182a90 test: ловить старую формулировку процесса через перенос строки (#553)
Issue: #553
User-Visible: no
2026-09-13 15:03:47 +03:00
Sergey Matyuninandclaude[bot] 55db3d4986 docs: устранить противоречия процессного канона (#553)
Issue: #553
User-Visible: no
2026-09-13 11:54:02 +00:00
Sergey Matyunin 62e0eff219 fix: отделить delimiter результата ревью от JSON (#551)
Issue: #551
User-Visible: no
2026-09-13 14:34:17 +03:00
Sergey Matyunin 23f48829c2 fix: сохранить объект вердикта между стадиями ревью (#551)
Issue: #551
User-Visible: no
2026-09-13 14:11:42 +03:00
Sergey Matyunin 31ef70cee6 ci: разделить стадии ревью по бюджетам (#551)
Issue: #551
User-Visible: no
2026-09-13 13:05:25 +03:00
Sergey Matyunin d89b55ccf0 test: распознавать исполнившийся subtest в outcome (#550)
Issue: #550
User-Visible: no
2026-09-13 12:42:01 +03:00
Sergey Matyunin 4d8ad3db32 test: различать исходы мутационного гейта (#550)
Issue: #550
User-Visible: no
2026-09-13 12:31:22 +03:00
Sergey Matyunin 80e3fee527 fix(ci): запускать агрегатор из material (#549)
Issue: #549
User-Visible: no
2026-09-13 11:48:16 +03:00
Sergey Matyunin 723ec6d362 ci: фиксировать material ночных мутаций (#549)
Issue: #549
User-Visible: no
2026-09-13 11:21:40 +03:00
Sergey Matyunin b15d357fa2 fix(ci): принимать proof reuse геометрического parity (#548)
Issue: #548
User-Visible: no
2026-09-13 10:58:19 +03:00
Sergey Matyunin 76d8017e87 ci: исполнять TS/Python parity на чистом runner (#548)
Issue: #548
User-Visible: no
2026-09-13 10:49:07 +03:00
Sergey Matyunin 6c6f53491f fix(release): bind beta bookkeeping to candidate (#547)
Issue: #547
User-Visible: no
2026-09-13 10:35:43 +03:00
Sergey Matyunin 5fc596c748 fix(process): bind verdict wait to current review round (#546)
Issue: #546
User-Visible: no
2026-09-13 10:26:12 +03:00
Sergey Matyunin fdb0d0743d ci: keep proof job names API-verifiable (#541)
Issue: #541
User-Visible: no
2026-09-13 10:07:04 +03:00
Sergey Matyunin a8ae5a45e1 ci: fix proof job workflow syntax (#541)
Issue: #541
User-Visible: no
2026-09-13 10:07:04 +03:00
Sergey Matyunin 9c269c302d ci: unify Validate proof across gates (#541)
Issue: #541
User-Visible: no
2026-09-13 10:07:04 +03:00
Sergey Matyuninandclaude[bot] d6180f7f5d fix: подсказывать infra-вход до появления ветки (#562)
Issue: #562
User-Visible: no
2026-09-13 06:56:20 +00:00
Sergey Matyuninandclaude[bot] 7b58f73e57 fix: доказывать infra-трек по diff (#562)
Issue: #562
User-Visible: no
2026-09-13 06:56:20 +00:00
Sergey Matyuninandclaude[bot] 3934f8d8e5 process: отвязать роли от конкретных агентов (#562)
Issue: #562
User-Visible: no
2026-09-13 06:56:20 +00:00
Sergey Matyuninandclaude[bot] 744f502ba3 ci: include dynamic backend inputs in gates (#542)
Issue: #542
User-Visible: no
2026-09-13 06:46:38 +00:00
Sergey Matyuninandclaude[bot] c1c3743f5d infra: закрепить локальный toolchain Windows и WSL (#557)
Добавлены безопасные pinned entrypoints, вывод фактических путей, идемпотентный Windows setup и WSL verification с настоящим HA subset и Linux capture.

Issue: #557
User-Visible: no
2026-09-13 06:05:45 +00:00
Claude eb77224e0c ci: единый staged→tested→published путь установочных ассетов (#540)
`release-zip.yml` выкладывал `houseplan.zip` в ту же секунду, когда релиз
становился публичным — до Validate, Full Performance и E2E; `release.yml`
параллельно пересобирал `houseplan-card.js`, а E2E требовал публичного ZIP,
чтобы вообще начаться. Публикаторов было четыре, порядок — ни одного.

Теперь публикатор стабильных один — `release.yml`: закрепить SHA → релиз в
черновике (опубликованный руками немедленно возвращается в черновик) → гейты
на SHA (трейлер `Release: <tag>`, контракт `--stable`, Validate, Full
Performance, E2E на коммите-кандидате через tarball codeload) → одна сборка,
`git archive` ZIP из того же дерева, `SHA256SUMS` → загрузка в черновик →
публикация → скачать публичное и сверить с паспортом → анонс. Dispatch на
публичный тег — ремонт: догружается только недостающее, расходящийся хеш —
отказ. Беты кладут тот же паспорт; локальный публикатор больше не ждёт
републикаторов — их нет.

- `.github/workflows/release-zip.yml` удалён
- `scripts/release-assets.mjs` — паспорт ассетов (`sums`/`check`), чистые
  функции под юнитами
- `scripts/e2e-gate.mjs --ref=<sha>` — под тестом кандидат, `--tag` только
  для выбора `upgrade_from`
- `scripts/release-contract.mjs --stable`
- мутанты: независимый публикатор, снятая зависимость от гейта, релиз без
  возврата в черновик, `--clobber` в ремонте, E2E на теге, слепой паспорт

Issue: #540
User-Visible: no
2026-09-13 07:42:23 +03:00
Sergey Matyunin bb35af993a fix: сохранить identity карточек Masonry после reload (#561)
Сводная панель теперь использует канонический порядок карточек Home Assistant и не переносит локальные настройки между визуальными колонками после remount.

Issue: #561
User-Visible: yes
2026-09-13 02:04:45 +03:00
Sergey Matyunin a1fac44d72 fix: не откатывать конфигурацию поздним reload (#543)
Issue: #543
User-Visible: yes
2026-09-12 22:29:16 +03:00
Sergey Matyunin 6502f516f9 fix: keep live pan edges covered (#544)
Issue: #544
User-Visible: yes
2026-09-12 20:44:05 +03:00
Codex 66a6485418 Контракт беты пинит отсутствие ветки события, а не её наличие
`release-contract.test.mjs` требовал в анонсе условие про
`github.event_name == 'release'` — оно и было единственным местом, где путь
события закреплялся. Раз анонс вызывается только после выкладки, требование
перевёрнуто: ветки события в файле быть не должно.

Issue: #538
User-Visible: no
2026-09-12 14:02:27 +03:00
Codex 7baa1cfa13 Свидетель требует директиву, а не её цитату в комментарии
Мутант, снимающий `needs: build` с анонса, выживал: проверка искала подстроку
`needs: build` в блоке задания, а ровно эта строка процитирована двумя
строками выше — в комментарии, объясняющем, зачем зависимость нужна. Проверка
зеленела на собственном объяснении.

Issue: #538
User-Visible: no
2026-09-12 14:02:27 +03:00
Codex 293309355b Анонс уходит после выкладки ассетов, а не рядом с ней
Три воркфлоу висели на одном событии `release: published` и бежали
параллельно. Анонс выигрывал эту гонку всегда: проверять ему нечего. 12.09
стабильную v1.75.0 объявили в канале в ту же минуту, когда гейт отказал —
Full Performance был красный (#537), E2E после него не выполнялся вовсе,
ассеты не выкладывались. Подписчики получили сообщение о релизе, страница
которого осталась без `houseplan-card.js`.

Триггер события снят: у анонса остаются кнопка проверки связи и вызов из
воркфлоу. `release.yml` зовёт его после джобы выкладки (`needs: build`), то
есть красный гейт или несостоявшаяся выкладка сообщения не рождают. Путь беты
не тронут — `publish-prerelease.yml` звал анонс сам и раньше.

Мёртвая ветка чтения события из шага убрана вместе с триггером: тело берётся
из заметок ветки тега, как в вызове из беты.

Issue: #538
User-Visible: no
2026-09-12 14:02:27 +03:00
Codex c291384b7a Свидетель ожидания пинит саму сверку, а не её обвязку
Мутант, выкидывающий сравнение ответа REST с новой вершиной, выживал: проверка
смотрела на вызов `gh api`, токен, порядок шагов и текст отказа — всё это
мутант оставляет на месте, а цикл после него выходит на первой же итерации, и
ожидание становится декорацией.

Issue: #539
User-Visible: no
2026-09-12 13:54:38 +03:00
Codex ccfd2565a7 Диспатч уходит после того, как ссылка ветки доехала
`workflow_dispatch` в API принимает только ref: SHA туда передать нельзя, имя
ветки резолвится на стороне GitHub в момент запуска. Конвейер перед этим сам
переписывает ветку ребейзом — и 12.09 на #536 диспатч, отправленный через три
секунды после force-push, встал на ДОпушевый SHA. Гейт искал прогон строго на
SHA материала, не нашёл и вернул задачу автору со словами «материал сменился».
Чинить было нечего: дерево задачи не менялось ни на байт, материал сдвинул сам
конвейер.

Две меры, у каждой своя роль.

Шаг ребейза не заканчивается, пока REST не отдаст новую вершину — именно REST,
потому что через него же идёт диспатч. Минута ожидания, после чего отказ, а не
молчание: диспатч на устаревший SHA стоит трёх минут гейта и потерянного
захода.

Гейт, не дождавшись прогона на материале и увидев на ветке диспатч на другом
SHA, сначала пробует запустить ещё раз. Своя гонка этим закрывается, чужой
коммит переживает и вторую попытку, а формулировка отказа больше не называет
сменой материала то, что ею не является.

Issue: #539
User-Visible: no
2026-09-12 13:54:03 +03:00
Claude 1ef35883e0 Ask a foreign manifest whether it can be loaded, not how it was wired
Проверка (CI) / Классификация изменённых файлов (push) Successful in 22s
Проверка (CI) / Мутанты по диффу (1/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (2/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (3/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (4/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (5/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Мутанты по диффу (6/6): затронутые свидетели краснеют (push) Skipped
Проверка (CI) / Предполётные проверки: документация, провенанс, процесс (push) Successful in 52s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 27s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 21s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 1m10s
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Failing after 13m27s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 15m22s
Проверка (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
The performance harness runs the candidate's benchmark against a
baseline checkout, so the candidate's validator reads a manifest built
by an older commit. #535 put a rule about the CURRENT build into that
shared validator — the panel graph must not contain the card facade —
and it is false of every build before #535 by construction. The
candidate then refused to load any older baseline: all nine performance
profiles went red at once on the same step, the stable release gate
withheld `houseplan-card.js` from the published v1.75.0, and none of it
was about speed.

assertBundleManifest now answers only the loader's question: paths
exist, nothing is duplicated, graphs reference listed assets, sizes add
up. The topology of the current build moves to assertOwnBundleTopology,
called from bundle-sync.mjs, which materializes our own dist, and from
the unit test that reads dist/houseplan-assets.json. Neither ever looks
at a foreign tree.

Reproduced end to end, not only in a unit: a v1.74.0 worktree built with
its own code, then `node demo/benchmark_large_house.mjs
--target-root=<baseline>` from this tree. Before the change it stops
with «initial panel graph must contain its own stable entry only»; after
it, the profile is captured.

Issue: #537
User-Visible: no
2026-09-12 09:39:05 +03:00