ループを掘り起こす:変更はいかにして組織の記憶になるか
> Gitのコミットは構造化された変更履歴とアーキテクチャ上の意思決定記録になり、クエリ可能な組織の記憶としてAIエージェントへフィードバックされます。
この記事の数値は公開時点(2026年2月)のシステムを反映しています。最新の数値はチームページをご覧ください。
どのエンジニアリングチームも同じ課題に直面します。変更は絶えず起こりますが、その変更の背後にある理由は消え去っていきます。半年後、誰かが「なぜパイプラインのステージにDuckDBを採用したのか?」と尋ねたとき、その答えはその判断を下した本人の頭の中にしか存在しません ―― しかもその人がまだ在籍していればの話です。
私たちは、このループを閉じるためのマイニングワークフローを構築しました。変更はgitのコミットとして流れ込み、私たちのマイニングパイプラインで処理され、構造化された変更履歴やアーキテクチャ上の意思決定記録になり、そしてCLIクエリを通じて私たちのAIエージェントへとフィードバックされます。結果として得られるのは、人間とAIの両方がアクセスできる組織の記憶です。
問題:意思決定は蒸発する
典型的なシナリオを考えてみましょう。ある開発者が次のようにコミットします:
feat(canonical): add DuckDB runtime for pipeline stages
このコミットは、重要なアーキテクチャ上の選択を表しています。チームは選択肢を評価し、トレードオフを検討し、特定の理由からDuckDBに落ち着きました。しかしそのコンテキストはすべて、次のような場所に存在しています:
- Slackのスレッド(おそらく削除済み)
- 誰かの記憶(確実に薄れつつある)
- コード中のコメント(運が良ければ、もしかしたら)
3か月後、新しいチームメンバーがこう尋ねます。「この新しいステージには、DuckDBとSQLiteのどちらを使うべきですか?」組織の記憶がなければ、彼らは車輪の再発明をするか、一貫性のない選択をすることになります。
ループ:コミットからコンテキストへ
私たちのマイニングワークフローは、git履歴をクエリ可能な知識へと変換します:
Git Commits
│
▼
┌─────────────────────┐
│ mine sync │ ← Build index from git history
└─────────────────────┘
│
▼
┌─────────────────────┐
│ mine candidates │ ← Surface commits for review
└─────────────────────┘
│
▼
┌─────────────────────┐
│ Classification │ ← Human or LLM assessment
│ (changelog or ADR) │
└─────────────────────┘
│
├──────────────────────┐
▼ ▼
┌─────────────┐ ┌───────────────┐
│ Changelog │ │ Decisions │
│ Ledger │ │ Registry │
│ (JSONL) │ │ (YAML files) │
└─────────────┘ └───────────────┘
│ │
▼ ▼
┌─────────────┐ ┌───────────────┐
│ CHANGELOG.md│ │ orkestra CLI │
│ per package │ │ queries │
└─────────────┘ └───────────────┘
│ │
└──────────────────────┘
│
▼
┌───────────────┐
│ AI Agents │
│ (via CLI) │
└───────────────┘
ここでの重要な洞察は、変更履歴とアーキテクチャ上の意思決定の両方が、同じgit履歴から、統一されたパイプラインを通じて流れ出すということです。これにより、何かが見落とされることがなくなります。
マイニングの仕組み
ステップ1:インデックスを同期する
uv run orkestra mine sync
このコマンドはgit履歴をスキャンし、すべてのコミットのインデックスを構築します。各コミットから構造化されたシグナルを抽出します:
- 標準的なコミットタイプ(
feat、fix、chore、docs) - スコープ(どのパッケージまたは領域か)
- 破壊的変更のマーカー
- 変更されたファイルと複雑度のメトリクス
ステップ2:カバレッジ状況を確認する
uv run orkestra mine status
現在の状況は次のようになっています:
Mining Status
=============
Decisions
---------
Coverage: 100.0%
Processed: 15637 (of 15637)
Extracted: 476
Skipped: 15161
Changelog
---------
Coverage: 100.0%
Processed: 15637 (of 15637)
Released: 6799
Skipped: 8838
15,637件のコミットを処理済み。うち476件がアーキテクチャ上の意思決定になり、6,799件が変更履歴のエントリになりました。すべてのコミットが分類済みです。
ステップ3:レビュー対象の候補を取得する
uv run orkestra mine candidates --limit 50 --full
これにより、まだ処理されていないコミットが、分類に必要な完全なコンテキストとともに表示されます:
on
{
"sha": "90571786d99166c0039ca2e80e4d9cd96184bd85",
"date": "2026-01-26",
"subject": "feat(canonical): add DuckDB runtime for pipeline stages",
"signals": {
"commit_type": "feat",
"scope": "canonical",
"breaking": false,
"is_releasable_type": true,
"domains_affected": ["pipeline", "data-architecture"]
},
"body": "Establishes DuckDB as canonical in-process analytical database...",
"files_changed": ["packages/canonical/pipelines/stages/duckdb_runtime.py", "..."],
"stats": {"files": 8, "insertions": 450, "deletions": 120}
}
これらのシグナルは分類の指針になります。is_releasable_type: trueは、これが変更履歴に載るべきものであることを示唆しています。挿入行数の多さとインフラ関連ファイルの存在は、これがアーキテクチャ上の意思決定でもある可能性を示唆しています。
ステップ4:コミットを分類する
ここで2つの経路に分岐します。変更履歴のエントリと、アーキテクチャ上の意思決定です。
変更履歴のエントリの場合:
uv run orkestra mine classify abc123 --changelog added
これにより、コミットabc123が変更履歴の「Added」カテゴリーに載るべきものとして記録されます。
アーキテクチャ上の意思決定の場合:
まず、実際の意思決定IDを取得します:
uv run orkestra decisions new --domain pipeline --dry-run
# Returns: DEC-PL-143
続いて、その意思決定IDを使って分類します:
uv run orkestra mine classify abc123 --decision DEC-PL-143
これにより、コミットが、作成または更新されることになる意思決定レコードに紐づけられます。
バッチ処理の場合(私たちが実際に行っている方法):
# Generate classifications file with LLM assistance
uv run orkestra mine commit --input classifications.jsonl
JSONL形式なら、1回のパスで両方のドメインに対応できます:
on
l
{"sha":"abc123","domain":"changelog","action":"release","category":"added","summary":"Add DuckDB runtime for pipeline stages"}
{"sha":"abc123","domain":"decisions","action":"extract","decision_id":"DEC-PL-142"}
{"sha":"def456","domain":"changelog","action":"skip","reason":"Chore: dependency update"}
ステップ5:出力をレンダリングする
uv run orkestra changelog render --package <pkg>
これにより、台帳からパッケージごとのCHANGELOG.mdファイルが生成されます。変更履歴は派生成果物です ―― 削除しても、元の台帳から完璧に再生成されます。
意思決定レコードの構造
抽出された意思決定は、豊富なメタデータを持つYAMLファイルになります:
id: DEC-PL-142
title: Adopt DuckDB as Canonical Processing Runtime for Pipeline Stages
domain: pipeline
status: active
created: '2026-01-26'
summary: |
Establishes DuckDB as the canonical in-process analytical database for pipeline
stage transformations. Provides a shared runtime module that resolves settings
from pipeline defaults with stage-level overrides.
context: |
Pipeline stages performing data transformations each independently configured
DuckDB connections. This led to inconsistent settings, duplicated configuration
code, and no way to tune DuckDB globally for a pipeline run.
rationale:
- DuckDB provides efficient in-process OLAP with zero configuration deployment
- Centralized runtime module eliminates duplicated DuckDB setup across stages
- Hierarchical settings enable global tuning with stage-level overrides
- Memory limits and thread counts can be adjusted per-pipeline
impact:
positive:
- Consistent DuckDB configuration across all pipeline stages
- Single point of control for memory/thread tuning
- Reduced code duplication in conversion and export stages
negative:
- Adds dependency on shared runtime module
- Stages must adopt new configuration pattern
source_commits:
- sha: 90571786d99166c0039ca2e80e4d9cd96184bd85
message: 'feat(canonical): add DuckDB runtime for pipeline stages'
date: '2026-01-26'
role: primary
files:
- packages/canonical/pipelines/stages/duckdb_runtime.py
- packages/canonical/pipelines/runner.py
- packages/canonical/pipelines/stages/convert_hdx_admin_boundaries_to_geoparquet.py
related:
- DEC-DA-014 # Data architecture decisions that influenced this
すべての意思決定は、元となったコミットへリンクバックしています。すべての意思決定は、どのファイルに影響するかを明記しています。意思決定同士の関係も明示的です。
CLIとの統合:組織の記憶へのクエリ
ここでループが閉じます。エージェントはCLIを通じて意思決定にクエリを投げられます:
# Search by topic
uv run orkestra decisions search --query "retry"
リトライロジック、エラーハンドリング、リカバリーパターンに関する意思決定を返します。
# Get full details on a specific decision
uv run orkestra decisions info DEC-PL-142
コンテキスト、根拠、影響を含む完全な意思決定レコードを返します。
# List recent decisions for context
uv run orkestra decisions list --limit 15
最近どのようなアーキテクチャ上の選択が行われたかを表示します。
エージェントはこれをどう使うか
私たちのオーケストレーターのベースライン指示には、次のような内容が含まれています:
**Essential CLI commands:**
- `orkestra decisions search "X"` — Find architectural decisions
エージェントがDuckDBに関連する何かの実装を依頼されたとき、まず次のように確認できます:
uv run orkestra decisions search --query "DuckDB"
そしてDEC-PL-142を発見し、次のことを学びます:
- なぜDuckDBを選んだのか(コンテキスト)
- 正しい使い方(agent_guidance)
- どのファイルを見ればよいか(files)
- どんな関連する意思決定が存在するか(related)
エージェントは車輪の再発明をしません。確立されたパターンの上に積み上げていきます。
3つの質問テスト
すべてのコミットが意思決定レコードに値するわけではありません。私たちは3つの質問テストでふるいにかけています:
- 判断が難しかったか? 大きな分析、トレードオフの検討、あるいは議論を要したか?
- 変更のコストは高いか? この決定を覆すには大幅な作り直しが必要か?
- システム全体に影響するか? 複数のパッケージに影響を与えるか、他が従うことになるパターンを確立するか?
これらの質問のうち少なくとも1つに「はい」と答えられるコミットは、意思決定抽出の候補になります。私たちの典型的な割合は、100コミットあたり1〜4件の意思決定(約1〜4%)です。
変更履歴のエントリについては、基準はもっと低めです。ユーザーに見える変更(機能、修正、改善)であれば何でも記録されます。内部的な雑務、ドキュメント更新、リファクタリングは通常スキップされます。私たちの典型的な割合は、100コミットあたり30〜50件の変更履歴エントリです。
データストレージ:追記専用台帳
マイニングシステムは、マルチエージェントによる運用で競合が起きないよう、追記専用のJSONL台帳を使用します:
packages/orchestration/ai_assets/reference/changelog/
├── commits_processed.jsonl # Classification ledger (both domains)
├── release_notes.jsonl # Changelog entries
└── commits_index.yaml # Derived index (gitignored)
packages/orchestration/ai_assets/reference/decisions/
├── registry.yaml # Decision index
└── records/
├── DEC-AD-001.yaml
├── DEC-AD-002.yaml
└── ...
.gitattributesにおけるmerge=unionを伴うJSONL形式のおかげで、複数のエージェントがマージコンフリクトを起こすことなく同時にコミットを分類できます。各行は独立しています。
バリデーションゲート
マイニングセッションを行う前には、必ずバリデーションを実行します:
uv run orkestra mine validate --quick
これは次を確認します:
- SHA形式の妥当性
- 意思決定IDの形式準拠
- 同一SHAに対する重複エントリがないこと
- 参照されている意思決定が実際に存在すること
分類後、変更をコミットする前にもう一度バリデーションを行います。
これが重要な理由
私たちが構築したフィードバックループは、いくつかの問題を解決します:
新しいチームメンバーにとって: 「なぜXをしたのか?」と尋ねる代わりに、意思決定レジストリを検索できます。コンテキストは保存されています。
AIエージェントにとって: 真空の中で動作しているわけではありません。提案を行う前に、組織的な知識にクエリを投げられます。新しいパイプラインステージの追加を依頼されたとき、DuckDBのパターンを発見し、それに従うことができます。
アーキテクチャの一貫性にとって: 意思決定は明示的で検索可能です。誰かが既存の意思決定と矛盾するアプローチを提案したとき、システムはその衝突を表面化できます。
変更履歴の生成にとって: リリースノートは土壇場でのドタバタ作業ではなくなります。開発中に継続的に行われる分類の副産物になるのです。
オンボーディングにとって: 新しいエージェントは、コードベースの完全なコンテキストを引き継ぎます。コードを見るだけでなく、それを形作った意思決定も見ることになります。
現在の状態
現時点で:
- 15,637件のコミットがパイプラインで処理済み
- 476件のアーキテクチャ上の意思決定が抽出・文書化済み
- 6,799件の変更履歴エントリが記録済み
- 両ドメインにわたる100%のカバレッジ
開始以来のすべてのコミットが分類済みです。組織の記憶は完全であり、クエリ可能です。
はじめに
同様の仕組みを実装したい場合:
-
まずConventional Commitsから始める。 マイニングパイプラインは、コミットに構造化されたプレフィックス(
feat:、fix:、chore:)がある場合に最もよく機能します。 -
ドメインを定義する。 私たちは
pipeline、agent-design、observability、data-modelingのようなドメインを使っています。これらは意思決定を領域別に整理します。 -
分類する習慣を作る。 マイニングは、チームが定期的にコミットを分類することで機能します。LLMの支援によるバッチ処理はスケールを助けます。
-
意思決定をクエリ可能にする。 エージェントがCLI経由で意思決定を検索できるようになると、価値は複利的に積み上がります。出力を機械が消費しやすい形に構造化しましょう。
-
ループを閉じる。 意思決定は今後の作業に影響を与えるべきです。エージェントへの指示やコードレビューのチェックリストに、意思決定への参照を含めましょう。
目標は完璧なドキュメントを作ることではありません。変更の背後にある理由を、今日も半年後も、人間とAIの双方がアクセスできるようにすることです。変更が組織の記憶になるとき、チームは再発明するのではなく、確立されたパターンの上に積み上げていけるようになります。
マイニングワークフローは、私たちのオーケストレーションエンジンの一部であり、具体的にはオーケストレーションパッケージ内のコンテキストエンジンモジュールに含まれています。
関連記事
Maguyva開発ログのその他の記事
コード検索をvoyage-4-largeへアップグレードした理由_
私たちはコード埋め込みをvoyage-4-largeへ移行しました ―― 現在、公開RTEBコード検索リーダーボードのトップに立つモデルです。正直に言うと:私たちが受け入れているトレードオフ、実際に何をインデックス化しているか、そしてなぜプレミアムな埋め込みにお金を払うのか。
言語の再帰的自己改善:約280言語にわたるコードインテリジェンスの磨き上げ_
私たちは約280言語のコードインテリジェンスに対応しています。人間の手でそのすべてを監査することはできません。そこで私たちは、言語の再帰的自己改善ループ ―― 抜き取り検査、LLM-as-judge、1点修正、再検証 ―― を構築し、抽出が単に「グリーン」であるだけでなく実際に正しくなるまで、隔離されたエージェント群でこれを回し続けています。
マルチモーダル・フュージョン検索:あらゆるクエリに最適な検索エンジンを選ぶ_
「parseConfigはどこで定義されているか」のようなクエリと「認証はどう動いているか」のようなクエリでは、求められる検索の種類が異なります。Maguyvaは意図を分類し、それに応じて4つの検索モダリティに重みを付け、重み付き相互順位融合で結果を統合します。