TL;DR
CodeMeepo — схема работы для агентов, где перенос проекта на другой язык делится на ордеренные этапы (milestones). Каждую часть работы делает отдельная роль, а передают её друг другу через файлы, а не через переписку. Принимает работу фиксированный набор тестов, который агенты не пишут и не правят. Когда этап закончен, решает не сам агент, а жёсткие правила.
Главная находка: если агент пишет и код, и тесты для него, оба наследуют одну и ту же ошибку понимания. Всё компилируется, тесты зелёные, а половина функций — заглушки или пропущена. Авторы называют это «тихо недоделанным портом». Агент уверенно рапортует «готово», потому что проверяет себя собственной линейкой.
Метод лечит это тремя ходами. Приёмку делает внешний неизменяемый набор тестов. Отдельный проверяющий агент без права править код сверяет источник и результат по компонентам. Каждая найденная дыра возвращается в план как новая обязательная задача. После переноса идёт фаза оптимизации по бенчмаркам, а в конце — полный прогон тестов.
Схема метода
ФАЗА 1 — ПЕРЕНОС
ШАГ 1: Analyzer — изучает исходник, пишет дизайн цели → analysis.md (кода не пишет)
ШАГ 2: Scoper — режет поведение на упорядоченные этапы → milestones.json
ШАГ 3: Planner — план + скелет-заглушки без логики → plan.json
ШАГ 4: Translator — делает ОДИН этап, правит ошибки → код + свои юнит-тесты
ШАГ 5: Validator — гоняет внешние тесты (этот этап + все прошлые) → report.json
провал → назад к шагу 4 (лимит попыток)
лимит исчерпан → этап пропущен, тесты отложены (skips.json)
ШАГ 6: Parity — сравнивает источник и цель по компонентам → parity.json
есть дыры → Scoper добавляет новые этапы → назад к шагу 4
дыр нет → фаза закончена
ФАЗА 2 — ОПТИМИЗАЦИЯ (по раундам)
ШАГ 7: Benchmarker — замеряет, ничего не правит → bench.json
ШАГ 8: Optimizer — одна небольшая правка с сохранением поведения → optimize.json
ШАГ 9: Финальный этап: ВЕСЬ набор тестов; ломает поведение → чинить или откатить оптимизацию
Какой агент идёт дальше и когда конец — решает детерминированный контроллер (код по правилам), не агент.
Пример применения
Важно: в статье контроллер — это программа. В чате или в Claude Code его роль берёте на себя вы: вы или главная инструкция решаете, что идти дальше можно только по правилам.
Задача: Команда сервиса доставки продуктов (в духе «Самоката» или «Яндекс Лавки») переписывает модуль расчёта стоимости доставки. Он написан на PHP, живёт 8 лет, документации нет. Переносят на Python. Боль в том, что ИИ уверенно пишет код и свои тесты, а потом выясняется, что забыты надбавка за дождь и пересчёт тарифа для Новосибирска. Есть готовый набор из 120 приёмочных тестов, написанный отделом QA.
Промпт (файл CLAUDE.md в корне проекта для Claude Code или Cursor):
Проект: перенос модуля расчёта доставки из PHP (/legacy) в Python (/target).
Приёмочные тесты QA лежат в /acceptance. Их ЗАПРЕЩЕНО создавать, править,
удалять, ослаблять или пропускать. Если тест кажется неправильным — сообщи мне, не трогай.
Работаем этапами, по одному:
Этап 1 — скелет: проект собирается и стартует.
Этап 2 — базовый тариф по расстоянию.
Этап 3 — надбавки (погода, время суток, вес).
Этап 4 — региональные тарифы (все города из /legacy/regions.php).
Этап 5 — ошибки и граничные случаи.
Правила:
1. Бери только текущий этап. Заглушки на будущие этапы не трогай.
2. Этап считается готовым, только если проходят приёмочные тесты этого этапа
И всех предыдущих этапов.
3. Пока тесты красные, не пиши «готово». Чини причину, а не тест.
4. Не больше 5 попыток на этап. После этого запиши в skips.md, что не прошло, и иди дальше.
5. Слова «миграция завершена» разрешены, только когда
(а) все этапы пройдены или записаны в skips.md и
(б) проверка полноты (роль Parity) выдала «полное покрытие».
Роль Parity (запускай отдельным субагентом или чатом, права на правку кода — нет):
сравни по компонентам /legacy и /target: модули, классы, функции, публичные
интерфейсы. Для каждого компонента-заглушки, пропущенного или реализованного
частично укажи путь в источнике и предложи этап. Выдай parity.md с вердиктом
«полное покрытие» или «есть пробелы». Каждый пробел становится новым этапом.
Результат: Агент идёт по этапам и после каждого отчитывается о прогоне приёмочных тестов. Падающие тесты не маскируются, а попадают в skips.md. После последнего этапа отдельный проверяющий выдаёт parity.md со списком недоделок: например, пропущенные региональные тарифы или функции-пустышки. Каждая недоделка превращается в новый этап. «Готово» агент говорит, только когда проверка полноты не нашла пробелов.
Почему это работает
Слабость. Если один и тот же агент пишет код и тесты, его слепые пятна совпадают. Тесты фиксируют то, что код делает, а не то, что он должен делать. Зелёная галочка тогда ничего не доказывает. Плюс агент любит объявить «готово» своим словом. Ещё одна проблема: в большом проекте всё не влезает в контекст, а точность падает, когда нужное закопано в длинном тексте.
Сильная сторона. Модель хорошо делает узкую задачу с чёткой обратной связью: реализуй этот этап, чини вот этот упавший тест. Она также неплохо сравнивает два набора (список функций источника и цели) и находит расхождения, если ей не нужно ничего писать.
Как метод это использует. Он разводит роли: кто пишет, тот не принимает. Принимающий (тесты, Parity) не имеет права править. Приёмочные тесты внешние, их нельзя ослабить ради зелёного результата. Реализующему агенту отдают только отчёт с диагнозом, а не исходники тестов, чтобы он не подгонял код под них (в статье это защита от закона Гудхарта, но авторы честно пишут, что полностью она не работает: тексты ошибок могут «протекать»). Ограничение этапами решает проблему контекста. Накопительные ворота (этот этап плюс все прошлые) не дают новой работе ломать старую.
Рычаги управления: - Размер этапа: мельче — надёжнее, но больше циклов. - Лимит попыток на этап: меньше — быстрее едем дальше, но больше отложенных тестов. - Права ролей: чем меньше инструментов у проверяющего, тем честнее проверка (в статье Parity и Benchmarker вообще без инструмента правки файлов). - Что видит реализующий: только отчёт или ещё и тесты. Отчёт снижает подгонку. - Условие конца: внешний вердикт, а не слова агента. Можно добавить свой критерий (например, «ни одного пропущенного теста»). - Раунды оптимизации: фиксированный бюджет вместо «пока не станет быстрее».
Шаблон промпта
Источник: {путь_к_исходнику} ({язык_источника}). Цель: {путь_к_цели} ({язык_цели}).
Приёмочные тесты: {путь_к_тестам} — ЗАПРЕЩЕНО создавать, править, удалять, ослаблять.
Не входит в миграцию (исключения, не пробелы): {исключения}.
Команда сборки: {команда_сборки}. Команда тестов: {команда_тестов}.
Этап 1 — скелет: собирается и стартует.
Этап 2 — {срез_функциональности_1}
Этап 3 — {срез_функциональности_2}
...
Последний этап — полный контракт.
Каждый следующий этап зависит только от предыдущих.
Изучи источник, его зависимости и его юнит-тесты. Запиши analysis.md: соответствие
модулей источника и цели, аналоги сторонних библиотек, перечень поведений источника.
Код цели не пиши. Больше никаких файлов не создавай.
Реализуй ТОЛЬКО текущий этап: замени заглушки реальной логикой, перенеси юнит-тесты
источника, добавь тесты на новый код. Получив report.json, для каждой ошибки определи:
это дефект или функциональность ещё не перенесена, и чини причину.
Тесты не ослабляй. Не пиши «готово» сам.
Код не меняй. Запусти юнит-тесты и приёмочные тесты по накопительным воротам
(тесты этого этапа + всех предыдущих). Запиши report.json: количество прошедших и упавших
по каждому уровню, для каждой ошибки — вероятная причина и подсказка к починке.
Исходный текст приёмочных тестов не раскрывай, давай только диагноз.
Этап пройден, только если оба уровня зелёные; ошибка сборки = провал.
Права на правку кода нет. Сравни источник и цель по компонентам: модули, типы,
функции, публичный интерфейс. Исключения из игнорируй.
Запиши parity.json: вердикт («полное покрытие» / «есть пробелы») и для каждого
отсутствующего, заглушечного или частичного компонента — путь в источнике
и предлагаемый этап.
1. Следующую роль и конец работы определяют ТОЛЬКО эти правила, а не мнение агента.
2. Этап → Translator → Validator. Провал → Translator, не больше {лимит_попыток} раз.
3. Лимит исчерпан → запиши этап как пропущенный, упавшие тесты внеси в skips.md, иди дальше.
4. После последнего этапа → Parity. Если отложенные тесты ещё не перепроверялись —
добавь один этап для их повторной попытки (одна попытка на тест).
5. Есть пробелы → добавь этапы под каждый пробел, перепланируй, после них снова Parity.
Не больше {лимит_раундов_parity} раундов.
6. Фаза завершена успешно, только если Parity вернул «полное покрытие».
7. В итоговом отчёте перечисли открытые и отложенные обязательства.
Роли общаются только через файлы: analysis.md, milestones.json, plan.json,
report.json, parity.json, skips.md. Перед работой роль читает нужные файлы,
после работы записывает свой.
Подставьте: пути, языки, команды сборки и тестов, список этапов, исключения, лимиты попыток и раундов.
🚀 Быстрый старт — вставь в чат:
Вот шаблон CodeMeepo (многоролевой перенос проекта с независимой приёмкой).
Адаптируй под мою задачу: [опиши, что и на что переписываешь или что нужно
переделать крупным куском]. Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит про источник и цель, набор приёмочных тестов (кто его написал и где лежит), как резать работу на этапы, что исключено из объёма и лимиты попыток. Всё это нужно, потому что метод держится на трёх вещах: внешней приёмке, чёткой границе этапов и честных условиях остановки. Из шаблона она возьмёт структуру ролей и перенесёт на вашу задачу. Роли можно запускать отдельными чатами или субагентами в Claude Code, а передавать между ними файлы.
Ограничения
⚠️ Нужны внешние тесты: Вся схема опирается на готовый независимый набор приёмочных тестов. Нет такого набора — приёмка разваливается, а тесты, которые пишет сам агент, авторы прямо считают слабым доказательством.
⚠️ Нужен контроллер: В статье порядок шагов и условие остановки держит программа (машина состояний). В чате вы заменяете её вручную или правилами в инструкции, и тогда агент снова может объявить «готово» сам.
⚠️ Утечка тестов: Скрытие исходников тестов снижает подгонку, но не убирает её: в тексте ошибок и диагнозе могут просочиться ожидаемые значения.
⚠️ Parity — тоже модель: Проверяющий агент может ошибиться. Детерминированная обработка неверного отчёта не делает его верным.
⚠️ Оптимизация не страхуется на каждом шаге: Правки копятся от раунда к раунду, полный набор тестов гоняется только в конце, а финальный замер после ремонта не повторяется автоматически. Скорость нужно перепроверять самим.
⚠️ Узкая область проверки: Проверяли на переносе кода: 9 проектов, три пары языков, одна модель. Оптимизацию показали на одном рабочем демоне. Для других задач это принципы, а не доказанный результат.
⚠️ Разбор по частям не показан: По доступному тексту нет проверки, какой именно элемент (этапы, Parity, внешние тесты) даёт какой вклад. Сравнивали всю систему целиком с чужой.
Как исследовали
Авторы (Microsoft, UC Irvine) взяли девять проектов в трёх парах языков: Java→Python, C→Rust и промышленный демон. Для каждого был готовый набор приёмочных тестов. CodeMeepo сравнивали с агентом ReCodeAgent, который считается передовым, и с четырьмя более простыми вариантами на той же модели. Мерили долю пройденных тестов.
CodeMeepo выиграл на всех девяти проектах. Java→Python: 1166 из 1180 тестов против 1029. C→Rust: все 63 против 47. Демон: все 105 против 53. В среднем получилось на 18% больше пройденных тестов.
Потом на демоне запустили фазу оптимизации: пять раундов. Пять из десяти бенчмарков улучшились больше чем на 5%. Чтения оборудования снизились на 21,6%, простой процессора — на 12,2%. В среднем у улучшившейся половины прирост около 25%.
Для практика важный вывод такой: выигрыш дала не «умная модель», а устройство процесса. Роли без права править, внешняя приёмка и правило «дыры возвращаются в план» убирают самообман агента. Сама статья при этом честно называет слабые места: утечку тестов и зависимость от отчётов агентов.
Адаптации и экстраполяции
🔧 Техника: Parity как отдельный чат-ревьюер → проверка полноты любой работы
Parity-принцип работает не только для кода. Откройте новый чат без доступа к основной работе:
Ты проверяющий, править ничего нельзя. Вот ТЗ клиента и вот готовый документ. Пройди по пунктам ТЗ и для каждого выдай: есть / частично / заглушка / нет, с цитатой из документа. В конце — список недоработок как новых задач.Ответ «всё есть» от автора документа ничего не стоит. Ответ от чата, который документ не писал, стоит больше.
🔧 Техника: «Не ослабляй тест» → правило в инструкции агента
Добавьте в
CLAUDE.mdлюбого проекта: «Тесты, которые я дал, не менять. Если красный — чини код. Если считаешь тест ошибочным — остановись и спроси». Это прямо следует из логики статьи: тесты можно ослабить так же легко, как улучшить код.
Экстраполяция, не из статьи:
Мы правим большой проект в Cursor. Работай этапами по списку ниже. Перед началом
каждого этапа назови, какие проверки докажут, что он готов. «Готово» писать нельзя,
пока я не подтвердил, что проверки прошли. Если упёрся в лимит попыток —
запиши проблему в отдельный файл и иди дальше.
Ресурсы
- CodeMeepo: A Multi-Agent Workflow for Repository-Level Code Migration and Optimization
- Авторы: Farzad Habibi (UC Irvine), Changrong Wu, Jinzhou Jiang (Microsoft), Guohan Lu (OpenAI); работа выполнена в Microsoft
- Базовая система для сравнения: ReCodeAgent
- Контекст: репозиторные миграции кода (Java→Python, C→Rust), приёмочные тесты как независимый оракул, закон Гудхарта
