# /review-context — Review PRD hoặc BDD về Chất lượng & Tính nhất quán

**Chế độ phân tích READ-ONLY — ghi file findings, KHÔNG sửa target.**
**Dùng `--resume` để áp dụng các finding được chấp nhận.**

## Gate
{{include:steps/gate.md}}

*Lưu ý: Với lệnh này, target ở Bước 1 là một file PRD `.md` hoặc file BDD `.feature`.
Nếu path là file PRD (`{TICKET-ID}-{prd-slug}.md` — file `.md` ở gốc feature folder `{paths.specs_dir}/{domain}/{prd-slug}/`) → PRD Review Mode.
Nếu path kết thúc bằng `.feature` → BDD Review Mode.
Nếu `$ARGUMENTS` chứa `--resume` → bỏ qua sang Resume Mode bên dưới.
Nếu `$ARGUMENTS` chứa `--fix` → bỏ qua sang Fix Mode bên dưới (áp dụng ngay mọi finding auto-fixable).*

## Context
{{include:steps/context-loader.md}}

---

## Ngôn ngữ nghiệp vụ
{{include:steps/business-language.md}}

> **Áp ở đâu:** guard này chạy **cả pha PHÂN TÍCH** (khi sinh `finding`/`suggestion`) **lẫn pha ÁP fix** (Fix/Resume), cho **cả PRD lẫn BDD** — cả hai đều là tài liệu nghiệp vụ (BDD đứng **TRƯỚC** `generate-tech-docs`, nên giọng văn reviewer vẫn phải thuần nghiệp vụ). Trước khi ghi file findings, quét `finding` + `suggestion` của **mọi** finding qua guard — đây là prose PO/BA đọc, phải **thuần nghiệp vụ** (gồm Nhóm 4 ẩn dụ dữ liệu). Field `quote` **MIỄN** (trích nguyên văn target — được phép chứa từ kỹ thuật, kể cả đoạn Gherkin đang bị bắt lỗi). **Riêng BDD:** danh từ **cấu trúc** của tài liệu — `Scenario`/`Given`-`When`-`Then`/`Background`/data table/tag `@trace`/Coverage Matrix/side-effect — là từ vựng hợp lệ, guard **KHÔNG** tính là "thuật ngữ kỹ thuật" (giống P0/P3 được miễn danh từ hạ tầng). R3 (no-tech *trong step* Gherkin) vẫn là luật riêng của nội dung BDD, độc lập với guard này.

---

## Phát hiện Review Mode

Sau khi phân giải target file:
- File `.feature` → **BDD Review Mode** (nhảy tới section BDD)
- File `.md` ở gốc feature folder `{paths.specs_dir}/*/*/` (không phải dưới `bdd/`·`tech-docs/`·`design-spec/`) → **PRD Review Mode** (tiếp tục bên dưới)
- Không xác định → hỏi: "Đây là file PRD hay file BDD feature? (prd/bdd)"

Đồng thời kiểm tra flag:
- Có `--fix` → sau khi chạy hết các check, áp dụng ngay các finding `auto_fixable: true` (bỏ qua Review Board)
- Có `--resume` → bỏ qua phân tích hoàn toàn, sang Resume Mode

Suy ra tên file findings output:
- PRD: `{paths.refinement_dir}/{prd-slug}-review-context-findings.yaml`
- BDD: `{paths.refinement_dir}/{uc-id}-{platform}-review-bdd-findings.yaml` — `{platform}` đọc từ `@trace.platform` của header `.feature` target (web/app/system). **Bắt buộc có platform**: mỗi UC có `.feature` riêng theo platform cùng `@trace.id`, nên tên file thiếu platform sẽ khiến review platform này **đè** findings platform khác (đối xứng với sổ TSV `{UC-ID}-{platform}.tsv`).

---

## Quy trình Review
{{include:steps/review-fanout.md}}

**Các check dưới đây map vào quy trình như sau:**
- **DIMENSIONS** = các nhóm check theo mode phát hiện được — PRD: `P1, P2, P4, P5`; BDD: `B1, B2, B3, B4, B5, B6`. Fan out một sub-agent cho mỗi nhóm check, mỗi cái quét toàn bộ target file chỉ cho nhóm đó.
- **Check do orchestrator chạy (không fan out):** `P0` (umbrella routing) và `P3` (xung đột cross-PRD) cần config / context của PRD khác — orchestrator tự chạy chúng **trước** fan-out và thêm kết quả vào `ALL_FINDINGS`.
- Vòng lặp completeness-critic (Phase 2) đảm bảo file findings đầy đủ trong một lần chạy — chạy lại `/review-context` sẽ lòi ra **0 finding mới**. Map mỗi dimension vào field `check_id` của schema dưới đây.

