機能をリリースしてから6か月後にリポジトリを開いても、多くのことは再構成できます。アーキテクチャをたどり、スキーマを確認し、テストを読み、どの行が変更されたのかを正確に把握できます。
ただし通常、再構成できないのは、なぜその行が必要になったのかを決めた会話です。
コードだけでは、ある検証ルールが存在する理由が、1社の顧客が不正な形式のエクスポートを送ってくるためだとはわかりません。奇妙に見える再試行ポリシーが、下流システムでの重複トランザクションを防ぐためのものだとも説明してくれません。よりクリーンなインターフェース案がアクセシビリティテストの後に却下されたことも、サービス境界がエンジニアリング上の好みではなく契約上の制約を反映していることも、コードからは見えてきません。
Gitはコードの履歴を保存するのには非常に優れています。意図まで保存できるのは、チームがその意図を意識的に書き残し、実装と結びつけ続けた場合だけです。
このギャップは、昔からソフトウェアエンジニアリングの一部でした。AIコーディングツールは、それをより目立たせています。システムはリポジトリ内のすべてのファイルを読み、あらゆるシンボルを追跡し、技術的にはもっともらしいパッチを生成できます。それでも、解いている問題そのものが間違っていることがあります。
問題は、コードが誤解を招くことではありません。コードが答えている問いの範囲が、より狭いのです。
エンジニアリングの真実を形づくる5つの層
意味のあるソフトウェア変更の多くは、5つの異なる証拠の層に依存しています。
- 意図 — ユーザー、顧客、あるいはビジネスは、どんな結果を求めているのか。これは仕様書、チケット、サポートでのやり取り、会議メモなどに存在することがあります。
- 制約 — 何を壊してはいけないのか。互換性の約束、セキュリティ境界、規制、契約、予算、締め切りは、しばしばリポジトリの外にあります。
- 実装 — システムは現在どのように動いているのか。コード、テスト、スキーマ、依存関係、デプロイ設定がこの層を構成します。
- 実行時の証拠 — 実際のシステムでは何が起きているのか。ログ、トレース、メトリクス、本番データ、インシデントレポートは、コード上ではもっともらしく見える前提に反することがあります。
- 意思決定の履歴 — なぜ現在のアプローチが選ばれたのか。Pull Request、設計に関する議論、却下された代替案、過去のインシデントにその答えがあります。
リポジトリが最も強いのは3つ目の層です。他の層の一部も含まれていますが、それらを完全に表現できるほど十分であることはほとんどありません。
これが重要なのは、ソフトウェアの障害がしばしば層同士の境界で現れるからです。実装は古くなった仕様には合っている。修正はチケットの要件は満たしているが、運用上の制約に違反している。テストが通るのは、そこに昨日の前提が埋め込まれているからにすぎない。コード内部では整合していても、本番データは誰にも文書化されていないパターンに従っている。
ローカルには正しいパッチでも、変更としては間違っていることがあります。
リポジトリだけでは答えられないこと
あるユーザーがドキュメントを編集し、その更新後の文を検索したのに、結果には古い版しか表示されないとします。「検索結果をすぐに更新してほしい」というのは、一見すると明確な要望です。リポジトリを見れば着手できそうな箇所はいくつか見つかりますが、それだけで正しい修正内容を定義することはできません。
| Question | Likely source |
|---|---|
| どの版のドキュメントが正とされるのか? | ソースドキュメントと改訂履歴 |
| 古いテキストはどこに残っているのか? | 同期ログ、抽出結果、検索インデックス、またはキャッシュ |
| このプロダクトにおいて「すぐに」とは何を意味するのか? | プロダクトの約束またはサービス目標 |
| ドキュメントの権限は内容変更と一緒に変わったのか? | ソース権限と監査履歴 |
| 古い結果は特定のユーザー、ソース、またはリージョンに限られるのか? | リクエストトレースと本番メトリクス |
検索コードを見れば、結果がどのように返されるかは説明できるかもしれません。しかし、本当の不具合が同期遅延なのか、古い抽出結果なのか、キャッシュ無効化なのか、権限伝播なのか、あるいはそもそもプロダクトで定義されていない期待値なのかまでは、それだけでは分かりません。
この区別は、成熟したシステムになるほどいっそう重要になります。古く見えるフィールドが、実はレガシークライアントをまだ支えているかもしれません。重複しているように見えるサービスが、権限要件の異なるデータを分離しているのかもしれません。過剰に見えるチェックが、現チームは知らない本番障害の、コード上に残る唯一の痕跡であることもあります。
複雑さを削ることには価値があります。だが、複雑さに見せかけた履歴を削るのは高くつきます。
文脈を増やしても、なお間違った答えになることがある
分かりやすい解決策は、AIにもっと多くの材料を与えることです。つまり、リポジトリ全体、すべてのチケット、すべての文書、すべてのメッセージ、そしてすべてのログです。
それで得られるのはアクセスであって、理解ではありません。
情報源は古くなっていたり、互いに矛盾していたり、推測に基づいていたり、異なる読者向けに書かれていたりします。ブレインストーミングの内容が、承認済みの仕様より優先されるべきではありません。6か月前の要件が、昨日のプロダクト判断を黙って上書きしてよいはずもありません。本番ログは、それを生んだリリース、環境、コードパスと結び付けて扱う必要があります。顧客からの要望も、適用範囲を確認せずに普遍的な要件として扱うべきではありません。
したがって、本格的なコンテキストシステムには、単なる検索以上のものが必要です。少なくとも次の点について推論できなければなりません。
- Authority: どの情報源が要件を定義してよいのか?
- Recency: どの情報が最新で、何がすでに置き換えられているのか?
- Provenance: それぞれの主張、制約、結論はどこから来たのか?
- Relationships: どの issue、release、customer、dataset、code path が互いに結び付いているのか?
- Permissions: このタスクで利用でき、この人に見せてよい情報源はどれか?
コンテキストは、トークンの山ではありません。時間、権威、境界を持つグラフです。
より多くのコンテキストが生むべきなのは、より多くの証拠であって、証拠のない自信の増大ではありません。
本当の作業単位は変更である
エディタやコーディングツールがファイル中心に構成されているのは、私たちが変更する対象がファイルだからです。一方、エンジニアリングチームは変更を中心に組織されています。
変更は理由から始まります。それが要件となり、コードやデータに触れ、レビューを通過し、本番に届き、新たな証拠を生みます。こうした段階が分断されたままだと、将来のあらゆる作業はまた一から発掘調査をやり直すことになります。
実際のソフトウェアを扱うAIシステムも、このライフサイクルに従うべきです。
実装前には、依頼内容、関連する制約、そして矛盾する情報源があればそれを特定できるべきです。それが不具合修正なのか、期待される挙動の変更なのか、それとも新しい契約の導入なのかを把握している必要があります。
実装中には、意味のある選択それぞれを証拠と結び付けるべきです。なぜこのモジュールなのか? なぜこのマイグレーション戦略なのか? なぜこの分岐を残すのか? その説明は、コードを生んだチャットの外でも生き残らなければなりません。
実装後は、検証結果、レビューでの判断、新たに判明した制約をその変更に紐づけておくべきです。そうしなければ、次の担当者—あるいは次のAIセッション—がそれらをまた発見し直すことになります。
これこそが、リポジトリを編集できるツールと、エンジニアリング業務に参加できるシステムの違いです。
AIは再構築の負担を減らすべきであって、判断をなくすべきではない
より良いコンテキストは、ときに自律的なソフトウェア開発への道として語られます。ですが、目先の価値はそこまで劇的なものではなく、もっと実用的です。つまり、変更を加える前に現実を再構築するコストを下げることです。
AIは、元の要件を関連するコードのすぐそばに持ってくることができます。異例の安全策の理由を説明するインシデントを浮かび上がらせることもできます。失敗しているメトリクスを、それを変えたリリースに結びつけることもできます。さらに、実装が始まる前に、2つの信頼できる情報源が食い違っていることを示すこともできます。
そうした能力は、エンジニアリング上の判断を不要にするものではありません。判断を、より十分な情報に基づいたものにするのです。
どのトレードオフを受け入れられるか、要件が完全かどうか、そしてリリースがどれだけのリスクを負えるかは、依然として人が判断しなければなりません。システムは、根拠を見えるようにし、推論を検証可能にするべきです。洗練されたパッチの陰に不確実性を隠すべきではありません。
基準は「コードを生成できるか?」ではありません。
基準は「なぜ今これが正しい変更なのかを説明できるか?」です。
リポジトリ認識から、業務認識へ
コーディング支援ツールが最初に役立つようになったのは、開発者の目の前にあるファイルを理解できるようになったときでした。次の大きな一歩が、リポジトリ認識です。関連するコードを見つけ、シンボルをたどり、プロジェクト全体に変更を適用できるようになりました。
次の一歩は、リポジトリの周囲にある業務を認識することです。
それは、コードを、その実装を求めた仕様、それを明確にした会話、それに疑義を投げかけた本番環境の証拠、そして後から記憶されるべき判断と結びつけることを意味します。同時に、無関係なコンテキスト、古くなったコンテキスト、あるいはユーザーの権限外にあるコンテキストを除外することも意味します。
Dvinaを構築する中で、これは私たちが何度も立ち返る考えの一つです。業務は、単一のファイル、アプリケーション、会話の中だけで起こるものではありません。意味は、それらのあいだのつながりの中にあり、そのつながりが時間とともにどう変化するかの中にあります。
リポジトリは依然として不可欠です。システムの振る舞いに関する、実行可能な信頼できる情報源だからです。ただし、それはプロダクトの意図、運用上の現実、組織の記憶に関する完全な情報源ではありません。
全体像が、何が作られるかを変える
コードしかないとき、自然に出てくる問いはこうです。
このシステムに適合する変更は何か?
より広いコンテキストがあれば、問いはこう変わります。
このシステム、この要件、この履歴、そしてこの瞬間に適合する変更は何か?
その2つ目の問いは、制約がリグレッションになる前に捉えます。レビュー担当者には、その実装の背景にある考え方を伝えられます。新しくチームに加わったメンバーが、システムがなぜ今のような形になっているのかを理解する助けにもなります。そしてAIに、地に足のついた役割を与えます。エディタの中の神託ではなく、作業全体にまたがって根拠を組み立てられる参加者として。
あなたのリポジトリが、物語のすべてだったことは一度もありません。
ここでの機会は、その残りの部分も読み取り、しかも根拠を示せるシステムを築くことです。

