@edupia-tutor/spec-driven-docs 0.14.8 → 0.14.9

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.
@@ -837,6 +837,20 @@ Với mỗi UC, ghi vào path đã phân giải ở trên. Dùng từ vựng cho
837
837
  # Tham chiếu nhanh các term dùng trong feature này. Chi tiết SoT: business-dictionary.md
838
838
  # <Term 1>: <định nghĩa ngắn>
839
839
  # <Term 2>: <định nghĩa ngắn>
840
+ #
841
+ # --- Popup/Modal Lifecycle (tùy chọn — BẮT BUỘC nếu feature là popup/modal; Pre-merge yêu cầu) ---
842
+ # - Open trigger: <khi nào popup hiển thị, vd: click menu sidebar>
843
+ # - Close trigger: <khi nào popup đóng, vd: F5 / click X / ESC / navigate away>
844
+ # - Refresh model: <data refresh khi nào, vd: mỗi lần open (NO CACHE) / persisted / polling>
845
+ # - State reset: <state nào reset khi đóng/mở lại, vd: pagination, expand, dropdown selection>
846
+ #
847
+ # --- Display Logic Matrix (tùy chọn — BẮT BUỘC nếu display logic phụ thuộc ≥2 chiều; Pre-merge yêu cầu) ---
848
+ # Liệt kê đủ ma trận N×M case + map mỗi case → SC. Tên SC theo pattern `<cấu trúc>: <outcome>` (KHÔNG dùng "(Case X)").
849
+ # | # | Dim1 | Dim2 | Format hiển thị | SC |
850
+ # |---|------|------|------------------------|------|
851
+ # | 1 | 0 | 0 | `Tên hàng` | SC{} |
852
+ # | 2 | 0 | 1 | `Tên hàng (đơn vị)` | SC{} |
853
+ # | ... | ... | ... | ... | ... |
840
854
 
841
855
  Feature: <Feature name>
842
856
  As a <role>
@@ -884,11 +898,7 @@ Feature: <Feature name>
884
898
  Given <state>
885
899
  When <action>
886
900
  Then <expected error handling>
887
- ```
888
-
889
- ### Coverage Matrix & Pre-merge Checklist *(thêm vào cuối mỗi file)*
890
901
 
891
- ```gherkin
892
902
  # === PRD COVERAGE (C.1 + C.2) ===
893
903
  # AC mapping:
894
904
  # AC1 (...) → SC1, SC2
@@ -915,8 +925,11 @@ Feature: <Feature name>
915
925
  # - [ ] Feature ≥3 SC có NHÓM grouping theo business theme (C.5)
916
926
  # - [ ] Nếu popup/modal: khai báo Popup/Modal Lifecycle trong BUSINESS DEFINITION
917
927
  # - [ ] Nếu display logic ≥2 chiều: Display Logic Matrix trong BUSINESS DEFINITION
928
+
918
929
  ```
919
930
 
931
+ *(Template `.feature` là **single-source** ở `templates/feature.template` — sửa file đó để đổi cấu trúc mọi `.feature` sinh ra. Coverage Matrix + Pre-merge Checklist nằm ở **cuối** template, thêm vào cuối mỗi file.)*
932
+
920
933
  ---
921
934
 
922
935
  ## Write Trace State
@@ -410,117 +410,10 @@ CHECKPOINT: "Outline này đúng chưa? Bạn muốn thêm hay bớt SC nào kh
410
410
  Với mỗi UC, ghi vào path đã phân giải ở trên. Dùng từ vựng cho active platform (từ Platform Selection hoặc Service Detection).
411
411
 
412
412
  ```gherkin
