Package the validated Stage 4 candidate while keeping the isometric experiment hidden and the default Flat experience unchanged.
Release: v1.76.0-beta.3
Issue: #570
User-Visible: yes
Первый ночной прогон с честным критерием (#550) дал 726 из 735: девять мутантов
не доходили до заявленного теста. Причины оказались тремя, а не одной, как я
ожидал по трём случаям из #566:
- статически мёртвая ветка (`if (false && …)`, `if (true) throw`) — TypeScript
теряет сужение, сделанное выше: `united`, `_relation`, `previous`, остаток
функции после безусловного throw. Лечится ложью, ложной в рантайме, но не
статически;
- пустой литерал `[]` выводится как `never[]`, и падают уже вызывающие. Лечится
сохранением типа при потере содержимого (`slice(0, 0)`, `as string[]`);
- несовпадение типов в самой замене: `canonicalizeNumber` отдаёт `unknown` там,
где нужен `T`; подмена резолвера литералом сужала union, и ветка
`resolution.reason` становилась `never`; бракованная метка `case` ломала
`switch` по union.
Смысл каждого мутанта сохранён: все девять прогнаны по `--id=` и краснят свой
заявленный тест.
Issue: #569
User-Visible: no
Свидетель, который не готовится к прогону, краснил гейт той задачи, чей дифф его
выбрал, даже когда причина лежала в чужом коммите: на #566 это стоило двух
кругов. Теперь при исходе `setup-failure` в дифф-режиме прогоняется ОПРЕДЕЛЕНИЕ
БАЗЫ на дереве базы, и раннер говорит прямо — отказ предсуществующий или внесён
этим диффом. Сравнение подобного с подобным здесь принципиально: с определением
из головы собственная сломанная правка реестра выглядела бы предсуществующей.
Предсуществующий гейт задачи не красит (решение владельца 14.09) и не теряется:
он назван машиночитаемой строкой и обязан покраснеть в ночном полном прогоне, у
которого есть адресат (#472). Мутанта, которого в базе нет, оправдывать нечем по
построению.
Композиция чтения реестра базы и запуска мутанта живёт отдельным модулем:
границу «запуск не зависит от отбора» держит тест #558, и CLI обязан остаться
тонким.
Issue: #568
User-Visible: no
Ревью r1, Medium: наблюдение о записи на удалённом пространстве говорило
«владелец жив» и про ключ, который ни во что не резолвится. Это заявление о
доказанности там, где её нет: продукт в этом состоянии ничего не удаляет не
потому, что владелец жив, а потому, что не знает — `space-reference-repair`
ведёт `live`, `absent` и `unverified`, три состояния, а не два.
Проверка ведёт те же три. Нерезолвящийся ключ получает наблюдение
`unknown_owner` с той же формулировкой, что и в живом пространстве: «владелец не
найден в конфигурации (возможно устройство HA)». Тест сверяет теперь и ТЕКСТ
причины — вид наблюдения без текста эту асимметрию пропускал, ровно так она и
проехала.
Issue: #566
User-Visible: no
`optimizer-micro-interval-cleanup-disabled` вставлял безусловный `return` в
начало функции. Остаток функции становился недостижимым, и там TypeScript терял
сужение `profile` — компиляция падала до теста. Возврат сделан под
рантайм-условием: смысл мутанта («очистка отключена») тот же, остаток кода для
проверки типов остаётся достижимым.
Issue: #566
User-Visible: no
`inner-span-reads-whole-edge-thickness` и `safe-resize-legacy-midpoint-fail-open`
падали на `npx tsc -p tsconfig.test.json` до запуска заявленного теста и потому
не проверяли ничего. Причина одна: патч делал ветку статически мёртвой
(`if (false)`, `false &&`), а в мёртвой ветке TypeScript теряет сужение типов,
сделанное выше — `profile` снова `| null`, `direct` снова `| undefined`.
Условия заменены на ложные в рантайме, но не статически. Смысл мутантов тот же,
и оба теперь ловятся заявленными тестами. Обнаружено прогоном на этой ветке:
правка реестра затягивает в отбор мутантов чужие файлы, и красным стал гейт
задачи, к которой эти записи отношения не имеют. Провал такого мутанта
незаметен, пока его не выберет дифф — это отдельный пробел, #568.
Issue: #566
User-Visible: no
Инварианты объявляли нарушением ЛЮБУЮ запись layout, чьё пространство удалено.
Продукт так не считает: `space-reference-repair` удаляет такую запись только
когда может доказать, что владелец тоже исчез, и сознательно хранит её, когда
владелец жив или доказательств нет — удаление уносит расстановку пользователя.
Конфиг сразу после Optimize законно содержит такие записи, и проверка называла
нарушением штатное состояние.
Теперь правило то же, что у продукта: нарушение — только когда владельца нет по
самой конфигурации (комната, область или снятый маркер). Остальное —
наблюдение, как у ветки `unknown_owner` рядом.
Issue: #566
User-Visible: no
Гард `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
Полевая проверка основного View по #560: шесть обезличенных планов корпуса и
цепочка import → Optimize → Optimize → Resize → сохранение с численными
оракулами, семь household-путей с независимыми оракулами в двух ширинах
карточки, аудит доступности с измеренными числами. Продуктовых правок нет:
находки заведены отдельно (#564, #565, #566).
Issue: #560
User-Visible: no
Объявленные `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
Комментарий с версией рядом с SHA — единственное, что говорит читателю, какой
релиз держали в руках; `docs/DEVELOPMENT.md` описывает, как посмотреть, что
сейчас за тегом, и заменить обе части одним коммитом. Отдельно записано, что у
`home-assistant/actions` и `hacs/action` тегов нет вовсе — там в комментарии
стоит дата, на которую читалась голова ветки.
Запись `NOT_AN_INPUT` для `.github/workflows/*.yml` снята: воркфлоу читает
проверка пинов, то есть они теперь честный вход, а не «у каждого свой запуск».
Issue: #556
User-Visible: no
Три вещи, которые аудит 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
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
Синхронизировать исполняемый process workflow с dev и добавить bounded queue reconciler в ветку по умолчанию. Product source, release candidate и version files не меняются.
Issue: #555
User-Visible: no