この記事でできること
AIエージェントにコードを書かせていると、ファイルは少しずつ大きくなっていきます。エージェントのファイル読み取りツールには1回で読める量の上限があり、それを超えたファイルは何回かに分けて読まれます。読んだ内容はその後の会話にも残るので、大きいファイルほどコンテキストを多く使います。
個人開発している技術記事キュレーションサービスDevPickでは、上限を超えたファイルを分割しても、数日後には別のファイルが上限を超えていました。そこで、上限を超えるファイルを新しく作らせず、すでに超えているファイルもそれ以上大きくさせない検査をCIに入れました。
この記事では、その検査の決めごとを点検リストの形でまとめます。実装のコードは載せず、作るときに決めておくべきことに絞ります。
背景:上限を超えたファイルは何回も読まれる
DevPickで使っているAIエージェントの読み取りツールは、1回に最大800行、または46,080バイトまでしか読みません。これを超えるファイルを全部確認しようとすると、エージェントは範囲を変えて何回も読み直します。
実際にエージェントのログを数えると、874行あったテストファイルの1つは、1つのセッションの中で範囲を変えて読み直された回数が、直近7日間で21回ありました。上限を超えたファイルは、少し直すだけでも毎回このように分けて読まれます。
点検1:上限の値は、使っているツールの読み取り上限から決める
上限の値は「何行くらいが読みやすいか」という好みではなく、使っているエージェントの読み取りツールが1回で読める量から決めます。DevPickでは800行と46,080バイトの両方を上限にして、どちらか一方でも超えたら違反にしています。行数だけを見ると、1行が長いファイルがすり抜けるためです。
- 上限の値は、ツールの種類やバージョンで変わります。自分の環境で、どこまで1回で読まれるかを確かめてから決めます
- 分割するときの目標は、上限ちょうどではなく600〜700行程度にします。上限ぎりぎりで分けると、テストを数件足しただけでまた超えます
- 画像・ロックファイル・自動生成されたファイルのように、エージェントが全文を読まないものは対象から外します
点検2:すでに超えているファイルは、上限付きの例外リストに登録する
すでに上限を超えているファイルは、例外リストに登録したうえで検査を始めます。分割はその後、1本ずつ進めれば十分です。
例外リストには、ファイルごとに次の4つを書きます。
- ファイルのパス
- 許容する最大行数
- 許容する最大バイト数
- 例外にしている理由(関連するIssue番号など)
最大行数・最大バイト数には、登録した時点の実測値をそのまま入れます。「とりあえず大きめの値」を入れると、その分だけ肥大化を許すことになります。
点検3:例外リストは、縮むことしか許さない
例外リストに登録したファイルは「今の大きさまでは許す」という扱いです。そこから大きくなる方向の変更はすべて拒否し、小さくなる方向だけを認めます。このような一方向にしか動かない仕組みは、ラチェットと呼ばれます。
検査で拒否するのは次の4つです。
- 例外リストに無いファイルが上限を超えた
- 例外リストにあるファイルが、登録した最大値を超えた
- 例外リストにあるファイルが小さくなったのに、登録した最大値が古いまま
- 例外リストにあるファイルが上限内に収まったのに、リストに残っている
3つ目と4つ目が大事です。ファイルが小さくなっても最大値を書き換えなければ、次の変更でまた元の大きさまで戻せてしまいます。DevPickでは、リストの最大値を実測値まで縮め、解消したファイルをリストから消すコマンドを用意して、違反メッセージでそのコマンドを案内しています。
点検4:例外リストの比較は、PRの変更前の状態と行う
例外リスト自体もリポジトリの中のファイルなので、PRの中で書き換えられます。ファイルを大きくしたPRが、同じPRの中でリストの最大値も引き上げてしまえば、検査は通ってしまいます。
これを防ぐため、PRの検査では、変更前(マージ先のコミット)の例外リストと比べます。
- 変更前のリストに無いファイルを、新しく例外に追加することは拒否する
- 変更前のリストより最大値を引き上げることは拒否する
- 変更前の時点では上限内だったファイルを、PRで大きくしてから例外に登録することは拒否する
- 変更前のコミットを取得できなかったときは、検査を通さずに失敗させる
最後の項目は、取得に失敗したときに比較を飛ばして合格にすると、そのPRだけ何でも通ってしまうためです。
点検5:増えて当然のファイルは、別の決まりにする
要件定義書や設計書のように、機能を足すたびに追記するのが正しい文書もあります。こうした文書にコードと同じ「縮むことしか許さない」決まりを当てはめると、機能を足すPRがすべて止まります。
そこで、設計文書だけは別の決まりにしています。
- 例外リストの最大値は、実測値に1〜2割の余裕を足した上限にする。上限までの追記は認め、小さくなっても最大値の書き換えは求めない
- 上限を引き上げるときは、1回のPRで15%までにする。理由の欄にIssue番号と理由を書き直さないと拒否する
- 新しく作る設計文書は、例外にせず上限内に収める
点検6:分割するときに、ファイル名に依存している箇所を探す
例外リストのファイルを分割すると、ファイル名が変わります。CIが変更されたファイルに応じて実行するテストを選んでいる場合、元のファイル名が書かれた箇所が残っていると、分割後のテストが実行されなくなります。
- CIの設定やテストを選ぶスクリプトに、分割前のファイル名が書かれていないか検索する
- 分割した両方のファイルで使う準備処理は、コピーせず共有の場所に移す
- 分割の前後でテストの件数が減っていないことを確かめる
まとめ
- 上限は、使っているエージェントの読み取りツールが1回で読める量から決める。行数とバイト数の両方を見る
- すでに超えているファイルは、登録時点の実測値で例外リストに入れてから検査を始める
- 例外リストは縮むことしか許さない。小さくなったら最大値を縮め、解消したら消すことまで検査する
- 例外リストの比較はPRの変更前の状態と行い、比較できないときは失敗させる
- 追記するのが正しい設計文書は、余裕のある上限と、1回あたりの引き上げ幅の制限で管理する
分割を繰り返しても終わらなかった経緯と、設計文書だけ別の決まりにした理由は、Zenn版に書いています。