BunのAI駆動Rust書き換え:100万行のコード移行を実現する検証マニュアル

BunがZigからRustへの移行をAI支援で実践した事例に触発された検証マニュアル。動作契約、分離コーディングエージェント、差分テスト、ファジング、unsafeコードレビュー、進捗測定、安全なリリースを網羅。

发布于 2026年7月12日generalGEO 评分: 06 次阅读
画像はBunのAI駆動Rust書き換えに関連する内容を示している。背景は暗色で、左側に漫画風の人物アイコン、右側にRustの歯車アイコンがある。画像中央に「Bun's AI-Powered Rust Rewrite」と大きく表示され、「AI-Powered」は紫色、「Rust Rewrite」は青色。下部に2つのコードブロックがあり、左側はJavaScriptコード、右側はRustコードで、それぞれリクエスト処理を行う関数の例を示している。画像はドキュメントで紹介されているBunのAI支援によるZigからRustへの移行内容に対応し、Rust書き換えにおけるAIの活用を視覚的に表現している。

BunのAI駆動Rustリライト:百万行規模のマイグレーションにおける検証プレイブック

はじめに

この見出しは無視するのが難しい。Bunは、動的なClaude Codeワークフローを用いて、主要な実装をZigからRustに11日で移行したと報じられている。公開された報告によれば、数千のコミット、最大64のClaudeエージェント、約78万行のRustコード、各実装ユニットに対する2人の敵対的レビューア、そしてコンパイルが通らなかったコードからテストスイートを通過し出荷可能な移植版への進化が記されている。

間違った教訓は、言語のリライトがワンクリック作業になったというものだ。有用な教訓は、実装スループットと検証スループットが今や別々の工学的問題であるということだ。

AIエージェントは、人間のチームが読み取るよりも速くコードを生成できる。一度そうなれば、従来のプルリクエストレビューはもはや主要な安全機構として機能しなくなる。チームは、大規模な確率的変更を、機械で検証可能な証拠に裏付けられた小さな主張に変換するシステムを必要としている。

Bunのその後の本番環境レポートは、これを異常に具体化した。チームは19の既知のリグレッション(すべて後に修正済み)、11回のセキュリティレビュー、パーサー全体にわたる継続的なカバレッジ誘導ファジング、そして約78万行中約2万7千行のunsafeブロック内のRustコードを報告した。これらの事実は移行の物語を弱めるものではない。印象的なデモが終わった後に、真剣な移行作業がどのようなものかを示している。

このガイドは、その経験を再利用可能な検証プレイブックに変換する。目標はBunの規模をコピーすることではない。AIコーディングエージェントがチームが責任を持って一行ずつ検査できる以上のコードを書くことができる、あらゆる移行(言語移植、フレームワーク置き換え、API近代化、データベース変換、またはリポジトリ全体のリファクタリング)のための方法を提供することである。

重要なポイント

  • Bunのリライトは、AIエージェントが実装時間を圧縮できることを示している。検証時間を排除できることを示してはいない。
  • 移行可能な資産は移行システムである:記述された動作契約、リスクマップ、小規模パイロット、隔離されたワーカー、独立したレビューア、決定論的ゲート、および復元可能なコミット。
  • コンパイラとレガシーテストスイートは異なる障害クラスを捕捉する。どちらも言語間のセマンティックミスマッチ、リリースモードの違い、パフォーマンスリグレッション、unsafe境界のすべてを捕捉するわけではない。
  • 大規模な差分には証拠指向のレビューが必要である。人間は、生成されたすべての行が等しく精査を受けるふりをするのではなく、契約、リスクホットスポット、反例、テストのギャップ、およびロールアウトの決定を検査すべきである。
  • チームは百万行のリライトを試みずとも同じパターンを採用できる:エージェントに一度に一つのスライスで動作を証明するよう要求し、測定された結果の後にのみより広範な自律性を付与する。

Bunが実際に行ったこと、そして見出しが省略していること

工学的記述は、大規模なコード生成の前から始まっていた。

Jarred Sumnerは、繰り返し現れるZigのパターンをRustにマッピングするPORTING.mdの作成に約3時間を費やしたと報じられている。別のワークフローは構造体フィールドを分析し、Rustのライフタイムを提案し、それらの選択を2人の敵対的レビューアに送り、結果をLIFETIMES.tsvにシリアライズした。これらの成果物も手動でレビューされた。

以下は、提供された内容を日本語に翻訳したものです。

実装試験はリポジトリ全体ではなく、3つのファイルを対象として実施された。各ファイルに対して:

  1. 1体のエージェントがRust版を実装した。
  2. 2体の新規エージェントが、動作の等価性と移行ドキュメントへの準拠をレビューした。
  3. 別のエージェントが承認された修正を適用した。

この試験運用が行われた後にのみ、作業は1,448のZigファイルに広がった。

