Skip to content

Instantly share code, notes, and snippets.

@nghyane
Created February 26, 2026 06:59
Show Gist options
  • Select an option

  • Save nghyane/c6bc7abcbf618d13993eda348fefa5fa to your computer and use it in GitHub Desktop.

Select an option

Save nghyane/c6bc7abcbf618d13993eda348fefa5fa to your computer and use it in GitHub Desktop.
Codebase Audit với AI Coding Agent: Prompt như thế nào để không bỏ sót

Codebase Audit với AI Coding Agent: Prompt như thế nào để không bỏ sót

Hầu hết developer dùng AI coding agent để viết code. Ít ai dùng nó để xóa code. Đây là bài viết về việc sử dụng AI agent (Claude Code, Cursor, v.v.) để tìm và loại bỏ dead code, stale architecture, wrapper pattern thừa — và cách prompt sao cho kết quả thực sự toàn diện.

Vấn đề: Grep không phải là proof

Cách phổ biến nhất để tìm dead code: grep tên function, thấy 0 kết quả, kết luận nó dead. Sai.

  • Grep không hiểu re-exports. export { X } from "./foo" rồi import { X } from "./barrel" — grep tìm "foo" sẽ bỏ qua consumer thật.
  • Grep không phân biệt type-only import vs runtime import. Symbol có thể được import bởi 10 files nhưng chỉ dùng ở type position — runtime code vẫn dead.
  • Grep match text, không match semantics. toolResult trong import { toolResult }const toolResult = { role: "toolResult" } là hai thứ hoàn toàn khác nhau.

Khi bạn bảo AI agent "tìm dead code", nó sẽ dùng grep. Và nó sẽ bỏ sót.

Nguyên tắc: Compiler là proof, grep là heuristic

Cách duy nhất chứng minh code dead: xóa nó, chạy compiler, xem có gì vỡ không.

