@educa-corp/fw 0.8.1 → 0.10.0

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.
@@ -0,0 +1,43 @@
1
+ # /bdd — luật viết kịch bản
2
+
3
+ Đọc cùng `new.md` hoặc `change.md`. Khuôn file: `.fw/core/templates/bdd.feature`.
4
+
5
+ ## 1. Một kịch bản là một hành vi, viết bằng ngôn ngữ nghiệp vụ
6
+
7
+ 1. **Khai báo, không mô tả thao tác giao diện.** Viết *"Admin import file 10 dòng"*, không viết *"Admin bấm nút Import, chọn file, bấm Lưu"*. Không ghi tên API, bảng dữ liệu, mã HTTP. Chi tiết giao diện thuộc về design-spec.
8
+ 2. **Mỗi kịch bản kiểm đúng một hành vi.** Tiêu đề nói rõ hành vi và điều kiện, ví dụ *"Import có dòng trùng email với tài khoản đã có"*.
9
+ 3. **`Given` tự dựng đủ trạng thái**, không dựa vào kịch bản khác chạy trước. Dùng giá trị cụ thể: *"đã có tài khoản nhân sự với email "an@edupia.vn""*.
10
+ 4. **`Then` là kết quả nhìn thấy được**, kiểm được đạt hay không đạt. **Hệ quả đi kèm** (ghi lịch sử, gửi email, đăng xuất ở nơi khác) là các bước `And` trong phần `Then`.
11
+ 5. **Giá trị cụ thể lấy từ AC.** AC ghi *"file 10 dòng, 2 dòng trùng"* thì kịch bản dùng đúng các con số đó.
12
+ 6. **Câu báo lỗi dùng đúng câu trong PRD.** PRD không ghi câu báo thì viết theo ý của BR, và thêm dòng `# 🤖 UC-NNN-SCnn: giả định câu báo "…" (PRD chưa ghi)` ngay trên tag để PO chốt.
13
+ 7. Từ khoá Gherkin để tiếng Anh (`Feature`, `Scenario`, `Given`, `When`, `Then`, `And`), nội dung viết tiếng Việt. Thuật ngữ phải đúng glossary và mục Khái niệm của PRD.
14
+
15
+ ## 2. Đủ ý: nhánh, biên, biến thể
16
+
17
+ 1. **Tách nhánh trong cột Business Logic.** Mỗi nhánh phải có một kịch bản hoặc một dòng `Examples`. Ví dụ: *"Email trống, sai định dạng, hoặc đã thuộc tài khoản nhân sự → từ chối"* là 3 nhánh.
18
+ 2. **Giá trị biên ghi trong BR phải có cả hai phía.** BR ghi tối đa 1.000 dòng thì phải có "1.000 dòng → nhận" và "1.001 dòng → từ chối". Biên thời gian cũng vậy: "trước mốc 7×24 giờ → còn active", "đủ mốc → inactive".
19
+ 3. **Biến thể của cùng một luật gộp thành `Scenario Outline` + `Examples`.** Đừng viết 3 kịch bản gần giống nhau. Ví dụ username không hợp lệ: một Outline với các dòng `an@b`, `Lê An`, `an an`.
20
+ 4. **Không viết điều PRD không có.** PRD thiếu hoặc mơ hồ thì **hỏi PO**, không tự bịa. Điều hoàn toàn mới là thay đổi yêu cầu, nên phải đi qua `/prd … change`.
21
+ 5. Kỹ thuật kiểm sâu hơn (phân vùng tương đương, tổ hợp, biên ngoài những gì BR ghi) là việc của QC. BDD chỉ cần đủ mọi hành vi mà code phải làm.
22
+
23
+ ## 3. Nền tảng
24
+
25
+ 1. Hành vi **giống nhau** trên các nền tảng: **một** kịch bản, gắn đủ tag, ví dụ `@web @app`. Lý do: phía server chỉ làm luật này một lần, nên chỉ được có một mã.
26
+ 2. Hành vi **khác nhau**, tức kết quả khác nhau theo PRD: tách thành kịch bản riêng, mỗi kịch bản một mã. Ví dụ `UC-003-SC08 @web` và `UC-003-SC09 @app`.
27
+ 3. Khác nhau chỉ ở giao diện hay thao tác (bố cục, cử chỉ) thì **không** tách, vì đó là việc của design-spec.
28
+ 4. Chỉ dùng nền tảng mà UC khai (dòng `Nền tảng` trong UC, không có thì lấy ở Tổng quan).
29
+
30
+ ## 4. Điểm giao nhận với UC khác
31
+
32
+ UC này nhận một thứ từ UC trước, hoặc tạo ra một thứ UC sau cần (lấy từ các hành trình trong `SE context`). Khi đó kịch bản phải **nêu rõ thứ đó**, và gọi đúng tên mà UC kia dùng. Ví dụ ở J1: `Then` của UC-001 là *"người dùng nhận email có username và link đặt mật khẩu"*, còn `Given` của UC-003 là *"có link đặt mật khẩu lần đầu còn hạn"*. Lỗi ở chỗ nối giữa các UC hay bị phát hiện muộn nhất, nên phải viết rõ.
33
+
34
+ ## 5. Loại và nhóm
35
+
36
+ | Loại | Khi nào |
37
+ |---|---|
38
+ | `@happy` | Luồng chính, thành công |
39
+ | `@alternative` | Luồng khác, vẫn thành công. Ví dụ không đặt username thì hệ thống tự sinh |
40
+ | `@edge` | Biên, giới hạn, mốc thời gian |
41
+ | `@negative` | Bị từ chối, lỗi, không có quyền |
42
+
43
+ Gom kịch bản theo **chủ đề nghiệp vụ**, mỗi nhóm mở đầu bằng `# ── {chủ đề} ──`. Không gom theo loại.
package/ref/common.md ADDED
@@ -0,0 +1,47 @@
1
+ # Luật chung cho mọi lệnh
2
+
3
+ Mọi lệnh của framework đọc file này ở bước đầu tiên. Luật riêng của từng lệnh nằm trong file lệnh và trong `ref/<lệnh>/`.
4
+
5
+ ## 1. Xưng hô
6
+
7
+ Gọi người dùng là **"bạn"**, tự xưng **"tôi"**. Không dùng "mình", "em", "anh/chị", "chúng ta". Áp cho mọi câu trả lời, kể cả khi người dùng xưng khác.
8
+
9
+ ## 2. Kết quả của lệnh Bash đầu tiên
10
+
11
+ Lệnh Bash đầu tiên in nội dung file này, `.fw/config.yaml`, rồi kết quả kiểm Python. Xử lý theo thứ tự:
12
+
13
+ | Thấy | Làm |
14
+ |---|---|
15
+ | Không có `.fw/config.yaml` | **Dừng**, báo *"Chưa cài framework vào dự án này. Chạy `npx @educa-corp/fw install` ở thư mục gốc dự án."* |
16
+ | `ok — Python 3.x` | Dùng `python` cho cả phiên |
17
+ | Lỗi không tìm thấy `python` | Thử lại lần lượt `python3 .fw/core/tools/spec_edit.py --check`, rồi `py -3 …`. Dùng lệnh chạy được cho cả phiên |
18
+ | Cả ba đều lỗi | **DỪNG NGAY**, không hỏi gì thêm, báo: *"❌ Máy chưa có Python 3.8+. Cài Python (Windows: `winget install Python.Python.3.12`), mở terminal mới rồi chạy lại lệnh."* |
19
+
20
+ Lấy `specs` (thư mục spec) và `tracker` từ config.
21
+
22
+ **Phiên dài:** nếu **trước lệnh này** phiên đã có hội thoại khác, dòng đầu tiên của câu trả lời là *"💡 Phiên này đã dài. Nên `/clear` rồi gọi lại lệnh để rẻ hơn, vì mọi thứ đã chốt đều nằm trong file."* Sau đó vẫn làm tiếp bình thường.
23
+
24
+ ## 3. Khi hỏi người dùng
25
+
26
+ 1. **Tối đa 4 câu hỏi mỗi lượt, tính cả câu phụ.** Mọi chỗ cần người dùng trả lời hoặc xác nhận đều được **đánh số** trong 4 câu đó, không kèm thêm "còn vài điểm…" ở ngoài. Còn câu thì để lượt sau.
27
+ 2. **Chỉ nói ngôn ngữ nghiệp vụ** trong tài liệu spec. Không hỏi và không đề xuất API, bảng dữ liệu hay framework.
28
+ 3. **Dấu `🤖` / `✅`.** Mục AI trích, tự thêm, tách hoặc suy ra thì mang `🤖`. Chỉ khi người dùng xác nhận thì mới đổi thành `✅`. **Không bao giờ tự đổi thay người dùng.**
29
+
30
+ ## 4. Sửa file spec: CHỈ dùng `spec_edit.py`
31
+
32
+ Gọi là `SE` = `python .fw/core/tools/spec_edit.py` (hoặc `python3` / `py -3` theo mục 2). **Không dùng Edit/Write, không tự viết script.**
33
+
34
+ | Việc | Lệnh |
35
+ |---|---|
36
+ | Tạo file mới (lỗi nếu đã có) | `SE create <file> <<'EOF'` … nội dung … `EOF` |
37
+ | Sửa nội dung | `SE edit <file> <<'EOF'` `[{"old": "…", "new": "…"}]` `EOF`. Gom mọi chỗ sửa của một lượt vào **một** lần gọi. Đoạn lặp giống nhau thì thêm `"all": true` |
38
+ | Frontmatter | `SE set <file> key=value …` (giá trị được kiểm trước khi ghi) |
39
+ | Mục còn chờ xác nhận · xác nhận theo mã | `SE pending <file>` · `SE confirm <file> <mã…>` |
40
+ | Đọc **một mục** | `SE section <file> <mã>`, mã là `<!-- sec:… -->` ở tiêu đề |
41
+ | Đọc **một UC** | `SE uc <file> UC-003 [UC-005 …]` |
42
+ | Sửa / thêm **dòng có mã** (BR, AC) | `SE item <file> <<'EOF'` `[{"id": "UC-003-BR10", "new": "<dòng mới>"}, {"after": "UC-003-BR10", "new": "<dòng thêm>"}]` `EOF`. Chỉ viết dòng mới. Mã không đổi, không dùng lại |
43
+ | File theo khuôn cũ | `SE upgrade <file>`: gắn mã mục, bổ sung trường và mục còn thiếu |
44
+
45
+ - **Luôn tìm theo mã** (`sec:`, `UC-…`, `F…`), không theo số hay tên tiêu đề, không tự cắt file bằng `sed` / `grep`. Khi sửa, giữ nguyên `<!-- sec:… -->`.
46
+ - `SE` báo lỗi thì **không có gì được ghi**. Đọc lại file, sửa lệnh rồi chạy lại. Không bỏ qua lỗi, không tìm cách lách.
47
+ - Lỗi mà **không in dòng nào** là Python chưa kịp chạy: chạy lại đúng lệnh đó **một lần**.
package/ref/prd/change.md CHANGED
@@ -24,10 +24,10 @@ Dùng cho **mọi** thay đổi: thêm, sửa, bỏ. Mã không bao giờ đánh
24
24
 