最初の大規模実行は失敗した。エージェントはワークスペースを共有し、git stashgit stash popgit reset --hardなどのコマンドを使用していた。そのため、互いの変更が干渉し合った。その後、ワークフローは、安全でない調整コマンドを禁止し、各16体のエージェントからなる4つのワークツリーを使用するように変更された。

この詳細は、ピーク時のコード生成速度よりも重要である。並行コーディングは分散システムの問題である。共有状態、競合する書き込み、高コストなグローバル操作、所有権、およびリカバリには、すべて明示的なルールが必要となる。

生成されたコードはすぐには動作しなかった。Bunはコンパイラエラーをキューとして使用し、一度に1つのクレートずつ進行した。ある時点では、約16,000のコンパイラエラーがエージェントに割り当てられた。このループでは、1体の修正エージェント、2体のレビューエージェント、1体の適用エージェントが使用され、cargo checkやGit操作などの高コストなコマンドの実行頻度が制限された。

これは魔法のような翻訳ではなかった。これは、決定論的なフィードバックによって駆動される段階的な収束であった。

Anthropicの動的ワークフローに関する発表では、初期の記事執筆時点で既存のテストスイートの99.8%が合格したと報告されている一方で、この移植がまだ本番環境には移行されていないことが明記されていた。その後のBunの記事では、その後に続く作業(セキュリティレビュー、ファジング、本番環境でのリグレッション、意味論的な修正、unsafeコードの削減)について詳述されている。

これらの情報源を合わせて読むと、2つの異なるマイルストーンが説明されていることがわかる。

  • マージに十分な実装完了
  • 安全に実行するのに十分なエビデンス完了

知っておくべき用語:移植、オラクル、差分テスト、unsafeな表面

これらの定義が重要なのは、チームがエビデンスが何を証明すべきかに合意するまでは、移行を検証できないからである。また、エージェントの確信表明と、外部から確認可能な結果を区別するためでもある。

移植(Port)

移植とは、定義された一連の振る舞いを維持しながら、ソフトウェアを新しい言語、ランタイム、プラットフォーム、またはフレームワークで再実装することである。

「振る舞いを維持する」には境界が必要である。移植は、公開APIや出力を維持しながら、内部アーキテクチャ、パフォーマンス特性、エラーメッセージ、またはサポートされていないエッジケースを意図的に変更することがある。

振る舞い契約(Behavior Contract)

振る舞い契約とは、新しい実装が維持しなければならないプロパティの明示的なリストである。

これには以下のものが含まれる可能性がある。

  • 入力と出力
  • エラー動作
  • 順序付け
  • 副作用
  • 並行処理のセマンティクス
  • リソース制限
  • サポート対象プラットフォーム
  • パフォーマンス目標
  • 可観測性要件

既存のコードには振る舞いが含まれているが、既存のすべての振る舞いが意図的なものではない。契約は、要件を歴史的な偶発的なものから分離する。

テストオラクル(Test Oracle)

テストオラクルは、出力が正しいかどうかを判断するものである。

単体テストのアサーションは一つのオラクルである。リファレンス実装、プロトコル仕様、ゴールデンファイル、データベースの不変条件、または人間が作成したルールもオラクルとして機能しうる。

Anthropicの長期実行に関するガイダンス

科学的コーディングにおいては、自律的な作業には進捗を判断できるよう、参照先、測定可能な目標、またはテストスイートが必要であることが強調されています。

差分テスト

差分テストは、古い実装と新しい実装に同じ入力を与え、観測可能な結果を比較します。

これは、古い実装が信頼されているものの、完全な形式的仕様が存在しない場合に特に有用です。結果が一致しても両方の実装が正しいとは限りませんが、不一致があれば正確な調査の優先順位が生まれます。

メタモルフィックテスト

メタモルフィックテストは、正確な期待出力を記述することが難しい場合に、複数の実行間の関係をチェックします。

例としては以下が挙げられます:

  • 値をシリアライズしてパースすると、元の値が保持されること。
  • 独立した入力を並べ替えても、集合値の結果が変わらないこと。
  • 冪等なマイグレーションを2回実行しても、2回目の実行で状態が変わらないこと。
  • 同じ冪等性キーでリトライしても、重複した副作用が発生しないこと。

Unsafe インターフェース

Unsafe インターフェースとは、対象言語の通常の保証が弱められたり回避されたりするコードです。

Rustでは、unsafe はC言語やC++のFFI境界、カスタムアロケータ内部、または低レベルのランタイム統合のために必要となる場合があります。その生の数が評価を決定するわけではありません。チームは各 unsafe 境界に対して、所有権、不変条件、テスト、および明確な計画を持つ必要があります。

エスケープされた欠陥

エスケープされた欠陥とは、それを検出するはずのゲート(マージ後、カナリアデプロイ後、リリース候補テスト後、または本番ロールアウト後)で発見された、マイグレーション起因のバグです。

エスケープされた欠陥は、実装だけでなく、検証システムに関するフィードバックでもあります。

