


低水準のライブラリを、公開APIを壊さずに小さく直す
低水準のシステムライブラリをAIに直させる時に使う。変更は小さくし、頼まれない限り公開APIとABIを変えず、ビルドと変えたサブシステムのテストを動かし、メモリが足りない時も安全に失敗させ、リモートへのpushはしない。
このAIルールを使うには
## 変更は小さくし、頼まれない限り公開APIとABIを変えない
安定した公開APIとABIを厳格な制約として扱う。
### 編集前
- 自明でない作業の前に、リポジトリのビルド、テスト、設定、コントリビューション、リリースに関する文書を読む。
- 依頼された変更を担うサブシステムまたは論点を一つに特定する。
- 変更する各ファイルのローカルな慣例に従う。
- 無関係なユーザー変更と未追跡の生成物をそのまま保つ。
### 変更の境界
- 大規模な書き換えより、最小限の差分と段階的な追加変更を優先する。
- 無関係なコードの名前、順序、書式を変えたり、整理したりしない。
- 明示的に依頼されない限り、新しい公開インターフェースを追加しない。
- 明示的に依頼されない限り、既存の公開インターフェースまたはバイナリ契約を変更、廃止しない。
- 任意機能の挙動、機能を減らしたビルド、コンパイル時の機能ガードを保つ。
- ビルドまたは機能の既定値を暗黙に変えない。
一見不自然なコードが互換性の境界にある場合、テスト、履歴、周辺の挙動が別の根拠を示すまでは、実際の境界条件を処理している可能性があると考える。
## 決まった流れでビルドし、変えたサブシステムのテストを動かす
専門的な確認に頼る前に、リポジトリ標準の設定、コンパイル、テストの流れを使う。
### 既定の手順
1. 指定されたビルドディレクトリを設定または再設定する。
2. 影響を受ける対象をコンパイルする。
3. 現在の段階に適したテストスイートを実行する。
4. ビルドによって新しい警告が発生していないことを確認する。
ビルドディレクトリが存在しない場合は、再設定専用の経路ではなく初期設定を使う。コードに実質的な変更を加えるたびに、変更した対象を再ビルドする。
### 対象別の最低限の確認
- 変換または文字組版のロジックでは、専用の挙動テストスイートを実行する。
- 縮小、サブセット化、グラフ処理では、対応するサブシステムのテストスイートを実行する。
- 公開インターフェースの作業では、APIテストスイートを実行する。
- コマンドラインツールの作業では、対象ツールを再ビルドし、小さな代表サンプルで動作させる。
- バグ修正またはパーサー強化では、可能な限り最も近い回帰テスト、ファジング入力、ファジング対象、期待結果のいずれかを追加または更新する。
対象別の確認は反復を速めるが、共有の挙動やリリース準備に影響する場合の広範な検証を置き換えるものではない。
## 直す場所をサブシステムごとに選び、プロジェクトのやり方に合わせる
コードを変更する場所を選ぶ前に、隣接する責務を理解する。
### 責務の境界
- コアライブラリの挙動を、インストールされるツール、ベンチマーク、文書、言語バインディング、実験的コンポーネントと分離する。
- グラフ用ヘルパーが縮小処理の挙動に関与する場合は、その処理系の一部として扱う。
- ラスター、ベクター、グラフィックスなどの大きすぎる翻訳単位では、分岐を増やすのではなく、目的を絞ったヘルパーを抽出し、責務ごとに分割する。
- 言語統合では、ビルド連携を変える前に、ネイティブ側のビルド定義と言語パッケージのマニフェストの両方を確認する。
### 既存の慣例
- プロジェクトで確立された、割り当て、エラー、分岐予測、ヌルオブジェクト、コンテナ、ユーティリティのパターンを使う。
- プロジェクトのラッパーが移植性や安全性を組み込んでいる場合、プラットフォームの生のプリミティブよりそのラッパーを優先する。
- プロジェクトに確立済みのコンテナとユーティリティがある場合、コアコードへ外部のコンテナライブラリを導入しない。
- 公開インターフェースの文書は、リポジトリで慣例となっているソースまたは文書の場所へ追加する。
解析、キャッシュ、ヘルパーの重複が広がり始めたら共通化する。ただし、限定的な修正を無関係なアーキテクチャの書き換えへ変えない。
## メモリ不足や悪意ある入力でも、対応する全部の環境で安全に失敗させる
割り当て失敗、悪意ある入力、コンパイラの多様性、機能を減らしたビルドを、対応範囲の通常部分として扱う。
### 割り当てとパーサーの安全性
- メモリ逼迫時に新しいコードが安全に失敗するよう、既存の割り当てとエラー処理のパターンに従う。
- 入力処理を強化する前に、既存のパーサー防護策とファジング基盤を確認する。
- 割り当て失敗を注入した場合の最低合格条件は、クラッシュ、範囲外アクセス、メモリ破損が起きないことである。
- 実験的なコンポーネントでは、メモリ逼迫時に可能な範囲で早期に失敗する挙動を許容する。
- コンポーネントの契約が求めない限り、割り当て失敗後の途中結果を保つことだけを目的とする複雑なロールバック処理を追加しない。
### 移植性
- コンパイラ、オペレーティングシステム、アーキテクチャのビット幅、クロスビルド、機能を減らしたビルドの後退を実際のバグとして扱う。
- プロジェクトが対応するツールチェーンと整数幅の全体で前提を検証する。
- コンパイル時の機能ガードと代替経路を実際に動かして確認する。
- 低水準コードを簡略化する際は、元の複雑さがアラインメント、オーバーフロー、寿命、エイリアシング、プラットフォーム固有の挙動を処理していたか確認する。
元の失敗を示せない修正だけの変更より、再現可能な回帰テストを優先する。
## 生成されたテーブルは手で直さず、ジェネレーターから作り直す
すべてのビルド記述と生成結果をソース変更と同期させる。
### ビルドシステムの変更
- オプション、設定概要、インストール対象ツール、テスト、依存するビルド対象を一緒に更新する。
- パッケージングまたはクロスビルドに影響する場合、主要なものだけを変えず、対応するすべてのビルドシステムを確認する。
- タスクが既定値の変更を明示的に求めない限り、オプションの既定値を保つ。
- 影響を受ける任意機能について、有効な構成と無効な構成の両方を検証する。
### 生成データ
- ジェネレーター、元データ、ビルド自動化の流れを変更してから、結果を再生成する。
- タスクが明示的に求めない限り、生成されたテーブルや索引を手作業で編集しない。
- 生成結果、ローカルのテスト素材、フォント、未追跡の生成物を破棄可能だと決めつけない。
- 再生成された差分に、予期しない広がりや非決定的な変更がないか確認する。
ジェネレーターの変更が公開データまたはテストの期待値に影響する場合、同じ限定的な変更の中で関連するテストと文書を更新する。
## 公開APIは頼まれた時だけ足し、バージョンの印と文書を付ける
ユーザーから見える挙動を、コード、文書、バージョン管理、ビルド連携を一体化した変更として扱う。
### 公開インターフェースの関門
- 公開宣言は内部実装ファイルではなく、指定された公開ヘッダーまたはモジュールに置く。
- 依頼が明示的に許可した場合に限り、新しい公開範囲を追加する。
- 新しいインターフェースが許可された場合、リポジトリで必須のバージョンマーカーとリリースノート項目を追加する。
- 生成されるセクション索引、文書マニフェスト、参照一覧は、承認済みの手順で更新する。
- 互換性を壊す変更が明示的に承認されない限り、バイナリ配置、シンボルの可視性、呼出規約、ソース互換性を保つ。
### ユーザーから見える挙動
- ライブラリまたはインストールされるツールを通じて機能が見えるようになった場合、関連文書を更新する。
- インストールとビルド連携を、新しく公開された挙動と同期させる。
- 公開インターフェースの文書と生成される索引を、ローカルな慣例が定める場所に置く。
- 合格状態にすることだけを目的に失敗中のテストを無効化しない。正当な例外とその影響を記録する。
## 先に根本の原因を突き止め、pushせずにコミットする
変更を完了として示す前に、原因と結果を立証する。
### 作業方法
1. 可能な場合は問題を再現する。
2. 修正を書く前に根本原因を理解する。
3. 重要な曖昧さが残る場合、推測せず確認する。
4. 異常に複雑に見えるコードを簡略化する前に履歴を確認する。
5. 最も近い回帰テストを追加または更新する。
6. 変更したサブシステム、影響を受ける構成、より広い挙動を検証する。
### コミットの規律
- コード、ビルドロジック、生成結果、テスト入力をコミットする前に、完全なテストスイートを実行する。
- 文書のみ、または継続的インテグレーションのみの変更は、それらの領域へ影響し得ない場合に限り、完全なテストを省略できる。省略したことを報告する。
- 各コミットは一つの問題または論点に集中させる。
- リモートリポジトリへpushしない。pushは権限を持つ人に任せる。
- リポジトリのサブシステム接頭辞、帰属トレーラー、メッセージ規約を使う。
- 複数行のコミットメッセージでは、エスケープされた改行列ではなく、ファイルまたはエディタ経由の入力を使う。
- 根本原因、修正、テストは、実際に行った作業で裏付けられる場合に限り記述する。
引き渡しでは、変更範囲、実行したテスト、警告、未対応の構成、未解決のリスク、実施していない検証を報告する。
