AI-управляемая перезапись Bun на Rust: Практическое руководство по миграции миллиона строк кода

Практическое руководство, вдохновленное AI-ассистированной миграцией Bun с Zig на Rust, охватывающее контракты поведения, изолированные кодовые агенты, дифференциальное тестирование, фаззинг, проверку небезопасного кода, метрики прогресса и безопасный выпуск.

发布于 2026年7月12日generalGEO 评分: 09 次阅读
Изображение, демонстрирующее AI-управляемую перезапись Bun на Rust. Темный фон, слева — мультяшный аватар, справа — иконка шестеренки Rust. В центре крупный текст «Bun’s AI-Powered Rust Rewrite», где «AI-Powered» выделен фиолетовым, а «Rust Rewrite» — синим. Внизу два блока кода: слева JavaScript, справа Rust, показывающие примеры обработки запросов функциями. Изображение соответствует описанию AI-ассистированной миграции Bun с Zig на Rust, наглядно иллюстрируя применение AI в перезаписи на Rust.

Переписывание на Rust с помощью ИИ от Bun: Практическое руководство по верификации для миграции миллионов строк кода

Введение

Заголовок сложно игнорировать: по сообщениям, Bun выполнил миграцию основной реализации с Zig на Rust за 11 дней, используя динамический рабочий процесс Claude Code. Опубликованные отчеты описывают тысячи коммитов, до 64 агентов Claude, примерно 780 000 строк Rust, двух независимых рецензентов для каждой единицы реализации и прогресс от кода, который не компилировался, до порта, способного пройти тестовый набор и выйти в продакшн.

Неправильный урок заключается в том, что переписывание языков стало задачей в один клик. Полезный урок состоит в том, что пропускная способность реализации и пропускная способность верификации теперь являются отдельными инженерными проблемами.

Агенты ИИ могут генерировать код быстрее, чем команда людей может его прочитать. Когда это происходит, обычное рецензирование pull-request'ов больше не может служить основным механизмом безопасности. Командам нужна система, которая преобразует массивное вероятностное изменение в небольшие утверждения, подкрепленные проверяемыми машиной доказательствами.

Последующий производственный отчет Bun сделал это необычно конкретным. Команда сообщила о 19 известных регрессиях, все из которых были впоследствии исправлены; 11 раундах проверки безопасности; непрерывном фаззинге с покрытием для парсеров; и примерно 27 000 строках Rust внутри блоков unsafe из общего количества около 780 000 строк. Эти факты не ослабляют историю миграции. Они показывают, как выглядит серьезная работа по миграции после того, как впечатляющая демонстрация завершена.

Это руководство превращает этот опыт в многократно используемое практическое руководство по верификации. Цель не в том, чтобы скопировать масштаб Bun. Она состоит в том, чтобы предоставить метод для любой миграции — языковых портов, замены фреймворков, модернизации API, конвертации баз данных или рефакторинга всего репозитория — где агенты ИИ для написания кода могут написать больше кода, чем команда может ответственно проверить построчно.

Ключевые выводы

  • Переписывание Bun показывает, что агенты ИИ могут сжать время реализации. Оно не показывает, что время верификации можно исключить.
  • Переносимым активом является система миграции: письменные контракты поведения, карты рисков, небольшие пилотные проекты, изолированные исполнители, независимые рецензенты, детерминированные шлюзы и восстанавливаемые коммиты.
  • Компиляторы и устаревшие тестовые наборы выявляют разные классы отказов. Ни один из них не выявляет каждое кросс-языковое семантическое несоответствие, различия в режиме релиза, регрессии производительности или небезопасные границы.
  • Большие diff'ы требуют ориентированного на доказательства рецензирования. Люди должны проверять контракты, горячие точки риска, контрпримеры, пробелы в тестах и решения по развертыванию, а не делать вид, что каждая сгенерированная строка получает одинаковое внимание.
  • Команды могут принять ту же схему, не пытаясь выполнить переписывание миллиона строк: требовать от агентов доказывать поведение по одной части за раз, а затем предоставлять более широкую автономию только после измеренных результатов.

Что Bun Фактически Сделал — и Что Заголовок Опускает

Инженерный отчет начался до крупномасштабной генерации кода.

Сообщается, что Джарред Самнер потратил около трех часов на создание PORTING.md, который отображал повторяющиеся паттерны Zig на Rust. Отдельный рабочий процесс анализировал поля структур, предлагал времени жизни Rust, отправлял эти выборы двум независимым рецензентам и сериализовал результаты в LIFETIMES.tsv. Эти артефакты также были проверены вручную.

Первый

Пробная реализация охватывала три файла, а не весь репозиторий. Для каждого файла:

  1. Один агент реализовал версию на Rust.
  2. Два новых агента проверили поведенческую эквивалентность и соответствие документации по миграции.
  3. Ещё один агент применил одобренные исправления.

Только после этого пилотного этапа работа распространилась на 1 448 файлов Zig.

Первый крупномасштабный запуск провалился. Агенты использовали общее рабочее пространство и команды, такие как git stash, git stash pop и git reset --hard. Их изменения мешали друг другу. Затем рабочий процесс был изменён: запретили небезопасные команды координации и начали использовать четыре рабочих дерева, каждое с 16 агентами.

Эта деталь важнее пиковой скорости генерации строк. Параллельное кодирование — это проблема распределённых систем. Общее состояние, конфликтующие писатели, дорогие глобальные операции, владение и восстановление требуют чётких правил.

