Чем он отличается от двух соседних циклов
В базе описаны два цикла, и оба про одну попытку решить задачу:
- ReAct — цикл внутри задачи: наблюдение, рассуждение, действие, и так до ответа;
- Reflexion — цикл между попытками: разбор неудачи переносится вперёд, следующая попытка начинается с ним.
Здесь третий класс: цикл над системой, у которого нет «ответа» и нет конца. Он запускается по расписанию, каждый раз берёт небольшой кусок работы и возвращается. Определяющая разница — возмущение: пока цикл работает, коллеги вливают свои изменения, обновляются зависимости, перегенерируется код. Свойство, которое цикл улучшает, одновременно ухудшается снаружи, и конструкция должна это выдерживать.
Пять компонентов
| Компонент | Что это | Типовая ошибка |
|---|---|---|
| уставка | желаемое значение свойства: инвариант («ни один модуль не импортирует через эту границу»), порог («покрытие ≥ 80% в ядре») или направление («каждый прогон — меньше вхождений») | сформулирована так, что её нечем измерить |
| датчик | чем меряется текущее состояние и разрыв до уставки: линтер, структурный поиск, проверка типов, набор тестов, запрос к телеметрии, скрипт — или агент, читающий код | измерение нестабильно, и регулятор не может на нём работать |
| регулятор | как из измерения выбирается следующее изменение: что делать сейчас, что отложить, сколько взять за раз | сразу делается умным; его настраивают по выходу цикла, поэтому начинают с простого |
| исполнитель | что применяет изменение: кодовый агент с умением проекта, открывающий пул-реквест | ему не заданы образцы того, как выглядит правильное изменение |
| возмущение | что меняет систему снаружи цикла: чужие коммиты, обновления зависимостей, генерируемый код, нестабильные тесты | не названо, и тогда цикл считается сломанным при первом откате прогресса |
Между датчиком и регулятором лежит рассогласование — разрыв между уставкой и измерением: находки сверх порога либо новые находки относительно базового замера. Это и есть то, на что реагирует регулятор, а не измерение целиком.
Компоненты сливаются, и разделение не выдумывают. Инструмент, который и находит нарушения, и ранжирует их по важности, делает работу датчика и регулятора сразу. Один промпт, который выбирает цель и меняет её, — регулятор с исполнителем. Раскладывать такой цикл на пять отдельных шагов только ради полноты схемы значит завести три места, где что-то может рассинхронизироваться.
Четвёртый критерий выбора датчика
Датчик обычно выбирают по трём свойствам: устойчивость измерения, стоимость прогона, повторяемость. Есть четвёртое, которое нельзя измерить — только заметить при проектировании: можно ли этот датчик тихо отключить.
Вопрос существенный именно здесь, потому что исполнитель цикла — агент, и у него есть все права, чтобы отключение выполнить. Правило то же, что в цикле починки (AI Native SDLC, Generator Evaluator): тому, кто исправляет систему, нельзя позволять ослаблять измерение, по которому его исправление оценивают. Датчик, выключаемый строкой в конфиге, которую агент имеет право править, измеряет не систему, а собственную включённость.
Цикл и демпфер — два механизма на одно свойство
Цикл уменьшает уже имеющиеся нарушения. Он не мешает появляться новым — и на этом проигрывает возмущению: пока он чинит по одному за прогон, снаружи добавляют по два.
Поэтому рядом ставится демпфер: проверка на пул-реквестах, сравнивающая измерение того же датчика с базовым, и показывающая — а со временем и блокирующая — вновь появившиеся отклонения. Разделение труда получается чистым:
- цикл отвечает за то, чтобы величина убывала;
- демпфер отвечает за то, чтобы она не росла.
Это ратчет, собранный из двух разных механизмов, и ни один из них в одиночку свойство не держит. Обратная сторона того же — обратный ход ратчета в Agent First Repository: там записано, при каких условиях ограничение снимается.
Демпфер нужен не каждому циклу: там, где возмущение не создаёт новых нарушений (разовая миграция, зачистка после переименования), он только добавляет шума на чужих изменениях.
Ограничение потока: цикл не должен обгонять приёмку
Самая частая поломка планового цикла не в качестве изменений, а в их количестве: ежедневный запуск накапливает дублирующие и конфликтующие пул-реквесты, пока никто их не смотрит.
Рабочее умолчание — один открытый пул-реквест на цикл: плановый запуск ничего не делает, если предыдущий ещё не закрыт, а ручной запуск ограничение обходит. Проверка дешёвая: помеченные этим циклом открытые изменения, и выход без работы, если предел достигнут.
Это вторая половина того, что записано про потолок размера изменения (Agent Code Review). Потолок делает единичное изменение пригодным к чтению, но не увеличивает объём внимания; ограничение потока управляет тем, сколько таких изменений одновременно ждёт этого внимания. Оба ограничения выведены из одной и той же ёмкости приёмки, и без второго первое просто откладывает затор.
Отсюда же берётся частота запуска: её выбирают по риску задачи и по нагрузке на ревью, а не по тому, как часто цикл технически может отработать. Учащают после того, как цикл начал давать стабильно принимаемый результат, — тогда же расширяют и порцию.
Память цикла — не журнал прогонов
Плановый цикл без управления дрейфует, а управляют им через файл, который детерминированно загружается в контекст исполнителя на каждом прогоне — после регулятора, чтобы он влиял на выполнение, а не на отбор.
Различение содержания здесь жёсткое:
| Туда идёт | Туда не идёт |
|---|---|
| постоянные исключения из области действия | разовые указания на этот прогон |
| известные ложные срабатывания датчика | журнал того, что делалось в прошлые разы |
| обратная связь ревьюера, меняющая будущий отбор | пересказ уже применённых изменений |
Критерий один: запись обязана менять будущее поведение. Всё, что описывает прошлое, относится к журналу и в этот файл не попадает — иначе он растёт монотонно и вытесняет собой то, ради чего заведён (Memory Write Policy).
Второй канал управления — правка по комментарию к открытому изменению: ревьюер пишет замечание, цикл подхватывает его вместе с диффом и обновляет и текущее изменение, и файл памяти. Без второй половины замечание придётся повторять каждый прогон.
Каждый компонент запускается руками до того, как попадёт в расписание
Датчик прогоняется отдельно, и его вывод читается глазами. Регулятор прогоняется на настоящем выводе датчика. Исполнитель прогоняется на цели, которую выбрал регулятор. Только после этого всё связывается в плановый запуск, и он остаётся тонким оркестратором уже работающих кусков.
Требование выглядит процедурным, но у него техническая причина: сломавшийся плановый цикл отлаживать нечем. Его прогон идёт в чужой среде, по расписанию, без человека рядом, и различить «датчик ничего не нашёл» и «датчик не запустился» по пустому результату невозможно (Unknown Not A Value).
Границы
- Это не способ сделать разовый рефакторинг. Контур окупается там, где свойство надо удерживать против возмущения; для однократной задачи он дороже прямого изменения.
- Уставка обязана быть измеримой. Свойство, для которого не нашлось датчика, контуром не управляется — получается агент, запускаемый по расписанию, и это другой, гораздо более слабый механизм.
- Регулятор — то, что настраивают, а не то, что проектируют один раз. Его качество видно только по выходу цикла, поэтому первая версия делается простой намеренно.
Связано с
- ReAct — цикл внутри одной задачи; здесь цикл над системой
- Reflexion — цикл между попытками одной задачи и его потолок
- Agent Code Review — потолок размера изменения, вторая половина того же ограничения по ёмкости приёмки
- Agent First Repository — устройство репозитория, в котором такой цикл работает
- AI Native SDLC — цепочка артефактов одного изменения; контур гоняет её по расписанию
- Generator Evaluator — почему исправляющему нельзя ослаблять измерение
- Memory Write Policy — критерий «меняет будущее поведение» как условие записи
- Unknown Not A Value — пустой результат датчика не отличается от незапустившегося датчика
- Online Quality Signal — соседний контур обратной связи, замкнутый внутри одного запроса, а не по расписанию
- Harness Optimization — когда наблюдение вообще достойно превращения в правку