
“Готово”
Я поручил AI-агенту написать тесты для 527 функций. Агент закончил работу и отчитался:
“Выполнено.”
Фактически тесты были написаны для 40 функций.
Он не врал. Просто после 40-й решил, что этого достаточно. Встретив сложную функцию, пропустил её, прошёл ещё несколько и заключил: “Остальные похожи, этого хватит.”
LLM хорошо генерирует. Но его оценка завершённости ненадёжна.
Храповик
Храповой ключ имеет зубья, которые цепляются только в одном направлении. Вращаете – движется вперёд. Отпускаете – останавливается, но не откатывается назад.
Ratchet Pattern переносит этот механизм на управление агентом.
Элемент 1: механическая проверка → PASS → далее
Элемент 2: механическая проверка → FAIL → повтор (с обратной связью)
Элемент 2: механическая проверка → PASS → далее
...
Элемент N: PASS → завершено. Стоп.
Три правила:
- Показывать только один элемент за раз.
- Следующий открывается только после прохождения текущего.
- Когда всё пройдено – остановка.
Реализуйте эти правила в CLI, и агенту достаточно знать одну команду: next. Остальное решает машина.
Агент останавливается на 40, храповик доводит до 527
Та же модель. Тот же проект. Те же 527 функций.
Автономный агент: 40 / 527 (7.6%) — агент объявил "готово"
Ratchet CLI: 527 / 527 (100%) — машина объявила "ещё 487 осталось"
Разница не в производительности модели. Разница в том, кто решает, что работа закончена.
В автономном режиме LLM сам определяет момент завершения. LLM оптимистичен. После 40 элементов ему “кажется достаточно”. В храповике завершение определяет машина. Машина не чувствует. Она говорит “ещё” до тех пор, пока оставшихся элементов не станет ноль.
Определение в одном предложении
Поместить вероятностного агента внутрь детерминированного автомата.
| Роль | Кто отвечает |
|---|---|
| Генерация | LLM |
| Оценка | verifier |
| Управление ходом | ratchet |
Многие системы возлагают генерацию, оценку и решение о завершении на LLM. Ratchet разделяет эти функции.
Пять принципов
1. Условие завершения механическое
pass/fail. Не “looks good”. go test проходит – PASS. coverage 100% – PASS. Субъективной оценке нет места.
2. PASS неизменяем
Пройденный элемент не открывается заново. Не откатывается. Число оставшихся элементов монотонно убывает.
remaining_work(t+1) ≤ remaining_work(t)
То, что сделано сегодня, не разбирается завтра. Только вперёд. Это принципиальное отличие от “24-часового агента”. Агент без условия завершения сегодня добавляет абстракцию, завтра удаляет, послезавтра добавляет снова. Храповик не допускает таких колебаний.
3. LLM только генерирует
Генерировать код, писать тесты, предлагать исправления – вот роль LLM. Что исправлять, пройдено ли, что дальше, закончено ли – всё это решает машина. LLM – не planner, а constrained generator.
4. У агента отбирается право решать о завершении
Когда “готово” говорит LLM – остановка на 40. Когда “готово” говорит машина – остановка на 527. Смысл существования храповика умещается в одну строку.
5. Verifier должен быть детерминированным
Не всё может быть verifier.
| Может | Не может |
|---|---|
go test | “looks cleaner” |
| coverage измерение | “seems better” |
| AST validation | “more scalable” |
| schema diff | “clean architecture” |
Требования к Verifier: deterministic, machine-checkable, resumable, localized feedback. Если хотя бы одно не выполняется – зубья храповика не зацепятся.
Обратная связь как gradient signal
Если храповик возвращает только “pass/fail”, LLM исправляет вслепую. Чем конкретнее обратная связь, тем точнее коррекция.
Слабая: "тест не пройден" → LLM исправляет без направления
Средняя: "coverage 65%" → LLM примерно усиливает
Сильная: "line 41, 44, 70 не покрыты" → LLM точно покрывает эти ветки
Цифры, подтверждённые на реальном проекте:
Без обратной связи: 60–70% coverage, затем стагнация
С обратной связью: 100% (для достижимых функций)
Та же модель. Одна строка “line 41 not covered” работает как gradient signal.
Чем выше разрешение обратной связи, тем точнее исправления LLM, тем меньше итераций цикла, тем ниже стоимость.
Агент умирает. Прогресс остаётся.
Агент неизбежно падает. Лимит токенов, сетевая ошибка, разрыв сессии. Если храповик сохраняет состояние прогресса, следующий агент подхватывает работу с того же места.
Агент A: функции 1–200 → падение
Агент B: next → продолжение с 201
Агент C: next → продолжение с 401
Агент одноразовый. Прогресс накапливается.
Замени Verifier – получишь другой инструмент
Храповик не привязан к конкретному верификатору. Поменяйте верификатор – получите другой инструмент.
| Храповик + верификатор | Назначение |
|---|---|
Храповик + go test + coverage | Генерация тестов для функций |
| Храповик + структурный validator | Рефакторинг структуры кода |
| Храповик + hurl pass/fail | Проверка API-эндпоинтов |
| Храповик + перекрёстная проверка спецификаций | Обеспечение целостности SSOT |
| Храповик + Toulmin verdict | Принудительное применение пользовательских правил |
Паттерн один. Верификатор определяет домен.
Вопрос
Сколько элементов выполнил ваш агент, прежде чем сказать “готово”?
Это действительно всё?
Кто решил, что работа закончена – агент или машина?
Связанная статья: Топология обратной связи важнее IQ модели – теоретическая основа Ratchet Pattern. Почему структура обратной связи важнее производительности модели.