9月9日、Mistralが「Modernizing complex legacy code with AI agents」と題した記事を公開した。AIエージェントに4万行のFortran 77を丸ごと任せたら何が起きるか——答えは「動くが、モダナイズとは呼べないもの」だった。完全自律でも手作業でもなく、人間がゲートを握る構造化ワークフローこそが実運用に耐える唯一の構成だったという実例を、Mistralが詳細に報告している。
4万行のFortran 77をC++へ——単純な「翻訳」では済まなかった理由
Mistralが支援したのは、あるヨーロッパのエネルギー事業者が抱えていた物理シミュレーター(油層シミュレーター)のモダナイゼーションだ。対象はFortran 77(1977年規格)で書かれた4万行のコードで、テストスイートも集中管理されたドキュメントも存在しない状態だった。
なぜ単純な翻訳で済まないのか。Fortran 77は、モジュールも名前空間も構造体もなく、状態はプログラム全体で共有される**COMMONブロック(グローバルメモリ)に格納される。変数名の先頭文字がIからNなら整数型、という暗黙型付け**ルールもある。変数名の長さは6文字に制限されており、タイポしても新しい変数が黙って生成されるだけでコンパイルエラーにはならない。
たとえば1次テイラー展開の実装はこうなる:
10 RHOG(IC) = ROG(IV) + DROG(IV)*(P(IC)-PTAB(IV))
入出力はすべてCOMMONブロック経由のグローバル変数で、ICが整数なのは変数名の先頭がIだからだ。
これをC++に移行すると:
double gasDensity(const GasProperties& gas, double pressure) {
size_t i = lookup(gas.pressure, pressure);
return gas.density[i] + gas.slope[i] * (pressure - gas.pressure[i]);
}
散在していたCOMMON配列はGasPropertiesという単一のパラメータに集約され、グリッドループは呼び出し元へ移動する。行単位で対応が取れないため、移行の正しさを検証するのが難しい。これが今回の作業を非自明にしている根本的な理由だ。
最初にやるべきこと:パリティハーネスの構築
エージェントを動かす前に、MistralチームがまずやったのはFortranとC++の出力が数値的に一致することを証明するための検証基盤(パリティハーネス)の構築だ。
具体的には以下の3点を整備した:
- Fortranコードベースの状態をエクスポートするサブルーチン
- そのチェックポイントをC++に読み込むテストフレームワーク
- エージェントを正しく誘導するためのSkill.mdファイル(エージェントへの指示・制約・コーディング規約をまとめたMarkdownドキュメント)
たとえば、FortranコードにRHOG変数をダンプする1行を挿入し(実行結果:42.71834)、その値をC++モジュールの検証用リファレンスとして使う、という形だ。記事では「どのコードモダナイゼーション案件でも最初にやるべきステップ」と断言している。
AIエージェントの使い方:3回の試行錯誤
第1試行:完全自律
Fortranのサブルーチン1つにつきエージェント1体を割り当て、1週間かけて自律的に変換させた。結果は「動くが、モダナイズとは呼べないもの」。COMMONブロックはそのままグローバル構造体になり、GOTOだらけの制御フローも残った。Fortranの構文をC++で書き直しただけの状態だった。
第2試行:役割分担エージェント
プランナー・コーダー・テスター・コードレビュアーの4役をエージェントに割り当て、連携させた。コード品質は大幅に改善したが、コードの複雑さに追いつけなくなるとバグを前にエージェントが止まり、誰も介入できない問題が発生した。
採用した最終構成
「人間がワークフローを操作しながら、コーダー・テスター・レビュアーの各エージェントをモジュール単位で動かす」という折衷案に落ち着いた。エージェントが詰まったときに人間がアンブロックする役割を担うことで、第2試行の品質を維持しながら実運用に耐えるフローを実現した。
具体的な流れは以下の通り:
- 対象C++アーキテクチャを生成
- 油層エンジニアがレビュー
- 承認後、タスクキューに分解
- 実装サブワークフロー(計画→実装→テスト)を実行
- 人間がPRをレビューし、マージまで修正を繰り返す
ドキュメント整備にもエージェントを活用
コードの移行と並行して取り組んだのがドキュメントの整備だ。元のドキュメントは古いPDFとFortranコード内のコメントに散在していた。
手続き型コードには「プログラム全体を単一の呼び出しツリーとして表現できる」という性質がある。Mistralはカスタムパーサーでこのツリーを生成し、**Vibe CLIで100体超のエージェントを並列起動**してドキュメント化を実施。各エージェントはMistral OCR経由でPDFを参照しながらツリーの葉から順番に処理し、PRを自動で開いた。レビュアーエージェントがcronで定期実行され、新規PRを確認して修正タスクをスケジュールする構成だ。
結果と3つの教訓
第1スプリントで処理したのは全30万行のうちの4万行。Fortranコードベースが自己完結していて単体で実行可能だったことが、今回の好条件として挙げられている。外部システムへの依存があったり、実行可能なベースラインが存在しない場合は難易度が跳ね上がると記事は指摘している。
この点は、レガシーシステムのモダナイゼーション全般に共通する課題でもある。たとえばCOBOLやPL/Iで書かれた金融系システムのように、外部DBや帳票システムと密結合したコードベースでは、パリティハーネスの構築自体がより困難になる。今回のケースが「好条件」だったという記事の指摘は、他のモダナイゼーション案件との比較において重要な留保だ。
Mistralがまとめた3つの原則:
- パリティハーネスを先に作れ——数値的な一致証明が最も安価で説得力のある完了基準になる
- ドキュメントを先に整備しろ——誰も読めないコードは移行できない
- この規模では、人間のレビューゲートを持つ構造化ワークフローが最強——完全自律も手作業も両方負ける
3つ目の教訓は、「AIに任せれば自動化できる」という期待への明確な反証でもある。完全自律エージェントは品質で落第し、役割分担エージェントは複雑さの前で停止した。人間の判断をワークフローに組み込むことが、大規模・高複雑度のコード移行では現時点での必須条件だとMistralは結論付けている。
詳細はModernizing complex legacy code with AI agentsを参照していただきたい。