**Tham số truyền vào Quy trình Review:**
- `GRANULARITY = per-uc` — LUÔN fan-out theo từng UC (bỏ ngưỡng cả-file), để **cổng review bắt đủ lỗi ngay lần đầu** (cổng cuối trước khi sinh BDD — sót ở đây thì test sai theo).
- `CHANGED_SCOPE` — theo full/delta dưới đây.
- **Ngôn ngữ finding (mọi dimension):** khi fan-out — PRD `P1/P2/P4/P5` **và** BDD `B1–B6` — thêm vào `DIMENSION_DESCRIPTION` của mỗi sub-agent chỉ dẫn: *"Đây là tài liệu nghiệp vụ (đứng TRƯỚC `generate-tech-docs`) — `finding` và `suggestion` viết bằng lời nghiệp vụ cho PO/BA, KHÔNG kê cơ chế/giải pháp kỹ thuật (retry/timeout/API/selector/cấu trúc dữ liệu). PRD: cơ chế lạc tầng → đề xuất DI DỜI xuống BR/BL bằng business logic. BDD: step lấn kỹ thuật → đề xuất diễn đạt lại bằng hành vi nghiệp vụ quan sát được (danh từ cấu trúc Gherkin/`@trace` được phép). `quote` giữ nguyên văn."* (Xem "Nguyên tắc chung" ở đầu mỗi Review Mode.)

**Chọn full vs delta** *(mặc định: lần đầu FULL, lần sau DELTA)*:
1. Tách `--full` khỏi `$ARGUMENTS` nếu có.
2. Kiểm tra file findings của target (tên suy ở "Phát hiện Review Mode"):
   - **Không tồn tại** (lần đầu) → **FULL**: KHÔNG truyền `CHANGED_SCOPE`.
   - **Tồn tại** + có `--full` → **FULL**: bỏ qua findings cũ.
   - **Tồn tại** + KHÔNG `--full` → so `source_version` trong findings cũ với version target hiện tại (PRD: Metadata `Version`; BDD: `@trace.bdd_version`):
     - **Bằng nhau** (target chưa đổi từ lần review trước) → DỪNG, báo: `"Target chưa đổi từ v{X} (lần review gần nhất). Không có gì để review lại — dùng --full nếu vẫn muốn quét toàn bộ."`
     - **Khác** → kiểm tra `applied_to_version` trong findings cũ (version mà lần `--fix`/`--resume` gần nhất của CHÍNH lệnh này đã bump target tới) để biết ai gây ra thay đổi:
       - **`applied_to_version` có mặt VÀ `==` version target hiện tại** → target đổi đúng bằng phần lệnh này tự áp, không actor khác động vào → **DELTA**: `CHANGED_SCOPE` = { `uc_id`/`section` của finding đã xử lý (status `accepted`/`modified`/`applied`) trong findings cũ } ∪ { UC có trong target hiện tại nhưng chưa từng xuất hiện ở findings cũ }.
       - **`applied_to_version` vắng mặt HOẶC `≠` version hiện tại** → target đã bị sửa bởi **actor khác** (lệnh `/refine-prd`, `/generate-bdd` regen, sửa tay…) sau lần áp này → KHÔNG tin được phạm vi hẹp → **FULL** (KHÔNG truyền `CHANGED_SCOPE`), kèm cảnh báo: `"Target đổi ngoài tầm theo dõi của findings (applied_to_version={A} ≠ hiện tại={C}); quét lại toàn bộ để khỏi sót UC do người/lệnh khác sửa."`

---

## PRD Review Mode

> **Nguyên tắc chung cho mọi P-check — soi bằng mắt kỹ thuật, VIẾT bằng lời nghiệp vụ.**
> Các check dùng con mắt kỹ thuật để **phát hiện** chỗ nghiệp vụ mô tả thiếu/mơ hồ/mâu thuẫn/lấn tầng — mục tiêu là **làm rõ vấn đề nghiệp vụ để sau xử lý được về kỹ thuật**. **KHÔNG** đưa góc nhìn kỹ thuật vào PRD, **KHÔNG** đề xuất giải pháp/cơ chế kỹ thuật (số lần retry, timeout, cấu trúc dữ liệu, API, thư viện). Mọi `finding` và `suggestion` phải **thuần nghiệp vụ** (tuân Business Language Guard ở trên, gồm Nhóm 4). Altitude: khi chỉ ra cơ chế lạc chỗ, suggestion là **DI DỜI xuống BR/BL** và diễn đạt bằng *business logic*, KHÔNG viết lại thành chi tiết code. `quote` giữ nguyên văn.
> *(P0/P3 nói về routing/metadata & xung đột cross-PRD — được nhắc "service/domain/config" như danh từ hạ tầng hợp lệ; nguyên tắc này chủ yếu siết nội dung nghiệp vụ ở P1/P2/P4/P5.)*

### P0 — Umbrella Routing Check (chỉ chế độ umbrella)

*Bỏ qua hoàn toàn check này nếu `setup.mode` không phải `"umbrella"` (tức không có section `services` trong project-context.yaml).*

Khi `setup.mode = umbrella`, PRD phải có metadata routing đúng để context-loader Bước 1.5 có thể đưa output sinh ra tới đúng service submodule. Chạy các check này **trước P1–P5**:

> **Nguồn đọc:** PRD mang **Domain** ở **bảng Metadata** (`| **Domain** | … |`) — **KHÔNG** phải frontmatter `@trace.*` (cái đó dành cho file `.feature`/tech-docs do máy đọc). Routing umbrella dựa trên Domain (bảng) + path, đúng như context-loader Bước 1.5.

