Две крупные миграции на Rust — рантайма Copilot у GitHub и JavaScript-рантайма Bun у Anthropic — устроены настолько по-разному, что их удобно читать как два противоположных ответа на один вопрос: как встроить агентов в переписывание большого объёма кода. Ниже — механика обоих процессов, роль инструментов Rust в агентном цикле и условия, при которых такая миграция вообще становится возможной.
Две кодовые базы и два подхода
GitHub переписывал на Rust рантайм продукта Copilot. Работу выполняли собственные агенты компании — приложение GitHub Copilot и Copilot CLI. Изменения шли 128 pull request'ами, которые мержились и поставлялись постепенно. Разработка продукта при этом продолжалась вокруг миграции: части рантайма конвертировались и выпускались по мере готовности.
Anthropic переписывал Bun — JavaScript-рантайм, приобретённый в декабре. Это был порт 535 496 строк Zig в Rust, выполненный сразу целиком: множество параллельно работающих агентов Claude Code переводили и проверяли разные части одновременно, а основатель Bun Jarred Sumner следил за их работой и вмешивался при сбоях.
Разница принципиальна. Bun выбрал all-at-once portперевод всей кодовой базы сразу, до возврата результата в основную ветку. GitHub выбрал более медленный инкрементальный путь: части рантайма конвертировались и поставлялись по мере готовности, пока разработка продукта продолжалась вокруг миграции. Мотивация у обеих компаний схожая: агенты сделали крупные переписывания доступными по стоимости там, где раньше такие проекты были бы слишком дорогими.
Playbook GitHub: агенты в цикле миграции
Инициатором выступила сама компания. Microsoft engineer Stephen Toub сообщает, что GitHub использовала собственные Copilot coding agents для перевода рантайма Copilot на Rust, а инструментами служили GitHub Copilot app и Copilot CLI.
Работа была разбита на 128 pull request'ов, которые мержились и поставлялись инкрементально. Такой подход, по словам Toub, позволял ловить и исправлять регрессии по ходу. Процесс занял примерно 14 с половиной недель, при этом разработка продукта продолжалась параллельно.
Какие именно проверки и guardrailsограничители, стоящие между агентом и мержем GitHub ставит перед слиянием и на каком шаге обязан вмешаться человек, не описано. Известно только, что работа шла через 128 pull request'ов с постепенным мержем и выпуском, что давало возможность находить и исправлять регрессии по ходу. Отдельно упоминается, что нужны CI с merge queueочередью слияний — механизмом, который выстраивает готовые к мержу изменения в очередь и проверяет каждое на актуальном состоянии основной ветки перед слиянием; «улучшенная» очередь отличается тем, что рассчитана на работу агентов, а не только людей, а лимитирующим фактором для dev-агентов является окружение, в котором они работают, а не модели и harnessesобвязки — программные каркасы, которые запускают модель, подают ей контекст и инструменты и управляют циклом её работы.
Playbook Anthropic: агенты как основной исполнитель
У Bun Sumner организовал несколько агентов Claude Code, которые параллельно переводили и проверяли разные части кодовой базы. Задачи распределялись по разным частям Bun, а сам Sumner следил за работой агентов и вмешивался при отклонениях процесса.
Проверка корректности опиралась на существующие тесты: через одиннадцать дней после старта Rust-версия проходила существующие тесты Bun на всех шести поддерживаемых платформах. После этого код был смержен, но дальнейшее ревью и очистка продолжались до релиза.
Инструменты Rust в агентном цикле
clippy
clippy запускается в трёх режимах: базовый — cargo clippy, автоматическое исправление — cargo clippy --fix, превращение предупреждений в ошибки — cargo clippy -- -D warnings. Дополнительный набор придирчивых проверок включается флагом -W clippy::pedantic.
Поведение части линтов настраивается в TOML-файле clippy.toml или .clippy.toml, который содержит простое сопоставление variable = value. Один из таких параметров — msrvминимальная поддерживаемая версия Rust, для которой проверяются линты, задаваемый строкой версии:
msrv = "1.30.0"rustfmt
rustfmt — инструмент форматирования кода Rust. Запускается как rustfmt filename либо через cargo fmt для всех бинарных и библиотечных целей крейта. Для согласованного форматирования между cargo fmt и rustfmt рекомендуется задавать style_editionнабор правил расстановки кода, привязанный к редакции языка в rustfmt.toml, например style_edition = "2024". Причина в том, что rustfmt по умолчанию использует стилевую редакцию 2015, а cargo fmt выводит её из edition в Cargo.toml; рассинхрон этих настроек приводит к тому, что две команды форматируют один и тот же код по-разному. Чтобы разбор тоже был согласованным, следует настраивать edition в rustfmt.toml.
Ограничения rustfmt, влияющие на автоматизацию, включают: программы, где любая часть не парсится; объявления и использования макросов; комментарии и узлы AST с комментарием внутри; код Rust в блоках кода в комментариях; фрагменты программ; код с не-ASCII Unicode; а также баги самого rustfmt. Среди nightly-only опций — coverageпоказывает, какая доля входного файла была обработана, checkstyleвыводит результат в формате checkstyle и jsonвыводит различия в формате JSON, тогда как files и stdout доступны без nightly.
rust-analyzer и rustup
rust-analyzer — языковой сервер, предоставляющий функциональность IDE для написания программ на Rust; совместим с любым редактором, поддерживающим Language Server Protocol. Его возможности включают переход к определению, поиск всех ссылок, рефакторинги и автодополнение кода, а также интегрированное форматирование (с rustfmt) и интегрированную диагностику (с rustc и clippy). Внутренне rust-analyzer устроен как набор библиотек для анализа кода на Rust.
rustup — установщик тулчейна Rust из официальных каналов выпуска, позволяющий легко переключаться между компиляторами stable, beta и nightly и поддерживать их в актуальном состоянии. Он упрощает кросс-компиляцию за счёт бинарных сборок стандартной библиотеки для распространённых платформ и работает на всех платформах, которые поддерживает Rust, включая Windows.
Условия, при которых агентная миграция вообще возможна
agent-legible dev environmentsСреды разработки, устройство которых агент способен воспринимать нужны потому, что ошибки возникают преимущественно там, где агенты их не видят; без видимости интеграций и фронтенда агенты работают вслепую.
global memoryОбщая память, доступная всем агентам в цепочке инструментов нужна, чтобы агенты не повторяли одни и те же ошибки. Исправления, сделанные одним агентом, должны быть известны всем будущим агентам: система памяти должна работать по всему инструментарию, чтобы бот ревью кода знал о поправке, выданной агенту две недели назад.
codebase rot preventionПредотвращение гниения кодовой базы нужно, чтобы не накапливались мёртвый код, несколько способов делать одно и то же и расхождения типа и данных с продуктом. Без этого кодовая база начинает спиралить.
Защитный код агенты генерируют из-за стремления закрыть любую мыслимую неоднозначность без понимания реальных рисков. Повторение ошибок связано с отсутствием общей памяти: если каждому новому агенту приходится заново объяснять одно и то же, команда возвращается в цикл низкоуровневой работы.
Tokenmaxxing и следующий шаг
Авторы описывают tokenmaxxingперекладывание максимума работы на армии агентов и состязательные циклы: в первой половине года инженерные организации делали это, но получили горы сомнительного кода без цунами невероятного софта, а ROI по токенам был в лучшем случае шатким.
Следующим шагом авторы называют не простое увеличение контекста, а self-driving codebaseкодовую базу, которая в значительной степени управляет собой, оставляя инженерам хорошие идеи. Причина в том, что ценность инженерной работы смещается к наличию хороших идей и убийственной архитектуре, а не к низкоуровневой работе, которую должны брать на себя агенты. Предлагаемый путь состоит из трёх шагов: искать баги в кодовых базах и учиться выбирать значимые; исправлять их, отслеживая пробелы, мешающие проверить корректность фикса или реальность бага; использовать трассы исправлений для приоритизации работы по адаптации кодовой базы к агентам. Это позволяет постепенно повышать готовность кодовой базы к агентам и передавать им всё большую часть работы. Ограничивающим фактором для dev-агентов авторы называют среду, в которой они работают, а не модели и харнессы.
Пограничные случаи и риски
Систематическая ошибка агентов, которую называют источники, — большие объёмы избыточно защитного кода: агенты пытаются закрыть любую мыслимую неоднозначность, не зная, какие риски реальны.
Для отлова ошибок до мержа источники предлагают clippy: cargo clippy -- -D warnings превращает предупреждения в ошибки, cargo clippy -- -W clippy::pedantic включает дополнительный набор придирчивых проверок. Кроме того, нужна глобальная память: исправления, выданные одному агенту, должны быть известны всем будущим агентам, включая бота-ревьюера, чтобы ошибки не повторялись. Также упоминается предотвращение гниения кодовой базы — контроль мёртвого кода, дублирующих способов решения и интуитивности типов. В примере с миграцией Bun код сначала прошёл существующие тесты на всех шести платформах, и только затем был смержен, хотя дальнейшая проверка и очистка продолжались до релиза.
Boneheaded mistakes и роль global memory
Сам факт множества глупых ошибок агентов источник считает допустимым. Недопустимо лишь повторение одной и той же ошибки. Проблема в том, что если одну и ту же поправку приходится сообщать каждому агенту, который касается этой области, человек снова оказывается в цикле низкоуровневой работы. Поэтому global memory позиционируется как система, работающая по всему инструментарию: бот ревью кода должен знать о поправке, выданной агенту две недели назад, а после выговора SRE-боту за небезопасную prod-операцию агент должен понять причину, и каждый будущий агент должен знать об этой поправке.
Что видит пользователь во время миграции
Для пользователей продуктов GitHub миграция была постепенной: части рантайма Copilot переводились и выпускались по мере готовности, разработка продукта продолжалась вокруг миграции. Работа была разбита на 128 pull request'ов, что позволяло находить и исправлять регрессии по ходу.
Для пользователей Bun миграция была связана со стабильностью: рост проекта сопровождался постоянными ошибками управления памятью, включая утечки и падения, и компания заявила, что обязана систематически предотвращать их повторение, а не чинить по одному случаю. Через одиннадцать дней после старта версия на Rust проходила существующие тесты Bun на всех шести поддерживаемых платформах, затем код был слит, но до релиза продолжались проверка и очистка.
Компромиссы и мотивация
Подходы у компаний разные: Bun пошёл на all-at-once port с множеством параллельных экземпляров Claude, GitHub выбрал более медленный инкрементальный путь с конвертацией и выпуском частей рантайма по мере готовности в 128 pull request'ах.
Причина выбора массовой переписи у Bun экономическая: обычный рерайт 535 496 строк Zig потребовал бы небольшой команды примерно на год, что сделало бы проект нереалистичным, поскольку означало бы заморозку багфиксов, security-фиксов и разработки фич. GitHub также считает, что рерайт такого размера был недоступен до агентов, оценивая прежнюю стоимость в год-два работы команды.
Компромиссы: у GitHub инкрементальный подход через 128 pull request'ов позволил ловить и исправлять регрессии по ходу, а у Bun после слияния Rust-версии продолжались дополнительное ревью и очистка перед релизом.
Конфликт интересов
GitHub и Anthropic — крупные вендоры тех самых кодирующих агентов, которым они приписывают заслугу в выполнении проектов, поэтому их рассказы по своей природе корыстны. У обеих компаний есть все основания приводить такие доводы: именно они больше всех выигрывают от демонстрации того, на что способны агенты при крупных переписываниях. Такие проекты пока остаются отдельными кейсами, о которых сообщают компании с наибольшей выгодой. При этом по индустрии есть признаки, что явление «агенты делают крупную миграцию на Rust» набирает силу. Отдельно указано, что владелец TNS Insight Partners является инвестором OpenAI и Anthropic.
Что из этого следует на практике
- Выбор между all-at-once и инкрементальным путём — это выбор между скоростью и управляемостью регрессий. Bun прошёл путь до прохождения тестов на всех шести платформах за одиннадцать дней, но после слияния ещё продолжал ревью и очистку до релиза. GitHub шёл медленнее, зато ловил и исправлял регрессии по ходу.
- Экономика решает. Обычный рерайт 535 496 строк Zig потребовал бы небольшой команды примерно на год с заморозкой багфиксов, security-фиксов и фич. Именно недоступность такой цены до агентов — общий аргумент обеих компаний.
- Тесты — единственный названный критерий готовности. У Bun это прохождение существующих тестов на всех шести поддерживаемых платформах; порогов покрытия или clippy не приводится.
- Инструменты Rust дают агенту обратную связь, которую можно автоматизировать. clippy с
-D warningsпревращает предупреждения в ошибки,--fixправит автоматически,-W clippy::pedanticдобавляет придирчивые проверки; rustfmt нормализует диффы, но не парсит макросы, комментарии и фрагменты программ, а часть его опций доступна только на nightly. - Среда важнее модели. Лимитирующий фактор для dev-агентов — окружение, в котором они работают, а не модели и харнессы; ошибки возникают там, где агенты не видят.
- Без общей памяти ошибки повторяются. Допустимы многие глупые ошибки, недопустимо их повторение: если поправку приходится сообщать каждому агенту, затрагивающему область, человек возвращается в цикл низкоуровневой работы.
- Избыточно защитный код — систематическая ошибка агентов, и её приходится отлавливать до мержа вместе с мёртвым кодом, дублирующими способами решения и неинтуитивными типами.
- Кейсы публикуют заинтересованные стороны. Обе компании — вендоры тех самых агентов, поэтому цифры и выводы стоит читать с поправкой на этот интерес.