·

Quy trình Thực tế: Tài liệu từ Code & Code từ Đặc tả

Đi qua một quy trình thực tế dùng Confluence MCP để AI agent đọc và viết trang tài liệu từ đầu đến cuối.

Đây là bài tổng kết module — thay vì nói về một công cụ cụ thể, mình sẽ ghép các kỹ thuật đã học ở các bài trước (Claude Code, OpenCode, Gemini CLI, Cursor) thành một vòng lặp hoàn chỉnh: spec trên Confluence sinh ra code, code sinh ngược lại tài liệu, và toàn bộ vòng lặp này được tự động hóa để không phụ thuộc vào việc ai đó "nhớ" phải update tài liệu.

Đây chính là bài toán cốt lõi mà Confluence MCP giải quyết: xóa bỏ khoảng lệch (drift) giữa spec và code — thứ mà hầu như team nào cũng gặp sau vài tháng phát triển sản phẩm. Nội dung dưới đây mô tả một quy trình cụ thể, có thể áp dụng ngay, không phụ thuộc bạn đang dùng client MCP nào trong 4 client đã học.

Tổng Quan Quy Trình: Giữ Code Và Tài Liệu Confluence Luôn Đồng Bộ

Vòng lặp đồng bộ hai chiều gồm ba giai đoạn lặp lại liên tục trong chu kỳ phát triển:

┌─────────────────┐      đọc spec       ┌──────────────────┐
│  Confluence      │  ────────────────▶  │  AI Agent         │
│  (Spec Page)     │                     │  (scaffold code)  │
└─────────────────┘                     └──────────────────┘
        ▲                                         │
        │           sinh page từ code             │  code hoàn thiện
        │                                          ▼
┌─────────────────┐                     ┌──────────────────┐
│  Confluence      │  ◀────────────────  │  Source Code       │
│  (Doc Page)      │   annotation/diff   │  (implementation)   │
└─────────────────┘                     └──────────────────┘

Giai đoạn 1 — Spec → Code: Kỹ sư viết spec trên Confluence trước (hoặc product manager viết), AI agent đọc spec đó để scaffold cấu trúc code ban đầu (interface, function signature, file structure), sau đó người viết logic chi tiết.

Giai đoạn 2 — Code → Docs: Sau khi code hoàn thiện và merge, AI agent đọc lại code (hoặc annotation trong code) để sinh/cập nhật page tài liệu kỹ thuật — API reference, runbook, hoặc note bổ sung vào spec gốc.

Giai đoạn 3 — Automation liên tục: Thay vì chạy hai giai đoạn trên bằng tay mỗi lần, thiết lập trigger tự động (CI job, git hook) để agent tự chạy lại giai đoạn 2 mỗi khi có thay đổi code đáng kể, giữ tài liệu luôn "tươi" mà không cần con người nhớ phải làm.

Điểm mấu chốt để vòng lặp này bền vững lâu dài: mỗi page Confluence tham gia vào vòng lặp cần có convention rõ ràng — page nào là "nguồn spec" (con người sở hữu, AI chỉ đọc), page nào là "tài liệu sinh tự động" (AI sở hữu, con người không nên sửa tay trực tiếp). Trộn lẫn hai loại này trong cùng một page sẽ khiến automation ghi đè mất nội dung con người vừa thêm.

Mẹo: Đặt convention đặt tên rõ ràng ngay từ đầu — ví dụ mọi page do AI sở hữu hoàn toàn có label Confluence ai-generated, và ghi rõ trong tiêu đề hoặc dòng đầu page "Auto-generated — see source at [đường dẫn code]". Convention nhỏ này giúp cả team (và cả AI agent tương lai) phân biệt được page nào an toàn để ghi đè.

Bước 1: Đọc Spec Page Trên Confluence Và Scaffold Cấu Trúc Code

Giả sử team vừa viết xong spec cho một feature mới trên Confluence — page "Refund Processing — Spec v1" trong space PROD, mô tả luồng xử lý hoàn tiền cho đơn hàng bị lỗi.

Bước đầu tiên: yêu cầu agent đọc spec và scaffold cấu trúc code (chưa cần logic đầy đủ, chỉ cần khung sườn đúng kiến trúc):

Đọc Confluence page "Refund Processing — Spec v1" trong space PROD.
Dựa vào spec, tạo cấu trúc file sau trong src/services/refund/ (chỉ tạo
skeleton với function signature và comment mô tả, chưa cần implement
logic đầy đủ):
- refund-processor.ts (function chính processRefund)
- refund-validator.ts (validate điều kiện được hoàn tiền)
- refund-types.ts (type definition cho RefundRequest, RefundResult)

