@edupia-tutor/spec-driven-docs 0.14.5 → 0.14.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/bin/index.js +1 -1
  2. package/commands/debug.md +1 -1
  3. package/commands/define-product.md +1 -1
  4. package/commands/dev-gen-test.md +1 -1
  5. package/commands/dev-run-test.md +1 -1
  6. package/commands/dev-smoke-test.md +1 -1
  7. package/commands/fix-bug.md +1 -1
  8. package/commands/generate-bdd.md +16 -2
  9. package/commands/generate-bdd.tmpl +15 -1
  10. package/commands/generate-code.md +1 -1
  11. package/commands/generate-design-spec.md +15 -1
  12. package/commands/generate-design-spec.tmpl +14 -0
  13. package/commands/generate-prd.md +2 -1
  14. package/commands/generate-prd.tmpl +1 -0
  15. package/commands/generate-spec-manifest.md +1 -1
  16. package/commands/generate-tech-docs.md +1 -1
  17. package/commands/learn.md +1 -1
  18. package/commands/map-testids.md +1 -1
  19. package/commands/propose-scenario.md +1 -1
  20. package/commands/qc-analyze.md +1 -1
  21. package/commands/qc-design-test.md +1 -1
  22. package/commands/qc-plan.md +1 -1
  23. package/commands/qc-report.md +1 -1
  24. package/commands/qc-review.md +1 -1
  25. package/commands/qc-run-test.md +1 -1
  26. package/commands/refine-prd.md +19 -10
  27. package/commands/refine-prd.tmpl +18 -9
  28. package/commands/report-bug.md +1 -1
  29. package/commands/review-code.md +1 -1
  30. package/commands/review-context.md +124 -34
  31. package/commands/review-context.tmpl +87 -33
  32. package/commands/review-tech-docs.md +1 -1
  33. package/commands/setup-ai-first.md +10 -10
  34. package/commands/setup-ai-first.tmpl +9 -9
  35. package/commands/sync.md +1 -1
  36. package/commands/update-framework.md +1 -1
  37. package/commands/validate-traces.md +1 -1
  38. package/core/FRAMEWORK_VERSION +1 -1
  39. package/core/commands/debug.md +1 -1
  40. package/core/commands/define-product.md +1 -1
  41. package/core/commands/dev-gen-test.md +1 -1
  42. package/core/commands/dev-run-test.md +1 -1
  43. package/core/commands/dev-smoke-test.md +1 -1
  44. package/core/commands/fix-bug.md +1 -1
  45. package/core/commands/generate-bdd.md +16 -2
  46. package/core/commands/generate-code.md +1 -1
  47. package/core/commands/generate-design-spec.md +15 -1
  48. package/core/commands/generate-prd.md +2 -1
  49. package/core/commands/generate-spec-manifest.md +1 -1
  50. package/core/commands/generate-tech-docs.md +1 -1
  51. package/core/commands/learn.md +1 -1
  52. package/core/commands/map-testids.md +1 -1
  53. package/core/commands/propose-scenario.md +1 -1
  54. package/core/commands/qc-analyze.md +1 -1
  55. package/core/commands/qc-design-test.md +1 -1
  56. package/core/commands/qc-plan.md +1 -1
  57. package/core/commands/qc-report.md +1 -1
  58. package/core/commands/qc-review.md +1 -1
  59. package/core/commands/qc-run-test.md +1 -1
  60. package/core/commands/refine-prd.md +19 -10
  61. package/core/commands/report-bug.md +1 -1
  62. package/core/commands/review-code.md +1 -1
  63. package/core/commands/review-context.md +124 -34
  64. package/core/commands/review-tech-docs.md +1 -1
  65. package/core/commands/setup-ai-first.md +10 -10
  66. package/core/commands/sync.md +1 -1
  67. package/core/commands/update-framework.md +1 -1
  68. package/core/commands/validate-traces.md +1 -1
  69. package/core/skills/code/SKILL.md +2 -2
  70. package/core/skills/debug/SKILL.md +3 -3
  71. package/core/skills/design-spec/SKILL.md +1 -1
  72. package/core/skills/prd/SKILL.md +1 -1
  73. package/core/skills/setup-ai-first/SKILL.md +1 -1
  74. package/core/skills/spec/SKILL.md +2 -2
  75. package/core/skills/test/SKILL.md +3 -3
  76. package/core/steps/report-footer.md +1 -1
  77. package/core/templates/project-context.yaml +2 -2
  78. package/docs/01-getting-started/core-concepts.md +1 -1
  79. package/docs/02-guides/developer/bdd-and-trace.md +3 -3
  80. package/docs/02-guides/developer/scenarios.md +2 -2
  81. package/docs/02-guides/developer/workflow.md +1 -1
  82. package/docs/02-guides/product-owner/README.md +2 -2
  83. package/docs/02-guides/product-owner/handoff-checklist.md +5 -5
  84. package/docs/02-guides/product-owner/scenarios.md +19 -17
  85. package/docs/03-concepts/traceability.md +3 -3
  86. package/docs/04-operations/sync-and-update.md +3 -3
  87. package/docs/05-reference/command-cheatsheet.md +1 -1
  88. package/package.json +1 -1
  89. package/skills/code/SKILL.md +2 -2
  90. package/skills/debug/SKILL.md +3 -3
  91. package/skills/design-spec/SKILL.md +1 -1
  92. package/skills/prd/SKILL.md +1 -1
  93. package/skills/setup-ai-first/SKILL.md +1 -1
  94. package/skills/spec/SKILL.md +2 -2
  95. package/skills/test/SKILL.md +3 -3
  96. package/steps/report-footer.md +1 -1
  97. package/templates/project-context.yaml +2 -2
