ci: имена job validate.yml — контракт, сверяемый с файлом; шарды из матрицы (#622)

- scripts/workflow-jobs.mjs: разбор job-уровня validate.yml (id, name,
  inline matrix) без зависимостей; незнакомые формы — громкая ошибка.
- ci-proof: JOB_RULES по id job с именем-контрактом; число и точные имена
  экземпляров — из матрицы YAML (константы count: 6 нет); resolveJobRules
  на каждом evaluateCiProof — переименование даёт failed с названной job;
  jobContractProblems — сверка в обе стороны, UNCONSUMED_JOBS для proof.
- validate-gate: MUTANT_JOB_PREFIX — из контракта ci-proof.
- e2e-gate: E2E_JOB_NAME — зеркало name: из houseplan-e2e e2e.yml
  (43899da5), распознавание выводится из шаблона; missing называет
  завершённые прогоны без job по контракту.
- тесты: фикстуры имён выводятся из validate.yml; новый
  test/workflow-jobs.test.mjs; 5 мутантов в реестре.

Issue: #622
User-Visible: no
This commit is contained in:
Claude
2026-09-24 01:35:25 +00:00
committed by claude[bot]
parent 0ca56b4450
commit 1514899746
12 changed files with 593 additions and 93 deletions
+7 -7
View File
@@ -4,18 +4,18 @@ import test from 'node:test';
import { validateGate, isMutantRun, provesMutants } from '../scripts/validate-gate.mjs';
import { buildCiProof } from '../scripts/ci-proof.mjs';
import { jobInstanceNames, validateJobs } from '../scripts/workflow-jobs.mjs';
const SHA = 'a'.repeat(40);
const TREE = 'b'.repeat(40);
/** Fake gh: a scripted list of run snapshots per call, a virtual clock. */
const MUTANT_JOBS = [1, 2, 3, 4, 5, 6].map((n) => ({ name: `Мутанты по диффу (${n}/6): затронутые свидетели краснеют`, conclusion: 'success' }));
const OTHER_JOBS = [{ name: 'Фронтенд: типы, юниты, мутанты, синхрон бандла', conclusion: 'success' }];
const BASE_JOBS = [
{ name: 'Предполёт: документация, провенанс, процесс', conclusion: 'success' },
{ name: 'Классификация изменённых файлов', conclusion: 'success' },
{ name: 'Переиспользование: это дерево уже проверено', conclusion: 'success' },
];
// #622: имена и число экземпляров job — из validate.yml, не копией строк.
const WORKFLOW = validateJobs();
const jobsOf = (...ids) => ids.flatMap((id) => jobInstanceNames(WORKFLOW.get(id)).map((name) => ({ name, conclusion: 'success' })));
const MUTANT_JOBS = jobsOf('changed_mutants');
const OTHER_JOBS = jobsOf('frontend');
const BASE_JOBS = jobsOf('preflight', 'changes', 'reuse');
function fakeOps({ snapshots, onRef = [], jobsById = {} }) {
let clock = 0;