因果連鎖:なぜ高速な生成にはより強力な検証が必要か

エージェントの並列化は実装の経済性を変えます。64人のワーカーが同時にファイルを翻訳すれば、コード生成時間は劇的に短縮される可能性があります。依存関係グラフ、対象言語のセマンティクス、共有テスト環境がなくなるわけではありません。スループットが単にボトルネックを下流に移すだけです。

ボトルネック1:統合

個々には妥当なファイルでも、一緒にコンパイルすると失敗する場合があります。

Bunの約16,000件のコンパイラエラーと循環クレート依存関係は、局所的な翻訳と全体的な一貫性の間のギャップを示しています。コンパイラは、型、所有権、ライフタイム、名前、および一部の制御フロープロパティに対しては優れた決定論的オラクルですが、製品の動作に対するオラクルではありません。

ボトルネック2:意味的等価性

Bunは、言語間でほぼ同一に見えるコードでも、動作が異なるバグを文書化しています。

例としては以下が含まれます:

  • Rustの debug_assert! 内に配置された副作用がリリースビルドで消える一方で、同等のZigのアサーションはその引数を評価し続けること。
  • 先行評価される unwrap_or 式が、遅延評価されるべき動作を引き起こすこと。
  • 実装間でバイトスライスと境界のセマンティクスが異なること。
  • 奇数長のUTF-16入力でクラッシュが露呈すること。

これらはまさに、表面的なレビューでは見逃される種類の障害です。翻訳されたコードがもっともらしく見えるからです。

ボトルネック3:レビューの相関性

同じモデルが同じコンテキストと前提を使用して変更を記述しレビューすると、そのモデルは以前のエラーを再現する可能性があります。

original mistake(原文の誤り)

AnthropicのClaude Codeベストプラクティスドキュメントでは、新しいレビューアコンテキストを使用することを推奨しています。レビューアは、作成者の推論を受け継がずに、差分と標準を確認します。独立性は正確性を保証するものではありませんが、共有コンテキストのバイアスを低減します。

ボトルネック4:運用上のエビデンス

レイテンシが倍増し、メモリ使用量が増加し、あるOSターゲットが壊れ、または可観測性が失われても、テストは合格する可能性があります。

変更が大きければ大きいほど、チームがデプロイ後に初めて要件違反を発見する可能性が高くなります。そのため、移行計画にはカナリア、ロールバック、テレメトリの比較、そして発見されたすべての欠陥を新しい契約ルールまたはテストに変換するプロセスを含める必要があります。

因果関係の結論は単純です:

AIは移行コストを排除しません。コストをタイピングから、仕様、ハーネス設計、エビデンスレビュー、デプロイ管理へと移行させるのです。

この変化を無視するチームは、コード生成を迅速に完了しても、リライトが実際に機能するかどうかを判断するのに数ヶ月を費やすことになるでしょう。

AI駆動移行のための検証アーキテクチャ

このアーキテクチャには4つのプレーンがあります。

1. 契約プレーン

契約プレーンは以下を格納します:

  • パブリックな振る舞い
  • 互換性の約束
  • 意図的な変更
  • サポート対象プラットフォームマトリックス
  • パフォーマンス予算
  • セキュリティ制約
  • 可観測性要件

人間がこのプレーンを維持し、リポジトリがバージョン管理します。

2. 実行プレーン

実行プレーンには、独立した実装エージェントが含まれます。

各エージェントは以下を受け取ります:

  • 1つの移行ユニット
  • 関連するソースファイル
  • 承認された契約
  • セマンティックマップ
  • 範囲を限定されたツール
  • 対象を絞ったチェック

エージェントは契約やグローバルテストを変更できません。割り当てられた範囲のみを編集し、コミットとエビデンスの両方を返します。

3. 検証プレーン

検証プレーンは実装から独立しています。

以下のことが可能です:

  • 候補のコンパイル
  • 対象を絞ったテストとグローバルテストの実行
  • 新旧差分チェックの実行
  • パーサーとプロトコル境界のファジング
  • セキュリティに敏感なコードのスキャン
  • 代表的なワークロードのベンチマーク
  • 新規レビューアへの反例の探索依頼

検証エージェントはテストを提案することもありますが、ゲート通過の可否は決定論的CIが判断します。

4. リリースプレーン

リリースプレーンは統合と本番公開を制御します。

以下のことを行います:

  • 依存関係の順序でマージ
  • 再現可能なアーティファクトの生成
  • 不変のバージョンまたはハッシュによるビルドの識別
  • 可能な場合のシャドウトラフィックの実行
  • カナリアの段階的拡大
  • サービスレベル指標の監視
  • テスト済みロールバックパスの保持

We0 AIはこれらのプレーン間で、オーケストレーションとエビデンスレイヤーとして機能できます。チームはタスクを使用して、移行スライスの割り当て、ワークツリーの分離、契約の添付、テスト出力の収集、作業進行前のレビュー要求を行うことができます。