@@ -410,6 +410,47 @@ Sau khi hoàn thành tất cả các bước, bạn đã nạp:
410
410
  Tiếp tục sang bước kế tiếp của lệnh đang gọi.
411
411
 
412
412
 
413
+ ---
414
+
415
+ ## Ngôn ngữ nghiệp vụ *(áp khi viết — Fix Mode & Resume Mode)*
416
+ # Business Language Guard — chặn thuật ngữ kỹ thuật rò vào tài liệu nghiệp vụ
417
+
418
+ Tài liệu nghiệp vụ (PRD, product-definition) mô tả **WHAT** — chỉ ngôn ngữ nghiệp vụ. Guard này chạy **mỗi khi viết hoặc sửa** prose (gen mới, áp fix `--resume`, hiệu chỉnh): **quét và xử lý** các thuật ngữ kỹ thuật/UI phổ thông bên dưới **trước khi ghi**.
419
+
420
+ > Guard này là **baseline framework**, chạy **song song** với Banned Terms của `business-dictionary.md` (cơ chế dictionary giữ nguyên; project vẫn bổ sung term đặc thù vào đó). Khi cả hai cùng áp, ưu tiên bản chuẩn của dictionary nếu có.
421
+
422
+ ## Bản đồ xử lý (3 nhóm)
423
+
424
+ **Nhóm 1 — Tương tác/triển khai → DIỄN ĐẠT LẠI sang nghiệp vụ (giữ nguyên nghĩa):**
425
+
426
+ | Kỹ thuật/UI | Cách nói nghiệp vụ |
427
+ |---|---|
428
+ | re-render / render lại / reload / refresh (màn) | "hiển thị lại {tên màn}" |
429
+ | timeout | "quá thời gian chờ" |
430
+ | lỗi mạng / network error | "lỗi kết nối" |
431
+ | UI / giao diện (khi chỉ một màn) | "màn" / "màn hình" |
432
+ | click / tap | "bấm" / "chọn" |
433
+ | popup / modal (nếu chỉ là khái niệm hiển thị) | "hộp thoại" / "thông báo" |
434
+ | disable / enable (nút) | "khoá" / "mở" thao tác |
435
+ | redirect / navigate | "chuyển tới {màn}" |
436
+
437
+ **Nhóm 2 — Visual thuần → CHUYỂN Design Spec (bỏ khỏi PRD, ghi nhận lại):**
438
+ `spinner`, `loading indicator`, `animation`, `fade/slide`, màu sắc, font, layout pixel, micro-interaction → *"Chi tiết visual này thuộc Design Spec — ghi nhận để tạo Design Spec sau."*
439
+
440
+ **Nhóm 3 — Backend/contract thuần → BỎ khỏi PRD (thuộc Tech Docs):**
441
+ `API`, `endpoint`, `token/JWT`, `HTTP status`, tên class/bảng/cột DB, query, payload, header.
442
+ *(Ngoại lệ DUY NHẤT: Appendix "Existing API Contract" khi `API Source: existing` — xem Platform Strategy.)*
443
+
444
+ ## Quy tắc áp dụng
445
+ - Quét toàn bộ text sắp ghi (User Story, AC, BR, Business Logic, Scope, Edge Cases, Assumptions…).
446
+ - Nhóm 1 → thay tại chỗ, giữ nguyên nghĩa nghiệp vụ. **Đồng bộ cách diễn đạt** với chỗ đã có sẵn trong cùng tài liệu (vd nếu "quá thời gian chờ" đã dùng ở một BR → dùng nhất quán ở mọi nơi).
447
+ - Nhóm 2 → gỡ khỏi prose nghiệp vụ + nhắc chuyển Design Spec.
448
+ - Nhóm 3 → gỡ khỏi PRD (trừ ngoại lệ brownfield).
449
+ - Nếu term không có trong bản đồ nhưng rõ ràng là tên kỹ thuật/triển khai → vẫn diễn đạt lại theo tinh thần Nhóm 1, đừng để lọt.
450
+
451
+ **Checklist (dùng ở Quality Checklist của lệnh):** 0 thuật ngữ kỹ thuật/UI (re-render, UI, timeout, spinner, API/endpoint/token…) trong prose nghiệp vụ — đã diễn đạt lại (Nhóm 1) / chuyển Design Spec (Nhóm 2) / bỏ về Tech Docs (Nhóm 3).
452
+
453
+
413
454
  ---
414
455
 
415
456
  ## Phát hiện Review Mode
@@ -589,6 +630,21 @@ Convergence: {convergence_rounds} vòng critic — file findings đã đầy đ
589
630
  - **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`.
590
631
  - 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.
591
632
 
633
+ **Tham số truyền vào Quy trình Review:**
634
+ - `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).
635
+ - `CHANGED_SCOPE` — theo full/delta dưới đây.
636
+
637
+ **Chọn full vs delta** *(mặc định: lần đầu FULL, lần sau DELTA)*:
638
+ 1. Tách `--full` khỏi `$ARGUMENTS` nếu có.
639
+ 2. Kiểm tra file findings của target (tên suy ở "Phát hiện Review Mode"):
640
+ - **Không tồn tại** (lần đầu) → **FULL**: KHÔNG truyền `CHANGED_SCOPE`.
641
+ - **Tồn tại** + có `--full` → **FULL**: bỏ qua findings cũ.
642
+ - **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`):
643
+ - **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ộ."`
644
+ - **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:
645
+ - **`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ũ }.
646
+ - **`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."`
647
+
592
648
  ---
593
649
 
594
650
  ## PRD Review Mode