413
- # ============================================================
414
- # @trace.id: {TICKET-ID}-UC{N}
415
- # @trace.title: <Feature name>
416
- # @trace.revision: 1 ← field tĩnh; dùng @trace.bdd_version để theo dõi version (tăng bởi /review-context --fix hoặc --resume)
417
- # @trace.domain: <domain>
418
- # @trace.platform: {active_platform — web | app | system | (bỏ trong umbrella mode)}
419
- # @trace.service: {active_service — bỏ trong spec repo mode}
420
- # @trace.module: {active_module trong umbrella mode; "unknown" trong spec repo mode}
421
- # @trace.status: draft
422
- # @trace.author: AI-generated
423
- # @trace.created_at: {YYYY-MM-DD}
424
- # @trace.prd: {TICKET-ID}
425
- # @trace.prd_version: {đọc từ metadata PRD "| **Version** |"}
426
- # @trace.bdd_version: {1.0 nếu gen mới; tăng 0.1 khi gen lại — vd 1.0 → 1.1}
427
- # @trace.business_rules: {TICKET-ID}-UC{N}-BR1, {TICKET-ID}-UC{N}-BR2
428
- # @trace.dataset: {domain}.testdata.yaml
429
- # ============================================================
430
-
431
- # === CONTEXT ===
432
- # Actor: <vai trò thực hiện hành động, vd: Consumer, Staff, System>
433
- # Screens: <các màn liên quan, vd: Cart → Confirm Order → Order Detail>
434
- # Entities: <business entity, vd: Order, OrderItem, Consumer>
435
- # Pre-state: <state dùng chung trước khi vào các scenario>
436
-
437
- # === SCOPE ===
438
- # In: <UC này phủ gì>
439
- # Out: <cái gì KHÔNG thuộc UC này — link tới UC/feature khác (R10)>
440
-
441
- # === BUSINESS DEFINITION ===
442
- # Tham chiếu nhanh các term dùng trong feature này. Chi tiết SoT: business-dictionary.md
443
- # <Term 1>: <định nghĩa ngắn>
444
- # <Term 2>: <định nghĩa ngắn>
445
-
446
- Feature: <Feature name>
447
- As a <role>
448
- I want to <action>
449
- So that <business value>
450
-
451
- Background:
452
- Given <precondition dùng chung — dùng alias từ dataset, không phải ID kỹ thuật>
453
-
454
- # ==========================================================
455
- # NHÓM 1: <Business theme> (<BR refs>)
456
- # ==========================================================
457
-
458
- # Side-effects: <liệt kê ngắn các Then side-effect cần verify>
459
- # @trace.scenario: {TICKET-ID}-UC{N}-SC1
460
- # @trace.sc_version: 1.0
461
- # @trace.business_rules: {TICKET-ID}-UC{N}-BR1
462
- @happy
463
- Scenario: <mô tả business outcome — dùng động từ chính xác: create/receive/assign/block>
464
- Given <input state — alias từ dataset>
465
- When <single action>
466
- Then <main observable outcome>
467
- And <side-effect 1 khai báo trong header>
468
-
469
- # Side-effects: <...>
470
- # @trace.scenario: {TICKET-ID}-UC{N}-SC2
471
- # @trace.sc_version: 1.0
472
- # @trace.business_rules: {TICKET-ID}-UC{N}-BR1
473
- @happy @alternative
474
- Scenario: <cùng theme NHÓM 1 nhưng path khác — vd: giá trị enum khác>
475
- Given <state>
476
- When <action>
477
- Then <outcome>
478
-
479
- # ==========================================================
480
- # NHÓM 2: <Business theme 2> (<BR refs>)
481
- # ==========================================================
482
-
483
- # Side-effects: <...>
484
- # @trace.scenario: {TICKET-ID}-UC{N}-SC3
485
- # @trace.sc_version: 1.0
486
- # @trace.business_rules: {TICKET-ID}-UC{N}-BR2
487
- @edge
488
- Scenario: <scenario boundary / error>
489
- Given <state>
490
- When <action>
491
- Then <expected error handling>
413
+ {{include:templates/feature.template}}
492
414
  ```
493
415
 
494
- ### Coverage Matrix & Pre-merge Checklist *(thêm vào cuối mỗi file)*
495
-
496
- ```gherkin
497
- # === PRD COVERAGE (C.1 + C.2) ===
498
- # AC mapping:
499
- # AC1 (...) → SC1, SC2
500
- # AC2 (...) → SC3
501
- # BR mapping (mỗi bullet PHẢI có ≥1 SC — C.2):
502
- # {TICKET-ID}-UC{N}-BR1 (...) → SC1, SC2
503
- # {TICKET-ID}-UC{N}-BR2 (...) → SC3
504
- # Wireframe mapping (mỗi component/action ≥1 SC — C.1):
505
- # Screen "<screen name>":
506
- # [x] <action 1> → SC1
507
- # [x] <action 2> → SC2
508
- # [ ] <action 3> → MISSING ← BLOCK MERGE
509
- # Design Spec coverage (chỉ FE/App — C.1 mở rộng; bỏ khối này nếu không nạp design-spec):
510
- # Screen "<screen>": loading → SC?, error → SC?, empty → SC?
511
- # AC-UI behavioral: AC-UI3 (lỗi+khôi phục) → SC?, AC-UI4 (empty CTA) → SC?
512
- # (bỏ AC-UI visual thuần: AC-UI1 khớp Figma, AC-UI5 WCAG — Designer/QA review riêng)
513
-
514
- # === PRE-MERGE CHECKLIST ===
515
- # - [ ] Mỗi SC có Side-effects + @trace.scenario + @trace.sc_version + @trace.business_rules
516
- # - [ ] Coverage Matrix: 0 dòng MISSING (C.1)
517
- # - [ ] FE/App: mỗi Screen State (≠default) + AC-UI behavioral của design-spec có ≥1 SC (C.1 mở rộng)
518
- # - [ ] Mỗi AC/BR map tới ≥1 SC (C.2)
519
- # - [ ] 0 banned term (C.4) — grep file trước khi merge
520
- # - [ ] Feature ≥3 SC có NHÓM grouping theo business theme (C.5)
521
- # - [ ] Nếu popup/modal: khai báo Popup/Modal Lifecycle trong BUSINESS DEFINITION
522
- # - [ ] Nếu display logic ≥2 chiều: Display Logic Matrix trong BUSINESS DEFINITION
523
- ```
416
+ *(Template `.feature` là **single-source** ở `templates/feature.template` — sửa file đó để đổi cấu trúc mọi `.feature` sinh ra. Coverage Matrix + Pre-merge Checklist nằm ở **cuối** template, thêm vào cuối mỗi file.)*
524
417
 
525
418
  ---
526
419
 
@@ -624,6 +624,8 @@ Ghi `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` theo cấu
624
624
 
625
625
  ## b. Phạm vi
626
626
 
627
+ > **Scope = ranh giới, KHÔNG phải đặc tả.** Mỗi mục một dòng ngắn "làm gì / không làm gì". Đừng nhét **cơ chế** (retry/timeout/nhánh lỗi → BR/BL) hay **định nghĩa thuật ngữ** (vd "điểm khởi tạo = …" → Business Definition / business-dictionary) vào đây.
628
+
627
629
  **In Scope**
628
630
  - {hạng mục trong phạm vi 1}
629
631
  - {hạng mục trong phạm vi 2}
@@ -642,10 +644,14 @@ Ghi `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` theo cấu
642
644
  # 2. Acceptance Criteria
643
645
 
644
646
  > Mỗi AC kế thừa liên kết "Bắt nguồn từ BR" của Product Definition (Phase 6), remap sang BR ID của PRD. Vì BR ID đã chứa số UC nên ref BR truy ngược được tới đúng UC.
647
+ >
648
+ > **1 AC = 1 tiêu chí NGHIỆM THU (outcome quan sát/kiểm được) + ref BR.** KHÔNG viết cơ chế trong AC (số lần retry, timeout, tên/chủ cờ, nhánh lỗi chi tiết) — cái đó thuộc **BR/BL** ở §3, AC chỉ trỏ tới. Nếu tiêu chí có **nhiều nhánh** → tách **bullet con** (mỗi ý một dòng), đừng dồn thành câu dài. Khi `/refine-prd` làm rõ thêm: chi tiết cơ chế → đẩy sang BR/BL; ở tầng AC thì tách bullet/AC mới — KHÔNG nối mệnh đề vào câu cũ (tránh AC thành "đoạn văn" và trùng BR).
645
649
 
646
650
  **AC1:** {Tiêu chí nghiệm thu, văn xuôi, kiểm chứng được.} _(BR: {TICKET}-{N}-UC{n}-BR{m})_
647
651
 
648
- **AC2:** {} _(BR: {TICKET}-{N}-UC{n}-BR{m})_
652
+ **AC2:** {Tiêu chí có nhiều nhánh — tách bullet:} _(BR: {TICKET}-{N}-UC{n}-BR{m})_
653
+ - {nhánh/điều kiện 1 → kết quả kỳ vọng}
654
+ - {nhánh/điều kiện 2 → kết quả kỳ vọng}
649
655
 
650
656
  ---
651
657
 
@@ -777,6 +783,7 @@ _(Nếu không có độ vênh: ghi "Không có — toàn bộ nội dung đã
777
783
  ## Quality Checklist *(kiểm tra trước khi ghi)*
778
784
 
779
785
  - [ ] Mọi AC đều testable (pass/fail rõ ràng), không có chi tiết kỹ thuật (API/token/DB) hay visual chi tiết (màu sắc, font, animation)
786
+ - [ ] **Altitude (AC vs BR/BL)**: AC chỉ nêu **outcome quan sát/kiểm được + ref BR** — KHÔNG chứa cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi chi tiết); cơ chế nằm ở **BR/BL** (§3). AC không lặp lại nội dung BR nó ref. **Scope** = ranh giới (KHÔNG định nghĩa thuật ngữ / KHÔNG cơ chế)
780
787
  - [ ] Mỗi UC có Actor / Description / Pre-condition / Post-condition
781
788
  - [ ] §1c "Phụ thuộc liên service" có mặt: kế thừa từ discovery Phase 1 câu 8 (hoặc "Không có" nếu discovery trống); case partner song song có ghi phụ thuộc partner ở đây
782
789
  - [ ] Business Rule (WHAT) và Business Logic (HOW) nằm chung bảng 3 cột `ID | Business Rule | Business Logic`
@@ -130,6 +130,7 @@ Ghi `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` theo cấu
130
130
  ## Quality Checklist *(kiểm tra trước khi ghi)*
131
131
 
132
132
  - [ ] Mọi AC đều testable (pass/fail rõ ràng), không có chi tiết kỹ thuật (API/token/DB) hay visual chi tiết (màu sắc, font, animation)
133
+ - [ ] **Altitude (AC vs BR/BL)**: AC chỉ nêu **outcome quan sát/kiểm được + ref BR** — KHÔNG chứa cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi chi tiết); cơ chế nằm ở **BR/BL** (§3). AC không lặp lại nội dung BR nó ref. **Scope** = ranh giới (KHÔNG định nghĩa thuật ngữ / KHÔNG cơ chế)
133
134
  - [ ] Mỗi UC có Actor / Description / Pre-condition / Post-condition
134
135
  - [ ] §1c "Phụ thuộc liên service" có mặt: kế thừa từ discovery Phase 1 câu 8 (hoặc "Không có" nếu discovery trống); case partner song song có ghi phụ thuộc partner ở đây
135
136
  - [ ] Business Rule (WHAT) và Business Logic (HOW) nằm chung bảng 3 cột `ID | Business Rule | Business Logic`
@@ -574,6 +574,13 @@ mới**, hoặc tới cap cứng **3 vòng**, cái nào đến trước:
574
574
  List ONLY real, additional issues NOT already in the list — gaps, ambiguities,
575
575
  contradictions, missing edge/negative paths, coverage holes, terminology drift,
576
576
  structural omissions, and any issue that a fix to an existing finding would expose.
577
+ ALSO flag ROLE-BOUNDARY / altitude violations (you are NOT limited to adding detail):
578
+ content sitting in the WRONG section — detailed mechanism (retry counts, timeouts, flag
579
+ names/owners, error branches) written INSIDE an acceptance criterion or a scope line
580
+ instead of the Business Rule/Logic section; an AC that merely restates its referenced BR
581
+ (same content, converged); a term definition crammed into In/Out Scope. For these, the
582
+ suggestion must be to MOVE the detail to its proper section (AC keeps only the observable
583
+ outcome + BR ref) — NOT to delete it, and NOT to add more detail.
577
584
  Do NOT repeat anything already listed. Return the same finding JSON shape, or [] if
578
585
  nothing new.
579
586
  ```
