7.1 KiB
| 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
1. Parse link
Từ URL suy ra:
GITEA_HOST= scheme + host.OWNER,REPO.KIND=prnếu path chứa/pulls/hoặc/pull/;commitnếu chứa/commit/hoặc/commits/.REF= số PR (chopr) hoặc SHA (chocommit).
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}.difflư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
authkhông? (theostart/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/restoreStatecó cover không. - Idle-timeout (
setTimeoutConnect, 8h) và keep-alive (keepConnectAPC40s /keepConnectStation120s) 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.
4.3. Performance
- Vòng lặp lồng nhau / N+1 query Lucid (eager loading?).
awaittrongforthay vìPromise.allkhi có thể song song.- Re-render React thừa (
App.tsxđang dùnglineBuffersRef+ flush 50ms — diff mới có phá vỡ pattern này không). - Bộ nhớ giữ output dài (truncate ở
saveState5000 chars — diff mới có giữ thêm field nặng không). - Setinterval/setTimeout có dồn (leak) không.
4.4. Consistency
Hai gạch đầu dòng phụ:
- Đúng
CLAUDE.md? Đối chiếu từng quy ước liên quan: subpath imports#controllers/*(không phải relative trừ file ngoàiapp/), folder namesultils/untils(không rename), VN/EN comment language giữ nguyên, hot-reload boundaries, idle/keep-alive paired,saveState/restoreStateextend khi thêm state. - Đúng coding standard? ESLint flat config / Prettier / TS strict / naming convention (camelCase biến, PascalCase component,
T*prefix cho type ở FE). Đặt tên file/component có nhất quán không. Comment có ý nghĩa, không lặp lại code.
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).
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: <1–2 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
/simplifyhoặc/code-review --fixriêng. - Không comment lên Gitea / Jira.
- Không approve / merge / close PR.
- Không in password.