Команда Android-разработки Домклика столкнулась с типичным техническим долгом: около 100 тестовых классов по-прежнему использовали Mockito — библиотеку для Java, которую команда давно заменила на MockK при переходе с Java на Kotlin. Файлы не имели явных владельцев, и задача годами откладывалась. Разработчик Сергей решил проверить, справится ли с этим LLM-агент.
Первая попытка — единый промпт «найди все тесты на Mockito и перепиши их на MockK» — дала нестабильный результат. Причина в явлении, которое называют Context Rot: при росте контекста модель начинает хуже справляться даже с простыми задачами. Дополнительно работает эффект Lost in the Middle — информация в середине длинного контекста обрабатывается хуже, чем в начале и конце. Проект Домклика насчитывает 250 Gradle-модулей, и попытка обработать всё за один проход предсказуемо деградировала.
Решением стала утилита Ralph (существует также вариант Open Ralph с поддержкой большего числа агентов). Ralph реализует workflow loop: берёт задачи из файла ralph_tasks.md и для каждой запускает агента с чистым контекстом. Агент мониторится по stdout — если он завершил работу, но не вывел заданную фразу-маркер (completion promise), Ralph перезапускает его. Когда задача закрыта, цикл переходит к следующей. Такой подход решает две практические проблемы автономной работы: зависший агент не блокирует очередь, а каждый файл обрабатывается изолированно.
Простой промпт «перепиши все тесты» давал плохой результат из-за Context Rot — деградации модели при росте контекста.
Задача переписать один тестовый класс — атомарная: агенту не нужна история предыдущих итераций, только правила миграции. Промпт содержал чёткий workflow из пяти шагов: переписать тест, убедиться в отсутствии импортов Mockito, запустить конкретный тестовый класс и проверить прохождение, сделать коммит, записать полезные наблюдения в knowledge.md. Файл knowledge.md — отдельная находка: автор заметил, что агент повторял одни и те же ошибки в каждой итерации, и добавил инструкцию накапливать опыт между запусками. Это улучшило стабильность.
Промпт также содержал жёсткие ограничения: не менять логику тестов и структуру assertions, не использовать mockk(relaxed = true) и аннотацию @MockK, придерживаться формата коммит-сообщений. При провале теста агенту давалось максимум пять попыток исправить его — после этого файл пропускался с пометкой. За ночь агент переписал более 100 классов. Утром разработчику оставалось открыть pull request.
На code review коллеги нашли места, где агент «схалтурил» — упростил или формально выполнил требование, не сохранив смысл. Перед командой встал выбор: доработать промпт или научить модель воспринимать замечания ревьюеров и исправлять код по ним. Судя по тексту, выбор сделан в пользу второго — интеграции агента в процесс code review.
Опыт Домклика иллюстрирует подход, при котором LLM даёт устойчивый результат: чёткое определение готовности (DoD), техническая возможность проверить результат (запуск тестов), цикл обратной связи (Ralph + completion promise). Рефакторинг с понятными правилами и верифицируемым результатом — именно тот класс задач, где автономный агент работает предсказуемо, в отличие от разработки новых фич с размытыми требованиями.