@@ -638,8 +645,8 @@ Chạy review qua **Quy trình Review** ở trên (`steps/review-fanout.md`).
638
645
  **DIMENSIONS** = 4 lăng kính dưới đây — fan out một sub-agent cho mỗi lăng kính, mỗi cái quét
639
646
  toàn bộ PRD qua đúng lăng kính của nó:
640
647
 
641
- - **Lăng kính QA**: AC có testable không? Edge case đã nêu? Điều kiện biên đã định nghĩa?
642
- - **Lăng kính DEV**: Input/output API rõ chưa? Business rule có mơ hồ không? Cross-service deps mô tả đủ chưa? rủi ro kỹ thuật nào?
648
+ - **Lăng kính QA (tầng nghiệm thu)**: AC có nêu **outcome quan sát/kiểm được** chưa? **KHÔNG** hỏi "AC đủ chi tiết chưa" (câu đó kéo cơ chế vào AC). Chi tiết cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi vụn) thuộc **BR/BL**: nếu gap là cơ chế → suggestion phải **route sang BR/BL + AC ref**, KHÔNG phình AC. AC có lặp lại nội dung BR (trùng tầng) không → nếu có, đề xuất làm mỏng AC.
649
+ - **Lăng kính DEV (tầng cơ chế)**: BR (WHAT) + Business Logic (HOW) đã đủ & rõ chưa — **đây là NƠI chứa chi tiết**: rẽ nhánh, điều kiện biên, retry, error path. Business rule có mơ hồ không? Cross-service deps đủ chưa? Rủi ro kỹ thuật?
643
650
  - **Lăng kính SA**: Khớp kiến trúc hiện tại? Hệ luỵ security/auth? Mô hình dữ liệu rõ chưa?