**P0.1 — Row `Domain` có mặt trong Metadata**
- Đọc bảng Metadata của PRD, lấy row `| **Domain** |`.
- Nếu **vắng mặt / để trống** → finding **critical**:
  - `finding`: "Row `Domain` trong bảng Metadata đang thiếu. Umbrella routing của team dev phụ thuộc Domain (+ path) để đưa BDD và code output tới đúng service submodule."
  - `suggestion`: "Thêm `| **Domain** | {domain} |` vào bảng Metadata. Dùng một trong các domain key được định nghĩa trong section services của `project-context.yaml` của umbrella."
  - `auto_fixable: false` — PO phải confirm tên domain đúng

**P0.2 — `Domain` khớp một service key**
- Nếu Domain có mặt, kiểm tra giá trị của nó có khớp key nào trong section `services` của project-context.yaml không.
- Nếu **không khớp** → finding **critical**:
  - `finding`: "Domain `{value}` không khớp key nào trong config `services` của umbrella. Routing sẽ fallback về path mặc định và BDD có thể được sinh sai chỗ."
  - `suggestion`: "Hoặc cập nhật row Domain cho khớp một service key có sẵn ({list known keys}), hoặc thêm entry mới vào `services` trong project-context.yaml cho domain `{value}`."
  - `auto_fixable: false`
- Nếu section `services` chưa được cấu hình (rỗng/placeholder) → finding **major**:
  - `finding`: "Section `services` của umbrella chưa được cấu hình. Không thể kiểm chứng domain routing."
  - `suggestion`: "Cập nhật section services trong `.agent/project-context.yaml` với mapping domain-to-submodule trước khi sinh BDD."
  - `auto_fixable: false`

> **Status KHÔNG còn là check của P0.** PRD chưa duyệt (`Status: draft`) là trạng thái **bình thường** lúc review — việc duyệt diễn ra *sau khi* review-context sạch, nên báo draft là "lỗi" ở đây chỉ gây nhiễu. Gác duyệt do `/generate-bdd` lo (cảnh báo mềm, áp **mọi mode**); lời nhắc đặt `approved` nằm ở Report (mọi mode). P4 chỉ lo trường hợp row Status **vắng mặt** (auto-fix mặc định `draft`).

> **P0 là một gate check:** Nếu P0.1 hoặc P0.2 cho finding critical, hiển thị cảnh báo trước khi tiếp tục:
> ```
> ⚠️  ROUTING WARNING: phát hiện vấn đề Domain trong Metadata.
>    BDD/code sinh từ PRD này có thể rơi vào sai service submodule.
>    Giải quyết các finding P0 trước khi chạy /generate-bdd.
> ```
> Rồi tiếp tục với P1–P5 (đừng abort — PO có thể đang review PRD giai đoạn sớm).

### P1 — Terminology Check (Business Dictionary)

Nạp `{paths.business_dictionary}`.
Quét toàn bộ PRD tìm vấn đề thuật ngữ:

1. **Banned terms** — mọi lần xuất hiện của một term trong §Banned Terms:
   → Severity: **critical**. AI có thể auto-fix khi `--resume`.

2. **Dùng không nhất quán** — cùng một khái niệm được đặt tên khác nhau giữa các section:
   → Severity: **major**. Gắn cờ cả hai chỗ. Người quyết định dạng chuẩn trong note Review Board.

3. **Business term chưa liệt kê** — các term quan trọng vắng trong dictionary:
   → Severity: **minor**. Đề xuất thêm vào `business-dictionary.md`.

4. **Thuật ngữ kỹ thuật/UI lọt vào prose nghiệp vụ** — theo baseline **Business Language Guard** (re-render, UI, timeout, spinner, API/endpoint/token…), không nằm trong dictionary nhưng vẫn là từ kỹ thuật:
   → Severity: **major**, auto-fixable. `suggestion` theo guard: diễn đạt lại (Nhóm 1) / chuyển Design Spec (Nhóm 2) / bỏ về Tech Docs (Nhóm 3).

### P2 — Ambiguity Check

Quét mỗi AC và BR tìm:

| Tín hiệu | Ví dụ | Severity |
|--------|---------|----------|
| Định lượng mơ hồ | "nhanh", "lớn", "hợp lý", "mau" | Critical |
| Thiếu actor | "hệ thống nên" mà không nêu trigger | Major |
| Tham chiếu chưa định nghĩa | "{SomeThing}" được dùng nhưng chưa định nghĩa trong PRD này | Major |
| Thiếu luồng âm | AC chỉ mô tả happy path nhưng BR có điều kiện lỗi | Minor |
| Câu bị động giấu actor | "Invoice is created" — ai tạo? | Minor |
| **AC lấn tầng (chứa cơ chế)** | AC ghi số lần retry / timeout / tên-chủ cờ / nhánh lỗi chi tiết — cái này thuộc BR/BL | Major |
| **AC ≈ BR (trùng nội dung, hội tụ tầng)** | AC lặp lại đúng nội dung BR nó ref | Major |

→ AI không thể auto-fix finding P2. Người viết bản fix trong note "Modify". Với 2 tín hiệu **altitude** (AC lấn tầng / AC≈BR): suggestion là **DI DỜI chi tiết cơ chế xuống BR/BL (§3), AC giữ outcome + ref** — không xoá, không phình.

