Tháng 7 năm 2026, Robert C. Martin viết rằng ông không còn đọc code do các agent lập trình của mình tạo ra nữa.
Phát biểu này thu hút nhiều sự chú ý. Phần còn lại của bài viết quan trọng hơn để hiểu cách ông làm việc. Martin bao quanh các agent bằng kiểm thử đơn vị, kiểm thử chấp nhận Gherkin, quy trình QA, kiểm thử đột biến, kiểm tra độ bao phủ và các chỉ số chất lượng. Code chỉ được ông tin tưởng khi vượt qua hệ thống này.
Ông từng nêu quan điểm tương tự vài tháng trước đó. Thay vì kiểm tra hiện thực, ông xem xét độ bao phủ kiểm thử, cấu trúc phụ thuộc, độ phức tạp chu trình, kích thước module và kết quả kiểm thử đột biến. Khi mọi người hiểu nhầm đây là từ bỏ review hoàn toàn, ông làm rõ: "Tôi review rất nhiều — chỉ là không phải code."
Những nhận xét này mô tả một vấn đề thực tế trong phát triển phần mềm nặng AI. Các agent lập trình có thể tạo ra thay đổi nhanh hơn tốc độ con người đọc. Khi lượng code do AI sinh ra vượt quá khả năng review của nhóm, kiểm tra từng dòng không thể là nguồn tin cậy duy nhất.
Chúng tôi đã đối mặt với vấn đề tương tự tại vm0 suốt tám tháng qua. Phần lớn hiện thực trong repository của chúng tôi được viết bởi các agent — lập trình vibe, theo cách gọi phổ biến — trong khi sáu kỹ sư vẫn chịu trách nhiệm về những gì code đó thực thi trên môi trường thật.
Tóm tắt ngắn
vm0 là một codebase vibe-coded: agent viết phần lớn hiện thực, sáu kỹ sư sở hữu những gì nó thực thi trên môi trường thật. Sau tám tháng, repository chứa 1,329,170 dòng và đã merge 630 pull request chỉ trong một tuần. Năm cơ chế gánh vác trọng trách chất lượng mà review từng dòng không còn đảm đương nổi.
- Môi trường hội tụ. Kỹ sư và agent làm việc trong cùng dev container, mỗi pull request có thể có nhánh database riêng. Lệnh chạy được cho agent cũng chạy được cho người.
- Ràng buộc thực thi. TypeScript nghiêm ngặt, khoảng 135 module hợp đồng API có kiểu, Oxlint, ESLint và quy tắc kiến trúc, CI không chấp nhận cảnh báo. Quy tắc kiểm tra được bằng máy không để lại cho review.
- Kiểm thử tập trung biên. Testing trophy thay vì test pyramid: kiểm thử tích hợp qua biên module công khai, PostgreSQL thật và migration thật, chỉ mock ở hệ thống ngoài. Code kiểm thử chiếm khoảng 36 phần trăm repository.
- Vòng phản hồi đầy đủ. Agent khởi động ứng dụng và database, chạy migration, điều khiển trình duyệt thật, rồi báo cáo lệnh đã chạy, đường dẫn đã kiểm thử và ảnh chụp màn hình. PR trung vị merge sau khoảng 53 phút.
- Dọn dẹp liên tục. Knip loại bỏ code chết một cách xác định, workflow hàng ngày dọn AI slop mà linter không phát hiện được, mẫu lặp lại đủ nhiều sẽ thành quy tắc lint hoặc ràng buộc kiểu.
Vibe coding và agentic coding thực sự là gì
Vibe coding là nhắc LLM sinh code, chạy kết quả, yêu cầu thay đổi và không quan tâm đến code sinh ra. Định nghĩa của Martin Fowler ở đây rất hẹp, nhấn mạnh cụm "quên rằng code tồn tại." Phù hợp cho prototype, phần mềm dùng một lần và công cụ nhỏ ít hậu quả.
Agentic coding, Fowler gọi là agentic programming, là cách nhóm làm khi kỳ vọng duy trì kết quả. Agent đọc repository, chỉnh sửa file, chạy kiểm thử, làm việc độc lập lâu dài, còn con người sở hữu cấu trúc, hành vi và review bằng chứng mà một lần chạy tạo ra: kết quả kiểm thử, tín hiệu chất lượng, bản xem trước và hành vi thực tế.
Khác biệt không nằm ở tỷ lệ code do model viết, mà ở nơi con người tập trung chú ý.
| Vibe coding | Agentic coding | |
|---|---|---|
| Độ tự chủ của agent | Prompt, chạy, prompt lại | Đọc repository, chỉnh sửa, kiểm thử, lặp lại |
| Ai đọc code | Không ai | Người đọc phần có rủi ro |
| Xác minh điều gì | Kết quả có đúng không | Kiểu, hợp đồng, kiểm thử, preview, tín hiệu thực tế |
| Phù hợp nhất | Prototype, công cụ dùng một lần | Phần mềm cần bảo trì lâu dài |
| Lỗi điển hình | Code không ai hiểu | Xác minh quá yếu so với khối lượng |
Agent chỉnh sửa repository là một nhánh của thay đổi rộng hơn; chúng tôi đã xem xét khía cạnh không dành cho lập trình viên riêng biệt.
Chúng tôi thường gọi vm0 là dự án vibe-coded vì cụm này đã thành cách gọi phổ biến cho phần mềm chủ yếu do AI viết. Theo Fowler, nó gần với agentic coding hơn. Kỹ sư của chúng tôi gõ ít hiện thực hơn trước, nhưng vẫn sở hữu kiến trúc, chi phí bảo trì và hành vi thực tế.
Khi sinh code nhanh hơn, trách nhiệm đó chuyển dần vào môi trường phát triển, hệ thống kiểu, bộ kiểm thử và workflow bảo trì tự động.
Tám tháng tăng trưởng trong codebase vibe-coded
Repository vm0 được tạo tháng 11 năm 2025. Theo báo cáo quy mô kỹ thuật hàng tuần mới nhất, nó khoảng tám tháng rưỡi tuổi.
Repository chứa:
| Chỉ số | Số lượng |
|---|---|
| Dòng logic không rỗng | 1,329,170 |
| Dòng production | 850,913 |
| Dòng kiểm thử | 478,257 |
| File nguồn | 5,549 |
| File kiểm thử | 1,327 |
| Package | 44 |
| Commit trên nhánh chính | 14,005 |
Các số liệu này lấy từ báo cáo kỹ thuật hàng tuần tuần của ngày 20–26, 2026, đo trực tiếp từ monorepo. Code kiểm thử chiếm khoảng 36 phần trăm codebase đo được. Đây là tỷ lệ khối lượng code, không phải độ bao phủ kiểm thử, nhưng cho thấy mức độ hiện thực xoay quanh xác minh.
Trong ba tuần gần đây, sáu kỹ sư thực hiện lần lượt 541, 640 và 631 commit. Tuần 20–26, GitHub ghi nhận 630 pull request được merge. Sáu kỹ sư tạo ra 556 PR, còn tự động phát hành tạo 74 còn lại.
Thời gian trung vị từ mở pull request đến merge là khoảng 53 phút. Phân vị 90% là khoảng 7.4 giờ.
Với tốc độ thay đổi này, review thủ công vẫn hữu ích nhưng không thể gánh toàn bộ hệ thống chất lượng. Chúng tôi cần tín hiệu độc lập ở nhiều điểm trong vòng đời thay đổi.
Cách tiếp cận hiện tại có năm chủ đề lặp lại: môi trường hội tụ, ràng buộc thực thi, kiểm thử biên, vòng phản hồi đầy đủ và dọn dẹp liên tục.
Hội tụ môi trường phát triển với dev container
Nhiều lỗi khó tái hiện xuất phát từ trạng thái không xuất hiện trong pull request.
Lập trình viên có thể có biến môi trường chưa tài liệu, công cụ cài toàn cục, file cấu hình cũ hoặc database chạy nhiều tháng. Con người quen với các chi tiết này. Agent thường không thấy được.
Chúng tôi dần ngừng coi máy chủ là môi trường phát triển chuẩn. Kỹ sư và agent làm việc trong dev container. Image phát triển gồm toolchain dự án, PostgreSQL, pgvector, Chromium và tiện ích tự động hóa trình duyệt.
CI chạy image toolchain có version, build từ cùng họ Dockerfile nhiều giai đoạn. Image phát triển và CI phục vụ mục đích khác nhau, production có hình dạng triển khai riêng. Tính chất hữu ích là hội tụ: version tool, phụ thuộc và giả định runtime đều rõ ràng, có version.
Điều này tạo kỳ vọng đơn giản: lệnh agent chạy phải tái hiện được bởi kỹ sư trong cùng container phát triển. Kiểm tra pass trong phát triển phải chạy được với toolchain gần giống trên CI.
Chúng tôi áp dụng ý tưởng tương tự cho dữ liệu. Mỗi preview pull request có thể có nhánh database riêng, chạy migration và seed thật. Agent có thể tạo, thay đổi dữ liệu, lặp lại kiểm thử phá hủy mà không dùng database của lập trình viên hay thừa hưởng trạng thái từ pull request khác.
Thay đổi môi trường đi qua repository. Nâng cấp tool, version trình duyệt, extension database đều được review và lan truyền như code ứng dụng.
Chuẩn kỹ thuật thực thi bằng kiểu và quy tắc lint
Chuẩn viết giúp con người hiểu quyết định thiết kế. Nhưng không đảm bảo mọi thay đổi đều tuân thủ, nhất là khi agent làm việc lâu.
Chúng tôi đưa quy tắc ổn định vào hệ thống kiểu, linter và CI khi có thể diễn đạt chắc chắn.
vm0 dùng thiết lập TypeScript nghiêm ngặt, gồm strict và noUncheckedIndexedAccess. Một số package bật kiểm tra bổ sung cho giá trị không dùng và trả về ngầm.
API dùng lớp hợp đồng REST typed theo schema, xây với tRPC và Zod. Drizzle kết nối truy cập database với kiểu TypeScript. Tại thời điểm review này, repository có khoảng 135 module hợp đồng.
Các lựa chọn này không bắt lỗi quyết định sản phẩm sai. Nhưng chúng phát hiện trôi giao diện sớm. Khi trường hoặc phản hồi thay đổi, các caller liên quan thường fail khi phân tích tĩnh. Lỗi tạo ra thường đủ cụ thể để agent dùng cho lần lặp tiếp theo.
Linting bao phủ nhóm quy tắc thứ hai. Nền tảng chạy Oxlint, kiểm tra nhận biết kiểu và ESLint, cùng quy tắc kiến trúc riêng dự án. CI không chấp nhận cảnh báo. Cảnh báo tồn tại lâu sẽ thành nhiễu nền, dễ bị cả người lẫn agent bỏ qua.
Khi vấn đề lặp lại, chúng tôi cân nhắc vị trí kiểm tra:
- Hệ thống kiểu có diễn đạt được không?
- Linter hoặc công cụ cấu trúc phát hiện chính xác không?
- Có cần đánh giá ngữ nghĩa toàn repository không?
Hai nhóm đầu cho phản hồi nhanh, xác định cho mọi thay đổi. Nhóm ba xử lý bằng workflow lặp lại, mô tả sau trong bài.
Thu hẹp mẫu dễ lỗi trong code AI sinh ra
Một số tính năng ngôn ngữ có cách dùng hợp lý nhưng cũng thường xuất hiện trong code agent sinh ra dễ vỡ.
try/catch có thể làm mờ ranh giới lỗi. Khi agent gặp lỗi, thêm catch và fallback là cách dễ để giữ đường đi hiện tại mà mất lỗi gốc. Trộn Promise .then() và .catch() với async/await làm luồng điều khiển phân tán nhiều kiểu.
React useEffect tạo vấn đề tương tự trong quản lý trạng thái. Thường dùng để copy state, đồng bộ hai nguồn dữ liệu, hoặc mã hóa phụ thuộc thứ tự khó thấy từ mô hình dữ liệu.
Nền tảng web cốt lõi mặc định hạn chế các mẫu này. Ngoại lệ hợp lý có thể giữ lại, kèm giải thích rõ ràng bên cạnh.
Code production trong nền tảng web cốt lõi hiện không có useEffect. Chúng tôi dùng ccstate và mẫu không hiệu ứng khác để mô hình hóa phụ thuộc và hiệu ứng rõ ràng hơn. Một số ít lệnh gọi useEffect production vẫn còn ở code UI dùng chung và desktop, nên phạm vi tuyên bố quan trọng.
Các quy tắc này xuất phát từ lỗi lặp lại trong repository. Khi mẫu liên tục gây vấn đề bảo trì, chúng tôi chuyển nó từ hướng dẫn review thành ràng buộc thực thi.
Kiểm thử tại biên module: testing trophy, không phải pyramid
vm0 không theo test pyramid truyền thống. Hướng dẫn kiểm thử mô tả testing trophy: phân tích tĩnh ở đáy, kiểm thử tích hợp là lớp chính, ít kiểm thử end-to-end cho hành trình người dùng quan trọng.
Unit test khá hiếm. Chúng tôi dùng chọn lọc cho logic nhạy cảm bảo mật, thuật toán, máy trạng thái. Phần lớn hành vi nghiệp vụ kiểm thử qua biên công khai của module.
Kiểm thử API gọi ứng dụng thật qua hợp đồng. Dữ liệu kiểm thử chuẩn bị qua endpoint production khi có thể, kiểm tra qua hành vi công khai. Test tránh truy cập trực tiếp dịch vụ nội bộ hoặc sửa bảng database, vì như vậy gắn chặt với hiện thực.
Hạ tầng nội bộ giữ thật khi chi phí hợp lý:
- PostgreSQL và pgvector
- migration database
- filesystem
- dịch vụ nội bộ
- mock ở biên hệ thống ngoài
Kiểm thử tích hợp chạy chậm hơn unit test cô lập và cần môi trường đầy đủ hơn. Nhưng giảm khoảng cách giữa "test pass" và "ứng dụng thực hiện được thao tác với database thật."
Kiểm thử biên cho phép refactor lớn bên trong. Agent có thể tổ chức lại module, tách dịch vụ, đổi lớp truy cập dữ liệu mà hành vi công khai vẫn được bảo vệ.
Uncle Bob ưa tỷ lệ khác, dùng nhiều unit test, Gherkin và kiểm thử đột biến. Nguyên tắc chung là xác minh độc lập. Quy trình sinh code không nên là nguồn duy nhất khẳng định code hoạt động.
Cho agent lập trình vòng phản hồi đầy đủ
Những lần chạy agent lập trình đầu tiên thường kết thúc với báo cáo quen thuộc: code đã đổi, TypeScript pass; hãy khởi động ứng dụng và kiểm tra trang.
Như vậy nửa vòng phát triển còn lại thuộc về kỹ sư. Ai đó vẫn phải chuẩn bị database, chạy dịch vụ, mở trình duyệt, tạo dữ liệu, quan sát lỗi và mô tả lại cho agent.
Giờ đây agent có đủ môi trường phát triển để làm nhiều việc đó. Chúng có thể khởi động ứng dụng và database, chạy migration, tạo dữ liệu kiểm thử, truy cập preview pull request và thao tác trình duyệt thật.
Kiểm tra trình duyệt phát hiện loại lỗi mà kiểm tra kiểu và API không bao phủ tốt: điều hướng hỏng, trạng thái tải không kết thúc, lỗi quyền chỉ xuất hiện trong luồng đầy đủ, và lỗi giao diện.
Kết thúc một lần chạy, agent báo cáo lệnh đã thực thi, đường dẫn đã kiểm thử và quan sát được gì. Với thay đổi giao diện, có thể kèm ảnh chụp màn hình. Kỹ sư kiểm tra bằng chứng đó trước khi quyết định tự mở preview.
Ảnh chụp màn hình không phải kiểm thử và không chứng minh không còn lỗi khác. Nhưng giúp tái hiện ngữ cảnh agent dễ dàng hơn. Với thay đổi nhỏ, bước tái hiện và ảnh chụp cuối hữu ích hơn nhiều so với thông báo "có vẻ đã sửa."
Chất lượng công việc của agent phụ thuộc lớn vào phản hồi nó tự thu được mà không phải chờ người.
Giữ branch ngắn với phát triển dựa trên trunk
Sinh code nhanh tạo ra nhiều branch.
Branch tính năng sống lâu tích tụ xung đột merge, trùng lặp công việc, ngữ cảnh cũ. PR càng lớn, review càng khó và chậm. Chúng tôi dùng phát triển dựa trên trunk để giữ branch ngắn, liên tục tích hợp quanh main.
Quy tắc nhánh chính yêu cầu:
- pull request cho mọi thay đổi
- lịch sử tuyến tính và squash merge
- hàng đợi merge
- kiểm tra Turbo, Rust, bảo mật
- không bỏ qua cổng kiểm tra bắt buộc
Tự động hóa cũng theo quy trình này. Agent có thể tạo pull request, một số tác vụ bảo trì rủi ro thấp có thể merge tự động, nhưng thay đổi vẫn phải qua CI và hàng đợi merge.
Kích thước và tuổi thọ pull request giải thích vì sao có thể merge 630 PR trong một tuần. Thay đổi nhỏ ít ngữ cảnh, dễ xác minh, ít xung đột với công việc sản phẩm hoặc sửa chữa tự động khác.
Knip như garbage collection repository: loại bỏ code chết
Sinh code tự nhiên thêm file và trừu tượng. Xóa thường cần prompt riêng.
Sau refactor, file cũ có thể còn trong repository. Xóa tính năng có thể để lại export, phụ thuộc, entry point. Những thứ này hiếm khi làm test fail, nhưng lâu dài khiến codebase khó đọc hơn.
Chúng tôi dùng Knip tìm file, export, phụ thuộc, entry point không dùng. TypeScript xác nhận code hợp lệ; Knip hỏi liệu nó còn tham gia hệ thống không.
Phần dư này còn gây thêm chi phí cho agent lập trình. Repository là nguồn ngữ cảnh quan trọng nhất của chúng. Helper lỗi thời hoặc hiện thực bỏ hoang có thể thành mẫu được chấp nhận cho agent tiếp theo. Giữ ngữ cảnh sạch là nửa công việc ít hào nhoáng của context engineering: những gì agent đọc từ repository quan trọng như prompt nó nhận.
Loại bỏ code chết cũng cải thiện đầu vào cho lần chạy sau. Knip xử lý phần xác định đủ nhanh để thành kiểm tra chất lượng thường xuyên.
Workflow dọn AI slop lặp lại
Knip và ESLint có giới hạn rõ ràng. Nhiều dạng xuống cấp cần ngữ cảnh dự án và đánh giá ngữ nghĩa.
Chúng tôi dùng "AI slop" để chỉ phần dư này: fallback không cần thiết, trừu tượng trùng lặp, test vượt biên công khai, nhánh phòng thủ cho trạng thái không thể xảy ra. Mỗi trường hợp có vẻ vô hại. Nhưng tổng thể làm repository khó hiểu hơn và cho agent sau mẫu xấu để học theo.
Một số workflow vm0 lặp lại quét các mẫu này theo lịch.
Dọn AI slop hàng ngày tìm phần dư mới, chọn một số sửa chữa xác suất cao, rủi ro thấp. Workflow khác kiểm tra test API truy cập dịch vụ nội bộ, antipattern React và ccstate, nợ kỹ thuật có thể xử lý an toàn.
Mỗi workflow giữ thay đổi hẹp. Nó mở pull request, dựa vào kiểm tra kiểu, lint, test, hàng đợi merge như thường lệ. PR cấu hình merge tự động vẫn phải qua các cổng này.