644
651
  - **Lăng kính PO**: Scope đã khoanh vùng? Priority rõ chưa? Success metric đã định nghĩa? Rủi ro scope creep?
645
652
 
@@ -886,6 +893,7 @@ Nếu có finding nào có `status: "needs_discussion"`, thêm warning block sau
886
893
  Với mỗi finding được chấp nhận, theo thứ tự severity (critical → major → minor):
887
894
  - Đi tới section PRD được chỉ định bởi `finding.section`.
888
895
  - Áp dụng `finding.suggestion`. Với finding `status: "modified"`, người đã sửa sẵn `finding.suggestion` trong Review Board — giá trị đã sửa đó CHÍNH LÀ bản fix cần áp dụng.
896
+ - **Giữ ĐÚNG TẦNG + gọn khi áp fix (altitude):** AC = **outcome quan sát được + ref BR**, KHÔNG chứa cơ chế. Nếu fix là **chi tiết cơ chế/rule** (retry N, timeout, tên/chủ cờ, nhánh lỗi) → **ghi vào bảng BR/BL của UC** (hoặc tạo BR mới), AC chỉ **ref**; KHÔNG inline vào câu AC. Nếu fix làm rõ **≥2 điều kiện/nhánh** ở đúng tầng của nó → **tách bullet con** (mỗi ý một dòng ` - …`) hoặc **AC/BR mới**, đừng nối mệnh đề vào câu cũ. Một AC = một tiêu chí kiểm chứng; đừng để AC lặp lại nội dung BR.
889
897
  - **Chạy Business Language Guard trên text mới TRƯỚC khi ghi** (xem section "Ngôn ngữ nghiệp vụ"): diễn đạt lại / gỡ thuật ngữ kỹ thuật-UI để fix không tự kéo theo term kỹ thuật vào PRD.
890
898
  - Không thay đổi bất kỳ section nào không được tham chiếu bởi một finding được chấp nhận.
891
899
 
@@ -55,8 +55,8 @@ Chạy review qua **Quy trình Review** ở trên (`steps/review-fanout.md`).
55
55
  **DIMENSIONS** = 4 lăng kính dưới đây — fan out một sub-agent cho mỗi lăng kính, mỗi cái quét
56
56
  toàn bộ PRD qua đúng lăng kính của nó:
57
57
 
