エージェント・ソフトウェア・エンジニアリング #6 | buffa:Anthropic 製 AI コーディング(Rust)からの方法論的見本

buffa は単なる protobuf ライブラリではない。それは「AI がシステムレベルのコードを記述する際、人間と AI がそれぞれ何をすべきか、何をすべきでないか、そして協働の質の天井を制御するためにどのようなドキュメントやツール構造を用いるべきか」を示す範例である。


なぜ buffa を個別に解体する価値があるのか

Anthropic が公開した 3 つの Rust プロジェクトのうち、buffaは AI によるコーディング実践を研究する上で最も注目すべき存在だ。なぜなら、それは「AI によって書かれ、かつ本番環境での運用が明言された唯一のコード」というきわめて特異な位置を占めているからだ。

claudes-c-compilerは能力デモンストレーション用であり、README には「このコードの使用は推奨しない」と明記されている。connect-rustには AI 生成の宣言がなく、中核コードは人間が記述したものだ。一方、buffaだけは「Written by Claude ❣️」と明記され、かつ「Anthropic の本番環境で稼働中」であることが公言されている。

これは、buffaのエンジニアリング実践が学術的な議論ではなく、本番環境という試練をくぐり抜けた「実証済み」のものだということを意味する。ここから抽出される方法論は、「もっともらしく聞こえる」ものではなく、「有効性が証明された」ものなのだ。

しかもbuffaが扱っているのはprotobufのランタイムとコード生成(codegen)であり、ステートマシンが複雑(ワイヤフォーマット)で、境界条件が膨大(未定義フィールド/enum/再帰)であり、パフォーマンスへの感受性が高く(デコードループ)、API 設計への要求も厳しい(Rust の型システムと人間中心設計の両立)。さらに長期にわたる保守も必要とされる。これは現在、AI が最も失敗しやすいコードの種類だ。しかしbuffaは失敗しなかった。


1. 制約先行:DESIGN.mdを AI の意思決定フレームワークとして機能させる

1.1 8 つの設計原則=AI へのハード制約セット

buffaDESIGN.md冒頭には、以下の 8 項目からなる設計原則が列挙されている。

1. Pure Rust, zero C dependencies.
2. Editions-first.
3. Correct by default.
4. Idiomatic Rust API.
5. Zero-copy read path.
6. Linear-time serialization.
7. no_std capable.
8. Descriptor-centric.

これらは人間向けのプロジェクトビジョンではなく、AI 向けの「意思決定ルール」だ。AI が 2 つの実装案の間で迷った際、これらの原則が暗黙の優先順位に基づき即座に決着をつける。

  • 「UTF-8 検証を高速化するために C 依存を追加すべきか?」→ 原則 1 により却下
  • 「ゼロコピーと正しさが衝突した場合、どちらを優先するか?」→ 原則 3 が原則 5 より上位。正しさが勝つ
  • 「buffa に proto パース機能を追加すべきか?」→ 原則 8 により、独自パースは行わずprotoc/bufdescriptorを利用すると判断

AI は曖昧な要件を最も苦手にし、制約下での最適化を最も得意とする。この 8 原則はbuffaの設計空間を「無限の可能性」から「AI が効率的に探索可能な有限空間」へと圧縮する役割を果たしている。

1.2 競合比較表=「既存ライブラリを使え」という AI の提案を封じる

DESIGN.mdの冒頭には、以下の競合比較表が配置されている。

| Library       | Pure Rust | Editions | Maintained |
|---------------|-----------|----------|------------|
| prost v0.13   | Yes       | No       | Passive    |
| protobuf v4   | No (upb)  | Yes      | Active     |
| rust-protobuf | Yes       | No       | Maintenance|

この表は人間のための市場調査ではなく、AI 向けの「意思決定のアンカー」だ。これがなければ、AI は「prostをフォークして editions をサポートできないか調査せよ」と指示された際、大量のトークンを消費して分析を試みるだろう。しかしこの表があれば、答えは即座に下る。「prostはメンテナンスが受動的で editions を非対応。フォークは不可能だ」。この表は Claude Code の全セッション開始時に読み込まれ、「なぜ X を使わないのか」といった不毛な議論を根こそぎ排除する。

1.3 モジュール境界=AI に「どのファイルを修正すべきか」を教える