@@ -599,33 +655,31 @@ Convergence: {convergence_rounds} vòng critic — file findings đã đầy đ
599
655
 
600
656
  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**:
601
657
 
602
- **P0.1 — `@trace.domain` mặt**
603
- - Đọc block frontmatter của PRD (các dòng bắt đầu bằng `@trace.` ở đầu file)
604
- - Nếu `@trace.domain` **vắng mặt** finding **critical**:
605
- - `finding`: "`@trace.domain` đang thiếu. Umbrella routing của team dev phụ thuộc field này để đưa BDD và code output tới đúng service submodule."
606
- - `suggestion`: "Thêm `@trace.domain: {domain}` vào frontmatter của PRD. Dùng một trong các domain key được định nghĩa trong section services của `project-context.yaml` của umbrella."
658
+ > **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.
659
+
660
+ **P0.1 Row `Domain` mặt trong Metadata**
661
+ - Đọc bảng Metadata của PRD, lấy row `| **Domain** |`.
662
+ - Nếu **vắng mặt / để trống** finding **critical**:
663
+ - `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."
664
+ - `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."
607
665
  - `auto_fixable: false` — PO phải confirm tên domain đúng
608
666
 
609
- **P0.2 — `@trace.domain` khớp một service key**
610
- - Nếu `@trace.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
667
+ **P0.2 — `Domain` khớp một service key**
668
+ - 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.
611
669
  - Nếu **không khớp** → finding **critical**:
612
- - `finding`: "`@trace.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ỗ."
613
- - `suggestion`: "Hoặc cập nhật `@trace.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}`."
670
+ - `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ỗ."
671
+ - `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}`."
614
672
  - `auto_fixable: false`
615
673
  - Nếu section `services` chưa được cấu hình (rỗng/placeholder) → finding **major**:
616
674
  - `finding`: "Section `services` của umbrella chưa được cấu hình. Không thể kiểm chứng domain routing."
617
675
  - `suggestion`: "Cập nhật section services trong `.agent/project-context.yaml` với mapping domain-to-submodule trước khi sinh BDD."
618
676
  - `auto_fixable: false`
619
677
 
620
- **P0.3Check `@trace.status`**
621
- - Nếu `@trace.status` vắng mặt → **minor**, `auto_fixable: true` (thêm `@trace.status: draft`)
622
- - Nếu `@trace.status: draft` → **major**, `auto_fixable: false`:
623
- - `finding`: "PRD status là `draft`. Team dev không nên sinh BDD từ một PRD chưa được duyệt."
624
- - `suggestion`: "PO/SA nên review và cập nhật status thành `approved` trước khi team dev tiếp tục."
678
+ > **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`).
625
679
 
626
680
  > **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:
627
681
  > ```
628
- > ⚠️ ROUTING WARNING: phát hiện vấn đề @trace.domain.
682
+ > ⚠️ ROUTING WARNING: phát hiện vấn đề Domain trong Metadata.
629
683
  > BDD/code sinh từ PRD này có thể rơi vào sai service submodule.
630
684
  > Giải quyết các finding P0 trước khi chạy /generate-bdd.
631
685
  > ```
@@ -645,6 +699,9 @@ Quét toàn bộ PRD tìm vấn đề thuật ngữ:
645
699
  3. **Business term chưa liệt kê** — các term quan trọng vắng trong dictionary:
646
700
  → Severity: **minor**. Đề xuất thêm vào `business-dictionary.md`.
647
701
 
702
+ 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:
703
+ → 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).
704
+
648
705
  ### P2 — Ambiguity Check
649
706
 
650
707
  Quét mỗi AC và BR tìm:
@@ -669,13 +726,20 @@ hoặc định nghĩa lại field/status transition của một entity khác đi
669
726
 
670
727
  ### P4 — Structural Completeness
671
728
 
672
- - [ ] Block Metadata: Version, Author, Date, Status
673
- - [ ] Ít nhất 1 UC với heading `#### {TICKET-ID}-UC{N}:`
674
- - [ ] Mỗi UC có: Description, Actors, Preconditions, Acceptance Criteria, Business Rules
675
- - [ ] section `## Changelog`
729
+ Đố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):
730
+
731
+ - [ ] **Metadata** có: Version, Status, Author, Created, Updated, Domain, Ticket (PO nếu có)
732
+ - [ ] **§1c "Phụ thuộc liên service"** có mặt (hoặc ghi rõ "Không có")
733
+ - [ ] **§2 Acceptance Criteria** (global) có mặt; **mỗi AC** kết thúc bằng ref `_(BR: …)_` (≥1 BR)
734
+ - [ ] **≥1 UC** với heading `#### {TICKET-ID}-UC{N}:`
735
+ - [ ] 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 đủ)
736
+ - [ ] **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 đó
737
+ - [ ] **§4 UI/UX**: có User Flow và **Wireframe** (Wireframe lái coverage BDD C.1)
738
+ - [ ] **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)
739
+ - [ ] Có section `# Change Log`
676
740
  - [ ] Không còn giá trị `{{PLACEHOLDER}}` chưa điền
677
741
 
678
- → Section thiếu: **major**. AI có thể thêm skeleton khi `--resume` nếu được chấp nhận.
742
+ → 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).
679
743
 
680
744
  ### P5 — Custom Criteria (tuỳ chọn)
681
745
 
@@ -759,6 +823,8 @@ Sau khi chạy hết các check, ghi `{paths.refinement_dir}/{slug}-review-*-fin
759
823
 
760
824
  ```yaml
761
825
  source_file: "{absolute path to reviewed file}"
826
+ 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}"
827
+ 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")
762
828
  generated_at: "{ISO datetime}"
763
829
  review_type: "{prd | bdd}"