重要な境界は、オーケストレーションがエビデンスを調整することです。エージェントの成功主張をリリース許可に変換することはありません。

シナリオ例:決済サービスのPythonからGoへの移行

12万行のPython決済サービスをGoに移行するケースを考えます。ビジネス目標は、

フェーズ0:移行契約と停止条件の定義

エージェントがコードを編集する前に、何をもって同一プロダクトとするかを決定します。

インベントリ:

  • 公開API
  • CLIの動作
  • ファイル形式
  • データベースへの影響
  • 環境変数
  • テレメトリー
  • ユーザーから見えるエラーメッセージ
  • サポート対象プラットフォーム
  • パフォーマンス特性

各プロパティを以下のいずれかに分類します:

  • 維持
  • 意図的に変更
  • 非推奨化
  • 不明

不明なものは推測を許可しません。これらは調査タスクとなります。

旧システムを実行し、Issueやチェンジログを検索し、本番トレースを調査するか、メンテナーに確認します。Bunの移行前のソースツリー

reorganization preserved Git history through move-only commits, making provenance an intentional requirement rather than collateral damage.

Define hard stop conditions. Stop fan-out when:

  • Pilot mismatch rates exceed the threshold.
  • Workers repeatedly modify protected global tests.
  • The compiler-error queue grows faster than it closes.
  • Target performance misses the budget.
  • A rollback artifact cannot be built.
  • Evidence is incomplete or unreadable.

Stopping protects the project from sunk-cost escalation.

The contract must be controlled separately from execution. An agent must not “fix” a failing test by weakening the requirement. Contract changes require a human-reviewed amendment explaining why the old behavior is obsolete or incorrect.

Phase 1: Build a Semantic Map Before Large-Scale Generation

Create explicit mappings for common, subtle, or dangerous source-to-target patterns.

Cover areas such as:

  • Ownership and lifetime rules
  • Nullability
  • Exceptions and error handling
  • Integer overflow
  • Time calculations
  • String encoding
  • Concurrency primitives
  • Allocator ownership
  • FFI
  • Debug-versus-release behavior
  • Platform-specific code

Bun’s PORTING.md and LIFETIMES.tsv served this purpose.

Their value was not limited to better prompts. They gave hundreds of workers a shared semantic strategy. Without such a map, every agent invents its own translation approach, and inconsistency becomes an integration problem.

Ask independent agents to attack the map:

  • Give one reviewer source-language semantics.
  • Give another target-language risks.
  • Give a third representative code examples.
  • Require concrete counterexamples.

Humans should inspect the highest-risk rules, especially those involving memory ownership, concurrency, safety boundaries, persistence, and release-only behavior.

Version the map. Every newly discovered mismatch should update the rules, identify affected migration units, and trigger targeted revalidation.

The semantic map is a living specification, not a prompt pasted once at the start.

Phase 2: Design Deliberately Difficult Pilots

Do not choose only the easiest files.

A useful pilot includes three shapes:

  1. A simple, representative unit
  2. A dependency-heavy unit
  3. A semantic hotspot

Bun used three files to validate the implement-review-fix loop before translating 1,448 files. The exact number matters less than the range of failure modes covered.

Measure the pilot process, not only its output:

  • Did workers respect file ownership?
  • Were commits atomic?
  • Did reviewers find real defects or mostly produce noise?
  • Could the fixer apply suggestions without violating the contract?
  • Was the evidence still readable?
  • How much context and compute did each accepted unit consume?

Seed faults deliberately. Add a subtle release-mode difference, an edge-case fixture, or a performance threshold and confirm the verification system detects it.

A harness that has only passed clean examples has not yet been tested.

Fan-out should begin only when the pilot produces stable, repeatable evidence. If the prompts, models, or tool policies later change substantially, rerun the small pilot. Workflow

設定はプロダクションコードであり、回帰テストが必要です。

フェーズ3: 分離、所有権、アトミックコミットによるファンアウト

依存関係グラフに沿った移行ユニットを作成します。

ファイルレベルの分割は便利ですが、動作がモジュールをまたぐ場合には適切な境界ではない可能性があります。各ユニットに1人の書き手を割り当て、所有権を機械可読にします。ワーカーは依存関係を読み取ることができますが、調整された変更を要求しない限り、自身のスコープのみを編集できます。

実用的な場合には、別々のワークツリー、コンテナ、または一時的な仮想マシンを使用します。

Bunの共有ワークスペースの失敗はその理由を示しています。リーフワーカーに対して、破壊的なGitコマンドや高コストなグローバルビルドコマンドを制限します。コーディネーターが順序立てた統合を実行します。

短命の認証情報とネットワーク許可リストにより、プロンプトインジェクションや依存関係の流出の影響を軽減します。Anthropicのサンドボックス化ガイダンスでは、ファイルシステムとネットワークの境界を、より安全な自律性の基盤として説明しています。