Сгенерированный код не заработал сразу. Bun использовал ошибки компилятора как очередь и продвигался по одному крейту за раз. В какой-то момент агентам было назначено около 16 000 ошибок компилятора. Цикл использовал одного исправителя, двух рецензентов и одного агента применения, при этом ограничивая частоту выполнения дорогих команд, таких как cargo check и операции Git.

Это не было волшебным переводом. Это была поэтапная конвергенция, движимая детерминированной обратной связью.

Anthropic в своём анонсе динамического рабочего процесса сообщил, что на момент первоначальной публикации 99,8% существующего набора тестов проходило, при этом явно отмечалось, что порт ещё не был в продакшене. Более поздняя статья Bun описывала последующую работу: проверки безопасности, фаззинг, регрессии в продакшене, семантические исправления и сокращение небезопасного кода.

В совокупности источники описывают два разных этапа:

  • Достаточно полная реализация для слияния
  • Достаточно полные доказательства для безопасной работы

Термины, которые нужно знать: Порт, Оракул, Дифференциальное тестирование и Небезопасная поверхность

Эти определения важны, потому что команда не может верифицировать миграцию, пока не согласует, что должны доказывать доказательства. Они также отделяют заявление об уверенности агента от внешне проверяемого результата.

Порт

Порт — это повторная реализация программного обеспечения на новом языке, среде выполнения, платформе или фреймворке с сохранением определённого набора поведений.

«Сохранить поведение» требует границ. Порт может сохранять публичные API и выходные данные, намеренно изменяя внутреннюю архитектуру, характеристики производительности, сообщения об ошибках или неподдерживаемые крайние случаи.

Поведенческий контракт

Поведенческий контракт — это явный список свойств, которые новая реализация должна сохранить.

Он может включать:

  • Входные и выходные данные
  • Поведение при ошибках
  • Порядок
  • Побочные эффекты
  • Семантику конкурентности
  • Ограничения ресурсов
  • Поддерживаемые платформы
  • Бюджеты производительности
  • Требования к наблюдаемости

Существующий код содержит поведение, но не каждое существующее поведение является намеренным. Контракт отделяет требования от исторических случайностей.

Тестовый оракул

Тестовый оракул определяет, является ли выходные данные правильными.

Утверждение модульного теста — это один оракул. Эталонная реализация, спецификация протокола, эталонный файл, инвариант базы данных или правило, созданное человеком, также могут выступать в качестве оракула.

Руководство Anthropic по долгосрочным...

Научное программирование подчеркивает, что для автономной работы необходимы ссылки, измеримые цели или тестовые наборы, чтобы агенты могли определить, прогрессируют ли они.

Дифференциальное тестирование

Дифференциальное тестирование отправляет одни и те же входные данные старой и новой реализациям, а затем сравнивает наблюдаемые результаты.

Особенно полезно, когда старая реализация заслуживает доверия, но полной формальной спецификации не существует. Совпадение результатов не доказывает, что обе реализации верны, но расхождение создает четкую очередь для расследования.

Метаморфическое тестирование

Метаморфическое тестирование проверяет взаимосвязи между несколькими выполнениями, когда точные ожидаемые результаты сложно записать.

Примеры включают:

  • Сериализация и разбор значения должны его сохранять.
  • Переупорядочивание независимых входных данных не должно изменять результат, представленный в виде набора.
  • Двукратный запуск идемпотентной миграции не должен изменять состояние при втором запуске.
  • Повторное использование того же ключа идемпотентности не должно приводить к дублирующему побочному эффекту.

Небезопасная поверхность

Небезопасная поверхность — это код, в котором ослаблены или обойдены обычные гарантии целевого языка.

В Rust unsafe может быть необходим на границах FFI с C или C++, внутри пользовательских аллокаторов или для низкоуровневой интеграции со средой выполнения. Сырое количество не является приговором. Команде нужны права собственности, инварианты, тесты и явный план для каждой небезопасной границы.

Упущенный дефект

Упущенный дефект — это ошибка, вызванная миграцией, обнаруженная после прохождения шлюза, который должен был ее выявить — после слияния, канареечного развертывания, тестирования кандидата на релиз или развертывания в production.

Упущенные дефекты — это обратная связь о системе верификации, а не только о реализации.

Причинно-следственная цепочка: почему более быстрая генерация требует более строгой верификации

Агентный параллелизм меняет экономику реализации. Если 64 рабочих одновременно переводят файлы, время генерации кода может резко сократиться. Граф зависимостей, семантика целевого языка и общая тестовая среда никуда не деваются. Пропускная способность просто перемещает узкое место дальше по потоку.

Узкое место 1: Интеграция

Отдельно разумные файлы могут не работать при совместной компиляции.

Примерно 16 000 ошибок компилятора и циклические зависимости крейтов в Bun иллюстрируют разрыв между локальным переводом и глобальной согласованностью. Компилятор является отличным детерминированным оракулом для типов, владения, времен жизни, имен и некоторых свойств потока управления. Он не является оракулом для поведения продукта.

Узкое место 2: Семантическая эквивалентность

Bun задокументировал ошибки, где код выглядел почти одинаково на разных языках, но вел себя по-разному.

Примеры включали:

  • Побочные эффекты, помещенные в Rust debug_assert!, исчезающие в релизных сборках, в то время как аналогичное утверждение в Zig все еще вычисляло свои аргументы.
  • Жадное выражение unwrap_or, вызывающее поведение, которое должно было оставаться ленивым.
  • Различия в семантике байтовых срезов и границ между реализациями.
  • Входные данные UTF-16 нечетной длины, приводящие к сбою.

Это именно те сбои, которые поверхностный обзор пропускает, потому что переведенный код выглядит правдоподобно.

