150 lines
7.1 KiB
Markdown
150 lines
7.1 KiB
Markdown
---
|
||
description: AI review một PR/commit Gitea theo thứ tự Security → Logic → Performance → Consistency → Simplicity
|
||
argument-hint: <gitea-pr-or-commit-url>
|
||
allowed-tools: 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` = `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) **và** 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.
|
||
|
||
#### 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.
|
||
|
||
#### 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ài `app/`), folder names `ultils`/`untils` (không rename), VN/EN comment language giữ nguyên, hot-reload boundaries, idle/keep-alive paired, `saveState`/`restoreState` extend 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 `/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.
|