25
25
  Khi PO đồng ý kế hoạch:
26
26
 
27
- 1. **Một** lần `SE edit D` cho mọi chỗ sửa:
27
+ 1. Sửa hoặc thêm dòng BR / AC **theo mã** bằng **một** lần `SE item D` (chỉ viết dòng mới, không chép đoạn cũ). Phần không phải dòng BR / AC (luồng, User flow, Tổng quan, tiêu đề UC) thì dùng **một** lần `SE edit D`:
28
28
  - Mục sửa và mục thêm mang `✅`, vì PO vừa duyệt kế hoạch. Mục thêm ghi `(nguồn: PRD)`, trừ khi lấy từ một mã epic hay ràng buộc cụ thể.
29
29
  - Mục bỏ: giữ dòng, gạch ngang nội dung, ghi *"Đã bỏ (v{mới})"*.
30
30
  - Thay đổi làm đổi luồng (thêm UC, đổi thứ tự, thêm nhánh lỗi) thì sửa luôn mục **User flow**. Yêu cầu là *"thêm User flow"* (PRD tạo bằng bản cũ) thì vẽ mục này từ checkpoint 2 của epic, theo luật trong `new.md`.
31
31
  - Thêm dòng vào mục **Lịch sử thay đổi**, dạng *"v1.1 — UC-003: khoá sau 3 lần sai (BR02 sửa, AC05 thêm, BR04 bỏ)"*.
