
Buổi 4 — Quản trị AI Engineering
Buổi 4 — Quản trị AI Engineering
Một team chạy nhanh suốt ba tháng. Sang tháng thứ tư yêu cầu đổi — hồ sơ vay cần thêm video xác thực người vay. Hai tuần công. Không phải vì thay đổi đó khó, mà vì phần việc chính là ngồi hiểu lại đống code AI đã sinh ra.
Đó là kiểu thất bại mà Buổi 4 nói tới. Team đi rất nhanh nhưng không để lại đủ dấu vết để quay lại an toàn.
Về bài viết này
Đây là ghi chép của tôi từ Ngày 4 khoá AI-Driven Software Development Life-Cycle, giảng viên TS. Bùi Thị Mai Anh, Trường Công nghệ Thông tin và Truyền thông (SOICT), Đại học Bách Khoa Hà Nội, tháng 7/2026. Khung tư duy và thiết kế workshop là của cô; phần tóm tắt và câu chữ ở đây là của tôi. Các prompt trích bên dưới lấy nguyên từ workbook của khoá học — chúng là của cô, không phải của tôi.
Bài nối tiếp Buổi 1, Buổi 2 và Buổi 3. Bài cũng có bản tiếng Anh.
Context debt
Khoá học đặt tên cho tình trạng này:
Context debt là tình trạng tri thức kỹ thuật và nghiệp vụ không còn được lưu giữ trong các engineering artifact, mà chỉ tồn tại trong trí nhớ con người hoặc lịch sử hội thoại với AI.
Technical debt thì nhìn thấy trong code. Context debt thì vô hình cho tới lúc có người hỏi một câu mà không ai trả lời được.
Ba câu hỏi phơi nó ra:
"Sao chỗ này là premium?" — "Hồi tháng 3 PO nói vậy." — "Có tài liệu không?" — "Không." Khi logic nghiệp vụ chỉ tồn tại trong đầu những người cũ, hoặc trong code, thì team đang vibe coding dù có thể họ không nhận ra.
"Verified nghĩa là gì?" Rule là Verified = OCR AND valid ID AND face match AND blacklist check. Unit test đang kiểm tra implementation chứ không kiểm cái rule đó. Behavior test bảo vệ nghiệp vụ; implementation test chỉ bảo vệ hình dạng hiện tại của code.
"PO đổi rule sau hai tháng." Ban đầu: chỉ giải ngân khi khách đã được xác thực. Giờ: khách VIP được giải ngân trước, hoàn tất xác thực trong 24 giờ. Nếu traceability tốt, bạn biết chính xác những use case, acceptance criteria, test case và module nào bị chạm. Không có nó thì đi mò.
Phân loại thất bại
Thất bại được xếp nhóm, vì mỗi nhóm cần một cách chữa khác nhau.
Context Loss
| Kiểu | Nó trông như thế nào |
|---|---|
| Requirement Drift | Code đổi, requirement không đổi |
| Incomplete Spec | AI không thể sinh ra hành vi mà spec không mô tả — mỗi spec nên có ##History |
| Domain Language | Đặt tên nghèo nàn tới mức model không có gì để suy luận |
Ví dụ về domain language là thứ sắc nhất trên slide. So hai prompt:
A: Tạo service quản lý
tbl_dh_v2với các cộtid,ma_kh,tong_tien,tt,ngay_tao,ngay_cap_nhat.
B: Tạo service quản lý
Order. MộtOrdercó nhiềuOrderItem, thuộc về mộtCustomer, có mộtPaymentsau khi thanh toán, và có trạng tháidraft,awaiting_payment,paid,cancelled.
Cùng một cái bảng. Cái thứ hai cho model ngữ nghĩa để suy luận; cái thứ nhất cho nó sáu chuỗi ký tự mù mờ. Và một cái bẫy liên quan: cùng một thuật ngữ nằm ở các spec khác nhau thì AI hiểu khác nhau mỗi lần — nên một ghi chú giải thích ngắn cạnh thuật ngữ là đáng chỗ.
Engineering Failures
| Kiểu | Dấu hiệu | Hậu quả |
|---|---|---|
| Wrong AI Decision | Rule có trong code nhưng không có trong spec | Logic nghiệp vụ sai — mà test vẫn pass |
| Architecture Erosion | Cùng một business rule bị nhân bản qua các feature | Single source of truth lặng lẽ biến mất |
| False Test Confidence | Test chạm vào implementation chứ không phải business rule | Bộ test xanh, hành vi không được bảo vệ |
Về erosion, ý rất cụ thể: AI tăng tốc architecture erosion khi mỗi feature được sinh ra độc lập mà không bị ràng buộc bởi cùng một kiến trúc và engineering context.
Cái case đã xảy ra thật
Đây mới là chỗ buổi học đắt. Trong lúc chuẩn bị bài giải mẫu cho chính khoá này, kịch bản mà Buổi 1 cảnh báo đã xảy ra thật.
Nhánh day03 được lập trình theo một bản đặc tả 1-file đã lỗi thời — bản nháp tự nhận là "Frozen Business Rules" nhưng thực chất đã bị thay thế — thay vì bộ chín file Specification Package v1.0 FROZEN chính thức.
Hậu quả:
- Sai mô hình dữ liệu — thiếu
medical_priority, thiếu bảng auditoffer_events - Sai phân quyền — bệnh nhân tự đăng ký, trong khi spec nói chỉ staff
- Chọn ứng viên theo FIFO thuần thay vì ưu tiên y tế
- Một Notification Service mà spec thật cấm tuyệt đối, vẫn được code ra vì bản nháp cũ đòi nó
Không ai phát hiện. Và lý do không ai phát hiện mới là phần đáng nhớ:
Bộ test của bản nháp cũ pass 100% — vì nó kiểm chứng hệ thống theo đúng cái hiểu sai mà hệ thống được dựng lên từ đó. Một bộ test tự nhất quán không phải là một bộ test đúng. Chỉ một audit độc lập đối chiếu trực tiếp code với spec FROZEN mới tìm ra.
Rồi một audit thứ hai, sâu hơn — sau khi viết lại, với bộ test 37/37 xanh — tìm thêm năm lỗ hổng reliability thật (một transaction thiếu, một công tắc an toàn chưa test, code chết) và ba acceptance criteria không có test nào chạm tới.
Spec-centric, và câu hỏi waterfall
Câu trả lời cho tất cả những chuyện trên là đặt spec vào trung tâm: spec là nơi team thống nhất mình đang làm gì, AI viết code và test và doc xoay quanh nó, và khi có gì sai thì sửa spec rồi mới sửa code.
Việc đó dẫn tới một phản biện hiển nhiên: vậy có phải quay lại waterfall không?
Cách phân biệt khoá học đưa ra đáng giữ. Làm việc kiểu spec-centric lấy cái waterfall đúng — yêu cầu rõ ràng, truy vết được, kiểm thử được — và bỏ đi cái làm nó khổ: phê duyệt cứng nhắc, thiết kế trước mọi chi tiết, và sửa đổi thì tốn kém.
Sáu nguyên tắc quản trị
1 · Requirement-Centric. Đối lập với nó là prompt-centric, và câu trên slide rất đắt: conversation trôi đi, business rule nằm lại trên prompt. Prompt là tạm thời và không được quản lý; tri thức dự án không nên phân tán trong các đoạn chat. Quy tắc: spec dẫn dắt code, không phải code dẫn dắt spec — một khái niệm mới xuất hiện trong code thì lẽ ra nó phải xuất hiện trong spec trước.
2 · AI-Assisted. AI rất hợp với việc có khuôn rõ: CRUD, mapping, sinh test theo AC đã có, sinh doc từ code và spec. AI không được tự quyết những phần có hệ quả business lớn — huỷ khoản vay, chính sách refund. Human quyết định đúng nghiệp vụ là gì, AI thực thi nhất quán.
3 · Iterative Improvement. Spec không cần hoàn hảo ngay từ đầu. Nó là living document. Cập nhật spec trước, AI sinh code sau.
4 · Test-Protected. Test là hàng rào để AI được phép viết lại mà không làm lệch hành vi. Cụ thể: mỗi acceptance criteria nên có ít nhất một test, và tên test hoặc annotation nên chứa UC ID cùng AC ID.
5 · Stakeholder-Centric. Spec chỉ thực sự có giá trị khi được xác nhận bởi người hiểu business context và business impact. Mỗi sprint: một approval từ business, một từ tech lead. Một feature cần hai góc nhìn — spec có được cài đặt đúng và không lệch kiến trúc không? và spec có đúng thực tế không, có thiếu rule "đương nhiên" nào không?
6 · Traceable. Từ code tìm được spec, từ spec tìm được test, từ test tìm được requirement. Traceability phải đi được ba chiều — business requirement ⇔ use case ⇔ code/test — để khi PO đổi yêu cầu, team biết chính xác những UC, AC, TC và module code nào cần sửa.
Workshop: các bước thực hiện
Sáu mươi phút, và đối tượng bị audit là chính sản phẩm Day 3 của nhóm. Buổi 1 bảo mọi người đoán xem ngữ cảnh sẽ đứt ở đâu. Buổi 4 kiểm lại xem nó có đứt thật không.
AI đóng vai AI-Assisted Auditor — đúng vai đã dùng để tạo ra bản audit ở trên. Nó được đối chiếu artifact giữa các phase, đối chiếu code với business rule đã chốt, tìm dead code bằng grep, và phác thảo nhãn nguyên nhân gốc cùng governance rule.
Nó không chịu trách nhiệm: quyết định một finding có đủ nghiêm trọng để chặn release không, quyết định governance rule nào khả thi với nhóm, hay xác nhận một artifact "khớp" khi việc đó cần hiểu ý định nghiệp vụ ban đầu — chỉ những người ngồi trong buổi họp yêu cầu ở Day 2 mới biết ý định thật.
Nguyên tắc lần này là Human-on-the-loop, kèm một điều kiện cứng: không để AI tự chấm "an toàn" mà không có bằng chứng trỏ tới file, dòng hay artifact cụ thể.
Bước 0 — Readiness Check. Xác nhận đủ năm artifact: SDLC Artifact Map của Day 1, Specification Package FROZEN của Day 2, Development Package của Day 3, QA Package của Day 3, và source code cùng test suite thật đang chạy. Câu hỏi thảo luận rất hay: nếu thiếu một artifact ở trên, bước audit nào bên dưới sẽ yếu đi trước tiên?
Bước 1 — SDLC Context-Drift Audit. Đây là audit thông tin, không phải audit code. Câu hỏi trung tâm: người hoặc AI ở phase sau có đọc đúng phiên bản mới nhất của artifact phase trước không? — chính câu hỏi mà case thật đã trả lời "không". Mỗi điểm đứt gãy cần ghi rõ nó nằm giữa hai phase nào, hậu quả cụ thể, và bằng chứng trích từ file kèm dòng.
Prompt — Context-Drift Audit
Bạn là AI-Assisted Auditor đang rà lại quy trình SDLC của một nhóm vừa hoàn thành
Day 1-3 của case study MedBook.
Dựa trên:
- SDLC Artifact Map của nhóm (Day 1)
- Specification Package đã dùng làm input cho Day 3 (Day 2)
- Development Package và source code thật đã sinh ra (Day 3)
Hãy đối chiếu và trả lời: Source code Day 3 có khớp với ĐÚNG phiên bản spec mới
nhất của Day 2 không? Chỉ ra bằng chứng cụ thể (tên bảng, tên endpoint, business
rule) - không kết luận chung chung "có vẻ khớp". Có artifact nào ở Day 2 bị thay
thế/cập nhật sau đó mà Day 3 vẫn dùng bản cũ không? Có quyết định nào ở Day 1
(Human-AI Responsibility Matrix, checkpoint) bị bỏ qua trong thực tế triển khai
Day 3 không?
Với mỗi điểm đứt gãy tìm được, ghi rõ: đứt gãy nằm giữa phase nào và phase nào,
hậu quả cụ thể, và bằng chứng (trích dẫn file + dòng hoặc đoạn artifact). Không
tự suy diễn nếu không có bằng chứng - đánh dấu "Cần xác nhận với nhóm".Bước 2 — Code & Test-Coverage Failure Analysis. Đọc trực tiếp source và test suite — không dùng báo cáo cũ, không suy đoán từ tên file — và ánh xạ từng business rule tới file hiện thực nó và test kiểm chứng nó. Nếu một phần của rule không có test nào chạm tới, đó là gap, không phải "covered". Hàm không được gọi ở đâu phải xác nhận là dead code bằng grep, không đoán. Và đoạn code có comment giải thích cái gì nhưng không giải thích vì sao chọn cách này thay vì quy ước chung của repo thì bị đánh dấu là thiếu ngữ cảnh.
Prompt — Audit code & coverage
Bạn là AI-Assisted Auditor. Đọc trực tiếp source code và test suite hiện có của
nhóm (không dùng báo cáo cũ, không suy đoán từ tên file) và đối chiếu với đúng
bản Business Rules đã FROZEN.
Với từng Business Rule:
- Trỏ tới đúng file/hàm hiện thực nó.
- Trỏ tới đúng test (nếu có) kiểm chứng nó, ghi rõ tên test.
- Nếu một phần của rule không có test nào chạm tới, ghi rõ đó là "gap", không
phải "covered".
- Nếu code có hàm không được gọi ở đâu cả (dùng grep xác nhận, không đoán), liệt
kê là dead code.
- Nếu một đoạn code có comment giải thích Ý NGHĨA nhưng không giải thích LÝ DO
CHỌN cách làm này thay vì cách làm mà quy ước phần còn lại của repo đang dùng,
đánh dấu là "thiếu ngữ cảnh".
Trình bày dưới dạng bảng: Business Rule -> File hiện thực -> Test kiểm chứng ->
Trạng thái (Có test / Gián tiếp / Không có test).Bước 3 — Phân loại nguyên nhân gốc. Mỗi finding gắn đúng một trong năm nhãn.
Prompt — Phân loại nguyên nhân gốc
Với danh sách finding ở Bước 1 và Bước 2, hãy gắn đúng 1 trong 5 nhãn nguyên nhân
gốc (Spec sai/thiếu · AI tự bịa khi thiếu ngữ cảnh · Human review bỏ sót ·
Process không có checkpoint · Kỹ thuật/concurrency) và mức độ (Critical / Major /
Minor).
Giải thích ngắn gọn vì sao chọn nhãn đó thay vì nhãn khác - đặc biệt phân biệt rõ
"AI tự bịa" với "Spec sai/thiếu" (AI tự bịa là khi spec KHÔNG nói gì và AI vẫn
quyết; Spec sai/thiếu là khi spec CÓ nói nhưng sai hoặc đã lỗi thời).
Không tự xếp một finding vào nhóm nhẹ hơn để "cho gọn".Workbook nói rõ chỗ người ta hay nhầm: AI tự bịa là khi spec không nói gì mà AI vẫn quyết; spec sai/thiếu là khi spec có nói nhưng sai hoặc đã lỗi thời. Nó cũng cảnh báo việc lặng lẽ xếp một finding vào nhóm nhẹ hơn để "cho gọn".
Bước 4 — Thiết kế Governance Charter. Từ nhóm nguyên nhân chiếm đa số, viết ba đến năm rule. Mỗi rule phải phát biểu hành động bắt buộc dưới dạng một điều kiện đúng/sai được, trỏ lại nó chặn nguyên nhân nào, nói rõ kiểm chứng bằng cách nào — công cụ tự động hay checklist có người ký — và nêu chủ sở hữu theo vai trò.
Ngưỡng được đặt bằng một phản ví dụ: "review kỹ hơn" không phải governance rule. Nó không kiểm chứng được và không ai chịu trách nhiệm khi bị bỏ qua. Rule mẫu của workbook cho thấy hình dạng đúng:
Trước khi bắt đầu coding task mới, AI phải trích dẫn lại đúng tên file + ngày FROZEN của spec đang dùng làm input, và Human xác nhận đó là bản mới nhất trước khi cho phép sinh code.
Và câu hỏi khép lại cả ngày: nếu áp dụng đúng Governance Charter vừa thiết kế từ đầu Day 3, sự cố ở case thật có xảy ra không?
Prompt — Governance Charter
Bạn là Technical Lead đang thiết kế governance cho quy trình AI-Assisted
Development của nhóm, dựa trên phân loại nguyên nhân gốc ở Bước 3.
Với mỗi nhóm nguyên nhân chiếm tỷ trọng đáng kể, đề xuất một governance rule cụ
thể gồm:
- Rule - hành động bắt buộc, diễn đạt như một điều kiện có thể đúng/sai (không
phải lời khuyên).
- Chặn nguyên nhân nào - trỏ lại đúng nhãn ở Bước 3.
- Cách kiểm chứng - bằng công cụ tự động (test, CI, lint) hay bằng checklist con
người ký xác nhận?
- Chủ sở hữu - vai trò nào (BA / Dev / QA / Tech Lead) chịu trách nhiệm rule này
không bị bỏ qua?
Ví dụ tham khảo (không copy nguyên văn, phải khớp với finding thật của nhóm):
"Trước khi bắt đầu coding task mới, AI phải trích dẫn lại đúng tên file + ngày
FROZEN của spec đang dùng làm input, và Human xác nhận đó là bản mới nhất trước
khi cho phép sinh code."
Không đề xuất rule chung chung không đo lường được (vd. "review kỹ hơn", "cẩn
thận khi prompt").Tôi rút ra được gì
Context debt vô hình theo đúng bản chất của nó. Technical debt hiện ra trong code; context debt chỉ hiện ra khi có người hỏi vì sao, và câu trả lời nằm trong trí nhớ ai đó hoặc một đoạn chat đã trôi mất.
Bộ test xanh là bằng chứng về tính nhất quán, không phải tính đúng. Nếu test sinh ra từ cùng một cách đọc spec với code, nó sẽ luôn đồng ý với code. Thứ duy nhất bắt được chuyện đó là đối chiếu code với spec.
Gọi đúng tên nguyên nhân gốc, không thì không sửa được. "Đây là bug" và "quy trình không bắt buộc ai xác nhận đang dùng phiên bản spec nào" dẫn tới hai hành động hoàn toàn khác nhau.
Governance rule không kiểm chứng được thì chỉ là khẩu hiệu. Điều kiện đúng/sai, chủ sở hữu có tên, cách kiểm rõ ràng. Thiếu những thứ đó thì nó chỉ là một lời nhắc hãy cẩn thận hơn — mà cẩn thận thì ai cũng đang cố rồi, ngay lúc sự cố xảy ra.