adversarial-rust について
adversarial-rustは、他のプログラミングパラダイムのパターンを持ち込んだ既存Rustコードを、アーキテクチャレベルでレビューしリファクタリングするスキルです。codex-rsワークスペースに基づくルールと例で、所有権、型、エラー処理、反復処理、並行処理を扱います。
主な機能
- 01Rustのアーキテクチャレビュー
- 02所有権と型のリファクタリング指針
- 03ResultとOptionによるエラー処理
- 04反復処理と動的ディスパッチの指針
- 05非同期並行処理のレビュー規則
- 06codex-rsに基づく例
活用シーン
- 01Rust内のJava風パターンのリファクタリング
- 02cloneに依存した所有権設計の整理
- 03番兵値やunwrapによるエラー処理の置き換え
- 04非同期コードのブロッキングやロックのレビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pproenca/ dot-skills --skill adversarial-rustインストール後、Claude Code で/adversarial-rustを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
AGENTS.mdmetadata.jsonassets/templates/_template.mdreferences/_sections.mdarch-default-literal-over-builder.mdarch-drop-di-trait-single-impl.mdarch-free-functions-over-manager-struct.mdarch-no-deref-inheritance.mdarch-public-fields-over-getter-ceremony.mdconc-blocking-pool-over-async-cpu-fanout.mdconc-narrow-locks-before-await.mdconc-own-spawned-task-handles.mdconc-spawn-blocking-over-blocking-async.mddyn-enum-over-box-dyn-closed-set.mddyn-generics-over-boxed-callbacks.mdflow-no-catch-unwind-try-catch.mdflow-option-over-sentinel-values.mdflow-result-over-unwrap-expected.mdflow-thiserror-library-anyhow-application.mditer-combinator-over-index-loop.mditer-stay-lazy-single-collect.mdown-id-map-over-self-referential.mdown-no-rc-refcell-object-graph.mdown-restructure-over-clone.mdtype-enum-over-bool-string-state.mdtype-newtype-parse-dont-validate.mdtype-result-over-parallel-options.mdtype-split-option-god-struct.md詳細
Adversarial Rust
Rust を対象とした、アーキテクチャレベルの敵対的レビューとリファクタリングです。グリーンフィールド向けのイディオムスキルが「今、どのツールを使うべきか?」に答えるのに対し、このスキルが扱うのは、すでに存在し、誤ったメンタルモデルを持ち込んでしまったコードです。Java/C# のオブジェクトやインターフェース、ガベージコレクション言語の共有前提のグラフ、例外、C スタイルのループやセンチネル、切り離された Promise による並行処理などが対象です。コードがどのパラダイムに反しているかを示し、イディオマティックな Rust に戻すリファクタリングを提示します。
各ルールの根拠は、単一の本番コードベースである codex-rs workspace(github.com/openai/codex、コミット f1affbac5e 時点の codex-rs/、約 125 個のクレート/約 2,500 個の Rust ファイル)です。各ルールの「正しい」側には、そのコードベースで実際に採用されている方法を示します。適用を強制する根拠は、そのワークスペースの lint 設定(unwrap_used、redundant_clone、needless_collect、await_holding_lock など、約 30 項目を deny)です。また、例外として扱うものには、実際に設けられている例外を示します。そのため、「適用しないとき」は仮定の話ではありません。有能なモデルがすでに正しく扱える内容については、ルールを設けていません。
適用する場面
- スタイルだけでなく、アーキテクチャの観点から既存の Rust をレビューまたはリファクタリングするとき。「本当にイディオマティックにして」「Rust なのに Java みたいに感じるのはなぜ?」など
- 移植によって持ち込まれた過剰な作法を整理するとき。実装が 1 つしかない依存性注入用トレイト、
Derefで模倣した継承、状態を持たない*Manager/*Service構造体、ゲッター/セッターの定型コード、すべての構造体に用意されたビルダーなど - 所有権に無理が生じているコードを整理するとき。コンパイルが通るまであちこちに
.clone()を追加したコード、Rc<RefCell<T>>のオブジェクトグラフ、自己参照構造体の試みなど - 貧弱なデータ表現を修正するとき。ブール値/文字列による状態機械、並列する
Optionフィールド、ドメイン上の意味を持つ生のプリミティブ、serde の境界を越えて漏れ出すOptionだらけの巨大構造体など - 例外スタイルの制御フローをなくすとき。想定される失敗への
unwrap、センチネルを返す処理、try/catch 代わりのcatch_unwind、ライブラリ API の表面に現れるanyhowなど - 習慣的な間接参照を減らすとき。閉じた集合に対する
Box<dyn Trait>、ボックス化されたコールバック引数、インデックスを使うループ、各段階でcollect()する連鎖など - 持ち込まれた並行処理の習慣を改めるとき。
async fn内のブロッキング呼び出し、.awaitをまたいで保持されるガード、CPU バウンド処理のための非同期タスクの大量生成、起動後に追跡しないtokio::spawnなど
新しい Rust を書く際のグリーンフィールドの「どのパターン、どのクレート、どの設計規律を使うか」という判断(非同期キャンセル、エラー enum の設計、サンドボックス化、テストアーキテクチャなど)には、代わりに openai-codex-rust-patterns を使用してください。このスキルは、同じコードベースから導き出した、診断とレイヤー整理に特化した対となるスキルです。
ルールのカテゴリ
| # | カテゴリ | プレフィックス | 取り除くべき異質なモデル |
|---|---|---|---|
| 1 | エンタープライズ的な過剰作法と偽の OO | arch- | DI トレイト、Deref による継承、Manager 構造体、ゲッターの定型処理、自己言及的なビルダー → 具象型、委譲、モジュール関数、公開フィールド、構造体リテラル |
| 2 | 所有権を活用せず、無理に扱う | own- | コンパイルのための clone、Rc グラフ、自己参照構造体 → 意図を持った clone、所有権を持つ ID キー付きマップ、単一の所有者 |
| 3 | 貧弱で文字列頼みのデータ | type- | bool/String による状態、並列する Option、生のプリミティブ、外部に漏れ出す巨大構造体 → データを保持する enum、新しい型、wire 形式からドメイン型への一度限りの変換 |
| 4 | 例外スタイルの制御フロー | flow- | 処理の代わりに使う unwrap、センチネル、catch_unwind、不透明なライブラリエラー → Result と ?、Option、thiserror の enum、境界部分での anyhow |
| 5 | 習慣による動的ディスパッチ | dyn- | 閉じた集合に対する Box、ボックス化されたコールバック引数 → タグ付き enum、API でのジェネリックな Fn、リスナーの代わりにチャネル |
| 6 | 命令型の反復処理 | iter- | インデックスループ、可変アキュムレーター、各段階での collect → 名前付きコンビネーター、1 つの遅延チェーン、Result への collect |
| 7 | 別のランタイムから持ち込まれた並行処理 | conc- | 非同期処理内のブロッキング、await をまたぐガード、CPU 処理の非同期ファンアウト、孤立した spawn → spawn_blocking、ロック範囲の限定、上限付きスレッドプール、所有権を持つハンドル |
クイックリファレンス
1. エンタープライズ的な形式主義と見せかけのオブジェクト指向
arch-drop-di-trait-single-impl— 実装が1つしかないDIトレイトは削除します。codex-rsでは具象型のModelClientとSessionを使いますarch-no-deref-inheritance— codex-rsの18個すべてのDeref実装は、ニュータイプまたはスマートポインターです。継承階層を模倣するものはありませんarch-free-functions-over-manager-struct— ステートレスな機能はモジュール関数(git-utils、apply-patch)で表します。*Managerと名乗るなら、状態を所有する必要がありますarch-public-fields-over-getter-ceremony—Configとすべてのプロトコル型は、フィールドがすべてpubです。アクセサーがあるのは、不変条件が存在する場合だけですarch-default-literal-over-builder—..Default::default()を使う構造体リテラルは1,787件、ビルダーは16件です。段階的な構築が必要な場合にのみ、ビルダーを使う価値があります
2. 所有権に抗うのではなく、活用する
own-restructure-over-clone— 残っているクローンは意図して使われています(Copy型のID、Arcの参照カウント増加、ロックのスナップショット)。コンパイルを通すためだけのクローンはデータを分岐させますown-no-rc-refcell-object-graph— 約2,500ファイルにRc<RefCell>はありません。代わりに、対象を絞ったMutexフィールド、チャネル、またはIDマップを使いますown-id-map-over-self-referential— グラフはHashMap<ThreadId, Arc<CodexThread>>に格納します。相互参照には参照ではなく、常にIDを使います
3. データの貧血と文字列頼み
type-enum-over-bool-string-state— バリアントがそれぞれのフィールドを持ちます(SandboxPolicy)。外部サンドボックスのバリアントでは、はい/いいえさえboolではなくNetworkAccessで型付けしますtype-result-over-parallel-options— 形状ごとに1つのOptionを使うのは、CodexAuthでは適切ではありません。見つかった/見つからない/失敗したを表すにはResult<Option<T>, E>を使いますtype-newtype-parse-dont-validate— 一度だけパースしてThreadId/AgentPathに変換します。不変条件がないため、モデル名はStringのままにしますtype-split-option-god-struct—ConfigToml(97個中91個のフィールドがOptions)は、ワイヤー上では問題ありません。一度解決して、より豊かなConfigに変換します
4. 例外スタイルの制御フロー
flow-result-over-unwrap-expected— ワークスペース全体でunwrap_used/expect_usedを禁止しています。例外には#[expect]と明記された不変条件が必要ですflow-option-over-sentinel-values— 検索結果はOptionで返します。-1を使うのは、OSの終了コードとの境界だけですflow-no-catch-unwind-try-catch— codex-rsの本番コードでの使用箇所はすべて、外部の障害ドメインを監視しています。想定される失敗を捕捉する用途ではありませんflow-thiserror-library-anyhow-application— レイヤーごとにCodexErr/ApiError/TransportErrorを使い、main()ではanyhowを使います
5. 慣習的な動的ディスパッチ
dyn-enum-over-box-dyn-closed-set—Op/EventMsg/TurnItemはenumです。dynを使うのは、他の実装が実行時に拡張するツールレジストリーだけですdyn-generics-over-boxed-callbacks— APIではジェネリックなF: Fnを使い、保存する場合に限ってボックス化します。リスナー登録の代わりにチャネルを使います
6. 命令型の反復処理
iter-combinator-over-index-loop—manual_*リンツを13個禁止しています。forループを使うのは、await、副作用、データとしてのインデックス、FFIが必要な場合ですiter-stay-lazy-single-collect— 遅延評価のチェーンを1つ使います。collect::<Result<Vec<_>, _>>()は、失敗し得るパイプラインでの定番のイディオムです(本番コードで49箇所に使用)
7. 別のランタイムに由来する並行処理
conc-spawn-blocking-over-blocking-async—spawn_blockingを約50箇所で使用しています。対象は git、ファイルロック、zstd、OAuth サーバーですconc-narrow-locks-before-await— tokio のガードであっても.awaitをまたいではいけない場合があります。スナップショットを取得するか、アトミック性の理由を添えて#[expect]を使いますconc-blocking-pool-over-async-cpu-fanout— rayon は使いません。CPU 処理のファンアウトは、1つのspawn_blockingの配下で有界な OS スレッド上で行いますconc-own-spawned-task-handles—AbortOnDropHandleと子のCancellationTokenを使用します。中断時はキャンセル → 猶予期間 → 強制終了の順です
使い方
レビュー対象のコードに該当する兆候が見つかったら、リファレンスファイルを読んでください。各ルールでは、なじみのないパターンを挙げ、なぜ Rust がそれを拒否するのかを説明し、実際の codex-rs の名前と固定されたコミットのコードベースへのパーマリンクを使ってリファクタリング方法を示します。変更予算の範囲で、できるだけ根本的なリファクタリングを優先してください。所有権を再設計する方が clone を散在させるより効果的ですし、DI トレイトを削除する方が、それを介してモックするより効果的です。すべての例は Rust 1.86(2021 edition)でコンパイルできます。
関連スキル
openai-codex-rust-patterns— 同じ codex-rs ワークスペースから抽出した、新規開発向けの対応スキルです。本番用 Rust を記述する際に選ぶべきパターン(非同期キャンセル、エラー列挙型の設計、サンドボックス化、テスト、ワークスペースのレイアウト)をまとめています。実装方針の判断にはこちらを、厳密なレビューや過剰な儀式を取り除くリファクタリングにはこのスキルを使用してください。こちらの複数のルールでは、冗長さを取り除いた後に関連スキルへ引き継ぎます(flow-thiserror-library-anyhow-application→ 関連スキルのerrors-ルール、flow-result-over-unwrap-expected→defensive-deny-unwrap-workspace-wide、arch-drop-di-trait-single-impl→ テスト用のシーム)。
リファレンスファイル
| ファイル | 説明 |
|---|---|
| references/_sections.md | カテゴリーの定義と順序 |
| assets/templates/_template.md | 新しいルール用のテンプレート |
| metadata.json | バージョンとソースへの参照 |