# 挖掘迴圈：變更如何化為組織記憶

Canonical source: https://maguyva.ai/zh-hant/blog/mining-workflow-closing-the-loop

License: text under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); code samples under [MIT-0](https://opensource.org/license/mit-0); the Maguyva name, logos, brand assets and other code are not covered. Details: [maguyva.ai/license](https://maguyva.ai/license).

Date: 2026-02-03 · Author: Maguyva Team

> Git 提交會轉化為結構化的變更日誌條目與架構決策紀錄，再回饋給 AI 代理，成為可查詢的組織記憶。

> *本文中的數字反映發布當下（2026 年 2 月）的系統狀態。目前最新數字請參見我們的[團隊頁面](/zh-hant/team)。*

每個工程團隊都面臨同樣的難題：變更不斷發生，但這些變更背後的*原因*卻不斷流失。六個月後，有人問「我們當初為什麼在 pipeline 各階段採用 DuckDB？」而答案只存在於當初做出這個決定的人腦中——前提是那個人還在團隊裡。

我們打造了一套挖掘工作流程，補上了這個缺口。變更透過 git 提交流動，經我們的挖掘管線處理後，化為結構化的變更日誌條目與架構決策紀錄，再透過 CLI 查詢回饋給我們的 AI 代理。結果就是：人類與 AI 都能存取的組織記憶。

## 問題所在：決策會蒸發

想想一個典型情境。某位開發者提交了：

```
feat(canonical): add DuckDB runtime for pipeline stages
```

這筆提交代表了一項重大的架構抉擇。團隊評估了多個選項、權衡了各種取捨，最終基於特定原因選擇了 DuckDB。但這些脈絡全都存在於：

- 某個 Slack 討論串中（大概已經被刪掉了）
- 某人的記憶裡（肯定正在淡去）
- 程式碼中的一則註解（也許有，如果你夠幸運的話）

三個月後，一位新加入的團隊成員問道：「這個新階段該用 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 歷史，經由統一的管線處理。這確保了不會有任何內容遺漏。

## 挖掘機制如何運作

### 步驟一：同步索引

```bash
uv run orkestra mine sync
```

此指令會掃描 git 歷史，為所有提交建立索引，並從每筆提交中擷取結構化訊號：

- Conventional Commits 提交類型（`feat`、`fix`、`chore`、`docs`）
- 範圍（屬於哪個套件或領域）
- 不相容變更標記
- 異動檔案與複雜度指標

### 步驟二：檢查涵蓋率狀態

```bash
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 筆成為變更日誌條目，每一筆提交都已完成分類。

### 步驟三：取得待審核候選項目

```bash
uv run orkestra mine candidates --limit 50 --full
```

這會列出尚未處理的提交，並附上供分類使用的完整脈絡：

```json
{
  "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` 顯示這應該出現在變更日誌中；較大的新增行數與基礎架構檔案，則顯示它也可能是一項架構決策。

### 步驟四：為提交分類

從這裡開始分成兩條路徑：變更日誌條目，以及架構決策。

**針對變更日誌條目：**

```bash
uv run orkestra mine classify abc123 --changelog added
```

這會記錄提交 `abc123` 應出現在變更日誌的「新增」類別下。

**針對架構決策：**

首先，取得一個真實的決策編號：

```bash
uv run orkestra registry decisions new --domain pipeline --dry-run
# Returns: DEC-PL-143
```

接著使用該決策編號進行分類：

```bash
uv run orkestra mine classify abc123 --decision DEC-PL-143
```

這會將該提交連結到一份即將建立或更新的決策紀錄。

**針對批次處理（我們實際採用的方式）：**

```bash
# Generate classifications file with LLM assistance
uv run orkestra mine commit --input classifications.jsonl
```

JSONL 格式讓兩種領域能一次處理完成：

```jsonl
{"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"}
```

### 步驟五：渲染輸出

```bash
uv run orkestra registry changelog render --package <pkg>
```

這會依帳本內容產生各套件專屬的 `CHANGELOG.md` 檔案。變更日誌屬於衍生產物——就算刪除它們，也能從來源帳本完美重新生成。

## 決策紀錄的結構

擷取出的決策會化為附帶豐富中繼資料的 YAML 檔案：

```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 查詢決策：

```bash
# Search by topic
uv run orkestra registry decisions search --query "retry"
```

回傳與重試邏輯、錯誤處理、復原模式相關的決策。

```bash
# Get full details on a specific decision
uv run orkestra registry decisions info DEC-PL-142
```

回傳包含情境、理由與影響的完整決策紀錄。

```bash
# List recent decisions for context
uv run orkestra registry decisions list --limit 15
```

顯示近期做出了哪些架構抉擇。

### 代理如何運用這套機制

我們協調器的基準指令中包含：

```markdown
**Essential CLI commands:**
- `orkestra registry decisions search "X"` — Find architectural decisions
```

當代理被要求實作與 DuckDB 相關的內容時，它可以先檢查：

```bash
uv run orkestra registry decisions search --query "DuckDB"
```

並發現 DEC-PL-142，從中了解：
- 我們為何選擇 DuckDB（脈絡）
- 該如何正確使用它（代理指引）
- 該查看哪些檔案（檔案）
- 有哪些相關決策（相關項目）

代理不必重新發明輪子，而是能在既有模式的基礎上繼續建構。

## 三問測試

並非每筆提交都值得建立決策紀錄，我們以「三問測試」來篩選：

1. **這個決定當初難做嗎？** 是否需要大量分析、取捨評估或討論？
2. **改變它的代價高嗎？** 若要推翻這項決策，是否需要大幅重做？
3. **它是否具有全系統層級的影響？** 是否影響多個套件，或建立了其他人將遵循的模式？

只要一筆提交對這三個問題中至少一項回答「是」，就是決策擷取的候選對象。我們的一般比例是：每 100 筆提交約產生 1 到 4 項決策（約 1% 到 4%）。

至於變更日誌條目，門檻較低：任何面向使用者的變更（功能、修正、改善）都會被記錄下來；內部雜務、文件更新與重構通常會被略過。我們的一般比例是：每 100 筆提交約產生 30 到 50 則變更日誌條目。

## 資料儲存：僅可附加的帳本

挖掘系統採用僅可附加（append-only）的 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
    └── ...
```

這種採用 `merge=union` 合併設定（記錄於 `.gitattributes`）的 JSONL 格式，代表多個代理可以同時為提交分類，而不會產生合併衝突——每一行都是獨立的。

## 驗證關卡

在任何一次挖掘作業開始前，我們都會執行驗證：

```bash
uv run orkestra mine validate --quick
```

此驗證會檢查：
- SHA 格式是否有效
- 決策編號格式是否符合規範
- 同一個 SHA 是否有重複項目
- 所參照的決策是否確實存在

分類完成後，我們會在提交變更前再次驗證。

## 為什麼這很重要

我們建構的這個回饋迴圈，解決了幾項問題：

**對新進團隊成員而言：** 他們不必再問「我們當初為什麼這麼做？」，而是可以直接搜尋決策登錄檔，脈絡都被完整保留。

**對 AI 代理而言：** 它們不必在真空中運作，可以在提出建議前先查詢組織知識。當被要求新增一個 pipeline 階段時，它們能發現 DuckDB 這項模式，並依循它。

**對架構一致性而言：** 決策是明確且可搜尋的。當有人提出與既有決策相牴觸的做法時，系統能夠揭露這項衝突。

**對變更日誌生成而言：** 發布說明不再是最後一刻的臨時拼湊，而是開發過程中持續分類所產生的副產品。

**對新人上手而言：** 新進代理會繼承程式碼庫的完整脈絡。它們看到的不只是程式碼本身，還有塑造出這些程式碼的種種決策。

## 目前狀態

截至目前為止：
- 已透過此管線處理 **15,637 筆提交**
- 已擷取並記錄 **476 項架構決策**
- 已記錄 **6,799 則變更日誌條目**
- 兩個領域的涵蓋率皆為 **100%**

自我們開始執行以來，每一筆提交都已完成分類，組織記憶完整且可查詢。

## 開始使用

若你想實作類似的機制：

1. **從 Conventional Commits 格式開始。** 當提交具備結構化前綴（`feat:`、`fix:`、`chore:`）時，挖掘管線的效果最好。

2. **定義你的領域。** 我們使用像 `pipeline`、`agent-design`、`observability`、`data-modeling` 這樣的領域，用以依區塊整理決策。

3. **養成分類的習慣。** 當團隊定期為提交分類時，挖掘機制才會奏效；搭配 LLM 協助的批次處理，有助於擴大規模。

4. **讓決策可被查詢。** 當代理能透過 CLI 搜尋決策時，其價值會不斷複利累積；請將輸出結構化，以利機器讀取。

5. **閉合這個迴圈。** 決策應該影響未來的工作，請在代理指令與程式碼審查檢查清單中納入決策參照。

目標並非追求完美的文件，而是讓變更背後的*原因*，無論是今天還是六個月後，都能讓人類與 AI 同樣觸手可及。當變更化為組織記憶，團隊便能在既有模式的基礎上持續建構，而不必一再重新發明。

---

*這套挖掘工作流程是我們協調引擎的一部分，具體來說，屬於我們協調套件中的情境引擎模組。*