32
32
  2. Chạy `SE flowcheck D`. Còn UC chưa có trong hành trình nào thì sửa cho đủ. Sau đó tăng version phụ (1.0 → 1.1): `SE set D version=1.1 updated=…`. PRD đang `approved` thì đặt luôn `status=draft approved_by=— approved_at=—`.
33
- 3. Báo lại cho PO. Không in lại cả PRD, chỉ tóm tắt những gì đã đổi. Nếu không còn `🤖` và không còn câu hỏi mở thì hỏi: *"Duyệt lại bản v1.1 không?"* PO đồng ý thì duyệt theo luật 7 của lệnh. Bản mới cần người duyệt mới, nên đặt lại `approved_by` và `approved_at`.
33
+ 3. Báo lại cho PO. Không in lại cả PRD, chỉ tóm tắt những gì đã đổi. Nếu không còn `🤖` và không còn câu hỏi mở thì hỏi: *"Duyệt lại bản v1.1 không?"* PO đồng ý thì duyệt theo luật 5 (Duyệt) trong Bước 3 của lệnh. Bản mới cần người duyệt mới, nên đặt lại `approved_by` và `approved_at`.
package/ref/prd/new.md CHANGED
@@ -9,6 +9,7 @@ Chỉ **2 lượt** hỏi-đáp, vì epic đã được làm rõ kỹ. Không h
9
9
  3. Đề xuất cách chia UC.
