コンテンツにスキップ

エアークローゼット — 46リポジトリの本番コードベースをAIが扱える形にする(知識グラフ+LLM Observability)

作成日: 2026-07-07 出典 / きっかけ: 辻亮佑(エアークローゼットCTO)による Zenn 連作3本 - 前編「46リポジトリに跨るコードベースを、静的解析で一つのナレッジグラフにした話」(2026-06-23) - 後編「46リポジトリに跨るコンテキストを、AIがセマンティックに検索できるようにした話」(2026-06-30) - 「AI時代のObservability設計 — アプリケーション / インフラ / CI / LLM すべてを監視する(設計編)」(2026-07-07) 関連: エアークローゼット_cortex_aiハーネス6部作_整理 / エアークローゼット_agentic_graph_rag_と社内mcp基盤_整理 / エアークローゼット_非エンジニア内製化_sandbox_mcpと議事録rag_整理 / オントロジーと知識グラフ_金融業界の実践例_整理 / 社内mcp共通基盤_認証認可ログ_整理 / llmops_データ基盤からの転用_整理 / ミラティブ_ashura_分析民主化aiエージェント基盤_整理


0. 要点(3行)

  • 46リポジトリに散った本番コードベースを AIに渡す前に「正しい形」に整える という一貫した思想で、①静的解析のコードグラフ、②意味を注入した3層グラフ+セマンティック検索、③本番の動的データ(Observability)を順に作った実践記録。
  • 効くのは 境界ノード(API・DB・Event経由のリポジトリ間依存)にだけ意味を注入する という割り切りと、静的解析グラフ + AIコンテキスト注入 = 自然言語の意味検索 というパターンの再利用。全関数を注釈せず、境界だけ注釈しても実用になる。
  • 実運用では 非エンジニア(スタイリスト・CS)を含む約73人・約5万回 の自然言語検索が成立し、現場の開発フロー(mainブランチ)に一切干渉しない 設計(annotation専用ブランチ・post-hoc pull)で回している点が肝。

1. 全体像 — 3部作が解こうとした「一つの問題」

課題はシンプルで、「46リポジトリに跨る本番の文脈を、AIに正しく扱わせたい」。素朴に全コードを渡す案は、コンテキストウィンドウとハルシネーションで破綻する。そこで「外側から構造を取り出し、AIが噛める形に整えてから渡す」方針を、対象を変えて3回適用したのが本連作である。

記事 対象 何を「正しい形」にしたか 中心成果物
前編(06-23) 静的構造 コードの依存関係を静的解析でグラフ化 code-graph(46リポジトリ)
後編(06-30) 意味 境界ノードに意図・DB文脈をベクトルで注入 annotation graph + db-graph、MCPフロントドア
Observability編(07-07) 動的データ 本番のlog/trace/metric/LLM利用を統一形式で観測可能に OTel + Grafana Cloud + BigQuery

貫くテーゼは筆者の言葉で 「AIに渡す前にデータを正しい形にしてあげる必要がある」。静的(コード)→ 意味(グラフ)→ 動的(本番挙動)と、AIの入力を段階的に整地していく構成になっている。


2. 前編:静的解析で46リポジトリを一つのナレッジグラフに(code-graph)

2-1. 規模と狙い

  • 対象は air-closet graph 37リポジトリ + mall graph 9リポジトリ = 計46リポジトリ。複数サービス横断の巨大コードベース。
  • 目的は AIによる影響範囲分析。「このAPIを変えたら、どのサービスのどこに波及するか」を機械的に辿れるようにする。

2-2. 核心は「境界ノード」