Chạy agent theo lịch không miễn phí, chúng tôi đã viết riêng về giảm chi phí này. Workflow không cố xóa hết nợ kỹ thuật trong một lần. Mỗi ngày một ít dễ xác minh, ít xáo trộn hơn dọn lớn vài tháng một lần.
Khi workflow lặp lại phát hiện mẫu giống nhau đủ nhiều, chúng tôi cân nhắc chuyển kiểm tra vào ESLint, Knip hoặc hệ thống kiểu. Workflow ngữ nghĩa là nơi quan sát, tinh chỉnh quy tắc trước khi biến thành kiểm tra xác định rẻ hơn.
Biến lỗi kiểm thử không ổn định thành sửa chữa tự động
Một nhóm workflow khác bắt đầu từ lỗi GitHub Actions.
Khi test fail trên nhánh chính hoặc hàng đợi merge, workflow đọc log, kiểm tra dấu hiệu không ổn định, xem retry, thời gian, yếu tố môi trường. Nếu có bằng chứng cho sửa chữa cụ thể, nó cập nhật test hoặc hiện thực, mở pull request, chạy lại toàn bộ CI.
Pass khi retry không làm lỗi gốc vô hại. Nhóm dựa vào nút retry dần mất niềm tin vào build đỏ. Khi đó, kiểm tra fail thành nhiễu nền.
Workflow sửa chữa tự động biến lỗi ngắt quãng thành thay đổi code có thể truy vết. Chẩn đoán, bản vá, xác minh đều hiện trên pull request. Kỹ sư kiểm tra thay đổi rủi ro cao, còn sửa nhỏ có bằng chứng mạnh có thể qua hàng đợi merge.
Hệ thống chất lượng hiện có ba lớp lớn:
| Giai đoạn | Cơ chế | Mối quan tâm điển hình |
|---|---|---|
| Khi viết | TypeScript, hợp đồng, Drizzle, ESLint | lỗi kiểu, trôi giao diện, mẫu code đã biết |
| Trước khi merge | Knip, kiểm thử tích hợp, database thật, preview, hàng đợi merge | code chết, hành vi module, kết quả runtime đầy đủ |
| Sau khi merge | workflow vm0 theo lịch và sự kiện | AI slop, antipattern ngữ nghĩa, test không ổn định, trôi kiến trúc |
Các lớp này bổ trợ nhau. Vấn đề workflow phát hiện có thể thành quy tắc tĩnh. Lỗi CI hoặc production có thể thành test và hướng dẫn kỹ thuật mới.
Con người tập trung vào đâu khi review code AI sinh ra
Kỹ sư vm0 vẫn đọc code, nhất là thay đổi kiến trúc, bảo mật, thanh toán, migration dữ liệu. Chúng tôi không đặt ra quy tắc "không bao giờ đọc code".
Điều thay đổi là phân bổ chú ý khi review. Đọc code là một tín hiệu trong số hợp đồng, biên kiểm thử, hành vi preview, ảnh chụp màn hình, chỉ số chất lượng, chẩn đoán workflow.
Một số quyết định vẫn cần kinh nghiệm:
- yêu cầu đã đầy đủ chưa
- biên module đặt ở đâu
- lỗi nào có thể phục hồi
- lỗi có thể gây ảnh hưởng kinh doanh đến mức nào
- mô hình bảo mật có phù hợp không
- mẫu lỗi mới nào quy tắc hiện tại chưa bao phủ
Thiên hướng tương tự xảy ra ở phía thiết kế, nơi design-as-code chuyển quyết định giao diện vào cùng repository và quy trình review. Kỹ sư cũng duy trì môi trường quanh agent. Khi vấn đề lặp lại, chúng tôi quyết định thêm ràng buộc kiểu, quy tắc lint, test hay workflow lặp lại. Hệ thống phát triển đã thành hiện vật kỹ thuật quan trọng.
Code dễ đọc vẫn quan trọng. Người đọc tiếp theo có thể là kỹ sư hoặc agent khác. Code rối tiêu tốn nhiều ngữ cảnh, mở rộng phạm vi thay đổi tương lai, làm xác minh kém tin cậy.
Bảo mật và những thay đổi không tăng tốc
Tốc độ không áp dụng đều. vm0 giữ danh sách ngắn thay đổi đi theo nhịp riêng: bảo mật, thanh toán, migration dữ liệu, quyết định kiến trúc. Kỹ sư đọc từng dòng, bất kể ai viết.
Rủi ro bảo mật code AI sinh ra, theo kinh nghiệm chúng tôi, không phải lỗ hổng lạ mà là code hợp lý không ai sở hữu. Kiểm soát quan trọng là những thứ thông thường, áp dụng nhất quán:
- Unit test, vốn dùng hạn chế, được dùng có chủ đích cho logic bảo mật, thuật toán, máy trạng thái.
- Test chỉ mock ở biên hệ thống ngoài. Hạ tầng nội bộ giữ thật, nên thay đổi phá vỡ hợp đồng nội bộ fail ở CI thay vì production.
- Agent làm việc trong dev container với nhánh database riêng cho mỗi pull request, không dùng máy lập trình viên hay database chung.
- Hàng đợi merge và kiểm tra bắt buộc không có ngoại lệ thường lệ, kể cả với pull request agent mở và đánh dấu merge tự động.
try/catchmặc định bị hạn chế, nên lỗi ít bị nuốt bởi fallback agent thêm để giữ đường đi.
Xử lý credential là vấn đề thiết kế riêng: chúng tôi đã mô tả mẫu broker giữ token ngoài tầm agent trong bài riêng.
Tất cả điều này không làm code sinh ra an toàn tự thân. Nó thu hẹp tập thay đổi cần quyết định con người, và làm tập đó rõ ràng.
Những con số này không thể hiện điều gì
Báo cáo hàng tuần cho thấy quy mô repository và tốc độ giao hàng. Nó không tự chứng minh độ tin cậy production.
Đánh giá tác động lên chất lượng runtime cần độ sẵn sàng, tỷ lệ lỗi production, số sự cố, tỷ lệ thay đổi lỗi, tần suất rollback, thời gian phục hồi trung bình. CI xanh chỉ mô tả một phần quy trình giao hàng.
Chúng tôi vẫn đang tổng hợp các chỉ số kết quả đó. Thực hành kỹ thuật giải thích cách hệ thống quản lý rủi ro; dữ liệu production cho thấy quản lý đó hiệu quả ra sao.
FAQ
Vibe coding là gì? Vibe coding là nhắc LLM sinh code, chạy kết quả, yêu cầu thay đổi và không đọc code sinh ra. Định nghĩa của Martin Fowler cố tình hẹp: lập trình viên nên "quên rằng code tồn tại." Phù hợp cho prototype, phần mềm dùng một lần, công cụ ít hậu quả.
Agentic coding là gì? Agentic coding là dạng phát triển hỗ trợ AI lâu dài, trong đó agent đọc repository, chỉnh sửa file, chạy kiểm thử, lặp lại độc lập. Con người vẫn sở hữu kiến trúc, hành vi và review bằng chứng một lần chạy tạo ra thay vì từng dòng code.
Khác biệt giữa vibe coding và agentic coding là gì? Chú ý, không phải tác giả. Vibe coding không kiểm tra code. Agentic coding agent làm độc lập, kỹ sư kiểm tra bằng chứng quanh nó: kết quả kiểm thử, tín hiệu chất lượng, preview, hành vi thực tế. vm0 thường gọi là vibe-coded; theo Fowler là agentic coding.
AI slop là gì? AI slop là phần dư code AI sinh ra để lại: fallback không cần thiết, trừu tượng trùng lặp, test vượt biên công khai, nhánh phòng thủ cho trạng thái không thể xảy ra. Mỗi trường hợp có vẻ vô hại. Tổng thể làm repository khó hiểu hơn và cho agent sau mẫu xấu.
Làm sao review code AI sinh ra với 630 pull request mỗi tuần? Không từng dòng. Ở vm0, review thủ công tập trung nơi cần phán đoán: kiến trúc, bảo mật, thanh toán, migration dữ liệu. Phần còn lại dựa vào cơ chế: kiểu và hợp đồng nghiêm ngặt, kiểm thử tích hợp ở biên module, database thật trong preview từng pull request, kiểm tra trình duyệt, Knip và hàng đợi merge không cho phép bỏ qua thường lệ.
Thực hành tốt nhất cho vibe coding quy mô lớn là gì? Năm điều giữ vững suốt tám tháng ở vm0: hội tụ môi trường phát triển để agent và người chạy cùng lệnh; biến chuẩn thành thực thi qua kiểu, linter, CI thay vì tài liệu; kiểm thử ở biên module với hạ tầng thật; cho agent vòng phản hồi đầy đủ gồm trình duyệt; và dọn dẹp liên tục thay vì dọn lớn thỉnh thoảng.
Rủi ro bảo mật của code AI sinh ra là gì?
Rủi ro phổ biến không phải lỗ hổng lạ mà là code hợp lý không ai sở hữu. vm0 giữ công việc bảo mật, thanh toán, migration dữ liệu cho review con người, dùng unit test có chủ đích cho logic đó, giữ hạ tầng nội bộ thật trong test, hạn chế mẫu như try/catch nuốt lỗi, không cho phép bỏ qua kiểm tra bắt buộc.
Code AI sinh ra có tạo nợ kỹ thuật không? Nó tạo loại nợ đặc thù: code vẫn biên dịch, pass test nhưng không còn tham gia hệ thống, cộng thêm phần dư ngữ nghĩa linter không phát hiện. Knip loại bỏ phần xác định. Workflow lặp lại xử lý phần còn lại theo lô nhỏ hàng ngày, mẫu lặp lại đủ nhiều thành quy tắc lint hoặc ràng buộc kiểu.
Bao nhiêu phần codebase vm0 do AI viết? Phần lớn hiện thực. Sáu kỹ sư tạo 556 trong tổng số 630 pull request merge tuần 20–26, 2026, phần còn lại do tự động phát hành, agent viết phần lớn code trong các pull request đó. Kỹ sư sở hữu kiến trúc, ràng buộc và hành vi thực tế.
Testing trophy là gì, tại sao không dùng test pyramid? Testing trophy đặt phân tích tĩnh ở đáy, kiểm thử tích hợp là lớp chính, ít kiểm thử end-to-end trên cùng. vm0 dùng vì test qua biên module công khai tiếp tục bảo vệ hành vi khi agent tổ chức lại hiện thực bên dưới, điều mà lớp unit test lớn không làm được.
Làm sao tìm code chết trong repository do AI viết? Sinh code thêm file, trừu tượng; xóa thường cần prompt riêng. vm0 chạy Knip thường xuyên để tìm file, export, phụ thuộc, entry point không dùng. TypeScript xác nhận code hợp lệ; Knip hỏi nó còn tham gia hệ thống không, đó mới là câu hỏi quan trọng với code chết.
Code vibe-coded có an toàn chạy production không? Phụ thuộc vào cái gì xác minh, không phải ai gõ. Tín hiệu bắt buộc không đổi: kiểu và hợp đồng, kiểm thử qua biên công khai, hạ tầng thật, pipeline phải xanh. Số liệu trong bài mô tả quy mô repository và tốc độ giao hàng. Độ sẵn sàng, tỷ lệ lỗi, tỷ lệ thay đổi lỗi mới trả lời câu hỏi production, chúng tôi vẫn đang tổng hợp.
Tám tháng nhìn lại
Tám tháng là quá sớm để kết luận phương pháp cuối cùng. Model, công cụ agent, repository vẫn thay đổi, quy tắc và workflow của chúng tôi cũng vậy.
Một thay đổi đã rõ ràng. Khi sinh code nhanh hơn, môi trường, ràng buộc, kiểm thử, hệ thống phản hồi gánh nhiều trọng trách chất lượng hơn. Kỹ sư dành ít thời gian gõ hiện thực, nhiều thời gian định nghĩa hành vi, thiết kế biên, cải thiện xác minh.
Codebase vm0 sẽ tiếp tục lớn lên. Knip loại bỏ phần dư xác định. Quy tắc tĩnh chặn mẫu lỗi đã hiểu. Kiểm thử tích hợp bảo vệ hành vi module. Workflow lặp lại xử lý xuống cấp chưa thể diễn đạt bằng máy.
Code vẫn quan trọng. Thực hành tốt nhất trong bài không nhằm viết ít code hơn, mà là quyết định điều gì phải đúng trước khi thay đổi lên nhánh chính. Chúng tôi dùng nhiều bằng chứng thực thi bằng máy hơn để quyết định thay đổi nào nên lên nhánh chính, và hiện thực nào nên giữ lại trong repository.





