SDD-057 - Error Learning
Nguyên tắc: Một lỗi đã gặp thì không được gặp lại theo cùng một đường. Ghi nhận lỗi chưa đủ; mỗi lỗi phải đổi lấy một chốt chặn do MÁY thi hành, đặt càng gần lúc sinh code càng tốt.
Lý do có domain này: trong 30 ngày đo (§6), CI đỏ 463 lần, khoảng 15 lần mỗi ngày, và phần lớn là cùng một vài lỗi lặp lại. Mỗi lần CI đỏ trên main là deploy của mọi phiên đứng lại. Bài học cũ chủ yếu được ghi thành memory, nhưng memory là thứ agent sau CÓ THỂ đọc; chốt chặn là thứ agent sau KHÔNG THỂ vượt qua.
1. Phạm vi: nguồn lỗi (REQ-NFR-16)
| Nguồn | Thu gì | Cách đọc |
|---|---|---|
| GitHub Actions | Mọi run failure, startup_failure, cancelled; tên job, tên bước hỏng, log bước hỏng | gh api .../actions/runs, gh run view --log-failed |
| Cloudflare Workers | Exception theo worker (scriptThrewException, exceededResources), tỉ lệ trên tổng lượt gọi | GraphQL workersInvocationsAdaptive |
| Cloudflare deploy và D1 | Deploy hỏng, migration hỏng | Đã nằm trong log GitHub Actions vì deploy chỉ đi qua CI (skill deploy) |
| Cloudflare lỗi 5xx do code tự trả | Response 5xx không ném exception | Cần bật Workers Logs; chưa đo được, xem §7 |
clientDisconnected (người dùng đóng tab giữa chừng) không phải lỗi và không vào sổ.
2. Sổ lỗi và fingerprint (REQ-NFR-16)
Mỗi lần lỗi là một dòng: nguồn, thời điểm, commit, nhánh, app hoặc worker, tên bước, đoạn log lỗi. Nhiều dòng cùng một fingerprint là cùng một lỗi.
Fingerprint lấy từ các dòng đánh dấu lỗi (##[error], ✗, FAIL, error TS, [chromium] ›) sau khi chuẩn hoá: bỏ hash commit, số dòng và cột, thời lượng, mọi con số. Dòng log phụ của test đang XANH (vd KV down trong test cố ý giả lỗi) không được tính; phép đo nền đã dính đúng bẫy này ở lượt đầu và đếm nhầm 355 run thành "lỗi Cloudflare".
Mỗi fingerprint mang: số lần gặp, lần đầu, lần gần nhất, loại (§3), chốt chặn (§4), trạng thái.
3. Luật xử lý: lần 1 rà và chặn, lần 2 là chốt hỏng (REQ-NFR-17)
Chủ dự án chốt ngày 13.10.2026: không chờ lỗi xảy ra lần hai mới chặn. Chờ lần hai nghĩa là trả thêm một lần CI đỏ và deploy đứng cho một lỗi đã biết.
Lần 1, mọi fingerprint mới: rà nguyên nhân gốc ngay, xếp vào đúng một loại:
| Loại | Ví dụ | Chốt bắt buộc |
|---|---|---|
| Máy phát hiện được | Quên gen:reference, lint, số migration trùng | Chốt máy ngay (§4) |
| Ngoại cảnh | GitHub, npm hay Cloudflare sập, mạng chập chờn | Không thêm cổng; retry tự động và gắn nhãn ngoại cảnh để không làm nhiễu số đo |
| Phán đoán | Hiểu sai yêu cầu, chọn sai thiết kế | Ghi vào rule, skill hoặc PRD mà agent đọc TRƯỚC khi viết |
Lần 2 cùng fingerprint: không phải lỗi mới mà là bằng chứng chốt lần 1 hỏng hoặc chọn sai loại. Xử lý trước mọi việc khác.
Vì sao không chốt máy cho MỌI lỗi: mỗi cổng có giá (thời gian commit, bảo trì, báo oan). Hook chậm và báo oan dạy người ta dùng --no-verify, tức là mất luôn mọi cổng. Nên ngưỡng nằm ở chọn đúng loại chốt, không nằm ở chờ lần hai.
4. Thang chốt chặn: càng sớm càng rẻ (REQ-NFR-18)
| Bậc | Chốt | Chặn lúc |
|---|---|---|
| 1 | Rule .claude/rules/, skill, CLAUDE.md | Agent đang SINH code |
| 2 | Hook PreToolUse (.claude/hooks/block-dangerous.mjs) | Agent sắp chạy lệnh nguy hiểm |
| 3 | Pre-commit TỰ SỬA (scripts/precommit-autofix.mjs) | Commit; máy sửa luôn, không cần ai nhớ |
| 4 | Pre-commit CHẶN (lint, typecheck, check:code, check:docs) | Commit, trên máy, vài giây |
| 5 | Cổng CI, test hồi quy | Sau push, khoảng 10 phút |
Chọn bậc thấp nhất làm được. Một bước "phải nhớ làm" mà máy làm được thì phải ở bậc 3, không được dừng ở bậc 4 hay 5: cổng chỉ BÁO đỏ vẫn cần người nhớ sửa.
Đã có (PR #649, 13.10.2026): bậc 3 tự bump last_reviewed, tự sinh lại docs/reference và catalog skill; bậc 4 chạy ESLint trên file đã stage và typecheck đúng workspace bị đụng. Script không bao giờ git add file còn phần chưa stage (luật cây chung SRC-457).
5. Đo: hệ có đang tốt lên không (REQ-NFR-19)
| Chỉ số | Định nghĩa | Đích |
|---|---|---|
| Tỉ lệ lỗi lặp | Số lần gặp của các fingerprint ĐÃ có chốt, trên tổng số lần lỗi | 0 |
| Run CI đỏ mỗi ngày | Trung bình 7 ngày, chỉ tính main | Giảm theo tuần |
| Fingerprint chưa phân loại | Fingerprint mới quá 24 giờ chưa có loại và chốt | 0 |
| Nhiễu | Run đỏ không do code (workflow hỏng cấu hình, ngoại cảnh) | Tách riêng, không trộn vào hai số trên |
Báo cáo tuần: lỗi mới, lỗi lặp, chốt mới thêm, chốt hỏng.
6. Số đo nền 13.09.2026 - 13.10.2026
GitHub Actions: 463 run đỏ (305 trên main), 416 run huỷ, 90 run không khởi động được.
| Nhóm nguyên nhân | Run | Loại | Chốt |
|---|---|---|---|
Docs quên cập nhật: last_reviewed 65, SRC thiếu ở canonical 36, docs/reference lệch 31, catalog skill 6 | ~138 | Máy | Bậc 3 đã có, trừ SRC canonical (cần người viết nội dung) |
| e2e learn | 81 | Máy | Chưa rà từng ca |
Thiếu secret AUTOMERGE_TOKEN | 69 | Nhiễu cấu hình | Đã tắt workflow automerge 13.10.2026 |
| Lint 46, typecheck 26 | 72 | Máy | Bậc 4 đã có |
| Test API (16 ca route thiếu xác thực) | 44 | Máy | Cổng authCoverage có sẵn, chặn ở bậc 5 |
| Ký tự cấm, SEO keyword, tương phản, bindings, số migration | ~42 | Máy | Cổng có sẵn, phần lớn đã ở bậc 4 |
Startup failure từ workflow BuildFailed đã xoá | 81 | Nhiễu | Chưa tìm nhánh còn giữ file |
seed-data tự huỷ khi chờ production | 69 huỷ | Nhiễu | Chưa xử lý |
Cloudflare Workers (cả tài khoản): nemo12-api có 2.180 lượt không thành công trên 94.287, gần như toàn bộ là clientDisconnected, chỉ khoảng 4 exception thật. Nguồn exception lớn nhất là dự án cũ chung tài khoản: chuyenchon-diagnosis-quality (2.176 exception, 100% lượt gọi) và chuyenchon-mori-quality (429, 27%).
7. Chưa dựng
- Bộ thu tự động và sổ lỗi trong D1. Số đo §6 làm tay bằng
ghvà GraphQL. Theo luật dự án, bộ thu chạy định kỳ là Cloudflare Workflows. - Đọc lỗi 5xx do code tự trả về (cần Workers Logs).
- Trang báo cáo tuần trên admin.
- Rà từng ca e2e đỏ để xếp loại.
Trace
| REQ | Section |
|---|---|
| REQ-NFR-16 | §1, §2 |
| REQ-NFR-17 | §3 |
| REQ-NFR-18 | §4 |
| REQ-NFR-19 | §5, §6 |