受け入れられた各ユニットは、以下を含むアトミックコミットを生成する必要があります:

  • ソース識別子
  • 適用可能な契約ルール
  • 実行されたコマンド
  • テストとチェックの出力
  • レビューアの結果
  • 承認された例外

Gitは、調整メカニズムとリカバリメカニズムの両方になります。

Anthropicの長期実行ワークフローガイダンスでは、各コミットの前に意味のあるコミットとテストを推奨しています。なぜなら、回復可能な履歴により、長時間のエージェント実行が不透明な成果物になるのを防ぐからです。

1分あたりの行数を最適化しないでください。1時間あたりの検証済みユニット数を最適化してください。

高い生成スループットと増大する統合キューは、マイナスの進歩です。

フェーズ4: コンパイラエラーとテストを証明ではなくキューとして扱う

コンパイラの出力は構造化された作業を生み出します。

所有権ユニットまたは依存関係レイヤーごとにエラーをグループ化し、重複するカスケードを削除し、リーフの症状の前に根本原因を修正します。

契約が明示的に許可しない限り、以下のショートカットを禁止します:

  • 空のスタブ
  • 無視された結果
  • 広範なallow属性
  • 無効化されたアサーション
  • プレースホルダーの実装
  • 候補を通すためだけに変更されたテスト

テストは範囲を広げて実行します:

  1. 変更されたモジュールのユニットテスト
  2. 公開境界での契約テスト
  3. 依存関係をまたぐ統合テスト
  4. クロスプラットフォームスイート
  5. 完全な回帰テスト

失敗した出力は成果物として保持します。履歴のない最終的なグリーン実行は、ワーカーが途中でチェックを繰り返し弱体化させたことを隠す可能性があります。

可能な場合は、テストの作成を実装から分離します。

1つのエージェントが契約と古い実装からエッジケースを導出し、別のエージェントがポートを記述します。承認された互換性テストをロックして、実装ワーカーが変更できないようにします。新しいレビューアは、コードが意図された理由で合格しているかどうかを確認する必要があります。

Bunのプロダクション回帰は、グリーンスイートと意味的な完全性の間のギャップを示しています。

リリース専用のHMR障害は、debug_assert!内の副作用から発生しました。奇数の長さのUTF-16クラッシュは、異なるスライス動作を反映していました。回避されたすべての欠陥は、恒久的な回帰テストと新しいセマンティックマップルールの両方になる必要があります。

フェーズ5: 差分テスト、ファジング、パフォーマンスバジェットの追加

新旧の実装を同じコーパスに対して実行します。

比較:

  • 終了コード

  • 正規化出力

  • エラーカテゴリ

  • 副作用

  • データベース状態

  • 発行されたイベント

  • トレース

以下のための境界値ジェネレータを構築する:

  • 空の入力
  • 最大サイズ
  • 不正なエンコーディング
  • Unixエポック前後の時刻
  • 並行競合
  • プラットフォーム固有のパス
  • リソース枯渇

継続的にパーサーとプロトコル境界をファジングする。

Bunは、カバレッジガイド付きファザーがパーサーコードを約1000億回実行し、約15件の修正プルリクエストを生成したと報告している。絶対的な数はワークロードに依存する。転用可能なパターンは、クラッシュの発見を再現可能なテスト、エージェント提案の修正、および人間がレビューするプルリクエストに結び付けることである。

ユーザーがパフォーマンスに依存する場合、パフォーマンスは振る舞いの一部である。

ベンチマーク:

  • コールドスタート
  • スループット
  • p50レイテンシ
  • p95レイテンシ
  • p99レイテンシ
  • ピークメモリ
  • バイナリサイズ
  • ビルド時間
  • 代表的なワークロード下でのCPU

平均値ではなく分布を比較する。移行前に予算を設定し、チームが書き換えに多大な投資をした後に性能低下を正当化できないようにする。

耐久テストも実行する。メモリリーク、ディスクリプタリーク、キュー成長、アロケータの断片化、まれな競合は、顕在化するまでに数時間から数日かかる場合がある。

メモリ安全性保証がより強い言語は、異なる割り当て、スケジューリング、またはパフォーマンス動作を導入しつつも、バグのクラス全体を排除できる。

unsafeコード、FFI、およびセキュリティ境界を個別にレビューする

以下をそれぞれ個別のレビュークラスとして扱う:

  • unsafeブロック
  • FFI呼び出し
  • 生ポインタ
  • カスタムアロケータ
  • 暗号境界
  • パーサー
  • デシリアライザ
  • 権限チェック
  • 認証ロジック
  • 永続化境界

ソースレポート時点で、Bunは約78万行のRustコードのうち約2万7千行がunsafeブロック内にあり、その多くはCおよびC++統合に関連していると説明している。

その表面領域には、通常のコードレビュー以上のものが必要である。

すべてのunsafe境界の近くに不変条件コメントを必須とする:

  • 何が真でなければならないか?
  • 誰が不変条件を確立するか?
  • ポインタはどのくらい有効であり続けるか?
  • どのスレッドが値を所有するか?
  • どのテストが条件を検証するか?