10
10
  - **Một UC = một mục tiêu của một actor**, xong trong một lần tương tác. Ví dụ "Đổi và quên mật khẩu", không phải "Quản lý bảo mật".
11
11
  - Mỗi UC nên có khoảng 2–8 Business Rule (BR). Nhiều hơn thì cân nhắc tách, ít hơn một thì cân nhắc gộp.
12
+ - **Epic chia ra hơn 8 UC** thì hỏi PO trước khi viết: *"Epic này có {n} UC. PRD lớn sẽ làm mọi bước sau đắt hơn. Có tách epic thành {đề xuất cách tách} không?"*
12
13
  - **Mọi `BR…` và `AC…` của epic phải thuộc ít nhất một UC.** Một BR áp cho nhiều UC thì ghi ở tất cả các UC đó.
13
14
  4. Trình cho PO dạng bảng:
14
15
 
@@ -16,6 +17,8 @@ Chỉ **2 lượt** hỏi-đáp, vì epic đã được làm rõ kỹ. Không h
16
17
  |---|---|---|---|
17
18
  | UC-001 | … | ACT-01 | BR8, BR9, BR10, AC4, AC5 |
18
19
 
20
+ Epic và `product.md` chưa nói tính năng chạy trên **nền tảng** nào (web, app hay cả hai) thì hỏi luôn trong lượt này. UC nào chạy khác phần còn lại (ví dụ chỉ có trên app) thì ghi rõ trong bảng.
21
+
19
22
  Kèm tối đa 3 câu hỏi khác, chỉ khi cần. Ví dụ: một BR nên đặt vào UC nào, hoặc hai UC có nên gộp không. Không có gì cần hỏi thì chỉ hỏi *"Cách chia này được chưa?"*.
20
23
 
21
24
  ## Lượt 2 — Viết PRD
@@ -23,7 +26,7 @@ Chỉ **2 lượt** hỏi-đáp, vì epic đã được làm rõ kỹ. Không h
23
26
  Khi PO đồng ý cách chia UC:
24
27
 
25
28
  1. Tạo `D` bằng **một** lần `SE create`, theo khuôn `.fw/core/templates/prd.md`:
26
- - **Tổng quan:** chuyển từ checkpoint 1 của epic. Ghi các ràng buộc `CON-xx` áp cho epic này.
29
+ - **Tổng quan:** chuyển từ checkpoint 1 của epic. Ghi các ràng buộc `CON-xx` áp cho epic này. Dòng **Nền tảng** là mặc định cho mọi UC. UC nào chạy khác thì ghi thêm dòng `Nền tảng` trong UC đó. BR chỉ áp cho một nền tảng thì ghi rõ trong BR, ví dụ *"Trên app: …"*. BDD dựa vào dòng này để tách kịch bản theo nền tảng, và PRD thiếu dòng này thì không duyệt được.
27
30
  - **User flow** (`sec:userflow`): vẽ các **hành trình** xuyên suốt nhiều UC, lấy từ luồng chính và edge case ở checkpoint 2 của epic. Mỗi hành trình gồm một dòng trong bảng và một sơ đồ `mermaid` (`flowchart TD`). Nút trong sơ đồ ghi mã UC, không chép lại BR. **Mỗi hành trình có ít nhất một nhánh lỗi hoặc ngoại lệ. Mỗi UC có mặt trong ít nhất một hành trình.** Nút nào AI tự suy ra (không có trong epic) thì ghi kèm `🤖` trong nhãn.