58
- - **Lăng kính QA**: AC có testable không? Edge case đã nêu? Điều kiện biên đã định nghĩa?
59
- - **Lăng kính DEV**: Input/output API rõ chưa? Business rule có mơ hồ không? Cross-service deps mô tả đủ chưa? rủi ro kỹ thuật nào?
58
+ - **Lăng kính QA (tầng nghiệm thu)**: AC có nêu **outcome quan sát/kiểm được** chưa? **KHÔNG** hỏi "AC đủ chi tiết chưa" (câu đó kéo cơ chế vào AC). Chi tiết cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi vụn) thuộc **BR/BL**: nếu gap là cơ chế → suggestion phải **route sang BR/BL + AC ref**, KHÔNG phình AC. AC có lặp lại nội dung BR (trùng tầng) không → nếu có, đề xuất làm mỏng AC.
59
+ - **Lăng kính DEV (tầng cơ chế)**: BR (WHAT) + Business Logic (HOW) đã đủ & rõ chưa — **đây là NƠI chứa chi tiết**: rẽ nhánh, điều kiện biên, retry, error path. Business rule có mơ hồ không? Cross-service deps đủ chưa? Rủi ro kỹ thuật?
60
60
  - **Lăng kính SA**: Khớp kiến trúc hiện tại? Hệ luỵ security/auth? Mô hình dữ liệu rõ chưa?
61
61
  - **Lăng kính PO**: Scope đã khoanh vùng? Priority rõ chưa? Success metric đã định nghĩa? Rủi ro scope creep?
62
62
 
@@ -203,6 +203,7 @@ Nếu có finding nào có `status: "needs_discussion"`, thêm warning block sau
203
203
  Với mỗi finding được chấp nhận, theo thứ tự severity (critical → major → minor):
204
204
  - Đi tới section PRD được chỉ định bởi `finding.section`.
205
205
  - Áp dụng `finding.suggestion`. Với finding `status: "modified"`, người đã sửa sẵn `finding.suggestion` trong Review Board — giá trị đã sửa đó CHÍNH LÀ bản fix cần áp dụng.
206
+ - **Giữ ĐÚNG TẦNG + gọn khi áp fix (altitude):** AC = **outcome quan sát được + ref BR**, KHÔNG chứa cơ chế. Nếu fix là **chi tiết cơ chế/rule** (retry N, timeout, tên/chủ cờ, nhánh lỗi) → **ghi vào bảng BR/BL của UC** (hoặc tạo BR mới), AC chỉ **ref**; KHÔNG inline vào câu AC. Nếu fix làm rõ **≥2 điều kiện/nhánh** ở đúng tầng của nó → **tách bullet con** (mỗi ý một dòng ` - …`) hoặc **AC/BR mới**, đừng nối mệnh đề vào câu cũ. Một AC = một tiêu chí kiểm chứng; đừng để AC lặp lại nội dung BR.
206
207
  - **Chạy Business Language Guard trên text mới TRƯỚC khi ghi** (xem section "Ngôn ngữ nghiệp vụ"): diễn đạt lại / gỡ thuật ngữ kỹ thuật-UI để fix không tự kéo theo term kỹ thuật vào PRD.
207
208
  - Không thay đổi bất kỳ section nào không được tham chiếu bởi một finding được chấp nhận.
208
209
 
@@ -585,6 +585,13 @@ mới**, hoặc tới cap cứng **3 vòng**, cái nào đến trước:
585
585
  List ONLY real, additional issues NOT already in the list — gaps, ambiguities,
586
586
  contradictions, missing edge/negative paths, coverage holes, terminology drift,
587
587
  structural omissions, and any issue that a fix to an existing finding would expose.
588
+ ALSO flag ROLE-BOUNDARY / altitude violations (you are NOT limited to adding detail):
589
+ content sitting in the WRONG section — detailed mechanism (retry counts, timeouts, flag
590
+ names/owners, error branches) written INSIDE an acceptance criterion or a scope line
591
+ instead of the Business Rule/Logic section; an AC that merely restates its referenced BR
592
+ (same content, converged); a term definition crammed into In/Out Scope. For these, the
593
+ suggestion must be to MOVE the detail to its proper section (AC keeps only the observable
594
+ outcome + BR ref) — NOT to delete it, and NOT to add more detail.
588
595
  Do NOT repeat anything already listed. Return the same finding JSON shape, or [] if
589
596
  nothing new.
590
597
  ```
@@ -713,8 +720,10 @@ Quét mỗi AC và BR tìm:
713
720
  | Tham chiếu chưa định nghĩa | "{SomeThing}" được dùng nhưng chưa định nghĩa trong PRD này | Major |
714
721
  | Thiếu luồng âm | AC chỉ mô tả happy path nhưng BR có điều kiện lỗi | Minor |
715
722
  | Câu bị động giấu actor | "Invoice is created" — ai tạo? | Minor |
723
+ | **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 |
724
+ | **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 |
716
725
 
717
- → AI không thể auto-fix finding P2. Người phải viết bản fix trong note "Modify" của Review Board.
726
+ → 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.
718
727
 
719
728
  ### P3 — Domain Conflict Check
720
729
 
@@ -1111,6 +1120,8 @@ Với mỗi finding `accepted`/`modified` sau khi áp xong → đặt `status: "
1111
1120
 
1112
1121
  > **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.
1113
1122
 
1123
+ > **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.
1124
+
1114
1125
  **Với finding PRD:**
1115
1126
  | check_id | Làm gì |
1116
1127
  |----------|-----------|
@@ -130,8 +130,10 @@ Quét mỗi AC và BR tìm:
130
130
  | Tham chiếu chưa định nghĩa | "{SomeThing}" được dùng nhưng chưa định nghĩa trong PRD này | Major |
131
131
  | Thiếu luồng âm | AC chỉ mô tả happy path nhưng BR có điều kiện lỗi | Minor |
