ci(metrics): еженедельный замер процесса одним скриптом (#637)

scripts/process-metrics.mjs — чистые функции над снимками GitHub: по issue
(таймлайн меток) вход по первой статусной метке, S4→S5, вход→S7, S7→S8,
повторные постановки S7; раунды ревью — по документам docs/reviews, не по
событиям метки (конвейер с #636 ставит S7 сам); прогоны Actions по workflow —
исходы, wall-time, события (прогоны конвейера сведены в одну строку); минуты
S4/S7 конвейера без skipped; при наличии jobs — job-минуты и доля «Мутанты».
Markdown-отчёт со сводкой и таблицей по issue; CLI на gh (только чтение).

process-metrics.yml — понедельник 05:00 UTC и по кнопке; отчёт в step summary
и артефакт на 90 дней; прав на запись нет.

Тесты на фикстурах, в т. ч. воспроизведение формы аудита 22.09 (30 issue:
15 r1/13 r2/2 r3 → 1,57; Validate 226/178/37/11). Мутанты
metrics-count-skipped-pipeline-runs, metrics-rounds-by-s7-events.

Issue: #637
User-Visible: no
This commit is contained in:
Claude
2026-09-23 11:42:37 +03:00
parent 0b55163dc3
commit 46edcb1f37
4 changed files with 491 additions and 0 deletions
+24
View File
@@ -8532,6 +8532,30 @@ const MUTANT_DEFINITIONS = [
replace: " if (false && run.pendingValidate === 'active') {",
}],
},
// #637: метрики процесса — цифры, по которым судят об ускорении; ошибка счёта
// хуже отсутствия счёта.
{
id: 'metrics-count-skipped-pipeline-runs',
guard: 'node --test --test-name-pattern="#637 pipelineMetrics" test/process-metrics.test.mjs',
because: 'process.yml runs on every label event and most runs are skipped by the guard; counting '
+ 'them as review rounds would inflate S7 minutes and per-run averages (#637)',
patches: [{
file: 'scripts/process-metrics.mjs',
find: " if (!match || run.conclusion === 'skipped') continue;",
replace: " if (!match) continue; // mutant: skipped runs counted",
}],
},
{
id: 'metrics-rounds-by-s7-events',
guard: 'node --test --test-name-pattern="#637 buildReport" test/process-metrics.test.mjs',
because: 'review rounds come from review documents, not from S7 label events — the pipeline '
+ 're-applies S7 itself after a pending Validate (#636), so events would overcount (#637)',
patches: [{
file: 'scripts/process-metrics.mjs',
find: " const codeRounds = completed.map((issue) => rounds.get(`CODE:${issue.number}`)).filter(Boolean);",
replace: " const codeRounds = completed.map((issue) => issue.s7Requests).filter(Boolean); // mutant: rounds = S7 events",
}],
},
{
id: 'process-reconcile-restarts-healthy-run',
guard: 'node --test test/process-reconcile.test.mjs',