Узкое место 3: Корреляция рецензирования

Если одна и та же модель пишет и рецензирует изменение, используя один и тот же контекст и предположения, она может воспроизвести

original mistake.

Anthropic рекомендует в своей документации по лучшим практикам Claude Code использовать свежий контекст рецензента. Рецензент видит diff и стандарт без наследования логики автора. Независимость не гарантирует корректность, но снижает смещение общего контекста.

Узкое место 4: Операционные доказательства

Тесты могут проходить, пока латентность удваивается, использование памяти растёт, ломается одна целевая операционная система или исчезает наблюдаемость.

Чем масштабнее изменение, тем выше вероятность, что команда обнаружит нарушенное требование только после развёртывания. Поэтому план миграции должен включать canary-выпуски, откаты, сравнение телеметрии и процесс, преобразующий каждый утекший дефект в новое правило контракта или тест.

Причинно-следственный вывод прост:

ИИ не устраняет затраты на миграцию. Он переносит затраты с набора текста на спецификацию, разработку harness'ов, анализ доказательств и контроль развёртывания.

Команда, игнорирующая этот сдвиг, может быстро закончить генерацию кода, а затем потратить месяцы на выяснение, работает ли переписанный код на самом деле.

Архитектура верификации для миграций на основе ИИ

Архитектура состоит из четырёх плоскостей.

1. Плоскость контрактов

Плоскость контрактов хранит:

  • Публичное поведение
  • Обещания совместимости
  • Преднамеренные изменения
  • Матрицу поддерживаемых платформ
  • Бюджеты производительности
  • Ограничения безопасности
  • Требования к наблюдаемости

Эту плоскость поддерживают люди, а репозиторий её версионирует.

2. Плоскость выполнения

Плоскость выполнения содержит изолированные агенты реализации.

Каждый агент получает:

  • Одну единицу миграции
  • Соответствующие исходные файлы
  • Утверждённый контракт
  • Семантическую карту
  • Узко ограниченные инструменты
  • Целевые проверки

Агент не может изменять контракт или глобальные тесты. Он редактирует только свою назначенную область и возвращает как коммит, так и доказательства.

3. Плоскость верификации

Плоскость верификации независима от реализации.

Она может:

  • Компилировать кандидата
  • Запускать целевые и глобальные тесты
  • Выполнять дифференциальные проверки старого и нового кода
  • Фаззить анализаторы и границы протоколов
  • Сканировать код, чувствительный к безопасности
  • Бенчмаркать репрезентативные рабочие нагрузки
  • Запрашивать у новых рецензентов поиск контрпримеров

Агенты верификации могут предлагать тесты, но детерминированный CI решает, пройдёт ли шлюз.

4. Плоскость релиза

Плоскость релиза управляет интеграцией и развёртыванием в production.

Она:

  • Объединяет в порядке зависимостей
  • Создаёт воспроизводимые артефакты
  • Идентифицирует сборки с неизменяемыми версиями или хэшами
  • Запускает теневой трафик, где возможно
  • Расширяет canary-выпуски постепенно
  • Мониторит индикаторы уровня обслуживания
  • Сохраняет проверенный путь отката

ИИ может располагаться между этими плоскостями как слой оркестрации и доказательств. Команды могут использовать задачи для назначения срезов миграции, изоляции рабочих деревьев, прикрепления контрактов, сбора результатов тестов и требования проверки перед продвижением работы.

Важная граница в том, что оркестрация координирует доказательства. Она не превращает утверждение агента об успехе в разрешение на релиз.

Пример сценария: Миграция платёжного сервиса с Python на Go

Рассмотрим миграцию платёжного сервиса на Python объёмом 120 000 строк на Go. Бизнес-цель — снизить

задержка на хвосте и упрощение развертывания.

Опасный промпт может выглядеть так:

Перепишите этот сервис на Go и добейтесь прохождения всех тестов.

Такой промпт оставляет неопределенными семантику транзакций, поведение при ошибках, денежную точность, идемпотентность и порядок развертывания.

Шаг 1: Напишите контракт

Для каждой конечной точки команда фиксирует:

  • Схемы запросов и ответов
  • Правила авторизации
  • Поведение ключа идемпотентности
  • Округление валюты
  • Семантику повторных попыток
  • Транзакции базы данных
  • Порядок событий
  • Коды ошибок
  • Требования к телеметрии

Также отмечаются намеренные изменения, например, удаление заголовка отладки, специфичного для Python. Команда определяет поддерживаемую платформу и матрицу зависимостей, затем задаёт бюджет задержки для p95 и p99, а также порог пиковой памяти.

Шаг 2: Выберите три пилотных сегмента

Команда выбирает:

  1. Чистый модуль форматирования валюты
  2. Репозиторий идемпотентности с побочными эффектами в базе данных
  3. Конечную точку HTTP только для чтения

Первый тестирует механический перевод. Второй — транзакции и конкурентность. Третий — совместимость HTTP.

Каждый сегмент обрабатывается одним агентом реализации. Новые рецензенты получают только контракт, исходный код, предлагаемый diff и команды для валидации.

Шаг 3: Используйте старый сервис как дифференциальный оракул

Очищенный корпус исторических запросов воспроизводится на обеих версиях.

Ответы нормализуются только там, где контракт допускает различия, и затем сравниваются. Для путей записи обе реализации запускаются на одноразовых снимках базы данных. Сравниваются результирующие строки и сгенерированные события.

Затем выполняются метаморфические тесты:

  • Повторяется один и тот же ключ идемпотентности
  • Изменяется безвредный порядок ключей JSON
  • Вводятся вариации времени повторных попыток
  • Проверяются граничные денежные значения

