Код после ИИ. Как проверять результат?

Генерация перестала быть узким местом - им стала проверка. Агент пишет за вечер то, на что раньше уходила неделя, но прохождения тестов недостаточно, чтобы принять результат, если код и критерии его оценки созданы в одном процессе.

Даже сотня зеленых тестов может проверять лишь то, что код и так делает. Количество тестов и покрытие еще не говорят, правильно ли понята задача.

Верификация отвечает на вопрос: соответствует ли результат спецификации? Валидация - решает ли он исходную задачу и подходит ли для предполагаемого использования? Можно выполнить спецификацию без ошибок, но неверно понять потребность. Агент может ошибиться и в реализации, и в понимании задачи, соответствие придуманным им критериям не доказывает, что результат ожидаемый.

Методы проверки различаются не только строгостью, но и источником ожиданий, их независимостью от реализации и типами ошибок, которые метод способен обнаружить. Затраты ниже - ориентировочная «стоимость» внедрения и применения.

Проверки с риском общей ошибки

• TDD без человека. Тест до кода помогает ловить регрессии. Но если один агент создал и тест, и реализацию по одной трактовке задачи, они могут разделить общую ошибку. Затраты низкие.

• LLM-as-a-Judge. Может проверять соответствие ясным критериям. Общие данные, модели и слепые зоны ослабляют независимость. Иногда это не проверка, а перебор вариантов в поиске самого убедительного для судьи. Затраты низкие.

Человек и внешние источники

• Ручные тесты и ревью. Помогают заметить подгонку, хардкод и ослабленные проверки, но человек тоже устает и может разделять допущения. Ревью может выродиться в бездумный пуш «ок». Затраты высокие.

• SDD и BDD. Спецификация и сценарии отделяют «что» от «как» и помогают заметить расхождения. Для этого требования должны быть осмысленны, актуальны и сверяться с реализацией. Документ сам по себе дрейф не остановит. Затраты средние.

• Контрактные тесты. Проверяют совместимость с ожиданиями, например, соседней команды или внешнего API. Но стороны могут согласовать неверный контракт и обе ему следовать. Затраты средние.

• Property-based testing. Человек задает инвариант, машина генерирует входы и ищет контрпримеры. Слабый инвариант не спасет: «список не пустой» верно и для списка из одних нулей. Затраты средние.

• Формальные методы. Проверяют модель или реализацию на соответствие формально заданным свойствам при явных допущениях. Можно найти контрпример или доказать свойство - но не то, что спецификация выражает нужную задачу. Затраты высокие.

Механические проверки

• Типы, линтеры, анализаторы. Ловят целые классы ошибок по заданным правилам, но не знают намерения: типы сходятся и у программы, которая делает не то. Затраты низкие.

• Mutation testing. Проверяет, замечают ли тесты выбранные изменения программы. Метод не доказывает, что ожидания верны. Затраты высокие.

Прод - проверка реальным поведением

• Canary, shadow-режим, метрики, анализ инцидентов показывают поведение в реальном мире. Но незаметные метрикам ошибки и редкие сценарии могут ускользнуть: алерты глушат, инциденты переклассифицируют. Прод - важный, но рискованный слой. Затраты высокие - это не замена остальным методам.

Вывод

Модель оптимизирует метрику, а не намерение. Важно, кто и на каком основании задал ожидание и какие предположения разделяют код и его проверка.

Полного метода нет. Разумная цепочка сочетает механические проверки, тесты, актуальную спецификацию, независимые критерии и наблюдение за реальным поведением. Цель - не просто добавить тестов, а снизить риск общей ошибки.