132
132
  | Câu bị động giấu actor | "Invoice is created" — ai tạo? | Minor |
133
+ | **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 |
134
+ | **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 |
133
135
 
134
- → AI không thể auto-fix finding P2. Người phải viết bản fix trong note "Modify" của Review Board.
136
+ → 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.
135
137
 
136
138
  ### P3 — Domain Conflict Check
137
139
 
@@ -428,6 +430,8 @@ Với mỗi finding `accepted`/`modified` sau khi áp xong → đặt `status: "
428
430
 
429
431
  > **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.
430
432
 
433
+ > **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.
434
+
431
435
  **Với finding PRD:**
432
436
  | check_id | Làm gì |
433
437
  |----------|-----------|
@@ -1 +1 @@
1
- 0.14.8
1
+ 0.14.9
@@ -837,6 +837,20 @@ Với mỗi UC, ghi vào path đã phân giải ở trên. Dùng từ vựng cho
837
837
  # Tham chiếu nhanh các term dùng trong feature này. Chi tiết SoT: business-dictionary.md
838
838
  # <Term 1>: <định nghĩa ngắn>
839
839
  # <Term 2>: <định nghĩa ngắn>
840
+ #
841
+ # --- Popup/Modal Lifecycle (tùy chọn — BẮT BUỘC nếu feature là popup/modal; Pre-merge yêu cầu) ---
842
+ # - Open trigger: <khi nào popup hiển thị, vd: click menu sidebar>
843
+ # - Close trigger: <khi nào popup đóng, vd: F5 / click X / ESC / navigate away>
844
+ # - Refresh model: <data refresh khi nào, vd: mỗi lần open (NO CACHE) / persisted / polling>
845
+ # - State reset: <state nào reset khi đóng/mở lại, vd: pagination, expand, dropdown selection>
846
+ #
847
+ # --- Display Logic Matrix (tùy chọn — BẮT BUỘC nếu display logic phụ thuộc ≥2 chiều; Pre-merge yêu cầu) ---
848
+ # Liệt kê đủ ma trận N×M case + map mỗi case → SC. Tên SC theo pattern `<cấu trúc>: <outcome>` (KHÔNG dùng "(Case X)").
849
+ # | # | Dim1 | Dim2 | Format hiển thị | SC |
850
+ # |---|------|------|------------------------|------|
851
+ # | 1 | 0 | 0 | `Tên hàng` | SC{} |
852
+ # | 2 | 0 | 1 | `Tên hàng (đơn vị)` | SC{} |
853
+ # | ... | ... | ... | ... | ... |
840
854
 
841
855
  Feature: <Feature name>
842
856
  As a <role>
@@ -884,11 +898,7 @@ Feature: <Feature name>
884
898
  Given <state>
885
899
  When <action>
886
900
  Then <expected error handling>
887
- ```
888
-
889
- ### Coverage Matrix & Pre-merge Checklist *(thêm vào cuối mỗi file)*
890
901
 
891
- ```gherkin
892
902
  # === PRD COVERAGE (C.1 + C.2) ===
893
903
  # AC mapping:
894
904
  # AC1 (...) → SC1, SC2
@@ -915,8 +925,11 @@ Feature: <Feature name>
915
925
  # - [ ] Feature ≥3 SC có NHÓM grouping theo business theme (C.5)
916
926
  # - [ ] Nếu popup/modal: khai báo Popup/Modal Lifecycle trong BUSINESS DEFINITION
917
927
  # - [ ] Nếu display logic ≥2 chiều: Display Logic Matrix trong BUSINESS DEFINITION
928
+
918
929
  ```
919
930
 
931
+ *(Template `.feature` là **single-source** ở `templates/feature.template` — sửa file đó để đổi cấu trúc mọi `.feature` sinh ra. Coverage Matrix + Pre-merge Checklist nằm ở **cuối** template, thêm vào cuối mỗi file.)*
932
+
920
933
  ---
921
934
 
922
935
  ## Write Trace State
@@ -624,6 +624,8 @@ Ghi `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` theo cấu
624
624
 
625
625
  ## b. Phạm vi
626
626
 
627
+ > **Scope = ranh giới, KHÔNG phải đặc tả.** Mỗi mục một dòng ngắn "làm gì / không làm gì". Đừng nhét **cơ chế** (retry/timeout/nhánh lỗi → BR/BL) hay **định nghĩa thuật ngữ** (vd "điểm khởi tạo = …" → Business Definition / business-dictionary) vào đây.
628
+
627
629
  **In Scope**
628
630
  - {hạng mục trong phạm vi 1}
629
631
  - {hạng mục trong phạm vi 2}
@@ -642,10 +644,14 @@ Ghi `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` theo cấu
642
644
  # 2. Acceptance Criteria
643
645
 
644
646
  > Mỗi AC kế thừa liên kết "Bắt nguồn từ BR" của Product Definition (Phase 6), remap sang BR ID của PRD. Vì BR ID đã chứa số UC nên ref BR truy ngược được tới đúng UC.