28
31
  - **Use case:** mỗi UC gồm điều kiện trước, kết quả sau, luồng chính (lấy các bước liên quan ở checkpoint 2 của epic), bảng BR, Acceptance Criteria (điều kiện nghiệm thu).
29
32
  - **Cột Business Rule:** một BR mỗi dòng, dạng *"Hệ thống PHẢI / KHÔNG ĐƯỢC …"*.
@@ -32,9 +35,9 @@ Khi PO đồng ý cách chia UC:
32
35
  - **Màn hình:** chuyển từ "Màn hình chính" của epic, kèm cột UC.
33
36
  - **Câu hỏi còn mở:** chỉ những gì phát sinh khi viết PRD.
34
37
  - **Lịch sử thay đổi:** dòng `1.0`.
35
- 2. Chạy `SE coverage <epic> D` và `SE flowcheck D`. **Thiếu mục nào thì bổ sung vào UC phù hợp rồi chạy lại cho tới khi đủ.** Mục mà PO muốn bỏ thì hỏi PO. Không được tự bỏ.
38
+ 2. Chạy `SE coverage <epic> D` và `SE flowcheck D`. Có cảnh báo `⚠ PRD … KB` thì báo PO kèm đề xuất tách epic. **Thiếu mục nào thì bổ sung vào UC phù hợp rồi chạy lại cho tới khi đủ.** Mục mà PO muốn bỏ thì hỏi PO. Không được tự bỏ.
36
39
  3. Epic giờ chỉ còn là lịch sử:
37
40
  - `SE set <epic> status=handed-off`
38
41
  - Trong `{specs}/product/product.md`, sửa cột Trạng thái của epic thành `đã có PRD`.
39
42
  4. Chạy `SE pending D`. **Chỉ trình các mục `🤖`**, không in lại cả PRD. Mỗi dòng gồm mã và nội dung ngắn gọn. Kèm câu hỏi mở nếu có. Nhắc PO: *"Mở file để đọc toàn bộ. Trả lời, hoặc xác nhận theo mã, ví dụ 'OK UC-003-BR04'."*
40
- 5. Khi PO xác nhận: `SE confirm D <mã…>`. Không còn `🤖` và không còn câu hỏi mở thì duyệt theo luật 7 của lệnh.
43
+ 5. Khi PO xác nhận: `SE confirm D <mã…>`. Không còn `🤖` và không còn câu hỏi mở thì duyệt theo luật 5 (Duyệt) trong Bước 3 của lệnh.
package/ref/prd/refine.md CHANGED
@@ -42,11 +42,20 @@ Phiên chính **không đọc** kết quả chi tiết của các agent. Agent g
42
42
  - *"Quyết theo nhóm được, áp cho major và minor: 'nhận tất cả minor' · 'nhận hết UC-003 trừ F12' · 'bác F20–F24 vì …'. Critical phải quyết từng mã."*
43
43
  4. Lượt này không có finding nào thì báo, rồi sang Bước D luôn.
44
44
 