764
830
  status: "pending_review"
@@ -773,7 +839,8 @@ findings:
773
839
  finding: "{mô tả rõ ràng vấn đề}"
774
840
  suggestion: "{bản fix cụ thể, hành động được — AI sẽ áp dụng khi --resume nếu được chấp nhận}"
775
841
  auto_fixable: true # true = AI áp dụng được; false = người phải viết note trong Review Board
776
- status: "pending" # pending | accepted | modified | rejected | deferred
842
+ status: "pending" # pending | accepted | modified | rejected | needs_discussion | deferred | applied (vòng đời chung — xem chú thích dưới)
843
+ applied_via: "" # set khi status='applied': "fix" (auto qua --fix) | "resume" (người duyệt qua --resume)
777
844
 
778
845
  summary:
779
846
  total_findings: {N}
@@ -783,6 +850,15 @@ summary:
783
850
  recommendation: "APPROVED | NEEDS_REVISION | BLOCKED"
784
851
  ```
785
852
 
853
+ > **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):**
854
+ > - `pending` → mới, chưa review
855
+ > - `accepted` → nhận suggestion gốc → `--resume` sẽ áp
856
+ > - `modified` → người đã sửa suggestion trong Review Board → `--resume` dùng bản đã sửa
857
+ > - `rejected` → bác bỏ, không áp
858
+ > - `needs_discussion` → xung đột/chưa ngã ngũ → **chặn** `--resume` (bỏ qua + cảnh báo) tới khi người quyết
859
+ > - `deferred` → cố ý hoãn (không chặn), bỏ qua lượt này, xem lại sau
860
+ > - `applied` → đã áp vào target; `applied_via` ghi cách áp: `"fix"` (auto qua `--fix`) hoặc `"resume"` (người duyệt qua `--resume`)
861
+
786
862
  > **Field định vị (`quote` + `uc_id`) — bắt buộc cho source-jump của Review Board.**
787
863
  > Với mỗi finding, copy một đoạn `quote` **nguyên văn** thẳng từ file đang review tại đúng
788
864
  > 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.
@@ -861,7 +937,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
861
937
  | /define-product | `/generate-prd {product-definition-file}` |
862
938
  | /generate-prd | `/refine-prd {prd-file}` rồi `/review-context {prd-file}` |
863
939
  | /refine-prd | Mở Review Board → cập nhật PRD → `/review-context {prd-file}` |
864
- | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (rồi BDD sau khi sign-off); BE: `/generate-bdd {prd-file}` trực tiếp; sửa PRD nếu NEEDS_FIX |
940
+ | /review-context (PRD) | Khi 0 critical → PO đặt `Status: approved`, rồi FE/App: `/generate-design-spec {prd-file}` ( design sign-off → BDD); BE: `/generate-bdd {prd-file}`. Còn critical/NEEDS_FIX sửa PRD (giữ draft) |
865
941
  | /generate-design-spec | Designer review → xác nhận link Figma → PO + Designer sign-off → `/generate-bdd {prd-file}` |
866
942
  | /generate-bdd | `/review-context {feature-file}` để kiểm tra độ phủ |
867
943
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` nếu APPROVED; sinh lại nếu NEEDS_FIX |
@@ -916,6 +992,10 @@ Lựa chọn tiếp theo:
916
992
  → áp dụng ngay mọi finding auto-fixable
917
993
  B) Review Board: mở file findings → accept/modify/reject
918
994
  → /review-context --resume {target-file}
995
+
996
+ {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}:
997
+ ✅ PRD đã sạch critical. Khi PO hài lòng → đặt `| **Status** | approved |` trong
998
+ Metadata PRD (dấu duyệt nghiệp vụ, do người quyết) → rồi /generate-bdd.
919
999
  ```
920
1000
 
921
1001
  ---
@@ -945,9 +1025,11 @@ Với mỗi finding có `auto_fixable: true`, theo thứ tự (critical → majo
945
1025
 
946
1026
  | check_id | Áp dụng gì |
947
1027
  |----------|--------------|
948
- | P0.3 (Thiếu status) | Thêm `@trace.status: draft` vào frontmatter |
949
1028
  | P1 (Banned term) | Thay mọi lần xuất hiện banned term bằng canonical term |
950
- | P4 (Structure) | Thêm skeleton section/metadata còn thiếu |
1029
+ | 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) |
1030
+ | 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 |
1031
+
1032
+ > **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.
951
1033
 
952
1034
  **Với file BDD:**
953
1035
 
@@ -963,13 +1045,14 @@ Với mỗi finding có `auto_fixable: true`, theo thứ tự (critical → majo
963
1045
  | B5 | Thêm @trace header còn thiếu, sinh lại Coverage Matrix / Pre-merge Checklist |
964
1046
  | B6 | Thêm `And <side-effect>` còn thiếu vào block Then |
965
1047
 
966
- Sau khi áp dụng mỗi finding, đánh dấu nó `status: "applied_automatically"` trong file findings.
1048
+ Sau khi áp dụng mỗi finding, đánh dấu nó `status: "applied"` + `applied_via: "fix"` trong file findings.
967
1049
 
968
1050
  ### Phase 3 — Version bump
969
1051
 
970
- - **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), thêm entry Changelog:
1052
+ - **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:
971
1053
  `Auto-fix: applied {N} auto-fixable review-context findings`
972
1054
  - **BDD**: nếu ≥1 finding được áp dụng → tăng `@trace.bdd_version` lên 0.1
1055
+ - **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").
973
1056
 
974
1057
  ### Phase 4 — Report
975
1058
 
@@ -984,13 +1067,14 @@ Auto-fixed : {N} findings ({critical} critical, {major} major, {minor} minor)
984
1067
  Còn pending (cần quyết định của con người): {N}
985
1068
  - F00X [{severity}] {tóm tắt finding} ← mở file findings trong Review Board
986
1069
 
987
- {If PRD}: Version bumped: {old} → {new}
1070
+ {If PRD}: Version bumped: {old} → {new} | Status: reset về draft (cần duyệt lại)
988
1071
  {If BDD}: bdd_version: {old} → {new}
989
1072
 
990
1073
  File findings:
991
1074
  {If PRD}: {paths.refinement_dir}/{prd-slug}-review-context-findings.yaml
992
1075
  {If BDD}: {paths.refinement_dir}/{uc-id}-review-bdd-findings.yaml
993
1076
  Chạy lại /review-context {file} để xác nhận 0 finding critical còn lại.
1077
+ Khi sạch critical + PO duyệt → đặt | **Status** | approved | trong Metadata rồi /generate-bdd.
994
1078
  ```