647
+ >
648
+ > **1 AC = 1 tiêu chí NGHIỆM THU (outcome quan sát/kiểm được) + ref BR.** KHÔNG viết cơ chế trong AC (số lần retry, timeout, tên/chủ cờ, nhánh lỗi chi tiết) — cái đó thuộc **BR/BL** ở §3, AC chỉ trỏ tới. Nếu tiêu chí có **nhiều nhánh** → tách **bullet con** (mỗi ý một dòng), đừng dồn thành câu dài. Khi `/refine-prd` làm rõ thêm: chi tiết cơ chế → đẩy sang BR/BL; ở tầng AC thì tách bullet/AC mới — KHÔNG nối mệnh đề vào câu cũ (tránh AC thành "đoạn văn" và trùng BR).
645
649
 
646
650
  **AC1:** {Tiêu chí nghiệm thu, văn xuôi, kiểm chứng được.} _(BR: {TICKET}-{N}-UC{n}-BR{m})_
647
651
 
648
- **AC2:** {} _(BR: {TICKET}-{N}-UC{n}-BR{m})_
652
+ **AC2:** {Tiêu chí có nhiều nhánh — tách bullet:} _(BR: {TICKET}-{N}-UC{n}-BR{m})_
653
+ - {nhánh/điều kiện 1 → kết quả kỳ vọng}
654
+ - {nhánh/điều kiện 2 → kết quả kỳ vọng}
649
655
 
650
656
  ---
651
657
 
@@ -777,6 +783,7 @@ _(Nếu không có độ vênh: ghi "Không có — toàn bộ nội dung đã
777
783
  ## Quality Checklist *(kiểm tra trước khi ghi)*
778
784
 
779
785
  - [ ] Mọi AC đều testable (pass/fail rõ ràng), không có chi tiết kỹ thuật (API/token/DB) hay visual chi tiết (màu sắc, font, animation)
786
+ - [ ] **Altitude (AC vs BR/BL)**: AC chỉ nêu **outcome quan sát/kiểm được + ref BR** — KHÔNG chứa cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi chi tiết); cơ chế nằm ở **BR/BL** (§3). AC không lặp lại nội dung BR nó ref. **Scope** = ranh giới (KHÔNG định nghĩa thuật ngữ / KHÔNG cơ chế)
780
787
  - [ ] Mỗi UC có Actor / Description / Pre-condition / Post-condition
781
788
  - [ ] §1c "Phụ thuộc liên service" có mặt: kế thừa từ discovery Phase 1 câu 8 (hoặc "Không có" nếu discovery trống); case partner song song có ghi phụ thuộc partner ở đây
782
789
  - [ ] Business Rule (WHAT) và Business Logic (HOW) nằm chung bảng 3 cột `ID | Business Rule | Business Logic`
@@ -574,6 +574,13 @@ mới**, hoặc tới cap cứng **3 vòng**, cái nào đến trước:
574
574
  List ONLY real, additional issues NOT already in the list — gaps, ambiguities,
575
575
  contradictions, missing edge/negative paths, coverage holes, terminology drift,
576
576
  structural omissions, and any issue that a fix to an existing finding would expose.
577
+ ALSO flag ROLE-BOUNDARY / altitude violations (you are NOT limited to adding detail):
578
+ content sitting in the WRONG section — detailed mechanism (retry counts, timeouts, flag
579
+ names/owners, error branches) written INSIDE an acceptance criterion or a scope line
580
+ instead of the Business Rule/Logic section; an AC that merely restates its referenced BR
581
+ (same content, converged); a term definition crammed into In/Out Scope. For these, the
582
+ suggestion must be to MOVE the detail to its proper section (AC keeps only the observable
583
+ outcome + BR ref) — NOT to delete it, and NOT to add more detail.
577
584
  Do NOT repeat anything already listed. Return the same finding JSON shape, or [] if
578
585
  nothing new.
