ci(mutants): skip the nightly registry on a proven tree; install only the shard's environment

#620. Mutants were ~70 % of CI machine time.

1. mutation-gate.yml: a green full run (aggregator verified all six shards)
   leaves a cache marker keyed by material tree + workflow SHA. A scheduled
   night with the same tree and workflow, marker not older than 7 days, skips
   the shards and writes "reused from run N" to the run summary. Red runs
   leave no marker, so the next night runs again and still files the issue
   (#472). Manual dispatch always runs the full registry. Decision is a pure
   function in scripts/mutation-nightly-reuse.mjs.
2. changed_mutants: the shard plan (already computed before setup, #518) now
   names the environment of its guards (plan-browser=/plan-python=, from
   scripts/mutation-environment.mjs). Python + backend deps only for shards
   with pytest guards, Chromium only for shards whose guards reach
   Playwright; pip wheels cached. Every shard still runs and reports, so the
   six mutant jobs of the review proof are unchanged.

Item 3 of the issue (smoke guards -> node --test) is out of scope here.

Issue: #620
User-Visible: no
This commit is contained in:
Claude
2026-09-24 05:48:42 +00:00
committed by claude[bot]
parent 7bb55c2a41
commit 44ee23ee33
10 changed files with 739 additions and 11 deletions
+21 -1
View File
@@ -45,7 +45,15 @@ identity и исход шага прогона, а отдельный агрег
rerun; лог шарда считается зелёным только с итоговой строкой `поймано N из M`)
каждую ночь по расписанию (01:00 UTC); в
релизном гейте он не участвует — проверяет тесты, а не продукт; отказ сам
заводит issue с отчётом (#472, #513). Дешёвая половина
заводит issue с отчётом (#472, #513). С #620 ночь по расписанию на дереве, уже
доказанном зелёным полным прогоном, шарды не гоняет: зелёный агрегатор
оставляет маркер в кэше Actions (tree материала, `github.workflow_sha`, номер
прогона), следующая ночь с тем же tree и тем же workflow принимает его и пишет в
сводку `reused from run N`. Маркер старше семи суток не принимается (tree
фиксирует код, а не раннер), ручной dispatch гоняет реестр всегда, а красный
прогон маркера не оставляет — следующая ночь гонит реестр заново и снова
заводит issue. Решение — чистая функция `scripts/mutation-nightly-reuse.mjs`
(`test/mutation-nightly-reuse.test.mjs`). Дешёвая половина
идёт с юнитами: `test/mutation-gate.test.mjs`. Локально для дельты задачи —
`node scripts/mutation-gate.mjs --changed origin/dev..HEAD`: гоняются только
мутанты, чьи patch-файлы или **входы гарда** задеты диффом (#332, #475, #492).
@@ -103,6 +111,18 @@ job-минут и в основном отменялись следующим п
на точном SHA; зелёный push-прогон им не является. Релизный гейт mutant-jobs не
требует (`CI_PROOF_POLICIES.release.mutants = false`).
План шарда (`--plan-only`) считается до установки окружения (#518) и с #620
называет окружение своих гардов строками `plan-browser=` и `plan-python=`
(`scripts/mutation-environment.mjs`). Python с зависимостями бэкенда ставится
только шарду с pytest-гардами (в графе исполнения гарда есть `.py` или запуск
`'python3'`/pytest), Chromium — только шарду, чей граф исполнения импортирует
Playwright (смоки, golden, юниты через `demo/serve.mjs`). Граф исполнения — не
замыкание входов для отбора: файлы из строки гарда, объявленные входы обёрток,
пути, названные в этих точках входа, и их относительные импорты. Шард без
таких гардов окружение не ставит, но исполняется и отчитывается — шесть
mutant-jobs в доказательстве ревью (#541) не меняются. Ошибка признака
ложной зелени не даёт: гард без своей среды краснеет уже чистым прогоном.
`changed_mutants` добавляет `--ledger=<файл>` — журнал доказанных
свидетелей (#481, #550): после каждого пойманного мутанта в файл пишутся тип
доказательства (`assertion` или явно объявленный `compile`) и отпечаток