リポジトリ = 知識ベース
はじめに
Agent-First Development における鉄則がある:
リポジトリにないものは、エージェントにとって存在しない。
Slack で共有された設計判断、口頭で伝えられた規約、誰かの頭の中にあるドメイン知識。これらはエージェントにとっては「存在しない」。エージェントが参照できるのはリポジトリ内のファイルだけだ。
なぜリポジトリに集約するのか
エージェントの視界
エージェントが見えるもの:
[リポジトリ内のファイル] ← これがすべて
エージェントが見えないもの:
- Slack の会話
- Notion のページ
- 誰かの頭の中の知識
- 過去のミーティングでの合意
- 「暗黙の了解」
人間にとっても良い
リポジトリに知識を集約することは、エージェントのためだけではない:
- 新メンバーのオンボーディング: 「あの人に聞いて」が不要になる
- バス係数の改善: 特定の人に依存する知識が減る
- 意思決定の追跡可能性: なぜそう決めたかの記録が残る
- 非同期コミュニケーション: タイムゾーンや勤務時間に依存しない
docs/ ディレクトリの構造設計
推奨構造
docs/
architecture/ # アーキテクチャの設計判断
overview.md # システム全体像
data-flow.md # データフロー
auth-design.md # 認証・認可の設計
conventions/ # コーディング規約、命名規則
coding-standards.md
naming-conventions.md
error-handling.md
design/ # 機能ごとの設計ドキュメント
patient-management.md
appointment-scheduling.md
billing-integration.md
exec-plans/ # 実装計画(エージェントへの指示書)
patient-search-api.md
notification-system.md
references/ # 外部仕様、API ドキュメント
fhir-resource-mapping.md
insurance-api-spec.md
guides/ # 手順書
adding-new-feature.md
database-migration.md
deployment.md
adr/ # Architecture Decision Records
001-use-postgresql.md
002-clean-architecture.md
003-event-driven-notifications.md
各ディレクトリの役割
architecture/
システムレベルの設計判断。変更頻度は低いが、重要度は高い。エージェントが「なぜこの構造なのか」を理解するための基盤。
conventions/
コーディング規約やパターン。エージェントが一貫したコードを生成するために参照する。理想的には linter ルールと対応させる。
design/
機能ごとの設計ドキュメント。ビジネスロジックの背景、ユースケース、制約を記述する。エージェントがドメイン知識を得る主要なソース。
exec-plans/
具体的な実装計画。エージェントに渡す「作業指示書」として機能する。完了後はアーカイブするか design/ に統合する。
adr/ (Architecture Decision Records)
「なぜその技術を選んだのか」「なぜこの設計にしたのか」を記録する。エージェントが設計の背景を理解し、一貫した判断を下すために重要。
AGENTS.md: テーブルオブコンテンツとしての設計
アンチパターン: 百科事典型
# 悪い例: すべてを AGENTS.md に書く
## コーディング規約
(200 行の規約...)
## アーキテクチャ
(300 行の設計説明...)
## API 仕様
(500 行の仕様...)
この問題:
- ファイルが巨大になり、更新が困難
- エージェントが重要な情報を見落とす
- 情報の重複が発生し、矛盾が生まれる
推奨パターン: ポインタ型
# AGENTS.md
## Overview
raica IDP のバックエンド。患者管理、予約管理、請求管理を提供する
医療 SaaS の中核システム。
## Quick Start
- `make build` - ビルド
- `make test` - テスト実行
- `make lint` - lint 実行
- `make migrate` - DB マイグレーション
## Directory Structure
src/
domain/ → ドメインモデル。外部パッケージへの依存禁止。
api/ → HTTP ハンドラ。domain の interface を通じてデータアクセス。
infra/ → DB 接続、外部 API クライアント。
pkg/ → 共有ユーティリティ。
## Key Documents
- Architecture: docs/architecture/overview.md
- Coding Standards: docs/conventions/coding-standards.md
- Error Handling: docs/conventions/error-handling.md
- Adding Features: docs/guides/adding-new-feature.md
## Critical Rules
1. domain/ は外部パッケージに依存してはならない
2. 患者データを扱う API は必ず auth middleware を通す
3. DB クエリには必ず context を渡し、timeout を設定する
ポイント: AGENTS.md は 50-80 行程度に収める。詳細は別ファイルへのポインタで。
Progressive Disclosure パターン
3 層構造
Layer 1: AGENTS.md (常に読まれる)
↓ ポインタ
Layer 2: docs/ 内の主要ドキュメント (必要に応じて参照)
↓ ポインタ
Layer 3: ソースコード内のコメント、テストケース (深い理解が必要なとき)
実装例
Layer 1 (AGENTS.md):
## Error Handling
→ docs/conventions/error-handling.md を参照
Layer 2 (docs/conventions/error-handling.md):
# Error Handling
## 原則
- エラーは必ず wrap して上位に返す
- エラーメッセージには原因特定に必要な情報を含める
- ユーザー向けエラーとシステムエラーを分離する
## パターン
→ 実装例は src/api/handlers/medication.go L45-80 を参照
## カスタムエラー型
→ src/domain/errors/types.go を参照
Layer 3 (ソースコード):
// WrapError はエラーをドメインエラーとして wrap する。
// 使用例:
// return WrapError(err, "failed to fetch patient", PatientNotFound)
//
// エラーメッセージには以下を含めること:
// - 何をしようとしたか
// - なぜ失敗したか(可能であれば)
// - 影響を受けるリソースの識別子
func WrapError(err error, msg string, code ErrorCode) error {
ドキュメントの鮮度維持: Doc Gardening
問題: 古いドキュメントは害になる
古いドキュメントはないのと同じどころか、エージェントに誤った情報を与えるためむしろ有害だ。
対策 1: ドキュメントに日付とオーナーを記載
---
title: 患者検索 API 設計
author: @yamada
created: 2025-11-15
last_reviewed: 2026-02-01
status: active # active | draft | deprecated
---
対策 2: 自動 staleness チェック
# .github/workflows/doc-freshness.yml
name: Document Freshness Check
on:
schedule:
- cron: '0 9 1 * *' # 毎月1日
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Check stale docs
run: |
# 90 日以上更新されていないドキュメントを検出
find docs/ -name "*.md" -mtime +90 -print
対策 3: PR テンプレートにドキュメント更新チェック
## PR Checklist
- [ ] 関連するドキュメントを更新したか?
- [ ] 新しい規約やパターンを docs/ に追加したか?
- [ ] AGENTS.md の更新が必要か確認したか?
対策 4: 定期的な Doc Gardening セッション
月に一度、チームでドキュメントの棚卸しを行う:
- deprecated なドキュメントを削除またはアーカイブ
- 内容が古いドキュメントを更新
- 不足しているドキュメントを特定して作成
Slack から Design Doc への移行
よくある問題
Slack #backend チャンネル:
田中: 「患者検索のページネーションどうする?」
佐藤: 「cursor-based がいいと思う」
田中: 「了解、offset はパフォーマンス問題あるもんね」
鈴木: 「limit は 50 にしよう」
→ 3 週間後、この会話は流れて誰も覚えていない
→ エージェントはこの議論に一切アクセスできない
解決策: Discussion → Decision → Document
1. Slack で議論する(これは自然なこと)
2. 結論が出たら design doc に書く
3. design doc を PR で追加する
4. Slack に design doc へのリンクを貼る
Design Doc の例:
# docs/design/patient-search-pagination.md
## 背景
患者検索 API にページネーションを追加する必要がある。
## 検討した選択肢
1. Offset-based: シンプルだが、大量データでパフォーマンス劣化
2. Cursor-based: 一貫したパフォーマンス、実装はやや複雑
## 決定
Cursor-based pagination を採用する。
## 理由
- 患者数が増加しても一貫したパフォーマンス
- リアルタイムデータ更新時にページずれが発生しない
- 既存の medication API も cursor-based で統一感がある
## 仕様
- cursor: 最後のレコードの ID(UUID)を base64 エンコード
- limit: デフォルト 20、最大 50
- レスポンスに next_cursor を含める
Try This: リポジトリ知識ベース化
Exercise 1: 知識の棚卸し
チームの知識がどこにあるか棚卸しする:
- Slack の #backend チャンネルの過去 1 ヶ月の技術的な議論を 5 つピックアップする
- それぞれについて「この情報はリポジトリ内にあるか?」を確認する
- ないものは design doc として追加する
Exercise 2: Progressive Disclosure の実装
自分のリポジトリで Progressive Disclosure を実装する:
- AGENTS.md を作成(または改善)する - 50 行以内
- AGENTS.md から参照される docs/ 内のドキュメントを 3 つ作成する
- Claude Code で「このリポジトリに新しい API を追加する方法を教えて」と聞いて、エージェントが正しいドキュメントにたどり着けるか確認する
Exercise 3: ADR の作成
過去にチームで行った技術的な意思決定を 1 つ選び、ADR として記録する:
# ADR-XXX: [タイトル]
## Status
Accepted
## Context
[なぜこの決定が必要だったか]
## Decision
[何を決めたか]
## Consequences
[この決定の結果、何が変わるか]
まとめ
リポジトリを知識ベースとして機能させるための原則:
- If it's not in the repo, it doesn't exist - すべての重要な情報をリポジトリ内に
- Progressive Disclosure - AGENTS.md は入り口、詳細は別ファイルへ
- Doc Gardening - ドキュメントは作って終わりではなく、継続的にメンテナンスする
- Discussion → Document - Slack の議論は design doc に昇華させる
- Pointer, not copy - 情報の重複を避け、Single Source of Truth を維持する
次のステップ
- フィードバックループの構築 - エージェント出力の品質保証
- エージェントに優しいアーキテクチャ - 構造的な制約の設計