Шаг 4: Затенение и канареечное развёртывание нового сервиса

Перед включением записи в продакшене сервис на Go получает теневой трафик с отключённой записью или перенаправлением в изолированное хранилище.

Команда сравнивает:

  • Распределение задержек
  • Классификацию ошибок
  • Вызовы зависимостей
  • Формы трассировок
  • Использование памяти
  • Поведение событий

Затем команда направляет 1% канареечного трафика от группы мерчантов с низким риском.

Для расширения требуются:

  • Отсутствие необъяснимых финансовых расхождений
  • Паритет уровней ошибок
  • Задержка в рамках согласованного бюджета
  • Успешная тренировка отката

Реализация при этом может двигаться быстро. Безопасность обеспечивается преобразованием задачи «перепишите сервис» в проверяемые утверждения.

Этот пример также показывает, почему остаётся необходимой экспертиза в предметной области. Агенты могут переводить код, но специалисты по платежам знают, что дублирующиеся события, различия в округлении и поведение при повторных попытках — это бизнес-требования.

Фаза 0: Определите миграционный контракт и условия остановки

Прежде чем любой агент начнёт редактировать код, решите, что считать тем же самым продуктом.

Инвентаризация:

  • Публичные API
  • Поведение CLI
  • Форматы файлов
  • Эффекты в базе данных
  • Переменные окружения
  • Телеметрия
  • Видимые пользователю сообщения об ошибках
  • Поддерживаемые платформы
  • Характеристики производительности

Пометьте каждое свойство как одно из следующих:

  • Сохранить
  • Намеренно изменить
  • Устарело
  • Неизвестно

Неизвестное — не повод гадать. Это становится задачами для исследования.

Запустите старую систему, изучите вопросы и журналы изменений, проверьте производственные трассировки или спросите у поддерживающих специалистов. Древо исходного кода до миграции Bun

реорганизация сохранила историю Git через коммиты, содержащие только перемещения, что сделало происхождение целенаправленным требованием, а не побочным ущербом.

Определите жёсткие условия остановки. Остановите расширение, когда:

  • уровень несоответствия пилотного проекта превышает порог.
  • Работники многократно изменяют защищённые глобальные тесты.
  • Очередь ошибок компилятора растёт быстрее, чем закрывается.
  • Целевая производительность не укладывается в бюджет.
  • Артефакт отката не может быть собран.
  • Доказательства неполны или нечитаемы.

Остановка защищает проект от эскалации безвозвратных затрат.

Контракт должен контролироваться отдельно от выполнения. Агент не должен «исправлять» проваленный тест, ослабляя требование. Изменения контракта требуют проверки человеком и пояснения, почему старое поведение устарело или некорректно.

Этап 1: Построение семантической карты перед массовой генерацией

Создайте явные сопоставления для распространённых, тонких или опасных шаблонов «источник-цель».

Охватите такие области, как:

  • Правила владения и времени жизни
  • Возможность нулевого значения
  • Исключения и обработка ошибок
  • Целочисленное переполнение
  • Расчёты времени
  • Кодирование строк
  • Примитивы параллелизма
  • Владение аллокатором
  • FFI
  • Поведение в отладочной и релизной версиях
  • Платформозависимый код

Файлы PORTING.md и LIFETIMES.tsv Bun’а служили этой цели.

Их ценность не ограничивалась лучшими промптами. Они дали сотням работников общую семантическую стратегию. Без такой карты каждый агент изобретает собственный подход к переводу, и несогласованность становится проблемой интеграции.

Поручите независимым агентам атаковать карту:

  • Дайте одному рецензенту семантику исходного языка.
  • Дайте другому риски целевого языка.
  • Дайте третьему типичные примеры кода.
  • Потребуйте конкретные контрпримеры.

Люди должны проверять правила с наивысшим риском, особенно касающиеся владения памятью, параллелизма, границ безопасности, сохранения и поведения, существующего только в релизе.

Версионируйте карту. Каждое новое обнаруженное несоответствие должно обновлять правила, идентифицировать затронутые миграционные единицы и запускать целевую перепроверку.

Семантическая карта — это живая спецификация, а не промпт, вставленный один раз в начале.

Этап 2: Разработка намеренно сложных пилотных проектов

Не выбирайте только самые простые файлы.

Полезный пилотный проект включает три формы:

  1. Простая, репрезентативная единица
  2. Единица с большой зависимостью
  3. Семантическая горячая точка

Bun использовал три файла для проверки цикла «реализация-рецензирование-исправление» перед переводом 1448 файлов. Точное число менее важно, чем охваченный диапазон режимов отказов.

Измеряйте процесс пилотного проекта, а не только его результат:

  • Уважали ли работники владение файлами?
  • Были ли коммиты атомарными?
  • Находили ли рецензенты реальные дефекты или в основном создавали шум?
  • Мог ли исправитель применить предложения, не нарушая контракт?
  • Были ли доказательства всё ещё читаемы?
  • Сколько контекста и вычислений потребляла каждая принятая единица?

Сознательно вносите сбои. Добавьте тонкое различие в релизном режиме, тестовый пример для крайнего случая или порог производительности и убедитесь, что система проверки это обнаруживает.

Оборудование, прошедшее только чистые примеры, ещё не было протестировано.

Расширение должно начинаться только тогда, когда пилотный проект даёт стабильные, воспроизводимые результаты. Если впоследствии промпты, модели или политики инструментов существенно изменятся, запустите малый пилотный проект заново. Рабочий процесс