### P3 — Domain Conflict Check

Liệt kê tất cả PRD khác trong `{paths.specs_dir}/{domain}/*/*.md` (file `.md` ở gốc mỗi feature folder = PRD).
Với mỗi PRD, kiểm tra xem PRD này có mâu thuẫn với một BR đã định nghĩa không (cùng trigger, khác outcome)
hoặc định nghĩa lại field/status transition của một entity khác đi.

→ Severity: **critical**. Người quyết định PRD nào đúng. Bắt buộc có note.

### P4 — Structural Completeness

Đối chiếu với cấu trúc template PRD (Metadata · §1 Tổng quan · §2 AC · §3 UC · §4 UI/UX · Appendix · Change Log):

- [ ] **Metadata** có: Version, Status, Author, Created, Updated, Domain, Ticket (PO nếu có)
- [ ] **§1c "Phụ thuộc liên service"** có mặt (hoặc ghi rõ "Không có")
- [ ] **§2 Acceptance Criteria** (global) có mặt; **mỗi AC** kết thúc bằng ref `_(BR: …)_` (≥1 BR)
- [ ] **≥1 UC** với heading `#### {TICKET-ID}-UC{N}:`
- [ ] Mỗi UC có: **Actor, Description, Pre-condition, Post-condition, AC liên quan**, bảng Business Rule (AC là §2 global — UC chỉ trỏ qua "AC liên quan", KHÔNG chứa AC đầy đủ)
- [ ] **Nhất quán 2 chiều**: tập "AC liên quan" của mỗi UC = tập AC §2 có ref BR trỏ về UC đó
- [ ] **§4 UI/UX**: có User Flow và **Wireframe** (Wireframe lái coverage BDD C.1)
- [ ] **API Source nhất quán**: nếu Metadata `API Source: existing` → Appendix "Existing API Contract" đủ method/path/request/response (hoặc có block ⛔ PENDING + con trỏ nguồn); nếu greenfield/partner (API Source trống) → section "Existing API Contract" đã bị **xoá hẳn** (không để bảng rỗng)
- [ ] Có section `# Change Log`
- [ ] Không còn giá trị `{{PLACEHOLDER}}` chưa điền

→ Section/field thiếu hoặc lệch cấu trúc: **major**. AI có thể thêm skeleton khi `--resume` nếu được chấp nhận. Riêng **"Nhất quán 2 chiều"** lệch → **major**, `auto_fixable: false` (người xác nhận AC↔UC, AI không tự đoán). **API Source: existing thiếu contract** → **major**, `auto_fixable: false` (cần nguồn contract); **greenfield còn sót section "Existing API Contract" rỗng** → **minor**, `auto_fixable: true` (xoá section). Riêng **row `Status` vắng mặt** → **minor**, `auto_fixable: true` (thêm `| **Status** | draft |`) — KHÔNG flag *giá trị* draft (đó là trạng thái bình thường lúc review; gác duyệt do `/generate-bdd` lo).

### P5 — Custom Criteria (tuỳ chọn)

Nếu `$ARGUMENTS` chứa tiêu chí bổ sung sau path file, đánh giá chúng và tạo
finding với `check_id: "P5"` và severity phù hợp.

---

## BDD Review Mode

> **Nguyên tắc chung cho mọi B-check — BDD cũng là tài liệu nghiệp vụ (đứng TRƯỚC `generate-tech-docs`) → soi bằng mắt kỹ thuật, VIẾT bằng lời nghiệp vụ.**
> Các check dùng con mắt kỹ thuật để **phát hiện** step/scenario thiếu-phủ, sai thuật ngữ, lấn tầng kỹ thuật — nhưng `finding` và `suggestion` là prose **PO/BA đọc**, phải **thuần nghiệp vụ** (tuân Business Language Guard ở trên, gồm Nhóm 4). **KHÔNG** kê cơ chế/giải pháp kỹ thuật trong prose finding (API, selector, retry, timeout, cấu trúc dữ liệu, thư viện). Khi một step lấn kỹ thuật (R3), `suggestion` là **cách diễn đạt lại bằng hành vi nghiệp vụ quan sát được**, không phải chỉ dẫn code. `quote` giữ nguyên văn (được phép chứa đúng đoạn Gherkin kỹ thuật đang bị bắt lỗi).
> *(Miễn trừ: danh từ **cấu trúc** BDD — `Scenario`/`Given`-`When`-`Then`/data table/tag `@trace`/Coverage Matrix/side-effect — là từ vựng hợp lệ của tài liệu này, không bị guard tính là thuật ngữ kỹ thuật. Nguyên tắc này siết **giọng văn nghiệp vụ**, không cấm nhắc tên cấu trúc Gherkin.)*

### B1 — PRD Coverage Check

Nạp PRD được tham chiếu bởi `# @trace.prd:` trong header file feature.
Map mọi AC và mọi BR (gồm cả sub-bullet) sang scenario:

```
AC1 ({short text}) → SC1, SC2  ✅
AC2 ({short text}) → MISSING   ❌
BR1 ({short text}) → SC1       ✅
BR2 ({short text}) → MISSING   ❌
```