繰り返されるunsafeパターンをレビュー済みラッパーの背後にグループ化する。unsafeな行とブロックを、総数を虚栄的な指標として扱うのではなく、所有者ごとに追跡する。

以下のツールを使用する:

  • 静的解析
  • サニタイザ
  • 依存関係監査
  • ファジング
  • 手動セキュリティレビュー

Bunの11ラウンドのセキュリティレビューは、継続的な強化の証拠であり、欠陥がなかった証拠ではない。

自動セキュリティレビューは、特に認証、サンドボックスエスケープ、機密情報、サプライチェーン変更の周辺において、ドメインレビューを補完するものである。

移行メカニズム自体をレビューする。エージェントはリポジトリコンテンツ、ビルドスクリプト、ツール出力を実行する。妥協された依存関係やソースコード内の隠された命令は、実行に影響を与える可能性がある。

ファイルシステムの分離、ネットワーク制限、スコープ付きトークン、不変のCIチェックは、このリスクを低減する。

段階的にリリースし、必要になる前にロールバックを練習する

マージはリリースではない。

既知のコミット、ツールチェーン、依存関係ロック、エビデンスマニフェストからバージョン管理された成果物を構築する。古い実装をビルド可能なままにしておく。

新旧両方のバイナリが共存できる場合は、ランタイムスイッチまたはルーティング層を追加する。

以下は、提供された内容を自然な日本語に翻訳したものです。


パスを不可逆的に置き換えるのではなく。

副作用を隔離できる場合は、シャドウ実行から始める。

次に、カナリアリリースを以下の対象で行う:

  • 内部ユーザー
  • 低リスクのテナント
  • プラットフォーム
  • リージョン
  • トラフィック割合

以下の項目に対して自動ロールバックのしきい値を定義する:

  • 正しさの不一致
  • クラッシュ率
  • レイテンシ
  • メモリ
  • エラーカテゴリ
  • サポートシグナル

自動化されたしきい値が発動していない場合でも、人間が展開を停止できる能力を保持しなければならない。

ロールバックを練習する。

以下を確認する:

  • 以前のアーティファクトが正常に起動すること。
  • スキーマに互換性があること。
  • キューに入った作業が処理可能であること。
  • 可観測性により、各リクエストをどの実装が処理したかが特定できること。
  • 測定されたロールバック時間が運用目標を満たしていること。

一度も実行されたことのないロールバックのドキュメントは、仮説に過ぎない。

すべてのエスケープされた欠陥の後、契約、セマンティックマップ、テストコーパス、リスクモデルを更新する。

Bunの19の既知のリグレッションは有用である。なぜなら、繰り返し発生する翻訳上の危険性を明らかにするからである。移行が完了するのは、新しい実装が運用可能になり、チームがそこから学んだときであり、生成された差分がマージされたときではない。

再利用可能な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

このポリシーは、実装ワーカーが契約または承認された契約テストを編集することを意図的に防止する。

以下を要求する:

  • リファレンスアーティファクト
  • 独立したレビュー
  • 定量的な証拠
  • ロールバック訓練
  • インシデントからの学習

パフォーマンスの限界

  • ロールアウトの証拠
  • テスト済みのロールバック手順

例外は可能ですが、プロンプト内に隠すのではなく、文書化され承認される必要があります。

生成量ではなく、検証済みの進捗を測定する

コード行数、エージェント数、経過日数は、処理能力に関する興味深い指標です。しかし、それらはプロダクトの成功を測定するものではありません。

バランスの取れた移行スコアカードを使用してください。

検証済みユニットスループット

以下の条件を満たす移行ユニットを追跡します:

  • コンパイルが通る
  • 対象の契約チェックを通過する
  • 独立したレビューを受ける
  • リグレッションなく統合される

単位時間あたりの承認ユニット数を測定します。

不一致の解消

発見された差異と、それぞれが以下のいずれであるかを追跡します:

  • 説明済み
  • 修正済み
  • 意図的なものとして承認済み
  • 未解決のまま

エスケープされた欠陥

本来は捕捉されるべきゲートを通過してしまった欠陥を追跡します。

エスケープされた各欠陥は、欠落している契約ルール、テスト、オラクル、レビュー手順、またはロールアウトの閾値を特定する必要があります。

人間の関与

人間が費やす時間を測定します:

  • 契約の定義
  • あいまいさの解消
  • 高リスクコードのレビュー
  • 不一致の調査
  • デプロイの運用

AIは、実装時間を短縮すると同時に、仕様の品質を向上させる可能性があります。これは、自動化の失敗ではなく、良いトレードオフです。

計算コストとツールコスト

承認ユニットあたりの総モデル、計算、ツールコストを測定します。

動的ワークフローは、通常のセッションよりも多くのトークンを消費する可能性があります。並列処理は、大規模な検証バックログを作成することなく、価値の高い作業の待ち時間を短縮する場合に正当化されます。

