docs: §2.7 требует таблицу «чем краснеет» у защитных AC

§2.7 уже требовал нужного: ревьюер обязан убедиться, что тест умеет
падать. Требование было, артефакта у него не было — в документе ревью
ничто не заставляло назвать, чем именно проверка краснеет, и «убедился»
писалось по впечатлению от чтения теста.

Цена известна по факту. Аудит v1.71.0-beta.1 нашёл пять защитных
контрактов #51 и #423, где снятие защиты не покраснило ни один тест
(#430). Все пять прошли код-ревью как доказанные; два теста попали в
закрытие coverage-ratchet под именами, обещавшими то, чего они не
проверяли.

Теперь у защитного AC три столбца: чем доказан, и отдельно — чем
краснеет, с результатом прогона. Пустой третий столбец — Medium.

Считаются защитные AC без свидетеля, а не мутанты на подсистему: у #421
мутанты были, и дыра всё равно проехала. Число мутантов остаётся
признаком — у #423 их ноль, и именно там нашёлся тест, спрашивавший
регулярку, находит ли она подстроку, которую сам же и вырезал.

Границы записаны явно, чтобы правило не стало ритуалом: AC без заявки на
защиту его не касаются, а «проверено чтением» остаётся законным — только
это видно во втором столбце.

Гейты: npm test 1791 tests, 1790 pass, 0 fail.

Issue: #435
User-Visible: no
This commit is contained in:
Claude
2026-09-03 10:58:12 +03:00
parent 1a8a51f2d9
commit bdf53dc482
+29
View File
@@ -193,6 +193,35 @@ S1-new → S2-analysis → S3-spec → S4-spec-review ⟲ → S5-ready →
кода отвечает на вопрос «оно вообще работает»: каждый AC либо доказан
автотестом — и ревьюер убедился, что **тест умеет падать**, — либо разобран по
коду с явной записью «проверено чтением, не исполнением».
- **Защитный AC доказывается таблицей «чем краснеет» (#435).** Для каждого AC,
заявляющего защиту — валидация, гард, лимит, отказ, инвариант, — в документе
ревью обязательна строка из трёх столбцов: **AC · чем доказан** (точная
команда или имя теста) **· чем краснеет** — мутация, снятая защита или
отрицательная проба, с результатом прогона. Пустой третий столбец — находка
Medium, а не примечание.
«Тест умеет падать» без названной мутации и её вывода доказательством не
является. Аудит v1.71.0-beta.1 нашёл пять контрактов #51 и #423, где тест
оставался зелёным на снятой защите; все пять прошли код-ревью как доказанные,
а два теста были записаны в закрытие coverage-ratchet под именами, обещавшими
то, чего они не проверяли (#430).
Мутант в `scripts/mutation-gate.mjs` обязателен, когда защита живёт в
продуктовом коде и проверяется дорогим гейтом (смок, бэкенд, golden): там
ревьюер не воспроизведёт отрицательный прогон второй раз. Для чистых юнитов
достаточно прогона со снятой защитой, приведённого в документе.
Считаются **защитные AC без названного свидетеля**, а не мутанты на
подсистему: у #421 мутанты были, и дыра всё равно проехала. «Сколько мутантов
принесла задача» остаётся признаком — у #423 их ноль, и именно у #423 нашёлся
тест, спрашивавший регулярку, находит ли она подстроку, которую сам же и
вырезал.
Правило не распространяется на AC, не заявляющие защиту (расположение, текст,
формат вывода): там свидетель — обычное сравнение ожидаемого с фактическим, и
третий столбец превратился бы в ритуал. И не отменяет «проверено чтением»:
тогда во втором столбце стоит «чтением», а не имя теста, и читатель ревью
видит разницу.
- **High блокируют.** Medium **в скоупе задачи** чинится в текущем issue:
без High это жёлтый вердикт и возврат автору, фикс проходит повторный цикл.
Medium **вне скоупа** — отдельный issue (#202).