はじめに
最近、AI Coding Agentを使って実際のソフトウェア開発を続けていると、以前とは少し違う問題に気づくようになりました。それは「AIのコーディング能力が足りない」という問題ではなく、AIが既存のリポジトリを正しく理解するまでのコストが非常に大きいという問題です。人間の開発者であれば、プロジェクトを数日、数週間、あるいは数か月見ていれば、「この機能はどこにあるのか」「なぜこの実装になっているのか」「このクラスを変更すると何が壊れるのか」「この処理にはどんな業務ルールがあるのか」といった情報を頭の中に蓄積できます。しかし、AI Coding Agentは、タスクごとに限られたコンテキストを使ってリポジトリを理解しなければなりません。プロジェクト全体を毎回読み込ませれば、コンテキストを大量に消費し、時間もコストも増えます。それだけではなく、情報量が増えれば増えるほど、本当に重要な情報と無関係な情報の区別も難しくなります。そこで、「AIにもっと大きなContext Windowを与える」のではなく、そもそもAIが少ないコンテキストで正しくプロジェクトを理解できるように、リポジトリそのものを設計するという考え方に至りました。
従来のソフトウェアアーキテクチャだけでは足りないのではないか
これまでのソフトウェア開発では、コードをどのように整理するかについて多くの優れた考え方が存在します。iOSならMVC、MVVM、TCA、Clean Architectureなどがあり、バックエンドならClean Architecture、DDD、Hexagonal Architecture、Dependency Inversion、Repository Patternなどがあります。これらは今でも非常に重要です。しかし、これらのアーキテクチャが主に解決している問題は、ソフトウェアがどのように動作し、責務や依存関係をどのように整理するかという問題です。
一方、AI Coding Agentには別の問題があります。
「このリポジトリを、AIはどの順番で理解すればよいのか?」
たとえば、人間にとっては次の構造が十分に理解しやすいかもしれません。
View
↓
ViewModel
↓
UseCase
↓
Repository
↓
API
これはRuntime Architectureとしては非常に分かりやすい構造です。
しかし、AIにとっては別の情報も必要になります。
Task
↓
Project Map
↓
Domain
↓
Interface / Contract
↓
Invariant
↓
ADR
↓
Test
↓
Implementation
こちらは「ソフトウェアがどう動くか」ではなく、AIがどう理解するかを表しています。
そこで、従来のSoftware Architectureとは別に、AIがリポジトリを理解するためのAI Context Architectureという層を考えることにしました。
AI Context Architectureとは何か
私が現在考えているモデルは、大きく次のようになります。
AI Coding Agent
│
▼
┌─────────────────────────────┐
│ AI Context Architecture │
│ │
│ Agent Rules │
│ Project Map │
│ Domain Knowledge │
│ Contracts / Interfaces │
│ Invariants │
│ ADRs │
│ Dependency / Impact │
│ Context Index │
│ Tests │
└──────────────┬──────────────┘
│
▼
┌─────────────────────────────┐
│ Software Architecture │
│ │
│ MVVM / TCA / Clean │
│ DDD / Hexagonal │
│ Dependency Inversion │
│ Repository │
│ etc. │
└──────────────┬──────────────┘
│
▼
Code
つまり、AI時代だからといってMVC、MVVM、DDD、Clean Architectureなどを捨てるのではありません。従来のSoftware Architectureの上に、AIがそのSoftware Architectureを理解するためのContext Architectureを追加するという考え方です。
これは「新しいMVVM」を作るという話ではありません。
AI-Friendlyなリポジトリとは、特定のRuntime Architectureを強制するものではなく、どのようなRuntime Architectureを採用していても、AIがそこを効率よく理解できる状態を作るための追加レイヤーです。
一番重要な原則は「Small Context → Large Understanding」
この考え方の中心にあるのが、
Small Context → Large Understanding
という原則です。
AIにプロジェクト全体を読ませることを目標にするのではなく、必要な情報だけを段階的に与えることで、少ないContextから大きな理解を得ることを目指します。
理想的なAIの読み方は、次のようになります。
Task
↓
AGENTS.md
↓
Project Map
↓
Domain Map
↓
Interface / Contract
↓
Invariant / ADR
↓
Relevant Tests
↓
Dependency / Impact
↓
Implementation
↓
Modify
↓
Verify
たとえば「音声認識がネットワーク切断時に動かなくなった」というタスクを受けた場合、最初からプロジェクト全体のSwiftやPythonコードを全部読む必要はありません。
まずプロジェクトマップを読み、「Voice」というDomainを見つけます。その後、VoiceのDomain Documentを読み、そこで定義されているInterfaceやContractを読み、ネットワーク障害時のInvariantを確認し、関連するTestを確認します。それでも原因が分からない場合にだけ、具体的なImplementationへ入っていきます。
これによって、AIは「プロジェクト全体を読む」のではなく、必要な部分を順番に深掘りすることができます。
Knowledge LayerとCode Layer
この考え方をリポジトリ構造として考えると、プロジェクトには大きく2つの層が存在します。
Repository
├── Knowledge Layer
│ ├── Agent Rules
│ ├── Project Map
│ ├── Architecture
│ ├── Domain Knowledge
│ ├── Contracts
│ ├── Invariants
│ ├── ADR
│ └── Context Index
│
└── Code Layer
├── iOS
├── Backend
├── Web
├── Worker
└── Infrastructure
Knowledge Layerは「このプロジェクトは何なのか」「どこに何があるのか」「なぜこの設計になっているのか」「何を変更してはいけないのか」を説明します。
Code Layerは実際の実装を持ちます。
これまでのプロジェクトでは、ドキュメントはコードの補助資料として扱われることが多かったと思います。しかしAI時代には、Knowledge LayerそのものがAIにとって重要なインターフェースになると考えています。
AGENTS.md は「百科事典」ではなく「ナビゲーター」
AI Coding Agent向けのルールをすべて1つの巨大なファイルに書く方法もあります。しかし、それでは結局Contextが巨大になってしまいます。
そのため、AGENTS.md は「すべてを説明するファイル」ではなく、AIが次にどこへ行けばよいかを教えるナビゲーターとして設計します。
たとえば、
AGENTS.md
↓
PROJECT_MAP.md
↓
DOMAIN
↓
CONTRACT
↓
TEST
↓
IMPLEMENTATION
というルートを示します。
詳細な内容は、それぞれのドキュメントへ分離します。
この考え方は非常に重要です。
AGENTS.mdがすべてを説明するのではなく、AGENTS.mdがAIを正しい場所へ案内する。
Project Map
プロジェクトには、AIが最初に読める非常に短いProject Mapを用意します。
Project Mapの目的は、プロジェクトのすべてを説明することではありません。
目的は、
「何がどこにあるのか」を短時間で理解させること
です。
例えば、
Voice
→ ios/Features/Voice/
→ backend/features/voice/
Navigation
→ ios/Features/Navigation/
→ backend/features/navigation/
Account
→ ios/Features/Account/
→ backend/features/account/
という情報があれば、AIは最初から全リポジトリを探索する必要がありません。
Feature / Domain単位でコードを整理する
AIにとって重要なのは、「どの技術のファイルなのか」だけではなく、どのビジネス機能に属しているのかです。
そのため、以下のような構造を優先します。
features/
├── voice/
├── navigation/
├── account/
└── billing/
一方で、
controllers/
services/
models/
utils/
のような技術種別だけで整理すると、1つの機能に関係するコードが複数の場所に分散しやすくなります。
AIが「Voice機能を修正したい」と考えたとき、
features/voice/
という境界が明確なら、Contextの範囲をかなり小さくできます。
InterfaceとImplementationを分離する
AI-Friendly Repositoryで特に重要なのが、InterfaceとImplementationの分離です。
例えばiOSなら、
protocol SpeechRecognizer {
func start() async throws
func stop() async
}
のように、まず「何ができるか」を定義します。
BackendならPythonのProtocolなどを使って、
from typing import Protocol
class SpeechService(Protocol):
async def transcribe(
self,
audio: bytes,
) -> str:
...
のように、「このサービスが提供する能力」を明示します。
これによってAIは、最初からOpenAI SDK、HTTP Client、FFmpegなどの具体的なImplementationを大量に読む必要がありません。
ただし、ここで重要なのは、
Implementationを「正しい」と仮定するわけではない
ということです。
正しい考え方は、
必要になるまでImplementationを展開しない
です。
Testが失敗した場合や、Contractと実際の挙動が一致しない場合には、AIはImplementationまで進んで原因を調査します。
Interfaceは「関数名一覧」ではない
単純に、
protocol VoiceService {
func start()
func stop()
}
と書くだけでは不十分です。
AIにとって本当に重要なのは、そのInterfaceのContractです。
例えば、
/// Converts spoken audio into a validated command.
///
/// Contract:
/// - Must not execute commands directly.
/// - Provider-specific errors must be translated.
/// - Network failure may trigger fallback.
/// - Returned commands must be validated.
protocol VoiceCommandService {
func process(
audio: AudioBuffer
) async throws -> VoiceCommand
}
このように、
- 何をするのか
- 何を返すのか
- どんな失敗があるのか
- どんな副作用があるのか
- 何をしてはいけないのか
まで明示すると、非常に小さなContextでAIが多くのことを理解できます。
Invariantを明示する
もう一つ重要なのが、実装とは独立した業務ルールです。
例えば音声システムで、
20秒間無音
→ Voice Session終了
ネットワーク障害
→ Fallback
未検証のCommand
→ 実行禁止
高リスク操作
→ ユーザー確認必須
というルールがあるとします。
これはImplementationの中だけに存在させてはいけません。
これらはInvariantとして明示します。
なぜなら、AIが実装を変更すること自体は問題ではありませんが、このルールを破ってしまうことが問題だからです。
つまり、
Implementation
→ 変更可能
Invariant
→ 原則として変更不可
という関係になります。
ADRで「なぜ」を残す
AIはコードを見て、
「この処理、もっと簡単にできない?」
と判断することがあります。
しかし、その複雑さに意味がある場合があります。
例えば、
WebSocket
→ REST Streaming
→ Local Fallback
という構成があったとします。
AIから見ると、
「WebSocketだけでいいのでは?」
と思うかもしれません。
そこでADRに、
Decision:
WebSocketをPrimary Transportとして使用する。
Reason:
低レイテンシと双方向通信が必要。
Fallback:
REST Streaming → Local Processing
と記録しておけば、AIは「なぜこの複雑さが存在するのか」を理解できます。
ADRは、過去の開発者が持っていた暗黙知を、AIが利用可能なKnowledgeに変換する仕組みだと考えています。
Dependency MapとImpact Map
AIがコード変更を安全に行うには、
「これは誰に使われているのか?」
だけでなく、
「これを変更すると何が影響を受けるのか?」
も重要です。
例えば、
VoiceService
├── SpeechService
├── LLMService
└── CommandValidator
さらに、
SpeechService
Used By:
- VoiceSession
- ConversationService
- VoiceRouter
という情報があれば、変更前に影響範囲を把握できます。
理想的には、Symbol、Reference、Dependency、Call GraphなどはAIが自動で取得・生成できるようにしたいと考えています。
一方で、
- なぜこの依存関係が必要なのか
- なぜこの境界を越えてはいけないのか
- なぜこの実装を選んだのか
といった情報は人間が明示する価値があります。
Testは「検証」だけではなく「Executable Knowledge」
AIにとってTestは非常に重要です。
例えば、
func testNetworkFailureFallsBackToLocalRecognition()
というTest名だけでも、
ネットワーク障害時にはLocal RecognitionへFallbackする必要がある
という意味を伝えることができます。
そのため、Testは単なる品質保証ではなく、システムの期待動作を機械的に表現したKnowledgeとして扱います。
AIによる変更は、
Contract
+
Invariant
+
Test
+
Implementation
のすべてを考慮したうえで行われるべきだと考えています。
AI-Friendlyとは「抽象化を増やすこと」ではない
ここはかなり重要です。
AI-Friendly Repositoryと聞くと、
Protocolを増やす
Adapterを増やす
Factoryを増やす
Interfaceを増やす
Documentを増やす
ほど良いように思えてしまいます。
しかし、それは逆効果になる可能性があります。
例えば、
UserService
IUserService
AbstractUserService
UserServiceProtocol
UserServiceFactory
UserServiceAdapter
UserServiceFacade
のように抽象化が増えすぎると、今度はAIが関係を理解するためにさらに多くのContextを必要とします。
したがって、
AI-Friendly ≠ Abstraction-Heavy
です。
目指すべきなのは、
明確な境界、高い情報密度、適切な抽象化
です。
AI-Friendly Architectureは特定のFrameworkを強制しない
この考え方はiOSだけに限定されません。
iOSなら、
MVVM
TCA
Clean Architecture
Feature-based Architecture
などを採用できます。
Backendなら、
DDD
Clean Architecture
Hexagonal Architecture
Vertical Slice
Dependency Inversion
などを採用できます。
重要なのは、
どのRuntime Architectureを採用するかではなく、そのRuntime ArchitectureをAIが理解・探索・検証しやすい形にすること
です。
つまり、
AI Context Architecture
+
Runtime Architecture
という関係になります。
iOS + FastAPIの実例
この考え方を、実際のリポジトリとしてまとめたサンプルを公開しています。
Armkas/ai-native-repo-template
このリポジトリでは、
spec/
template/
examples/
という構成を採用しています。
spec/にはAI-Friendly Repositoryの設計原則をまとめ、template/には新しいプロジェクトへ導入するための基本構造を用意し、examples/にはiOS、FastAPI、そしてiOS + Backendを組み合わせたMixed Exampleを用意しています。
特にMixed Exampleでは、単純にiOSとBackendのコードを並べるだけではなく、同じDomainを両方のシステムからどのように扱うか、InterfaceやContractをどのように定義するか、AIがどの順番でContextを辿るのか、という点を示すことを目指しています。
今後の課題
現在の段階では、主に「AI-Friendly Repositoryをどう設計するか」というSpecificationとTemplateの整理が中心です。
次の段階では、これを単なる思想やドキュメントではなく、実際に検証・生成できるToolingへ進化させたいと考えています。
例えば、
anr init
anr index
anr map
anr validate
のようなCLIを用意し、
Source Code
↓
AST / Symbol Analysis
↓
Dependency Analysis
↓
Context Index
↓
Architecture Validation
という流れで、AI-Friendlyな情報を自動生成・検証できるようにすることが考えられます。
特に重要なのは、AIが理解するための情報を人間がすべて手動でメンテナンスすることです。これは規模が大きくなるほど破綻しやすいため、
機械が知っている情報は機械が生成し、人間はIntent・Business Rule・Architecture Decisionを記述する
という役割分担が理想だと考えています。
まとめ
AI時代のソフトウェア開発では、「AIにどれだけ大きなContext Windowを与えられるか」だけではなく、
AIが正しいContextを、正しい順番で取得できるようにリポジトリを設計できているか
が非常に重要になると考えています。
従来のMVVM、DDD、Clean Architecture、Hexagonal Architecture、Dependency Inversionなどは、AI時代になったから不要になるわけではありません。
むしろ、
Software Architecture
+
AI Context Architecture
として組み合わせることで、これまで人間の頭の中にしか存在しなかった、
どこに何があるか
なぜこうなっているか
何をしてよいか
何をしてはいけないか
何を変更すると影響するか
どうやって正しさを確認するか
という情報を、AIが利用できる形に変換できるのではないかと考えています。
最終的な目標は、
AIにプロジェクト全体を読ませることではありません。
そうではなく、
プロジェクト全体を読まなくても、AIがプロジェクト全体を正しく理解できる状態を作ること
です。
まだこの考え方は完成された標準ではありません。
しかし、AI Coding Agentがソフトウェア開発の一部になっていくのであれば、これからのリポジトリには、コードだけではなくAIが理解するための構造化されたKnowledge Layerも必要になるのではないか、と考えています。
ぜひ、実際のプロジェクトや異なる言語・アーキテクチャで試してみて、改善点や異なる考え方があれば共有していただけるとうれしいです。