→ Mỗi AC/BR thiếu coverage: finding **critical**.
   Nếu được chấp nhận trong Review Board, `--resume` sinh scenario còn thiếu.

### B2 — Terminology & Entity Check

Dùng `{paths.business_dictionary}` và `{paths.core_entities}`:

1. **Banned terms trong steps** → **critical**, auto-fixable khi `--resume`
2. **Tên entity không chuẩn** → **major**, auto-fixable
3. **Tên field không chuẩn trong data table** → **major**, auto-fixable
4. **Sample data trông kỹ thuật** (UUID, `item_123`) → **minor**, auto-fixable

### B3 — Gherkin Rules Check (R1–R10)

| Rule | Check | Auto-fixable? |
|------|-------|---------------|
| R1 | Mỗi scenario có Given + When + Then | No — cần thiết kế lại scenario |
| R2 | Không chained `When … Then … When` | No — cần thiết kế lại |
| R3 | Không UI selector / API path / tech term trong steps | Yes — thay bằng cách diễn đạt nghiệp vụ |
| R4 | Tên scenario là một business outcome | No — cần người đổi tên |
| R5 | Khai báo WHAT, không phải mệnh lệnh HOW | No — cần viết lại |
| R6 | `Then` khẳng định business outcome quan sát được | No — cần thiết kế lại |
| R7 | Giá trị cụ thể, không phải "valid data" | Yes — thay bằng giá trị thực tế |
| R8 | Mỗi scenario chạy độc lập được | No — cần thiết kế lại |
| R9 | Data table đủ cột cho Then | Yes — thêm cột còn thiếu |
| R10 | Cross-UC reference dùng cách diễn đạt navigation + Note | Yes — thêm comment Note |

→ Vi phạm R3, R7, R9, R10: auto-fixable. Còn lại cần người hướng dẫn qua note Review Board.

### B4 — Compliance Checks (C.1–C.5)

- [ ] C.1 Wireframe Coverage: mỗi component/action của màn hình có ≥1 SC → một finding cho mỗi mục thiếu
- [ ] C.2 PRD Traceability: đã phủ đầy đủ bởi B1 — KHÔNG tạo finding mới ở đây; dedup với finding B1
- [ ] C.3 Term Business Dictionary được dùng → giống B2
- [ ] C.4 Banned Terms: 0 banned term → **critical**, auto-fixable
- [ ] C.5 NHÓM Grouping: nếu ≥3 SC, gom nhóm theo business theme → **major**, auto-fixable

### B5 — Metadata & Structural Check

- [ ] Header file có đủ các field `@trace.*` bắt buộc — kiểm tra từng cái tường minh: `@trace.id`, `@trace.title`, `@trace.revision`, `@trace.domain`, `@trace.service`, `@trace.module`, `@trace.status`, `@trace.author`, `@trace.created_at`, `@trace.prd`, `@trace.prd_version`, `@trace.bdd_version`, `@trace.business_rules`, `@trace.dataset` → **minor** cho mỗi field thiếu, auto-fixable
  - Lưu ý: `@trace.revision` luôn là `1` (field tĩnh — xem generate-bdd.tmpl). Chỉ kiểm tra có mặt; KHÔNG gắn cờ giá trị là stale.
- [ ] Mỗi scenario có `# @trace.scenario`, `# @trace.sc_version`, `# @trace.business_rules`, `# Side-effects:` → **minor**, auto-fixable
- [ ] Coverage Matrix ở cuối file → **major**, auto-fixable (AI sinh lại)
- [ ] Pre-merge Checklist ở cuối file → **minor**, auto-fixable

### B6 — Side-effect Completeness

Với mỗi scenario `@happy`:
- Comment `# Side-effects:` liệt kê tất cả side effect quan sát được
- Block `Then` có `And <side-effect>` cho mỗi side effect đã liệt kê

→ Thiếu assertion side-effect: **major**, auto-fixable.

---

## Ghi File Findings

Sau khi chạy hết các check, ghi `{paths.refinement_dir}/{slug}-review-*-findings.yaml`:

```yaml
source_file: "{absolute path to reviewed file}"
source_version: "{version target lúc sinh findings — PRD: Metadata Version; BDD: @trace.bdd_version — dùng chọn full/delta lần chạy sau}"
applied_to_version: ""   # để trống lúc phân tích; --fix/--resume sẽ ghi version target vừa bump tới. Lần delta sau: nếu version target hiện tại ≠ giá trị này → target bị actor khác sửa → fallback FULL (xem "Chọn full vs delta")
generated_at: "{ISO datetime}"
review_type: "{prd | bdd}"
status: "pending_review"

findings:
  - id: "F001"
    check_id: "P1"           # P1-P5 cho PRD; B1-B6 cho BDD
    severity: "critical"     # critical | major | minor
    section: "{section hoặc scenario ID nơi tìm thấy lỗi}"
    uc_id: "{UC-ID mà finding này thuộc về — PRD: UC heading; BDD: @trace.id; \"\" nếu global}"
    quote: "{trích đoạn nguyên văn copy CHÍNH XÁC từ file đang review tại vị trí lỗi, ≤120 ký tự}"
    finding: "{mô tả rõ ràng vấn đề}"
    suggestion: "{bản fix cụ thể, hành động được — AI sẽ áp dụng khi --resume nếu được chấp nhận}"
    auto_fixable: true       # true = AI áp dụng được; false = người phải viết note trong Review Board
    status: "pending"        # pending | accepted | modified | rejected | needs_discussion | deferred | applied (vòng đời chung — xem chú thích dưới)
    applied_via: ""          # set khi status='applied': "fix" (auto qua --fix) | "resume" (người duyệt qua --resume)

summary:
  total_findings: {N}
  by_severity: { critical: {N}, major: {N}, minor: {N} }
  auto_fixable: {N}
  requires_human_decision: {N}
  recommendation: "APPROVED | NEEDS_REVISION | BLOCKED"
```