995
1079
 
996
1080
  Nếu 0 finding nào auto-fixable → in:
@@ -1012,24 +1096,28 @@ Mở file findings trong Review Board → rồi chạy: /review-context --resume
1012
1096
  - PRD: `{paths.refinement_dir}/{prd-slug}-review-context-findings.yaml`
1013
1097
  - BDD: `{paths.refinement_dir}/{uc-id}-review-bdd-findings.yaml`
1014
1098
  2. Đọc file findings.
1015
- 3. Gom các finding có `status: "accepted"` hoặc `status: "modified"`.
1099
+ 3. Gom các finding có `status: "accepted"` hoặc `status: "modified"`. Bỏ qua `rejected`/`deferred`.
1016
1100
  4. Nếu không có → báo "No accepted findings. File unchanged." và dừng.
1101
+ 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."`
1017
1102
 
1018
1103
  ### Phase 2 — Áp dụng fix
1019
1104
 
1020
1105
  Áp dụng theo thứ tự: critical → major → minor.
1021
1106
 
1107
+ 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`).
1108
+
1109
+ > **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.
1110
+
1022
1111
  **Với finding PRD:**
1023
1112
  | check_id | Làm gì |
1024
1113
  |----------|-----------|
1025
- | P0.3 (Thiếu status) | Thêm `@trace.status: draft` vào frontmatter |
1026
- | P1 (Banned term) | Thay mọi lần xuất hiện banned term bằng canonical term |
1114
+ | 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 |
1027
1115
  | P2 (Ambiguity) | Áp dụng fix nêu trong `suggestion` hoặc note `modified` |
1028
1116
  | P3 (Conflict) | Áp dụng cách giải quyết nêu trong note modified |
1029
- | P4 (Structure) | Thêm section/metadata field còn thiếu |
1117
+ | P4 (Structure) | Thêm section/metadata field còn thiếu (row Status vắng → thêm mặc định `draft`) |
1030
1118
  | P5 (Custom) | Áp dụng như nêu trong suggestion/note |
1031
1119
 
1032
- → Sau khi áp dụng, bump version PRD (minor) thêm entry Changelog.
1120
+ → 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 entry Changelog, và ghi `applied_to_version: "{new_version}"` ở root level của findings (xem "Chọn full vs delta").
1033
1121
 
1034
1122
  **Với finding BDD:**
1035
1123
  | check_id | Làm gì |
@@ -1043,20 +1131,22 @@ Mở file findings trong Review Board → rồi chạy: /review-context --resume
1043
1131
 
1044
1132
  → Sau khi áp dụng, tăng `@trace.bdd_version` trong header file lên 0.1.
1045
1133
  → Đồng thời cập nhật `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}.tsv`: đặt cột `bdd_version` thành giá trị `@trace.bdd_version` mới cho mọi row, và đặt `last_updated` thành ngày hôm nay.
1134
+ → Ghi `applied_to_version: "{@trace.bdd_version mới}"` ở root level của findings (xem "Chọn full vs delta").
1046
1135
 
1047
1136
  ### Phase 3 — Report
1048
1137
 
1049
1138
  ```
1050
1139
  /review-context --resume Đã áp dụng — {target file}
1051
1140
  Applied : {N} findings ({critical} critical, {major} major, {minor} minor)
1052
- Skipped : {N} rejected/deferred
1141
+ Skipped : {N} rejected/deferred/needs_discussion
1053
1142
 
1054
1143
  Changes:
1055
1144
  - {tóm tắt change 1}
1056
1145
  - {tóm tắt change 2}
1057
1146
 
1058
- {If PRD}: Version bumped: {old} → {new}
1147
+ {If PRD}: Version bumped: {old} → {new} | Status: reset về draft (cần duyệt lại)
1059
1148
  {If BDD}: bdd_version: {old} → {new}
1060
1149
 
1061
1150
  Chạy lại /review-context {file} để xác nhận 0 finding critical còn lại.
1151
+ Khi sạch critical + PO duyệt → đặt | **Status** | approved | trong Metadata rồi /generate-bdd.
1062
1152
  ```
@@ -17,6 +17,11 @@ Nếu `$ARGUMENTS` chứa `--fix` → bỏ qua sang Fix Mode bên dưới (áp d
17
17
 
18
18
  ---
19
19
 
20
+ ## Ngôn ngữ nghiệp vụ *(áp khi viết — Fix Mode & Resume Mode)*
21
+ {{include:steps/business-language.md}}
22
+
23
+ ---
24
+
20
25
  ## Phát hiện Review Mode
21
26
 
22
27
  Sau khi phân giải target file:
@@ -42,6 +47,21 @@ Suy ra tên file findings output:
42
47
  - **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`.
