@educa-corp/fw 0.8.0 → 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.
- package/CHANGELOG.md +25 -0
- package/commands/bdd.md +68 -0
- package/commands/prd.md +10 -17
- package/commands/product.md +10 -26
- package/docs/guide/02-khai-niem.md +3 -0
- package/docs/guide/README.md +9 -6
- package/docs/guide/cach-lam/quyet-finding-refine.md +94 -0
- package/docs/guide/lenh/bdd.md +94 -0
- package/docs/guide/lenh/prd-refine.md +4 -15
- package/docs/guide/lenh/prd.md +3 -2
- package/docs/guide/vai-tro/po-ba.md +11 -4
- package/docs/guide/xu-ly-su-co.md +5 -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 +43 -0
- package/ref/common.md +47 -0
- package/ref/prd/change.md +2 -2
- package/ref/prd/new.md +6 -3
- package/ref/prd/refine.md +20 -8
- package/ref/product/epic.md +2 -0
- package/templates/bdd.feature +32 -0
- package/templates/prd.md +2 -0
- package/tools/spec_edit.py +598 -7
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,31 @@
|
|
|
3
3
|
> `fw install` in các mục của những version mới hơn bản đang cài trong dự án.
|
|
4
4
|
> Mỗi lần sửa lệnh, khuôn, bộ câu hỏi hay công cụ đều phải tăng version và thêm một mục ở đây. Test sẽ báo lỗi nếu version chưa có mục.
|
|
5
5
|
|
|
6
|
+
## 0.10.0 — 2026-10-02
|
|
7
|
+
|
|
8
|
+
- **Lệnh mới `/bdd <UC-ID>`**: viết kịch bản BDD cho một UC từ PRD đã duyệt, mỗi UC một file `{domain}/{slug}/bdd/UC-001.feature`. Có 2 lượt: lượt 1 trình dàn ý (kèm bảng nhánh của từng BR và các điểm giao nhận với UC khác), lượt 2 ghi file rồi kiểm độ phủ. Chỉ đọc đúng phần PRD của UC đó: với UC-001 của LMS là 15 KB thay vì 91 KB.
|
|
9
|
+
- **Mã kịch bản ổn định** `UC-001-SC01`: không đánh số lại, không dùng lại. Kịch bản bỏ đi còn lại dòng `# Đã bỏ (v…)`.
|
|
10
|
+
- **Tag Gherkin thật** cho từng kịch bản: mã, nền tảng (`@web @app`), loại (`@happy @alternative @edge @negative`), và mã đầy đủ của AC/BR được phủ.
|
|
11
|
+
- **Đã có file thì bù**: tìm AC/BR chưa có kịch bản, kịch bản trỏ tới mục đã bỏ, các mục PRD đổi sau version BDD viết theo. `/bdd <UC-ID> change <mô tả>` dùng khi kịch bản chưa đủ ý; nếu là yêu cầu mới thì chỉ sang `/prd change`.
|
|
12
|
+
- **Duyệt BDD** chỉ được khi độ phủ đủ, hết 🤖, PRD đang `approved`, và BDD viết theo đúng version PRD hiện tại.
|
|
13
|
+
- **PRD có dòng `Nền tảng`** ở Tổng quan (mặc định cho mọi UC), UC nào chạy khác thì ghi riêng. Thiếu dòng này thì PRD không duyệt được. PRD đã có: chạy `/prd <EPIC-ID> change khai nền tảng: web`.
|
|
14
|
+
- `spec_edit`: `where` · `context` (đọc phần PRD cần cho BDD) · `next-sc` · `scenario` (theo mã kịch bản hoặc mã AC/BR) · `sc` (thay, thêm, bỏ kịch bản theo mã) · `bddcheck` (kiểm khuôn, tag, độ phủ). `set`, `pending`, `confirm` dùng được với file `.feature`.
|
|
15
|
+
|
|
16
|
+
## 0.9.0 — 2026-10-02
|
|
17
|
+
|
|
18
|
+
- **Sửa theo mã**: `spec_edit item` sửa hoặc thêm dòng BR / AC theo mã (`UC-003-BR10`), chỉ cần viết dòng mới. Chặn đổi mã, dùng lại mã, nguồn bằng lời. Áp bản sửa tốn ít output hơn hẳn (lần đo trước: 81 KB nội dung sửa cho 39 finding).
|
|
19
|
+
- **Đọc đúng phần cần**: `spec_edit uc <file> UC-003` (một UC) · `spec_edit finding <file> F17` (một finding).
|
|
20
|
+
- **`/prd refine` ghi quyết định ngay sau mỗi đợt** (`spec_edit decide`), `bác` bắt buộc có lý do. Nghỉ quá 1 giờ thì `/clear` rồi gọi lại lệnh, không mất gì.
|
|
21
|
+
- **`/prd refine` áp bản sửa bằng một sub-agent Opus**, phiên chính chỉ hỏi và ghi quyết định (lần đo trước: phiên quyết + áp phình tới 268K ngữ cảnh, khoảng 2,4M token).
|
|
22
|
+
- **Cảnh báo PRD quá 60 KB** khi `coverage` / `flowcheck`. `/product` (epic) và `/prd` (chia UC) hỏi tách epic khi dự kiến hơn 8 UC.
|
|
23
|
+
- **Luật chung tách ra `ref/common.md`**: xưng hô, kiểm Python, config, cách hỏi (tối đa 4 câu, ngôn ngữ nghiệp vụ, 🤖/✅), cách sửa file bằng `spec_edit`. Mọi lệnh đọc file này trong lệnh Bash đầu tiên, nên không tốn thêm lượt gọi. File lệnh nhẹ đi: `/product` 8,2 → 6,0 KB, `/prd` 6,5 → 5,1 KB. Sửa một luật chung chỉ cần sửa một chỗ.
|
|
24
|
+
- **Xưng hô cố định**: AI gọi người dùng là "bạn" và tự xưng "tôi" ở mọi lệnh. Không dùng "mình", "em", "anh/chị". Trước bản này, AI tự chọn cách xưng hô và thường tự xưng "mình".
|
|
25
|
+
|
|
26
|
+
## 0.8.1 — 2026-10-01
|
|
27
|
+
|
|
28
|
+
- Hướng dẫn có thêm loại trang **Cách làm** (`.fw/guide/cach-lam/`), gồm các bước làm một việc cụ thể kèm câu gõ mẫu. Trang đầu tiên: **Cách quyết finding sau khi refine** (cho PO / BA).
|
|
29
|
+
- Sửa lỗi `/prd refine`: gọi lại lệnh khi lượt trước **đang chờ PO quyết** thì không rà lại từ đầu nữa, mà trình lại bảng tóm tắt để PO quyết tiếp. Trước bản này, lệnh sẽ chạy lại cả lượt 1, tốn thêm token và sinh ra finding trùng.
|
|
30
|
+
|
|
6
31
|
## 0.8.0 — 2026-10-01
|
|
7
32
|
|
|
8
33
|
- PRD có mục mới **User flow**: các hành trình xuyên suốt nhiều UC, mỗi hành trình gồm một dòng trong bảng và một sơ đồ mermaid, có nhánh lỗi. **Mỗi UC phải có mặt trong ít nhất một hành trình**, `spec_edit flowcheck` kiểm và PRD thiếu User flow thì không duyệt được. PRD đã có: chạy `/prd <EPIC-ID> change thêm User flow`.
|
package/commands/bdd.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Viết kịch bản BDD cho một UC từ PRD đã duyệt (UC-ID), bù khi PRD đổi, hoặc đổi theo mô tả (UC-ID change)
|
|
3
|
+
argument-hint: "<UC-ID> [change <mô tả>] [--force]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /bdd
|
|
7
|
+
|
|
8
|
+
Mục đích: biến một UC của PRD đã duyệt thành **kịch bản BDD** (file `.feature`, Gherkin). Mỗi kịch bản có **mã ổn định** `UC-001-SC01`. Kịch bản là spec để dev viết code và test, và là nguồn để QC thiết kế test case. Mã này cũng là khoá nối code (`@trace.implements`), test (`@trace.verifies`) và QC.
|
|
9
|
+
|
|
10
|
+
**Xưng hô: 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".
|
|
11
|
+
|
|
12
|
+
- `/bdd <UC-ID>`: chưa có file thì **tạo**. Đã có file thì **bù** những gì PRD mới đổi hoặc còn thiếu.
|
|
13
|
+
- `/bdd <UC-ID> change <mô tả>`: thêm, sửa hoặc bỏ kịch bản theo mô tả. Ví dụ QC thấy một nhánh của BR chưa có kịch bản.
|
|
14
|
+
|
|
15
|
+
Tham số: `$ARGUMENTS`
|
|
16
|
+
|
|
17
|
+
## Bước 1 — Nạp context
|
|
18
|
+
|
|
19
|
+
1. Chạy **một** lệnh Bash: `cat .fw/core/ref/common.md .fw/config.yaml; python .fw/core/tools/spec_edit.py --check`. Làm đúng theo `common.md` (luật chung: xưng hô, Python, config, cách hỏi, cách sửa file bằng `SE`). Không có `common.md` thì 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."*
|
|
20
|
+
2. Tìm PRD: `SE where {specs} <UC-ID>`. Kết quả là `D`. File BDD: `F = {thư mục của D}/bdd/<UC-ID>.feature`.
|
|
21
|
+
3. Đọc đầu vào **duy nhất** từ PRD: `SE context D <UC-ID>`. Lệnh này in Tổng quan, các hành trình có UC này, các dòng Màn hình, khối UC, và đúng các mục của UC khác mà UC này trỏ tới. **Không đọc cả PRD.** Cần thêm một UC khác thì chỉ đọc `SE uc D UC-xxx`.
|
|
22
|
+
4. Đọc `{specs}/product/glossary.md` nếu có. Viết đúng thuật ngữ.
|
|
23
|
+
|
|
24
|
+
## Bước 2 — Chọn chế độ
|
|
25
|
+
|
|
26
|
+
Xét **từ trên xuống**, gặp dòng nào khớp trước thì theo dòng đó.
|
|
27
|
+
|
|
28
|
+
| Tình huống | Làm gì |
|
|
29
|
+
|---|---|
|
|
30
|
+
| UC đã bỏ trong PRD (tiêu đề gạch ngang) | Dừng: *"UC-xxx đã bỏ trong PRD (v…). Không viết BDD cho UC đã bỏ."* |
|
|
31
|
+
| PRD chưa khai **Nền tảng**: không có dòng `Nền tảng` ở Tổng quan, cũng không có trong UC | Dừng: *"PRD chưa khai nền tảng. Chạy `/prd EP-xx change khai nền tảng: web …` trước. UC nào chạy khác mặc định thì nêu riêng."* |
|
|
32
|
+
| PRD chưa `approved`, **không** có `--force` | Dừng: *"PRD chưa duyệt. Duyệt PRD trước, hoặc chạy `/bdd UC-xxx --force` để viết sớm (BDD sẽ không duyệt được cho tới khi PRD được duyệt)."* |
|
|
33
|
+
| Không có `change`, chưa có `F` | Chế độ **tạo**: đọc `.fw/core/ref/bdd/writing.md` và `.fw/core/ref/bdd/new.md` |
|
|
34
|
+
| Không có `change`, **đã có** `F` | Chế độ **bù**: đọc `.fw/core/ref/bdd/writing.md` và `.fw/core/ref/bdd/change.md` |
|
|
35
|
+
| Có `change`, đã có `F` | Chế độ **đổi**: đọc `.fw/core/ref/bdd/writing.md` và `.fw/core/ref/bdd/change.md` |
|
|
36
|
+
| Có `change`, chưa có `F` | Dừng: *"Chưa có BDD cho UC-xxx. Chạy `/bdd UC-xxx` trước."* |
|
|
37
|
+
|
|
38
|
+
Có `--force` khi PRD chưa duyệt: in cảnh báo, và thêm dòng `# Viết khi PRD còn draft (--force)` ngay dưới header của `F`.
|
|
39
|
+
|
|
40
|
+
## Bước 3 — Luật riêng của BDD
|
|
41
|
+
|
|
42
|
+
Ngoài luật chung (`common.md`) và luật viết (`writing.md`):
|
|
43
|
+
1. **Mã ổn định.** `UC-NNN-SCnn` đánh số trong từng UC. Mã đã cấp thì **không bao giờ đổi, không dùng lại**. Mã mới lấy bằng `SE next-sc F`. Kịch bản bỏ đi còn lại dòng `# Đã bỏ (v…) @mã — tên`, do `SE sc` tự ghi.
|
|
44
|
+
2. **Tag của mỗi kịch bản:**
|
|
45
|
+
- đúng **1** mã `@UC-NNN-SCnn`;
|
|
46
|
+
- ít nhất 1 nền tảng, chỉ dùng những nền tảng UC khai;
|
|
47
|
+
- đúng **1** loại: `@happy` · `@alternative` · `@edge` · `@negative`;
|
|
48
|
+
- **mã đầy đủ** của mọi AC/BR mà kịch bản phủ, ví dụ `@UC-001-AC01 @UC-003-BR14`.
|
|
49
|
+
3. **Phủ.** Mọi AC và BR còn dùng của UC đều phải có mặt trong ít nhất một kịch bản, trực tiếp hoặc qua kịch bản của BR dùng nó. Không viết kịch bản cho điều PRD không có.
|
|
50
|
+
4. **Lệnh `SE` riêng của BDD:**
|
|
51
|
+
- `SE next-sc F`: mã kế tiếp.
|
|
52
|
+
- `SE scenario F <mã SC | mã AC/BR>`: đọc kịch bản theo mã.
|
|
53
|
+
- `SE sc F`: thay, thêm, bỏ kịch bản theo mã. Chỉ viết khối mới, không chép khối cũ.
|
|
54
|
+
- `SE bddcheck F`: kiểm khuôn, tag và độ phủ.
|
|
55
|
+
5. **Duyệt.** `status=approved` chỉ đặt được khi `bddcheck` sạch, không còn `🤖`, PRD đang `approved`, `prd_version` của `F` bằng version của PRD, và có người duyệt. Hỏi *"Ai duyệt BDD này?"* (mặc định là người đã duyệt PRD), rồi đặt trong **một** lệnh: `SE set F status=approved approved_by=<tên> approved_at=YYYY-MM-DD`. `SE` tự chặn nếu chưa đủ.
|
|
56
|
+
|
|
57
|
+
## Bước 4 — Kết thúc
|
|
58
|
+
|
|
59
|
+
In ra đúng khối sau:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
---
|
|
63
|
+
Trạng thái : {✅ Đã duyệt v{version} | 🟡 Nháp v{version} — còn {n} mục 🤖}
|
|
64
|
+
Đã ghi : {F}
|
|
65
|
+
Kiểm : {dòng số liệu đầu tiên của `SE bddcheck F`}
|
|
66
|
+
Luồng : Product → PRD → [BDD ◀ bạn ở đây] → TDD · Design-spec → Code → Test → QC
|
|
67
|
+
Bước tiếp : {trả lời / xác nhận các mục trên | `/clear` rồi `/bdd UC-xxx` (UC đầu tiên trong dòng "UC chưa có BDD" của bddcheck) | mọi UC đã có BDD: TDD (sắp có)}
|
|
68
|
+
```
|
package/commands/prd.md
CHANGED
|
@@ -7,18 +7,17 @@ argument-hint: "<EPIC-ID> [refine | change <mô tả thay đổi>] [--force]"
|
|
|
7
7
|
|
|
8
8
|
Mục đích: biến epic đã làm rõ (`/product`) thành **PRD chính thức**, gồm các use case, Business Rule (BR) và **Acceptance Criteria (điều kiện nghiệm thu)**, viết tắt **AC**, có **mã ổn định**. Sau đó PRD là nguồn cho BDD, TDD và code.
|
|
9
9
|
|
|
10
|
+
**Xưng hô: 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".
|
|
11
|
+
|
|
10
12
|
- `/prd <EPIC-ID>`: tạo PRD từ epic `ready`.
|
|
13
|
+
- `/prd <EPIC-ID> refine`: rà nội dung PRD qua 4 lăng kính. **Bắt buộc** trước khi duyệt.
|
|
11
14
|
- `/prd <EPIC-ID> change <mô tả>`: thêm, sửa hoặc bỏ nội dung trong PRD đã có.
|
|
12
15
|
|
|
13
16
|
Tham số: `$ARGUMENTS`
|
|
14
17
|
|
|
15
18
|
## Bước 1 — Nạp context
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
1. Chạy **một** lệnh Bash: `python .fw/core/tools/spec_edit.py --check && cat .fw/config.yaml`
|
|
20
|
-
- Lỗi không tìm thấy python: thử `python3`, rồi `py -3`, và dùng lệnh chạy được cho cả phiên. Cả ba đều lỗi thì **DỪNG NGAY** và 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."*
|
|
21
|
-
- Không có `.fw/config.yaml`: dừng và báo *"Chưa cài framework. Chạy `npx @educa-corp/fw install` ở thư mục gốc dự án."*
|
|
20
|
+
1. Chạy **một** lệnh Bash: `cat .fw/core/ref/common.md .fw/config.yaml; python .fw/core/tools/spec_edit.py --check`. Làm đúng theo `common.md` (luật chung: xưng hô, Python, config, cách hỏi, cách sửa file bằng `SE`). Không có `common.md` thì 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."*
|
|
22
21
|
2. Tìm file epic: `{specs}/product/epics/{EPIC-ID}-*.md`. Đọc frontmatter để lấy `slug`, `domain`, `status`.
|
|
23
22
|
3. File PRD: `D = {specs}/{domain}/{slug}/prd.md`.
|
|
24
23
|
4. Đọc `{specs}/product/glossary.md` nếu có, và `SE section {specs}/product/product.md constraints`. Viết đúng thuật ngữ. PRD không được đi ngược ràng buộc nào. BR bắt nguồn từ ràng buộc thì ghi `(nguồn: CON-01)`. `SE` báo không có mục đó (khuôn cũ): coi như chưa có ràng buộc, và nhắc một dòng *"Chạy `/product` để bổ sung Ràng buộc và Giai đoạn cho tầng sản phẩm."*
|
|
@@ -28,26 +27,20 @@ Nếu **trước lệnh này** phiên đã có hội thoại khác, dòng đầu
|
|
|
28
27
|
| Tình huống | Làm gì |
|
|
29
28
|
|---|---|
|
|
30
29
|
| Không có `change`, chưa có `D`, epic `ready` | Chế độ **tạo**: đọc `.fw/core/ref/prd/new.md` |
|
|
31
|
-
| Không có `change`, chưa có `D`, epic **chưa** `ready` | Dừng: *"EP-xx chưa làm rõ xong. Chạy `/product EP-xx` trước."* Có `--force` thì làm tiếp, nhưng in cảnh báo, ghi vào mục
|
|
30
|
+
| Không có `change`, chưa có `D`, epic **chưa** `ready` | Dừng: *"EP-xx chưa làm rõ xong. Chạy `/product EP-xx` trước."* Có `--force` thì làm tiếp, nhưng in cảnh báo, ghi vào mục Câu hỏi còn mở của PRD dòng *"Tạo khi epic chưa ready (--force)"*, và không cho `approved` khi epic còn câu hỏi mở |
|
|
32
31
|
| Không có `change` / `refine`, **đã có** `D` | Dừng: *"PRD đã có. Rà nội dung: `/prd EP-xx refine` · Đổi: `/prd EP-xx change <mô tả>`."* Không ghi đè |
|
|
33
32
|
| Có `refine`, đã có `D` | Chế độ **rà nội dung**: đọc `.fw/core/ref/prd/refine.md` |
|
|
34
33
|
| Có `change`, đã có `D` | Chế độ **đổi**: đọc `.fw/core/ref/prd/change.md` |
|
|
35
34
|
| Có `change` hoặc `refine`, chưa có `D` | Dừng: *"Chưa có PRD. Chạy `/prd EP-xx` trước."* |
|
|
36
35
|
|
|
37
|
-
## Bước 3 — Luật
|
|
36
|
+
## Bước 3 — Luật riêng của PRD
|
|
38
37
|
|
|
38
|
+
Ngoài luật chung (`common.md`):
|
|
39
39
|
1. **Mã ổn định.** `UC-NNN` đánh số trên toàn sản phẩm. `UC-NNN-BRnn`, `UC-NNN-ACnn` đánh số trong từng UC. Mã đã cấp thì **không bao giờ đổi, không dùng lại**. Thêm mới thì lấy số kế tiếp trong UC đó. Mục bỏ đi thì giữ dòng, gạch ngang nội dung, và ghi *"Đã bỏ (v…)"*.
|
|
40
40
|
2. **Nguồn.** Mọi BR và AC phải ghi `(nguồn: …)`, và **chỉ ghi mã**: mã epic (`BR3`, `AC1`), ràng buộc (`CON-02`), hoặc `PRD` (thêm khi viết PRD, PO đã duyệt). Không ghi lời giải thích. `SE` chặn nếu sai.
|
|
41
|
-
3. **Dấu.** Nội dung chuyển nguyên ý từ mục `✅` của epic thì giữ `✅`. Chỗ nào AI **tự thêm, tách hoặc suy ra** thì gắn `🤖`.
|
|
42
|
-
4. **
|
|
43
|
-
5. **
|
|
44
|
-
6. **Sửa file: CHỈ dùng `spec_edit.py`** (gọi là `SE`). Không dùng Edit/Write, không tự viết script:
|
|
45
|
-
- Tạo: `SE create <file> <<'EOF'` … `EOF` · Sửa: `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)
|
|
46
|
-
- Frontmatter: `SE set <file> version=1.1 status=draft updated=YYYY-MM-DD`
|
|
47
|
-
- `SE pending <file>` · `SE confirm <file> UC-003-BR02 UC-003-AC01` · `SE next-uc {specs}` · `SE coverage <epic> <prd>` · `SE flowcheck <prd>`
|
|
48
|
-
- Đọc **một mục**: `SE section <file> <mã>`. Mã mục là `<!-- sec:… -->` ở tiêu đề (vd `constraints`, `usecases`, `open`). **Luôn tìm mục theo mã**, 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:… -->`.
|
|
49
|
-
- `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. 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.
|
|
50
|
-
7. **Duyệt.** `status=approved` chỉ đặt được khi không còn `🤖`, `open_questions=0`, **đã refine đúng version này** (`refined` = `version`, không còn critical/major chưa quyết), và có người duyệt. Chưa refine thì báo *"Chạy `/prd EP-xx refine` trước khi duyệt."* Hỏi PO *"Ai duyệt PRD này?"* (mặc định là PO của epic), rồi đặt trong **một** lệnh: `SE set D status=approved approved_by=<tên> approved_at=YYYY-MM-DD`. `SE` tự chặn nếu chưa đủ. Không tìm cách lách.
|
|
41
|
+
3. **Dấu.** Nội dung chuyển nguyên ý từ mục `✅` của epic thì giữ `✅`. Chỗ nào AI **tự thêm, tách hoặc suy ra** thì gắn `🤖`.
|
|
42
|
+
4. **Lệnh `SE` riêng của PRD:** `SE next-uc {specs}` (mã UC kế tiếp) · `SE coverage <epic> <prd>` (không rơi BR/AC nào của epic) · `SE flowcheck <prd>` (mọi UC có mặt trong User flow).
|
|
43
|
+
5. **Duyệt.** `status=approved` chỉ đặt được khi không còn `🤖`, `open_questions=0`, User flow đủ, **đã refine đúng version này** (`refined` = `version`, không còn critical/major chưa quyết), và có người duyệt. Chưa refine thì báo *"Chạy `/prd EP-xx refine` trước khi duyệt."* Hỏi PO *"Ai duyệt PRD này?"* (mặc định là PO của epic), rồi đặt trong **một** lệnh: `SE set D status=approved approved_by=<tên> approved_at=YYYY-MM-DD`. `SE` tự chặn nếu chưa đủ.
|
|
51
44
|
|
|
52
45
|
## Bước 4 — Kết thúc
|
|
53
46
|
|
package/commands/product.md
CHANGED
|
@@ -5,7 +5,9 @@ argument-hint: "[EPIC-ID | tên tính năng]"
|
|
|
5
5
|
|
|
6
6
|
# /product
|
|
7
7
|
|
|
8
|
-
Mục đích: **hỏi ngược lại PO** để làm rõ những gì PO biết mà chưa viết ra, **trước** khi viết PRD. Giá trị
|
|
8
|
+
Mục đích: **hỏi ngược lại PO** để làm rõ những gì PO biết mà chưa viết ra, **trước** khi viết PRD. Giá trị nằm ở **câu hỏi**, không ở việc chép lại tài liệu.
|
|
9
|
+
|
|
10
|
+
**Xưng hô: 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".
|
|
9
11
|
|
|
10
12
|
- `/product`: tầng **sản phẩm**, gồm tầm nhìn, nhóm người dùng, danh sách epic.
|
|
11
13
|
- `/product <EPIC-ID | tên>`: làm rõ yêu cầu cho **một epic**.
|
|
@@ -14,15 +16,9 @@ Tham số: `$ARGUMENTS`
|
|
|
14
16
|
|
|
15
17
|
## Bước 1 — Nạp context (chỉ những gì cần)
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
1. Chạy **một** lệnh Bash: `python .fw/core/tools/spec_edit.py --check && cat .fw/config.yaml`
|
|
20
|
-
- Lỗi "không tìm thấy python": thử lại lần lượt với `python3`, rồi `py -3`, và dùng lệnh chạy được cho cả phiên. Cả ba đều lỗi thì **DỪNG NGAY**, không hỏi gì thêm, và 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."*
|
|
21
|
-
- Không có `.fw/config.yaml`: dừng và 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."*
|
|
22
|
-
- Lấy `specs` (thư mục spec) và `tracker` từ config.
|
|
19
|
+
1. Chạy **một** lệnh Bash: `cat .fw/core/ref/common.md .fw/config.yaml; python .fw/core/tools/spec_edit.py --check`. Làm đúng theo `common.md` (luật chung: xưng hô, Python, config, cách hỏi, cách sửa file bằng `SE`). Không có `common.md` thì 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."*
|
|
23
20
|
2. Đặt `P = {specs}/product`.
|
|
24
|
-
3. Chế độ epic: đọc thêm `SE section P/product.md actors`, `… epics`, `… constraints` (gộp trong một lệnh Bash) và `P/glossary.md` nếu có. Epic không được đi ngược một ràng buộc `CON-xx`. PO muốn làm vậy thì hỏi PO có sửa ràng buộc ở tầng sản phẩm không.
|
|
25
|
-
**Không** đọc PRD khác, trừ khi PO nhắc tới một tính năng liên quan.
|
|
21
|
+
3. Chế độ epic: đọc thêm `SE section P/product.md actors`, `… epics`, `… constraints` (gộp trong một lệnh Bash) và `P/glossary.md` nếu có. Epic không được đi ngược một ràng buộc `CON-xx`. PO muốn làm vậy thì hỏi PO có sửa ràng buộc ở tầng sản phẩm không. Không đọc PRD khác, trừ khi PO nhắc tới.
|
|
26
22
|
4. **Bảng thuật ngữ cũ.** Nếu `{specs}/domain-knowledge/business-dictionary.md` (của framework cũ) có **dòng thuật ngữ thật** (không chỉ là khuôn trống), thì ở lượt hỏi đầu, đề xuất gộp các thuật ngữ đó vào `P/glossary.md`. PO đồng ý thì gộp, sau đó hỏi PO xoá file cũ hay giữ. Mục tiêu là dự án chỉ còn **một** bảng thuật ngữ.
|
|
27
23
|
|
|
28
24
|
## Bước 2 — Xác định file đích
|
|
@@ -40,16 +36,12 @@ Xác định `id` và `slug` của epic:
|
|
|
40
36
|
|
|
41
37
|
**File đích đã tồn tại** thì đọc `.fw/core/ref/product/resume.md` và làm theo đó. Không ghi đè.
|
|
42
38
|
|
|
43
|
-
## Bước 3 — Luật khi
|
|
39
|
+
## Bước 3 — Luật riêng khi làm rõ yêu cầu
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- Mục mà tài liệu chưa có: hỏi mới.
|
|
48
|
-
- Chỉ khi PO xác nhận thì mới đổi `🤖` thành `✅`. **Không bao giờ tự đổi thay PO.**
|
|
41
|
+
Ngoài luật chung (`common.md` mục 3):
|
|
42
|
+
1. **Tài liệu PO dán vào là nguyên liệu**, không phải câu trả lời thay cho các bước. Mục mà tài liệu đã có thì trình bản trích với dấu `🤖`, rồi hỏi *"Đúng chưa, cần sửa gì?"*. Mục mà tài liệu chưa có thì hỏi mới.
|
|
49
43
|
2. **Không bỏ checkpoint**, kể cả khi tài liệu rất dày.
|
|
50
|
-
3. **
|
|
51
|
-
4. **Chỉ nói ngôn ngữ nghiệp vụ.** Không hỏi và không đề xuất API, bảng dữ liệu hay framework.
|
|
52
|
-
5. Gặp **thuật ngữ mới** (lặp từ 2 lần trở lên, chưa có trong `glossary.md`) thì đưa vào lượt hỏi kế tiếp: nghĩa là gì, có thêm vào `glossary.md` không.
|
|
44
|
+
3. Gặp **thuật ngữ mới** (lặp từ 2 lần trở lên, chưa có trong `glossary.md`) thì đưa vào lượt hỏi kế tiếp: nghĩa là gì, có thêm vào `glossary.md` không.
|
|
53
45
|
|
|
54
46
|
## Bước 4 — Đi qua các checkpoint
|
|
55
47
|
|
|
@@ -59,16 +51,8 @@ Xác định `id` và `slug` của epic:
|
|
|
59
51
|
|
|
60
52
|
Trước checkpoint 1 của epic, AI tự điền mục **Bối cảnh hệ thống** (nhóm người dùng liên quan, tính năng đã có liên quan, thuật ngữ mới). Mục này không cần PO.
|
|
61
53
|
|
|
62
|
-
**Sửa file: CHỈ dùng `spec_edit.py`** (gọi là `SE` bên dưới). Không dùng Edit/Write, không tự viết script:
|
|
63
|
-
- Tạo file mới: `SE create <file> <<'EOF'` … nội dung … `EOF`
|
|
64
|
-
- 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`.
|
|
65
|
-
- Frontmatter: `SE set <file> checkpoint=1 open_questions=3 updated=YYYY-MM-DD`
|
|
66
|
-
- Xem các mục còn chờ PO: `SE pending <file>`. PO xác nhận các mục có mã: `SE confirm <file> AC2 AC3 BR8b`
|
|
67
|
-
- Đọc một mục: `SE section <file> <mã>` (mã là `<!-- sec:… -->` ở tiêu đề). **Luôn tìm mục theo mã**, không theo số hay tên. Khi sửa, giữ nguyên `<!-- sec:… -->`.
|
|
68
|
-
- `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. 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.
|
|
69
|
-
|
|
70
54
|
**Sau mỗi checkpoint** mà PO đã chốt:
|
|
71
|
-
1. **Ghi file ngay
|
|
55
|
+
1. **Ghi file ngay** (bằng `SE`, xem `common.md` mục 4). Không đợi tới cuối, để lần sau chạy tiếp được.
|
|
72
56
|
2. `SE set` các trường `checkpoint`, `open_questions` (đếm số dòng trong mục `sec:open` của file, **không** đếm câu vừa hỏi trong lượt), `updated`.
|
|
73
57
|
3. Checkpoint chỉ được tính là chốt khi **mọi mục của nó mang `✅`**. Còn mục `🤖` thì không tăng `checkpoint`.
|
|
74
58
|
|
|
@@ -26,6 +26,8 @@ Chỉ những khái niệm bạn **gặp khi dùng** các lệnh hiện có.
|
|
|
26
26
|
| **AC** (Acceptance Criteria, điều kiện nghiệm thu) | Điều kiện kiểm được là đạt hay không đạt, dạng *"Khi … thì …"* | UC-002-AC01: Khi tài khoản mới quá 7 ngày chưa đăng nhập thì bị chuyển inactive, đăng nhập bị từ chối |
|
|
27
27
|
| **Ràng buộc** | Điều kiện áp cho **mọi epic**, mã `CON-01`… | CON-01: Audit log không được xoá hay sửa |
|
|
28
28
|
| **User flow** (hành trình) | Đường đi của một actor qua nhiều UC, có rẽ nhánh và nhánh lỗi, vẽ bằng sơ đồ trong PRD. Mã `J1`, `J2`… | J1 Nhân sự mới vào hệ thống: UC-001 → UC-003 → UC-005 |
|
|
29
|
+
| **Kịch bản BDD** (scenario) | Một hành vi cụ thể của hệ thống, viết dạng *Given / When / Then*, dev viết code và test theo đó. Mỗi UC có một file `.feature` | UC-001-SC01: Import có dòng trùng email với tài khoản đã có |
|
|
30
|
+
| **Nền tảng** | Nơi người dùng dùng tính năng: `web`, `app`… Khai ở Tổng quan của PRD, UC nào khác thì ghi riêng | Nền tảng: web · app |
|
|
29
31
|
| **Checkpoint** | Một điểm dừng để bạn chốt. `/product` có 2 (sản phẩm) hoặc 3 (epic) checkpoint | — |
|
|
30
32
|
|
|
31
33
|
## Mã ổn định
|
|
@@ -35,6 +37,7 @@ Chỉ những khái niệm bạn **gặp khi dùng** các lệnh hiện có.
|
|
|
35
37
|
| UC | `UC-001` | Toàn sản phẩm, mọi epic dùng chung một dãy |
|
|
36
38
|
| Business Rule trong PRD | `UC-003-BR02` | Trong từng UC |
|
|
37
39
|
| AC trong PRD | `UC-003-AC04` | Trong từng UC |
|
|
40
|
+
| Kịch bản BDD | `UC-003-SC01` | Trong từng UC |
|
|
38
41
|
| Business Rule / AC trong epic | `BR1.`, `AC1.` | Trong epic. Chèn giữa thì dùng `BR8a.` |
|
|
39
42
|
|
|
40
43
|
**Mã đã cấp không bao giờ đổi và không dùng lại.** Mục bỏ đi được giữ lại, gạch ngang và ghi *"Đã bỏ (v1.1)"*. Nhờ vậy BDD, code và test sau này luôn trỏ đúng mục.
|
package/docs/guide/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Hướng dẫn sử dụng `@educa-corp/fw`
|
|
2
2
|
|
|
3
3
|
> Framework làm việc với Claude Code: đưa một tính năng đi từ **ý tưởng → làm rõ yêu cầu → PRD → …**, AI hỏi và viết, con người xác nhận ở mỗi bước.
|
|
4
|
-
> Hướng dẫn này viết cho **bản 0.
|
|
4
|
+
> Hướng dẫn này viết cho **bản 0.10.0**. Chỉ mô tả những lệnh **đã có**. Lệnh mới có thì hướng dẫn mới được bổ sung.
|
|
5
5
|
> Trong dự án đã cài framework, bản hướng dẫn đúng với version đang dùng nằm ở **`.fw/guide/`**. Có thể hỏi Claude: *"Đọc .fw/guide và cho biết cách đổi PRD"*.
|
|
6
6
|
|
|
7
7
|
---
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
|---|---|
|
|
13
13
|
| Cài vào dự án và chạy lần đầu | [Bắt đầu](01-bat-dau.md) |
|
|
14
14
|
| Hiểu vài khái niệm trước khi dùng (UC, BR, AC, 🤖/✅…) | [Khái niệm](02-khai-niem.md) |
|
|
15
|
-
| Biết **vai trò của
|
|
15
|
+
| Biết **vai trò của bạn** dùng lệnh nào | [PO / BA](vai-tro/po-ba.md) · *Dev, QC: sắp có* |
|
|
16
|
+
| Làm một việc cụ thể, từng bước, có câu gõ mẫu | **Cách làm:** [Quyết finding sau khi refine](cach-lam/quyet-finding-refine.md) |
|
|
16
17
|
| Tra cứu một lệnh cụ thể | Bảng lệnh ngay bên dưới |
|
|
17
18
|
| Gặp lỗi | [Xử lý sự cố](xu-ly-su-co.md) |
|
|
18
19
|
|
|
@@ -21,10 +22,10 @@
|
|
|
21
22
|
## Pipeline hiện có
|
|
22
23
|
|
|
23
24
|
```
|
|
24
|
-
cài framework ──► /product ──► /product EP-xx ──► /prd EP-xx ──► /prd EP-xx refine ──► duyệt
|
|
25
|
-
tầng làm rõ một viết PRD rà nội dung
|
|
26
|
-
sản phẩm tính năng ▲ │ (bắt buộc)
|
|
27
|
-
└── /prd EP-xx change ◄──┘ đổi PRD thì refine lại
|
|
25
|
+
cài framework ──► /product ──► /product EP-xx ──► /prd EP-xx ──► /prd EP-xx refine ──► duyệt ──► /bdd UC-xxx ──► duyệt
|
|
26
|
+
tầng làm rõ một viết PRD rà nội dung mỗi UC một
|
|
27
|
+
sản phẩm tính năng ▲ │ (bắt buộc) file kịch bản
|
|
28
|
+
└── /prd EP-xx change ◄──┘ đổi PRD thì refine lại, rồi /bdd UC-xxx để bù
|
|
28
29
|
```
|
|
29
30
|
|
|
30
31
|
Mỗi lệnh kết thúc bằng một khối giống nhau. Bạn chỉ cần đọc dòng **Bước tiếp**:
|
|
@@ -50,6 +51,8 @@ Bước tiếp : `/clear` rồi `/product EP-01`
|
|
|
50
51
|
| `/prd <EPIC-ID>` | PO / BA | Viết **PRD chính thức** từ epic đã làm rõ | [/prd](lenh/prd.md) |
|
|
51
52
|
| `/prd <EPIC-ID> refine` | PO / BA | **Rà nội dung** PRD qua 4 lăng kính. **Bắt buộc** trước khi duyệt | [/prd refine](lenh/prd-refine.md) |
|
|
52
53
|
| `/prd <EPIC-ID> change <mô tả>` | PO / BA | Thêm, sửa hoặc bỏ nội dung PRD | [/prd](lenh/prd.md) |
|
|
54
|
+
| `/bdd <UC-ID>` | PO / BA | Viết **kịch bản BDD** cho một UC. Đã có thì **bù** phần PRD mới đổi | [/bdd](lenh/bdd.md) |
|
|
55
|
+
| `/bdd <UC-ID> change <mô tả>` | PO / BA · QC · Dev | Thêm, sửa, bỏ kịch bản khi chưa đủ ý | [/bdd](lenh/bdd.md#đổi-bdd-uc-001-change-mô-tả) |
|
|
53
56
|
|
|
54
57
|
---
|
|
55
58
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
[← Hướng dẫn](../README.md) · [PO / BA](../vai-tro/po-ba.md) · [/prd refine](../lenh/prd-refine.md)
|
|
2
|
+
|
|
3
|
+
# Cách quyết finding sau khi refine PRD
|
|
4
|
+
|
|
5
|
+
> **Dành cho:** PO / BA · **Khi nào:** sau khi `/prd EP-xx refine` trình bảng finding · **Mất khoảng:** 30–60 phút với vài chục finding
|
|
6
|
+
> Muốn tra cứu các luật (lượt, mức độ, điều kiện duyệt) thì xem [/prd refine](../lenh/prd-refine.md).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Mở đúng chỗ
|
|
11
|
+
|
|
12
|
+
Không cần quyết ngay trong phiên vừa rà. Khi đã sẵn sàng:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
/clear
|
|
16
|
+
/prd EP-01 refine
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Lệnh thấy lượt trước đang chờ bạn quyết. Nó **không rà lại**, chỉ trình lại bảng tóm tắt theo thứ tự F01 → F… (nặng nhất trước).
|
|
20
|
+
|
|
21
|
+
Mở thêm file chi tiết bên cạnh, ví dụ trong VS Code:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
specs/{domain}/{slug}/review/prd-refine.md
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Mỗi finding gồm: **Trích** (đoạn PRD liên quan) · **Vấn đề** · **Đề xuất** · **Nếu chốt đề xuất này** (hệ quả có thể phát sinh, chỉ có ở critical và major).
|
|
28
|
+
|
|
29
|
+
## 2. Quyết theo từng đợt nhỏ, nặng trước
|
|
30
|
+
|
|
31
|
+
Nên chia thành 4–5 tin nhắn, đừng dồn tất cả vào một lần:
|
|
32
|
+
|
|
33
|
+
| Đợt | Gõ ví dụ *(minh hoạ)* |
|
|
34
|
+
|---|---|
|
|
35
|
+
| **Critical**: bắt buộc quyết **từng mã** | `nhận F01` |
|
|
36
|
+
| Major nhóm QA | `nhận F02, F04, F05 · F03 sửa thành "hiển thị thông báo 'Email đã tồn tại'" · bác F06 vì AC đã đủ rõ` |
|
|
37
|
+
| Major nhóm DEV | `nhận F07–F15 trừ F11 · hoãn F11` |
|
|
38
|
+
| Major nhóm SA, Phạm vi | Như trên, quyết từng phần |
|
|
39
|
+
| **Minor** | `nhận tất cả minor` |
|
|
40
|
+
|
|
41
|
+
Quyết theo nhóm thì Claude **liệt kê lại đúng các mã** sẽ bị áp và hỏi *"Đúng chưa?"*. Kiểm danh sách đó trước khi trả lời "đúng".
|
|
42
|
+
|
|
43
|
+
**Mỗi đợt quyết được lưu vào file ngay.** Bạn dừng giữa chừng được. **Nghỉ quá 1 giờ thì `/clear` rồi gọi lại `/prd EP-01 refine`**, đừng để phiên mở qua đêm: phiên cũ phải nạp lại toàn bộ khi bạn quay lại, đo thực tế tốn khoảng 470K token cho một lần nghỉ qua đêm.
|
|
44
|
+
|
|
45
|
+
## 3. Chọn quyết định nào
|
|
46
|
+
|
|
47
|
+
| Quyết định | Dùng khi | Lưu ý |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `nhận` | Đồng ý cả vấn đề lẫn đề xuất | AI sửa PRD đúng theo đề xuất |
|
|
50
|
+
| `sửa: …` | Đồng ý là có vấn đề, nhưng muốn sửa **theo cách khác** | Ghi rõ cách của bạn, càng cụ thể càng tốt |
|
|
51
|
+
| `bác vì …` | Finding **sai**, **thừa**, hoặc PRD đã trả lời ở chỗ khác | **Luôn ghi lý do.** Lý do được lưu vào sổ quyết định, lần rà sau sẽ không nêu lại |
|
|
52
|
+
| `hoãn` | Đúng là có vấn đề, nhưng **để bước sau** xử lý (giao diện, kỹ thuật, chưa đủ thông tin) | Được ghi vào "Câu hỏi còn mở" của PRD, kèm chú thích "để bước QC" |
|
|
53
|
+
|
|
54
|
+
**Phân biệt bác và hoãn:** finding **không đúng** thì `bác`. Finding **đúng nhưng chưa phải lúc** thì `hoãn`.
|
|
55
|
+
|
|
56
|
+
## 4. Chưa hiểu thì hỏi trước
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
F18 nghĩa là gì? Cho ví dụ tình huống cụ thể.
|
|
60
|
+
F07 và F12 có trùng nhau không?
|
|
61
|
+
Nếu nhận F21 thì UC nào bị sửa?
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Claude giải thích **mà không sửa gì**. Chỉ khi bạn gõ quyết định thì mới có thay đổi.
|
|
65
|
+
|
|
66
|
+
## 5. Cách khác: ghi thẳng vào file
|
|
67
|
+
|
|
68
|
+
Sửa các dòng `- Quyết định: chờ` trong `prd-refine.md`, ví dụ:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
- Quyết định: nhận
|
|
72
|
+
- Quyết định: sửa: khoá 30 phút thay vì 15 phút
|
|
73
|
+
- Quyết định: bác: đã có ở UC-002-BR03
|
|
74
|
+
- Quyết định: hoãn
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Xong thì gõ: `Tôi đã ghi quyết định vào file, đọc và áp giúp.`
|
|
78
|
+
|
|
79
|
+
Cách này hợp khi bạn muốn đọc kỹ từng finding, hoặc cần hỏi ý người khác trước khi quyết.
|
|
80
|
+
|
|
81
|
+
## 6. Sau khi quyết xong
|
|
82
|
+
|
|
83
|
+
Khi mọi critical và major đã có quyết định:
|
|
84
|
+
1. Claude giao việc áp cho **một agent riêng**: agent đọc từng finding, sửa PRD theo mã, tăng version (ví dụ 1.2 → 1.3), ghi Lịch sử thay đổi, rồi báo lại một dòng.
|
|
85
|
+
2. Bảng **Tóm tắt** trong `prd-refine.md` có thêm số **nhận · sửa · bác · hoãn**.
|
|
86
|
+
3. Claude nhắc `/clear` rồi `/prd EP-01 refine` để chạy **lượt 2**. Lượt này chỉ soi phần vừa sửa, nhanh hơn nhiều.
|
|
87
|
+
|
|
88
|
+
Minor không bắt buộc phải quyết. Minor còn `chờ` vẫn duyệt PRD được.
|
|
89
|
+
|
|
90
|
+
## Mẹo
|
|
91
|
+
|
|
92
|
+
- **Thấy finding sai hoặc thừa thì `bác` và ghi lý do, đừng bỏ qua.** Tỉ lệ bác cho người phụ trách framework biết bước kiểm chứng của AI có làm tốt không.
|
|
93
|
+
- Nhiều finding cùng nói về một UC thì quyết chúng **cùng lúc**, để các bản sửa không giẫm lên nhau.
|
|
94
|
+
- Đang quyết dở mà phải dừng thì cứ dừng. Quyết định nào đã ghi thì đã được lưu. Lần sau gọi lại lệnh là tiếp tục từ chỗ còn `chờ`.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
[← Hướng dẫn](../README.md) · [Bảng lệnh](../README.md#bảng-lệnh)
|
|
2
|
+
|
|
3
|
+
# `/bdd` — kịch bản BDD cho một use case
|
|
4
|
+
|
|
5
|
+
> Biến một UC của PRD đã duyệt thành **kịch bản BDD** (file `.feature`, viết theo Gherkin). Mỗi kịch bản có **mã ổn định** `UC-001-SC01`. Dev viết code và test theo kịch bản, còn QC thiết kế test case từ kịch bản.
|
|
6
|
+
|
|
7
|
+
| | Tạo | Bù | Đổi |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| **Gõ** | `/bdd UC-001` | `/bdd UC-001` | `/bdd UC-001 change <mô tả>` |
|
|
10
|
+
| **Khi nào** | Chưa có BDD cho UC này | Đã có BDD, PRD vừa đổi | Kịch bản có nhưng **chưa đủ ý** |
|
|
11
|
+
| **Ai** | PO / BA | PO / BA | PO / BA, hoặc QC / dev báo thiếu |
|
|
12
|
+
| **Cần có trước** | PRD `approved`, có dòng **Nền tảng** | như bên trái | BDD đã có |
|
|
13
|
+
| **Số lượt** | 2 | 2 | 2 |
|
|
14
|
+
| **Ghi ra** | `specs/{domain}/{slug}/bdd/UC-001.feature` | cùng file, version tăng | cùng file, version tăng |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Tạo: `/bdd UC-001`
|
|
19
|
+
|
|
20
|
+
AI chỉ đọc **đúng phần PRD cần cho UC này**: Tổng quan, các hành trình có UC, các dòng Màn hình, khối UC, và các BR của UC khác mà UC này trỏ tới. Với UC-001 của LMS, phần này khoảng 15 KB, trong khi cả PRD là 91 KB.
|
|
21
|
+
|
|
22
|
+
**Lượt 1: dàn ý.** AI trình ba bảng, chưa viết Given/When/Then. Ví dụ minh hoạ, dựng từ UC-001 của LMS:
|
|
23
|
+
|
|
24
|
+
| Mã | Kịch bản | Loại | Nền tảng | Phủ |
|
|
25
|
+
|---|---|---|---|---|
|
|
26
|
+
| UC-001-SC01 | Import có dòng trùng email với tài khoản đã có | happy | web | AC01 · BR04 |
|
|
27
|
+
| UC-001-SC02 | Username không hợp lệ ("@", có dấu, khoảng trắng) | negative | web | AC07 · BR11 |
|
|
28
|
+
|
|
29
|
+
- **Bảng nhánh**: các BR có nhiều nhánh, mỗi nhánh ứng với kịch bản nào. Bạn soát xem có nhánh nào bị sót không.
|
|
30
|
+
- **Điểm giao nhận** với UC khác, lấy từ User flow. Ví dụ *"→ UC-003: người dùng nhận email có link đặt mật khẩu"*. 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õ.
|
|
31
|
+
|
|
32
|
+
Bạn đồng ý, hoặc sửa: *"tách SC02 làm hai"*, *"thiếu nhánh email trống"*.
|
|
33
|
+
|
|
34
|
+
**Lượt 2: ghi và duyệt.**
|
|
35
|
+
1. AI ghi cả file trong một lần.
|
|
36
|
+
2. Công cụ **kiểm độ phủ**: mọi AC và BR của UC đều phải có mặt trong ít nhất một kịch bản. Thiếu thì AI bổ sung, không được tự bỏ.
|
|
37
|
+
3. AI chỉ in các mục 🤖, tức những chỗ phải giả định vì PRD chưa ghi, ví dụ câu báo lỗi. Bạn xác nhận theo mã: *"OK UC-001-SC02"*.
|
|
38
|
+
4. AI hỏi *"Ai duyệt BDD này?"* rồi đặt `status: approved`.
|
|
39
|
+
|
|
40
|
+
## File BDD trông như thế nào
|
|
41
|
+
|
|
42
|
+
```gherkin
|
|
43
|
+
# ── Import file ──
|
|
44
|
+
@UC-001-SC01 @web @happy @UC-001-AC01 @UC-001-BR04
|
|
45
|
+
Scenario: Import có dòng trùng email với tài khoản đã có
|
|
46
|
+
Given đã có tài khoản nhân sự với email "an@edupia.vn"
|
|
47
|
+
When Admin import file 10 dòng, trong đó 2 dòng dùng email "an@edupia.vn"
|
|
48
|
+
Then 8 tài khoản được tạo
|
|
49
|
+
And 2 dòng được báo lỗi kèm lý do
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Dòng `@…` là **tag**. Mỗi kịch bản có đủ bốn loại tag:
|
|
53
|
+
|
|
54
|
+
| Tag | Nghĩa |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `@UC-001-SC01` | Mã kịch bản. Không bao giờ đổi. Code và test trỏ về kịch bản bằng mã này |
|
|
57
|
+
| `@web` `@app` | Nền tảng. Hành vi giống nhau thì một kịch bản mang cả hai tag. Hành vi khác nhau thì tách thành hai kịch bản |
|
|
58
|
+
| `@happy` `@alternative` `@edge` `@negative` | Loại: thành công · luồng khác vẫn thành công · biên, giới hạn · bị từ chối, lỗi |
|
|
59
|
+
| `@UC-001-AC01` `@UC-001-BR04` | AC và BR mà kịch bản này kiểm |
|
|
60
|
+
|
|
61
|
+
Các biến thể của cùng một luật được gộp thành **`Scenario Outline`** kèm bảng `Examples`, ví dụ ba kiểu username không hợp lệ nằm trong một bảng. Giá trị biên ghi trong BR phải có cả hai phía: 1.000 dòng được nhận, 1.001 dòng bị từ chối.
|
|
62
|
+
|
|
63
|
+
## Nền tảng
|
|
64
|
+
|
|
65
|
+
PRD khai nền tảng ở Tổng quan, ví dụ `- **Nền tảng:** web · app`. UC nào chạy khác thì ghi dòng riêng trong UC. **Thiếu dòng này thì PRD không duyệt được, và `/bdd` dừng.** PRD tạo bằng bản trước 0.10.0 chưa có dòng này, nên phải chạy `/prd EP-01 change khai nền tảng: web` trước.
|
|
66
|
+
|
|
67
|
+
Khác nhau chỉ ở giao diện (bố cục, cử chỉ) thì **không** tách kịch bản, vì đó là việc của design-spec. Chỉ tách khi **kết quả** khác nhau.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Bù: `/bdd UC-001` khi đã có file
|
|
72
|
+
|
|
73
|
+
Dùng sau khi PRD đổi (`/prd EP-01 change`, refine, rồi duyệt lại). Công cụ tự tìm ra:
|
|
74
|
+
- AC hoặc BR **chưa có kịch bản** nào;
|
|
75
|
+
- kịch bản trỏ tới mục **đã bỏ** trong PRD;
|
|
76
|
+
- các mục đổi nội dung kể từ version PRD mà BDD viết theo (đọc từ Lịch sử thay đổi của PRD).
|
|
77
|
+
|
|
78
|
+
AI trình kế hoạch *thêm · sửa · bỏ* theo mã, bạn duyệt rồi AI áp. Không có gì để bù thì AI báo *"BDD đã khớp PRD"* và dừng.
|
|
79
|
+
|
|
80
|
+
## Đổi: `/bdd UC-001 change <mô tả>`
|
|
81
|
+
|
|
82
|
+
Dùng khi kịch bản **có rồi nhưng chưa đủ ý**, và công cụ không tự bắt được. Ví dụ:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
/bdd UC-001 change BR01 mới có kịch bản email đã thuộc người khác, thiếu nhánh email trống và sai định dạng
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Nếu điều bạn mô tả **chưa có trong PRD**, thì đó là thay đổi yêu cầu. AI sẽ từ chối và chỉ sang `/prd EP-01 change …`, vì kịch bản không được có điều PRD không ghi.
|
|
89
|
+
|
|
90
|
+
## Lưu ý
|
|
91
|
+
|
|
92
|
+
- **Mã không bao giờ đổi.** Kịch bản bỏ đi vẫn còn một dòng `# Đã bỏ (v1.1) @UC-001-SC05 — …` trong file, và số đó không bị dùng lại.
|
|
93
|
+
- **Kịch bản E2E** đi qua nhiều UC (các hành trình J1, J2… trong User flow) do QC làm, không nằm trong `/bdd`.
|
|
94
|
+
- Đổi BDD đã `approved` thì file quay về `draft` và phải duyệt lại. BDD chỉ duyệt được khi viết theo **đúng version PRD hiện tại**.
|
|
@@ -41,21 +41,9 @@ Khi bạn quyết xong, bảng Tóm tắt trong `prd-refine.md` ghi số **nhậ
|
|
|
41
41
|
|
|
42
42
|
## Bạn quyết thế nào
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
> Cách làm từng bước, kèm câu gõ mẫu và mẹo: **[Cách quyết finding sau khi refine](../cach-lam/quyet-finding-refine.md)**.
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
nhận F01, F03 · bác F02 vì đã có ở UC-002 · F04 sửa thành "khoá 30 phút" · hoãn F05
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Hoặc **quyết theo nhóm**, áp cho major và minor:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
nhận tất cả minor · nhận hết UC-003 trừ F12 · bác F20–F24 vì đã có ở epic khác
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Quyết theo nhóm thì AI **liệt kê lại đúng các mã** sẽ bị áp rồi hỏi bạn xác nhận. **Critical luôn phải quyết từng mã.**
|
|
46
|
+
AI trình bảng tóm tắt, **sắp theo mức độ** (critical → major → minor), rồi **theo lăng kính** (QA → DEV → SA → Phạm vi). Mã F đánh theo đúng thứ tự đó, nên F01 luôn là finding nặng nhất. Chi tiết từng finding nằm trong `review/prd-refine.md`. Gọi lại lệnh khi lượt trước đang chờ quyết thì lệnh **không rà lại**, chỉ trình lại bảng tóm tắt.
|
|
59
47
|
|
|
60
48
|
| Quyết định | Kết quả |
|
|
61
49
|
|---|---|
|
|
@@ -64,7 +52,8 @@ Quyết theo nhóm thì AI **liệt kê lại đúng các mã** sẽ bị áp r
|
|
|
64
52
|
| `bác: <lý do>` | Không sửa. Lần rà sau **không nêu lại** điểm này |
|
|
65
53
|
| `hoãn` | Không sửa lúc này. Được ghi vào "Câu hỏi còn mở" của PRD để bước QC xử lý |
|
|
66
54
|
|
|
67
|
-
|
|
55
|
+
- Quyết được **theo mã** hoặc **theo nhóm** (chỉ cho major và minor). **Critical phải quyết từng mã.**
|
|
56
|
+
- Bác hay hoãn đều tính là **đã quyết**. Mọi critical và major đã có quyết định là đi tiếp được. Minor còn `chờ` không chặn.
|
|
68
57
|
|
|
69
58
|
## Vì sao chỉ có 2 lượt
|
|
70
59
|
|
package/docs/guide/lenh/prd.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| **Cần có trước** | Epic `ready` (xem [/product](product.md)) | PRD đã có |
|
|
12
12
|
| **Số lượt** | 2 | 2 |
|
|
13
13
|
| **Ghi ra** | `specs/{domain}/{slug}/prd.md` · epic chuyển `handed-off` | `prd.md`, version tăng (1.0 → 1.1) |
|
|
14
|
-
| **Bước tiếp** | [`/prd EP-01 refine`](prd-refine.md) → duyệt PRD → `/bdd UC-xxx`
|
|
14
|
+
| **Bước tiếp** | [`/prd EP-01 refine`](prd-refine.md) → duyệt PRD → [`/bdd UC-xxx`](bdd.md) | [`/prd EP-01 refine`](prd-refine.md) (chỉ rà phần vừa đổi) → duyệt lại → [`/bdd UC-xxx`](bdd.md) để bù |
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -51,7 +51,7 @@ Acceptance Criteria (điều kiện nghiệm thu)
|
|
|
51
51
|
- UC-001-AC01. Khi Admin import file 10 dòng, trong đó 2 dòng trùng email thì 8 tài khoản được tạo, 2 dòng được báo lỗi kèm lý do. (nguồn: AC1)
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
Gồm 6 mục: **Tổng quan** (mục tiêu, actor, phạm vi, ràng buộc áp dụng) · **User flow** · **Use case** · **Màn hình** · **Câu hỏi còn mở** · **Lịch sử thay đổi**.
|
|
54
|
+
Gồm 6 mục: **Tổng quan** (mục tiêu, actor, **nền tảng**, phạm vi, ràng buộc áp dụng) · **User flow** · **Use case** · **Màn hình** · **Câu hỏi còn mở** · **Lịch sử thay đổi**.
|
|
55
55
|
|
|
56
56
|
**User flow** là các **hành trình** xuyên suốt nhiều UC: actor đi qua những UC nào, rẽ nhánh ở đâu, gặp lỗi thì đi đâu. Mỗi hành trình gồm một dòng trong bảng và một sơ đồ (GitLab hiển thị sẵn):
|
|
57
57
|
|
|
@@ -91,6 +91,7 @@ Dùng cho **mọi** thay đổi: thêm, sửa, bỏ.
|
|
|
91
91
|
|
|
92
92
|
## Lưu ý
|
|
93
93
|
|
|
94
|
+
- **Nền tảng** (`web`, `app`…) ghi ở Tổng quan và là mặc định cho mọi UC. UC nào chạy khác thì ghi dòng riêng trong UC. Thiếu dòng này thì PRD không duyệt được, vì BDD cần nó để tách kịch bản theo nền tảng. PRD tạo bằng bản trước 0.10.0: `/prd EP-01 change khai nền tảng: web`.
|
|
94
95
|
- **Bạn được tự sửa tay PRD.** Nhưng giữ nguyên mã, dấu ✅ / 🤖 và đoạn `<!-- sec:… -->`. Sửa nhiều thì nên dùng `change`, để AI tìm giúp các mục bị kéo theo.
|
|
95
96
|
- **Không sửa epic sau khi đã có PRD.** Epic lúc này chỉ còn là lịch sử.
|
|
96
97
|
- PRD tạo bằng bản framework cũ (trước 0.6.1) có thể còn ghi nguồn bằng lời, ví dụ *"(nguồn: PO chốt khi viết PRD)"*. Lần sửa đầu tiên AI sẽ được yêu cầu đổi các chỗ đó thành mã, thường là `PRD`.
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
## Đường đi của bạn
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
/product ──► /product EP-xx ──► /prd EP-xx ──► /prd EP-xx refine ──► duyệt PRD ──►
|
|
11
|
-
▲ │
|
|
12
|
-
└─ /prd EP-xx change ◄┘ khi yêu cầu thay đổi
|
|
10
|
+
/product ──► /product EP-xx ──► /prd EP-xx ──► /prd EP-xx refine ──► duyệt PRD ──► /bdd UC-xxx ──► duyệt BDD
|
|
11
|
+
▲ │ (từng UC)
|
|
12
|
+
└─ /prd EP-xx change ◄┘ khi yêu cầu thay đổ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 |
|
|
@@ -18,7 +18,14 @@
|
|
|
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
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. Xong thì duyệt PRD | [/prd refine](../lenh/prd-refine.md) |
|
|
21
|
-
| 5 | `/
|
|
21
|
+
| 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) |
|
|
22
|
+
| 6 | `/prd EP-xx change …` | Khi yêu cầu đổi. Duyệt kế hoạch thay đổi, refine 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ả) |
|
|
23
|
+
|
|
24
|
+
## Cách làm thường gặp
|
|
25
|
+
|
|
26
|
+
| Việc | Hướng dẫn |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Quyết vài chục finding sau khi refine PRD | [Cách quyết finding sau khi refine](../cach-lam/quyet-finding-refine.md) |
|
|
22
29
|
|
|
23
30
|
## Mẹo
|
|
24
31
|
|
|
@@ -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,10 @@
|
|
|
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 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`) |
|
|
32
|
+
| `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ù |
|
|
33
|
+
| `@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 đó |
|
|
34
|
+
| `⚠ 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
35
|
| `💡 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
36
|
| `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
37
|
| `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ả>` |
|