移行後の保守性

以下を追跡します:

  • 起動時間
  • ビルド速度
  • 変更障害率
  • レビューのレイテンシ
  • 欠陥密度
  • 安全でないモジュールの所有権
  • デバッグの容易さ
  • 運用ドキュメントの品質

迅速に出荷されたものの、チームにとって不透明なままの移植は、負債を除去するのではなく、移動させるだけです。

チームが100万行のリライトなしで開始する方法

ライブのリファレンス実装がある、範囲を限定した移行を選択してください。例:

  • 単一のSDKバージョン変更
  • 単一のフレームワークサブシステム
  • 単一のCLIコマンド
  • 単一のサービスエンドポイント

1ページの動作契約書と、リスクに焦点を当てた3つのパイロットケースを作成します。

実装とレビューに別々のエージェントタスクを使用し、それらのコンテキストが独立したままになるようにします。

実装前:

  1. 受け入れチェックをロックダウンする。
  2. 実装者に、散文による主張ではなく、コミットと証拠を返すよう要求する。
  3. レビュー担当者に、反例を見つけ、欠落しているテストを特定するよう依頼する。
  4. モデル外のCIでチェックを実行する。
  5. パイロットが成功した後でのみ、次の依存関係レイヤーに拡張する。

完全な実行記録を保持します:

  • プロンプト
  • モデル
  • ツールスコープ
  • ソースコミット
  • ターゲットコミット
  • 変更されたパス
  • チェック
  • 失敗
  • レビュー担当者の所見
  • 例外
  • コスト
  • 最終決定

この記録により、チームはハーネスのバージョンを比較し、エージェントが見たものを推測することなく欠陥を調査できます。

シンプルな採用ルールを使用します:

自律性は獲得されるべきものである。

検証済みユニットを繰り返し生成するワークフローは、より広いファイルスコープまたはより長い無人実行時間を与えられる場合があります。デプロイ許可が自動的に与えられるわけではありません。

能力、証拠、および権限は別個のままです。

限界:Bunのケースが証明しないこと

Bunは異例のプロジェクトです。

その創設者は、

移行作業には、コードベースに対する深い知識と、直接的なアーキテクチャ上の権限が必要でした。旧実装には大規模なテストスイートがあり、Rustは強力なコンパイラフィードバックを提供し、プロジェクトでは大規模な並列計算を活用できました。

ほとんどのチームは、これらすべての利点を共有することはありません。

この事例はAnthropicを通じて提示され、元の記事では、この作業にプレリリース版のClaude Fable 5モデルが使用されたと述べられています。これは貴重な一次証拠ですが、独立したベンダー比較ではありません。

人間のチームにどれだけの時間が必要だったかという主張は、反実仮想的な推定です。チームは、一度の成功した移行事例だけで調達判断を下すべきではありません。

報告された19件のリグレッションは確認されたものであり、完全な数を保証するものではありません。ファジング実行やセキュリティレビューのラウンド数は、労力を測定するものであり、欠陥の不存在を証明するものではありません。

最も妥当で控えめな結論は、次の通りです。

強力な決定論的フィードバックと専門家によるオーケストレーションを組み合わせた場合、大規模なAI主導の移行は実現可能ですが、コード生成完了後も、そのリスクは依然として工学的な問題として残ります。

この結論はそれでも意味があります。チームは、これまでコストを理由に延期されていたモダナイゼーションプロジェクトに、実装と同規模の仕様策定、検証、管理されたロールアウトの予算を確保すれば、着手できます。

実践的な移行チェックリスト

  • 保存する動作、変更する動作、非推奨とする動作、未知の動作を定義する。
  • プラットフォーム、パフォーマンス、テレメトリ、エラー、副作用に関する契約を棚卸しする。
  • リスクの高いソースからターゲットへのパターンのためのセマンティックマップを構築する。
  • 実装作業者から契約と承認済みテストを保護する。
  • リポジトリ全体に展開する前に、困難なパイロットユニットを実行する。
  • 書き込み役を隔離し、破壊的なGit操作とネットワーク操作を制限する。
  • コマンド、出力、契約参照を含むアトミックなコミットを要求する。
  • 高リスクユニットには、新しいコンテキストで敵対的レビューを行うレビューアを割り当てる。
  • コンパイラ、ユニット、契約、統合、クロスプラットフォームのゲートチェックを実行する。
  • 代表的なコーパスで新旧実装を比較する。
  • メタモルフィックテスト、ファジング、サニタイザー、パフォーマンスチェックを追加する。
  • unsafe、FFI、認証、パーサー、永続化の境界を棚卸しする。
  • 再現可能なロールバック用アーティファクトを保存し、ロールバック訓練を実施する。
  • 自動停止しきい値を設定したシャドウおよびカナリア段階でロールアウトする。
  • 発見されたすべての欠陥を、契約や検証の改善に変換する。
  • 検証済みユニット、不一致、人的注意、コスト、保守性を測定する。