43
48
  - 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.
44
49
 
50
+ **Tham số truyền vào Quy trình Review:**
51
+ - `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).
52
+ - `CHANGED_SCOPE` — theo full/delta dưới đây.
53
+
54
+ **Chọn full vs delta** *(mặc định: lần đầu FULL, lần sau DELTA)*:
55
+ 1. Tách `--full` khỏi `$ARGUMENTS` nếu có.
56
+ 2. Kiểm tra file findings của target (tên suy ở "Phát hiện Review Mode"):
57
+ - **Không tồn tại** (lần đầu) → **FULL**: KHÔNG truyền `CHANGED_SCOPE`.
58
+ - **Tồn tại** + có `--full` → **FULL**: bỏ qua findings cũ.
59
+ - **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`):
60
+ - **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ộ."`
61
+ - **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:
62
+ - **`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ũ }.
63
+ - **`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."`
64
+
45
65
  ---
46
66
 
47
67
  ## PRD Review Mode
@@ -52,33 +72,31 @@ Suy ra tên file findings output:
52
72
 
53
73
  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**:
54
74
 
55
- **P0.1 — `@trace.domain` mặt**
56
- - Đọc block frontmatter của PRD (các dòng bắt đầu bằng `@trace.` ở đầu file)
57
- - Nếu `@trace.domain` **vắng mặt** finding **critical**:
58
- - `finding`: "`@trace.domain` đang thiếu. Umbrella routing của team dev phụ thuộc field này để đưa BDD và code output tới đúng service submodule."
59
- - `suggestion`: "Thêm `@trace.domain: {domain}` vào frontmatter của PRD. Dùng một trong các domain key được định nghĩa trong section services của `project-context.yaml` của umbrella."
75
+ > **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.
76
+
77
+ **P0.1 Row `Domain` mặt trong Metadata**
78
+ - Đọc bảng Metadata của PRD, lấy row `| **Domain** |`.
79
+ - Nếu **vắng mặt / để trống** finding **critical**:
80
+ - `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."
81
+ - `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."
60
82
  - `auto_fixable: false` — PO phải confirm tên domain đúng
61
83
 
62
- **P0.2 — `@trace.domain` khớp một service key**
63
- - Nếu `@trace.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
84
+ **P0.2 — `Domain` khớp một service key**
85
+ - 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.
64
86
  - Nếu **không khớp** → finding **critical**:
65
- - `finding`: "`@trace.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ỗ."
66
- - `suggestion`: "Hoặc cập nhật `@trace.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}`."
87
+ - `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ỗ."
88
+ - `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}`."
67
89
  - `auto_fixable: false`
68
90
  - Nếu section `services` chưa được cấu hình (rỗng/placeholder) → finding **major**:
69
91
  - `finding`: "Section `services` của umbrella chưa được cấu hình. Không thể kiểm chứng domain routing."
70
92
  - `suggestion`: "Cập nhật section services trong `.agent/project-context.yaml` với mapping domain-to-submodule trước khi sinh BDD."
71
93
  - `auto_fixable: false`
72
94
 
73
- **P0.3Check `@trace.status`**
74
- - Nếu `@trace.status` vắng mặt → **minor**, `auto_fixable: true` (thêm `@trace.status: draft`)
75
- - Nếu `@trace.status: draft` → **major**, `auto_fixable: false`:
76
- - `finding`: "PRD status là `draft`. Team dev không nên sinh BDD từ một PRD chưa được duyệt."
77
- - `suggestion`: "PO/SA nên review và cập nhật status thành `approved` trước khi team dev tiếp tục."
95
+ > **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`).
78
96
 
79
97
  > **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:
80
98
  > ```
81
- > ⚠️ ROUTING WARNING: phát hiện vấn đề @trace.domain.
99
+ > ⚠️ ROUTING WARNING: phát hiện vấn đề Domain trong Metadata.
82
100
  > BDD/code sinh từ PRD này có thể rơi vào sai service submodule.
83
101
  > Giải quyết các finding P0 trước khi chạy /generate-bdd.
84
102
  > ```
@@ -98,6 +116,9 @@ Quét toàn bộ PRD tìm vấn đề thuật ngữ:
98
116
  3. **Business term chưa liệt kê** — các term quan trọng vắng trong dictionary:
99
117
  → Severity: **minor**. Đề xuất thêm vào `business-dictionary.md`.
100
118
 
119
+ 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:
120
+ → 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).
121
+
101
122
  ### P2 — Ambiguity Check
102
123
 
103
124
  Quét mỗi AC và BR tìm:
@@ -122,13 +143,20 @@ hoặc định nghĩa lại field/status transition của một entity khác đi
122
143
 
123
144
  ### P4 — Structural Completeness
124
145
 
125
- - [ ] Block Metadata: Version, Author, Date, Status
126
- - [ ] Ít nhất 1 UC với heading `#### {TICKET-ID}-UC{N}:`
127
- - [ ] Mỗi UC có: Description, Actors, Preconditions, Acceptance Criteria, Business Rules
128
- - [ ] section `## Changelog`
146
+ Đố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):
147
+
148
+ - [ ] **Metadata** có: Version, Status, Author, Created, Updated, Domain, Ticket (PO nếu có)
149
+ - [ ] **§1c "Phụ thuộc liên service"** có mặt (hoặc ghi rõ "Không có")
150
+ - [ ] **§2 Acceptance Criteria** (global) có mặt; **mỗi AC** kết thúc bằng ref `_(BR: …)_` (≥1 BR)
151
+ - [ ] **≥1 UC** với heading `#### {TICKET-ID}-UC{N}:`
152
+ - [ ] 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 đủ)
153
+ - [ ] **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 đó
154
+ - [ ] **§4 UI/UX**: có User Flow và **Wireframe** (Wireframe lái coverage BDD C.1)
155
+ - [ ] **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)
156
+ - [ ] Có section `# Change Log`
129
157
  - [ ] Không còn giá trị `{{PLACEHOLDER}}` chưa điền