DESIGN.mdの約 30%は、各クレートの境界、責任範囲、どのコードがどのファイルに存在するかを説明することに割かれている。

WKT のワイヤフォーマットはsrc/generated/に、JSON およびstdlib変換は*_ext.rsに配置する。

この記述の真価は、人間に「WKT が事前生成されている」ことを伝えることではない(人間ならsrc/generated/ディレクトリを見ればわかる)。真の価値は AI に対して「Timestampwire encodingを修正したければgenerated/へ、RFC3339フォーマットを修正したければtimestamp_ext.rsへ」と明確に指示できる点にある。数十ものファイルからなるプロジェクトにおいて、AI が犯しがちなミスの筆頭が「間違ったファイルの修正」だ。モジュール境界の明文化は、このミスの発生確率をほぼゼロに押し下げる。


2. パラメータ化による分岐の排除:複雑さをコード生成段階へ前倒しする

2.1 Editions を中核抽象として据える

buffa のコード生成(codegen)内部にはif proto2 {} else if proto3 {}といった分岐は存在しない。すべての振る舞いの差異は、解決済みの機能(resolved features)の値の組み合わせによってのみ生み出される。

proto2 ファイル → proto2 機能のデフォルト値
proto3 ファイル → proto3 機能のデフォルト値
edition N     → edition N のデフォルト値+上書き

コード生成は構文バージョンではなく、解決済みの機能(FieldPresence::ExplicitImplicitEnumType::OpenClosedなど)のみを参照する。

この設計から得られる AI コーディングへの示唆は極めて深い。

悪いパターン良いパターン
AI がランタイムのif/else分岐を記述するAI がコード生成で静的コードを生成する
AI が複雑な状態判断を担うAI が状態をコードへコンパイルする
動的な振る舞い静的展開

AI には「決定論的代码」を生成させ、ランタイムの分岐ロジックは書かせないこと。分岐ロジックの正しさは「すべての分岐の組み合わせ」の理解に依存するが、静的展開の正しさは「各展開インスタンスの局所的な正しさ」にのみ依存するからだ。後者こそが AI の真骨頂である。

2.2 ディスクリプタ中心主義=AI にパースをさせない

buffa は独自の.protoパーサを持たない。代わりにprotoc/buf.protoファイルをFileDescriptorProto(構造化されたprotobufメッセージ)へパースさせ、コード生成はその構造化済み入力を直接消費する。

これは「能力の境界線」を明確に引いた好例だ。.protoファイルのパースには、曖昧な構文境界、複雑なインポート解決、機能継承チェーンの処理が伴う。これらは AI がミスを犯しやすい領域だ。一方、既に変換済みのディスクリプタから Rust コードを生成する作業は、入力が明確で出力も明確、かつ自動検証が容易な高度に構造化されたタスクである。

buffa は「AI が不得意な部分(パース)」を既存の信頼できるツール(protoc)に任せ、「AI が得意な部分(構造化入力からのコード生成)」を自ら担当する。これは手抜きではなく、能力配分の精密化だ。


3. 2 段構えの型システム:AI によるパフォーマンスコード作成のための構造的テンプレート

3.1 Owned と View の分離

buffa は各 protobuf メッセージに対し、2 種類の Rust 型を生成する。

// Owned: ヒープ割り当て。構築・変更に使用
pub struct Person {
    pub name: String,
    pub id: i32,
    pub address: buffa::MessageField
, } // View: ゼロコピー。高性能読み取りに使用 pub struct PersonView<'a> { pub name: &'a str, pub id: i32, pub address: buffa::MessageFieldView>, }

