ci: разделить стадии ревью по бюджетам (#551)

Issue: #551
User-Visible: no
This commit is contained in:
Sergey Matyunin
2026-09-13 13:05:25 +03:00
parent 6102aabbdc
commit 31ef70cee6
6 changed files with 536 additions and 122 deletions
+33
View File
@@ -7847,6 +7847,39 @@ const MUTANT_DEFINITIONS = [
replace: ' settled=true; break',
}],
},
{
id: 'review-model-checks-out-moving-dev',
guard: 'node --test --test-name-pattern="#551" test/review-doc-guard.test.mjs',
because: '#551: модель должна читать exact material, подготовленный до её запуска; checkout '
+ 'подвижного dev разрывает контракт между зелёным gate и вердиктом',
patches: [{
file: '.github/workflows/process.yml',
find: ' ref: ${{ needs.prepare.outputs.material_sha }}',
replace: ' ref: dev # mutant: moving material',
}],
},
{
id: 'review-integration-skips-evidence-checksum',
guard: 'node --test --test-name-pattern="#551" test/review-doc-guard.test.mjs',
because: '#551: artifact между моделью и привилегированной интеграцией — вход доверенной '
+ 'стадии; без checksum неполный или подменённый документ можно опубликовать и слить',
patches: [{
file: '.github/workflows/process.yml',
find: ' (cd "$dir" && sha256sum -c manifest.sha256)\n test -s "$dir/review-document.md"',
replace: ' # mutant: result contents are trusted\n test -s "$dir/review-document.md"',
}],
},
{
id: 'review-integration-trusts-failed-model',
guard: 'node --test --test-name-pattern="#551" test/review-doc-guard.test.mjs',
because: '#551: timeout/cancel/failure модели не является вердиктом; интеграция обязана '
+ 'остановиться, сохранить метку и назвать упавшую стадию',
patches: [{
file: '.github/workflows/process.yml',
find: ' if [ "$REUSE" != "true" ] && [ "$MODEL_RESULT" != "success" ]; then',
replace: ' if false; then # mutant: every model result is accepted',
}],
},
{
id: 'announce-listens-to-the-release-event-again',
guard: 'node --test test/release-workflow.test.mjs',
+3 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env node
// Детерминированное ожидание вердикта / CI (#496).
//
// Runbook велит автору ждать вердикт опросом: раз в 90 секунд, не более 30 раз,
// Runbook велит автору ждать вердикт опросом: раз в 90 секунд, не более 110 раз,
// смотреть на метку. В исполнении LLM каждый тик — это ход модели с чтением JSON
// и рассуждением «ничего не изменилось» — десятки пустых ходов на одно ревью.
// Этот скрипт делает опрос сам и ГОВОРИТ только при смене состояния: одинаковое
@@ -16,7 +16,7 @@
// Скрипт НИЧЕГО не пишет: ни меток, ни комментариев, ни запусков. Новое ревью
// или релиз начинаются только по текущей авторизации человека.
//
// node scripts/wait-verdict.mjs --issue 437 [--sha <tip>] [--interval 90] [--max 30]
// node scripts/wait-verdict.mjs --issue 437 [--sha <tip>] [--interval 90] [--max 110]
//
// Коды выхода: 0 — статус сменился (вердикт есть, читать метку и комментарий);
// 3 — доставлено событие, требующее действия (отказ конвейера, конфликт,
@@ -171,7 +171,7 @@ if (isMainModule(import.meta.url)) {
const repo = value('repo', 'Matysh/houseplan-card');
const sha = value('sha') || null;
const intervalMs = Number(value('interval', '90')) * 1000;
const maxTicks = Number(value('max', '30'));
const maxTicks = Number(value('max', '110'));
waitForVerdict({ readSnapshot: ghSnapshotReader({ number, repo, sha }), intervalMs, maxTicks })
.then((code) => { process.exitCode = code; })
.catch((error) => { console.error(`wait-verdict: ${error.message}`); process.exitCode = 2; });