よくある質問

BunはRustで何を書き換えたのですか?

Bunは、以前Zigで書かれていた主要な実装をRustに移行しました。公開された報告では、約78万行のRustコードと、高度に並列化されたAI支援ワークフローに続き、広範なテスト、セキュリティレビュー、ファジング、プロダクション強化が行われたと説明されています。

AIは人間のレビューなしでBunのRust書き換えを完了したのですか?

いいえ。人間が作成した移行ルール、手動による成果物レビュー、隔離されたワークフロー、コンパイラフィードバック、独立したエージェントレビューア、セキュリティレビュー、ファジング、プロダクションロールアウト管理がすべて重要な役割を果たしました。この事例は、無人でのコード変換というよりも、AIによる加速を受けたエンジニアリングと理解するのが適切です。

なぜ既存のテストだけでは不十分なので

言語の移行?

既存のテストは通常、観測された動作の一部のみをカバーしています。リリース時のみのセマンティクス、プラットフォームの違い、パフォーマンスの後退、unsafeな境界、テレメトリの変更、あるいはテストスイートにエンコードされていないエッジケースを見逃している可能性があります。

コード移行における差分テストとは?

差分テストは、新旧の実装に同じ入力を与え、その観測可能な出力と副作用を比較します。これは、旧システムが信頼されているが、完全な正式な仕様が存在しない場合に特に有効です。

実装エージェントとレビューエージェントはなぜ別々のコンテキストを使うべきか?

新しいレビューアは、作成エージェントの前提や推論の誤りを受け継ぎにくくなります。レビューアは、変更を生み出した実装経路を擁護するのではなく、契約、差分、証拠、反例に集中できます。

移行中、チームはどのようにunsafeなRustコードをレビューすべきか?

すべてのunsafeブロックまたはFFI境界には、名前付きの所有者、文書化された不変条件、対象を絞ったテスト、そしてポインタの有効性、ライフタイム、スレッドの所有権に関する明確な説明が必要です。静的解析、サニタイザー、ファジング、依存関係レビュー、手動セキュリティレビューは、通常のコードレビューとは別に適用する必要があります。

AI支援による移行ではどのような指標を追跡すべきか?

検証済みのユニットスループット、不一致の解消、外部に漏れた欠陥、人的注意、計算コスト、ロールアウトの健全性、移行後の保守性を追跡します。生成された行数やエージェント数は、正しさの証明ではなく、キャパシティの指標です。

小規模チームでも、多数のエージェントを実行せずにこのプレイブックを使用できるか?

はい。まずは一つの限定されたコンポーネント、文書化された動作契約、三つのリスク重視のパイロット、独立した実装とレビューのコンテキスト、決定論的なCIゲート、そしてテスト済みのロールバックパスから始めてください。検証可能な結果を繰り返し生み出せるようになってから、ワークフローを拡大してください。

関連ツール

  • Bun: オールインワンのJavaScriptおよびTypeScriptツールキット。そのRustへの移行が、このプレイブックの主要なケーススタディとなっています。
  • Rust: 強力なコンパイル時の安全性保証と明示的なunsafe境界を持つシステムプログラミング言語。
  • Claude Code: Anthropicのエージェント型コーディング環境。ソース資料に記述された動的ワークフローで使用されています。
  • GitHub Actions: 決定論的なコンパイル、テスト、セキュリティ、ベンチマーク、証拠のゲートに適したCI/CDプラットフォーム。
  • cargo-fuzz: libFuzzer上に構築された、Rustプロジェクト向けの標準的なファジングツール。
  • Miri: unsafeなコードにおける特定の形態の未定義動作を検出できるRustインタプリタ。

関連リンク

  • Bun: Rewriting Bun in Rust: Bunの公式エンジニアリングブログによる、リライト、プロダクションの強化、ファジング、既知の後退についての解説。
  • Bun Source Repository: Rust実装、課題、テスト、移行履歴を含むBunの公式リポジトリ。
  • [Anthropic: Introducing Dynamic Workflows](https://claude.

要約

BunのRustによる書き換えは、AIコーディングエージェントが実装時間を劇的に短縮できることを示す一方で、検証を第一級のエンジニアリングシステムとしなければならない理由も明らかにしています。契約、セマンティックマップ、分離されたワーカー、独立したレビュー、差分テスト、ファジング、パフォーマンス予算、段階的なロールアウトこそが、生成されたコードを信頼性のある移行の証拠へと変える要素です。

実際的な教訓は、エージェントの数やコード行数を模倣することではありません。移行を境界のある主張に分割し、各主張に対して決定的な証明を要求し、ワークフローが繰り返し信頼性のある結果を生み出した後にのみ自律性を拡大することです。

大規模なAI支援による書き換えが完了するのは、新しいシステムが検証され、運用可能で、復元可能であり、理解されたときであり、生成されたコードがマージされたときではありません。