Với mỗi exported symbol trong src/utils/*.ts:
- Tạm xóa symbol đó
- Chạy bun check (hoặc tsc, cargo check)
- Nếu pass → symbol dead, ghi nhận
- Revert
Chỉ report, không fix.

Agent có khả năng edit, check, undo trong cùng 1 turn. Tận dụng nó. Đây không phải là cách con người audit code — quá chậm, quá tedious. Nhưng máy thì không care.

6 kỹ thuật prompt cho audit toàn diện

1. Staged removal

Thử xóa [module]. Chạy typecheck. 
Pass → dead. Fail → revert, report consumers.

Đơn giản nhất, chính xác nhất. Không false positive. Agent xóa thử, compiler verify, agent revert. Bạn chỉ nhận report.

Khi nào dùng: Khi bạn nghi ngờ 1 file/module cụ thể là dead nhưng không chắc vì dependency graph phức tạp.

2. Diff-driven scope

git log --diff-filter=D --name-only -20
Tìm references còn sót tới files đã xóa.

Dead code không xuất hiện từ hư không. Nó sinh ra khi ai đó xóa feature nhưng không clean hết references. Config entries, type re-exports, model roles, setting schemas — những thứ này hay bị bỏ sót vì chúng không gây compile error.

Khi nào dùng: Sau mỗi đợt refactor lớn. Hoặc khi bạn thấy codebase có nhiều deleted files trong git log gần đây.

Ví dụ thực tế: Một module commit/ với 50+ files bị xóa. Sau khi xóa, vẫn còn sót:

  • CommitSettings interface trong settings schema
  • "commit" model role trong registry
  • format-prompts script reference tới commit/prompts/ directory
  • Re-export trong settings.ts

Không cái nào gây compile error. Tất cả đều là dead weight mà grep bình thường không target.

3. Cross-layer consistency

Cross-reference:
1. Tool registration (BUILTIN_TOOLS)
2. Settings schema (*.enabled keys)
3. Renderer registration (registerRenderer)
4. Agent allowlists (task/agents.ts)
5. Frontmatter tool lists (.md files)

Report mismatches.

Ứng dụng lớn thường có nhiều "registration layers" — nơi một entity (tool, plugin, feature) phải được khai báo ở nhiều chỗ. Khi xóa feature, dễ bỏ sót 1-2 layers.

Khi nào dùng: Khi codebase có plugin/tool architecture với multiple registration points.

4. Invert dependency graph qua LSP

Với mỗi exported symbol trong src/tools/*.ts:
dùng LSP references đếm consumers.
Report symbols có 0-1 consumers.

LSP (Language Server Protocol) hiểu code ở semantic level — nó biết import type { X } khác import { X }, biết re-export chain, biết interface implementation. Prompt agent dùng LSP thay vì grep cho kết quả chính xác hơn nhiều.

Khi nào dùng: Khi cần audit exports của utility/shared modules. Đặc biệt hiệu quả cho barrel files (index.ts) nơi re-exports tích tụ qua thời gian.

5. High-churn targeting

git log --since=3months --format= --name-only src/ | sort | uniq -c | sort -rn | head 20

Với 20 files churn cao nhất: audit wrapper patterns, over-abstraction, SRP violations.

Không phải mọi code xấu đều đáng fix. File 500 dòng không ai đụng 1 năm — để yên. File 50 dòng bị sửa mỗi tuần — mỗi lần sửa đều trả cost cho design tệ. Churn rate là proxy tốt nhất cho ROI của refactor.

Khi nào dùng: Khi cần prioritize — quá nhiều tech debt, không biết bắt đầu từ đâu.

6. Type-only dependency detection

Tìm files chỉ được import qua `import type`.
Nếu file export cả runtime code mà chỉ có type consumers → runtime code dead.

Đây là blind spot mà cả compiler lẫn linter đều bỏ qua. File export 1 class và 1 interface. Interface được import type bởi 5 files. Class không ai dùng. Compiler thấy file có consumers → không warn. Nhưng runtime code trong file đó hoàn toàn dead.

Khi nào dùng: Trong TypeScript codebases nặng type — monorepos với shared type packages.

Anti-patterns khi prompt audit

"Tìm tất cả vấn đề"

Quá mơ hồ. Agent sẽ cherry-pick vài thứ dễ tìm (unused imports, obvious dead functions) rồi dừng. Bạn nghĩ scan xong, thực ra mới quét bề mặt.

Thay bằng: Nêu rõ category — dead exports, orphaned files, stale config, wrapper indirection.

Gộp scan + fix trong 1 prompt

# Đừng
Tìm và xóa tất cả dead code.

# Nên
Tìm dead code. Report theo category và priority. Không fix.

Agent sẽ tìm 3 thứ, fix luôn, rồi dừng — vì nó nghĩ task xong. Tách scan và fix thành 2 bước để bạn review findings trước khi quyết định.

Scan toàn bộ repo khi chỉ care 1 package

Scope càng rộng, kết quả càng shallow. Nếu bạn biết vấn đề nằm ở packages/core/, nói rõ. Agent sẽ deep dive thay vì skim.

Workflow đề xuất

Bước 1 (Discovery):    Scan rộng theo categories → nhận report
Bước 2 (Verification): Với mỗi finding, staged removal để confirm
Bước 3 (Review):       Bạn quyết định cái nào fix, cái nào để
Bước 4 (Execution):    Agent fix từng batch, verify sau mỗi batch

Mỗi bước là 1 prompt riêng. Bước 1-2 agent làm autonomous. Bước 3 bạn quyết định. Bước 4 agent thực thi.

Template sẵn dùng

Copy và điều chỉnh cho project của bạn:

Audit `[package/directory]`:

1. Orphaned files — .ts files với zero inbound imports (trừ entry points)
2. Dead exports — exported symbols với zero external consumers (dùng LSP, không grep)
3. Stale config — settings/schema entries reference features đã xóa
4. Wrapper indirection — class/function chỉ delegate 1:1 tới target khác
5. Registration mismatches — entity có mặt ở layer A nhưng vắng ở layer B

List findings theo category, kèm severity và recommended action.
Với mỗi finding nghi ngờ, dùng staged removal để confirm.
Không fix — chỉ report.

Dead code không gây bug. Nó gây friction — mỗi lần đọc, mỗi lần navigate, mỗi lần onboard người mới. AI agent là công cụ tốt nhất hiện tại để tìm nó, miễn bạn prompt đúng cách.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment