検索/ビルドが厳しいリポジトリで、AIに警告ゼロのコードと正直な報告をさせる

ビルドが厳しいリポジトリで、AIに警告ゼロのコードと正直な報告をさせる

ビルドの検査が厳しいリポジトリで、AIのコーディングエージェントを動かす時に使う。pushの前にビルドと検証を通し、コミットの決まりを守り、安全なコードを書き、すべての主張をコードと照らして確かめる。

このAIルールを使うには
## 作業中は変えたモジュールだけビルドし、pushの前は検証を全部通す グローバルにインストールされたツールチェーンではなく、リポジトリにコミットされているビルドラッパーを使う。そうすることで、すべてのコントリビューターとエージェントが同じ方法でビルドできる。素早く反復するには、マルチモジュール全体をビルドするのではなく、変更したモジュールだけをビルド・テストする。通常は静的解析チェックを省略する「fast」プロファイルと、テストを省略するフラグが用意されている。ただしこれらのショートカットはローカルでの反復作業専用であり、それ以外では使わない。 コミット前には、影響を受けるモジュールをチェック有効の状態でフルコンパイルし、警告がゼロであることを確認しなければならない。チェックを省略したビルドの結果だけを根拠にコミットしてはいけない。プッシュ前には、プロジェクトの検証ステップを実行する。このステップは差分を認識し、変更を分類したうえで(ドキュメントのみ・単一モジュール・ルート/設定変更のいずれか)、影響を受けるモジュールとその依存関係だけをビルドする。ただしルートのビルド設定を変更した場合は、フルビルドが強制される。検証を通ると短命なマーカーが残され、プッシュフックがそれをチェックする。プッシュ前には自分のブランチ上で古くなったパイプライン実行をキャンセルし、共有のランナーを無駄遣いしないようにする。 ## Gitのフックを飛ばさず、AIの署名を入れない短いコミットメッセージを書く 作業セッションを開始するたびに、リポジトリのフックパスを有効化する。セッションはアーカイブされたり復元されたりすることがあるため、これは一度きりの設定ではない。フックを迂回してはならない——検証をスキップするフラグも、署名を迂回する手段も使わない。フックはライセンスヘッダーの有無、未使用・重複インポートがないこと、コミットメッセージの形式を強制する。 コミットの件名は `type(scope): description` の形式で書き、feat・fix・docs・refactor・test・chore などのタイプを使う。メッセージは空行を除いて最大2行までとし、1行目はおよそ100文字未満に収める。トレーラー行は一切追加しない——共同作者トレーラーも、署名トレーラーも、そして何よりAIが作成した・AIが生成したことを示す署名の類も禁止で、コミットメッセージフックがそれらを拒否する。バグ修正はメイン開発ブランチへ直接反映し、新機能はフィーチャーブランチを使う。 ## まわりのコードの書き方に合わせ、警告はすべてエラーとして扱う 周囲のコードのスタイルに合わせ、目的を達成するために妥当な範囲で最小限の変更にとどめる。すべてのソースファイルに必須のライセンスヘッダーを付ける。継承よりコンポジションを優先する。クローズ可能なリソースにはすべて try-with-resources 構文を使う。公開APIからはnullではなくオプショナルなラッパーを返す。ローカル型推論は、文脈から型が明らかな場合にのみ使う。長いif/else連鎖よりswitch式やパターンマッチを優先する。適合する場面ではシールド型やイミュータブルなレコード型を使う。ジェネリクスには必ず型パラメータを指定する。オーバーライドするメソッドにはアノテーションを付ける。ループ内での文字列構築にはビルダーを使う。変更不可のコレクションは標準のファクトリヘルパーで構築する。 コンパイラの警告・非推奨警告・静的解析の警告は、すべてエラーとして扱う。ビルドはすべてのlintチェックを有効にした状態で実行され、未使用・重複インポートがあると失敗する。したがって出荷には警告ゼロが必須となる。新しい警告抑制アノテーションを追加する場合は、なぜそれが避けられないのかを説明するコメントを必ず添える。コードコメントは、それが明らかに誤りであると証明できない限り削除しない。 ## リソースは作った側だけが閉じ、容量の上限を無視しない 以下の不変条件は、機能の規模にかかわらずリリースをブロックする。どれだけ小さな変更であっても、これらのいずれかに違反すればリリースは止まる。 **所有権** —— リソースを解放・クローズ・シャットダウンできるのは、そのリソースを作成した者だけである。所有権は明示的に追跡し、外部から渡されたエグゼキューター・プール・接続を受け取る場合は、ライフサイクル呼び出しが自分で作成していないものを破壊できないようラップする。あらゆる開始処理には、リスナー・ハンドラー・フックなどの登録をすべて解除する対称的な停止処理が必要であり、すべてのバッファは、正常終了・エラーを問わずすべての終端パスで解放されなければならない。 **終端パスの完全性** —— すべての終了経路(成功・失敗・キャンセル・タイムアウト・拒否)は、システムを完了状態にして終わらなければならない。futureを解決し、フラグをリセットし、バッファを解放する。クローズ処理はcompare-and-setや「一度だけクローズする」パターンで冪等にする。ガード条件がカウンターを参照するなら、どこかのパスで実際にそのカウンターをインクリメントしていなければならない。 **バックプレッシャー** —— 拒否シグナルや容量シグナルを無視してはならない。上限付きofferの戻り値は必ずチェックし、実行拒否を処理し、部分書き込みを処理する。すべてのキャッシュとバッファにはサイズ上限か退避ポリシーが必要である。外部入力によって埋められる無制限の構造は、サービス拒否攻撃の経路になる。 ## 境界ごとに入力を確かめ、実際に動いている物だけを知らせる これらの不変条件も、機能の規模にかかわらずリリースをブロックする。 **境界の安全性** —— あらゆる境界(通信、ファイルシステム、シェル、URL、HTTP)において、解釈する前に検証・エンコードを行う。テキストのデコードは完全にフレーミングされたメッセージからのみ行い、生の転送チャンクから直接デコードしてはならない。ファイルシステムのパスは正規化・検証する——解決し、正規化したうえで、結果が意図したルート配下にとどまっていることを確認し、親ディレクトリを指すセグメント・セパレーター・空のセグメントは拒否する。シェル呼び出しには引数配列を使い、動的なパス部分やクエリ部分はURLエンコードし、コンテンツタイプは大文字小文字を区別せずに照合し、境界でパース失敗を捕捉して、不正な入力に対してはサーバーエラーではなくクライアントエラーを返す。 **実行時の真実** —— 公開・報告してよいのは確認済みの実行時状態のみであり、設定上の意図やクラスパス上に存在するというだけの状態を公開してはならない。機能フラグやディスカバリーエンドポイントは、実際に稼働している内容を反映しなければならず、起動に失敗した場合は機能の公開を抑制する必要がある。 **セキュリティ** —— 状態を変更する操作や管理系の窓口はすべて、明示的な認証・認可を必要とし、デフォルトでは拒否とする。整合性検証は「失敗したら閉じる(fail closed)」でなければならず、「失敗しても開く(fail open)」モードを使う場合は明示的な設定とし、デフォルトにしてはならない。安全でないデフォルト設定を本番経路に出荷してはならない——使う場合は明示的なオプトインと起動時警告の背後に置く——サンプルコードもこの方針を後退させてはならない。 **モード間の一貫性** —— ある機能が複数の呼び出しモード(同期・非同期・ストリーム)で存在する場合、その意味論——エラー処理、ライフサイクルイベント、可観測性、完了時の挙動——は一致していなければならない。意図的な差異があれば文書化しテストする。ある経路に機能を追加したら、すべての経路で検証する。 ## 重いバグには回帰テストを付け、中身のないテストを禁止する 深刻度の高いバグ修正には、失敗するシナリオを再現する回帰テストを必ず添える。必須のCIレーンでは、プレースホルダーや何もしないテストは許されない——自明な真理を主張するだけのテストは禁止であり、各テストは自らが検証すると主張する具体的な挙動を検証しなければならない。エンドツーエンドテストは、単にサーバーが起動したことではなく、テスト対象の機能そのものを検証しなければならない。 不安定なテストを隔離せざるを得ない場合は、担当者・期限・追跡用のissueを必ず設定し、スケジュール実行のレーンでは引き続き実行させる。ワークフローのパスフィルターには、変更対象領域で挙動に影響するスクリプトや設定ファイルの場所をすべて含めなければならない。そうしないと、まさに変更したコードをCIが黙ってスキップしてしまう。 ## サンプルは、偽物でごまかさず本物のAPIを呼ぶ サンプルアプリやサンプルコードはユーザーが最初に目にするものなので、スタブではなく本番品質でなければならない。実演すると謳っているインテグレーションは、実際にそれを使う。実在する機能を名乗るサンプルであれば、インメモリの代替物でごまかすのではなく、その本物のAPIを実際に呼び出さなければならない。本物のインテグレーションを動かせない場合は、それを隠したモックを出荷するのではなく、正直にそう伝えて助けを求める。「実際のアプリではここでこれを呼び出す」といったコメントは、そのサンプルが本物のアプリになっていないという危険信号である。 サードパーティのライブラリに対するインテグレーションコードを書く前に、そのライブラリの実際のAPIを読む——依存アーティファクトを調べ、公開シグネチャを読む——そしてメソッド呼び出しを想像で書いてはならない。手動での配線よりも、ライブラリが提供するオートコンフィグレーションを優先する。すべてのサンプルはコンパイルが通り、何をするのか・どう実行するのか・重要なコードが何を示しているのかを説明する短いREADMEを添えて出荷する。差し替え可能な単一の依存関係こそが抽象化の要点である場合に、バックエンドのバリエーションごとに個別のサンプルを作ってはならない。 ## 書く前に、すべての主張をコードかGitの履歴で確かめる ドキュメント・変更履歴の項目・コミットメッセージ・ユーザー向けテキストに書くあらゆる事実の主張は、コードまたはgitの履歴に実際に存在するものと対応していなければならない。機能・メソッド名・機能一覧・数値指標・修正コミットをでっち上げてはならない。捏造は一つひとつが信用を損ない、後から追跡してロールバックする手間を生む。 数値に関する主張には根拠が必要であり、書く前に実際のコードと照らして件数を確認する。変更履歴の「修正」「追加」の項目は実際のコミットと一致していなければならない。ログでその変更を検索し、下書きにコミットハッシュを残してから本文に格上げする。コミットが見つからなければ、その修正は実際には起きていない。APIの表面に関する主張は、まず実際のソース(フィールド一覧、メソッド名)を読むことを要求する。何かが出荷された・配線された・統合されたという主張には、単なるサービスプロバイダーインターフェースやリファレンス実装ではなく、ユーザーの操作から到達する経路上に実際の本番の利用者が存在することが必要である。事実を検証できない場合は、それを削除するか、未検証であると明示したうえで公開前に確認を求める。自分が何かをでっち上げていると気づいたら、そこで止まり、コミットせず、その虚偽の主張を事実と照らして報告し、そのコピーすべてを修正する。 ## 決まり同士の食い違いを言い訳にせず、途中で完了と言わない 事実面での誠実さに加えて、行動面での不誠実さも避ける——個々の発言は弁明可能でも、全体としては誤解を招くような構成のことである。楽な方の道を正当化するために、2つのルールが対立しているかのように捏造してはならない。ルール同士が対立しているように見える場合は、より困難で安全な作業を要求する方のルールがほぼ常に優先される。矛盾するガイドラインが存在するのに、都合の良い方だけをつまみ食いして引用してはならない。矛盾は隠さず表に出して解消する。ルールが「黙って直せ」と定めている状況について、状況をそのまま報告するだけで済ませてはならない——共有パイプラインが壊れているなら、その壊れ具合を説明するのではなく、直したうえで成功を報告する。「もともと壊れていた」「自分が起こした劣化ではない」は言い訳ではなく単なる状況説明にすぎない。共有ブランチに対する責任は、変更を加えるたびに引き継がれる。 ルールがすでに義務付けている行動について、あらためて許可を求めてはならない——尋ねるより実行する方が良く、義務付けられた作業をそのまま行い、方向転換を指示されるまで残っている項目に取り組み続ける。作業の途中で勝ち誇って完了を宣言してはならない。正直なシグナルとは、終わっていないことも終わったことと並べて示すものである。簡潔さと正しさ・安全性のルールが対立する場合は、安全性のルールが勝つ——「冗長だが正しい」は「簡潔だが安全でない」に勝る。こうしたパターンのいずれかに気づいたら、それを名指しし、そのルールが本来義務付けている作業を実際に行う。謝罪は作業の代わりにはならないことを忘れてはならない。 ## 決めた事や計画を、チャットだけでなく共有のナレッジベースに残す チャットは永続しないため、共有ナレッジベースを構造化された成果物の永続的な置き場所として扱う。構造化された作業に着手する前に、まずそこを読んで過去の意思決定・設計・文脈を確認し、成果を会話の中だけに残すのではなく、永続的な結果としてそこへ書き戻す。ドキュメントの種類ごとに置き場所を振り分ける——アーキテクチャ上の意思決定や設計記録、フェーズ分けした計画、ランブックやオンコール手順、監査・分析・引き継ぎ資料には、それぞれ指定の置き場所がある。リファレンス文書はコードと一緒に生きたまま出荷し、ディレクトリ単位の仕様書はそのディレクトリのREADMEに置く。 個人のハンドルネーム、ロールプレイ上の名前、マシン固有のパスといった、私的またはローカル限定の識別子は、コミットする成果物には一切含めない。テストやサンプルでは中立的なプレースホルダー名を使い、実在の識別子を使うのは、それが本当に公開アカウントを指す場合に限る。永続的な保存先が使えない場合は、共有可能なリンクに切り替えて記録しておき、後のセッションが正しい場所へ格納できるようにする。