кофигурация — это производственный код, заслуживающий регрессионного тестирования.

Фаза 3: Распределение с изоляцией, владением и атомарными коммитами

Создавайте миграционные единицы, согласованные с графом зависимостей.

Разделение на уровне файлов удобно, но может быть неверной границей, если поведение пересекает модули. Назначьте одного автора на каждую единицу и сделайте владение читаемым для машин. Участники могут читать зависимости, но редактируют только свою область, если не запрашивают скоординированное изменение.

Используйте отдельные рабочие каталоги, контейнеры или эфемерные виртуальные машины, где это практично.

Неудача Bun с общим рабочим пространством показывает, почему. Ограничьте деструктивные Git-команды и дорогие глобальные команды сборки для конечных участников. Пусть координатор выполняет упорядоченную интеграцию.

Краткосрочные учётные данные и сетевые белые списки снижают влияние инъекций подсказок или утечки зависимостей. Рекомендации Anthropic по изоляции описывают границы файловой системы и сети как основу для более безопасной автономии.

Каждая принятая единица должна порождать атомарный коммит, содержащий:

  • Идентификатор источника
  • Применимые правила контракта
  • Выполненные команды
  • Результаты тестов и проверок
  • Результаты рецензирования
  • Одобренные исключения

Git становится как механизмом координации, так и восстановления.

Рекомендации Anthropic по длительным рабочим процессам советуют осмысленные коммиты и тестирование перед каждым коммитом, потому что восстанавливаемая история предотвращает превращение длительного выполнения агента в непрозрачный артефакт.

Не оптимизируйте под строки в минуту. Оптимизируйте под проверенные единицы в час.

Высокая пропускная способность генерации в сочетании с растущей очередью интеграции — это отрицательный прогресс.

Фаза 4: Относитесь к ошибкам компилятора и тестам как к очередям, а не как к доказательствам

Вывод компилятора создаёт структурированную работу.

Группируйте ошибки по единицам владения или слоям зависимостей, удаляйте дублирующие каскады и исправляйте коренные причины до листовых симптомов.

Запретите сокращения, если только контракт явно их не разрешает, включая:

  • Пустые заглушки
  • Игнорированные результаты
  • Широкие атрибуты allow
  • Отключённые утверждения
  • Заглушечные реализации
  • Тесты, изменённые только для того, чтобы кандидат прошёл

Запускайте тесты по расширяющимся кругам:

  1. Модульные тесты для изменённого модуля
  2. Контрактные тесты на публичных границах
  3. Интеграционные тесты через зависимости
  4. Кроссплатформенные наборы
  5. Полное регрессионное тестирование

Сохраняйте вывод неудачных запусков как артефакт. Финальный зелёный прогон без истории может скрыть, ослабляли ли участники проверки по пути.

Там, где возможно, отделяйте авторство тестов от реализации.

Один агент может вывести граничные случаи из контракта и старой реализации, в то время как другой пишет порт. Блокируйте одобренные тесты совместимости, чтобы участники реализации не могли их изменять. Свежие рецензенты должны спрашивать, проходит ли код по задуманной причине.

Производственные регрессии Bun демонстрируют разрыв между зелёным набором и семантической полнотой.

Отказ HMR только в релизной версии возник из-за побочного эффекта внутри debug_assert!. Сбой с UTF-16 нечётной длины отразил другое поведение срезов. Каждый ускользнувший дефект должен стать как постоянным регрессионным тестом, так и новым правилом семантической карты.

Фаза 5: Добавьте дифференциальное тестирование, фазинг и бюджеты производительности

Запустите старую и новую реализации на одном корпусе.

Сравните:

  • Коды выхода

  • Нормализованный вывод

  • Категории ошибок

  • Побочные эффекты

  • Состояние базы данных

  • Сгенерированные события

  • Трассировки

Построить генераторы граничных значений для:

  • Пустых входных данных
  • Максимальных размеров
  • Некорректных кодировок
  • Времени около начала эпохи Unix
  • Конкурентных состояний гонки
  • Платформо-зависимых путей
  • Истощения ресурсов

Непрерывно фаззить парсеры и границы протоколов.

Bun сообщил, что его фаззеры с направляемым покрытием выполнили код парсера примерно 100 миллиардов раз и привели к созданию около 15 pull request'ов с исправлениями. Абсолютное число зависит от нагрузки. Переносимый шаблон заключается в связывании обнаружения сбоев с воспроизводимыми тестами, исправлениями, предложенными агентом, и pull request'ами, проверенными человеком.

Когда пользователи зависят от производительности, производительность является частью поведения.

Бенчмарк:

  • Холодный запуск
  • Пропускная способность
  • Задержка p50
  • Задержка p95
  • Задержка p99
  • Пиковое использование памяти
  • Размер бинарного файла
  • Время сборки
  • Загрузка ЦП при репрезентативных рабочих нагрузках

Сравнивайте распределения, а не средние значения. Устанавливайте бюджеты до миграции, чтобы команда не могла рационализировать регрессии после значительных вложений в переписывание.

Также проводите длительные тесты (soak tests). Утечки памяти, утечки дескрипторов, рост очередей, фрагментация аллокатора и редкие состояния гонки могут проявляться часами или днями.

Язык с более сильными гарантиями безопасности памяти может устранить целые классы ошибок, при этом внося другое поведение в отношении выделения памяти, планирования или производительности.

Отдельно проверять небезопасный код, FFI и границы безопасности