単一リポジトリ内のコールグラフだけでは足りない。価値の源泉は リポジトリ間の依存=境界ノード で、これは主に3経路で生じる。

  • API:あるサービスが別サービスのエンドポイントを呼ぶ(CALLS_API / HANDLES_API
  • Event:Pub/Sub 等でイベントを発行・購読する(EMITS_TO / SUBSCRIBES_TO
  • DB:同じテーブルを別サービスが読み書きする(WRITES_TO / READS_FROM

エッジは 21種類 定義(CALLSEXTENDS 等の言語内関係も含む)。この境界を接合できるかどうかが、グラフが「横断分析に使えるか」を決める。

2-3. 実装スタック(tree-sitter を主軸に、必要箇所だけ重い道具)

tree-sitter        … 構文木から基本構造を高速抽出(全体の土台)
  └─ TypeScript Compiler API … 変数・型の解決が要る箇所だけ
       └─ Gemini            … 静的に決まらない動的ケースの推定

「基本は軽い tree-sitter、解決精度が要る所だけ TypeScript Compiler、それでも決まらない所だけ LLM」というコスト/精度の三段構え。jQuery / AngularJS / Express / NestJS / TypeORM などフレームワーク別 parser を継続追加している。

2-4. 「90%では使い物にならない」— マルチホップ精度への執着

影響範囲分析は複数ホップを辿るため、1エッジの精度が指数で効く。筆者の試算:

  • 99%精度 → 2ホップで約0.98(0.99² ≈ 0.980)、5ホップで約0.95(0.99⁵ ≈ 0.951)
  • (※この算術は独立に検算しても整合する。裏返すと90%精度では5ホップで 0.9⁵ ≈ 0.59 まで落ち、実用に耐えない)

だからこそ parser を増やし境界の取りこぼしを潰し続ける、という判断につながる。

2-5. 運用と残課題

  • 毎日 JST 7:00 に「境界分析 cron」 を実行。API/Event/DB 境界の接続率を集計し、5%以上劣化で Grafana 経由アラート。グラフの品質を放置せず日次で監視する。
  • 残課題は4つ:①セマンティック検索ができない(入口問題)、②helper/型など無関連ノードのノード爆発、③関数内部は結局ファイル閲覧が必要、④新フレームワーク対応の parser 拡張が続く。
  • 別解として社内 cortex(100+アプリのモノレポ)ではアノテーション前提の設計を採るが、本番系は多チーム運営で現実的でないため、code-graph を進化させる道を選んだ。→ この「入口問題」が後編の主題。

3. 後編:AIがセマンティックに検索できるようにする(3層グラフの SAME_ENTITY 接合)

3-1. ヒントは db-graph にあった

先行して作っていた db-graph が成功パターンを示していた。複数サービスの 1,133テーブル・10,815カラム のスキーマを ORM 定義から静的抽出し、Gemini で各カラムの説明文を自動生成 → 768次元ベクトル化 してグラフに格納。ここで確立したのが再利用可能な公式:

静的解析グラフ(構造)+ AIコンテキスト注入(意味)= 自然言語の意味検索

3-2. 3層グラフを SAME_ENTITY で並列接続

同じパターンを code-graph にも持ち込む。ただし API/Event/Page の「意味」は別途与える必要がある。そこで3種のグラフを SAME_ENTITY エッジで束ねる。

        code-graph            db-graph              annotation graph
        (構造)              (DB文脈)            (意図)
   46リポジトリの関数     1,133テーブルの        境界ノードだけに
   /クラス/境界ノード      意味付き説明          @graph-* で意図を注入
        │                     │                        │
        └──────── SAME_ENTITY ┴──────── SAME_ENTITY ────┘
                         (同一実体として接合)

3-3. annotation 戦略 — 「境界だけ注釈すれば足りる」

全関数への注釈は非現実的。そこで 境界ノードだけに @graph-* アノテーションを付ける 割り切り。

  • @graph-business:日本語の意図テキスト(→ ベクトル化されて意味検索の対象になる)
  • @graph-flow / @graph-status:会員ライフサイクルや区分などの構造情報

「境界ノードだけ注釈すれば十分意味を持つ」という設計判断が、注釈コストを実運用可能な水準に抑える鍵。

3-4. 現場フローに干渉しない運用

  • main ブランチは現場エンジニアの開発フローのまま。AI 用の注釈は別の annotation ブランチに隔離。
  • main の変更を webhook で検知 → 注釈を自動生成 → レビューまで自動化人とAIのレビューを混在させない
  • ここが本連作で最も再利用価値の高い運用パターン。「AI 資産を本番コードに混ぜず、並走レーンを引く」。

3-5. 接合品質を SLO で機械検査

3グラフの繋ぎ目は放っておくと腐るので、機械的に検査する。

検査項目 基準
API ハンドラの下流呼び出し率 95%以上
DB アクセスエッジの db-graph カラム接合率 80%以上
Event フィールド情報の保有率 70%以上
名前解決が曖昧なエッジ 0件

ブリッジ(静的ノード↔annotationノード)の接続は 4段階フォールバック:①リポ別 prefix 変換 → ②バージョン除去 → ③パラメータ正規化 → ④末尾処理と動的 dispatch fallback。

3-6. 実利用の数字 — 非エンジニアまで届いた

2026-04-16 〜 執筆時点(約2.5ヶ月)で約50,000回・約73人 が利用。

利用者層 回数 人数
エンジニア(PI・QA・関連チーム) 約47,000回 51人
非エンジニア(スタイリスト・CS・モール業務等) 約2,800回 21人

「会員のサブスク料金計算」のような自然文でグラフに入れる。非技術者が自然言語で本番の仕組みを検索できる状態が実際に成立した点が成果(分析民主化の文脈は ミラティブ_ashura_分析民主化aiエージェント基盤_整理 とも通じる)。

3-7. 唯一の入口としての MCP

  • MCP サーバーが唯一のエントリーポイント。6ツール(サービス検索 / サービス詳細 / API詳細 / データフロー追跡 / 影響範囲追跡 / ビジネスルール検索)を提供。
  • db-graph は直接繋がせず、annotation graph 側の MCP がプロキシする。窓口を一本化して権限・整合を握る設計は 社内mcp共通基盤_認証認可ログ_整理 と同じ発想。
  • ※ MCP は Anthropic のオープン標準。ツール=LLM が呼べる実行可能関数で、データ源とAIを繋ぐ二方向プロトコル。

3-8. 残課題

①annotation カバレッジ維持(backend・Go・batch 系がまだ薄い)、②ブリッジ誤接合の完全排除は構造的に困難、③動的解析が未実装(本番実行回数を流し込む dead-code 検出は未着手)、④新リポ追加時の調整負荷。→ ③が Observability 編へ繋がる。


4. Observability編:動的データもAIが扱える形に(アプリ / インフラ / CI / LLM)

静的(コード)と意味(グラフ)を整えたら、次は 本番の動的挙動。「4つの観測対象を、それぞれ別の形で Observable にする」。

監視対象 問い 形式 主な道具
アプリケーション 「いま本番で何が起きてる?」(探索) log + trace OTel + Loki + Tempo
インフラ 「リソースは足りてる?落ちてない?」(時系列) metric Cloud Monitoring → Mimir
CI 「何が壊れた?いつから?」(alert + 履歴探索) log + alert GitHub API post-hoc pull → Loki
LLM 「いくらかかってる?誰がどれだけ?」(即時 + 集計) metric + 構造化レコード Prometheus / BigQuery 使い分け

4-1. アプリ — OTel + Grafana LGTM で「全アプリ同じ形」

OpenTelemetry 標準スタック(Grafana LGTM:Loki=logs / Grafana=可視化 / Tempo=traces / Mimir=metrics)で統一。肝は 全アプリが同じ形で log と trace を出す こと。統一されているから、AI が {service_name="<service>"} |~ "error" のような LogQL で横断検索できる。ここでも「AIが噛める統一フォーマット」が主眼。

4-2. インフラ — GCP metric を Mimir に集約

Cloud Run / BigQuery / Pub/Sub 等の metric を Cloud Monitoring 経由で Mimir に集約。「先週 CPU 最多の service は?」「queue 滞留 worker は?」に AI が自然に答えられる状態を作る。

4-3. CI — webhook push ではなく post-hoc pull(AI時代特有の設計)

GitHub Actions のログを、実行と切り離して後追いで取りに行く

workflow_run 終了
  └─ 別 workflow が起動
       └─ GitHub API /repos/.../actions/jobs/.../logs からログ取得
            └─ job/status/ref/pr/commit/output を JSON 構造化
                 └─ OTLP /v1/logs で Grafana Cloud へ送信

利点が明快:①CI 実行と observability を分離(送信失敗がテスト本体に波及しない)、②PR 由来コードが鍵に触れないworkflow_run トリガーは default ブランチの context で走る=セキュリティ)、③送信 workflow の成否自体を観測対象化

4-4. LLM — 「集計の性質」で道具を分ける(最も差別化された設計)

同じ LLM 監視でも、Gemini と Claude Code で別の形を選ぶ。基準は「リアルタイム即時性か、SQL 集計強度か」。

Gemini → Prometheus(即時性) - 呼び出し元コードを自社で握っているので、共通ラッパ traceGeminiCallinline に metric を emit。 - 出力:gemini.tokens.total / gemini.requests.total / gemini.request.duration / gemini.cost.usd(label: model / service)。 - コストは Billing API を待たず、クライアント側でトークン数×単価表(GEMINI_PRICING 定数)で即時計算。理由は「何にどれだけかかったか分からないとチューニングできない」=呼び出しコンテキスト単位(db-graph 説明生成 / code-graph 型推論 等)の粒度が要る。副次効果として暴走 prompt/batch を翌朝の billing を待たず察知。$1/hour 超過で Slack 即通知

Claude Code → BigQuery(集計強度) - 外部 CLI でラッパを挟めない → 利用ログは事後レコードとして集める。 - パイプライン:

Claude Code analyzer
  → 社内 endpoint(CORTEX_API_KEY 検証)
    → Cloudflare Edge Router worker(email を X-Cortex-User-Email 付与)
      → Cloud Run API(dedup → Pub/Sub)
        → Cloud Run worker(BigQuery streaming insert)
- スキーマ:email / repository / timestamp / input_tokens / output_tokens / cache_creation_input_tokens / cache_read_input_tokens。 - SQL 向きの問い:「先週チームAの累計使用量?」「リポジトリXの1ヶ月コスト?」「prompt-cache hit ratio?」。 - 実績:過去30日で 77.5B トークン / 382K メッセージ / 47ユーザー / 79リポジトリ。cache 読込が全体の 96%。prompt-cache 無し前提比で実効 input 単価ベース約7倍効率。 - (※検算:Claude の cache read は基本 input 単価の約0.1倍。96%が cache read なら実効単価 ≈ 0.96×0.1 + 0.04×1.0 ≈ 0.136 → 無キャッシュ比 1/0.136 ≈ 7.3倍。記事の「約7倍」と整合する)

設計の本質は「全部 OTel + 全部 Loki」という単一 backend 指向を避け、集計の質的性質に応じて道具を分けること。即時性なら Prometheus、SQL 集計強度なら BigQuery。


5. 通底する設計思想(横串で読むと見えるもの)

  • AIに渡す前に「正しい形」に整える:素の全文投入をやめ、構造化→意味付与→観測可能化と入力を整地する。3記事すべてがこの一点の変奏。
  • 境界だけに投資する:全関数を注釈しない/全コードを渡さない。API・DB・Event の境界ノードにだけ意味を注ぐと費用対効果が跳ねる。
  • 静的グラフ + AIコンテキスト注入 = 意味検索:db-graph で確立した公式を code-graph に横展開。パターンの再利用が速度を生んだ。
  • 現場フローに干渉しない並走レーン:annotation は別ブランチ、CI ログは post-hoc pull。AI 資産を本番の人間フローに混ぜない。
  • 品質を日次・機械で監視:境界接続率 cron、3グラフ接合の SLO。グラフもデータも「作って終わり」にせず劣化を検知する。
  • 道具は目的で選ぶ:LGTM で統一しつつ、LLM 監視だけは Prometheus と BigQuery を集計性質で使い分ける。単一 backend の思考停止を避ける。

6. まとめ — いつ効くか(早見表)

状況 この連作から借りる打ち手
多リポ・多サービスで AI に影響範囲を辿らせたい 静的解析で 境界ノード(API/DB/Event) を接合した code-graph を作る
コード検索が「入口問題」で自然文に効かない 静的グラフ + AI生成説明のベクトル化 で意味検索を後付けする
全部を注釈するコストが払えない 境界ノードだけ @graph-* 注釈、main と別ブランチで自動生成
現場エンジニアの開発フローを壊したくない AI 資産を 別レーン(annotationブランチ / post-hoc pull) に隔離
非エンジニアにも本番知識を開きたい MCP を唯一の窓口にして権限・整合を握る
LLM のコストが「翌朝の billing」でしか見えない 握れる呼び出しは クライアント側で即時 metric 化(Prometheus)、握れない CLI は 事後レコードを BigQuery 集計
CI ログを安全に observability へ流したい workflow_run の post-hoc pull(実行と分離・鍵に触れない・送信成否も観測)

一言でいえば 「AIに丸投げせず、AIが噛める形に整地してから渡す」 を、静的・意味・動的の3層で徹底した実装記録。既存組織の本番系でも AI と協働できる設計が成立することを、実利用の数字込みで示している。


参考リンク


作成: 2026-07-07 / 最終更新: 2026-07-07