Khai thác vòng lặp: Làm sao các thay đổi trở thành ký ức tổ chức
> Các commit Git trở thành các mục changelog có cấu trúc và các bản ghi quyết định kiến trúc, sau đó được đưa trở lại vào AI agent như một ký ức tổ chức có thể truy vấn.
Các con số trong bài này phản ánh hệ thống tại thời điểm xuất bản (tháng 2/2026). Xem trang team của chúng tôi để biết số liệu hiện tại.
Mọi đội kỹ thuật đều đối mặt với cùng một thách thức: các thay đổi diễn ra liên tục, nhưng cái lý do đằng sau những thay đổi đó lại biến mất. Sáu tháng sau, ai đó hỏi “tại sao chúng ta lại chọn DuckDB cho các giai đoạn pipeline?” và câu trả lời chỉ tồn tại trong đầu người đã đưa ra quyết định đó — nếu người đó vẫn còn ở đây.
Chúng tôi đã xây dựng một quy trình khai thác (mining workflow) khép kín vòng lặp này. Các thay đổi chảy qua các commit git, được xử lý bởi pipeline khai thác của chúng tôi, trở thành các mục changelog có cấu trúc và các bản ghi quyết định kiến trúc, sau đó được đưa trở lại vào các AI agent của chúng tôi thông qua các truy vấn CLI. Kết quả: một ký ức tổ chức mà cả con người và AI đều có thể truy cập.
Vấn đề: Quyết định bốc hơi
Hãy xem xét một kịch bản điển hình. Một developer commit:
feat(canonical): add DuckDB runtime for pipeline stages
Commit này đại diện cho một lựa chọn kiến trúc quan trọng. Đội đã đánh giá các phương án, cân nhắc sự đánh đổi, và chốt DuckDB vì những lý do cụ thể. Nhưng toàn bộ ngữ cảnh đó sống trong:
- Một luồng Slack (có lẽ đã bị xóa)
- Ký ức của ai đó (chắc chắn đang phai mờ)
- Một comment trong mã (có thể, nếu may mắn)
Ba tháng sau, một thành viên mới trong đội hỏi: “Tôi nên dùng DuckDB hay SQLite cho giai đoạn mới này?” Không có ký ức tổ chức, họ hoặc phải phát minh lại bánh xe hoặc đưa ra những lựa chọn không nhất quán.
Vòng lặp: Từ Commit đến ngữ cảnh
Quy trình khai thác của chúng tôi biến lịch sử git thành tri thức có thể truy vấn:
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) │
└───────────────┘
Insight cốt lõi: cả changelog lẫn quyết định kiến trúc đều chảy ra từ cùng một lịch sử git, được xử lý qua một pipeline thống nhất. Điều này đảm bảo không có gì lọt qua kẽ hở.
Cách khai thác hoạt động
Bước 1: Đồng bộ chỉ mục
uv run orkestra mine sync
Lệnh này quét lịch sử git và xây dựng một chỉ mục của tất cả các commit. Nó trích xuất các tín hiệu có cấu trúc từ mỗi commit:
- Loại commit theo quy ước (conventional commit type) (
feat,fix,chore,docs) - Scope (package hoặc khu vực nào)
- Các dấu hiệu breaking change
- Các file bị động đến và các chỉ số độ phức tạp
Bước 2: Kiểm tra trạng thái độ phủ
uv run orkestra mine status
Đây là trạng thái hiện tại của chúng tôi trông như thế nào:
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 commit đã được xử lý. 476 trở thành quyết định kiến trúc. 6.799 trở thành mục changelog. Mọi commit đều được phân loại.
Bước 3: Lấy các ứng viên để rà soát
uv run orkestra mine candidates --limit 50 --full
Lệnh này làm nổi lên những commit chưa được xử lý, kèm đầy đủ ngữ cảnh để phân loại:
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}
}
Các tín hiệu giúp định hướng việc phân loại: is_releasable_type: true gợi ý rằng commit này nên xuất hiện trong changelog. Số lượng dòng thêm vào lớn và các file hạ tầng gợi ý rằng nó cũng có thể là một quyết định kiến trúc.
Bước 4: Phân loại commit
Hai con đường tách nhánh ở đây: mục changelog và quyết định kiến trúc.
Đối với mục changelog:
uv run orkestra mine classify abc123 --changelog added
Điều này ghi nhận rằng commit abc123 nên xuất hiện trong changelog dưới danh mục “Added.”
Đối với quyết định kiến trúc:
Trước tiên, lấy một decision ID thật:
uv run orkestra decisions new --domain pipeline --dry-run
# Returns: DEC-PL-143
Sau đó phân loại kèm decision ID đó:
uv run orkestra mine classify abc123 --decision DEC-PL-143
Điều này liên kết commit với một bản ghi quyết định sẽ được tạo mới hoặc cập nhật.
Đối với xử lý theo lô (điều chúng tôi thực sự làm):
# Generate classifications file with LLM assistance
uv run orkestra mine commit --input classifications.jsonl
Định dạng JSONL hỗ trợ cả hai domain trong một lượt:
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"}
Bước 5: Render đầu ra
uv run orkestra changelog render --package <pkg>
Điều này sinh ra các file CHANGELOG.md cho từng package từ ledger. Các changelog là các tài sản dẫn xuất — xóa chúng đi và chúng sẽ được tái sinh hoàn hảo từ ledger nguồn.
Cấu trúc bản ghi quyết định
Các quyết định đã trích xuất trở thành các file YAML với metadata phong phú:
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
Mọi quyết định đều liên kết ngược về các commit nguồn của nó. Mọi quyết định đều chỉ rõ những file nào nó ảnh hưởng. Các quan hệ giữa các quyết định là tường minh.
Tích hợp CLI: Truy vấn ký ức tổ chức
Đây là nơi vòng lặp khép lại. Các agent có thể truy vấn quyết định qua CLI:
# Search by topic
uv run orkestra decisions search --query "retry"
Trả về các quyết định về logic thử lại, xử lý lỗi, các mẫu khôi phục.
# Get full details on a specific decision
uv run orkestra decisions info DEC-PL-142
Trả về bản ghi quyết định đầy đủ kèm ngữ cảnh, lý do, và tác động.
# List recent decisions for context
uv run orkestra decisions list --limit 15
Cho thấy những lựa chọn kiến trúc nào đã được thực hiện gần đây.
Cách các agent sử dụng điều này
Các chỉ dẫn nền tảng của orchestrator của chúng tôi bao gồm:
**Essential CLI commands:**
- `orkestra decisions search "X"` — Find architectural decisions
Khi một agent được yêu cầu triển khai thứ gì đó liên quan đến DuckDB, nó có thể kiểm tra trước:
uv run orkestra decisions search --query "DuckDB"
Và khám phá ra DEC-PL-142, học được:
- Vì sao chúng tôi chọn DuckDB (context)
- Cách dùng nó đúng cách (agent_guidance)
- Những file nào cần xem (files)
- Những quyết định liên quan nào tồn tại (related)
Agent không phát minh lại bánh xe. Nó xây dựng dựa trên các mẫu đã được thiết lập.
Bài kiểm tra ba câu hỏi
Không phải commit nào cũng xứng đáng có một bản ghi quyết định. Chúng tôi dùng Bài kiểm tra ba câu hỏi để lọc:
- Việc này có khó để đưa ra không? Nó có đòi hỏi phân tích đáng kể, đánh giá sự đánh đổi, hoặc tranh luận không?
- Việc thay đổi nó có tốn kém không? Việc đảo ngược quyết định này có đòi hỏi phải làm lại đáng kể không?
- Nó có tác động toàn hệ thống không? Nó có ảnh hưởng đến nhiều package hoặc thiết lập các mẫu mà những người khác sẽ tuân theo không?
Nếu một commit trả lời “có” cho ít nhất một trong các câu hỏi này, nó là ứng viên để trích xuất thành quyết định. Tỷ lệ điển hình của chúng tôi: 1-4 quyết định trên mỗi 100 commit (khoảng 1-4%).
Đối với các mục changelog, thanh chắn thấp hơn: bất kỳ thay đổi nào hướng đến người dùng (tính năng, sửa lỗi, cải tiến) đều được ghi lại. Các công việc vặt nội bộ, cập nhật tài liệu, và refactor thường bị bỏ qua. Tỷ lệ điển hình của chúng tôi: 30-50 mục changelog trên mỗi 100 commit.
Lưu trữ dữ liệu: Ledger chỉ-thêm (Append-Only)
Hệ thống khai thác dùng các ledger JSONL chỉ-thêm để vận hành đa agent không xung đột:
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
└── ...
Định dạng JSONL với merge=union trong .gitattributes nghĩa là nhiều agent có thể phân loại commit đồng thời mà không có xung đột merge. Mỗi dòng độc lập với nhau.
Cổng xác thực
Trước mỗi phiên khai thác, chúng tôi chạy xác thực:
uv run orkestra mine validate --quick
Điều này kiểm tra:
- Tính hợp lệ của định dạng SHA
- Sự tuân thủ định dạng decision ID
- Không có mục trùng lặp cho cùng một SHA
- Các quyết định được tham chiếu thực sự tồn tại
Sau khi phân loại, chúng tôi xác thực lại lần nữa trước khi commit các thay đổi.
Vì sao điều này quan trọng
Vòng lặp phản hồi mà chúng tôi đã xây dựng giải quyết một số vấn đề:
Đối với thành viên mới trong đội: Thay vì hỏi “tại sao chúng ta lại làm X?”, họ có thể tìm kiếm trong registry quyết định. Ngữ cảnh được bảo toàn.
Đối với AI agent: Chúng không hoạt động trong chân không. Chúng có thể truy vấn tri thức tổ chức trước khi đưa ra đề xuất. Khi được yêu cầu thêm một giai đoạn pipeline mới, chúng có thể khám phá ra mẫu DuckDB và làm theo.
Đối với tính nhất quán kiến trúc: Các quyết định tường minh và có thể tìm kiếm được. Khi ai đó đề xuất một cách tiếp cận mâu thuẫn với một quyết định hiện có, hệ thống có thể làm nổi lên xung đột đó.
Đối với việc sinh changelog: Ghi chú phát hành không phải là một cuộc chạy đua vào phút chót. Chúng là sản phẩm phụ của việc phân loại liên tục trong suốt quá trình phát triển.
Đối với onboarding: Các agent mới thừa hưởng toàn bộ ngữ cảnh của codebase. Chúng không chỉ thấy mã nguồn — chúng thấy cả những quyết định đã định hình nên nó.
Trạng thái hiện tại
Tính đến hôm nay:
- 15.637 commit đã được xử lý qua pipeline
- 476 quyết định kiến trúc đã được trích xuất và ghi lại tài liệu
- 6.799 mục changelog đã được ghi nhận
- Độ phủ 100% trên cả hai domain
Mọi commit kể từ khi chúng tôi bắt đầu đều đã được phân loại. Ký ức tổ chức đã hoàn chỉnh và có thể truy vấn được.
Bắt đầu
Nếu bạn muốn triển khai một thứ tương tự:
-
Bắt đầu với conventional commit. Pipeline khai thác hoạt động tốt nhất khi các commit có tiền tố có cấu trúc (
feat:,fix:,chore:). -
Định nghĩa các domain của bạn. Chúng tôi dùng các domain như
pipeline,agent-design,observability,data-modeling. Chúng tổ chức các quyết định theo khu vực. -
Xây dựng thói quen phân loại. Việc khai thác chỉ hiệu quả khi các đội thường xuyên phân loại commit. Xử lý theo lô với sự hỗ trợ của LLM giúp mở rộng quy mô.
-
Làm cho quyết định có thể truy vấn được. Giá trị tăng lên khi các agent có thể tìm kiếm quyết định qua CLI. Cấu trúc đầu ra của bạn để máy có thể tiêu thụ được.
-
Khép kín vòng lặp. Các quyết định nên ảnh hưởng đến công việc trong tương lai. Đưa các tham chiếu quyết định vào chỉ dẫn agent và checklist rà soát mã.
Mục tiêu không phải là tài liệu hoàn hảo. Đó là làm cho cái lý do đằng sau các thay đổi trở nên dễ tiếp cận với cả con người và AI, ngay hôm nay và sáu tháng nữa. Khi các thay đổi trở thành ký ức tổ chức, các đội xây dựng dựa trên các mẫu đã được thiết lập thay vì phát minh lại chúng.
Quy trình khai thác là một phần của engine orchestration của chúng tôi, cụ thể là module context engine trong package orchestration của chúng tôi.
Đọc thêm liên quan
Thêm từ nhật ký xây dựng Maguyva
Vì sao chúng tôi nâng cấp tìm kiếm mã nguồn lên voyage-4-large_
Chúng tôi chuyển embedding mã nguồn sang voyage-4-large — hiện đang dẫn đầu bảng xếp hạng công khai RTEB cho truy xuất mã nguồn. Phiên bản thành thật: sự đánh đổi chúng tôi chấp nhận, những gì chúng tôi thực sự lập chỉ mục, và vì sao chúng tôi trả tiền cho embedding cao cấp.
Tự cải thiện đệ quy theo ngôn ngữ: Mài giũa trí tuệ mã nguồn trên khoảng 280 ngôn ngữ_
Chúng tôi hỗ trợ trí tuệ mã nguồn cho khoảng 280 ngôn ngữ. Không con người nào có thể tự tay rà soát hết được. Vì vậy chúng tôi xây dựng một vòng lặp tự cải thiện đệ quy theo ngôn ngữ — kiểm tra ngẫu nhiên, dùng LLM làm giám khảo, sửa từng thứ một, xác thực lại — và chạy nó với một đội quân agent cách ly cho đến khi việc trích xuất thực sự đúng, chứ không chỉ xanh (green).
Tìm kiếm hợp nhất đa phương thức: Chọn đúng bộ truy xuất cho mọi truy vấn_
Một truy vấn như 'parseConfig được định nghĩa ở đâu' cần một kiểu tìm kiếm khác với 'auth hoạt động như thế nào'. Maguyva phân loại ý định, gán trọng số cho bốn phương thức truy xuất tương ứng, và hợp nhất kết quả bằng Reciprocal Rank Fusion có trọng số.