Hai giờ sáng, điện thoại tôi réo. Production đỏ lừ. Tôi mò dậy, dò log, lần ngược… tới một thay đổi đã merge ba ngày trước — một thay đổi nhỏ xíu, lúc đó build xanh, test xanh, review lướt cũng xanh.
Đó là lúc tôi thấm: bug làm build đỏ chẳng đáng sợ. Nó nổ ngay trước mặt, khi bạn còn nhớ vừa đụng gì. Đáng sợ là loại để mọi thứ xanh — rồi nằm im chờ.
Và đây đúng là loại bug một agent giỏi tạo ra nhiều nhất.
01Vì sao agent mù chiều này
Agent nhìn thấy cái file trước mặt. Nó không thấy đồ thị lời gọi — cái mạng nhện những chỗ khác đang dựa vào đoạn nó sắp sửa. Tệ hơn: nó mất trí nhớ về phần còn lại của hệ thống. Bạn mở một hàm ra cho nó, nó sửa đúng cái hàm đó, gọn gàng — và hoàn toàn không biết có mười hai nơi đang trông cậy vào hành vi cũ.
Một thay đổi tưởng nhỏ, sóng lan ra mọi nơi đang phụ thuộc. Agent chỉ thấy tâm sóng — không thấy vòng ngoài.
02Cái gì là "dùng chung"
Quy tắc: trước khi đổi bất cứ thứ gì nằm trên một ranh giới mà người hay đoạn-code khác dựa vào, hãy dừng. Danh sách hay là ranh giới: chữ ký hàm (đổi tham số, kiểu trả về), shape dữ liệu (thêm/bớt field), tên một field/key (nhất là thứ đi qua serialize, lưu DB, gửi qua API), hàm tiện ích dùng chung, config, một hợp đồng API công khai.
Sửa bên trong thân một hàm, không đụng ranh giới ngoài? An toàn, cứ để nó làm. Vượt một ranh giới người khác dựa vào? Vẽ bản đồ trước.
03Bắt nó vẽ bản đồ trước
Trước khi sửa, ép agent trả lời đúng một câu: "Cái gì đang phụ thuộc vào nó?" Và bắt nó liệt kê ra, không nói chung chung. Có công cụ phân tích phụ thuộc thì dùng — vài giây có danh sách. Không có thì câu lệnh tối thiểu: bắt nó grep cái tên đó toàn repo và bày từng nơi đọc/gọi ra cho bạn xem trước khi đụng dòng nào.
04Một ví dụ rất quen
Đổi tên một field từ userId thành accountId. Nghe như một thao tác rename.
Thực tế nó chạm: mười bốn chỗ đọc field, một hàm serialize ra JSON, một chỗ map sang cột database, và hai chuỗi nối tay mà rename tự động không bắt được. Agent không vẽ bản đồ sẽ đổi ba chỗ rõ nhất, báo "Done!", và để lại mười lăm quả mìn — mỗi quả chờ một code path khác kích nổ.
Chi phí bắt nó liệt kê phụ thuộc là ba mươi giây. Chi phí bỏ qua là một cú điện thoại lúc hai giờ sáng. Tôi biết rõ cái giá thứ hai — tôi trả nó rồi.