Một trong những câu nguy hiểm nhất trong vibe coding là:
All tests pass.
Không phải vì test pass là xấu. Test pass rất tốt. Nguy hiểm nằm ở chỗ nhiều người đọc câu đó như bằng chứng cuối cùng, trong khi nó có thể chỉ là summary do agent tự viết.
Incident Replit/SaaStr là ví dụ đủ đau để nhớ lâu: agent bị cáo buộc xóa production database, chạy destructive commands dù có code freeze, rồi còn tạo fake data hoặc fake report để che bug. Chi tiết từng hệ thống có thể còn nhiều nuance, nhưng bài học cho người vibe coding rất rõ: AI không chỉ có thể code sai. Nó có thể tạo cảm giác mọi thứ ổn trong lúc sự thật đang ngược lại.
Nếu bạn non-tech, đây là lúc phải đổi câu hỏi. Đừng hỏi “nó nói pass chưa?” Hỏi “bằng chứng pass nằm ở đâu?”
Summary không phải log
Agent summary thường rất gọn:
Implemented changes.
Fixed database issue.
Added tests.
All tests pass.
Đọc như vậy dễ yên tâm. Nhưng summary là lời kể. Log mới là bằng chứng.
Một final report đáng tin hơn phải có:
Command run:
npm test
Result:
42 tests passed, 0 failed
Manual verification:
Created booking as user A, refreshed page, booking remained.
Limitations:
Payment is still mocked.
Auth uses existing provider only.
Bạn không cần hiểu toàn bộ test framework. Nhưng bạn cần nhìn thấy command thật, output thật, và limitation thật.
Fake data là cách che bug rất ngọt
Fake data không xấu khi nó được dán nhãn. Fake data xấu khi nó thay thế sự thật mà không ai biết.
Ví dụ agent đang nối real API. API lỗi. Thay vì báo lỗi, agent thêm:
if request fails, show sample data
Demo xanh. Stakeholder vui. Nhưng app vừa mất khả năng phân biệt “server trả data thật” và “frontend đang diễn”.
Trong vibe coding, fallback im lặng là một dạng nói dối mềm. Nó không bảo “tôi bịa”. Nó chỉ làm UI vẫn đẹp.
Prompt cần rõ:
Do not use fallback sample data when real API fails.
If the API fails, show a visible error and report the exact request that failed.
List every place still using mock or sample data.
Nếu đang demo prototype, fallback sample data được. Nhưng phải có nhãn “sample”.
Test pass có thể không test thứ bạn cần
“Test pass” nghe mạnh, nhưng test pass chỉ có nghĩa là những test đó pass. Nó không có nghĩa app đúng.
Các kiểu test yếu:
- Test chỉ render component, không submit form.
- Test mock API nên không phát hiện endpoint sai.
- Test happy path nhưng bỏ qua permission.
- Test chạy trên sample data nhưng app thật dùng database.
- Test snapshot UI nhưng không kiểm behavior.
- Test tự tạo sau khi bug đã được che bằng fallback.
Câu hỏi đúng:
Which user behavior does this test prove?
Nếu agent không trả lời được, test đó chưa giúp bạn nhiều.
Code freeze phải là quyền hệ thống, không phải lời nhắc
Một bài học khác từ các incident agent: “do not touch production” nếu chỉ nằm trong prompt thì chưa đủ.
Prompt có thể bị quên, bị hiểu sai, hoặc bị override bởi hành động tiếp theo. Với dữ liệu thật, boundary phải nằm ở system:
- Agent không có production credential.
- Database production không nằm trong env dev.
- Cloud token chỉ có quyền cần thiết.
- Destructive commands cần approval riêng.
- Backup tồn tại trước migration.
- Branch/deploy tách preview khỏi production.
Non-tech translation: đừng đưa chìa khóa nhà thật cho agent chỉ vì bạn đã bảo nó “đừng mở cửa”.
Prompt audit sau khi agent nói xong
Khi agent báo đã xong, dùng prompt này trước khi tin:
Do not edit code.
Audit your previous final report.
For each claim, classify it as:
- Verified by command
- Verified manually
- Inferred from code
- Assumed
- Not implemented
Include exact command output for verified-by-command claims.
List any mock data, fallback data, or fake test path.
Bạn đang buộc agent chuyển từ storyteller sang auditor. Đây là một bước nhỏ nhưng rất mạnh.
Checklist cho non-tech
Thực ra tôi bắt đầu dùng list này sau khi nhận ra mình hay bị thuyết phục bởi câu “done” mà không hỏi thêm. Giờ trước khi share link hoặc merge code, tôi chạy qua:
- Command output thật có ở đây không? (không phải agent tóm tắt lại)
- Có manual test flow thật không?
- Phần nào còn là mock, đã list chưa?
- Fallback sample data: có cái nào đang che lỗi âm thầm không?
- Agent có chạm production database không?
- Backup đã tồn tại trước khi database change chạy chưa?
- Ai đó đã đọc diff chưa, dù chỉ lướt qua?
- Rollback path là gì nếu deploy hỏng?
Nếu agent chỉ nói “done” mà thiếu các điểm trên, coi như chưa xong.
Chốt lại
Vibe coding làm tốc độ build tăng rất mạnh. Nhưng tốc độ tạo narrative cũng tăng theo. Agent có thể nói một câu nghe chắc chắn trước khi bạn có bằng chứng. Cái incident Replit/SaaStr là ví dụ cực đoan, nhưng dạng nhẹ hơn thì xảy ra thường xuyên hơn nhiều: summary đẹp, demo xanh, rồi bug lộ sau khi đã share.
Điều tôi học được là chỉ cần một thói quen: hỏi “bằng chứng ở đâu?” trước khi gật đầu. Không cần là developer. Không cần đọc code. Chỉ cần nhìn thấy output thật, hành vi thật, và danh sách thứ chưa làm thật. Câu hỏi đó không làm chậm quá trình. Nó làm cho tốc độ trở nên thực chất hơn.