@educa-corp/fw 0.8.1 → 0.11.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.
- package/CHANGELOG.md +30 -0
- package/commands/bdd.md +70 -0
- package/commands/prd.md +17 -22
- package/commands/product.md +10 -26
- package/docs/guide/02-khai-niem.md +3 -0
- package/docs/guide/README.md +10 -6
- package/docs/guide/cach-lam/quyet-finding-refine.md +3 -1
- package/docs/guide/lenh/bdd.md +94 -0
- package/docs/guide/lenh/prd-refine.md +7 -5
- package/docs/guide/lenh/prd-review.md +53 -0
- package/docs/guide/lenh/prd.md +4 -3
- package/docs/guide/vai-tro/po-ba.md +7 -5
- package/docs/guide/xu-ly-su-co.md +8 -0
- package/package.json +1 -1
- package/ref/bdd/change.md +47 -0
- package/ref/bdd/new.md +39 -0
- package/ref/bdd/writing.md +44 -0
- package/ref/common.md +47 -0
- package/ref/prd/change.md +3 -2
- package/ref/prd/new.md +6 -3
- package/ref/prd/refine.md +32 -10
- package/ref/prd/review.md +77 -0
- package/ref/product/epic.md +2 -0
- package/templates/bdd.feature +32 -0
- package/templates/prd.md +3 -0
- package/tools/spec_edit.py +692 -12
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
## Đường đi của bạn
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
/product ──► /product EP-xx ──► /prd EP-xx ──►
|
|
11
|
-
▲
|
|
12
|
-
└─ /prd EP-xx change
|
|
10
|
+
/product ──► /product EP-xx ──► /prd EP-xx ──► refine ──► review ──► duyệt PRD ──► /bdd UC-xxx ──► duyệt BDD
|
|
11
|
+
▲ (từng UC)
|
|
12
|
+
└─ /prd EP-xx change: refine, review lại, duyệt lại, rồi /bdd UC-xxx để bù
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
| Bước | Lệnh | Bạn làm gì | Hướng dẫn |
|
|
@@ -17,8 +17,10 @@
|
|
|
17
17
|
| 1 | `/product` | Trả lời về sản phẩm, nhóm người dùng, epic, ràng buộc. Chốt từng mục | [/product](../lenh/product.md) |
|
|
18
18
|
| 2 | `/product EP-xx` | Trả lời AI hỏi về tính năng. Đây là chỗ **quan trọng nhất**: câu trả lời càng rõ thì PRD càng ít phải sửa | [/product](../lenh/product.md#một-epic-product-ep-01) |
|
|
19
19
|
| 3 | `/prd EP-xx` | Duyệt cách chia UC, xác nhận các mục 🤖 | [/prd](../lenh/prd.md) |
|
|
20
|
-
| 4 | `/prd EP-xx refine` | Quyết từng finding: nhận, sửa, bác hay hoãn. Tối đa 2 lượt
|
|
21
|
-
|
|
|
20
|
+
| 4 | `/prd EP-xx refine` | Quyết từng finding: nhận, sửa, bác hay hoãn. Tối đa 2 lượt | [/prd refine](../lenh/prd-refine.md) |
|
|
21
|
+
| 4b | `/prd EP-xx review` | Xem các đề xuất sửa câu chữ, quyết theo nhóm (*"nhận hết trừ R03"*). Xong thì duyệt PRD | [/prd review](../lenh/prd-review.md) |
|
|
22
|
+
| 5 | `/bdd UC-xxx` | Với từng UC: duyệt dàn ý kịch bản (soát xem có sót nhánh nào không), xác nhận các mục 🤖, duyệt BDD | [/bdd](../lenh/bdd.md) |
|
|
23
|
+
| 6 | `/prd EP-xx change …` | Khi yêu cầu đổi. Duyệt kế hoạch thay đổi, refine và review lại phần vừa đổi, duyệt lại PRD, rồi `/bdd UC-xxx` để bù | [/prd](../lenh/prd.md#đổi-prd-prd-ep-01-change-mô-tả) |
|
|
22
24
|
|
|
23
25
|
## Cách làm thường gặp
|
|
24
26
|
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
| AI chạy lại cùng một lệnh `spec_edit` | Lần trước Python thoát mà không chạy (thường gặp với bản Store) | Bình thường, AI được dặn chạy lại một lần |
|
|
21
21
|
| `không đặt được status=approved: còn 3 dòng 🤖` | Còn mục chưa được bạn xác nhận | Xác nhận các mục AI liệt kê |
|
|
22
22
|
| `… chưa có approved_by` | Chưa ghi người duyệt | Trả lời câu *"Ai duyệt?"* |
|
|
23
|
+
| `⚠ PRD 89 KB (ngưỡng 60 KB) …` | PRD lớn, mọi bước sau đều nạp toàn bộ | Không chặn. Cân nhắc tách epic. Epic mới thì nên tách từ bước `/product` |
|
|
23
24
|
| `PRD chưa có mục User flow` | PRD tạo bằng bản trước 0.8.0 | Chạy `/prd EP-xx change thêm User flow` |
|
|
24
25
|
| `UC chưa có mặt trong hành trình nào của User flow: UC-007` | Có UC chưa được vẽ vào sơ đồ nào | AI sẽ bổ sung. Hoặc chạy `/prd EP-xx change thêm UC-007 vào user flow` |
|
|
25
26
|
| `… bản v1.2 chưa refine` | PRD chưa được rà nội dung ở version này | Chạy `/prd EP-xx refine` |
|
|
@@ -27,6 +28,13 @@
|
|
|
27
28
|
| `Bản v1.1 đã refine xong` | Gọi refine lại khi PRD chưa đổi | Không cần làm gì. Thật sự muốn rà lại từ đầu thì thêm `--full` |
|
|
28
29
|
| `chưa được PRD dùng tới: BR7, AC12` | Có BR hoặc AC của epic chưa được đưa vào PRD | AI sẽ bổ sung. Nếu bạn muốn bỏ thì nói rõ |
|
|
29
30
|
| `(nguồn: …) chỉ được ghi mã …` | PRD đang ghi nguồn bằng lời (thường là PRD tạo bằng bản trước 0.6.1) | AI sẽ đổi thành mã, thường là `PRD` |
|
|
31
|
+
| `… chưa rà hình thức (reviewed=…)` | PRD chưa qua `/prd … review` ở version này | Chạy `/prd EP-xx review`. PRD đã duyệt trước bản 0.11.0 vẫn giữ `approved`, nhưng `/bdd` sẽ dừng cho tới khi review xong |
|
|
32
|
+
| `Nền tảng ghi sai khuôn ở UC-009` | Dòng Nền tảng ghi bằng lời thay vì mã | `/prd EP-xx review` sẽ đề xuất sửa thành `system — …` (hoặc `web`, `app`) |
|
|
33
|
+
| `chỗ sửa #2 không phải sửa hình thức: mất 1.000 · thêm 2.000` | Lúc review, có một chỗ sửa làm đổi số, mã, dấu hoặc nguồn | Đó là đổi nghĩa. AI bỏ chỗ đó và ghi thành ghi chú. Muốn đổi thật thì dùng `/prd EP-xx change` |
|
|
34
|
+
| `chưa khai Nền tảng cho UC-001, UC-002` | PRD chưa có dòng Nền tảng (thường là PRD tạo bằng bản trước 0.10.0) | Chạy `/prd EP-xx change khai nền tảng: web` (hoặc `web · app`) |
|
|
35
|
+
| `AC/BR của UC-001 chưa có kịch bản nào: …` | BDD còn sót AC hoặc BR | AI sẽ bổ sung. Đã duyệt BDD rồi mà PRD mới thêm mục thì chạy `/bdd UC-001` để bù |
|
|
36
|
+
| `@UC-001-BR08 đã bỏ trong PRD` | Kịch bản trỏ tới mục PRD vừa bỏ | Chạy `/bdd UC-001`: AI đề xuất sửa hoặc bỏ kịch bản đó |
|
|
37
|
+
| `⚠ PRD đã ở v1.6, BDD viết theo v1.5` | PRD đổi sau khi viết BDD | Chạy `/bdd UC-xxx` để bù. BDD chỉ duyệt được khi viết theo đúng version PRD hiện tại |
|
|
30
38
|
| `💡 Phiên này đã dài. Nên /clear …` | Phiên đang mang theo hội thoại cũ | Gõ `/clear` rồi gọi lại lệnh |
|
|
31
39
|
| `EP-xx chưa làm rõ xong. Chạy /product EP-xx trước` | Epic chưa `ready` | Chạy tiếp `/product EP-xx`. Thật sự cần PRD sớm thì thêm `--force`, PRD sẽ được ghi chú là tạo khi epic chưa xong |
|
|
32
40
|
| `PRD đã có …` | Gọi `/prd EP-xx` khi PRD đã tồn tại | Rà nội dung: `/prd EP-xx refine` · Đổi: `/prd EP-xx change <mô tả>` |
|
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# /bdd — chế độ bù và chế độ đổi
|
|
2
|
+
|
|
3
|
+
Cả hai chế độ đều sửa **theo mã**: không đánh số lại, mã đã bỏ không dùng lại. Chỉ viết khối mới, không chép khối cũ.
|
|
4
|
+
|
|
5
|
+
## Bù — `/bdd UC-xxx` khi đã có file
|
|
6
|
+
|
|
7
|
+
Mục đích: đưa BDD theo kịp PRD. Ví dụ PRD vừa qua `/prd change`, hoặc có AC/BR chưa có kịch bản.
|
|
8
|
+
|
|
9
|
+
1. Chạy `SE bddcheck F`. Ghi lại:
|
|
10
|
+
- **lỗi**: AC/BR chưa có kịch bản, tag trỏ tới mục đã bỏ hoặc không có;
|
|
11
|
+
- **cảnh báo** *"PRD đã ở v…, BDD viết theo v…"*.
|
|
12
|
+
2. Có cảnh báo version thì đọc `SE section D history`. Lấy các dòng có version **lớn hơn** `prd_version` của `F`, rồi lọc ra những mục **thuộc UC này** (mã UC, BR, AC nêu trong dòng). Đây là các mục đã **đổi nội dung**, mà `bddcheck` không tự biết được. Dòng chỉ ghi mã finding thì đọc `SE finding {thư mục của D}/review/prd-refine.md F…` để biết mục nào đổi.
|
|
13
|
+
3. Không có lỗi, cũng không có mục nào đổi: báo *"BDD của UC-xxx đã khớp PRD v…: {dòng số liệu}. Muốn thêm hoặc sửa kịch bản: `/bdd UC-xxx change <mô tả>`."*, rồi sang Bước 4 của lệnh.
|
|
14
|
+
4. Đọc các kịch bản liên quan bằng `SE scenario F <mã AC/BR>`, lệnh này in mọi kịch bản gắn mã đó. Cùng lúc chỉ cần đọc đúng mục PRD trong kết quả `SE context`.
|
|
15
|
+
5. Lập **kế hoạch**, rồi sang phần **Áp**.
|
|
16
|
+
|
|
17
|
+
## Đổi — `/bdd UC-xxx change <mô tả>`
|
|
18
|
+
|
|
19
|
+
Mục đích: kịch bản **có rồi nhưng chưa đủ ý**, mà script không bắt được. Ví dụ BR có 3 nhánh nhưng chỉ có kịch bản cho 1 nhánh. Thường do PO, dev hoặc QC phát hiện.
|
|
20
|
+
|
|
21
|
+
1. Lấy mô tả từ `$ARGUMENTS`. Không có mô tả thì hỏi *"Bạn muốn thêm, sửa hay bỏ kịch bản nào?"* rồi dừng.
|
|
22
|
+
2. Đối chiếu mô tả với kết quả `SE context`:
|
|
23
|
+
- Hành vi **đã có** trong một AC/BR của UC: lập kế hoạch, rồi sang phần **Áp**.
|
|
24
|
+
- Hành vi **chưa có** trong AC/BR nào, hoặc **trái** với PRD: **từ chối**. Báo *"Điều này chưa có trong PRD (gần nhất là {mã}: …). Đây là thay đổi yêu cầu: chạy `/prd EP-xx change …` trước, rồi `/bdd UC-xxx` để bù."*, rồi dừng.
|
|
25
|
+
|
|
26
|
+
## Kế hoạch (chung cho bù và đổi)
|
|
27
|
+
|
|
28
|
+
| Mã | Loại | Vì sao | Hiện tại → Sẽ thành |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| UC-001-SC04 | sửa | UC-001-BR14 đổi 1.000 → 2.000 dòng (v1.6) | 1.001 dòng bị từ chối → 2.001 dòng bị từ chối |
|
|
31
|
+
| UC-001-SC15 | thêm | UC-001-AC10 mới (v1.6) | — → Import file có dòng thiếu họ tên |
|
|
32
|
+
| UC-001-SC09 | bỏ | UC-001-BR08 đã bỏ (v1.6) | ~~Username Admin đặt bị trùng~~ |
|
|
33
|
+
|
|
34
|
+
Mỗi ô "Sẽ thành" chỉ một dòng, không viết Given/When/Then. Kèm tối đa 4 câu hỏi, chỉ khi cần.
|
|
35
|
+
|
|
36
|
+
## Áp
|
|
37
|
+
|
|
38
|
+
Khi PO đồng ý kế hoạch:
|
|
39
|
+
|
|
40
|
+
1. Lấy mã cho kịch bản mới bằng `SE next-sc F`, rồi tăng dần.
|
|
41
|
+
2. Áp mọi thay đổi bằng **một** lần `SE sc F`:
|
|
42
|
+
- `{"id": mã, "new": khối}`: thay cả khối, giữ nguyên mã;
|
|
43
|
+
- `{"after": mã | "end", "new": khối}`: thêm sau một kịch bản, hoặc cuối file;
|
|
44
|
+
- `{"remove": mã, "version": "<version mới>"}`: bỏ, để lại dòng `# Đã bỏ (v…)`.
|
|
45
|
+
3. Chạy `SE bddcheck F` cho tới khi sạch.
|
|
46
|
+
4. Tăng version phụ (1.0 → 1.1) và đặt lại header trong **một** lệnh: `SE set F version=… prd_version=<version PRD> updated=…`. Nếu `F` đang `approved` thì đặt luôn `status=draft approved_by=— approved_at=—`.
|
|
47
|
+
5. Báo lại cho PO. Không in lại cả file, chỉ tóm tắt những gì đã đổi. Không còn `🤖` 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.
|
package/ref/bdd/new.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# /bdd — chế độ tạo
|
|
2
|
+
|
|
3
|
+
Chỉ **2 lượt** hỏi-đáp. PRD đã được duyệt và refine, nên không hỏi lại những gì PRD đã ghi rõ.
|
|
4
|
+
|
|
5
|
+
## Lượt 1 — Dàn ý
|
|
6
|
+
|
|
7
|
+
1. Từ kết quả `SE context`, liệt kê mọi AC và BR **còn dùng** của UC. Với từng BR, tách các nhánh trong cột Business Logic (luật 2.1 trong `writing.md`).
|
|
8
|
+
2. Lập dàn ý theo `writing.md`. Mã bắt đầu từ `UC-NNN-SC01`, tăng dần theo thứ tự trong file. Gom theo chủ đề nghiệp vụ.
|
|
9
|
+
3. Trình cho PO **ba phần**, không trình nội dung Given/When/Then:
|
|
10
|
+
|
|
11
|
+
**a. Dàn ý**
|
|
12
|
+
|
|
13
|
+
| Mã | Kịch bản | Loại | Nền tảng | Phủ |
|
|
14
|
+
|---|---|---|---|---|
|
|
15
|
+
| UC-001-SC01 | Import có dòng trùng email với tài khoản đã có | happy | web | AC01 · BR04 |
|
|
16
|
+
| UC-001-SC02 | Username không hợp lệ (Outline: "@", có dấu, khoảng trắng) | negative | web | AC07 · BR11 |
|
|
17
|
+
|
|
18
|
+
**b. Nhánh.** Chỉ liệt kê các BR có từ 2 nhánh trở lên, để PO soát xem có sót nhánh nào không:
|
|
19
|
+
|
|
20
|
+
| BR | Nhánh | Kịch bản |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| UC-001-BR01 | Email trống · sai định dạng | SC03 (dòng 1, 2) |
|
|
23
|
+
| | Đã thuộc nhân sự khác | SC04 |
|
|
24
|
+
|
|
25
|
+
**c. Điểm giao nhận** với UC khác, lấy từ User flow. Mỗi điểm một dòng, ví dụ *"→ UC-003: người dùng nhận email có link đặt mật khẩu (Then của SC06)"*.
|
|
26
|
+
|
|
27
|
+
Kèm tối đa 4 câu hỏi, chỉ khi cần. Ví dụ: BR không tìm được kịch bản nào, điều phải giả định vì PRD chưa ghi, chỗ PRD mơ hồ. Không có gì cần hỏi thì chỉ hỏi *"Dàn ý này được chưa?"*.
|
|
28
|
+
|
|
29
|
+
## Lượt 2 — Ghi file
|
|
30
|
+
|
|
31
|
+
Khi PO đồng ý dàn ý (có chỉnh thì làm theo chỉnh):
|
|
32
|
+
|
|
33
|
+
1. Tạo `F` bằng **một** lần `SE create`, theo khuôn `.fw/core/templates/bdd.feature`:
|
|
34
|
+
- Header: `prd_version` = version PRD đang có (dòng đầu của `SE context`), `version: 1.0`, `status: draft`.
|
|
35
|
+
- Thay các chỗ `{…}` trong dòng comment hướng dẫn của khuôn bằng mã UC thật.
|
|
36
|
+
- Chỗ AI giả định thì thêm dòng `# 🤖 UC-NNN-SCnn: …` ngay trên tag (luật 1.6 trong `writing.md`).
|
|
37
|
+
2. Chạy `SE bddcheck F`. Có lỗi thì sửa bằng **một** lần `SE sc F` (thay hoặc thêm theo mã), rồi chạy lại cho tới khi sạch. **Không được tự bỏ tag AC/BR để qua kiểm.** BR nào không viết được kịch bản thì hỏi PO.
|
|
38
|
+
3. Chạy `SE pending F`. **Chỉ trình các mục `🤖`** và dòng số liệu của `bddcheck`, không in lại cả file. Nhắc PO: *"Mở file để đọc toàn bộ. Xác nhận theo mã, ví dụ 'OK UC-001-SC07', hoặc sửa, ví dụ 'SC07: câu báo là …'."*
|
|
39
|
+
4. PO xác nhận thì chạy `SE confirm F <mã…>`. PO sửa thì thay khối bằng `SE sc F` và bỏ dòng `🤖` của kịch bản đó. Không còn `🤖` thì duyệt theo luật 5 (Duyệt) trong Bước 3 của lệnh.
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
5. **`@system`** dành cho luồng tự động, không có màn hình: job chạy định kỳ, tích hợp với hệ thống khác. `When` là một sự kiện, ví dụ *"EP-03 chuyển sang đơn hàng của học sinh "Lan""* hoặc *"đã đủ 7×24 giờ kể từ lúc tạo"*. `Then` là kết quả nhìn thấy được trong dữ liệu, trong email gửi đi, hoặc trong thông báo trả về hệ thống kia.
|
|
30
|
+
|
|
31
|
+
## 4. Điểm giao nhận với UC khác
|
|
32
|
+
|
|
33
|
+
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õ.
|
|
34
|
+
|
|
35
|
+
## 5. Loại và nhóm
|
|
36
|
+
|
|
37
|
+
| Loại | Khi nào |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `@happy` | Luồng chính, thành công |
|
|
40
|
+
| `@alternative` | Luồng khác, vẫn thành công. Ví dụ không đặt username thì hệ thống tự sinh |
|
|
41
|
+
| `@edge` | Biên, giới hạn, mốc thời gian |
|
|
42
|
+
| `@negative` | Bị từ chối, lỗi, không có quyền |
|
|
43
|
+
|
|
44
|
+
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ã…>`. Dòng không có mã thì xác nhận theo số dòng mà `pending` in ra: `SE confirm <file> L24` |
|
|
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,11 @@ 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. **
|
|
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
|
+
- Dòng **Nền tảng** (ở Tổng quan, hoặc trong UC chạy khác mặc định) chỉ ghi mã: `web`, `app` (nơi người dùng dùng tính năng), `system` (luồng tự động, không có màn hình). Giải thích để sau dấu ` — `. Ví dụ: `- ✅ **Nền tảng:** system — luồng tự động nhận đơn từ EP-03`.
|
|
32
33
|
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.
|
|
34
|
+
3. Báo lại cho PO. Không in lại cả PRD, chỉ tóm tắt những gì đã đổi. Còn `🤖` thì xác nhận trước. Bản mới chưa duyệt được ngay, vì phải refine rồi review lại phần vừa đổi. Báo: *"Bước tiếp: `/clear` rồi `/prd {id} refine`, sau đó `/prd {id} review`, rồi duyệt."* Bản mới cần người duyệt mới, nên khi duyệt phải đặ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
|
|
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
|
@@ -19,7 +19,7 @@ Xét **từ trên xuống**, gặp dòng nào khớp trước thì theo dòng đ
|
|
|
19
19
|
| `refined` = `version` | **Dừng.** Báo *"Bản v{version} đã refine xong."* Có `--full` thì chạy lượt 1 trên toàn PRD | — |
|
|
20
20
|
| Chưa có `R`, hoặc chưa từng refine | **1** | Toàn bộ PRD |
|
|
21
21
|
| `R` có `round: 1` **đã áp** bản sửa, `prd_version` < `version` | **2** | Chỉ các mục mà lượt 1 đã sửa hoặc thêm (đọc từ quyết định `nhận` / `sửa` trong `R`), cộng các mục tham chiếu tới chúng |
|
|
22
|
-
| `refined` có giá trị nhưng < `version` (PRD đã qua `/prd change`) | **1** | Chỉ các mục trong dòng Lịch sử thay đổi
|
|
22
|
+
| `refined` có giá trị nhưng < `version` (PRD đã qua `/prd change`) | **1** | Chỉ các mục trong các dòng Lịch sử thay đổi (`SE section D history`) có version lớn hơn `refined` |
|
|
23
23
|
|
|
24
24
|
**Không có lượt 3.** Sau lượt 2 thì luôn đặt `refined` (Bước D).
|
|
25
25
|
|
|
@@ -27,11 +27,24 @@ Xét **từ trên xuống**, gặp dòng nào khớp trước thì theo dòng đ
|
|
|
27
27
|
|
|
28
28
|
Phiên chính **không đọc** kết quả chi tiết của các agent. Agent ghi ra file, phiên chính chỉ đọc bảng tóm tắt cuối cùng.
|
|
29
29
|
|
|
30
|
-
1.
|
|
30
|
+
1. **Chọn số agent rà** theo lượt và phạm vi ở Bước A. Đếm UC bằng các mã `UC-…` nêu trong phạm vi. Thay đổi chỉ ở Tổng quan, User flow hoặc Màn hình tính là 0 UC.
|
|
31
|
+
|
|
32
|
+
| Lượt và phạm vi | Agent rà |
|
|
33
|
+
|---|---|
|
|
34
|
+
| Lượt 1, toàn bộ PRD | **4 agent**: QA · DEV · SA · Phạm vi |
|
|
35
|
+
| Lượt 1 sau `/prd change`, phạm vi chạm **≤ 3 UC** | **1 agent gộp** |
|
|
36
|
+
| Lượt 1 sau `/prd change`, phạm vi chạm > 3 UC | **4 agent** |
|
|
37
|
+
| Lượt 2 | **1 agent gộp** |
|
|
38
|
+
|
|
39
|
+
**Agent gộp** soi lần lượt cả 4 phần QA, DEV, SA, Phạm vi trong `lenses.md`. Mỗi finding ghi đúng `lens:` của phần đã phát hiện ra nó. Agent vẫn **đọc toàn bộ `D`**, để bắt được lỗi lan sang UC khác. Agent này nhận đủ tài liệu phụ của Phạm vi, và ghi vào `W/round-{n}-all.md`. Lý do: phạm vi hẹp thì một agent soi đủ 4 góc nhìn, nên không cần 4 agent cùng đọc lại cả PRD.
|
|
40
|
+
|
|
41
|
+
Dùng công cụ **Agent**, `model: "opus"`. Có nhiều agent thì gọi **song song trong cùng một lượt**. Mỗi agent nhận:
|
|
31
42
|
- đường dẫn `D` (**đọc toàn bộ**), `R` (nếu có, để đọc sổ quyết định), `.fw/core/ref/prd/lenses.md`, tên lăng kính, **phạm vi** và **ngưỡng báo** của lượt (lượt 1: mọi mức · lượt 2: chỉ critical hoặc lỗi do chính bản sửa gây ra);
|
|
32
43
|
- riêng **Phạm vi**: thêm các lệnh để đọc tài liệu phụ, **chỉ đúng phần cần**: `SE section <epic> cp1`, `SE section {specs}/product/product.md constraints`, `SE section {specs}/product/product.md epics`;
|
|
33
44
|
- file kết quả: `W/round-{n}-{lens}.md`. Agent ghi bằng `SE create --replace` (chỉ dùng được trong `.fw/tmp/`) và **chỉ trả về một dòng**: *"{lens}: {k} finding → {file}"*.
|
|
34
|
-
2.
|
|
45
|
+
2. **Tổng finding thô = 0** (mọi agent đều trả *"0 finding"*) và đã có `R`: **không gọi agent kiểm chứng**. Phiên chính tự ghi vào `R` bằng **một** lần `SE edit`: thêm mục `## Lượt {n} — v{version} <!-- sec:round-{k} -->` ở cuối (`k` = số `round-…` lớn nhất trong `R` cộng một), với một dòng *"Phạm vi: … · 0 finding thô"*, và thêm một dòng vào bảng Tóm tắt (các cột số đều 0, Kết luận `APPROVED`). Sau đó `SE set R prd_version={version} round={n}`, rồi sang thẳng **Bước D, bước 8**.
|
|
46
|
+
|
|
47
|
+
Còn lại: khi đủ dòng trả về của các agent rà, gọi **1 agent kiểm chứng** (`model: "opus"`), giao: `D`, `R`, `W`, số lượt `n`, mã F kế tiếp (lớn nhất trong `R` cộng một, hoặc F01), và phần **"Kiểm chứng và ghi file"** trong `lenses.md`. Agent này kiểm chứng, gộp, sắp xếp, đánh mã, ghi vào `R`, rồi trả về **một dòng** số liệu. File kết quả trong `W` có thể là 4 file theo lăng kính, hoặc 1 file `round-{n}-all.md`.
|
|
35
48
|
|
|
36
49
|
## Bước C — Trình
|
|
37
50
|
|
|
@@ -42,11 +55,20 @@ Phiên chính **không đọc** kết quả chi tiết của các agent. Agent g
|
|
|
42
55
|
- *"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
56
|
4. Lượt này không có finding nào thì báo, rồi sang Bước D luôn.
|
|
44
57
|
|
|
45
|
-
## Bước D —
|
|
58
|
+
## Bước D — Ghi quyết định, rồi áp
|
|
59
|
+
|
|
60
|
+
**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.
|
|
46
61
|
|
|
47
|
-
1.
|
|
48
|
-
2.
|
|
49
|
-
3.
|
|
50
|
-
4.
|
|
51
|
-
5.
|
|
52
|
-
6.
|
|
62
|
+
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`).
|
|
63
|
+
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.
|
|
64
|
+
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ì."*
|
|
65
|
+
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.
|
|
66
|
+
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.**
|
|
67
|
+
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:
|
|
68
|
+
- đọc từng finding bằng `SE finding`, đọc UC liên quan bằng `SE uc`;
|
|
69
|
+
- 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`;
|
|
70
|
+
- thêm dòng Lịch sử thay đổi nêu mã finding, ví dụ *"v1.3 — refine lượt 1: F01, F03, F04"*;
|
|
71
|
+
- chạy `SE flowcheck D`, rồi `SE set D version=… status=draft approved_by=— approved_at=—` và `SE set R status=applied`;
|
|
72
|
+
- **chỉ trả về một dòng**: *"áp {k} finding → v{version}; {số BR/AC sửa · thêm · bỏ}"*.
|
|
73
|
+
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."*
|
|
74
|
+
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)"*. Rồi báo: *"Refine xong v{version}. Bước tiếp: `/clear` rồi `/prd {id} review` để rà hình thức, bắt buộc trước khi duyệt."*
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# /prd — chế độ rà hình thức (review)
|
|
2
|
+
|
|
3
|
+
Mục đích: rà **câu chữ, chính tả, thuật ngữ, trình bày, đúng khuôn**, để người và AI ở các bước sau đọc đúng ý. **Không** rà nội dung nghiệp vụ, vì đó là việc của `refine` và đã làm xong.
|
|
4
|
+
|
|
5
|
+
- **Review đi sau refine.** Refine làm đổi câu chữ, nên rà hình thức trước thì phải rà lại.
|
|
6
|
+
- **Sửa trong cùng version, không được đổi nghĩa.** Không tăng version. PRD đang `approved` thì vẫn giữ `approved`. `SE edit --form` tự chặn mọi chỗ sửa làm đổi số, mã, dấu `🤖`/`✅`, gạch ngang hoặc nguồn.
|
|
7
|
+
- Thư mục làm việc: `W = .fw/tmp/review/{slug}/`, không commit. File kết quả: `W/review-{version}.md`.
|
|
8
|
+
|
|
9
|
+
## Bước A — Xác định phạm vi
|
|
10
|
+
|
|
11
|
+
Chạy `SE upgrade D` trước, để PRD tạo bằng bản cũ có trường `reviewed`. Đọc frontmatter của `D` (`version`, `refined`, `reviewed`, `status`).
|
|
12
|
+
|
|
13
|
+
Xét **từ trên xuống**, gặp dòng nào khớp trước thì theo dòng đó.
|
|
14
|
+
|
|
15
|
+
| Tình huống | Làm gì |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `refined` ≠ `version` | **Dừng.** Báo *"Bản v{version} chưa refine. Chạy `/prd {id} refine` trước. Review đi sau refine."* |
|
|
18
|
+
| `reviewed` = `version`, không có `--full` | **Dừng.** Báo *"Bản v{version} đã rà hình thức xong."* |
|
|
19
|
+
| Đã có `W/review-{version}.md` (rà xong, đang chờ PO quyết) | **Không rà lại.** Sang thẳng Bước C |
|
|
20
|
+
| `reviewed` là `—` (chưa từng review), hoặc có `--full` | Phạm vi: **toàn bộ PRD** |
|
|
21
|
+
| `reviewed` < `version` | Phạm vi: chỉ các mục nêu trong các dòng Lịch sử thay đổi (`SE section D history`) có version **lớn hơn** `reviewed` |
|
|
22
|
+
|
|
23
|
+
## Bước B — Rà (1 sub-agent)
|
|
24
|
+
|
|
25
|
+
Dùng công cụ **Agent**, `model: "sonnet"`, gọi **1** agent. Giao cho agent: đường dẫn `D`, phạm vi, `{specs}/product/glossary.md` (nếu có), file kết quả `W/review-{version}.md`, và phần **"Dành cho agent rà"** ở cuối file này. Agent **chỉ trả về một dòng**. Phiên chính không đọc PRD.
|
|
26
|
+
|
|
27
|
+
## Bước C — Trình
|
|
28
|
+
|
|
29
|
+
1. Đọc `W/review-{version}.md` (file nhỏ).
|
|
30
|
+
2. Trình theo thứ tự:
|
|
31
|
+
- **Đã tự sửa (A):** chỉ báo số chỗ, kèm 2–3 ví dụ. Danh sách đầy đủ nằm trong file.
|
|
32
|
+
- **Bảng đề xuất (B):** mã · loại · mục · *trước → sau*, rút gọn mỗi bên khoảng 60 ký tự.
|
|
33
|
+
- **Ghi chú (C):** những chỗ muốn sửa thì phải đổi nghĩa. Mỗi chỗ một dòng, kèm gợi ý `/prd {id} change …`.
|
|
34
|
+
3. Nhắc PO cách quyết: *"Quyết theo mã: 'nhận hết' · 'nhận hết trừ R03' · 'R04 sửa thành …' · 'bác R05'."* Không có đề xuất nào thì sang thẳng Bước D.
|
|
35
|
+
|
|
36
|
+
## Bước D — Áp
|
|
37
|
+
|
|
38
|
+
1. Áp các đề xuất được nhận bằng **một** lần `SE edit --form D`, với `old` là "Trước" và `new` là "Sau" (hoặc bản PO sửa). `SE` chặn chỗ nào thì chỗ đó làm đổi nghĩa: bỏ chỗ đó ra khỏi lần sửa, báo PO, và chuyển nó thành ghi chú C.
|
|
39
|
+
2. Có chỗ nào được sửa (A hoặc B) thì thêm **một** dòng vào cuối bảng Lịch sử thay đổi bằng `SE edit D`, **giữ nguyên version**: `| {version} | {ngày} | Rà hình thức: sửa {k} chỗ (chính tả, câu chữ, thuật ngữ, khuôn). Không đổi nội dung |`.
|
|
40
|
+
3. `SE set D reviewed={version} updated={ngày}`.
|
|
41
|
+
- PRD đang `approved` thì `SE` kiểm lại mọi điều kiện duyệt. Báo lỗi thì sửa theo lỗi, thường là một dòng sai khuôn còn sót, rồi chạy lại.
|
|
42
|
+
- PRD đang `draft`: không còn `🤖`, không còn câu hỏi mở thì hỏi *"Duyệt bản v{version} không?"* và duyệt theo luật 5 (Duyệt) trong Bước 3 của lệnh.
|
|
43
|
+
4. Còn ghi chú C thì nhắc PO một dòng. Ghi chú **không chặn** duyệt.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Dành cho agent rà
|
|
48
|
+
|
|
49
|
+
Bạn rà **hình thức** của PRD trong đúng phạm vi được giao. Phạm vi là toàn bộ PRD thì đọc cả file. Phạm vi hẹp thì đọc `SE uc D UC-…` và `SE section D <mã mục>`, cộng mục Tổng quan để biết thuật ngữ trong phần Khái niệm. `SE` = `python .fw/core/tools/spec_edit.py`.
|
|
50
|
+
|
|
51
|
+
**Ba loại:**
|
|
52
|
+
|
|
53
|
+
| Loại | Gồm | Làm gì |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| **A. Tự sửa** | Chính tả, dấu tiếng Việt, dấu câu, khoảng trắng thừa, bảng vỡ cột, danh sách lệch | Sửa luôn bằng **một** lần `SE edit --form D`. `SE` chặn chỗ nào thì chuyển chỗ đó sang B hoặc C |
|
|
56
|
+
| **B. Đề xuất** | Câu khó hiểu (quá dài, nhiều mệnh đề lồng nhau, đại từ không rõ chỉ ai, phủ định kép) · một khái niệm gọi hai tên, hoặc sai so với glossary và phần Khái niệm · dòng sai khuôn, ví dụ dòng Nền tảng ghi bằng lời thay vì mã `web` · `app` · `system` | **Không sửa.** Ghi vào file để PO quyết |
|
|
57
|
+
| **C. Ghi chú** | Chỗ chỉ sửa được nếu đổi nghĩa: số, điều kiện, phạm vi, thêm hoặc bớt ý | **Không sửa.** Ghi một dòng |
|
|
58
|
+
|
|
59
|
+
**Không làm:** rà nội dung nghiệp vụ (đó là việc của refine), đổi mã, đổi số, đổi dấu `🤖`/`✅`, đổi `(nguồn: …)`, sửa phần ngoài phạm vi. Viết lại câu thì giữ đúng mọi ý và mọi giá trị của câu cũ.
|
|
60
|
+
|
|
61
|
+
**Ghi file** `W/review-{version}.md` bằng `SE create --replace`, đúng khuôn sau:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
## Đã sửa (A)
|
|
65
|
+
- {mã mục}: "{trước}" → "{sau}"
|
|
66
|
+
|
|
67
|
+
## Đề xuất (B)
|
|
68
|
+
### R01 · {câu chữ | thuật ngữ | khuôn} · {mã mục}
|
|
69
|
+
- Trước: "{nguyên văn trong PRD, đủ dài để chỉ xuất hiện một lần}"
|
|
70
|
+
- Sau: "{…}"
|
|
71
|
+
- Lý do: {…}
|
|
72
|
+
|
|
73
|
+
## Ghi chú (C)
|
|
74
|
+
- {mã mục}: {vấn đề} → cần `/prd … change`
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Mục nào không có gì thì ghi `Không có`. Sau đó **chỉ trả về một dòng**: *"sửa {a} · đề xuất {b} · ghi chú {c} → {file}"*.
|
package/ref/product/epic.md
CHANGED
|
@@ -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
|
@@ -7,6 +7,7 @@ open_questions: 0
|
|
|
7
7
|
approved_by: — # người duyệt PRD; bắt buộc có khi status: approved
|
|
8
8
|
approved_at: — # YYYY-MM-DD
|
|
9
9
|
refined: — # version đã refine xong (/prd <EPIC-ID> refine); bắt buộc = version khi duyệt
|
|
10
|
+
reviewed: — # version đã rà hình thức xong (/prd <EPIC-ID> review, sau refine); bắt buộc = version khi duyệt
|
|
10
11
|
updated: {YYYY-MM-DD}
|
|
11
12
|
---
|
|
12
13
|
|
|
@@ -21,6 +22,7 @@ updated: {YYYY-MM-DD}
|
|
|
21
22
|
|
|
22
23
|
- **Mục tiêu:** {…}
|
|
23
24
|
- **Actor:** {ACT-xx (chính) · ACT-yy (phụ)}
|
|
25
|
+
- **Nền tảng:** {web · app · system — chỉ ghi mã: web, app (nơi người dùng dùng tính năng), system (luồng tự động, không có màn hình); giải thích sau dấu —. Là mặc định cho mọi UC}
|
|
24
26
|
- **Trong phạm vi:**
|
|
25
27
|
- {…}
|
|
26
28
|
- **Ngoài phạm vi:**
|
|
@@ -52,6 +54,7 @@ flowchart TD
|
|
|
52
54
|
|
|
53
55
|
- **Jira:** {key hoặc —}
|
|
54
56
|
- **Actor:** {ACT-xx}
|
|
57
|
+
- **Nền tảng:** {chỉ ghi khi UC này chạy khác Tổng quan, ví dụ `app` hoặc `system — luồng tự động nhận đơn`; giống thì bỏ dòng này}
|
|
55
58
|
- **Điều kiện trước:** {…}
|
|
56
59
|
- **Kết quả sau:** {…}
|
|
57
60
|
|