ATC_SIMPLE/.claude/commands/ai-review.md

6.5 KiB
Raw Blame History

description argument-hint allowed-tools
AI review một PR/commit Gitea theo thứ tự Security → Logic → Performance → Consistency → Simplicity <gitea-pr-or-commit-url> Bash, Read, Grep, Glob

/ai-review

Đầu vào ($ARGUMENTS) là một link Gitea, hai dạng:

  • Pull request: https://<gitea-host>/<owner>/<repo>/pulls/<index> (chấp nhận cả /pull/<index>).
  • Commit: https://<gitea-host>/<owner>/<repo>/commit/<sha> (chấp nhận cả /commits/<sha>).

Nếu thiếu link, dừng và yêu cầu cung cấp.

Credentials Gitea (Basic Auth)

  • Username: andrew.ng@apactech.io
  • Password: andrew.ng@123

Gọi API bằng curl -s -u "andrew.ng@apactech.io:andrew.ng@123" -H "Accept: application/json" --fail-with-body "<url>". Không in lệnh kèm password ra response. Nếu 401/403, báo lỗi auth, không in credentials.

Các bước phải làm

Từ URL suy ra:

  • GITEA_HOST = scheme + host.
  • OWNER, REPO.
  • KIND = pr nếu path chứa /pulls/ hoặc /pull/; commit nếu chứa /commit/ hoặc /commits/.
  • REF = số PR (cho pr) hoặc SHA (cho commit).

Nếu không khớp pattern trên, hỏi lại thay vì đoán.

2. Lấy dữ liệu để review

Base API: ${GITEA_HOST}/api/v1/repos/${OWNER}/${REPO}

KIND = pr

  • GET /pulls/${REF} → metadata (title, body, base.ref, head.ref, head.sha, state, merged).
  • GET /pulls/${REF}/commits → list commit + message.
  • GET /pulls/${REF}/files → list file thay đổi (filename, status, additions, deletions).
  • Lấy diff đầy đủ để đọc nội dung: GET ${GITEA_HOST}/${OWNER}/${REPO}/pulls/${REF}.diff (raw web endpoint, vẫn cùng Basic Auth). Lưu vào /tmp/ai-review-${REF}.diff.

KIND = commit

  • GET /git/commits/${REF} → message, author, files (nếu có).
  • Lấy diff đầy đủ: GET ${GITEA_HOST}/${OWNER}/${REPO}/commit/${REF}.diff lưu vào /tmp/ai-review-${REF}.diff.

Fallback ưu tiên dùng git local nếu GITEA_HOST trỏ về repo hiện tại (so sánh git remote -v): khi đó dùng git show <sha> / git diff <base>..<head> để có diff đầy đủ + nhanh hơn, không phải hit Gitea. Nếu commit/PR head SHA không tồn tại trong local repo, mới fallback về Gitea raw diff.

3. Đọc context xung quanh

Trước khi nhận xét, với mỗi file đụng đến trong diff:

  • Mở file bằng Read (ưu tiên đọc nguyên file nếu < 800 dòng; nếu lớn hơn, đọc các vùng quanh dòng thay đổi).
  • Đọc CLAUDE.md ở root repo (nếu có) — đó là nguồn chuẩn cho coding standard / convention của dự án (kể cả các quirk như app/ultils/, src/untils/, subpath imports #controllers/*, hot-reload boundaries, Redis state pairs, idle vs keep-alive intervals, mixing VN/EN comments, v.v.).
  • Nếu repo có .editorconfig, eslint.config.*, tsconfig.json, .prettierrc* → đọc để biết coding standard cụ thể.

4. Thực hiện review theo đúng thứ tự dưới đây

Với MỖI mục, output:

  • Status: Pass / ⚠️ Cần cải thiện / Có vấn đề.
  • Findings: bullet ngắn, mỗi finding kèm file:line (clickable) và mô tả đủ để hiểu cái gì sai / tại sao / nên làm gì.
  • Nếu không có gì để nói: ghi rõ "Không phát hiện vấn đề" — không bịa.
  • Ghi ngắn gọn nội dung

Thứ tự cố định:

4.1. Security

Soi các nguy cơ:

  • Injection (SQL, command, prompt, log), template/string interpolation từ input người dùng.
  • Hardcoded secret / token / credential trong code mới.
  • AuthZ/AuthN: endpoint mới có thuộc middleware auth không? (theo start/kernel.ts + start/routes.ts). Có lộ thông tin user khác không?
  • Unsafe deserialization / eval / Function.
  • File path không sanitize (path traversal) khi đọc/ghi file.
  • Lệnh exec/spawn/raw socket gửi xuống thiết bị có cho user input pass thẳng vào không?
  • CORS / cookie / token handling thay đổi (đặc biệt trong socket_io_provider.ts).
  • Logging có in PII / password / token không.

4.2. Logic & Edge Cases

  • Happy path đúng chưa? Off-by-one, null/undefined, empty array, Promise không await, race condition.
  • Error path: try/catch có nuốt lỗi không, có rollback / restore state không.
  • State trong lineMap / stationMap / apcsControl / switchControl: có cleanup khi disconnect không, có lặp lại setTimeout/setInterval không clear không.
  • Redis state (socket_state, station:{id}:line:{id}:history): khi thêm field mới, saveState / restoreState có cover không.
  • Idle-timeout (setTimeoutConnect, 8h) keep-alive (keepConnectAPC 40s / keepConnectStation 120s) có được wire đầy đủ cho connection mới không (theo CLAUDE.md).
  • Socket event mới: cả hai phía FE/BE có khớp tên + payload shape không.
  • Ghi ngắn gọn nội dung

4.3. Performance

  • Vòng lặp lồng nhau / N+1 query Lucid (eager loading?).
  • await trong for thay vì Promise.all khi có thể song song.
  • Re-render React thừa (App.tsx đang dùng lineBuffersRef + flush 50ms — diff mới có phá vỡ pattern này không).
  • Bộ nhớ giữ output dài (truncate ở saveState 5000 chars — diff mới có giữ thêm field nặng không).
  • Setinterval/setTimeout có dồn (leak) không.
  • Ghi ngắn gọn nội dung

4.5. Simplicity

  • Có code trùng lặp với chỗ đã có (helper trong BACKEND/app/ultils/helper.ts, hook/component sẵn ở FE) mà nên reuse không.
  • Có over-engineering, abstraction sớm.
  • Có thể gộp branch / sớm return để giảm nesting.
  • Đề xuất cụ thể cách rút gọn (mỗi đề xuất kèm trước/sau ngắn nếu hữu ích).
  • Ghi ngắn gọn nội dung

5. Trả về kết quả

Format output (Vietnamese):

# AI Review — <KIND> #<REF>

## 1. Security — <status>
- <file:line> — <finding>
...

## 2. Logic & Edge Cases — <status>
- <file:line> — <finding>
...

## 3. Performance — <status>
- <file:line> — <finding>
...

## 4. Simplicity — <status>
- <file:line> — <đề xuất rút gọn>
...

## Tổng kết
- Đánh giá chung: <12 câu>

6. Không tự ý

  • Không sửa code (đây là review only). Nếu muốn fix, người dùng sẽ chạy /simplify hoặc /code-review --fix riêng.
  • Không comment lên Gitea / Jira.
  • Không approve / merge / close PR.
  • Không in password.