Технологии

Mistral перенесла 40 000 строк Fortran 77 на C++ через parity harness и AI-агентов

В проекте для европейского энергетического оператора автономный перевод по одной подпрограмме дал работающий, но не модернизированный код. Лучший результат появился после восстановления документации, численных checkpoint-тестов и процесса coder → tester → reviewer с обязательными человеческими воротами.

Mistral перенесла 40 000 строк Fortran 77 на C++ через parity harness и AI-агентов

Задачей был не построчный перевод, а смена архитектуры

Mistral рассказала о первом этапе модернизации reservoir simulator европейского энергетического оператора: 40 000 строк из кодовой базы объёмом 300 000 строк перенесли с Fortran 77 на C++. Исходная система моделировала физические процессы, не имела централизованной документации и готового test suite. Это делало миграцию одновременно языковой, архитектурной и предметной задачей.

Fortran 77 хранит общее состояние в COMMON blocks, допускает неявную типизацию по первой букве имени и строит процедурный поток иначе, чем современный object-oriented C++. При осмысленном переносе глобальные массивы превращаются в явные структуры и параметры, а циклы и управление состоянием меняют расположение. Из-за этого проверка соответствия строка к строке перестаёт работать: сравнивать нужно поведение и числа.

Parity harness построили до миграции

Команда сначала добавила в Fortran подпрограммы для экспорта состояния, а в C++ — framework, который загружал эти checkpoints. Согласованность означала численное равенство финальных результатов и критических промежуточных точек, выбранных инженерами клиента. Агенты сами инструментировали legacy-код для выгрузки snapshots и запускали тесты соответствующих C++ modules.

Этот порядок превращает расплывчатое «кажется, работает так же» в исполнимый контракт. Он особенно важен для научного кода: итоговая цифра может случайно совпасть, пока промежуточные состояния уже разошлись и ошибка проявится на другом наборе параметров. При этом parity harness подтверждает эквивалентность только на покрытых scenarios; полнота контрольных точек и допуски остаются инженерным решением.

Более ста агентов восстанавливали карту системы

Документация проекта была рассыпана между старыми PDF и комментариями в исходниках. Команда написала parser, построила единое caller-callee tree и через Vibe CLI запустила более ста агентов для документирования. Они двигались от листьев дерева вверх, подтягивали нужные PDF через document libraries и Mistral OCR, а затем открывали PR в исходный repository.

Отдельный reviewer agent по cron находил новые PR и назначал исправления. В результате документация собиралась рядом с кодом, а не оставалась внешним архивом, который быстро теряет связь с реализацией. Важное ограничение этого подхода — агент может стройно описать неверно понятый фрагмент. Поэтому дерево вызовов помогает распределить работу, но предметные связи всё равно должны подтверждаться тестами и специалистами по reservoir simulation.

Полная автономия сохранила недостатки Fortran

В первой попытке каждой Fortran subroutine назначили отдельного агента и дали им неделю автономной работы. Результат был функциональным, но COMMON blocks превратились в глобальные structs один к одному, а управление через GOTO сохранилось вместо перехода к loops и early returns. Получился Fortran, перепечатанный синтаксисом C++, а не современная система.

Во второй попытке на каждый module появились planner, coder, tester и code quality reviewer. Качество выросло, но при сложной ошибке агенты делали несколько попыток и останавливались, потому что некому было изменить стратегию. Оба эксперимента показывают разные виды сбоя: одиночная автономия оптимизирует локальный перевод, а полностью автоматическая команда способна зациклиться на неверной гипотезе.

Рабочим оказался управляемый конвейер с человеком

Команда остановилась на среднем варианте: человек управлял группой coder, tester и reviewer, а миграция шла module за module. Вместе с инженерами клиента caller-callee tree разбивали на независимые поддеревья — на практике менее примерно 10 000 строк Fortran. Для каждого module сначала проектировали целевую C++ architecture и отдавали её на review reservoir engineer.

После согласования архитектуру раскладывали в task queue, а каждая задача проходила цикл plan → implement → test → repeat. Итоговые PR проверял человек и запрашивал изменения до merge. В этой схеме агентам оставили масштабируемую работу с кодом, но решения, определяющие границы module и допустимую архитектуру, не выдавали за автоматически доказанные. Именно такая комбинация дала mergeable результат.

Успех первого спринта нельзя переносить на весь legacy-код

Mistral подчёркивает благоприятное исходное условие: Fortran-система была самодостаточной и запускаемой. Первый sprint охватил core functionality — 40 000 из 300 000 строк. Проекты с недоступными внешними системами, неработающим baseline или физикой, которая нигде не описана, потребуют дополнительных способов верификации и не обязаны повторить этот темп.

Из кейса следуют три практических принципа: сначала построить parity harness, затем привести в порядок документацию и только после этого масштабировать structured agent workflows с human review gates. Это не обещание автоматической конвертации старых систем. Напротив, наиболее полезный вывод публикации в том, что AI-агенты ускоряют декомпозицию, документирование и реализацию лишь тогда, когда команда заранее создаёт проверяемую среду и оставляет человеку право остановить неверный путь.

Первоисточники

  1. Mistral — Modernizing complex legacy code with AI agents