45
- ## Bước D — Áp quyết định
46
-
47
- 1. **Quyết theo nhóm:** trước khi ghi, liệt kê lại **đúng các mã** sẽ nhận quyết định đó, rồi hỏi *"Đúng chưa?"*. Critical không được quyết theo nhóm.
48
- 2. Ghi quyết định vào `R` (`- Quyết định: …`). **Mọi** finding critical / major phải có quyết định khác `chờ`. Còn thiếu thì hỏi lại, tối đa 4 mã mỗi lượt.
49
- 3. Cập nhật dòng của lượt này trong bảng **Tóm tắt** của `R`: số `nhận` · `sửa` · `bác` · `hoãn`. Đây là số đo để đánh giá lớp kiểm chứng: **tỉ lệ bác cao nghĩa là kiểm chứng còn lỏng**.
50
- 4. Finding `nhận` hoặc `sửa`: áp vào `D` trong **một** lần `SE edit`, theo đúng luật của `.fw/core/ref/prd/change.md` (mã mới lấy số kế tiếp, mục bỏ thì gạch ngang, `(nguồn: PRD)`, có đổi luồng thì sửa cả mục User flow). Thêm một dòng Lịch sử thay đổi nêu mã finding, ví dụ *"v1.3 — refine lượt 1: F01, F03, F04"*.
51
- 5. Có áp bản sửa: tăng version phụ (`SE set D version=… status=draft approved_by=— approved_at=—`), rồi `SE set R status=applied`. Nếu đây là **lượt 1**, báo *"`/clear` rồi `/prd {id} refine` để chạy lượt 2, chỉ soi phần vừa sửa."*
52
- 6. Không áp gì (mọi finding đều bác / hoãn), **hoặc** vừa xong **lượt 2**: `SE set D refined={version hiện tại}` và `SE set R status=done`. Finding `hoãn` thì ghi thêm vào mục **Câu hỏi còn mở** của `D`, kèm chú thích *"(để bước QC)"*.
45
+ ## Bước D — Ghi quyết định, rồi áp
46
+
47
+ **Phiên chính chỉ hỏi và ghi quyết định.** Việc áp bản sửa vào PRD giao cho một sub-agent có ngữ cảnh mới, để phiên chính không phải nạp cả PRD lẫn các bản sửa.
48
+
49
+ 1. Muốn xem chi tiết một finding thì dùng `SE finding R F17` (không đọc cả lượt bằng `sed`).
50
+ 2. **Quyết theo nhóm:** trước khi ghi, liệt kê lại **đúng các mã** sẽ nhận quyết định đó, rồi hỏi *"Đúng chưa?"*. Critical không được quyết theo nhóm.
51
+ 3. **Ghi ngay sau mỗi đợt** PO quyết: `SE decide R <<'EOF'` `[{"f": "F17", "decision": "sửa: …"}, …]` `EOF`. Rồi báo một dòng: *"Đã lưu {k} quyết định. Còn {m} critical/major chờ. Nghỉ quá 1 giờ thì `/clear` rồi gọi lại lệnh, không mất gì."*
52
+ 4. **Mọi** finding critical / major phải có quyết định khác `chờ` thì mới sang bước 5. Còn thiếu thì hỏi tiếp, tối đa 4 mã mỗi lượt.
53
+ 5. Cập nhật dòng của lượt này trong bảng **Tóm tắt** của `R`: số `nhận` · `sửa` · `bác` · `hoãn`. **Tỉ lệ bác cao nghĩa là kiểm chứng còn lỏng.**
54
+ 6. Có finding `nhận` hoặc `sửa`: gọi **1 agent áp bản sửa** (công cụ **Agent**, `model: "opus"`). Giao: `D`, `R`, danh sách mã F cần áp, version mới (tăng version phụ), và `.fw/core/ref/prd/change.md` (phần **Lượt 2 — Áp thay đổi**). Agent:
55
+ - đọc từng finding bằng `SE finding`, đọc UC liên quan bằng `SE uc`;
56
+ - sửa hoặc thêm BR / AC **theo mã** bằng `SE item` (chỉ viết dòng mới); phần không phải dòng BR / AC (luồng, User flow, Tổng quan) thì dùng `SE edit`;
57
+ - thêm dòng Lịch sử thay đổi nêu mã finding, ví dụ *"v1.3 — refine lượt 1: F01, F03, F04"*;
58
+ - chạy `SE flowcheck D`, rồi `SE set D version=… status=draft approved_by=— approved_at=—` và `SE set R status=applied`;
59
+ - **chỉ trả về một dòng**: *"áp {k} finding → v{version}; {số BR/AC sửa · thêm · bỏ}"*.
60
+ 7. Lượt 1 có áp bản sửa: báo *"`/clear` rồi `/prd {id} refine` để chạy lượt 2, chỉ soi phần vừa sửa."*
61
+ 8. Không áp gì (mọi finding đều bác / hoãn), **hoặc** vừa xong **lượt 2**: `SE set D refined={version hiện tại}` và `SE set R status=done`. Finding `hoãn` thì ghi thêm vào mục **Câu hỏi còn mở** của `D`, kèm chú thích *"(để bước QC)"*.
@@ -47,4 +47,6 @@ Mỗi câu hỏi và câu trả lời được ghi vào **Nhật ký làm rõ**.
47
47
  - Không có hai BR mâu thuẫn nhau.