579
586
  ```
@@ -638,8 +645,8 @@ Chạy review qua **Quy trình Review** ở trên (`steps/review-fanout.md`).
638
645
  **DIMENSIONS** = 4 lăng kính dưới đây — fan out một sub-agent cho mỗi lăng kính, mỗi cái quét
639
646
  toàn bộ PRD qua đúng lăng kính của nó:
640
647
 
641
- - **Lăng kính QA**: AC có testable không? Edge case đã nêu? Điều kiện biên đã định nghĩa?
642
- - **Lăng kính DEV**: Input/output API rõ chưa? Business rule có mơ hồ không? Cross-service deps mô tả đủ chưa? rủi ro kỹ thuật nào?
648
+ - **Lăng kính QA (tầng nghiệm thu)**: AC có nêu **outcome quan sát/kiểm được** chưa? **KHÔNG** hỏi "AC đủ chi tiết chưa" (câu đó kéo cơ chế vào AC). Chi tiết cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi vụn) thuộc **BR/BL**: nếu gap là cơ chế → suggestion phải **route sang BR/BL + AC ref**, KHÔNG phình AC. AC có lặp lại nội dung BR (trùng tầng) không → nếu có, đề xuất làm mỏng AC.
649
+ - **Lăng kính DEV (tầng cơ chế)**: BR (WHAT) + Business Logic (HOW) đã đủ & rõ chưa — **đây là NƠI chứa chi tiết**: rẽ nhánh, điều kiện biên, retry, error path. Business rule có mơ hồ không? Cross-service deps đủ chưa? Rủi ro kỹ thuật?
643
650
  - **Lăng kính SA**: Khớp kiến trúc hiện tại? Hệ luỵ security/auth? Mô hình dữ liệu rõ chưa?
644
651
  - **Lăng kính PO**: Scope đã khoanh vùng? Priority rõ chưa? Success metric đã định nghĩa? Rủi ro scope creep?
645
652
 
@@ -886,6 +893,7 @@ Nếu có finding nào có `status: "needs_discussion"`, thêm warning block sau
886
893
  Với mỗi finding được chấp nhận, theo thứ tự severity (critical → major → minor):
887
894
  - Đi tới section PRD được chỉ định bởi `finding.section`.
888
895
  - Áp dụng `finding.suggestion`. Với finding `status: "modified"`, người đã sửa sẵn `finding.suggestion` trong Review Board — giá trị đã sửa đó CHÍNH LÀ bản fix cần áp dụng.
896
+ - **Giữ ĐÚNG TẦNG + gọn khi áp fix (altitude):** AC = **outcome quan sát được + ref BR**, KHÔNG chứa cơ chế. Nếu fix là **chi tiết cơ chế/rule** (retry N, timeout, tên/chủ cờ, nhánh lỗi) → **ghi vào bảng BR/BL của UC** (hoặc tạo BR mới), AC chỉ **ref**; KHÔNG inline vào câu AC. Nếu fix làm rõ **≥2 điều kiện/nhánh** ở đúng tầng của nó → **tách bullet con** (mỗi ý một dòng ` - …`) hoặc **AC/BR mới**, đừng nối mệnh đề vào câu cũ. Một AC = một tiêu chí kiểm chứng; đừng để AC lặp lại nội dung BR.
889
897
  - **Chạy Business Language Guard trên text mới TRƯỚC khi ghi** (xem section "Ngôn ngữ nghiệp vụ"): diễn đạt lại / gỡ thuật ngữ kỹ thuật-UI để fix không tự kéo theo term kỹ thuật vào PRD.
890
898
  - Không thay đổi bất kỳ section nào không được tham chiếu bởi một finding được chấp nhận.
891
899
 
@@ -585,6 +585,13 @@ mới**, hoặc tới cap cứng **3 vòng**, cái nào đến trước:
585
585
  List ONLY real, additional issues NOT already in the list — gaps, ambiguities,
586
586
  contradictions, missing edge/negative paths, coverage holes, terminology drift,
587
587
  structural omissions, and any issue that a fix to an existing finding would expose.
588
+ ALSO flag ROLE-BOUNDARY / altitude violations (you are NOT limited to adding detail):
589
+ content sitting in the WRONG section — detailed mechanism (retry counts, timeouts, flag
590
+ names/owners, error branches) written INSIDE an acceptance criterion or a scope line
591
+ instead of the Business Rule/Logic section; an AC that merely restates its referenced BR
592
+ (same content, converged); a term definition crammed into In/Out Scope. For these, the
593
+ suggestion must be to MOVE the detail to its proper section (AC keeps only the observable
594
+ outcome + BR ref) — NOT to delete it, and NOT to add more detail.
588
595
  Do NOT repeat anything already listed. Return the same finding JSON shape, or [] if
589
596
  nothing new.
590
597
  ```
@@ -713,8 +720,10 @@ Quét mỗi AC và BR tìm:
713
720
  | Tham chiếu chưa định nghĩa | "{SomeThing}" được dùng nhưng chưa định nghĩa trong PRD này | Major |
714
721
  | Thiếu luồng âm | AC chỉ mô tả happy path nhưng BR có điều kiện lỗi | Minor |
715
722
  | Câu bị động giấu actor | "Invoice is created" — ai tạo? | Minor |
723
+ | **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 |
724
+ | **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 |
716
725
 
717
- → AI không thể auto-fix finding P2. Người phải viết bản fix trong note "Modify" của Review Board.
726
+ → 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.
718
727
 
719
728
  ### P3 — Domain Conflict Check
720
729
 
@@ -1111,6 +1120,8 @@ Với mỗi finding `accepted`/`modified` sau khi áp xong → đặt `status: "
1111
1120
 
1112
1121
  > **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.
1113
1122
 
1123
+ > **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.
1124
+
1114
1125
  **Với finding PRD:**
1115
1126
  | check_id | Làm gì |
1116
1127
  |----------|-----------|
@@ -112,6 +112,13 @@ mới**, hoặc tới cap cứng **3 vòng**, cái nào đến trước:
112
112
  List ONLY real, additional issues NOT already in the list — gaps, ambiguities,
113
113
  contradictions, missing edge/negative paths, coverage holes, terminology drift,
114
114
  structural omissions, and any issue that a fix to an existing finding would expose.
115
+ ALSO flag ROLE-BOUNDARY / altitude violations (you are NOT limited to adding detail):
116
+ content sitting in the WRONG section — detailed mechanism (retry counts, timeouts, flag
117
+ names/owners, error branches) written INSIDE an acceptance criterion or a scope line
118
+ instead of the Business Rule/Logic section; an AC that merely restates its referenced BR
119
+ (same content, converged); a term definition crammed into In/Out Scope. For these, the
120
+ suggestion must be to MOVE the detail to its proper section (AC keeps only the observable
121
+ outcome + BR ref) — NOT to delete it, and NOT to add more detail.
115
122
  Do NOT repeat anything already listed. Return the same finding JSON shape, or [] if
116
123
  nothing new.
117
124
  ```