Commit Graph
17 Commits
Author SHA1 Message Date
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 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
Codexandclaude[bot] f8ae546fb0 test: бамп версии не меняет отпечатки мутантов ядра; бандл пересобран
source-fingerprint.mjs входит в отпечаток сборки — три копии бандла
обновлены вместе с тестом.

Issue: #481
User-Visible: no
2026-09-06 21:00:39 +00: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
Codex 0145f9bafe ci: правка реестра мутантов сама запускает гейт по диффу (#475 r1)
Классификатор отдаёт выход mutants по scripts/mutation-gate.mjs, job
changed_mutants получает третий дизъюнкт из ТЗ §2; fallback-ветки
выставляют mutants=true. Тест AC7 отбирает бэкенд-мутанты по файлу патча.

Issue: #475
User-Visible: no
2026-09-06 19:33:08 +03:00
Codex a6077ac922 ci: мутанты по диффу на каждом пуше, отбор и по файлам гарда
User-Visible: no
Issue: #475
2026-09-06 19:31:48 +03:00
Codex 57a4a0ed69 ci: SHA отчёта mutation-gate — от чекаута dev, не github.sha (#472 r1)
Issue: #472
User-Visible: no
2026-09-06 15:29:50 +03:00
Codex e76f3909d9 ci: отчёт об отказе расписания мутантов — issue и Telegram
User-Visible: no
Issue: #472
2026-09-06 15:29:50 +03:00
Claude de30066be7 test(gates): мутанты на восемь модулей горячего пути из #451
#451 принёс 1 651 строку в восьми новых модулях, а единственный мутант
того релиза патчил houseplan-card.ts и houseplan-editor-runtime.ts —
места, ОТКУДА код ушёл. Вынос в модули был правильным решением, но
защита осталась смотреть на старые файлы.

Восемь мутантов, семь модулей, все прогнаны штатным раннером (чистый
прогон зелёный, мутант красный):

- live-editor-view-mode-routes-live — режим View обязан оставаться
  реактивным: живой путь редактора там означает план, который перестал
  отвечать на Home Assistant у двух персон из трёх;
- live-editor-first-gesture-frame-goes-live — первый кадр жеста меняет
  выделение и хром и обязан остаться реактивным;
- pointer-move-queue-keeps-first-move — очередь last-wins: сохранение
  ПЕРВОГО коллбэка кадра рисует план там, где палец уже не находится;
- live-hass-tick-never-deferred — тик состояния посреди жеста
  откладывается намеренно, и флаг отложенности гарантирует его
  воспроизведение после;
- live-viewport-identity-projection-not-recognized — см. ниже;
- render-invalidation-unknown-key-ignored — классификатор обязан
  ошибаться в сторону перерисовки на незнакомых ключах hass;
- resize-live-preflight-keeps-every-room — живой resize проверяет только
  задетые комнаты, иначе каждый кадр становится полной проверкой плана;
- render-lifecycle-diagnostics-cache-never-invalidated — кэш диагностики
  обязан сбрасываться, иначе красная точка нового устройства не загорится.

Мутант на live-viewport пришлось заменить, и это стоит записать. Issue
предлагал снять `setLayerProjection(layer, null)` из
`commitHouseplanViewport` — прогон показал, что тест остаётся ЗЕЛЁНЫМ:
следом идёт `paintLiveViewport(root, painted, painted)`, который на
равных аргументах даёт identity и обнуляет проекцию сам. Тот цикл —
подстраховка, а не контракт. Настоящий контракт — распознавание identity
(`isIdentityLiveLayerProjection`), потому что даже единичный transform
переключает путь композитинга и сдвигает установившийся растр на
несколько уровней цвета. Мутируется теперь он.

`src/live-hover.ts` остался без мутанта сознательно: его контракты либо
чисто производительные (мемо по наведённой комнате), либо доменные
(подсветка комнаты, застрявшая после ухода курсора). Первое мутантом не
ловится в принципе, второе — только браузерным смоком, которого в
песочнице нет. Записано в тесте и в issue.

Чтобы требование не жило в памяти, добавлен гейт: у каждого модуля
горячего пути обязан быть свой мутант, и он не имеет права патчить
houseplan-card.ts или houseplan-editor-runtime.ts — то есть исходный
дефект #458 больше не воспроизводим молча. Проверено отрицательным
прогоном: перевод патча любого из модулей на старое ядро краснит гейт.

Гейты: npm test 1960 tests, 1959 pass, 0 fail; typecheck зелёный;
mutation-gate --check зелёный на всех якорях; каждый из восьми мутантов
прогнан отдельно.

Issue: #458
User-Visible: no
2026-09-05 09:08:09 +03:00
Codex d274e38d57 test: mutation-gate accepts python guard files (#42)
User-Visible: no
Issue: #42
2026-08-30 21:34:32 +03:00
Codex 2c20f2dc35 perf: mutation-gate builds the bundle only for browser guards, compiles incrementally, shards and diffs (#332)
Four independent cuts into the 2-4 hour full run, none touching the contract
"a mutant must turn its guard red":

- guardNeedsBundle: rollup runs only for guards that open the built bundle
  (demo/ smokes, golden captures, bundle:sync) — 68 of 253 registry entries.
  Unit and backend guards never read dist/ as a build artifact (verified
  against every test that mentions dist/**: they read the git checkout or
  synthetic files), so 185 mutants skip the most expensive step entirely.
- seedTestBuild + incremental tsc: the mutant worktree starts from the main
  tree's warm test-build/ and .tsbuildinfo; tsc compares file hashes, not
  mtimes, so the fresh checkout stays warm and only the mutated delta is
  recompiled. This also speeds up the long guards that run tsc themselves.
- --changed[=range]: run only mutants whose patch files are touched by the
  diff (origin/dev..HEAD by default). An empty selection is an honest success
  with an explicit message — the full registry remains the pre-release
  contract, per the workflow comment.
- --shard=i/n: deterministic interleaved slices; the workflow runs a 4-way
  matrix, and a warm test-build step feeds every shard. Interleaving spreads
  the expensive browser mutants across shards instead of clumping them.

Measured per mutant on this machine: unit 12-13 s (was ~50-70 s), backend
6 s, browser 32 s (unchanged — the bundle is genuinely needed there). Full
run estimate drops to ~70 sequential minutes, ~20 on four shards.

Unit coverage: guard classification on real registry shapes, a floor on both
classes so the split cannot silently collapse, changed-selection semantics,
and shard completeness/disjointness with an anti-clumping bound.

Issue: #332
User-Visible: no
2026-08-28 01:33:36 +03:00
Codex 273b0d5ecb test: the backend mutant follows the registry convention (#329 r2-H1)
The reviewer is right twice over. My previous commit fixed the red CI by
relaxing the contract — a guard could name a `.py` file — when the registry
already had a convention for exactly this case: every backend mutant runs
`node scripts/backend-test-guard.mjs <pattern> <file>`, which owns the python
executable choice and the `-k` selection. Bending a rule to fit my one-off is
the worse of the two possible fixes, so the contract goes back to demanding a
`.mjs` guard, and junction-limit-backend-raw-baseline now uses the helper and
targets the one test that proves the migration
(test_legacy_baseline_is_judged_after_the_same_migration).

Re-verified: registry --check clean, the mutant still catches its regression
1/1, npm test 1390 passed / 0 failed.

Issue: #329
User-Visible: no
2026-08-28 00:41:30 +03:00
Codex 26c6e87079 test: a mutant guard may be pytest, not only node (#329)
The registry contract demanded that every guard name a `.mjs` file, which was
true until this task added the first backend mutant —
junction-limit-backend-raw-baseline is guarded by pytest, and the mutation-gate
job already installs it. My mistake: I ran `--check` and the single mutant
after adding it, but not the unit suite that owns the registry contract, so CI
caught what I should have.

The contract keeps its point: a guard must name a file that exists.

Issue: #329
User-Visible: no
2026-08-28 00:28:12 +03:00
Matysh 3aba493b25 fix: compile test-build inside the mutant worktree
Issue: #235
User-Visible: no
2026-08-22 11:24:37 +03:00
Matysh 328ed7afc0 test: a registry of known breakages that tests must catch
Validate / provenance (push) Successful in 46s
Validate / hacs (push) Failing after 10s
Validate / hassfest (push) Failing after 12s
Validate / process-gate (push) Failing after 35s
Validate / frontend (push) Successful in 6m11s
Validate / backend (push) Failing after 9m24s
Validate / golden (push) Failing after 10m10s
Validate / performance_smoke (push) Failing after 12m46s
Validate / smoke (push) Failing after 30m15s
Five times in this project a green test meant nothing was checked. The
continuity smoke stayed green after the entire mechanism it guards was cut out.
The golden scene created to protect doorway light was empty — 1,177 warm pixels
against 107,119, all of them icons. The shadow smoke passed while no shadow was
drawn. Each time the test had been written alongside the code, went green at
once, and nobody ever asked whether it could go red.

The gate makes that question routine. Each mutant is a few lines of patch that
reproduce a known breakage, plus the name of the test that must fail on it. A
worktree is patched, the bundle rebuilt, the guard run — and a guard that stays
green fails the gate. Six mutants cover the holes documented in #85; the anchors
are exact strings from today's source, so the registry cannot silently drift —
a unit test that runs with the ordinary suite refuses a stale anchor.

The full run rebuilds the bundle per mutant, so it lives in its own workflow,
before a stable release and on a weekly schedule, not in Validate. The rules for
new tests are written at the top of docs/TESTING.md, and the sixth of them is
the cheapest: an assertion that reads back the property the code just set is
not written at all.

Issue: #85
User-Visible: no
2026-08-14 02:05:53 +03:00