Sau khi tạo skeleton, in ra danh sách requirement từ spec chưa được
map vào function nào, để tôi biết phần nào cần bổ sung thêm file.

Bước quan trọng ở đây: yêu cầu agent tự báo cáo phần spec chưa map được vào code — đây là cách phát hiện sớm spec có mô tả mơ hồ hoặc thiếu, trước khi ai đó bắt đầu code logic chi tiết dựa trên một khung sườn không đầy đủ.

Sau khi review skeleton, engineer tiếp tục điền logic chi tiết (thường vẫn cần con người, đặc biệt với business logic phức tạp như tính phí, điều kiện hoàn tiền theo policy). Agent có thể hỗ trợ từng phần nhỏ:

Trong refund-validator.ts, implement function validateRefundEligibility
theo đúng điều kiện được nêu trong mục "Eligibility Rules" của spec
(đã đọc ở trên): đơn hàng phải trong 30 ngày, chưa từng hoàn tiền trước
đó, và trạng thái đơn hàng không phải "disputed".

Mẹo: Luôn yêu cầu agent liệt kê requirement chưa map được vào code ngay sau bước scaffold — đây là bước rẻ nhất để bắt lỗi spec thiếu sót, tốn vài giây gọi tool nhưng tiết kiệm hàng giờ debug sau này khi phát hiện ra một edge case quan trọng bị bỏ sót từ đầu.

Bước 2: Sinh Confluence Page Từ Code Annotation

Sau khi refund-processor.ts, refund-validator.ts hoàn thiện và đã qua code review, đến lúc cập nhật tài liệu để phản ánh implementation thật (không chỉ spec ban đầu, mà cả những quyết định phát sinh trong lúc code).

Nếu codebase có annotation chuẩn hóa (như đã giới thiệu ở bài Gemini CLI), tận dụng luôn:

/**
 * @confluence-doc
 * @summary Processes a refund request after validating eligibility rules.
 * @param request RefundRequest containing orderId, reason, and requested amount.
 * @returns RefundResult with status (approved/rejected/pending_review) and transactionId if approved.
 * @throws RefundValidationError when eligibility rules in the spec are not met.
 * @businessRule Refunds above $500 are routed to pending_review instead of auto-approval.
 */
export function processRefund(request: RefundRequest): RefundResult {
  // ...
}

Chú ý field @businessRule — đây là chi tiết phát sinh trong lúc implement (ngưỡng $500 route sang manual review) mà rất có thể không có trong spec gốc, vì đây là quyết định kỹ thuật/nghiệp vụ được thêm vào khi code. Đây chính là loại thông tin quan trọng nhất cần đưa ngược lại Confluence — nó lấp đầy khoảng trống giữa "spec dự định" và "hệ thống thực tế đang chạy".

Prompt sinh tài liệu:

Tìm tất cả function có annotation @confluence-doc trong src/services/refund/.
Cập nhật Confluence page "Refund Processing — Spec v1" (đọc lại version
mới nhất trước khi update), thêm một mục mới ở cuối page: "Implementation
Notes (Auto-Generated)". Trong mục này, với mỗi function, ghi rõ signature,
@summary, và đặc biệt highlight riêng mọi @businessRule tìm được thành
một bảng riêng "Business Rules Not in Original Spec" để reviewer dễ
nhận ra phần phát sinh so với spec ban đầu.

Việc tách riêng "Business Rules Not in Original Spec" thành một bảng nổi bật (không lẫn vào phần mô tả function chung) là chi tiết nhỏ nhưng quan trọng — nó biến page tài liệu từ "bản sao code dưới dạng văn xuôi" thành công cụ thực sự giúp product manager hoặc reviewer nhận ra ngay những quyết định kỹ thuật ảnh hưởng tới nghiệp vụ mà họ cần biết.

Mẹo: Luôn tách riêng phần "phát sinh so với spec gốc" thành mục nổi bật khi update tài liệu, đừng trộn chung với phần mô tả thông thường — người đọc (đặc biệt là non-engineer) cần thấy ngay đâu là chỗ thực tế khác với những gì họ đã được thông báo ban đầu.

Bước 3: Thiết Lập Automation MCP Để Giữ Docs Và Code Luôn Đồng Bộ

Chạy tay hai bước trên mỗi lần có thay đổi là không bền — cách chắc chắn để tài liệu không bị lỗi thời là gắn nó vào pipeline CI, chạy tự động mỗi khi có PR merge vào nhánh chính.

