


RustのライブラリとCLIのワークスペースを、参照ツールと比べながら直す
ライブラリとCLIの両方に使う、Rustの複数crateのワークスペースをAIに直させる時に使う。失敗するテストから始め、参照ツールと結果を比べ、unwrap()を使わず、featureの組み合わせを全部テストする。
このAIルールを使うには
## 変更を受け持ちのcrateに置き、低水準のAPIは軽く保つ
このリポジトリは、ライブラリ利用者とコマンドライン利用者の両方に対応する複数crateのワークスペースとして扱ってください。編集前にワークスペースのマニフェストを読み、サポート対象の最低Rustバージョン、featureグラフ、各crateの役割、公開エントリポイントを把握してください。
低水準の基盤API(plumbing)と高水準の操作API(porcelain)を分離してください。
- 基盤APIは参照を優先し、変更可能な作業状態を明示的に公開し、利便性だけのcloneを避けること。
- 操作APIでは使いやすさのために、ある程度の割り当てや所有を許容してよい。
- 軽量なプラットフォームオブジェクトは通常、リポジトリを借用すること。
- 高コストなキャッシュは、ライフタイムがAPIを過度に支配する場合、リポジトリの状態を所有またはcloneしてよい。
既定値を設定できる分岐動作には`Options`を使用してください。操作の実行に必須であり、安全な既定値を設定できないデータには`Context`を使用してください。
関連するデータ構造や操作を所有するcrateに変更を配置してください。共通のコマンドライン動作は各バイナリに重複させず、共有CLI層に置いてください。
公開インターフェースを変更する前に、ライブラリを直接呼び出す利用者とコマンドラインの動作の両方を検討してください。
## 失敗するテストから始め、参照ツールと結果を比べる
動作の変更は、意図した理由で失敗する回帰テストから始めてください。テストは観察可能な動作に集中させ、通常の型や所有権の誤りはRustコンパイラに検出させてください。
確立されたプロトコルやファイル形式を実装する場合は、可能であれば主要な参照実装を判定基準として使用してください。両方の実装で同等のケースを実行し、意味上の違いを互換性があると決めつけずに調査してください。
変更前から存在する失敗を今回の変更によるものと誤認しないよう、編集前に既存テストを実行してください。次のテストを使い分けます。
- ローカルなアルゴリズムとデータ変換には単体テスト。
- crate境界には統合テスト。
- コマンドライン動作のエンドツーエンド確認にはjourneyテスト。
- 互換性の影響を受けやすい経路には実在するリポジトリまたは現実的なデータセット。
各アサーションメッセージには、単にアサーションが失敗したと記すのではなく、確認する不変条件を説明してください。
テスト対象の動作と、どの詳細が不可欠かを説明する明確なfixture文書を追加してください。fixtureシステムが対応している場合はドキュメンテーション文字列を優先してください。
## unwrap()をやめ、どこで何が失敗したか分かるエラーにする
プロダクションコードでは`unwrap()`を絶対に使用しないでください。テストでも避け、`?`を優先してください。`expect()`は、その条件が必ず成立する理由を簡潔に説明できる場合に限って使用してください。
利用者が何にどこで失敗したかを理解できるよう、完全なエラーチェーンを維持してください。コマンドラインバイナリでは柔軟な最上位エラー型を使用できますが、低水準crateではワークスペースの構造化エラー規約に従ってください。
エラーを追加する前に、crateのマニフェストと周辺コードを確認してください。
- そのcrateですでに新しい文脈保持型エラーフレームワークを使用している場合は、そのパターンを継続すること。
- 従来のderiveベースのエラーenumを引き続き使用している場合は、移行が明示的に作業範囲へ含まれていない限り、そのcrate内で一貫性を保つこと。
文脈保持型のパターンでは、次に従ってください。
- プロジェクトのヘルパーを通じて静的メッセージまたは書式付きメッセージを作成すること。
- 呼び出し先のエラーを伝播するときに文脈を追加すること。
- 呼び出し先のエラーがない場合は独立したメッセージを発生させること。
- コールバック境界で必要な場合に限り、型付きエラーの型情報を消去すること。
- プロジェクトの例外ラッパーを標準エラーへ変換するのは、相互運用境界に限ること。
プロジェクトの例外ラッパーが意図的に標準エラーtraitを実装していない場合は、汎用エラーAPIへ無理に渡さないでください。用意された境界メソッドで変換してください。box化された標準エラーを返すテストでは、`?`を使用する前にラッパーを変換する必要があります。
エラーチェーンを手作業で再構築せず、既存のエラー拡張traitとimportを使用してください。
## 余計なcloneを避け、リポジトリのパスをバイトのまま扱う
高コストなcloneを避けるため、低水準crateでは参照を優先してください。所有値が明示的に必要で、APIが接続された形式を受け取れない場合を除き、リポジトリに結び付いたハンドルを切り離さないでください。
内部可変性にはワークスペースの並行処理抽象化を使用してください。featureの互換性とプラットフォーム上の動作を確認せず、無関係な同期プリミティブへ置き換えないでください。
ネイティブのパスAPIが異なるエンコーディングを使うプラットフォームも含め、バージョン管理のパスをバイト指向データとして扱ってください。リポジトリのパスをOSのパスへ変換する際は、プロジェクトのパスユーティリティまたは専用の境界型だけを使用してください。
有効なリポジトリパスが有効なUnicodeであると仮定しないでください。パース、比較、保存、プロトコルコードでは情報が失われる変換を避けてください。
所有、キャッシュ、割り当てを追加する前にホットパスを測定してください。利便性は高水準層で提供し、低水準プリミティブでは制御可能性と予測可能なコストを維持してください。
## 既定のビルドだけでなく、featureの組み合わせを全部テストする
包括的なテストコマンド、ワークスペース設定の確認、lint、journeyテスト、文書ビルドにはリポジトリのタスクランナーを使用してください。単体テストだけの実行で意図的に十分な場合に限り、`cargo test`を直接使用してください。
既定ビルドと、lean構成や最小依存関係の構成を含む、サポート対象のリリース種別を検証してください。既定featureでしか動かない変更は未完成です。
small、lean、maximal、pureの各構成が存在する場合は、それらを含む、ワークスペースに文書化されたfeatureの組み合わせを実行してください。影響を受ける各組み合わせで、任意依存関係とプラットフォーム抽象化がコンパイルできることを確認してください。
生成されるfixtureの内容がプラットフォームによって変わる場合は、リポジトリのアーカイブ安定化機構を使用してください。バイト単位の安定性が重要な場合は、プラットフォーム上で生成したfixtureより、パッケージ化されたfixtureアーカイブを優先してください。
macOSまたはWindowsでのアーカイブテスト用にプラットフォーム固有の環境フラグが定義されている場合は、文書どおり正確に適用してください。他のプラットフォームで影響を受けるテストを暗黙にスキップしないでください。
利用者に見えるCLI変更についてはエンドツーエンドのコマンドテストを実行し、実用的な場合は参照実装と比較してください。
## changelogに使えるコミットを書き、互換性を壊す変更に印を付ける
目的が明確なconventional commitを使用してください。
- 変更がchangelogの対象となる場合に限り、conventional prefixを付けること。
- 利用者に見える機能と修正には`feat:`と`fix:`を使用すること。
- 内部リファクタリングと雑務ではprefixを省略すること。
- すべての破壊的変更に`!`接尾辞を付けること。
利用者に見える目的を示すコミット件名を書き、プロジェクトが求める場合はissueまたはレビューの参照を含めてください。
破壊的変更が複数のcrateに影響し、1つのコミットメッセージで全影響を正確に説明できない場合はcrateごとに分割してください。破壊的なAPI変更を最初のコミットに置き、下流側の対応を後続コミットに置いてください。
リリース自動化がコミットメッセージからバージョンやchangelogを生成する場合は、コミットメッセージをリリース入力として扱ってください。
コード変更が直接影響する場合は、高水準ガイド、コントリビューション手順、開発ノート、crate状態記録、安定性文書を更新してください。
プロジェクトがより厳しい対象を定義していない限り、主要CI環境で利用できる参照ツールのバージョンを互換性の基準線として使用してください。
## 最後に、crateの層からコミットメッセージまでチェックリストで確かめる
完了前に、次を行ってください。
1. 変更が基盤APIと操作APIのどちらに属するかを特定する。
2. 類似するcrateで確立されたパターンを調べる。
3. エラー処理がそのcrateの現在のフレームワークに一致することを確認する。
4. プロダクション用の`unwrap()`が導入されていないことを検証する。
5. 影響を受けるfeatureの全組み合わせとリリース種別を確認する。
6. ライブラリの呼び出し元とコマンドライン利用者を別々に検討する。
7. 必要に応じて対象を絞ったテスト、ワークスペーステスト、journeyテスト、互換性テストを実行する。
8. バイト指向パスがプラットフォーム間で情報を失わないことを確認する。
9. 新たなclone、切り離し、キャッシュ、同期に測定可能な必要性があるかレビューする。
10. 直接関連する文書を更新する。
11. コミットメッセージがchangelogへの影響と破壊的変更の影響を正しく説明していることを確認する。
未テストのfeatureセット、プラットフォーム、参照実装との比較、リリース種別がある場合は、不足している前提条件を正確に報告してください。既定featureの単体テストだけを根拠に、ワークスペース全体の互換性を主張しないでください。