Рассматривать каждое из следующих как отдельный класс проверки:

  • Блоки unsafe
  • Вызовы FFI
  • Сырые указатели
  • Пользовательские аллокаторы
  • Криптографические границы
  • Парсеры
  • Десериализаторы
  • Проверки разрешений
  • Логика аутентификации
  • Границы сохранения состояния

На момент составления исходного отчета Bun описал примерно 27 000 строк внутри блоков unsafe из примерно 780 000 строк Rust, большая часть которых связана с интеграцией C и C++.

Эта поверхность требует большего, чем обычный обзор кода.

Требовать комментарий-инвариант рядом с каждой небезопасной границей:

  • Что должно быть истинно?
  • Кто устанавливает инвариант?
  • Как долго указатель остается действительным?
  • Какой поток владеет значением?
  • Какой тест проверяет условие?

Группировать повторяющиеся шаблоны unsafe за проверенными обертками. Отслеживать небезопасные строки и блоки по владельцам, а не рассматривать общее количество как тщеславный показатель.

Использовать:

  • Статический анализ
  • Санитайзеры
  • Аудиты зависимостей
  • Фаззинг
  • Ручную проверку безопасности

11 раундов проверки безопасности от Bun являются свидетельством постоянного ужесточения, а не доказательством отсутствия дефектов.

Автоматизированная проверка безопасности должна дополнять предметную проверку, особенно в отношении аутентификации, побега из песочницы, секретов и изменений в цепочке поставок.

Проверять сам механизм миграции. Агенты выполняют содержимое репозитория, скрипты сборки и вывод инструментов. Скомпрометированная зависимость или скрытая инструкция в исходном коде могут повлиять на выполнение.

Изоляция файловой системы, сетевые ограничения, токены с ограниченной областью действия и неизменяемые проверки CI снижают этот риск.

Выпускать поэтапно и практиковать откат до того, как он понадобится

Слияние — это не релиз.

Создавать версионированные артефакты из известных коммитов, инструментальных цепочек, блокировок зависимостей и манифестов доказательств. Сохранять возможность сборки старой реализации.

Если старый и новый бинарные файлы могут сосуществовать, добавить переключатель времени выполнения или уровень маршрутизации.

Вместо необратимой замены пути.

Начните с теневого выполнения, когда побочные эффекты можно изолировать.

Затем канареечное развертывание по этапам:

  • Внутренние пользователи
  • Клиенты с низким риском
  • Платформа
  • Регион
  • Процент трафика

Определите пороги автоматического отката для:

  • Ошибок корректности
  • Частоты сбоев
  • Задержки
  • Памяти
  • Категорий ошибок
  • Сигналов поддержки

Даже если автоматические пороги не сработали, люди должны иметь возможность остановить расширение.

Отработайте откат.

Убедитесь, что:

  • Старый артефакт запускается успешно.
  • Схемы остаются совместимыми.
  • Поставленные в очередь задачи могут быть обработаны.
  • Средства мониторинга определяют, какая реализация обслужила каждый запрос.
  • Измеренное время отката соответствует эксплуатационным требованиям.

Документация по откату, которая никогда не выполнялась, — это всего лишь гипотеза.

После каждого пропущенного дефекта обновляйте контракт, семантическую карту, тестовый корпус и модель риска.

19 известных регрессий Bun полезны, так как они выявляют повторяющиеся проблемы перевода. Миграция завершена, когда новая реализация работоспособна и команда извлекла из нее уроки — а не когда сгенерированный diff объединен.

Многоразовая политика AI-миграции и манифест свидетельств

Следующий YAML предназначен для многократного использования командой. Адаптируйте команды, пороги и ответственных под свой репозиторий.

We0 AI или другая система оркестрации может прикрепить эту политику к задачам миграции и потребовать манифест свидетельств перед ревью.

ai_migration:
  name: payments-python-to-go
  contract: docs/MIGRATION_CONTRACT.md
  semantic_map: docs/PORTING_RULES.md
  old_reference: artifacts/payments-python@sha256:OLD
  new_candidate: artifacts/payments-go@sha256:NEW

  worker_policy:
    isolation: ephemeral_worktree
    one_writer_per_unit: true
    forbidden_commands:
      - "git reset --hard"
      - "git stash"
      - "git push --force"
    editable_paths: ["cmd/", "internal/", "tests/migration/"]
    protected_paths: ["tests/contracts/", "docs/MIGRATION_CONTRACT.md"]

  required_gates:
    compile: "go build ./..."
    unit: "go test ./..."
    contracts: "./scripts/run-contract-tests.sh"
    differential: "./scripts/compare-old-new.sh --corpus fixtures/replay"
    fuzz: "./scripts/fuzz.sh --hours 24 --unique-crashes 0"
    security: "./scripts/security-scan.sh --severity high"
    performance:
      p99_latency_regression_pct: 5
      peak_memory_regression_pct: 10
    platforms: [linux-amd64, linux-arm64]

  independent_review:
    fresh_context: true
    reviewers_per_unit: 2
    require_counterexample_search: true

  rollout:
    shadow_hours: 48
    canary_percentages: [1, 5, 20, 50, 100]
    rollback_artifact_required: true
    rollback_drill_required: true

  evidence_manifest:
    include:
      - contract_version
      - source_and_target_commits
      - changed_units
      - commands_and_exit_codes
      - differential_mismatches
      - fuzzing_summary
      - benchmark_distributions
      - unsafe_or_ffi_inventory
      - reviewer_findings
      - approved_exceptions
      - rollback_drill_result

Эта политика намеренно запрещает разработчикам реализации редактировать контракт или утвержденные контрактные тесты.

Она требует:

  • Референсные артефакты
  • Независимое ревью
  • Количественные

