Vấn đề
AI coding agent viết code rất nhanh, nhưng hay đi tắt theo những kiểu dễ đoán. Agent báo “xong” mà không chạy lại test. Agent sửa cả những file không ai nhờ. Lỗi khó thấy nhất là khi cùng một agent viết cả code lẫn test: test thường “đồng ý” với chính lỗi của code, mọi thứ xanh, và bug vẫn lên production.
Cách thường gặp là viết file hướng dẫn dài hơn. Cách đó có ích, nhưng văn bản chỉ là lời nhờ. Model có thể bỏ qua, và mình chỉ phát hiện lúc review. Tôi muốn những quy tắc quan trọng được kiểm tra bằng thứ không phụ thuộc vào model: git, exit code và CI.
agent-playbook cài một khối quy tắc ngắn luôn bật cùng năm skill vào ba harness, trong đó có Claude Code và OpenCode. Phần lõi là TDD với ba vai trò tách biệt. Agent tester viết test fail, agent implementer làm test pass, agent reviewer chạy lại mọi thứ ở chế độ chỉ đọc. Tôi thiết kế quy tắc và các gate; phần lớn việc code do agent làm, dưới chính các gate đó.
Tôi đã làm gì
Ép vai trò bằng git thay vì niềm tin
Role gate xét mọi đường dẫn thay đổi so với một commit gốc, kể cả file đã stage, chưa stage và chưa track, rồi phân loại từng file thành test, code hoặc hạ tầng test dựa trên một mẫu đường dẫn. Mỗi vai trò có một tập được phép. Tester chỉ được sửa test, implementer chỉ được sửa code, reviewer không được sửa gì. Chỉ cần một file vượt ranh giới là gate thoát với mã 1 và nêu tên file. Ghi chú bàn giao và log bằng chứng nằm trong một thư mục mà gate luôn cho qua.
Đánh đổi: gate kiểm tra theo đường dẫn. Nó không bắt được implementer cài điều kiện đặc biệt cho dữ liệu test ngay trong code production. Vai trò reviewer tồn tại để lo việc đó, và README ghi rõ điều này.
Fail closed khi cấu hình sai
Dự án có thể ghi đè mẫu đường dẫn test. Nếu giá trị ghi đè rỗng hoặc sai cú pháp, một phép kiểm tra ngây thơ sẽ khớp không file nào, hoặc khớp tất cả, và mọi file lặng lẽ lọt qua. Gate từ chối chạy và thoát với một mã lỗi cấu hình riêng. File snapshot cũng được tính là test: implementer sửa snapshot thì test fail sẽ pass mà hành vi không đổi. Cái giá là dự án nào có file snapshot không phải test thì phải tự đặt mẫu của mình.
Coi tính di động là yêu cầu bắt buộc
Các script là Bash thuần, không phụ thuộc gì thêm. CI chạy toàn bộ bộ test trên Ubuntu, trên macOS (Bash 3.2 và công cụ BSD) và trên Windows qua Git Bash. Windows khởi động process chậm nên bộ test được chia ba shard, phân bổ tham lam theo thời gian đo được của từng suite. Dùng Bash cũ nghĩa là bỏ một số tính năng shell mới, và test runner phải tự xử lý phần thiếu.
Chỉ release thứ mà main đã chứng minh
Tag phiên bản không chạy lại test. Job release chờ lần chạy trên nhánh main của cùng commit, yêu cầu nó thành công, kiểm tra tag, file version và changelog khớp nhau, và không bao giờ ghi đè release đã có. Release chậm hơn một chút; đổi lại không release nào đi ra từ code chưa được test.
Chọn độ nặng quy trình theo rủi ro
Không phải thay đổi nào cũng cần ba agent. Playbook có ba mức Full, Lite và Exempt. Một bước kiểm tra kích thước đếm số file production và số dòng thay đổi (mặc định 3 file, 100 dòng) và đẩy thay đổi “nhỏ” nhưng thật ra quá lớn lên mức Full.
Kết quả
Đến nay repo có 165 commit và 17 bản release có tag, mới nhất là v0.16.0. Lần chạy main gần nhất xanh trên cả ba hệ điều hành, và log Ubuntu cho thấy 2,325 test pass trong 21 suite, không test nào fail. Installer chỉ sửa các khối nó quản lý, giữ bản backup và có thể rollback về tag cũ. Dự án vẫn đang ở giai đoạn alpha.
Nếu làm lại
Gate chỉ biết đường dẫn, nên tôi sẽ đưa bước mutation spot-check từ checklist của reviewer vào CI. Tôi cũng sẽ chạy behaviour eval trên nhiều model và phiên bản harness hơn; hiện kết quả có ngày tháng mới bao phủ một bản harness. Quy tắc bằng văn bản vẫn phụ thuộc vào việc model có làm theo hay không, và tôi sẽ tiếp tục chuyển dần chúng thành kiểm tra tự động.