Бэктест модели риска закрытия — июль 2026
Замер выполнен в сессии #152 по задаче closure-risk-score-is-anti-predictive. Данные — собственные закрытия проекта, а не синтетика: 374 закрытые задачи с записанным риск-скором, из них 56 сбежавших (на задачу указывает defect_of более поздней задачи — то же определение, которым пользуется backend_defect_escape) и 318 чистых.
Метод: пермутационный тест на разность средних (20000 итераций, seed зафиксирован — повтор даёт тот же p) и AUC как мера различающей силы. AUC = 0.5 — монета; выше — оценка направлена верно; ниже — направлена обратно.
Что мерили и что получили
Композит: дело не в знаке, дело в отсутствии сигнала
| величина | значение |
|---|---|
| средний риск сбежавших | 0.2931 |
| средний риск чистых | 0.3174 |
| разность | −0.0243 |
| пермутационный p | 0.3848 |
| AUC | 0.4820 |
Инверсия, с которой началась задача, статистически незначима (p = 0.38). Но вывод из этого не «всё в порядке». AUC 0.4820 означает, что композит не разделяет закрытия, из которых дефект сбежал, и те, из которых не сбежал. Два средних показывали разрыв, не говоря, разделяет ли он хоть что-нибудь, — и именно поэтому число с нулевой различающей силой читалось как «слегка инвертированное».
Пофакторно: веса были назначены априорно и никогда не проверялись
| фактор | вес | AUC | p | вердикт |
|---|---|---|---|---|
gate_coverage | 0.25 | 0.409 | 0.0098 | значимо ИНВЕРТИРОВАН |
test_delta | 0.20 | 0.495 | 0.7666 | сигнала нет |
ac_evidence | 0.20 | 0.499 | 0.5287 | сигнала нет |
security_hits | 0.20 | 0.467 | 0.2515 | сигнала нет |
code_churn | 0.15 | 0.617 | 0.0098 | единственный верно направленный |
60% веса лежит на трёх факторах без измеримого сигнала. Самый тяжёлый фактор смотрит в обратную сторону, единственный работающий весит меньше всех. Композит, усредняющий это до монеты, — предсказуемое следствие, а не случайность.
Инверсия gate_coverage — не сложность в маскировке
Очевидное объяснение: сложные задачи и гейтов гоняют больше, и сбегают чаще, поэтому инверсия могла быть сложностью, протекающей через фактор. Проверено стратификацией — гипотеза опровергнута, эффект внутри страты не исчезает, а усиливается:
| страта | n | сбежало | AUC gate_coverage | p |
|---|---|---|---|---|
| simple | 117 | 8 | 0.502 | 1.0000 |
| medium | 193 | 35 | 0.444 | 0.2020 |
| complex | 40 | 11 | 0.293 | 0.0170 |
У всех 11 сбежавших complex-задач gate_coverage = 0.0000, то есть гейты отработали полностью, против 0.2069 у чистых.
Механизм не установлен и здесь не утверждается. n = 11. Правдоподобное объяснение — полное покрытие даёт уверенность, а уверенность заменяет внимание — не измерялось, и записывать его как вывод было бы ровно той ошибкой, которую эта задача исправляет.
Риск слеп к сложности, а сложность — сильнейший доступный предиктор
| сложность | n | средний риск | доля побегов |
|---|---|---|---|
| simple | 117 | 0.3330 | 6.8% |
| medium | 193 | 0.2905 | 18.1% |
| complex | 40 | 0.3147 | 27.5% |
Доля побегов меняется вчетверо, средний риск при этом почти плоский. Гипотеза из карточки — «оценка меряет затраченное усилие, а не остаточную опасность» — в этой форме не подтвердилась: риск не растёт со сложностью, он к ней слеп.
Главное число замера:
Одна сложность как предиктор даёт AUC 0.6327 (p = 0.0016) — против 0.4820 у всей пятифакторной формулы. Поле, которое модель игнорирует, работает лучше модели.
complexity_understated двигает оценку вниз
31 закрытие помечено детектором занижения сложности.
| помеченные | остальные | |
|---|---|---|
| доля побегов | 25.8% | 14.0% |
| средний риск | 0.2464 | 0.3198 |
Самый частый предвестник побега не просто невидим формуле — он двигает её оценку вниз. Это конкретный механизм наблюдаемой анти-корреляции, а не догадка.
Что с этим сделано
Композит понижен до описательного. Он по-прежнему считается и хранится (факторы диагностически полезны, а история закрытий не пересчитывается задним числом), но перестал подаваться как доказательство качества: строка при закрытии теперь называет его тем, что он есть.
Триггер обязательного L3-ревью на high оставлен. Он шумный, но асимметрия цен в его пользу: шумное требование посмотреть внимательнее стоит времени, шумное заверение в безопасности стоит дефектов.
Перевзвешивание не делалось, и это осознанный отказ. При 56 сбежавших и двух значимых факторах подгонка весов на тех же данных дала бы красивый коэффициент и ту же слепоту; удержанной выборки, на которой это можно проверить честно (AC6), такой объём не даёт. Вводить сложность в формулу как фактор — по той же причине преждевременно: сначала нужна выборка, на которой перевзвешивание можно фальсифицировать.
tausik metrics теперь печатает рядом со средними AUC композита и AUC одной сложности, чтобы статус числа был виден там, где его читают, а не только здесь.