Ограничения производительности

  • Доказательства развёртывания
  • Проверенный путь отката

Исключения возможны, но они должны быть задокументированы и утверждены, а не скрыты внутри подсказки.

Измеряйте проверенный прогресс, а не сгенерированный объём

Строки кода, количество агентов и прошедшие дни — это метрики ёмкости. Они не измеряют успех продукта.

Используйте сбалансированную карту показателей миграции.

Проверенная пропускная способность модулей

Отслеживайте модули миграции, которые:

  • Компилируются
  • Проходят целевые проверки контрактов
  • Получают независимую проверку
  • Интегрируются без регрессий

Измеряйте количество принятых модулей за единицу времени.

Устранение несоответствий

Отслеживайте обнаруженные различия и то, каждое ли из них:

  • Объяснено
  • Исправлено
  • Утверждено как намеренное
  • Всё ещё не решено

Утечки дефектов

Отслеживайте дефекты, которые прошли через шлюз, который должен был их остановить.

Каждый утекший дефект должен указывать на отсутствующее правило контракта, тест, оракул, этап проверки или порог развёртывания.

Внимание человека

Измеряйте время, которое люди тратят на:

  • Определение контрактов
  • Устранение неоднозначностей
  • Проверку высокорискованного кода
  • Исследование несоответствий
  • Управление развёртыванием

ИИ может сократить время на реализацию, повысив качество спецификации. Это хороший компромисс, а не сбой автоматизации.

Стоимость вычислений и инструментов

Измеряйте общую стоимость модели, вычислений и инструментов на принятый модуль.

Динамические рабочие процессы могут потреблять больше токенов, чем обычные сеансы. Параллелизм оправдан, если он сокращает время ожидания для ценной работы, не создавая большего объёма верификации.

Поддерживаемость после миграции

Отслеживайте:

  • Время запуска
  • Скорость сборки
  • Частоту сбоев при изменениях
  • Задержку проверки
  • Плотность дефектов
  • Владение небезопасными модулями
  • Лёгкость отладки
  • Качество эксплуатационной документации

Перенос, который выполняется быстро, но остаётся непрозрачным для команды, переносит долг, а не устраняет его.

Как команда может начать без переписывания миллиона строк

Выберите ограниченную миграцию с работающей эталонной реализацией, например:

  • Изменение одной версии SDK
  • Одна подсистема фреймворка
  • Одна команда CLI
  • Одна конечная точка сервиса

Напишите одностраничный контракт поведения и три пилотных сценария, ориентированных на риски.

Используйте отдельные задачи агента для реализации и проверки, чтобы их контексты оставались независимыми.

Перед реализацией:

  1. Зафиксируйте критерии приёмки.
  2. Требуйте от исполнителя возврата коммита и доказательств, а не словесных утверждений.
  3. Попросите проверяющего найти контрпримеры и выявить недостающие тесты.
  4. Выполняйте проверки в CI вне модели.
  5. Расширяйтесь только на следующий слой зависимостей после успеха пилота.

Ведите полную запись выполнения:

  • Подсказка
  • Модель
  • Область инструментов
  • Исходный коммит
  • Целевой коммит
  • Изменённые пути
  • Проверки
  • Сбои
  • Результаты проверяющего
  • Исключения
  • Стоимость
  • Итоговое решение

Эта запись позволяет команде сравнивать версии инструментов и исследовать дефекты, не гадая, что видел агент.

Используйте простое правило внедрения:

Автономию нужно заслужить.

Рабочий процесс, который многократно выдает проверенные модули, может получить более широкую область файлов или более длительное время работы без наблюдения. Он не получает автоматического разрешения на развёртывание.

Возможности, доказательства и полномочия остаются разделёнными.

Ограничения: что не доказывает пример Bun

Bun — необычный проект.

Его создатель руководил

migration, имел глубокое знание кодовой базы и обладал прямыми архитектурными полномочиями. Старая реализация имела обширный набор тестов, Rust предоставлял строгую обратную связь от компилятора, и проект мог использовать значительные параллельные вычисления.

Большинство команд не разделят все эти преимущества.

Этот случай также был представлен через Anthropic, и в исходной статье говорится, что работа выполнялась с использованием предрелизной модели Claude Fable 5. Это ценные первичные данные, но это не независимое сравнение вендоров.

Утверждения о том, сколько времени потребовалось бы команде людей, являются контрфактическими оценками. Команды не должны принимать решения о закупках на основе одной успешной миграции.

19 зарегистрированных регрессий — это известные регрессии, а не гарантия полного подсчёта. Запуски фазинга и раунды проверки безопасности измеряют усилия, а не отсутствие дефектов.

Самый сильный обоснованный вывод скромен:

Крупные миграции на основе ИИ осуществимы в сочетании с сильной детерминированной обратной связью и экспертной оркестровкой, но их риск остаётся инженерной проблемой после завершения генерации кода.

Этот вывод всё ещё значим. Команды могут попытаться реализовать проекты модернизации, которые ранее были отложены из-за стоимости, при условии, что они выделят бюджет на спецификацию, верификацию и контролируемое развёртывание в том же масштабе, что и реализация.