Ví dụ với GitHub Actions, dùng Claude Code chạy ở chế độ non-interactive (claude -p) sau khi merge:

name: Sync Confluence Docs
on:
  push:
    branches: [main]
    paths:
      - 'src/services/refund/**'

jobs:
  sync-docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Claude Code
        run: npm install -g @anthropic-ai/claude-code

      - name: Sync Confluence documentation
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          CONFLUENCE_API_TOKEN: ${{ secrets.CONFLUENCE_BOT_TOKEN }}
        run: |
          claude -p "Tìm tất cả function có annotation @confluence-doc trong
          src/services/refund/ vừa thay đổi ở commit này. Cập nhật Confluence
          page 'Refund Processing — Spec v1' trong space PROD, mục
          'Implementation Notes (Auto-Generated)', đọc version mới nhất
          trước khi update để tránh conflict." \
          --mcp-config .mcp.json \
          --allowedTools "mcp__confluence__confluence_search,mcp__confluence__confluence_get_page,mcp__confluence__confluence_update_page"

Vài điểm quan trọng khi thiết kế automation loại này:

Dùng service account riêng cho bot CI, không dùng token cá nhân. Biến CONFLUENCE_BOT_TOKEN nên gắn với một service account chỉ có quyền vào space cần thiết (PROD), tách biệt hoàn toàn với token cá nhân của engineer — giúp audit log rõ ràng đâu là hành động của bot, đâu là của người.

Giới hạn --allowedTools chặt trong CI. Trong môi trường không có người ngồi confirm permission prompt, chỉ cho phép đúng những tool cần thiết (search, get_page, update_page) — tuyệt đối không thêm confluence_delete_page vào allowlist của job automation.

Trigger theo path, không chạy toàn bộ repo mỗi lần. Dùng paths: filter trong GitHub Actions để job chỉ chạy khi thư mục liên quan thay đổi, tránh gọi Confluence API không cần thiết (và tránh chi phí LLM) cho những commit không liên quan tới phần có tài liệu cần sync.

Có cơ chế thông báo khi job fail. Nếu bước update Confluence fail (ví dụ version conflict vì có người vừa sửa page tay), job nên gửi thông báo vào Slack channel của team thay vì fail âm thầm — để không ai nhận ra tài liệu đã lệch khỏi code trong nhiều tuần.

Mẹo: Bắt đầu automation này ở chế độ "dry-run" trước — cho job chạy nhưng chỉ in ra nội dung sẽ update (không thực sự gọi confluence_update_page), gửi kết quả vào Slack để team review trong 1-2 tuần đầu. Chỉ khi tin tưởng chất lượng output ổn định, mới chuyển sang chế độ tự động update thật, giảm rủi ro để bot ghi sai lên tài liệu quan trọng của cả team.

Mẹo Và Lưu Ý Thực Chiến

Tổng kết những nguyên tắc quan trọng nhất sau khi triển khai vòng lặp Confluence MCP đồng bộ hai chiều cho nhiều team:

  • Vòng lặp này chỉ bền vững khi có convention rõ ràng phân biệt "spec do người viết" và "doc do AI sinh" — đừng để AI tự do sửa page mà con người cũng đang chủ động edit, sẽ dẫn tới xung đột version liên tục.
  • Annotation chuẩn hóa trong code (@confluence-doc, @businessRule...) là đầu tư đáng giá — nó biến việc sinh tài liệu từ "agent tự đọc và suy diễn toàn bộ code" (dễ sai, dễ generic) thành "agent trích xuất dữ liệu có cấu trúc" (chính xác, nhất quán).
  • Automation CI nên bắt đầu ở chế độ dry-run/review trước khi cho tự động ghi thật — không có automation nào nên được tin tưởng 100% ngay từ ngày đầu triển khai.
  • Định kỳ (quý một lần là hợp lý) rà lại toàn bộ page có label ai-generated, kiểm tra xem còn khớp với annotation/code hiện tại không — annotation cũng có thể bị xóa hoặc đổi mà không ai cập nhật lại doc tương ứng nếu job CI bị tắt âm thầm.

Mẹo: Việc quan trọng nhất không phải là chọn công cụ MCP client nào (Claude Code, Cursor, Gemini CLI, OpenCode đều làm được việc này) — mà là thiết kế đúng ranh giới trách nhiệm giữa người và AI trong vòng lặp tài liệu. Dành thời gian workshop với team để thống nhất convention này trước khi viết automation, sẽ tiết kiệm được rất nhiều công dọn dẹp về sau.