130
158
 
131
- → Section thiếu: **major**. AI có thể thêm skeleton khi `--resume` nếu được chấp nhận.
159
+ → 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).
132
160
 
133
161
  ### P5 — Custom Criteria (tuỳ chọn)
134
162
 
@@ -212,6 +240,8 @@ Sau khi chạy hết các check, ghi `{paths.refinement_dir}/{slug}-review-*-fin
212
240
 
213
241
  ```yaml
214
242
  source_file: "{absolute path to reviewed file}"
243
+ 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}"
244
+ 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")
215
245
  generated_at: "{ISO datetime}"
216
246
  review_type: "{prd | bdd}"
217
247
  status: "pending_review"
@@ -226,7 +256,8 @@ findings:
226
256
  finding: "{mô tả rõ ràng vấn đề}"
227
257
  suggestion: "{bản fix cụ thể, hành động được — AI sẽ áp dụng khi --resume nếu được chấp nhận}"
228
258
  auto_fixable: true # true = AI áp dụng được; false = người phải viết note trong Review Board
229
- status: "pending" # pending | accepted | modified | rejected | deferred
259
+ status: "pending" # pending | accepted | modified | rejected | needs_discussion | deferred | applied (vòng đời chung — xem chú thích dưới)
260
+ applied_via: "" # set khi status='applied': "fix" (auto qua --fix) | "resume" (người duyệt qua --resume)
230
261
 
231
262
  summary:
232
263
  total_findings: {N}
@@ -236,6 +267,15 @@ summary:
236
267
  recommendation: "APPROVED | NEEDS_REVISION | BLOCKED"
237
268
  ```
238
269
 
270
+ > **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):**
271
+ > - `pending` → mới, chưa review
272
+ > - `accepted` → nhận suggestion gốc → `--resume` sẽ áp
273
+ > - `modified` → người đã sửa suggestion trong Review Board → `--resume` dùng bản đã sửa
274
+ > - `rejected` → bác bỏ, không áp
275
+ > - `needs_discussion` → xung đột/chưa ngã ngũ → **chặn** `--resume` (bỏ qua + cảnh báo) tới khi người quyết
276
+ > - `deferred` → cố ý hoãn (không chặn), bỏ qua lượt này, xem lại sau
277
+ > - `applied` → đã áp vào target; `applied_via` ghi cách áp: `"fix"` (auto qua `--fix`) hoặc `"resume"` (người duyệt qua `--resume`)
278
+
239
279
  > **Field định vị (`quote` + `uc_id`) — bắt buộc cho source-jump của Review Board.**
240
280
  > Với mỗi finding, copy một đoạn `quote` **nguyên văn** thẳng từ file đang review tại đúng
241
281
  > 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.
@@ -269,6 +309,10 @@ Lựa chọn tiếp theo:
269
309
  → áp dụng ngay mọi finding auto-fixable
270
310
  B) Review Board: mở file findings → accept/modify/reject
271
311
  → /review-context --resume {target-file}
312
+
313
+ {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}:
314
+ ✅ PRD đã sạch critical. Khi PO hài lòng → đặt `| **Status** | approved |` trong
315
+ Metadata PRD (dấu duyệt nghiệp vụ, do người quyết) → rồi /generate-bdd.
272
316
  ```
273
317
 
274
318
  ---
@@ -298,9 +342,11 @@ Với mỗi finding có `auto_fixable: true`, theo thứ tự (critical → majo
298
342
 
299
343
  | check_id | Áp dụng gì |
300
344
  |----------|--------------|
301
- | P0.3 (Thiếu status) | Thêm `@trace.status: draft` vào frontmatter |
302
345
  | P1 (Banned term) | Thay mọi lần xuất hiện banned term bằng canonical term |
303
- | P4 (Structure) | Thêm skeleton section/metadata còn thiếu |
346
+ | 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) |
347
+ | 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 |
348
+
349
+ > **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.
304
350
 
305
351
  **Với file BDD:**
306
352
 
@@ -316,13 +362,14 @@ Với mỗi finding có `auto_fixable: true`, theo thứ tự (critical → majo
316
362
  | B5 | Thêm @trace header còn thiếu, sinh lại Coverage Matrix / Pre-merge Checklist |
317
363
  | B6 | Thêm `And <side-effect>` còn thiếu vào block Then |
318
364
 
319
- Sau khi áp dụng mỗi finding, đánh dấu nó `status: "applied_automatically"` trong file findings.
365
+ Sau khi áp dụng mỗi finding, đánh dấu nó `status: "applied"` + `applied_via: "fix"` trong file findings.
320
366
 
321
367
  ### Phase 3 — Version bump
322
368
 
323
- - **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), thêm entry Changelog:
369
+ - **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:
324
370
  `Auto-fix: applied {N} auto-fixable review-context findings`
325
371
  - **BDD**: nếu ≥1 finding được áp dụng → tăng `@trace.bdd_version` lên 0.1
372
+ - **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").
326
373
 
327
374
  ### Phase 4 — Report
328
375
 
@@ -337,13 +384,14 @@ Auto-fixed : {N} findings ({critical} critical, {major} major, {minor} minor)
337
384
  Còn pending (cần quyết định của con người): {N}
338
385
  - F00X [{severity}] {tóm tắt finding} ← mở file findings trong Review Board
339
386
 