> **Vòng đời finding-level (CHUNG với `/refine-prd` — một Review Board đọc cả hai loại file nên enum phải khớp):**
> - `pending` → mới, chưa review
> - `accepted` → nhận suggestion gốc → `--resume` sẽ áp
> - `modified` → người đã sửa suggestion trong Review Board → `--resume` dùng bản đã sửa
> - `rejected` → bác bỏ, không áp
> - `needs_discussion` → xung đột/chưa ngã ngũ → **chặn** `--resume` (bỏ qua + cảnh báo) tới khi người quyết
> - `deferred` → cố ý hoãn (không chặn), bỏ qua lượt này, xem lại sau
> - `applied` → đã áp vào target; `applied_via` ghi cách áp: `"fix"` (auto qua `--fix`) hoặc `"resume"` (người duyệt qua `--resume`)

> **Field định vị (`quote` + `uc_id`) — bắt buộc cho source-jump của Review Board.**
> Với mỗi finding, copy một đoạn `quote` **nguyên văn** thẳng từ file đang review tại đúng
> chỗ lỗi xảy ra — KHÔNG diễn giải lại; nó được so khớp với tài liệu để định vị dòng.
> Đặt `uc_id` là Use Case sở hữu (`@trace.id` cho BDD, UC heading cho PRD; `""` nếu global).
> Hai field này cho phép reviewer click một finding trong Review Board và nhảy tới đúng vị trí nguồn.

## Định tuyến sau phân tích (Post-Analysis Routing)

Sau khi chạy hết các check và ghi file findings:

**Nếu có flag `--fix`** → nhảy tới Fix Mode (áp dụng ngay các finding `auto_fixable: true`).

**Nếu không có flag** → in Report bên dưới và dừng.

## Report

{{include:steps/report-footer.md}}

```
/review-context Hoàn tất — {target file}
Mode: {PRD | BDD}
Findings: {total} | 🔴 Critical: {N} | 🟡 Major: {N} | 🟢 Minor: {N}
Auto-fixable: {N} | Needs human decision: {N}

File findings:
  {If PRD}: {paths.refinement_dir}/{prd-slug}-review-context-findings.yaml
  {If BDD}: {paths.refinement_dir}/{uc-id}-{platform}-review-bdd-findings.yaml

Lựa chọn tiếp theo:
  A) Quick fix  : /review-context --fix {target-file}
                  → áp dụng ngay mọi finding auto-fixable
  B) Review Board: mở file findings → accept/modify/reject
                  → /review-context --resume {target-file}

  {CHỈ in khối này khi 0 finding critical còn lại — còn critical thì nhắc duyệt là vô nghĩa}:
  {If PRD}: ✅ PRD đã sạch critical. Khi PO hài lòng → đặt `| **Status** | approved |` trong
            Metadata PRD (dấu duyệt nghiệp vụ, do người quyết) → rồi /generate-bdd.
  {If BDD}: ✅ BDD đã sạch critical. Sau khi review xong → đặt `# @trace.status: approved` trong
            header file .feature (dấu duyệt BDD, do người quyết) → rồi /generate-tech-docs.
