GitLab Flow (Jira → Code → MR → Merge)
Quy trình chuẩn cho một feature/bugfix mới. Có 2 vai trò: Developer (người làm task) và Reviewer (người review MR). Skill này hướng dẫn Claude thực hiện đúng từng bước theo prompt mà user gọi.
📦 Phần vai Reviewer nằm ở skill riêng. 4 trigger review the whole branch, review the MR !<N>, post review result to the MR, merge the request đã chuyển sang skill gitlab-review (add-on, chỉ Lead cài). Skill này giữ nguyên Conventions mà gitlab-review tham chiếu tới. Không cài gitlab-review ⇒ không có 4 trigger đó — nhờ Lead chạy hộ, đừng tự dựng lại quy trình.
Conventions
Branch naming
- Default: mọi branch dùng
feature/ — bất kể task là feature, bug fix, hay hotfix.
- Format:
feature/<TASK-ID>-<short-desc>
- Bug-fix branches dưới
feature/: mô tả trạng thái bug bằng direction marker (Duplicate, Stale, Missing, Broken, Wrong, Slow) thay vì verb "Fix" — vd feature/HNCW-311-Duplicate-survey-log
- Override: user chủ động gõ
bugfix/... hoặc hotfix/... trong prompt (Mode A) → skill respect và tạo đúng prefix đó. Skill KHÔNG tự động chọn bugfix/ hay hotfix/ dựa trên nội dung task.
Quy tắc <short-desc> (đủ để hiểu task ở first glance, chi tiết để Jira giữ):
| Rule |
Detail |
| Độ dài tổng |
≤ 50 ký tự cả branch (target ≤ 40). Vượt → rút thêm |
| Số từ |
2-4 từ key. Filler bị drop |
| Ngôn ngữ |
Tiếng Việt không dấu, kebab-case (- ngăn cách) |
| Capitalization |
Sentence case STRICT: chỉ chữ cái đầu của từ đầu tiên trong description viết hoa. Mọi từ sau (KỂ CẢ viết tắt như NVKD, VAT, API, JWT) đều lowercase. Vd Bao-cao-ngay-nvkd (KHÔNG Bao-cao-ngay-NVKD), Vat-discount (KHÔNG VAT-discount), Gioi-han-domain-account. TASK-ID giữ nguyên uppercase per Jira convention |
| Drop type filler |
"Cai-tien", "Update", "Improve", "Fix", "Sua", "Sua-loi", "Them", "Tao", "Add", "Create", "Bo-sung" — đều bỏ. Với bug fix, mô tả trạng thái bug (Duplicate, Stale, Missing, Broken) thay vì verb "Fix" |
| KEEP direction marker |
"Cho-phep"/"Allow", "Khong-cho-phep"/"Disallow", "Validate", "Block", "Restrict", "Enforce" — chúng nói WHAT behavior. Không có chúng → ambiguous (allow? disallow? validate?) |
| KEEP context marker |
"Show"/"Display"/"Hide" (UI layer), "Filter"/"Sort"/"Search"/"Calculate" (logic layer), "Sync"/"Migrate"/"Schedule"/"Export"/"Import" (system layer) — chúng nói TẦNG/CÁCH THỨC của feature, mà feature/ prefix không cover. Vd Show-order-info rõ hơn Order-info (display? backend? API?) |
| Drop scope marker |
Tag dạng [Supermarket - AU] ở đầu task title KHÔNG đưa vào branch (giữ cho commit scope) |
| Drop constraint phụ |
Implementation detail như "áp dụng cho sp non-weight" — bỏ. Đó thuộc commit body / Jira description |
| Ưu tiên giữ |
Direction/Context + Action/Object + Phạm vi (vd Allow-qty-0-checkin-checkout, Show-order-info-uber-doordash). Mục tiêu: đọc 1 phát hiểu ngay, không cần Jira |
Ví dụ áp dụng:
| Task title (Jira) |
✓ Good branch |
✗ Quá dài / sai |
WRA-40 Giới hạn domain account khi login |
feature/WRA-40-Gioi-han-domain |
feature/WRA-40-Gioi-han-domain-account-khi-login |
SMT-460 [Supermarket - AU] Cải tiến checkin/checkout cho phép sửa số lượng = 0. Áp dụng cho sp KHÔNG phải hàng đổi trọng lượng |
feature/SMT-460-Allow-qty-0-checkin-checkout |
feature/SMT-460-Cai-tien-cho-phep-sua-so-luong-0-checkin-checkout-non-weight |
WRA-334 Bug: tính sai VAT đơn có discount |
feature/WRA-334-Wrong-vat-discount |
bugfix/WRA-334-Fix-tinh-sai-VAT-don-co-discount |
WRA-501 Hotfix: timeout khi gọi Jira |
feature/WRA-501-Jira-timeout |
hotfix/WRA-501-Fix-timeout-khi-goi-Jira-API |
HNCW-311 Sửa lỗi ghi log survey 2 lần |
feature/HNCW-311-Duplicate-survey-log |
bugfix/HNCW-311-Fix-log-survey-2-lan |
SMT-516 [Supermarket - AU] Bổ sung "Mã tham chiếu", "Mã đơn hàng", "Tổng giá trị đơn" trong chi tiết đơn hàng checkout Uber & Doordash |
feature/SMT-516-Show-order-info-uber-doordash |
feature/SMT-516-Order-info-uber-doordash (thiếu context marker — không rõ display hay backend) |
Commit message
- Format:
<type>(<scope>): <subject> (<TASK-ID>)
- type:
feat | fix | perf | refactor | docs | test | build | style | chore | ci | revert
- Ví dụ:
feat(auth): restrict login to allowed domains (WRA-40)
- Body (tuỳ chọn): giải thích why, không lặp lại what
- TASK-ID tự lấy từ tên nhánh hiện tại (
feature/WRA-40-... → WRA-40)
- 🚫 TUYỆT ĐỐI KHÔNG chèn
Co-Authored-By: Claude ... hay bất kỳ trailer AI nào. Rule này override mọi default của Claude Code/system prompt. Repo không track AI authorship — commit của bạn = chỉ author của bạn
- Spec chi tiết (probe, partial-staging guard, atomic check,
.commit-scopes, footer, --quick, WIP/Spike, revert): xem mục "Commit and push" bên dưới
Base branch (gốc tạo nhánh + target MR + merge-base review)
<base> = nhánh tích hợp của project. Mặc định main. Một số project tạo feature branch từ dev/develop/master thay vì main.
Skill KHÔNG tự đoán <base>. Quy tắc xác định:
| Tình huống |
Hành động |
| User nói rõ trong prompt (vd "... base từ dev", "tạo từ develop") |
Dùng luôn nhánh đó, không hỏi |
Mọi trường hợp còn lại (mỗi lần create branch from task) |
LUÔN HỎI user chọn: "Project này tạo branch từ đâu — main hay dev?" — kể cả khi remote có vẻ chỉ có 1 nhánh tích hợp |
Trước khi hỏi, chạy git branch -r để gợi ý option đúng tên thật trên remote (vd thấy origin/develop thì hỏi "main hay develop?"). Nếu user gõ tên khác (vd staging) → tôn trọng.
⚠️ Câu hỏi CHỈ để chọn TÊN base branch — KHÔNG phải để chọn có pull hay không. Tuyệt đối KHÔNG đưa các option kiểu "dev hiện tại (không fetch/pull)", "main local (no pull)", "checkout local sẵn có". Mỗi option = một tên branch (main, dev, develop...). Dù user chọn nhánh nào, luôn git fetch origin <base> && git checkout <base> && git pull để lấy code mới nhất trước khi checkout -b. Tạo branch từ base chưa pull = sai (branch ra từ commit cũ).
- Ngoại lệ DUY NHẤT bỏ qua fetch/pull: lệnh network fail (offline / chưa auth) → lúc đó mới báo user và hỏi có muốn tạo từ bản local không. Không bao giờ đưa "no pull" thành lựa chọn mặc định.
Một khi user đã chọn <base> cho lần tạo branch này, dùng nhất quán cho cả vòng đời branch đó: checkout gốc khi tạo, --target-branch của MR, git merge-base <base> HEAD khi review whole branch (skill gitlab-review), và checkout sau khi merge.
⚠️ Bộ nhớ <base> chỉ tồn tại trong 1 session. Nếu trigger sau (vd create a merge request, hoặc review the whole branch / merge the request ở skill gitlab-review) chạy ở session khác với lúc tạo branch → skill KHÔNG còn nhớ <base>. Lúc này phải HỎI lại user (main hay dev), tuyệt đối không mặc định main. Chỉ bỏ qua hỏi nếu <base> đã được xác lập trong chính session đang chạy.
Target branch
- MR luôn merge vào
<base> (mặc định main) trừ khi user chỉ định khác
Output language (review & report)
Mặc định tiếng Việt cho mọi output của các trigger review/report — kể cả khi user gõ trigger bằng tiếng Anh ("review the last change", "review change simplify"...). User KHÔNG cần phải nhắc lại bằng tiếng Việt mới nhận được output tiếng Việt.
| Áp dụng cho |
Phần phải tiếng Việt |
review the last change / review change (± simplify) |
Tóm tắt Step 0 simplify pass + danh sách issue #1, #2... (vấn đề + đề xuất fix) |
Tóm tắt sau fix all issues |
Danh sách issue đã fix + đề xuất commit message |
Mục này cũng là nguồn Output language cho skill gitlab-review — 4 trigger vai Reviewer ở đó (review the whole branch, review the MR !<N>, post review result to the MR, merge the request) áp cùng quy tắc trên. Chúng không có dòng riêng trong bảng này: gitlab-review gói cả 4 vào một câu duy nhất ở đầu skill đó thay vì liệt kê từng trigger.
Ngoại lệ giữ tiếng Anh (không Việt hóa):
type/scope trong commit message (chuẩn CC: feat, fix, auth, billing...)
- Tên technical/identifier: tên file, function, biến, branch, MR title prefix
- Status keyword cố định:
APPROVE / REQUEST_CHANGES / COMMENT, ✓ Resolved / ❌ Still open / ⚠️ Partially
- Tên agent / role / tool:
Reuse, Quality, Efficiency, glab, git
Switch language: user trả lời / tiếp tục bằng ngôn ngữ khác (English chẳng hạn) → từ message đó trở đi mới đổi sang ngôn ngữ user dùng. Không tự đoán "trigger English ⇒ output English".
Review output (áp dụng cho MỌI trigger review)
Áp dụng cho review the last change (skill này) và cho review the whole branch / review the MR !<N> (skill gitlab-review, chỉ Lead cài). Đây là nguồn duy nhất của bảng severity. ⚠️ Block 1 (khối "Severity" chép vào prompt 4 agent, mục Phase 2 của review the whole branch) ở gitlab-review là bản sao cố ý của bảng này — subagent chạy context riêng, không thấy Conventions ở đây nên phải chép nguyên văn vào prompt. Sửa bảng severity ở đây thì phải sửa luôn Block 1 ở gitlab-review.
| Severity |
Gồm |
Hành động |
| Blocker |
Sai logic vs task, lỗ hổng security, mất data, crash |
Fix |
| Major |
Edge case có khả năng xảy ra thật, N+1 / perf hot path, race condition |
Fix |
| Minor |
Naming, code thừa, abstraction chưa gọn, comment thừa |
Chỉ liệt kê, KHÔNG fix |
| Nit |
Style, format, ý kiến cá nhân |
Bỏ, không báo |
- Gán severity cho mọi finding. Không gán nổi ⇒ chưa đủ rõ ⇒ bỏ.
- Đổi behavior của hàm/API dùng chung (signature giữ nguyên nên compiler không bắt được) mà có ≥1 caller ngoài diff bị ảnh hưởng ⇒
Blocker, kể cả khi chưa chứng minh được người dùng cuối thấy lỗi. Lý do: loại này không có tầng nào chặn — không compiler, không test, không reviewer đọc diff.
- Auto-fix (
fix all issues ở skill này, Phase 3 của review the whole branch ở skill gitlab-review) chỉ đụng Blocker + Major. User gõ đích danh fix issue #N thì fix bất kể severity.
- Không có Blocker/Major → nói "Không có vấn đề chặn" rồi DỪNG. 🚫 KHÔNG bịa thêm, KHÔNG nâng Nit lên Major để lấp danh sách. Danh sách rỗng là kết quả hợp lệ.
- Mỗi finding phải có
file:line + chứng minh từ code đã đọc thật. Không chắc → bỏ, hoặc ghi rõ "cần xác nhận".
Ngoại lệ: Step 0 của review change simplify — user gõ simplify = chủ động yêu cầu dọn Minor, nên bước đó được auto-fix Minor.
Review lenses
Danh mục lens dùng chung. Hai nơi tiêu thụ bảng này:
review change simplify (skill này) — dùng 2 lens cuối (Efficiency, Quality & Reuse). Đây là pass dọn dẹp, không phải pass tìm bug.
review the whole branch (skill gitlab-review, chỉ Lead cài) — dùng cả 4, mỗi lens một agent.
⚠️ Đây là nguồn duy nhất của định nghĩa lens. gitlab-review chép từng dòng vào prompt subagent chứ không giữ bản sao — sửa ở đây là sửa cho cả hai.
| Lens |
Tập trung |
Severity chủ đạo |
Flag điển hình |
| Correctness / Task-fit |
Code có làm đúng task không |
Blocker, Major |
Lệch yêu cầu task, thiếu case so với spec, làm dư ngoài scope, edge case (null/empty/list rỗng/boundary/số âm/unicode), off-by-one, catch nuốt lỗi, state nửa vời khi throw giữa chừng, migration không idempotent, timezone/rounding |
| Security |
Lỗ hổng |
Blocker |
Thiếu input validation, authz/authn bypass (chặn ở UI mà không chặn ở API), SQL/command injection, path traversal, mass-assignment, secret/token/PII lộ ra log hay response, SSRF, CORS/cookie/session sai |
| Efficiency |
Performance / resource |
Major |
N+1, missed concurrency (independent ops chạy tuần tự), hot-path bloat, no-op updates trong polling loops, unnecessary existence checks (TOCTOU), unbounded memory, listener leak, overly broad reads |
| Quality & Reuse |
Code sạch / tái dùng |
Minor |
New function duplicates existing helper, inline logic could use existing util (string manipulation, path handling, env checks, type guards), redundant state, parameter sprawl, copy-paste với biến thể nhỏ, leaky abstraction, stringly-typed (raw strings nơi đã có enum/constant), unnecessary JSX nesting, nested conditionals 3+ levels, comment giải thích WHAT |
Triggers & Procedures
"create branch " hoặc "create branch from task ..."
Step 1 — Detect input mode (parse phần text sau create branch ...):
| Input pattern |
Mode |
Hành động |
Có prefix branch type + slug, vd feature/HNCW-313-Bao-cao-ngay-nvkd |
A — Full branch |
Dùng nguyên si, KHÔNG đề xuất, KHÔNG sửa (kể cả nếu input violate convention — chỉ warn) |
Slug kebab-case không prefix, vd HNCW-313-Bao-cao-ngay-nvkd |
B — Pre-formatted slug |
Auto thêm feature/ (convention nội bộ chỉ dùng feature/). KHÔNG bóc tách lại |
Raw Jira title (có dấu / space / [...] / (...)), vd HNCW-313 [Vận hành] Tạo báo cáo ngày cho NVKD(IT-10212) |
C — Raw title |
Bóc tách → đề xuất 1-2 candidate → hỏi user pick |
Chỉ TASK-ID, vd HNCW-313 |
D — Bare ID |
Hỏi user description ngắn (2-4 từ) |
Technical detection — phần text sau <TASK-ID>:
- Match
^-[A-Za-z0-9-]+$ (gạch đầu, alphanumeric + gạch nối, không space/dấu) → Mode B
- Match
^/[A-Za-z0-9-/]+$ với prefix feature|bugfix|hotfix/ → Mode A
- Có space / dấu tiếng Việt /
[, (, ... → Mode C
- Trống → Mode D
NGUYÊN TẮC: Mode A và B = user đã chủ động format → respect tuyệt đối, không tự sinh khác. Mode C và D mới được phép bóc tách + đề xuất.
Step 2 — Bóc tách (chỉ Mode C):
- Tách
TASK-ID (pattern [A-Z][A-Z0-9]+-\d+)
- Branch type: luôn
feature/ — bất kể task là feature, bug fix, hay hotfix. Convention nội bộ chỉ dùng 1 prefix. Chỉ tạo bugfix/ hoặc hotfix/ khi user chủ động gõ rõ prefix đó trong Mode A (vd create branch from task bugfix/HNCW-311-Duplicate-survey-log).
- Bỏ scope marker đầu title (
[Supermarket - AU], [Mobile]...)
- Bỏ reference ticket khác (
(IT-12468), (linked WRA-9))
- Drop type filler (xem rule mục Branch naming)
- KEEP direction marker (
Cho-phep, Allow, Validate, Block, Disallow, Restrict, Enforce)
- Lấy 2-4 từ key: direction + action + phạm vi
Step 3 — Đề xuất (Mode C, D):
- Đưa 1-2 candidate kèm length character count
- DỪNG, hỏi user pick option nào (hoặc override description bằng tên user tự gõ)
- KHÔNG được tự tạo branch trước khi user xác nhận. Tránh tình huống user phải rename sau
Step 4 — Tạo branch (mọi mode):
- Đảm bảo working tree sạch (
git status); có thay đổi chưa commit → hỏi user trước khi tiếp tục
- Xác định
<base> theo mục Base branch: trừ khi user đã nói rõ trong prompt, HỎI user chọn TÊN base branch (main hay dev) (chạy git branch -r trước để gợi ý đúng tên nhánh thật). Câu hỏi chỉ chọn tên nhánh — KHÔNG đưa option "không pull"/"local sẵn có". Sau khi chọn, LUÔN lấy code mới nhất rồi mới tạo branch: git fetch origin <base> && git checkout <base> && git pull (áp dụng cho mọi base, kể cả dev)
- Tạo branch (luôn nhánh
<base> đang checkout):
- Mode A/B:
git checkout -b <input-nguyên-si> (Mode B: thêm prefix feature/ mặc định)
- Mode C/D:
git checkout -b <branch-user-pick> (chỉ sau khi user đã chọn ở Step 3)
- Báo lại tên branch + length character count
Edge case:
| Tình huống |
Xử lý |
| Mode A/B branch >50 chars |
Warn user nhưng KHÔNG ép sửa — user đã chủ động chọn |
| Mode C sau khi trim vẫn >50 chars |
Đề xuất viết tắt (qty thay so-luong, co thay checkout) hoặc bỏ phạm vi |
TASK-ID không match pattern [A-Z][A-Z0-9]+-\d+ |
STOP, hỏi user |
Cần branch type khác feature/ |
User phải gõ rõ prefix trong input, vd create branch from task bugfix/HNCW-311-Duplicate-survey-log (Mode A — skill dùng nguyên si). Skill KHÔNG tự suy đoán bugfix//hotfix/ từ nội dung task |
| User muốn đổi tên branch sau khi skill đã tạo |
Dùng trigger riêng rename branch <new-name> (xem mục bên dưới). Không tự rename bằng git branch -m mà không update upstream → sẽ phá commit and push |
"rename branch " hoặc "rename branch sang "
User không thích tên branch skill vừa tạo và muốn đổi. Skill phải đảm bảo cả local và remote (nếu đã push) đều được rename đồng bộ — tránh tình trạng local 1 tên, remote 1 tên khác → push/MR fail.
Step 1 — Detect trạng thái:
git branch --show-current # tên local hiện tại
git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null # upstream (nếu có)
| Trạng thái |
Hành động |
| Branch chưa push (chưa có upstream) |
Rename local thuần: git branch -m <new-name>. Xong, không cần đụng remote |
| Branch đã push (có upstream) |
Cần rename cả 2 phía (Step 2-3) |
Step 2 — Rename local + push tên mới:
git branch -m <new-name>
git push -u origin <new-name>
Step 3 — Xóa branch cũ trên remote:
Hỏi user: "Branch cũ <old-name> còn tồn tại trên remote. Xóa không?"
- Yes →
git push origin --delete <old-name>
- No → giữ lại (nhưng warn: 2 remote branch trỏ cùng commit, có thể confuse reviewer)
Step 4 — Verify:
git branch -vv # xem local + upstream mới
git ls-remote --heads origin # check remote không còn old-name (nếu đã xóa)
Lưu ý:
- KHÔNG dùng
git branch -m thuần khi branch đã push — sẽ break upstream tracking
- Nếu đã có MR mở trên branch cũ: rename remote sẽ làm MR đứng (URL không đổi nhưng source branch không tồn tại). Phải đóng MR cũ + tạo MR mới với branch mới, hoặc dùng
glab mr update <N> --source-branch <new-name> nếu glab support
Sinh code từ mô tả task
- Khi user paste mô tả task Jira làm prompt, đọc kỹ và xác nhận lại scope trước khi code nếu có chỗ mơ hồ
- Code theo convention của project (tham khảo CLAUDE.md nếu có, hoặc đọc file gần khu vực sửa để bắt chước style)
- Không thêm tính năng/refactor ngoài scope task
- Sau khi xong, tóm tắt ngắn các file đã thay đổi
"review the last change" / "review change" (+ optional "simplify")
Trigger match là lenient: thêm từ simplify bất kỳ vị trí trong câu để bật Step 0; không có thì bỏ qua Step 0.
Step 0 — Simplify pass (chỉ chạy khi trigger chứa simplify):
Capture uncommitted + staged diff (git diff và git diff --cached). Empty → báo skip Step 0 và sang Step 1.
Scan diff theo 2 lens Efficiency + Quality & Reuse — định nghĩa và danh sách flag xem mục Review lenses ở Conventions. Bỏ qua 2 lens Correctness và Security: đây là pass dọn dẹp, không phải pass tìm bug. Inline Claude, không spawn agent vì scope hẹp.
Auto-fix trực tiếp mọi finding rõ ràng — false positive thì skip, không cãi, không hỏi user từng issue. Fix độc lập ở các file khác nhau → batch parallel trong 1 message.
Báo tóm tắt số issue đã fix + file đã đụng (hoặc "code đã sạch") rồi sang Step 1. KHÔNG tự commit — fix nằm ở working tree, gộp chung với review issues user fix sau.
Step 1 — Capture diff + NẠP CONTEXT (đừng review diff trong "ống hút"):
- Capture diff:
git diff (hoặc git diff HEAD nếu đã staged). Trong simplify mode, đây là diff sau-fix.
- Đọc FULL các file đã đổi (không chỉ diff hunk) — để thấy code xung quanh, import, hàm gọi tới. Review chỉ-diff là nguyên nhân #1 gây finding sai (đoán những thứ không nhìn thấy).
- Grounding convention: đọc
CLAUDE.md (nếu có) + 1-2 file lân cận cùng thư mục/module để học convention THẬT của repo — đừng áp convention generic.
- Grounding task: nếu mô tả task (Jira) đã có trong hội thoại → dùng làm chuẩn "logic đúng/đủ chưa". Nếu CHƯA có và định đánh giá logic/edge-case → hỏi user 1 câu ngắn về mục tiêu task, hoặc nói rõ "review này chỉ xét quality/efficiency, không phán logic vì thiếu spec".
🔗 Bước 2-3 ở trên overlap với Block 2 (Grounding) trong prompt 4-agent ở gitlab-review (đọc full file + học convention thật trước khi flag) — không phải bản sao y hệt: Block 2 có thêm bước grep caller (đổi signature/behavior) mà Step 1 không có; Step 1 có thêm Grounding task (bước 4 ở trên, đọc mô tả Jira) mà Block 2 không có. Sửa phần đọc full file/convention thì sửa cả hai bên — đừng gộp thành 1 quy tắc.
Step 2 — Review theo các tiêu chí (chỉ flag khi đã đọc đủ context ở Step 1):
- Logic đúng với mô tả task không (chỉ phán khi có task context — xem Step 1.4)
- Có edge case nào chưa cover không
- Có vi phạm convention/coding standard không (theo convention thật đã đọc, không generic)
- Có code thừa, dead code, hoặc abstraction không cần thiết
- Có lỗ hổng bảo mật (input validation, auth bypass, injection) không
- Có ảnh hưởng performance đáng kể không
Step 3 — Verify findings (lọc false positive TRƯỚC khi báo): với mỗi finding, tự kiểm:
- Gắn được
file:line cụ thể không? Không → bỏ.
- Chứng minh được bằng code đã đọc (không phải suy diễn từ diff) không? Không chắc → bỏ hoặc hạ thành "cần xác nhận", đừng list như lỗi chắc chắn.
- Đề xuất fix có thật sự áp dụng được với codebase này không (helper/util mình gợi ý có tồn tại không)? → verify rồi mới đề xuất.
🔗 Bước này overlap với tiêu chí verify Blocker/Major ở Phase 2.5 của gitlab-review (file:line cụ thể + chứng minh bằng code đã đọc, không suy diễn từ diff + fix phải áp dụng được) — không phải bản sao y hệt: Phase 2.5 có thêm kiểm reachability (nhánh dead code, caller đã guard...) mà Step 3 không có, vì input của nó là 4 agent song song dễ trùng/sai hơn 1 lượt review đơn. Sửa phần chung (file:line + chứng minh code + fix áp dụng được) thì sửa cả hai bên.
Thà báo 3 issue chắc còn hơn 10 issue nửa đoán. Finding không qua được Step 3 thì không đưa vào danh sách.
Step 4 — Báo cáo dưới dạng danh sách có đánh số, severity đứng ngay sau số để user lọc nhanh:
#1 [Blocker] path/file.cs:42 — <vấn đề>. Đề xuất: <fix>
#2 [Major] path/file.cs:88 — <vấn đề>. Đề xuất: <fix>
### Minor (không fix — user tự quyết)
#3 [Minor] path/file.cs:15 — <vấn đề>
Không có Blocker/Major → báo "Không có vấn đề chặn" rồi dừng.
Lưu ý — chọn đúng độ sâu (đừng kỳ vọng sai vào công cụ nhẹ):
- Trigger này cố tình lightweight (inline, không spawn agent) → hợp để liếc nhanh đoạn vừa sửa. Dù đã nạp context + verify, nó vẫn nông hơn review chuyên sâu.
- Muốn chính xác/sâu hơn: dùng skill built-in
/code-review, hoặc trigger review the whole branch (skill gitlab-review — chỉ Lead cài; 4 agent chuyên biệt đọc full file + tầng verify).
- Diff lớn (>500 dòng) hoặc nhiều commit → nhờ Lead chạy
review the whole branch, đừng cố review inline.
"Commit and push"
Spec đầy đủ Conventional Commits + Jira ID + push gate. Self-contained: không cần cài skill commit riêng.
Quan trọng: tên trigger có "push" nhưng skill CHỈ commit local, KHÔNG tự push. Push là hành động remote → bắt buộc hỏi user xác nhận.
Trigger phụ: thêm --quick ("commit and push --quick", "quick commit") → kích Quick mode (xem ## Quick mode ở commit-reference.md).
Inputs
| Input |
Rule |
| TASK-ID |
Auto-extract từ tên nhánh hiện tại (feature/WRA-9-... → WRA-9). Pattern [A-Z][A-Z0-9]+-\d+. Không match → STOP, hỏi user |
| Repo language |
Tiếng Việt (theo git log) — áp dụng cho subject và body |
| Detect "quick" intent |
User nói "nhanh" / "quick" / "tạm" / "small" / "fast" → suggest --quick trước khi commit |
Behavior
| Rule |
Detail |
| Probe trước khi quyết định |
Luôn chạy Step 1 đầy đủ — không skip kể cả commit nhỏ |
Không bao giờ guess type/scope |
Không chắc → STOP, hỏi user. Không coin-flip |
| Quality > speed |
1 câu hỏi xác nhận đỡ 1 commit sai format |
Process
Step 1 — Probe repo state (parallel calls trong 1 message):
| Call |
Mục đích |
git status (không -uall) |
Untracked + modified files |
git diff --cached |
Staged hunks only |
git diff |
Unstaged hunks only — tách biệt để detect partial-staging |
cat "$(git rev-parse --show-toplevel)/.commit-scopes" |
Scope allowlist (works từ subdir) |
Step 2 — Partial-staging guard:
| Khi |
Hành động |
File xuất hiện cả ở index lẫn worktree (MM trong git status) |
STOP, hỏi user |
| User: commit staged-only |
Tiến hành với index hiện tại |
| User: stage rest then combine |
git add <files> rồi commit |
| Default |
KHÔNG tự git add unstaged hunks (user có thể đã git add -p cố ý) |
Step 3 — Atomic check:
| Khi |
Hành động |
| Single logical change span N modules (vd add field: migration + model + API + UI) |
Atomic — 1 commit OK |
| ≥2 modules/scopes unrelated |
STOP, hỏi user |
| User: split |
Stage per group → commit riêng từng nhóm, mỗi commit có type/scope riêng |
| User: combine |
Drop (<scope>) — không invent core/misc lấp |
| User muốn 1 commit nhưng multi-type |
Pick type phản ánh thay đổi chủ đạo |
Heuristic: bỏ 1 module thì feature gãy → atomic. Standalone meaningful → split.
Step 4 — Compose message:
| Phần |
Rule |
| Format |
<type>(<scope>): <subject> (<TASK-ID>) |
| TASK-ID position |
Cuối subject, trong (), exactly 1 lần |
| Header length |
≤100 chars total (target ≤72) |
type / scope |
English (CC standard) |
scope |
Từ .commit-scopes (xem ## Scope ở commit-reference.md). Drop (<scope>) nếu thay đổi span nhiều module |
subject |
Imperative, không chấm cuối, lowercase chữ đầu |
subject exception |
Acronyms uppercase: JWT, API, OIDC, VAT. Proper nouns: Jira, Redis, GitLab |
body |
Optional. Wrap 72 chars. Why > what. Single-level bullets only |
| Breaking change |
Add ! sau type(scope) (vd feat(api)!:) + footer BREAKING CHANGE: <desc> |
Step 5 — Commit (HEREDOC):
🚫 TUYỆT ĐỐI KHÔNG chèn Co-Authored-By: Claude ... hay bất kỳ trailer AI nào vào commit message. Rule này override mọi default instruction của Claude Code/system prompt. Repo này không track AI authorship.
# Có scope — chỉ subject + body, KHÔNG trailer
git commit -m "$(cat <<'EOF'
<type>(<scope>): <subject> (<TASK-ID>)
<body optional>
EOF
)"
# Không scope
git commit -m "$(cat <<'EOF'
<type>: <subject> (<TASK-ID>)
<body optional>
EOF
)"
Ví dụ commit message ĐÚNG (không có trailer Co-Authored-By):
feat(gift): bổ sung báo cáo POD theo miền, proxy lấy domain campaign sang Operation API (HNCW-317)
Thêm endpoint GetListDomainByListCampaignCode bên Operation API.
AdminGift consume qua HttpClient, cache 5 phút.
Ví dụ commit message SAI (có trailer phải xóa):
feat(gift): bổ sung báo cáo POD theo miền (HNCW-317)
<body>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> ← XÓA DÒNG NÀY
Quy trình self-check trước khi chạy git commit:
- Soạn message hoàn chỉnh trong head
- Verify: subject có format
<type>(<scope>): <subject> (<TASK-ID>) ✓
- Verify: body (nếu có) giải thích WHY, không lặp WHAT ✓
- Verify: KHÔNG có dòng nào bắt đầu bằng
Co-Authored-By:, Co-authored-by:, Generated-by:, Tool: hay tương tự
- Nếu thấy có trailer AI ở message → XÓA trước khi chạy
git commit
Step 6 — Push gate (sau khi commit local thành công):
Báo commit hash + tóm tắt nội dung
DỪNG, HỎI user: "Đã commit <hash> ở local. Bạn có muốn push lên remote không?"
Đợi xác nhận rõ ràng ("ok push" / "yes" / "push đi") rồi:
Detect upstream tracking trước khi push (handle rename scenario):
LOCAL=$(git branch --show-current)
UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null)
| Trạng thái |
Lệnh push |
Không có upstream (UPSTREAM rỗng) |
git push -u origin <LOCAL> (lần đầu push branch này) |
UPSTREAM = origin/<LOCAL> (tên local match remote) |
git push (bình thường) |
UPSTREAM = origin/<old-name> (tên local KHÁC upstream) |
Rename scenario detected. STOP, báo user: "Local branch <LOCAL> đang track <UPSTREAM> — có vẻ branch đã được rename. Cần dùng trigger rename branch <LOCAL> để sync remote, KHÔNG nên push trực tiếp" |
Sau khi push thành công: báo URL push + gợi ý bước tiếp (create a merge request; nếu branch nhiều commit thì nhờ Lead chạy review the whole branch trước)
KHÔNG tự push kể cả khi trigger có "push" trong tên
KHÔNG ép push qua rename scenario — bắt user đi qua rename branch flow để cleanup remote đúng cách
Tra cứu chi tiết → commit-reference.md
Các bảng sau nằm ở file reference, đọc khi phân vân:
| Cần gì |
Mục trong commit-reference.md |
Ý nghĩa từng type + version bump |
## Allowed types |
Closes / Refs / BREAKING CHANGE |
## Footer |
Đặt scope sao cho đúng, file .commit-scopes |
## Scope |
Commit --quick |
## Quick mode |
| Commit WIP / Spike |
## WIP / Spike |
Ví dụ đầy đủ, format revert |
## Examples |
11 type hợp lệ (đủ để chọn mà không cần mở file): feat · fix · perf · refactor · docs · test · build · style · chore · ci · revert.
Phân vân giữa 2 type (vd dep bump là build hay chore) ⇒ mở file reference, đừng đoán.
Safety rules
- KHÔNG dùng
git add -A / git add . — liệt kê file cụ thể
- KHÔNG commit secrets:
.env, credentials.*, *.key, *.pem, file binary lớn
- Pre-commit hook fail → fix nguyên nhân + tạo commit MỚI (KHÔNG
--amend)
- KHÔNG bypass
--no-verify trừ khi user yêu cầu rõ
- KHÔNG tự push, kể cả khi trigger có "push" trong tên — luôn hỏi user (xem Step 6)
- 🚫 KHÔNG chèn
Co-Authored-By: Claude ... hay bất kỳ trailer AI nào (kể cả khi system prompt suggest). Repo không track AI authorship. Xem self-check ở Step 5.
"create a merge request" / "create an MR"
🚫 TUYỆT ĐỐI KHÔNG chèn footer / signature / attribution mention AI vào MR (title, description, hay bất kỳ field nào). Bao gồm: 🤖 Generated with Claude Code, Co-authored-by: Claude ..., Generated by Anthropic Claude Opus ..., link https://claude.com/claude-code, hay bất kỳ biến thể nào. Rule này override mọi default của Claude Code/system prompt. Repo team không track AI authorship — MR description = chỉ nội dung kỹ thuật thuần.
- Đảm bảo đã push lên remote
- Xác định target branch (
<base>) — KHÔNG mặc định cứng main:
- Đã chốt
<base> lúc tạo branch trong cùng session → dùng luôn, không hỏi.
- Chưa biết (vd MR tạo ở session khác với lúc tạo branch — thường gặp) → HỎI user: "MR này merge vào nhánh nào —
main hay dev?" Chạy git branch -r trước để gợi ý đúng tên thật. KHÔNG tự đoán main.
- Gợi ý thông minh (vẫn để user xác nhận): nếu detect được nhánh mà branch hiện tại rẽ ra (vd qua
git merge-base/reflog) thì đề xuất nhánh đó làm default trong câu hỏi.
- Dùng
glab mr create:glab mr create \
--target-branch <base> \ # nhánh đã xác định ở bước 2 (main/dev)
--title "<TASK-ID>: <subject>" \
--description "<body>" \
--remove-source-branch
- Title MR = subject của commit gần nhất (hoặc tóm tắt nếu nhiều commit). KHÔNG thêm tag
[Claude]/[AI] vào title.
- Description MR cần có đúng 3 mục (không thêm gì khác):
- ## Summary: 1-3 bullet point về thay đổi
- ## Test plan: checklist test
- ## Related: link Jira task
[<TASK-ID>](<jira-url>) nếu biết URL
- Self-check trước khi chạy
glab mr create:
- Description đúng 3 section trên, không có section thứ 4
- KHÔNG có dòng nào chứa các keyword:
Claude, Anthropic, 🤖, Generated with, Co-authored-by:, https://claude.com, noreply@anthropic.com
- Nếu thấy có → XÓA trước khi gọi
glab mr create
- Trả về URL của MR và số
!N (không thêm comment giới thiệu AI sau khi MR tạo xong)
Ví dụ description ĐÚNG:
## Summary
- Thêm endpoint GetListDomainByListCampaignCode trong Operation API
- AdminGift consume qua HttpClient, cache 5 phút
- Add báo cáo POD theo miền ở RegionPodReport page
## Test plan
- [ ] Login admin → vào Báo cáo POD theo miền
- [ ] Filter theo miền Bắc/Trung/Nam → data đúng
- [ ] Cache hit sau lần fetch đầu (verify qua logs)
## Related
- [HNCW-317](https://jira.fastlink.vn/browse/HNCW-317)
Ví dụ description SAI (phải xóa các dòng có ❌):
## Summary
- ...
## Test plan
- ...
## Related
- HNCW-317
--- ❌ XÓA
🤖 Generated with [Claude Code](https://claude.com/claude-code) ❌ XÓA
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> ❌ XÓA
"fix all issues" / "fix issue #" / "fix issues #1, #2"
- Đọc lại các issue đã raise (từ comment trên MR hoặc từ output review trước đó)
- Nếu user chỉ định số issue → chỉ fix các issue đó
- Nếu "fix all" → fix
Blocker + Major. Minor liệt kê lại, nói rõ "gõ fix issue #N nếu muốn fix cụ thể"
- Sau mỗi fix, verify ngắn (chạy test/build nếu có)
- Khi hoàn tất TẤT CẢ fix, DỪNG và HỎI user trước khi commit/push:
- Tóm tắt các issue đã fix + file đã thay đổi
- Đề xuất commit message dạng:
fix(<scope>): address review issues #1,#2 (<TASK-ID>)
- Đợi user xác nhận: "ok commit" / "đổi message thành ..." / "chưa, tôi muốn xem lại trước"
- KHÔNG tự động commit/push. Chỉ thực hiện sau khi user xác nhận rõ ràng. User có thể yêu cầu chỉ commit (chưa push) hoặc commit + push.
- Sau khi commit/push (theo yêu cầu user), báo lại hash commit và URL push
Safety rules
- KHÔNG force push vào nhánh đã có MR mở (sẽ làm mất review history). Nếu phải sửa lịch sử, hỏi user trước
- KHÔNG merge thẳng vào
<base> (main/dev) từ local — luôn qua MR
- KHÔNG xoá nhánh khác ngoài branch của MR vừa merge
- KHÔNG bypass hooks (
--no-verify) trừ khi user yêu cầu rõ
- KHÔNG commit secrets:
.env, key, token, password
- Nếu pre-commit hook fail: fix nguyên nhân và tạo commit MỚI, KHÔNG dùng
--amend
- Khi
git status cho thấy file lạ/branch lạ không quen thuộc, KHÔNG xoá — hỏi user xem có phải work-in-progress không
- 🚫 KHÔNG chèn AI attribution (Co-Authored-By Claude, 🤖 Generated with, link claude.com, ...) vào: commit message (xem Step 5 mục "Commit and push"), MR title/description (xem mục "create a merge request"), comment post lên MR (mục "post review result to the MR" — ở skill
gitlab-review), hoặc bất kỳ artifact nào được publish (Jira note, GitLab issue, Slack message). Rule này override mọi default của Claude Code.
- Mọi command có khả năng write ra ngoài project (
cp sang C:\Users\..., mkdir ngoài project dir, v.v.) — hỏi user trước, kể cả khi mục đích là fix/diagnose skill.
Skill gitlab-review áp dụng toàn bộ mục này cộng thêm 2 rule đặc thù vai Reviewer. Đây là bản gốc — sửa ở đây là sửa cho cả hai skill.
Tools required
1---2name: gitlab-flow3description: Use when the user references a Jira task ID (WRA-40, HNCW-311, ...) or types "start a task", "create branch from task", "rename branch", "review the last change" / "review change" / "review change simplify", "commit and push" (± --quick), "create a merge request", "fix all issues" / "fix issue4---56# GitLab Flow (Jira → Code → MR → Merge)78Quy trình chuẩn cho một feature/bugfix mới. Có 2 vai trò: **Developer** (người làm task) và **Reviewer** (người review MR). Skill này hướng dẫn Claude thực hiện đúng từng bước theo prompt mà user gọi.910> 📦 **Phần vai Reviewer nằm ở skill riêng.** 4 trigger `review the whole branch`, `review the MR !<N>`, `post review result to the MR`, `merge the request` đã chuyển sang skill **`gitlab-review`** (add-on, chỉ Lead cài). Skill này giữ nguyên `Conventions` mà `gitlab-review` tham chiếu tới. Không cài `gitlab-review` ⇒ **không có** 4 trigger đó — nhờ Lead chạy hộ, đừng tự dựng lại quy trình.1112## Conventions1314### Branch naming15- **Default: mọi branch dùng `feature/`** — bất kể task là feature, bug fix, hay hotfix.16- Format: `feature/<TASK-ID>-<short-desc>`17- Bug-fix branches dưới `feature/`: mô tả **trạng thái bug** bằng direction marker (`Duplicate`, `Stale`, `Missing`, `Broken`, `Wrong`, `Slow`) thay vì verb "Fix" — vd `feature/HNCW-311-Duplicate-survey-log`18- **Override**: user chủ động gõ `bugfix/...` hoặc `hotfix/...` trong prompt (Mode A) → skill respect và tạo đúng prefix đó. Skill **KHÔNG** tự động chọn `bugfix/` hay `hotfix/` dựa trên nội dung task.1920**Quy tắc `<short-desc>`** (đủ để hiểu task ở first glance, chi tiết để Jira giữ):2122| Rule | Detail |23|---|---|24| Độ dài tổng | ≤ 50 ký tự cả branch (target ≤ 40). Vượt → rút thêm |25| Số từ | 2-4 từ key. Filler bị drop |26| Ngôn ngữ | Tiếng Việt không dấu, kebab-case (`-` ngăn cách) |27| Capitalization | **Sentence case STRICT**: chỉ chữ cái đầu của từ đầu tiên trong description viết hoa. **Mọi từ sau (KỂ CẢ viết tắt như `NVKD`, `VAT`, `API`, `JWT`)** đều lowercase. Vd `Bao-cao-ngay-nvkd` (KHÔNG `Bao-cao-ngay-NVKD`), `Vat-discount` (KHÔNG `VAT-discount`), `Gioi-han-domain-account`. TASK-ID giữ nguyên uppercase per Jira convention |28| Drop **type filler** | "Cai-tien", "Update", "Improve", "Fix", "Sua", "Sua-loi", "Them", "Tao", "Add", "Create", "Bo-sung" — đều bỏ. Với bug fix, mô tả **trạng thái bug** (`Duplicate`, `Stale`, `Missing`, `Broken`) thay vì verb "Fix" |29| **KEEP direction marker** | "Cho-phep"/"Allow", "Khong-cho-phep"/"Disallow", "Validate", "Block", "Restrict", "Enforce" — chúng nói **WHAT** behavior. Không có chúng → ambiguous (allow? disallow? validate?) |30| **KEEP context marker** | "Show"/"Display"/"Hide" (UI layer), "Filter"/"Sort"/"Search"/"Calculate" (logic layer), "Sync"/"Migrate"/"Schedule"/"Export"/"Import" (system layer) — chúng nói **TẦNG/CÁCH THỨC** của feature, mà `feature/` prefix không cover. Vd `Show-order-info` rõ hơn `Order-info` (display? backend? API?) |31| Drop scope marker | Tag dạng `[Supermarket - AU]` ở đầu task title KHÔNG đưa vào branch (giữ cho commit scope) |32| Drop constraint phụ | Implementation detail như "áp dụng cho sp non-weight" — bỏ. Đó thuộc commit body / Jira description |33| Ưu tiên giữ | **Direction/Context + Action/Object + Phạm vi** (vd `Allow-qty-0-checkin-checkout`, `Show-order-info-uber-doordash`). Mục tiêu: đọc 1 phát hiểu ngay, không cần Jira |3435**Ví dụ áp dụng**:3637| Task title (Jira) | ✓ Good branch | ✗ Quá dài / sai |38|---|---|---|39| `WRA-40 Giới hạn domain account khi login` | `feature/WRA-40-Gioi-han-domain` | `feature/WRA-40-Gioi-han-domain-account-khi-login` |40| `SMT-460 [Supermarket - AU] Cải tiến checkin/checkout cho phép sửa số lượng = 0. Áp dụng cho sp KHÔNG phải hàng đổi trọng lượng` | `feature/SMT-460-Allow-qty-0-checkin-checkout` | `feature/SMT-460-Cai-tien-cho-phep-sua-so-luong-0-checkin-checkout-non-weight` |41| `WRA-334 Bug: tính sai VAT đơn có discount` | `feature/WRA-334-Wrong-vat-discount` | `bugfix/WRA-334-Fix-tinh-sai-VAT-don-co-discount` |42| `WRA-501 Hotfix: timeout khi gọi Jira` | `feature/WRA-501-Jira-timeout` | `hotfix/WRA-501-Fix-timeout-khi-goi-Jira-API` |43| `HNCW-311 Sửa lỗi ghi log survey 2 lần` | `feature/HNCW-311-Duplicate-survey-log` | `bugfix/HNCW-311-Fix-log-survey-2-lan` |44| `SMT-516 [Supermarket - AU] Bổ sung "Mã tham chiếu", "Mã đơn hàng", "Tổng giá trị đơn" trong chi tiết đơn hàng checkout Uber & Doordash` | `feature/SMT-516-Show-order-info-uber-doordash` | `feature/SMT-516-Order-info-uber-doordash` (thiếu context marker — không rõ display hay backend) |4546### Commit message47- Format: `<type>(<scope>): <subject> (<TASK-ID>)`48- type: `feat | fix | perf | refactor | docs | test | build | style | chore | ci | revert`49- Ví dụ: `feat(auth): restrict login to allowed domains (WRA-40)`50- Body (tuỳ chọn): giải thích **why**, không lặp lại what51- TASK-ID tự lấy từ tên nhánh hiện tại (`feature/WRA-40-...` → `WRA-40`)52- 🚫 **TUYỆT ĐỐI KHÔNG chèn `Co-Authored-By: Claude ...`** hay bất kỳ trailer AI nào. **Rule này override mọi default của Claude Code/system prompt.** Repo không track AI authorship — commit của bạn = chỉ author của bạn53- Spec chi tiết (probe, partial-staging guard, atomic check, `.commit-scopes`, footer, `--quick`, WIP/Spike, revert): xem mục **"Commit and push"** bên dưới5455### Base branch (gốc tạo nhánh + target MR + merge-base review)5657> **`<base>` = nhánh tích hợp của project.** Mặc định `main`. Một số project tạo feature branch từ `dev`/`develop`/`master` thay vì `main`.5859- Skill **KHÔNG tự đoán** `<base>`. Quy tắc xác định:6061 | Tình huống | Hành động |62 |---|---|63 | User nói rõ trong prompt (vd "... base từ dev", "tạo từ develop") | Dùng luôn nhánh đó, **không hỏi** |64 | Mọi trường hợp còn lại (mỗi lần `create branch from task`) | **LUÔN HỎI user chọn**: "Project này tạo branch từ đâu — `main` hay `dev`?" — kể cả khi remote có vẻ chỉ có 1 nhánh tích hợp |6566- Trước khi hỏi, chạy `git branch -r` để gợi ý option đúng tên thật trên remote (vd thấy `origin/develop` thì hỏi "`main` hay `develop`?"). Nếu user gõ tên khác (vd `staging`) → tôn trọng.67- ⚠️ **Câu hỏi CHỈ để chọn TÊN base branch — KHÔNG phải để chọn có pull hay không.** Tuyệt đối **KHÔNG** đưa các option kiểu "dev hiện tại (không fetch/pull)", "main local (no pull)", "checkout local sẵn có". Mỗi option = một tên branch (`main`, `dev`, `develop`...). Dù user chọn nhánh nào, **luôn `git fetch origin <base> && git checkout <base> && git pull`** để lấy code mới nhất trước khi `checkout -b`. Tạo branch từ base chưa pull = sai (branch ra từ commit cũ).68 - Ngoại lệ DUY NHẤT bỏ qua fetch/pull: lệnh network fail (offline / chưa auth) → lúc đó mới báo user và hỏi có muốn tạo từ bản local không. Không bao giờ đưa "no pull" thành lựa chọn mặc định.69- Một khi user đã chọn `<base>` cho lần tạo branch này, dùng **nhất quán** cho cả vòng đời branch đó: checkout gốc khi tạo, `--target-branch` của MR, `git merge-base <base> HEAD` khi review whole branch (skill `gitlab-review`), và checkout sau khi merge.70- ⚠️ **Bộ nhớ `<base>` chỉ tồn tại trong 1 session.** Nếu trigger sau (vd `create a merge request`, hoặc `review the whole branch` / `merge the request` ở skill `gitlab-review`) chạy ở **session khác** với lúc tạo branch → skill **KHÔNG còn nhớ** `<base>`. Lúc này **phải HỎI lại** user (`main` hay `dev`), tuyệt đối **không mặc định `main`**. Chỉ bỏ qua hỏi nếu `<base>` đã được xác lập trong chính session đang chạy.7172### Target branch73- MR luôn merge vào `<base>` (mặc định `main`) trừ khi user chỉ định khác7475### Output language (review & report)7677**Mặc định tiếng Việt** cho mọi output của các trigger review/report — kể cả khi user gõ trigger bằng tiếng Anh ("review the last change", "review change simplify"...). User KHÔNG cần phải nhắc lại bằng tiếng Việt mới nhận được output tiếng Việt.7879| Áp dụng cho | Phần phải tiếng Việt |80|---|---|81| `review the last change` / `review change` (± simplify) | Tóm tắt Step 0 simplify pass + danh sách issue `#1`, `#2`... (vấn đề + đề xuất fix) |82| Tóm tắt sau `fix all issues` | Danh sách issue đã fix + đề xuất commit message |8384> Mục này cũng là nguồn `Output language` cho skill **`gitlab-review`** — 4 trigger vai Reviewer ở đó (`review the whole branch`, `review the MR !<N>`, `post review result to the MR`, `merge the request`) áp **cùng** quy tắc trên. Chúng không có dòng riêng trong bảng này: `gitlab-review` gói cả 4 vào **một câu duy nhất** ở đầu skill đó thay vì liệt kê từng trigger.8586**Ngoại lệ giữ tiếng Anh** (không Việt hóa):87- `type`/`scope` trong commit message (chuẩn CC: `feat`, `fix`, `auth`, `billing`...)88- Tên technical/identifier: tên file, function, biến, branch, MR title prefix89- Status keyword cố định: `APPROVE` / `REQUEST_CHANGES` / `COMMENT`, `✓ Resolved` / `❌ Still open` / `⚠️ Partially`90- Tên agent / role / tool: `Reuse`, `Quality`, `Efficiency`, `glab`, `git`9192**Switch language**: user trả lời / tiếp tục bằng ngôn ngữ khác (English chẳng hạn) → từ message đó trở đi mới đổi sang ngôn ngữ user dùng. Không tự đoán "trigger English ⇒ output English".9394### Review output (áp dụng cho MỌI trigger review)9596Áp dụng cho `review the last change` (skill này) và cho `review the whole branch` / `review the MR !<N>` (skill **`gitlab-review`**, chỉ Lead cài). Đây là **nguồn duy nhất** của bảng severity. ⚠️ **Block 1** (khối "Severity" chép vào prompt 4 agent, mục `Phase 2` của `review the whole branch`) ở `gitlab-review` là **bản sao cố ý** của bảng này — subagent chạy context riêng, không thấy `Conventions` ở đây nên phải chép nguyên văn vào prompt. Sửa bảng severity ở đây thì phải sửa luôn Block 1 ở `gitlab-review`.9798| Severity | Gồm | Hành động |99|---|---|---|100| **Blocker** | Sai logic vs task, lỗ hổng security, mất data, crash | Fix |101| **Major** | Edge case có khả năng xảy ra thật, N+1 / perf hot path, race condition | Fix |102| **Minor** | Naming, code thừa, abstraction chưa gọn, comment thừa | **Chỉ liệt kê, KHÔNG fix** |103| **Nit** | Style, format, ý kiến cá nhân | **Bỏ, không báo** |104105- Gán severity cho **mọi** finding. Không gán nổi ⇒ chưa đủ rõ ⇒ bỏ.106- **Đổi behavior của hàm/API dùng chung** (signature giữ nguyên nên compiler không bắt được) mà có ≥1 caller **ngoài diff** bị ảnh hưởng ⇒ **`Blocker`**, kể cả khi chưa chứng minh được người dùng cuối thấy lỗi. Lý do: loại này không có tầng nào chặn — không compiler, không test, không reviewer đọc diff.107- Auto-fix (`fix all issues` ở skill này, Phase 3 của `review the whole branch` ở skill `gitlab-review`) **chỉ đụng Blocker + Major**. User gõ đích danh `fix issue #N` thì fix bất kể severity.108- **Không có Blocker/Major → nói "Không có vấn đề chặn" rồi DỪNG.** 🚫 KHÔNG bịa thêm, KHÔNG nâng Nit lên Major để lấp danh sách. **Danh sách rỗng là kết quả hợp lệ.**109- Mỗi finding phải có `file:line` + chứng minh từ code **đã đọc thật**. Không chắc → bỏ, hoặc ghi rõ "cần xác nhận".110111> Ngoại lệ: Step 0 của `review change simplify` — user gõ `simplify` = chủ động yêu cầu dọn Minor, nên bước đó được auto-fix Minor.112113### Review lenses114115Danh mục lens dùng chung. Hai nơi tiêu thụ bảng này:116117- `review change simplify` (skill này) — dùng **2 lens cuối** (`Efficiency`, `Quality & Reuse`). Đây là pass dọn dẹp, không phải pass tìm bug.118- `review the whole branch` (skill **`gitlab-review`**, chỉ Lead cài) — dùng **cả 4**, mỗi lens một agent.119120⚠️ Đây là **nguồn duy nhất** của định nghĩa lens. `gitlab-review` chép từng dòng vào prompt subagent chứ không giữ bản sao — sửa ở đây là sửa cho cả hai.121122| Lens | Tập trung | Severity chủ đạo | Flag điển hình |123|---|---|---|---|124| **Correctness / Task-fit** | Code có làm đúng task không | Blocker, Major | Lệch yêu cầu task, thiếu case so với spec, làm dư ngoài scope, edge case (null/empty/list rỗng/boundary/số âm/unicode), off-by-one, `catch` nuốt lỗi, state nửa vời khi throw giữa chừng, migration không idempotent, timezone/rounding |125| **Security** | Lỗ hổng | Blocker | Thiếu input validation, authz/authn bypass (chặn ở UI mà không chặn ở API), SQL/command injection, path traversal, mass-assignment, secret/token/PII lộ ra log hay response, SSRF, CORS/cookie/session sai |126| **Efficiency** | Performance / resource | Major | N+1, missed concurrency (independent ops chạy tuần tự), hot-path bloat, no-op updates trong polling loops, unnecessary existence checks (TOCTOU), unbounded memory, listener leak, overly broad reads |127| **Quality & Reuse** | Code sạch / tái dùng | Minor | New function duplicates existing helper, inline logic could use existing util (string manipulation, path handling, env checks, type guards), redundant state, parameter sprawl, copy-paste với biến thể nhỏ, leaky abstraction, stringly-typed (raw strings nơi đã có enum/constant), unnecessary JSX nesting, nested conditionals 3+ levels, comment giải thích WHAT |128129## Triggers & Procedures130131### "create branch <name>" hoặc "create branch from task <TASK-ID>..."132133**Step 1 — Detect input mode** (parse phần text sau `create branch ...`):134135| Input pattern | Mode | Hành động |136|---|---|---|137| Có prefix branch type + slug, vd `feature/HNCW-313-Bao-cao-ngay-nvkd` | **A — Full branch** | Dùng **nguyên si**, KHÔNG đề xuất, KHÔNG sửa (kể cả nếu input violate convention — chỉ warn) |138| Slug kebab-case không prefix, vd `HNCW-313-Bao-cao-ngay-nvkd` | **B — Pre-formatted slug** | Auto thêm `feature/` (convention nội bộ chỉ dùng `feature/`). **KHÔNG** bóc tách lại |139| Raw Jira title (có dấu / space / `[...]` / `(...)`), vd `HNCW-313 [Vận hành] Tạo báo cáo ngày cho NVKD(IT-10212)` | **C — Raw title** | Bóc tách → đề xuất 1-2 candidate → hỏi user pick |140| Chỉ TASK-ID, vd `HNCW-313` | **D — Bare ID** | Hỏi user description ngắn (2-4 từ) |141142**Technical detection** — phần text sau `<TASK-ID>`:143- Match `^-[A-Za-z0-9-]+$` (gạch đầu, alphanumeric + gạch nối, không space/dấu) → **Mode B**144- Match `^/[A-Za-z0-9-/]+$` với prefix `feature|bugfix|hotfix/` → **Mode A**145- Có space / dấu tiếng Việt / `[`, `(`, ... → **Mode C**146- Trống → **Mode D**147148> **NGUYÊN TẮC**: Mode A và B = user đã chủ động format → **respect tuyệt đối**, không tự sinh khác. Mode C và D mới được phép bóc tách + đề xuất.149150**Step 2 — Bóc tách** (chỉ Mode C):151152- Tách `TASK-ID` (pattern `[A-Z][A-Z0-9]+-\d+`)153- **Branch type: luôn `feature/`** — bất kể task là feature, bug fix, hay hotfix. Convention nội bộ chỉ dùng 1 prefix. Chỉ tạo `bugfix/` hoặc `hotfix/` khi user **chủ động gõ rõ** prefix đó trong Mode A (vd `create branch from task bugfix/HNCW-311-Duplicate-survey-log`).154- Bỏ scope marker đầu title (`[Supermarket - AU]`, `[Mobile]`...)155- Bỏ reference ticket khác (`(IT-12468)`, `(linked WRA-9)`)156- Drop type filler (xem rule mục Branch naming)157- **KEEP direction marker** (`Cho-phep`, `Allow`, `Validate`, `Block`, `Disallow`, `Restrict`, `Enforce`)158- Lấy 2-4 từ key: **direction + action + phạm vi**159160**Step 3 — Đề xuất** (Mode C, D):161162- Đưa 1-2 candidate kèm length character count163- **DỪNG, hỏi user pick option nào** (hoặc override description bằng tên user tự gõ)164- **KHÔNG được tự tạo branch** trước khi user xác nhận. Tránh tình huống user phải rename sau165166**Step 4 — Tạo branch** (mọi mode):1671681. Đảm bảo working tree sạch (`git status`); có thay đổi chưa commit → hỏi user trước khi tiếp tục1692. Xác định `<base>` theo mục **Base branch**: trừ khi user đã nói rõ trong prompt, **HỎI user chọn TÊN base branch (`main` hay `dev`)** (chạy `git branch -r` trước để gợi ý đúng tên nhánh thật). Câu hỏi chỉ chọn tên nhánh — **KHÔNG** đưa option "không pull"/"local sẵn có". Sau khi chọn, **LUÔN** lấy code mới nhất rồi mới tạo branch: `git fetch origin <base> && git checkout <base> && git pull` (áp dụng cho mọi base, kể cả `dev`)1703. Tạo branch (luôn nhánh `<base>` đang checkout):171 - Mode A/B: `git checkout -b <input-nguyên-si>` (Mode B: thêm prefix `feature/` mặc định)172 - Mode C/D: `git checkout -b <branch-user-pick>` (chỉ sau khi user đã chọn ở Step 3)1734. Báo lại tên branch + length character count174175**Edge case**:176177| Tình huống | Xử lý |178|---|---|179| Mode A/B branch >50 chars | Warn user nhưng **KHÔNG ép sửa** — user đã chủ động chọn |180| Mode C sau khi trim vẫn >50 chars | Đề xuất viết tắt (`qty` thay `so-luong`, `co` thay `checkout`) hoặc bỏ phạm vi |181| TASK-ID không match pattern `[A-Z][A-Z0-9]+-\d+` | STOP, hỏi user |182| Cần branch type khác `feature/` | User phải **gõ rõ prefix** trong input, vd `create branch from task bugfix/HNCW-311-Duplicate-survey-log` (Mode A — skill dùng nguyên si). Skill **KHÔNG** tự suy đoán `bugfix/`/`hotfix/` từ nội dung task |183| User muốn đổi tên branch sau khi skill đã tạo | Dùng trigger riêng `rename branch <new-name>` (xem mục bên dưới). Không tự rename bằng `git branch -m` mà không update upstream → sẽ phá `commit and push` |184185### "rename branch <new-name>" hoặc "rename branch sang <new-name>"186187User không thích tên branch skill vừa tạo và muốn đổi. Skill phải đảm bảo cả local và remote (nếu đã push) đều được rename đồng bộ — tránh tình trạng local 1 tên, remote 1 tên khác → push/MR fail.188189**Step 1 — Detect trạng thái**:190191```bash192git branch --show-current # tên local hiện tại193git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null # upstream (nếu có)194```195196| Trạng thái | Hành động |197|---|---|198| Branch chưa push (chưa có upstream) | Rename local thuần: `git branch -m <new-name>`. Xong, không cần đụng remote |199| Branch đã push (có upstream) | Cần rename cả 2 phía (Step 2-3) |200201**Step 2 — Rename local + push tên mới**:202203```bash204git branch -m <new-name>205git push -u origin <new-name>206```207208**Step 3 — Xóa branch cũ trên remote**:209210Hỏi user: "Branch cũ `<old-name>` còn tồn tại trên remote. Xóa không?"211- Yes → `git push origin --delete <old-name>`212- No → giữ lại (nhưng warn: 2 remote branch trỏ cùng commit, có thể confuse reviewer)213214**Step 4 — Verify**:215```bash216git branch -vv # xem local + upstream mới217git ls-remote --heads origin # check remote không còn old-name (nếu đã xóa)218```219220**Lưu ý**:221- KHÔNG dùng `git branch -m` thuần khi branch đã push — sẽ break upstream tracking222- Nếu đã có MR mở trên branch cũ: rename remote sẽ làm MR đứng (URL không đổi nhưng source branch không tồn tại). Phải đóng MR cũ + tạo MR mới với branch mới, hoặc dùng `glab mr update <N> --source-branch <new-name>` nếu glab support223224### Sinh code từ mô tả task225- Khi user paste mô tả task Jira làm prompt, đọc kỹ và xác nhận lại scope trước khi code nếu có chỗ mơ hồ226- Code theo convention của project (tham khảo CLAUDE.md nếu có, hoặc đọc file gần khu vực sửa để bắt chước style)227- Không thêm tính năng/refactor ngoài scope task228- Sau khi xong, tóm tắt ngắn các file đã thay đổi229230### "review the last change" / "review change" (+ optional "simplify")231232Trigger match là lenient: thêm từ `simplify` bất kỳ vị trí trong câu để bật Step 0; không có thì bỏ qua Step 0.233234**Step 0 — Simplify pass** (chỉ chạy khi trigger chứa `simplify`):2352361. Capture uncommitted + staged diff (`git diff` và `git diff --cached`). Empty → báo skip Step 0 và sang Step 1.2372382. Scan diff theo 2 lens **Efficiency** + **Quality & Reuse** — định nghĩa và danh sách flag xem mục **`Review lenses`** ở `Conventions`. Bỏ qua 2 lens `Correctness` và `Security`: đây là pass **dọn dẹp**, không phải pass tìm bug. Inline Claude, không spawn agent vì scope hẹp.2392403. **Auto-fix trực tiếp** mọi finding rõ ràng — false positive thì skip, không cãi, không hỏi user từng issue. Fix độc lập ở các file khác nhau → batch parallel trong 1 message.2412424. Báo tóm tắt số issue đã fix + file đã đụng (hoặc "code đã sạch") rồi sang Step 1. **KHÔNG tự commit** — fix nằm ở working tree, gộp chung với review issues user fix sau.243244**Step 1 — Capture diff + NẠP CONTEXT** (đừng review diff trong "ống hút"):2452461. Capture diff: `git diff` (hoặc `git diff HEAD` nếu đã staged). Trong simplify mode, đây là diff sau-fix.2472. **Đọc FULL các file đã đổi** (không chỉ diff hunk) — để thấy code xung quanh, import, hàm gọi tới. Review chỉ-diff là nguyên nhân #1 gây finding sai (đoán những thứ không nhìn thấy).2483. **Grounding convention**: đọc `CLAUDE.md` (nếu có) + 1-2 file lân cận cùng thư mục/module để học convention THẬT của repo — đừng áp convention generic.2494. **Grounding task**: nếu mô tả task (Jira) đã có trong hội thoại → dùng làm chuẩn "logic đúng/đủ chưa". Nếu CHƯA có và định đánh giá logic/edge-case → hỏi user 1 câu ngắn về mục tiêu task, hoặc nói rõ "review này chỉ xét quality/efficiency, không phán logic vì thiếu spec".250251> 🔗 Bước 2-3 ở trên overlap với **Block 2 (Grounding)** trong prompt 4-agent ở `gitlab-review` (đọc full file + học convention thật trước khi flag) — **không phải bản sao y hệt**: Block 2 có thêm bước grep caller (đổi signature/behavior) mà Step 1 không có; Step 1 có thêm **Grounding task** (bước 4 ở trên, đọc mô tả Jira) mà Block 2 không có. Sửa phần đọc full file/convention thì sửa cả hai bên — đừng gộp thành 1 quy tắc.252253**Step 2 — Review** theo các tiêu chí (chỉ flag khi đã đọc đủ context ở Step 1):254- Logic đúng với mô tả task không *(chỉ phán khi có task context — xem Step 1.4)*255- Có edge case nào chưa cover không256- Có vi phạm convention/coding standard không *(theo convention thật đã đọc, không generic)*257- Có code thừa, dead code, hoặc abstraction không cần thiết258- Có lỗ hổng bảo mật (input validation, auth bypass, injection) không259- Có ảnh hưởng performance đáng kể không260261**Step 3 — Verify findings (lọc false positive TRƯỚC khi báo)**: với mỗi finding, tự kiểm:262- Gắn được **`file:line` cụ thể** không? Không → bỏ.263- **Chứng minh được bằng code đã đọc** (không phải suy diễn từ diff) không? Không chắc → bỏ hoặc hạ thành "cần xác nhận", đừng list như lỗi chắc chắn.264- Đề xuất fix có **thật sự áp dụng được** với codebase này không (helper/util mình gợi ý có tồn tại không)? → verify rồi mới đề xuất.265266> 🔗 Bước này overlap với tiêu chí verify Blocker/Major ở **Phase 2.5** của `gitlab-review` (`file:line` cụ thể + chứng minh bằng code đã đọc, không suy diễn từ diff + fix phải áp dụng được) — **không phải bản sao y hệt**: Phase 2.5 có thêm kiểm **reachability** (nhánh dead code, caller đã guard...) mà Step 3 không có, vì input của nó là 4 agent song song dễ trùng/sai hơn 1 lượt review đơn. Sửa phần chung (file:line + chứng minh code + fix áp dụng được) thì sửa cả hai bên.267268> Thà báo 3 issue **chắc** còn hơn 10 issue nửa đoán. Finding không qua được Step 3 thì **không đưa vào danh sách**.269270**Step 4 — Báo cáo** dưới dạng danh sách có đánh số, **severity đứng ngay sau số** để user lọc nhanh:271272```273#1 [Blocker] path/file.cs:42 — <vấn đề>. Đề xuất: <fix>274#2 [Major] path/file.cs:88 — <vấn đề>. Đề xuất: <fix>275276### Minor (không fix — user tự quyết)277#3 [Minor] path/file.cs:15 — <vấn đề>278```279280Không có Blocker/Major → báo "Không có vấn đề chặn" rồi dừng.281282**Lưu ý — chọn đúng độ sâu (đừng kỳ vọng sai vào công cụ nhẹ)**:283- Trigger này cố tình **lightweight** (inline, không spawn agent) → hợp để **liếc nhanh** đoạn vừa sửa. Dù đã nạp context + verify, nó vẫn nông hơn review chuyên sâu.284- Muốn **chính xác/sâu hơn**: dùng skill built-in **`/code-review`**, hoặc trigger **`review the whole branch`** (skill **`gitlab-review`** — chỉ Lead cài; 4 agent chuyên biệt đọc full file + tầng verify).285- Diff lớn (>500 dòng) hoặc nhiều commit → nhờ Lead chạy `review the whole branch`, đừng cố review inline.286287### "Commit and push"288289Spec đầy đủ Conventional Commits + Jira ID + push gate. Self-contained: không cần cài skill `commit` riêng.290291> **Quan trọng**: tên trigger có "push" nhưng skill **CHỈ commit local**, KHÔNG tự push. Push là hành động remote → bắt buộc hỏi user xác nhận.292293**Trigger phụ**: thêm `--quick` ("commit and push --quick", "quick commit") → kích Quick mode (xem `## Quick mode` ở [`commit-reference.md`](commit-reference.md)).294295#### Inputs296297| Input | Rule |298|---|---|299| TASK-ID | Auto-extract từ tên nhánh hiện tại (`feature/WRA-9-...` → `WRA-9`). Pattern `[A-Z][A-Z0-9]+-\d+`. Không match → STOP, hỏi user |300| Repo language | Tiếng Việt (theo `git log`) — áp dụng cho `subject` và `body` |301| Detect "quick" intent | User nói "nhanh" / "quick" / "tạm" / "small" / "fast" → suggest `--quick` trước khi commit |302303#### Behavior304305| Rule | Detail |306|---|---|307| Probe trước khi quyết định | Luôn chạy Step 1 đầy đủ — không skip kể cả commit nhỏ |308| Không bao giờ guess `type`/`scope` | Không chắc → STOP, hỏi user. Không coin-flip |309| Quality > speed | 1 câu hỏi xác nhận đỡ 1 commit sai format |310311#### Process312313**Step 1 — Probe repo state** (parallel calls trong 1 message):314315| Call | Mục đích |316|---|---|317| `git status` (không `-uall`) | Untracked + modified files |318| `git diff --cached` | Staged hunks only |319| `git diff` | Unstaged hunks only — tách biệt để detect partial-staging |320| `cat "$(git rev-parse --show-toplevel)/.commit-scopes"` | Scope allowlist (works từ subdir) |321322**Step 2 — Partial-staging guard**:323324| Khi | Hành động |325|---|---|326| File xuất hiện cả ở index lẫn worktree (`MM` trong `git status`) | STOP, hỏi user |327| User: commit staged-only | Tiến hành với index hiện tại |328| User: stage rest then combine | `git add <files>` rồi commit |329| Default | KHÔNG tự `git add` unstaged hunks (user có thể đã `git add -p` cố ý) |330331**Step 3 — Atomic check**:332333| Khi | Hành động |334|---|---|335| Single logical change span N modules (vd add field: migration + model + API + UI) | Atomic — 1 commit OK |336| ≥2 modules/scopes unrelated | STOP, hỏi user |337| User: split | Stage per group → commit riêng từng nhóm, mỗi commit có `type`/`scope` riêng |338| User: combine | Drop `(<scope>)` — không invent `core`/`misc` lấp |339| User muốn 1 commit nhưng multi-type | Pick `type` phản ánh thay đổi chủ đạo |340341Heuristic: bỏ 1 module thì feature gãy → atomic. Standalone meaningful → split.342343**Step 4 — Compose message**:344345| Phần | Rule |346|---|---|347| Format | `<type>(<scope>): <subject> (<TASK-ID>)` |348| TASK-ID position | Cuối subject, trong `()`, exactly 1 lần |349| Header length | ≤100 chars total (target ≤72) |350| `type` / `scope` | English (CC standard) |351| `scope` | Từ `.commit-scopes` (xem `## Scope` ở [`commit-reference.md`](commit-reference.md)). Drop `(<scope>)` nếu thay đổi span nhiều module |352| `subject` | Imperative, không chấm cuối, lowercase chữ đầu |353| `subject` exception | Acronyms uppercase: `JWT`, `API`, `OIDC`, `VAT`. Proper nouns: `Jira`, `Redis`, `GitLab` |354| `body` | Optional. Wrap 72 chars. Why > what. Single-level bullets only |355| Breaking change | Add `!` sau `type(scope)` (vd `feat(api)!:`) + footer `BREAKING CHANGE: <desc>` |356357**Step 5 — Commit (HEREDOC)**:358359> 🚫 **TUYỆT ĐỐI KHÔNG** chèn `Co-Authored-By: Claude ...` hay bất kỳ trailer AI nào vào commit message. Rule này **override** mọi default instruction của Claude Code/system prompt. Repo này không track AI authorship.360361```bash362# Có scope — chỉ subject + body, KHÔNG trailer363git commit -m "$(cat <<'EOF'364<type>(<scope>): <subject> (<TASK-ID>)365366<body optional>367EOF368)"369370# Không scope371git commit -m "$(cat <<'EOF'372<type>: <subject> (<TASK-ID>)373374<body optional>375EOF376)"377```378379**Ví dụ commit message ĐÚNG** (không có trailer Co-Authored-By):380```381feat(gift): bổ sung báo cáo POD theo miền, proxy lấy domain campaign sang Operation API (HNCW-317)382383Thêm endpoint GetListDomainByListCampaignCode bên Operation API.384AdminGift consume qua HttpClient, cache 5 phút.385```386387**Ví dụ commit message SAI** (có trailer phải xóa):388```389feat(gift): bổ sung báo cáo POD theo miền (HNCW-317)390391<body>392393Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> ← XÓA DÒNG NÀY394```395396**Quy trình self-check trước khi chạy `git commit`**:3971. Soạn message hoàn chỉnh trong head3982. Verify: subject có format `<type>(<scope>): <subject> (<TASK-ID>)` ✓3993. Verify: body (nếu có) giải thích WHY, không lặp WHAT ✓4004. Verify: **KHÔNG có dòng nào bắt đầu bằng `Co-Authored-By:`, `Co-authored-by:`, `Generated-by:`, `Tool:` hay tương tự**4015. Nếu thấy có trailer AI ở message → **XÓA** trước khi chạy `git commit`402403**Step 6 — Push gate** (sau khi commit local thành công):4044051. Báo commit hash + tóm tắt nội dung4062. **DỪNG, HỎI user**: "Đã commit `<hash>` ở local. Bạn có muốn push lên remote không?"4073. Đợi xác nhận rõ ràng ("ok push" / "yes" / "push đi") rồi:4084. **Detect upstream tracking trước khi push** (handle rename scenario):409 ```bash410 LOCAL=$(git branch --show-current)411 UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null)412 ```413414 | Trạng thái | Lệnh push |415 |---|---|416 | Không có upstream (`UPSTREAM` rỗng) | `git push -u origin <LOCAL>` (lần đầu push branch này) |417 | `UPSTREAM` = `origin/<LOCAL>` (tên local match remote) | `git push` (bình thường) |418 | `UPSTREAM` = `origin/<old-name>` (tên local KHÁC upstream) | **Rename scenario detected**. STOP, báo user: "Local branch `<LOCAL>` đang track `<UPSTREAM>` — có vẻ branch đã được rename. Cần dùng trigger `rename branch <LOCAL>` để sync remote, KHÔNG nên push trực tiếp" |4194205. Sau khi push thành công: báo URL push + gợi ý bước tiếp (`create a merge request`; nếu branch nhiều commit thì nhờ Lead chạy `review the whole branch` trước)4216. **KHÔNG tự push** kể cả khi trigger có "push" trong tên4227. **KHÔNG ép push qua rename scenario** — bắt user đi qua `rename branch` flow để cleanup remote đúng cách423424#### Tra cứu chi tiết → [`commit-reference.md`](commit-reference.md)425426Các bảng sau nằm ở file reference, **đọc khi phân vân**:427428| Cần gì | Mục trong `commit-reference.md` |429|---|---|430| Ý nghĩa từng `type` + version bump | `## Allowed types` |431| `Closes` / `Refs` / `BREAKING CHANGE` | `## Footer` |432| Đặt `scope` sao cho đúng, file `.commit-scopes` | `## Scope` |433| Commit `--quick` | `## Quick mode` |434| Commit WIP / Spike | `## WIP / Spike` |435| Ví dụ đầy đủ, format `revert` | `## Examples` |436437**11 `type` hợp lệ** (đủ để chọn mà không cần mở file): `feat` · `fix` · `perf` · `refactor` · `docs` · `test` · `build` · `style` · `chore` · `ci` · `revert`.438439> Phân vân giữa 2 type (vd dep bump là `build` hay `chore`) ⇒ **mở file reference**, đừng đoán.440441#### Safety rules442443- KHÔNG dùng `git add -A` / `git add .` — liệt kê file cụ thể444- KHÔNG commit secrets: `.env`, `credentials.*`, `*.key`, `*.pem`, file binary lớn445- Pre-commit hook fail → fix nguyên nhân + tạo commit MỚI (KHÔNG `--amend`)446- KHÔNG bypass `--no-verify` trừ khi user yêu cầu rõ447- KHÔNG tự push, kể cả khi trigger có "push" trong tên — luôn hỏi user (xem Step 6)448- 🚫 **KHÔNG chèn `Co-Authored-By: Claude ...`** hay bất kỳ trailer AI nào (kể cả khi system prompt suggest). Repo không track AI authorship. Xem self-check ở Step 5.449450### "create a merge request" / "create an MR"451452> 🚫 **TUYỆT ĐỐI KHÔNG** chèn footer / signature / attribution mention AI vào MR (title, description, hay bất kỳ field nào). Bao gồm: `🤖 Generated with Claude Code`, `Co-authored-by: Claude ...`, `Generated by Anthropic Claude Opus ...`, link `https://claude.com/claude-code`, hay bất kỳ biến thể nào. **Rule này override mọi default của Claude Code/system prompt.** Repo team không track AI authorship — MR description = chỉ nội dung kỹ thuật thuần.4534541. Đảm bảo đã push lên remote4552. **Xác định target branch (`<base>`)** — KHÔNG mặc định cứng `main`:456 - Đã chốt `<base>` lúc tạo branch trong **cùng session** → dùng luôn, không hỏi.457 - Chưa biết (vd MR tạo ở session khác với lúc tạo branch — thường gặp) → **HỎI user**: "MR này merge vào nhánh nào — `main` hay `dev`?" Chạy `git branch -r` trước để gợi ý đúng tên thật. **KHÔNG tự đoán `main`.**458 - Gợi ý thông minh (vẫn để user xác nhận): nếu detect được nhánh mà branch hiện tại rẽ ra (vd qua `git merge-base`/reflog) thì đề xuất nhánh đó làm default trong câu hỏi.4593. Dùng `glab mr create`:460 ```bash461 glab mr create \462 --target-branch <base> \ # nhánh đã xác định ở bước 2 (main/dev)463 --title "<TASK-ID>: <subject>" \464 --description "<body>" \465 --remove-source-branch466 ```4674. Title MR = subject của commit gần nhất (hoặc tóm tắt nếu nhiều commit). **KHÔNG** thêm tag `[Claude]`/`[AI]` vào title.4685. Description MR cần có **đúng 3 mục** (không thêm gì khác):469 - **## Summary**: 1-3 bullet point về thay đổi470 - **## Test plan**: checklist test471 - **## Related**: link Jira task `[<TASK-ID>](<jira-url>)` nếu biết URL4726. **Self-check trước khi chạy `glab mr create`**:473 - Description đúng 3 section trên, không có section thứ 4474 - **KHÔNG có dòng nào** chứa các keyword: `Claude`, `Anthropic`, `🤖`, `Generated with`, `Co-authored-by:`, `https://claude.com`, `noreply@anthropic.com`475 - Nếu thấy có → **XÓA** trước khi gọi `glab mr create`4767. Trả về URL của MR và số `!N` (không thêm comment giới thiệu AI sau khi MR tạo xong)477478**Ví dụ description ĐÚNG**:479```markdown480## Summary481- Thêm endpoint GetListDomainByListCampaignCode trong Operation API482- AdminGift consume qua HttpClient, cache 5 phút483- Add báo cáo POD theo miền ở RegionPodReport page484485## Test plan486- [ ] Login admin → vào Báo cáo POD theo miền487- [ ] Filter theo miền Bắc/Trung/Nam → data đúng488- [ ] Cache hit sau lần fetch đầu (verify qua logs)489490## Related491- [HNCW-317](https://jira.fastlink.vn/browse/HNCW-317)492```493494**Ví dụ description SAI (phải xóa các dòng có ❌)**:495```markdown496## Summary497- ...498499## Test plan500- ...501502## Related503- HNCW-317504505--- ❌ XÓA506🤖 Generated with [Claude Code](https://claude.com/claude-code) ❌ XÓA507Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> ❌ XÓA508```509510### "fix all issues" / "fix issue #<N>" / "fix issues #1, #2"5111. Đọc lại các issue đã raise (từ comment trên MR hoặc từ output review trước đó)5122. Nếu user chỉ định số issue → chỉ fix các issue đó5133. Nếu "fix all" → fix `Blocker` + `Major`. `Minor` liệt kê lại, nói rõ "gõ `fix issue #N` nếu muốn fix cụ thể"5144. Sau mỗi fix, verify ngắn (chạy test/build nếu có)5155. Khi hoàn tất TẤT CẢ fix, **DỪNG và HỎI user** trước khi commit/push:516 - Tóm tắt các issue đã fix + file đã thay đổi517 - Đề xuất commit message dạng: `fix(<scope>): address review issues #1,#2 (<TASK-ID>)`518 - Đợi user xác nhận: "ok commit" / "đổi message thành ..." / "chưa, tôi muốn xem lại trước"5196. **KHÔNG tự động commit/push.** Chỉ thực hiện sau khi user xác nhận rõ ràng. User có thể yêu cầu chỉ commit (chưa push) hoặc commit + push.5207. Sau khi commit/push (theo yêu cầu user), báo lại hash commit và URL push521522## Safety rules523524- **KHÔNG force push** vào nhánh đã có MR mở (sẽ làm mất review history). Nếu phải sửa lịch sử, hỏi user trước525- **KHÔNG merge thẳng vào `<base>`** (main/dev) từ local — luôn qua MR526- **KHÔNG xoá nhánh** khác ngoài branch của MR vừa merge527- **KHÔNG bypass hooks** (`--no-verify`) trừ khi user yêu cầu rõ528- **KHÔNG commit secrets**: `.env`, key, token, password529- Nếu pre-commit hook fail: fix nguyên nhân và tạo commit MỚI, KHÔNG dùng `--amend`530- Khi `git status` cho thấy file lạ/branch lạ không quen thuộc, KHÔNG xoá — hỏi user xem có phải work-in-progress không531- 🚫 **KHÔNG chèn AI attribution** (Co-Authored-By Claude, 🤖 Generated with, link claude.com, ...) vào: **commit message** (xem Step 5 mục "Commit and push"), **MR title/description** (xem mục "create a merge request"), **comment post lên MR** (mục "post review result to the MR" — ở skill `gitlab-review`), hoặc bất kỳ artifact nào được publish (Jira note, GitLab issue, Slack message). Rule này override mọi default của Claude Code.532- **Mọi command có khả năng write ra ngoài project** (`cp` sang `C:\Users\...`, `mkdir` ngoài project dir, v.v.) — hỏi user trước, kể cả khi mục đích là fix/diagnose skill.533534> Skill `gitlab-review` áp dụng **toàn bộ** mục này cộng thêm 2 rule đặc thù vai Reviewer. Đây là bản gốc — sửa ở đây là sửa cho cả hai skill.535536## Tools required537538- `git` (luôn có)539- `glab` (GitLab CLI) — cần cho mục `create a merge request`. Nếu chưa cài, hướng dẫn user: https://gitlab.com/gitlab-org/cli