AI に「使いやすくて高速な型」を直接書かせようとすれば、AI は苦悩する。Rust においては「使いやすさ(String)」と「高速さ(&'a str)」が矛盾するからだ。しかし「各メッセージに対し、所有権を持つ型と借用参照する型の 2 つを生成せよ」という構造的テンプレートを与えれば、AI は各型内部で適切な処理を施すことができる。

これは構造的プロンプト(structural prompt)の好例だ。「もっと高速なコードを書け」と指示するのではなく、アーキテクチャパターンを与え、構造から自然にパフォーマンスが湧き上がるように仕向けるのだ。

3.2 OwnedView:非同期境界を越える自己参照ラッパー

PersonView<'a>のライフタイム'a'static制約を満たせない。しかし Tower サービスやtokio::spawnBoxFuture<'static, _>などは'staticを要求する。OwnedView<V>Bytesバッファとデコード済みビューを結合し、transmuteを用いてライフタイムを強制的に'staticへ拡張する。

DESIGN.mdでは、このtransmuteの安全性について以下の 3 点から論証されている。

  1. Bytesは参照カウント方式であり、移動後もヒープデータポインタは安定している
  2. Bytesは不変であり、ビューが参照するデータは変更されない
  3. 手動のDrop実装により、ビューは必ずバッファより先に解放される

この論証は人間向けのコードレビューのためではなく、今後OwnedViewを修正する AI セッション向けに記述されている。AI が関連コードを修正する際、この 3 条件が依然として成立するか再検証せねばならない。「transmuteを使った」だけでなく「なぜ sound なのか」を明記しなければ、将来の AI が不変性を無自覚に破壊する恐れがある。


4. 意思決定の進化履歴:AI の後退を防止する

4.1 AtomicU32Cell<u32>:すでに歩んだ道

DESIGN.mdで最も価値が高いのは「意思決定の進化履歴」の記録だ。例としてCachedSizeを挙げよう。

An earlier design used Cell<u32> on the assumption that avoiding atomics would be faster... In practice, Relaxed-ordered atomic load/store compiles to identical machine instructions as a plain memory access on every major platform... Switching to AtomicU32 makes messages Sync, enabling Arc<Message>...

その構造は以下の通り。

  1. 当初はCell<u32>を使用(より効率的と仮定)
  2. 理由は「アトミック処理のオーバーヘッド回避」
  3. しかし実際にはRelaxed順序のアトミック操作は、主要プラットフォームすべてで通常メモリアクセスと同一の機械語にコンパイルされる
  4. AtomicU32へ変更した結果、メッセージがSyncとなり(Arcへ格納可能に)
  5. さらにDefaultInstanceトレイトがSyncを要求——Cellではコンパイルエラー

この記述の核心は「後退の防止」だ。この歴史がなければ、新たな Claude セッションがAtomicU32を「最適化」と称してCell<u32>へ戻そうとするかもしれない。「シリアライゼーションはシングルスレッドだからアトミックは無駄」という発想だ。しかしこの記述が「その道はすでに歩んだ。性能問題以前にコンパイルが通らない」と教える。

4.2 却下されたプレスキャン案:データ付きの「やるな」

Two approaches were benchmarked: - Per-field scanning: 20-97% regressions - Single-pass counting: 5-40% regressions Vec's doubling strategy produces at most log2(n) allocations, and for typical protobuf maps/repeated fields (2-20 entries), that's only 2-5 allocations — cheaper than a full buffer scan.

プレスキャン(要素数を事前に数えて一括確保)は「明らかに正しい最適化」に見える。経験豊富なプログラマでも AI でも提案しうる。しかしデータは「どちらの実装も遅かった」と告げる。

この「却下案+ベンチマークデータ」の記録は、AI 協働のために特別に設計されている。従来のドキュメントは「何をしなかったか」を記録しない。しかし AI にとっては「何をすべきか」だけでなく「何をしてはならないか」が同等か、あるいはそれ以上に重要だ。AI には「前回試して失敗した」という記憶がないのだから。

4.3 調査ログ:思考プロセスの完全記録

docs/investigations/e0477-owned-view-send/は完全な調査ログだ。trait_variantや RTN、さまざまなdrop()変形が試され、最終的に問題が関数本体ではなくシグネチャ側にあることが判明した経緯が記されている。これは思考プロセスそのものの記録であり、単なる結論の提示ではない。

将来、ある AI セッションが「OwnedViewの Send 実装を最適化し、V: 'static制約を復活させよう」と考えた場合、この調査ログが後退を食い止める。「試した。問題は Rust コンパイラの RPITIT デシュガーバグ(rust-lang/rust#128095)にあり、コードレベルで解決できる類のものではない」と。


5. 審査エージェント:実施と評価の分離

5.1 rust-code-reviewer.mdの設計

buffaCLAUDE.mdは、コミット前にrust-code-reviewerエージェントを実行するよう指示する。このエージェントのメタデータからは、3 つの重要な設計判断が読み取れる。

model: opus:最強モデルを検査に、Sonnet をコーディングに充当。判断力は生成速度より貴重だ。

tools: Read, Glob, Grep:読み取り専用権限。審査者はコードを変更できない。これにより「自分で修正して自分で合格を出す」という自己完結型ループが強制排除される。

16 の審査次元:API デザインから観測可能性まで、Rust エンジニアリングの全スペクトルを網羅。API デザインが筆頭(ユーザビリティが最重要品質)、Unsafe が 8 番目(安全性は良いデザインの結果であり、独立目標ではない)。

5.2 なぜ AI に自己審査をさせないのか

Anthropic のハーネス設計に関するブログによれば、AI は自らの成果を評価する際、体系的に過大評価する傾向がある。生成者に自己批判させるより、独立した評価者を設定して厳しくさせたほうが遥かに容易だ。

buffa のレビューアエージェントはこの知見の工学的実装だ。コーディング担当の Claude(おそらく Sonnet)がコードを書き、審査担当の Claude(Opus、読み取り専用)が評価する。両者は完全に分離されている。

5.3 2 段ドキュメントの重ね合わせ=完全なる審査

rust-code-reviewer.mdが汎用的な Rust の知識(16 次元)を提供し、CLAUDE.mdがプロジェクト固有のルール(「コード生成を変更したら型を再生成せよ」など)を提供する。この 2 段構成により、深さとプロジェクト文脈の両方を備えた審査が可能になる。これは再利用可能なパターンだ。rust-code-reviewer.mdを自らの Rust プロジェクトへ持ってくるだけで、自らのCLAUDE.mdを整えるだけで済む。


6. 未来の AI 協働者に向けたコードコメント

6.1「何をするか」より「なぜか」を注記

buffa のソースコード内のコメントスタイルは、一般的なオープンソースプロジェクトと明確に異なる。

// An unbounded `loop` is used intentionally: a bounded
// `for _ in 0..10` adds loop-counter overhead that LLVM cannot eliminate

これは「これがループだ」と説明するものではない。「なぜ、より安全に見える有界ループを使わないのか」を説明するものだ。LLVM はループが 10 回以内に終了すると証明できず、ループカウンタのオーバーヘッドが残るため、エンコードスループットが 40%も低下する。将来の AI が「改善」の名の下に性能劣化を招くことを防ぐための注記だ。

6.2 安全性の論証をインラインで記述

すべてのunsafeブロックには// SAFETY:コメントが付与されている。形式的な一行文ではなく、完全な論証チェーンだ。

// SAFETY: `Bytes` is StableDeref — its heap data never moves or is
// freed while we hold the `Bytes` value. We hold it in `self.bytes`,
// and drop order guarantees `view` drops first.

3 つの条件(StableDeref+保持関係+ドロップ順序)が缺一不可。このスタイルはむしろレビューアが要求する形式に近い。AI が自発的に記述する SAFETY コメントは「正しいと分かっているから安全」といった空疎なものになりがちだが、これはそれを防ぐ。

6.3 テスト名がそのまま仕様書

fn explicit_presence_with_zero_value()
fn has_extension_returns_false_on_extendee_mismatch()
fn extension_or_default_zero_is_present_not_default()

これらのテスト名それ自体が仕様書だ。AI はコード修正時、追加の仕様ドキュメントなしにテスト名から期待動作を理解できる。


7. パフォーマンス・エンジニアリングの「品味の境界線」

7.1 意図的な性能オーバーヘッド

DESIGN.mdには、各性能オーバーヘッドの理由が明記されている。

オーバーヘッド理由最適化可能か
未定義フィールドのVec::push往復忠実度の維持不可。中核機能
EnumValue ラッパー型安全なオープン enum不可。さもなくば prost 流の i32 へ後退
再帰深度チェック再帰メッセージ型のサポート不可。さもなくば E0275 エラー
ネストメッセージごとのBox標準 Rust オーナーシップアリーナ利用は可能だが原則 4 に違反

この表は AI 向けの「最適化するな」リストだ。AI は真っ先にこれらのオーバーヘッド排除を試みるが、表が明言する。「これらすべては意図的であり、放棄不可能な機能に対応する」。

7.2 可読性のレッドライン

Readability line we hold: fast-path/slow-path splits with a "why" comment are fine. Manual unrolling, #[inline(always)] sprinkled defensively, SIMD intrinsics, or likely()/unlikely() workarounds are not. The test: can a new contributor read the code, understand the fast path, and safely modify the slow path?

これは AI 時代のパフォーマンス・エンジニアリング哲学だ。「推論可能性」>「極限のマイクロ最適化」

AI は本能的に攻撃的最適化を志向する(可読性など気にしない)。このルールが AI を「人間が保守可能」な範囲へ引き戻す。許容される最適化(高速経路分離+why コメント)と禁止される最適化(手動展開、SIMD、likely/unlikely)の境界は精密に引かれている。

この点は特に詳述する価値がある

buffa の DESIGN.md は、3 つのプロファイルガイド付き最適化を記録した直後、この「可読性のレッドライン」宣言を特別に追加している。これは漠然としたコードスタイルガイドではない。「どの最適化は許容されるか」を具体的に示した上で「どの最適化は禁止されるか」を明確に線引きしているのだ。

この順序が重要だ。まずは許容されたものから見ていこう。

許容されるもの:3 つのプロファイルガイド付き最適化

これら 3 つの最適化はすべて、connect-rust統合プロセス中のpprofデータ(LogRecord ビューデコードベンチマーク。1 リクエストあたり約 350 文字列フィールド、450 変長整数)に基づいている。いずれも「小さく、注記があり、可読性を保つ」変更だ。

最適化 1:encode_varintの非有界ループ

// 以前(あるリファクタ後)
for _ in 0..10 {
    if value < 0x80 {
        buf.put_u8(value as u8);
        return;
    }
    buf.put_u8((value as u8 & 0x7F) | 0x80);
    value >>= 7;
}
// 以後(非有界ループへ復帰)
loop {
    if value < 0x80 {
        buf.put_u8(value as u8);
        return;
    }
    buf.put_u8((value as u8 & 0x7F) | 0x80);
    value >>= 7;
}

あるリファクタでloopfor _ in 0..10へ変更された。明示的境界があるため「より安全」に見える。しかし LLVM は内部のreturnが 10 回以内に必ず発動すると証明できず、ループカウンタ維持のオーバーヘッド(比較・増分・条件分岐)が残った。一方value >>= 7は単調減少するため終了は数学的に保証されており、非有界loopとすることで LLVM にはそれが認識され、よりコンパクトな機械語が生成される。

影響:エンコードスループットが約 40%回復

この最適化はレッドラインをクリアしている。高速経路の選択(非有界対有界ループ)であり、「なぜ安全に見える記法を使わないか」を完全に説明する why コメントがあり、新規貢献者にも理解可能で安全な修正が可能だ。

AI にとって特に重要だ。AI はこのコードを「改善」しようとするかもしれない。loopfor _ in 0..10へ(有界ループの方が「安全そう」だから)。DESIGN.md の記録が、この後退を直接防ぐ。

最適化 2:Tag::decodeの 1 バイト高速経路

protobufのフィールド番号 1〜15 は、任意のワイヤタイプと組み合わせて 1 バイトでエンコードされる。これは最も頻出するケースだ(protobufスタイルガイドでも高頻度フィールドはこの範囲に配置するよう推奨)。従来コードは汎用decode_varint経路を通過していた。decode_varint内部にも 1 バイト高速経路はあるが、#[inline]ヒントが十分強力でなく、LLVM はこれをper-field decodeループ内へインライン展開しないことが多かった。

解決策はTag::decode内で明示的な 1 バイト判定を追加することだ。

// 高速経路:フィールド 1-15 は 1 バイトで十分
if buf.remaining() > 0 {
    let byte = buf.chunk()[0];
    if byte < 0x80 {
        buf.advance(1);
        return Ok(Tag { field_number: (byte >> 3) as u32, wire_type: ... });
    }
}
// 低速経路:複数バイト変長整数
let v = decode_varint(buf)?;

影響:ビューデコードで+12〜29%、所有権デコードで+9〜16%

これもレッドラインに適合する。高速経路/低速経路の分離であり、why コメントがあり、低速経路は完全に影響を受けない。新規貢献者は高速経路の最適化動機を理解せずとも、低速経路を安全に修正できる。

最適化 3:strict_utf8_mappingのオプトイン

pprofcore::str::from_utf8がデコード CPU 時間の 11%を占めると示した。Rust の&str型はコンパイル時 UTF-8 不変性を有し、検証をスキップしながら&str型を維持することはできない。

解決策は検証スキップ(Rust 型安全性の破壊)ではなく、コード生成レベルでのオプション提供だ。protoutf8_validation = NONE時、文字列フィールドをString/&strではなくVec<u8>/&[u8]へマッピングする。呼び出し側がfrom_utf8(検証)を使うかfrom_utf8_unchecked(入力を信頼)を使うかを選択可能にする。

影響:connect-rustの信頼済み入力サービスでスループットが約 2 倍

この最適化の巧妙さは、ランタイム最適化(デコードループの直接変更)ではなくコード生成レベルでの型選択である点だ。生成コードの型シグネチャ(&str&[u8])を変更することで、「UTF-8 検証の有無」の決定をランタイムからコンパイル時へ移行している。

しかもこれはデフォルト無効(default-off)だ。proto2 のデフォルトはNONEであり、自動有効化すれば全 proto2 文字列フィールドの型を破壊する。この慎重さこそが可読性レッドラインの現れだ。デフォルトでの攻撃的最適化は避け、ユーザーに明示的オプトインを強いる

禁止されるもの:レッドラインを越える最適化

DESIGN.mdは明確に 4 種類の禁止最適化手段を列挙している。

手動ループ展開(Manual unrolling)for i in 0..4 { process(data[i]); }を 4 行のprocess(data[0]); process(data[1]); ...へ展開すること。protobufデコードの内側ループでは分岐予測オーバーヘッド低減に有効だが、展開後コードは「これがループだ」という意味を失う。新規貢献者は 4 行の重複コードが同一ロジックの展開だと分からず、1 行のみ修正するといったミスを犯す。

防御的#[inline(always)]:Rust の#[inline]はヒントだが、#[inline(always)]は強制だ。デコードのホットパス上に#[inline(always)]を散りばめれば関数呼び出しオーバーヘッドは回避できる。しかし代償はコード肥大化(全呼び出し点で関数本体が展開)とコンパイル時間増大。さらに重要なのは「コンパイラを信用しない」という態度の表明だ。人間維持コードでは妥当でも(人間の LLVM 判断は優れている)、AI 維持コードでは危険だ。AI には「なぜこの関数は always inline が必要で、他は不要か」という文脈が理解できない。

SIMD 命令(intrinsics)_mm_cmpeq_epi8といった SSE/AVX 命令を用いたvarintデコードや UTF-8 検証。性能向上は顕著(simdjson がこの路線)だが、SIMD コードの本質は「Rust 構文で記述されたアセンブリ」だ。対象アーキテクチャの命令セットを理解する者にしか修正できない。これは buffa の設計原則 1(Pure Rust、C 依存ゼロ)とも衝突する。SIMD 命令は Rust コードではあるが、no_stdやクロスプラットフォーム環境では挙動が一致しない。

likely()/unlikely()の回避策:Rust stable にはlikely/unlikely属性がない(nightly には#[cold]あり)。そのためコミュニティは各種回避策(#[cold]関数で低速経路をラップ、core::hint::black_boxでオプティマイザを欺くなど)を発明した。これらのトリックは LLVM 内部動作への依存度が高く、LLVM バージョンアップで無効化する恐れがある。AI にとっては完全な黒魔法だ。

レッドラインの判断基準

DESIGN.mdは精密なテストを提示している。

can a new contributor read the code, understand the fast path, and safely modify the slow path?

3 つの条件。缺一不可。

  • コードを読めるか:コードの意図が、LLVM ドキュメントや CPU マニュアルを参照せずに理解可能か
  • 高速経路を理解できるか:高速経路の発動条件が自明か(「最初のバイトが 0x80 未満=1 バイト変長整数」など)
  • 低速経路を安全に修正できるか:低速経路の修正が、高速経路の前提を破壊しないか

許容された 3 最適化はすべてこのテストをパスする。非有界ループはvalue >>= 7で必ず終了すると読めば分かる。1 バイト高速経路はbyte < 0x80の意味が変長整数を知っていれば自明。UTF-8 型マッピングはコード生成出力の型シグネチャ変更であり、ランタイムコードは無影響。

禁止された 4 最適化はすべて不合格。手動展開は展開倍率の根拠が不明。always inline はなぜ特定関数のみ強制インラインか不明。SIMD は命令の意味とプラットフォーム制約が不明。likely/unlikely は回避策が依存するコンパイラ挙動が不明。

このレッドラインが AI コーディングに意味するもの

核心へ戻ろう。buffa は Claude によって書かれたコードだ。Claude の最適化傾向は人間とは異なる。

人間は過小最適化を志向する。人間エンジニアはまず可読コードを書き、プロファイリングでボトルネックが判明してから標的を絞った最適化を行い、かつ躊躇する(「これで保守性は大丈夫か」)。

AI は過剰最適化を志向するAI には「この変更は将来の保守を困難にする」という直感がない。「デコード性能を最適化せよ」と指示すれば、訓練データ中の「高性能コード」サンプルに頻出する#[inline(always)]追加、ループ展開、SIMD 命令挿入を一気に行うだろう。

このレッドラインの真の機能は、AI が性能最適化を求められた際、「どこで最適化を止めるべきか」を教えることだ。このラインがなければ、AI は buffa のデコードループを SIMD 命令の山へ変えるかもしれない。性能は向上するが、次の AI セッション(または人間維持者)にはもはや理解も修正も不可能になる。

これが buffa の性能(ビューデコード 1,772 MiB/s。prost より 156%高速)が優れているにもかかわらず、Google のupb(C 実装、SIMD 加速)には及ばない理由だ。buffaはレッドラインを越えて極限を追求するのではなく、レッドライン内で可能な限りの性能を選ぶことを選んだ。これは意識的なトレードオフだ。AI による保守性 > 最後の 20%の性能

AI コーディング時代において、これは「いかに高速に書くか」以上に重要な設計課題かもしれない。可読性のために、どれほどの性能を犠牲にできるか? buffa の答えはこうだ。SIMD や手動展開レベルの最適化は放棄し、高速経路分離とコード生成型選択レベルの最適化は保持する。この線は極めて精密に引かれている。


8. インフラ制約:説教プロンプトに依存しない

8.1 CLAUDE.mdの 2 つの強制ルール

buffa のCLAUDE.mdには 2 つの中核ルールしかない。

ルール 1:コード生成出力を変更した後は、必ずチェックイン済みコードを再生成(task gen-wkt-types)せよ。さもなくば CI が失敗する。

ルール 2:コミット前には必ずrust-code-reviewerエージェントを実行し、Critical/High/Medium の全発見事項を解決せよ。

これは「推奨」ではない。CI が 1 を検査し、レビューアエージェントが 2 を検査する。これはインフラ制約だ。プロンプト内の「品質に注意せよ」といった注意書きではなく、ツールで AI の振る舞いを強制する。

8.2 Rust コンパイラそれ自体が第零の審査

buffa が Rust を選択した理由は性能だけではない。Rust の型チェッカは AI 生成コードに対し、迂回不可能な品質ゲートとして機能する。

  • メモリ安全性の問題 → コンパイル不可
  • ライフタイムエラー → コンパイル不可
  • Send/Sync違反 → コンパイル不可

claudes-c-compilerの unsafe ブロックゼロがこれを証明している。型チェッカは説得されず、寛容でもなく、「まあいいか」とも判断しない。buffa 内で数少ない unsafe 使用箇所(OwnedViewtransmute)についても、DESIGN.md の完全な安全性論証が、将来の AI による不変性破壊を防ぐ。

8.3 適合性テスト=究極の検証

buffa は Google 製 protobuf の二進および JSON 適合性テストスイート全集を通過した。このテストスイートは buffa チーム作成ではなく、protobuf 公式が管理し、全境界条件を網羅する権威ある検証だ。

これはつまり、AI 生成のエンコード/デコードコードが正しいかどうかは、AI の自己評価にも人間のコードレビューにも依存せず、外的で独立し、かつ権威ある検証体系に委ねられていることを意味する。「テストの品質がコードの品質を決める」という原則の最も純粋な現れだ。


9. 真のワークフローの復元

すべての証拠を総合すると、buffa の開発フローはおそらく以下の通りだ。

ステップ 1:人間(McGinniss)が設計制約を定義→DESIGN.md へ設計原則、競合比較、モジュール境界を記述

ステップ 2:AI(Claude)がコード生成+ランタイムコードを生成→制約空間内でエンコード/デコードロジックを実装

ステップ 3:自動検証→適合性テストスイートで正しさを確認

ステップ 4:AI による AI 審査→rust-code-reviewer エージェント(Opus、読み取り専用)がコード品質を審査

ステップ 5:人間がトレードオフを審査→AtomicU32 対 Cell、プレスキャン実施の可否などを決定

ステップ 6:AI による反復最適化→pprof データに基づきプロファイルガイド付き最適化を実施

ステップ 7:人間が DESIGN.md を更新→意思決定の進化、却下案、性能因果を記録

ステップ 8:ステップ 2〜7 を循環

人間と AI の役割分担に注目したい。人間は設計空間の定義と圧縮(ステップ 1, 5, 7)を担当し、AI は定義済み空間内での実装と最適化(ステップ 2, 4, 6)を担当する。検証(ステップ 3)は完全自動化され、いずれの判断にも依存しない。


10. 移植可能な 5 つの実践

buffa から抽出された AI コーディング実践は、「長期保守が必要なコード」を AI に書かせるあらゆるプロジェクトへ直接移植可能だ。

実践 1:コードより先にDESIGN.mdを記述

事後文書化ではない。AI が手を付ける前に、人間が設計原則(優先順位付き)、モジュール境界(どのファイルが何をするか)、競合分析(なぜ既存案を使わないか)を定義する。このファイルは人間向け背景説明ではなく、AI 向け意思決定フレームワークだ。

実践 2:意思決定履歴と却下案を DESIGN.md へ記録

従来ドキュメントは「何をしたか」を記録する。AI 協働ドキュメントは「なぜ他をしなかったか」も記録せねばならない。各却下案にはベンチマークデータを添付。「プレスキャン案は性能 20〜97%低下」という記述は、「プレスキャン案は良くない」という表現より 1 万倍有用だ。

実践 3:審査エージェントには最強モデル+読み取り専用権限を付与

コード生成は Sonnet(高速・低コスト)、コード審査は Opus(高精度・高コスト)を使用。審査エージェントはコード変更を禁止し、報告のみを許可。役割分離を強制する。

実践 4:AI にはコード生成で生成されるコードを書かせ、ランタイム分岐ロジックは書かせない

複雑さをコード生成段階へ前倒しする。AI は構造化入力(ディスクリプタ、仕様、スキーマ)から決定論的コードを生成し、ランタイムでは複雑な判断を行わない。これは仕様駆動開発や DSL→コードのパラダイムと完全に一致する。

実践 5:AI の自己評価に依存せず、外部権威テストスイートで検証

buffa は Google 製適合性テストを、claudes-c-compiler は GCC 恐怖テストを使用。AI 生成コードが信頼に足るのは、検証体系が完全かつ AI 自身から独立している場合に限られる。


最終判断

buffa が「AI 生成コードの本番投入」を成し得たのは、Claude が特別に優れていたからではない。Claude を取り囲む完全な制約、フィードバック、検証の構造を人間が構築したからだ。

  • DESIGN.md が意思決定空間を制約
  • rust-code-reviewer が外部審査を提供
  • 適合性テストが権威ある検証を提供
  • Rust コンパイラが型安全性を保証
  • CLAUDE.md がこれらを強制プロセスへ統合

このいずれか 1 つでも欠ければ、buffa のコード品質は著しく低下しただろう。モデル能力は必要条件ではあるが、十分条件からは程遠い。十分条件とは、人間が設計した制約構造そのものだ。

これこそが「AI によるインフラコード作成」の見本としての buffa の真の価値だ。「AI がどれほど優れたコードを書けるか」を示すものではなく、「人間がいかなる構造を構築すれば、AI に十分な品質のコードを書かせられるか」を示すものなのだ。

付録

付録 Abuffa-design-annotated.md—buffaDESIGN.mdの段落ごとの日英対訳解説 Gist[1]

付録 Brust-code-reviewer-annotated.mdconnect-rustrust-code-reviewer.mdの段落ごとの日英対訳解説 Gist[2]

参考文献

[1] buffa-design-annotated.md—buffaDESIGN.mdの段落ごとの日英対訳解説 Gist: https://gist.github.com/ZhangHanDong/f4ac670f2fdd939bc4355dad93df92b0

[2] rust-code-reviewer-annotated.mdconnect-rustrust-code-reviewer.mdの段落ごとの日英対訳解説 Gist: https://gist.github.com/ZhangHanDong/ebc9577991d0a5ce94f1d91c5d64fe40

関連記事

分享網址
AINews·AI 新聞聚合平台
© 2026 AINews. All rights reserved.