340
- {If PRD}: Version bumped: {old} → {new}
387
+ {If PRD}: Version bumped: {old} → {new} | Status: reset về draft (cần duyệt lại)
341
388
  {If BDD}: bdd_version: {old} → {new}
342
389
 
343
390
  File findings:
344
391
  {If PRD}: {paths.refinement_dir}/{prd-slug}-review-context-findings.yaml
345
392
  {If BDD}: {paths.refinement_dir}/{uc-id}-review-bdd-findings.yaml
346
393
  Chạy lại /review-context {file} để xác nhận 0 finding critical còn lại.
394
+ Khi sạch critical + PO duyệt → đặt | **Status** | approved | trong Metadata rồi /generate-bdd.
347
395
  ```
348
396
 
349
397
  Nếu 0 finding nào auto-fixable → in:
@@ -365,24 +413,28 @@ Mở file findings trong Review Board → rồi chạy: /review-context --resume
365
413
  - PRD: `{paths.refinement_dir}/{prd-slug}-review-context-findings.yaml`
366
414
  - BDD: `{paths.refinement_dir}/{uc-id}-review-bdd-findings.yaml`
367
415
  2. Đọc file findings.
368
- 3. Gom các finding có `status: "accepted"` hoặc `status: "modified"`.
416
+ 3. Gom các finding có `status: "accepted"` hoặc `status: "modified"`. Bỏ qua `rejected`/`deferred`.
369
417
  4. Nếu không có → báo "No accepted findings. File unchanged." và dừng.
418
+ 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."`
370
419
 
371
420
  ### Phase 2 — Áp dụng fix
372
421
 
373
422
  Áp dụng theo thứ tự: critical → major → minor.
374
423
 
424
+ 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`).
425
+
426
+ > **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.
427
+
375
428
  **Với finding PRD:**
376
429
  | check_id | Làm gì |
377
430
  |----------|-----------|
378
- | P0.3 (Thiếu status) | Thêm `@trace.status: draft` vào frontmatter |
379
- | P1 (Banned term) | Thay mọi lần xuất hiện banned term bằng canonical term |
431
+ | 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 |
380
432
  | P2 (Ambiguity) | Áp dụng fix nêu trong `suggestion` hoặc note `modified` |
381
433
  | P3 (Conflict) | Áp dụng cách giải quyết nêu trong note modified |
382
- | P4 (Structure) | Thêm section/metadata field còn thiếu |
434
+ | P4 (Structure) | Thêm section/metadata field còn thiếu (row Status vắng → thêm mặc định `draft`) |
383
435
  | P5 (Custom) | Áp dụng như nêu trong suggestion/note |
384
436
 
385
- → Sau khi áp dụng, bump version PRD (minor) thêm entry Changelog.
437
+ → 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 entry Changelog, và ghi `applied_to_version: "{new_version}"` ở root level của findings (xem "Chọn full vs delta").
386
438
 
387
439
  **Với finding BDD:**
388
440
  | check_id | Làm gì |
@@ -396,20 +448,22 @@ Mở file findings trong Review Board → rồi chạy: /review-context --resume
396
448
 
397
449
  → Sau khi áp dụng, tăng `@trace.bdd_version` trong header file lên 0.1.
398
450
  → Đồng thời cập nhật `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}.tsv`: đặt cột `bdd_version` thành giá trị `@trace.bdd_version` mới cho mọi row, và đặt `last_updated` thành ngày hôm nay.
451
+ → Ghi `applied_to_version: "{@trace.bdd_version mới}"` ở root level của findings (xem "Chọn full vs delta").
399
452
 
400
453
  ### Phase 3 — Report
401
454
 
402
455
  ```
403
456
  /review-context --resume Đã áp dụng — {target file}
404
457
  Applied : {N} findings ({critical} critical, {major} major, {minor} minor)
405
- Skipped : {N} rejected/deferred
458
+ Skipped : {N} rejected/deferred/needs_discussion
406
459
 
407
460
  Changes:
408
461
  - {tóm tắt change 1}
409
462
  - {tóm tắt change 2}
410
463
 
411
- {If PRD}: Version bumped: {old} → {new}
464
+ {If PRD}: Version bumped: {old} → {new} | Status: reset về draft (cần duyệt lại)
412
465
  {If BDD}: bdd_version: {old} → {new}
413
466
 
414
467
  Chạy lại /review-context {file} để xác nhận 0 finding critical còn lại.
468
+ Khi sạch critical + PO duyệt → đặt | **Status** | approved | trong Metadata rồi /generate-bdd.
415
469
  ```
@@ -682,7 +682,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
682
682
  | /define-product | `/generate-prd {product-definition-file}` |
683
683
  | /generate-prd | `/refine-prd {prd-file}` rồi `/review-context {prd-file}` |
684
684
  | /refine-prd | Mở Review Board → cập nhật PRD → `/review-context {prd-file}` |
685
- | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (rồi BDD sau khi sign-off); BE: `/generate-bdd {prd-file}` trực tiếp; sửa PRD nếu NEEDS_FIX |
685
+ | /review-context (PRD) | Khi 0 critical → PO đặt `Status: approved`, rồi FE/App: `/generate-design-spec {prd-file}` ( design sign-off → BDD); BE: `/generate-bdd {prd-file}`. Còn critical/NEEDS_FIX sửa PRD (giữ draft) |
686
686
  | /generate-design-spec | Designer review → xác nhận link Figma → PO + Designer sign-off → `/generate-bdd {prd-file}` |
687
687
  | /generate-bdd | `/review-context {feature-file}` để kiểm tra độ phủ |
688
688
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` nếu APPROVED; sinh lại nếu NEEDS_FIX |