48
48
  4. Trình cho PO. PO chốt từng mục. Mục nào PO chưa chốt thì giữ dấu `🤖`.
49
49
 
50
+ **Ước lượng kích thước.** Từ phạm vi và luồng, ước lượng epic sẽ có bao nhiêu UC. Hơn khoảng 8 UC thì hỏi PO có tách epic không, và đề xuất cách tách theo mảng nghiệp vụ độc lập (ví dụ: tài khoản và đăng nhập · vai trò và quyền). Epic càng lớn thì PRD và mọi bước sau càng đắt.
51
+
50
52
  Chỉ đặt `status: ready` khi đủ cả hai điều kiện: **mọi mục đều mang dấu `✅`** và **mục `sec:open` = "Không còn"**. Còn câu hỏi mở thì vẫn ghi file, `status` giữ `in-progress`.
@@ -0,0 +1,32 @@
1
+ # type: bdd
2
+ # uc: {UC-NNN}
3
+ # prd_version: {version PRD đang viết theo}
4
+ # version: 1.0
5
+ # status: draft # draft | approved
6
+ # approved_by: — # người duyệt BDD; bắt buộc có khi status: approved
7
+ # approved_at: — # YYYY-MM-DD
8
+ # updated: {YYYY-MM-DD}
9
+ #
10
+ # Kịch bản BDD của {UC-NNN}. Nguồn: ../prd.md
11
+ # Tag mỗi kịch bản: đúng 1 mã @{UC-NNN}-SCnn · nền tảng (@web @app …, chỉ những gì UC khai)
12
+ # · đúng 1 loại (@happy @alternative @edge @negative) · mã đầy đủ của AC/BR được phủ (@{UC-NNN}-AC01 @{UC-NNN}-BR04).
13
+ # Mã kịch bản không bao giờ đổi, không dùng lại. Kịch bản bỏ đi còn lại dòng "# Đã bỏ (v…) @mã — tên".
14
+ # Điều AI giả định mà PRD chưa ghi: một dòng comment mang dấu chờ PO chốt, ngay trên tag, kèm mã kịch bản (xem SC02).
15
+ Feature: {UC-NNN} — {Tên use case}
16
+
17
+ # ── {Chủ đề nghiệp vụ, ví dụ: Import file} ──
18
+ @{UC-NNN}-SC01 @web @happy @{UC-NNN}-AC01 @{UC-NNN}-BR04
19
+ Scenario: {Một hành vi, viết bằng ngôn ngữ nghiệp vụ}
20
+ Given {trạng thái ban đầu, giá trị cụ thể}
21
+ When {actor làm gì}
22
+ Then {kết quả nhìn thấy được}
23
+ And {hệ quả đi kèm: ghi lịch sử, gửi email…}
24
+
25
+ # 🤖 {UC-NNN}-SC02: {điều AI giả định, vì PRD chưa ghi}
26
+ @{UC-NNN}-SC02 @web @negative @{UC-NNN}-BR11
27
+ Scenario Outline: {Các biến thể của cùng một luật}
28
+ When {actor làm gì với "<giá trị>"}
29
+ Then {kết quả}
30
+ Examples:
31
+ | giá trị |
32
+ | {…} |
package/templates/prd.md CHANGED
@@ -21,6 +21,7 @@ updated: {YYYY-MM-DD}
21
21
 
22
22
  - **Mục tiêu:** {…}
23
23
  - **Actor:** {ACT-xx (chính) · ACT-yy (phụ)}
24
+ - **Nền tảng:** {web · app — nơi người dùng dùng tính năng; là mặc định cho mọi UC}
24
25
  - **Trong phạm vi:**
25
26
  - {…}
26
27
  - **Ngoài phạm vi:**
@@ -52,6 +53,7 @@ flowchart TD
52
53
 
53
54
  - **Jira:** {key hoặc —}
54
55
  - **Actor:** {ACT-xx}
56
+ - **Nền tảng:** {chỉ ghi khi UC này chạy khác Tổng quan, ví dụ chỉ app; giống thì bỏ dòng này}
55
57
  - **Điều kiện trước:** {…}
56
58
  - **Kết quả sau:** {…}
57
59