fix: count spec and code review documents apart (#395)
Проверка (CI) / Классификация изменённых файлов (push) Successful in 20s
Проверка (CI) / Предполётные проверки: документация, провенанс, процесс (push) Failing after 52s
Проверка (CI) / Переиспользование: это дерево уже проверено (push) Successful in 55s
Проверка (CI) / HACS: валидация репозитория (push) Failing after 20s
Проверка (CI) / Hassfest: манифест интеграции (push) Failing after 19s
Проверка (CI) / Фронтенд: типы, юниты, мутанты, синхрон бандла (push) Failing after 9m52s
Проверка (CI) / Смоки в браузере (шард 1 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 2 из 3) (push) Skipped
Проверка (CI) / Смоки в браузере (шард 3 из 3) (push) Skipped
Проверка (CI) / Смоки: все шарды зелёные (push) Skipped
Проверка (CI) / Golden-кадры против принятых эталонов (push) Skipped
Проверка (CI) / Перф-смок: бюджет времени кадра (push) Skipped
Проверка (CI) / Бэкенд: pytest в Home Assistant (push) Failing after 1h5m50s

The p.7 limit bucketed every review document of an issue together, so a
task that honestly passed both stages was refused for having passed
them: #42 has 4 SPEC-REVIEW plus 3 CODE-REVIEW documents — 4 and 3
rounds per stage, both inside the budget — and its already-published
GREEN r5 verdict could not publish its own artefact for three runs in a
row, blocking the merge each time.

The counter is now keyed by stage and issue, and the refusal names the
stage. The threshold itself is unchanged: seven documents of one kind
still fail, and the comment above the constant already said what the
number means — the round budget of ONE stage.

User-Visible: no
Issue: #395
This commit is contained in:
Codex
2026-08-30 21:34:19 +03:00
parent e2a681b543
commit 066cf44c2f
2 changed files with 42 additions and 7 deletions
+19 -7
View File
@@ -351,20 +351,32 @@ export function checkReviewDocLimit(files) {
if (!files.length) {
return [{ level: 'warn', rule: 7, sha: '-', msg: 'документов ревью не найдено — проверка 7 пропущена' }];
}
const byIssue = new Map();
// Счётчик ведётся ОТДЕЛЬНО по виду ревью (#395). Порог описывает бюджет
// заходов одного этапа: «четыре цикла плюс два ребейза» — а ревью ТЗ и
// ревью кода это два разных этапа со своими бюджетами (§4). Общая корзина
// наказывала задачу за то, что она честно прошла оба: у #42 набралось
// 4 spec + 3 code = 7 документов при 4 и 3 заходах по видам, и зелёный
// вердикт r5 три прогона подряд не мог опубликовать свой артефакт.
const byKindAndIssue = new Map();
for (const f of files) {
const m = f.match(/-(\d+)-r(\d+)\.md$/) || f.match(/(\d+).*-r(\d+)\.md$/);
const m = f.match(/(CODE|SPEC)-REVIEW-(\d+)-r(\d+)\.md$/)
|| f.match(/-(\d+)-r(\d+)\.md$/)
|| f.match(/(\d+).*-r(\d+)\.md$/);
if (!m) continue;
const arr = byIssue.get(m[1]) ?? [];
arr.push(Number(m[2]));
byIssue.set(m[1], arr);
const [kind, nn, round] = m.length === 4 ? [m[1], m[2], m[3]] : ['?', m[1], m[2]];
const key = `${kind}\u0000${nn}`;
const arr = byKindAndIssue.get(key) ?? [];
arr.push(Number(round));
byKindAndIssue.set(key, arr);
}
const out = [];
for (const [nn, rounds] of byIssue) {
for (const [key, rounds] of byKindAndIssue) {
if (Math.max(...rounds) > REVIEW_DOC_LIMIT || rounds.length > REVIEW_DOC_LIMIT) {
const [kind, nn] = key.split('\u0000');
const label = kind === '?' ? 'ревью' : `${kind}-REVIEW`;
out.push({
level: 'fail', rule: 7, sha: '-',
msg: `issue #${nn}: документов ревью ${rounds.length}, максимум r${Math.max(...rounds)} — больше ${REVIEW_DOC_LIMIT} заходов на один issue`,
msg: `issue #${nn}: документов ${label} ${rounds.length}, максимум r${Math.max(...rounds)} — больше ${REVIEW_DOC_LIMIT} заходов одного вида на один issue`,
});
}
}