```

---

## Fix Mode — Áp dụng ngay các Finding Auto-Fixable

*Kích hoạt khi `$ARGUMENTS` chứa `--fix`.*
*Ví dụ: `/review-context --fix specs/payment/process-payment/bdd/PAY-001.feature`*

Mode này chạy toàn bộ phân tích (giống mặc định), rồi áp dụng ngay mọi finding
`auto_fixable: true` mà không qua Review Board.

Dùng cho: dọn BDD, fix thuật ngữ, gap metadata — bất cứ thứ gì AI có thể sửa an toàn
mà không cần phán đoán của con người. Finding cần quyết định của con người vẫn được ghi
vào file findings như thường và để `status: pending`.

### Phase 1 — Chạy phân tích

Chạy hết các check qua **Quy trình Review** (fan-out + completeness loop) đúng như mode mặc định.
Ghi file findings với tất cả `status: "pending"` như thường.

### Phase 2 — Áp dụng các finding auto-fixable

Với mỗi finding có `auto_fixable: true`, theo thứ tự (critical → major → minor):

**Với file PRD:**

| check_id | Áp dụng gì |
|----------|--------------|
| P1 (Banned term) | Thay mọi lần xuất hiện banned term bằng canonical term |
| P1 (Thuật ngữ kỹ thuật/UI) | Diễn đạt lại theo Business Language Guard (Nhóm 1) / chuyển Design Spec (2) / bỏ về Tech Docs (3) |
| P4 (Structure) | Thêm skeleton section/metadata còn thiếu (row Status vắng → thêm mặc định `draft`); greenfield → xoá section "Existing API Contract" rỗng |

> **Chạy Business Language Guard trên text vừa sửa TRƯỚC khi ghi** (xem section "Ngôn ngữ nghiệp vụ") — không để bản auto-fix tự kéo thuật ngữ kỹ thuật vào.

**Với file BDD:**

| check_id | Áp dụng gì |
|----------|--------------|
| B2 (Terminology) | Thay banned term, fix tên entity/field, fix sample data kỹ thuật |
| B3 R3 | Thay tech term/UI selector bằng cách diễn đạt nghiệp vụ |
| B3 R7 | Thay bằng giá trị thực tế cụ thể |
| B3 R9 | Thêm cột data table còn thiếu |
| B3 R10 | Thêm comment Note navigation cross-UC |
| B4 C4 | Fix banned term trong tag |
| B4 C5 | Thêm NHÓM grouping nếu ≥3 SC |
| B5 | Thêm @trace header còn thiếu, sinh lại Coverage Matrix / Pre-merge Checklist |
| B6 | Thêm `And <side-effect>` còn thiếu vào block Then |

Sau khi áp dụng mỗi finding, đánh dấu nó `status: "applied"` + `applied_via: "fix"` trong file findings.

### Phase 3 — Version bump

- **PRD**: nếu ≥1 finding được áp dụng → bump version **minor** (auto-fix chỉ áp dụng thay banned-term P1 và thêm skeleton P4 — không bao giờ thay đổi cấu trúc UC hay nội dung BR, nên minor bump luôn đúng), **reset `| **Status** | draft |` trong Metadata** (PRD vừa đổi sau khi duyệt → con dấu duyệt cũ hết hiệu lực, phải duyệt lại — đồng bộ với /refine-prd), thêm entry Changelog:
  `| {new_version} | {today} | Auto-fix: applied {N} auto-fixable findings |` — bảng phẳng + **rollover giữ 5 row gần nhất** (dồn dư sang `changelog/{TICKET-ID}-{prd-slug}.changelog.md`); xem quy ước đầy đủ ở refine-prd Phase 3.
- **BDD**: nếu ≥1 finding được áp dụng → tăng `@trace.bdd_version` lên 0.1, **reset `# @trace.status: draft`** trong header (BDD đổi sau khi duyệt → phải duyệt lại — đồng bộ với cơ chế reset draft của PRD)
- **Cả hai**: ghi `applied_to_version: "{version vừa bump tới}"` ở root level của findings — đóng dấu "target đổi tới version này là do lệnh này áp", để lần review delta sau phân biệt thay đổi của chính mình với thay đổi do actor khác (xem "Chọn full vs delta").

### Phase 4 — Report

```
/review-context --fix Đã áp dụng — {target file}
Mode: {PRD | BDD}

Auto-fixed : {N} findings ({critical} critical, {major} major, {minor} minor)
  - {tóm tắt change 1}
  - {tóm tắt change 2}

Còn pending (cần quyết định của con người): {N}
  - F00X [{severity}] {tóm tắt finding}  ← mở file findings trong Review Board

{If PRD}: Version bumped: {old} → {new}  |  Status: reset về draft (cần duyệt lại)
{If BDD}: bdd_version: {old} → {new}  |  @trace.status: reset về draft (cần duyệt lại)

File findings:
  {If PRD}: {paths.refinement_dir}/{prd-slug}-review-context-findings.yaml
  {If BDD}: {paths.refinement_dir}/{uc-id}-{platform}-review-bdd-findings.yaml
Chạy lại /review-context {file} để xác nhận 0 finding critical còn lại.
{If PRD}: Khi sạch critical + PO duyệt → đặt | **Status** | approved | trong Metadata rồi /generate-bdd.
{If BDD}: Khi sạch critical + duyệt → đặt # @trace.status: approved trong header .feature rồi /generate-tech-docs.
```

Nếu 0 finding nào auto-fixable → in:
```
Không có gì để auto-fix. Cả {N} finding đều cần quyết định của con người.
Mở file findings trong Review Board → rồi chạy: /review-context --resume {file}
```

---

## Resume Mode — Áp dụng các Finding được chấp nhận

*Kích hoạt khi `$ARGUMENTS` chứa `--resume`.*
*Ví dụ: `/review-context --resume specs/payment/process-payment/PAY01-process-payment.md`*

### Phase 1 — Đọc các finding được chấp nhận

1. Suy ra tên file findings từ target file dùng cùng quy tắc như Detect Review Mode:
   - PRD: `{paths.refinement_dir}/{prd-slug}-review-context-findings.yaml`
   - BDD: `{paths.refinement_dir}/{uc-id}-{platform}-review-bdd-findings.yaml` (`{platform}` = `@trace.platform` header `.feature`)