Практический чеклист миграции

  • Определите сохранённое, изменённое, устаревшее и неизвестное поведение.
  • Инвентаризируйте контракты платформы, производительности, телеметрии, ошибок и побочных эффектов.
  • Постройте семантическую карту для рискованных шаблонов "источник-цель".
  • Защитите контракты и утверждённые тесты от исполнителей реализации.
  • Запустите сложные пилотные модули перед развёртыванием по всему репозиторию.
  • Изолируйте писателей и ограничьте деструктивные операции Git и сети.
  • Требуйте атомарные коммиты с командами, выводами и ссылками на контракты.
  • Используйте рецензентов-антагонистов с новым контекстом для высокорисковых модулей.
  • Запустите проверки компилятора, модульные, контрактные, интеграционные и кроссплатформенные шлюзы.
  • Сравните старую и новую реализации на репрезентативных корпусах.
  • Добавьте метаморфические, фазинговые, санитарные проверки и проверки производительности.
  • Инвентаризируйте границы unsafe, FFI, аутентификации, парсера и персистентности.
  • Сохраните воспроизводимый артефакт отката и проведите тренировку отката.
  • Разверните через теневые и канареечные стадии с автоматическими порогами остановки.
  • Превратите каждый утёкший дефект в улучшение контракта или верификации.
  • Измеряйте верифицированные модули, несоответствия, человеческое внимание, стоимость и поддерживаемость.

Часто задаваемые вопросы

Что Bun переписал на Rust?

Bun мигрировал крупную реализацию, которая ранее была написана на Zig, на Rust. В опубликованном отчёте описывается примерно 780 000 строк кода на Rust и высокопараллельный рабочий процесс с использованием ИИ, за которым последовало обширное тестирование, проверка безопасности, фазинг и производственная закалка.

Выполнил ли ИИ переписывание Bun на Rust без проверки человеком?

Нет. Правила миграции, написанные человеком, ручная проверка артефактов, изолированные рабочие процессы, обратная связь от компилятора, независимые рецензенты-агенты, проверка безопасности, фазинг и средства контроля производственного развёртывания — все они играли важные роли. Этот случай лучше понимать как инженерию, ускоренную ИИ, а не как безнадзорное преобразование кода.

Почему существующих тестов недостаточно для

Миграция языка?

Существующие тесты обычно покрывают лишь часть наблюдаемого поведения. Они могут упускать семантику, присущую только релизной версии, различия между платформами, регрессии производительности, небезопасные границы, изменения телеметрии или пограничные случаи, которые никогда не были закодированы в наборе тестов.

Что такое дифференциальное тестирование при миграции кода?

Дифференциальное тестирование запускает старую и новую реализации с одинаковыми входными данными и сравнивает их наблюдаемые выходные данные и побочные эффекты. Это особенно полезно, когда старая система заслуживает доверия, но не существует полной формальной спецификации.

Зачем реализаторам и рецензентам использовать отдельные контексты?

Новый рецензент с меньшей вероятностью унаследует допущения и ошибки в рассуждениях автора. Рецензент может сосредоточиться на контракте, diff, доказательствах и контрпримерах, а не на защите пути реализации, который привел к изменению.

Как командам следует проверять небезопасный код Rust при миграции?

Каждый небезопасный блок или граница FFI должны иметь назначенного владельца, задокументированные инварианты, целенаправленные тесты и четкое объяснение корректности указателей, времени жизни и владения потоками. Статический анализ, санитайзеры, фаззинг, проверка зависимостей и ручная проверка безопасности должны применяться отдельно от обычной проверки кода.

Какие метрики следует отслеживать при AI-ассистированной миграции?

Отслеживайте пропускную способность проверенных модулей, несоответствие закрытий, выявленные дефекты, время, затраченное человеком, вычислительные затраты, здоровье процесса развертывания и поддерживаемость после миграции. Сгенерированные строки кода и количество агентов — это метрики производительности, а не доказательства корректности.

Может ли небольшая команда использовать это руководство без запуска десятков агентов?

Да. Начните с одного ограниченного компонента, письменного контракта поведения, трех риск-ориентированных пилотов, отдельных контекстов реализации и рецензирования, детерминированных шлюзов CI и протестированного пути отката. Масштабируйте рабочий процесс только после того, как он неоднократно будет давать проверяемые результаты.

Связанные инструменты

  • Bun: Универсальный набор инструментов для JavaScript и TypeScript, чья миграция на Rust является основным примером для данного руководства.
  • Rust: Язык системного программирования с сильными гарантиями безопасности во время компиляции и явными небезопасными границами.
  • Claude Code: Агентная среда кодирования от Anthropic, используемая в динамическом рабочем процессе, описанном в исходном материале.
  • GitHub Actions: Платформа CI/CD, подходящая для детерминированных шлюзов компиляции, тестирования, безопасности, бенчмаркинга и проверки доказательств.
  • cargo-fuzz: Стандартный инструмент фаззинга для проектов на Rust, построенный на libFuzzer.
  • Miri: Интерпретатор Rust, который может обнаруживать определенные формы неопределенного поведения в небезопасном коде.

Связанные ссылки

Краткое содержание

Переписывание Bun на Rust показывает, что ИИ-агенты кодирования могут кардинально сократить время реализации, но также демонстрирует, почему верификация должна стать первоклассной инженерной системой. Контракты, семантические карты, изолированные рабочие процессы, независимое рецензирование, дифференциальное тестирование, фазинг-тестирование, бюджеты производительности и поэтапное развертывание превращают сгенерированный код в заслуживающий доверия доказательства миграции.

Практический вывод не в копировании количества агентов или строк кода. Он заключается в разбиении миграции на ограниченные утверждения, требовании детерминированных доказательств для каждого утверждения и расширении автономии только после того, как рабочий процесс неоднократно демонстрирует надежные результаты.

Крупная ИИ-ассистированная переработка завершается только тогда, когда новая система проверена, работоспособна, восстанавливаема и понятна — а не когда сгенерированный код был объединен.