Điều gì đang xảy ra → nên làm gì
Tra theo triệu chứng chứ không phải theo tiêu đề. Dưới mục "nên làm gì" là liên kết nhảy tới đoạn viết về cách xử lý đó. Mục lục toàn bộ bài viết nằm ở cuối trang này.
Bảng này giả định bạn dùng Claude Code (agent lập trình của Anthropic). hook, CLAUDE.md, subagent và auto memory là tên các tính năng của nó.
| Điều gì đang xảy ra | Nên làm gì |
|---|---|
| Mỗi lần AI chạy test, hàng chục nghìn dòng output lại tràn vào context |
Gom mọi lần chạy test qua một wrapper script duy nhất, ghi toàn bộ output ra file log, và chỉ trả về cho AI phần tóm tắt các lỗi thất bại. |
| AI càng lưu nhiều ghi chú kiến thức, mọi phiên làm việc sau càng phải đọc nhiều hơn |
Dùng một PreToolUse hook chạy ngay trước khi ghi memory để bắt AI đọc checklist trước, và chỉ để lại đúng 1 dòng trong file chỉ dẫn (CLAUDE.md): "đọc trước khi ghi". |
| Test vẫn pass, nhưng không rõ nó có thực sự bảo vệ được điều gì hay không |
Viết một chính sách 1 trang về mutation testing (cố tình phá code để xem test có bắt được không), và cho AI đọc nó mỗi khi bạn yêu cầu rà soát test. |
| Có skill đã đăng ký, nhưng lúc AI dùng lúc không |
Giữ nguyên lệnh dưới dạng script thông thường, dùng PreToolUse hook chặn các lần gọi sai, và chỉ AI đến đúng tài liệu cần đọc. |
| Việc đã giao cho sub-agent thì không thấy nó đang làm gì cho tới khi xong |
Định nghĩa bằng YAML những tác vụ nào được phép giao cho sub-agent và những file input nào phải có trước khi khởi chạy, rồi dùng hook kiểm tra điều đó trước khi bắt đầu. |
| Càng thêm rule vào file chỉ dẫn, các rule thêm trước đó càng ít được tuân theo |
Chuyển từng rule kiểu "không được làm X" thành một automated test (Minitest) có thể phát hiện vi phạm, làm từng cái một. |
| Memory dùng chung giữa các phiên chạy song song trở nên lộn xộn, cho đọc chính sách cũng không cải thiện |
Chuyển đúng file chính sách đó sang một PostToolUse hook và hiển thị nó cùng với diff ngay sau khi lưu. Giữ nguyên nội dung đọc, chỉ đổi thời điểm. |
| Dù đã viết sẵn cách xử lý một lỗi, lần sau AI vẫn mắc lại đúng lỗi đó |
Tóm tắt chính sách retry thành vài dòng trong một file, và để hook phát hiện lỗi tự động chèn nó vào. |
| Dù đã đọc ghi chú bàn giao và báo cáo hoàn thành, phần bất lợi vẫn bị thiếu |
Mỗi lần đều đặt các con số lấy một cách máy móc — như từ git diff --stat — ngay cạnh báo cáo hoàn thành. |
| Con số máy đếm ra lại biến thành con số khác vào lúc tới được báo cáo |
Gắn một tiền tố cố định vào dòng chứa con số, và dùng hook kiểm tra xem nó có được copy nguyên văn hay không. |
| Ngắt lời AI giữa chừng khi nó đang làm việc thì mọi thứ sau đó bị rối |
Thay vì để người ngắt lời giữa chừng, hãy để một PostToolUse hook trả lại chính sách ngay sau khi lưu và một hook phát hiện lỗi rồi trả việc lại làm nhiệm vụ can thiệp. Người chờ đến mốc tự nhiên. |
| Đến cuối phiên làm việc, chưa rõ nên đọc gì và không cần đọc gì |
Đừng đọc thành phẩm hay log làm việc — chỉ xét đạt/không đạt bằng exit code của test hoặc linter. |
| Một đề xuất đã bị từ chối lại quay lại ở phiên sau |
Gom mọi quyết định đã bị từ chối vào một tài liệu duy nhất, theo một định dạng cố định. |
| Dù đã viết một dòng cấm, nó vẫn bị diễn giải rộng ra hoặc hẹp lại |
Trong tài liệu duy nhất gom các quyết định đã bị từ chối (ví dụ non_goals.md), với mỗi điều cấm hãy thêm mục "lý do" đặt cạnh kết luận. |
| Điều cấm viết đúng nhưng không được tuân theo, và mỗi lần lại có người hỏi lại |
Trong tài liệu các quyết định bị từ chối, với mỗi điều cấm hãy thêm mục "phạm vi áp dụng" và liệt kê từng dòng các trường hợp biên gây khó phán đoán. |
| Đưa cùng một chỉ dẫn cho nhiều sub-agent thì kết quả trả về mỗi lần một hình dạng khác nhau |
Trong danh sách tác vụ được phép giao cho sub-agent, ghi rõ những file input cần chuẩn bị sẵn trước khi khởi chạy. |
| Các điều cấm không có automated test cứ chồng chất lên, chỉ tồn tại như chữ trên giấy |
Trong tài liệu các quyết định bị từ chối, thêm mục "kiểm chứng bằng máy" vào danh sách và ghi rõ theo từng mục có automated test (Minitest) tương ứng hay không. |
| Mỗi lần AI làm xong việc đều kết thúc bằng câu "vui lòng mở màn hình kiểm tra giúp" |
Chuẩn bị sẵn một smoke test bằng Playwright, và xét đạt/không đạt dựa trên bản ghi còn lại trong DB thay vì nhìn giao diện. |
| Mỗi lần AI nói điều gì hơi lệch, chính bạn lại là người phải giải thích và sửa lại |
Thay vì người giải thích và sửa từng chỗ lệch, hãy ghi lời chỉ ra vào stderr của hook (exit 2) và vào thông báo lỗi của automated test, để đó là con đường nó đến được AI. |
| Danh sách các quyết định đã bị từ chối cứ dài thêm, có vẻ sẽ đến lúc không ai đọc nữa |
Thêm mục "đề xuất không áp dụng" ở cuối tài liệu các quyết định bị từ chối, và ghi lại các đề xuất bị từ chối vào đó. |
| Dòng "nhất định phải chạy lệnh này" trong file chỉ dẫn cứ tồn tại mãi, không giảm đi |
Dùng một automated test để đối chiếu xem mọi lệnh mà file chỉ dẫn ghi là "nhất định phải chạy" có thực sự tồn tại trong pre-commit hook hay không. |
| Đã viết rõ cả cách làm mà đưa ra rồi, kết quả sửa vẫn không đúng như vậy |
Thay vì chỉ dẫn cả quy trình, định nghĩa theo từng mục đích sử dụng những file input phải tồn tại trước khi khởi chạy sub-agent. |
| Báo lỗi lần nào cũng phải tự viết lại các bước thao tác và triệu chứng |
Đặt một form báo lỗi, để người dùng chỉ cần gõ đúng một câu mô tả triệu chứng, còn URL, lịch sử thao tác và thông tin trình duyệt để JavaScript tự thu thập. |
| Công gõ "hãy đưa kế hoạch trước" mỗi lần vẫn cứ lặp lại |
Không cần thêm gì mới. Chỉ cần đặt sẵn một tài liệu thiết kế, AI sẽ đọc các tài liệu có sẵn và làm theo đúng thể thức đó. |
| Những dòng càng muốn được tuân theo lại càng viết nhấn mạnh, nhưng không biết có hiệu quả hay không |
Bỏ việc đo hiệu quả — thay vào đó đếm số dòng dùng cách nhấn mạnh trong file chỉ dẫn, và đặt một automated test (ratchet) báo lỗi khi con số đó vượt ngưỡng. |
| Thành phẩm sub-agent trả về có hình dạng khác với dự tính |
Với mỗi mục đích sử dụng sub-agent, định nghĩa điều kiện chấp nhận cho thành phẩm — tên file, định dạng, các trường bắt buộc — trong một tài liệu duy nhất. |
| Tìm ra một chỗ sai thì lại muốn hỏi vặn "đã đọc kỹ chưa vậy" |
Thay vì hỏi vặn, cố định câu thứ hai của mỗi yêu cầu thành mẫu câu hỏi "chẳng phải ... hay sao?". |
| Trả lời "không phải vậy" cho câu trả lời nhận được cũng không làm nó tốt hơn |
Thay vì tự chỉ ra, đưa các điều cấm không kèm phương án thay thế qua một PostToolUse hook, hiển thị cùng diff ngay sau khi lưu. |
| AI nói về nội dung một file như thể đã mở nó, dù thực ra chưa mở |
Bắt AI ghi các marker tương ứng ở cả tài liệu được tham chiếu lẫn trong code, rồi dùng automated test kiểm chứng rằng các marker đó thực sự tồn tại. |
| AI cứ hỏi "chọn A hay B" liên tục, khiến công việc dừng lại chờ bạn quyết định |
Ngừng trả lời ngay lập tức — thu xếp để việc lựa chọn được quyết định bởi automated test hoặc hook. |
| AI đang làm review, nhưng không rõ nó bỏ sót phần nào |
Dùng một automated test bên ngoài để đếm số lượng, nhằm phát hiện automated test nào quét file nhưng không có assertion chặn dưới về số lượng (ví dụ assert_operator ... :>=). |
| Ảnh chụp màn hình cứ chồng chất, nhưng không rõ ảnh nào xác nhận điều gì |
Trước khi kiểm tra màn hình, bắt trả lời hai câu hỏi — "đang xác minh điều gì" và "vì sao cách rẻ hơn không đủ" — và đặt sẵn một hướng dẫn 1 trang ưu tiên thử cách rẻ nhất trước, theo thứ tự unit test → integration test → E2E. |
| Đã đặt bước bắt buộc phải khai báo, nhưng không đếm được bao nhiêu lần chạy đã bỏ qua bước đó |
Trước khi chụp màn hình hay chạy E2E, hãy bắt viết một file khai báo nêu rõ đang xác minh điều gì (ví dụ tmp/visual_verification.md), biến sự tồn tại của nó thành điều kiện của một PreToolUse hook, và không có nó thì chụp màn hình hay E2E không được khởi động. |
| Code không đổi mà cùng một test vẫn chạy lại, và vẫn phải chờ thêm lần nữa |
Thêm tùy chọn --last vào wrapper script của test để phát lại log lần trước, khỏi cần chạy lại. |
| Chẳng có gì hỏng cả mà vẫn hiện ra một loạt lỗi lạ chưa từng thấy |
Cho wrapper script của test lấy một exclusive lock (dựa vào tính nguyên tử của mkdir), và không chạy nếu không lấy được lock. |
| Báo cáo "test đã pass" không nói rõ phần nào đã không được chạy |
Gắn tag theo tên khu vực cho các E2E nặng, mặc định skip chúng, và mỗi lần đều in ra danh sách các khu vực chưa chạy. |
| Không có cách nào để biết sau này liệu một chỉ dẫn quy định cách làm có thực sự được tuân theo hay không |
Khi muốn quy trình được tuân thủ, đừng viết chỉ dẫn mạnh hơn — thay vào đó đổi cách làm để dấu vết của việc tuân theo quy trình đó lưu lại trong thành phẩm (ví dụ: in ra 1 dòng cho mỗi file đã mở). |
| Wrapper đã đặt sẵn dần dần lại bị bỏ, quay về dùng lệnh gốc |
Khi muốn wrapper được dùng, đừng viết chỉ dẫn mạnh hơn — thay vào đó kiểm tra xem có còn lý do phải quay lại lệnh gốc không (tức là wrapper còn thiếu chức năng gì). |
| Hỏi cùng một câu nhiều lần thì mỗi lần câu trả lời lại khác nhau. Gộp lại thì có gì đó bị mất |
Trước khi gộp nhiều câu trả lời thành một, in ra số lần xuất hiện của từng loại nhận xét — bao nhiêu trong số bao nhiêu đã nêu ra điều đó. |
| Không biết được dòng "nếu cần thì hãy làm X" có từng thực sự được kích hoạt hay không |
Đừng viết chỉ dẫn có điều kiện kiểu "nếu cần thì hãy làm X" — thay vào đó bắt buộc bước đó bằng một hook chặn không cho đi tiếp nếu chưa qua bước đó. |
| Bảo "hãy suy nghĩ lại lần nữa" thì câu trả lời đổi khác, nhưng không rõ AI đã thực sự hiểu ra chưa |
Thay vì trả lại với câu "hãy suy nghĩ lại lần nữa", chỉ ra cụ thể tiền đề nào đang sai. |
| Viết "đừng đoán mò" thì AI bắt đầu quay lại mà chẳng làm ra được gì cả |
Đừng chỉ đưa ra điều cấm — kèm theo cả một đầu ra thay thế, kiểu như "nếu không có trường hợp nào phù hợp thì hãy in ra 'không áp dụng'". |
| Cuộc trò chuyện đang suôn sẻ càng kéo dài, công sức để kiểm chứng lại càng tăng |
Kết thúc phiên làm việc tại mỗi mốc hoàn thành tác vụ, và bắt đầu tác vụ tiếp theo trong một phiên mới. |
| Mọi thành phẩm đều đúng cả, nhưng lãng phí không hiện ra trong đó cứ tích tụ dần |
Khi thành phẩm đã hoàn tất, chạy một script để tổng hợp một lần chính bản thân work log (transcript). |
| Ghi chú kiến thức để lại cho người sau dần lệch khỏi thực tế và trở nên lỗi thời |
Đừng ghi kiến thức vào tài liệu — hãy nhúng nó vào thông báo lỗi của automated test hoặc thông báo dừng của hook, để nó hiện ra đúng vào lúc cần. |
| Cứ đào sâu tìm nguyên nhân, và vẫn tiếp tục đọc ngay cả sau khi đã có câu trả lời |
Đếm từ work log số lần đọc liên tiếp mà không thay đổi gì cả, và viết một dòng điều kiện dừng trước khi bắt đầu đào sâu. |
| Chọn mô hình có đơn giá rẻ nhất làm mặc định mà không đo xem nó có phù hợp mục đích hay không |
Giao cùng một tác vụ cho cả mô hình rẻ lẫn mô hình đắt, rồi chỉ quyết định sau khi đếm riêng số lượt cho tới khi hoàn thành, cùng lượng đọc mới, lượng dùng lại (cache read) và lượng viết ra. |
| Khi có gì đó không ổn, cách xử lý là nâng cấp mô hình chứ không phải sửa cơ chế |
Giao cùng một tác vụ cho cả mô hình đắt và mô hình rẻ, rồi biến những chỗ chỉ mô hình rẻ bị hỏng thành một kiểm tra cố định. |
| Việc tra cứu mà bản thân phiên chính tự làm xong được vẫn cứ giao cho sub-agent cho chắc |
Trước khi giao việc, xem xem agent cha đã có sẵn tiền đề đó chưa. Nếu có rồi thì tiếp tục làm ở agent cha; chỉ giao cho sub-agent phần đọc khối lượng lớn mà agent cha chưa có. |
| Cứ chia ra làm 4 rồi chạy song song cùng lúc, không vì lý do gì rõ ràng |
Chỉ giao cho mỗi sub-agent lượng việc vừa đủ trả lời trong một lượt phản hồi. Yếu tố quyết định chi phí không phải là số lượng sub-agent, mà là mỗi sub-agent sau khi chia phải qua lại với agent cha bao nhiêu lượt. |
| "Xem luôn cả chỗ này nữa" bị chen ngang từ bên ngoài vào giữa lúc đang làm |
Chờ đến mốc tự nhiên của công việc rồi mới đưa yêu cầu bổ sung vào, với phạm vi đã thu hẹp. Khi hỏi chính AI về chỗ thiếu, luôn thêm câu: "nếu đã đủ thì hãy nói rõ là đã đủ". Đó là lối thoát (escape hatch) để nó không phải bịa ra một chỗ thiếu. |
| Đang cố quyết định dùng mô hình nào bằng cách so sánh trực tiếp |
Trước khi bắt đầu so sánh mô hình, đếm xem việc so sánh đó tốn công bằng bao nhiêu hook hay automated test. Nếu số cơ chế có thể viết ra nhiều hơn con số đó, hãy đặt chúng vào trước rồi mới so sánh. |
| Lấy "không thấy khác biệt" làm lý do để kết thúc việc kiểm chứng |
Trước khi kết thúc bằng "không thấy khác biệt", đếm hai điều: nếu có kết quả bị loại khỏi tổng hợp (chẳng hạn các sub-agent thất bại) thì đưa lại vào và đếm lại; nếu hơn một nửa số mục đều bằng 0 ở mọi điều kiện thì đổi cách diễn đạt tác vụ rồi đo lại. |
Mục lục toàn bộ bài viết
Theo từng loạt bài, từ phần mở đầu tới phần cuối.
はじめに —— 3 つの連載を、1 冊に
バイブコーディングにおける読まない技術
- 読まない技術 序論 AIの出力を、もうほとんど読んでいない
- 読まない技術 第1回 テスト結果を読まない技術
- 読まない技術 第2回 メモリを読まない技術
- 読まない技術 第3回 単体テストを読まない技術
- 読まない技術 第4回 スキルを使わない技術
- 読まない技術 第5回 サブエージェントの出力だけは読め
- 読まない技術 第6回 ルールを読まない技術
- 読まない技術 第7回 共有メモリを整理しない技術
- 読まない技術 第8回 修正履歴を読まない技術
- 読まない技術 第9回 引き継ぎを読まない技術
- 読まない技術 第10回 AIに要約しろと言わない技術
- 読まない技術 第11回 口を挟まない技術
- 読まない技術 第12回 作業結果を読まない技術
- 読まない技術 最終回 AIの出力を、ほとんど読まなくなった
AIの意見を聞かない技術
言わない技術
- 言わない技術 序論 AI に指示することが、ほとんどなくなった
- 言わない技術 第1回 検証を指示しない技術
- 言わない技術 第2回 具体的な指示を出さない技術
- 言わない技術 第3回 不具合詳細を書かない技術
- 言わない技術 第4回 計画を書けと言わない技術
- 言わない技術 第5回 念を押さない技術
- 言わない技術 第6回 サブエージェントの出力だけは、細かく指示しろ
- 言わない技術 第7回 AI を問い詰めない技術
- 言わない技術 第8回 AI にダメ出ししない技術
- 言わない技術 第9回 AI に考えさせない技術
- 言わない技術 第10回 質問に答えない技術
- 言わない技術 第11回 AI にレビューをさせない技術
- 言わない技術 最終回 何もしない技術
付録
はじめに —— 前巻の続きを、もう 1 冊に
確かめない技術
動かさない技術
追わない技術
番外編
- 番外編 A-1 整理する技術 —— 記録が増えたときに、何が起きているか
- 番外編 A-2 指示を残す技術 —— 「調べるだけ」が通らなかった日
- 番外編 A-3 参照するタイミングを変える技術 —— 2,000 行の壁
- 番外編 A-4 導出を依頼者の言葉と分ける技術 —— 誰も言っていない条件が、memory に載った日
- 番外編 A-5 memory を要約しない技術 —— 整理から、要約を抜く
- 番外編 A-6 責務で線を引く技術 —— 仕組みが増えたときに、どれを消すか
- 番外編 A-7 読まれたかを確かめる技術 —— 確かめるのをやめて、読めていない形を止めた
- 番外編 A-8 面積で数える技術 —— 読ませた量で数えていたら、102 倍外していました
- 番外編 A-9 ルールを短くする技術 —— 読みに来るのは、止められた直後の人です
- 番外編 B-1 連載を本にする技術 —— 本単位のスイッチでは、足りなかった日
- 番外編 C-1 校正の方法に、先に本編を当てる技術 —— 方法を決める文が、本文と同じ地雷を踏んでいた日
- 番外編 C-2 仕組みと人を分ける技術 —— 検査を置いたその手で、検査の外側で 2 度転んだ日
- 番外編 C-3 要素ごとに観点を変える技術 —— 一様に当てた点検が、要素をまたいだところで数を落としていた
- 番外編 C-4 指示の揺れを、事故として残す技術 —— 事故を見て置いた仕組みは、まだ一度も鳴っていない
- 番外編 C-5 作業の流れを見る技術 —— 終わりにしたつもりの日に、まだ起きていたこと
- 番外編 C-6 作業を進める技術 —— 選ぶ場面が、1 つも残らなかった日
- 番外編 C-7 基準の出どころを見る技術 —— 2 分前に開いたページに、答えが書いてありました
- あとがき —— 本当の事実はどうでもいい話