2. Đọc file findings.
3. Gom các finding có `status: "accepted"` hoặc `status: "modified"`. Bỏ qua `rejected`/`deferred`.
4. Nếu không có → báo "No accepted findings. File unchanged." và dừng.
5. Nếu còn finding `status: "needs_discussion"` → cảnh báo (không dừng): `"⚠️  {N} finding chưa ngã ngũ (needs_discussion) — bỏ qua lần áp này; giải quyết trong Review Board rồi --resume lại."`

### Phase 2 — Áp dụng fix

Áp dụng theo thứ tự: critical → major → minor.

Với mỗi finding `accepted`/`modified` sau khi áp xong → đặt `status: "applied"` + `applied_via: "resume"` trong findings (hoàn tất vòng đời, cùng quy ước với `--fix` và `/refine-prd`).

> **Chạy Business Language Guard trên text vừa sửa TRƯỚC khi ghi** (xem section "Ngôn ngữ nghiệp vụ") — đặc biệt với P2 (sửa câu mơ hồ) / P4 skeleton: không để bản fix tự kéo thuật ngữ kỹ thuật-UI vào PRD.

> **Giữ ĐÚNG TẦNG + gọn khi áp fix (altitude):** AC = outcome quan sát được + ref BR, KHÔNG chứa cơ chế. Fix là **chi tiết cơ chế/rule** (retry, timeout, tên/chủ cờ, nhánh lỗi) → **di dời vào bảng BR/BL của UC** (hoặc BR mới), AC chỉ ref; KHÔNG inline vào AC. Fix làm rõ ≥2 nhánh ở đúng tầng → **tách bullet con** hoặc AC/BR mới, đừng nối mệnh đề vào câu cũ. Đừng để AC lặp lại nội dung BR.

**Với finding PRD:**
| check_id | Làm gì |
|----------|-----------|
| P1 (Banned term) | Thay banned term bằng canonical; thuật ngữ kỹ thuật/UI → diễn đạt lại theo Business Language Guard |
| P2 (Ambiguity) | Áp dụng fix nêu trong `suggestion` hoặc note `modified` |
| P3 (Conflict) | Áp dụng cách giải quyết nêu trong note modified |
| P4 (Structure) | Thêm section/metadata field còn thiếu (row Status vắng → thêm mặc định `draft`) |
| P5 (Custom) | Áp dụng như nêu trong suggestion/note |

→ Sau khi áp dụng, bump version PRD (minor), **reset `| **Status** | draft |` trong Metadata** (PRD vừa đổi sau khi duyệt → phải duyệt lại — đồng bộ với /refine-prd), thêm row Changelog (bảng phẳng, **kê UC/AC/BR bị ảnh hưởng**, + **rollover giữ 5 row gần nhất** dồn dư sang `changelog/` — xem quy ước ở refine-prd Phase 3), và ghi `applied_to_version: "{new_version}"` ở root level của findings (xem "Chọn full vs delta").

**Với finding BDD:**
| check_id | Làm gì |
|----------|-----------|
| B1 (Coverage gap) | Sinh scenario mới cho AC/BR chưa phủ và chèn vào đúng NHÓM |
| B2 (Terminology) | Thay banned term, fix tên entity/field |
| B3 (Gherkin rule) | Áp dụng fix theo từng rule (thay tech term, thêm giá trị cụ thể, v.v.) |
| B4 (Compliance) | Thêm NHÓM grouping, fix tag @trace |
| B5 (Metadata) | Thêm @trace header còn thiếu, sinh lại Coverage Matrix / Pre-merge Checklist |
| B6 (Side effects) | Thêm `And <side-effect>` còn thiếu vào block Then |

→ Sau khi áp dụng, tăng `@trace.bdd_version` trong header file lên 0.1, **reset `# @trace.status: draft`** trong header (BDD đổi sau khi duyệt → phải duyệt lại).
→ Đồng thời cập nhật **sổ của platform đang review** `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{@trace.platform}.tsv` (platform lấy từ header `.feature` đang review): đặt cột `bdd_version` thành giá trị `@trace.bdd_version` mới cho mọi row (của sổ này), đặt `uc_status = draft` (khớp header), và đặt `last_updated` thành ngày hôm nay.
→ Ghi `applied_to_version: "{@trace.bdd_version mới}"` ở root level của findings (xem "Chọn full vs delta").

### Phase 3 — Report

```
/review-context --resume Đã áp dụng — {target file}
Applied  : {N} findings ({critical} critical, {major} major, {minor} minor)
Skipped  : {N} rejected/deferred/needs_discussion

Changes:
  - {tóm tắt change 1}
  - {tóm tắt change 2}

{If PRD}: Version bumped: {old} → {new}  |  Status: reset về draft (cần duyệt lại)
{If BDD}: bdd_version: {old} → {new}  |  @trace.status: reset về draft (cần duyệt lại)

Chạy lại /review-context {file} để xác nhận 0 finding critical còn lại.
{If PRD}: Khi sạch critical + PO duyệt → đặt | **Status** | approved | trong Metadata rồi /generate-bdd.
{If BDD}: Khi sạch critical + duyệt → đặt # @trace.status: approved trong header .feature rồi /generate-tech-docs.
```
