@educa-corp/fw 0.11.1 → 0.11.2
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 +6 -0
- package/commands/bdd.md +1 -1
- package/docs/guide/README.md +1 -1
- package/docs/guide/lenh/bdd.md +2 -0
- package/package.json +1 -1
- package/ref/bdd/new.md +4 -0
- package/ref/prd/change.md +9 -2
- package/ref/prd/refine.md +2 -1
- package/tools/spec_edit.py +19 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
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.11.2 — 2026-10-02
|
|
7
|
+
|
|
8
|
+
- **Bản sửa PRD phải tự soát đồng bộ** trước khi tăng version, cho cả `/prd change` lẫn bước áp bản sửa của refine. Với từng BR / AC vừa viết: AC có kiểm được không, Luồng chính và Kết quả sau đã khớp chưa, User flow đã khớp chưa, UC khác trỏ tới có cần sửa theo không. Lý do: cả 3 lỗi lọt qua refine của LMS đều sinh ra từ chính bản sửa, và đều thuộc kiểu "thêm một dòng mà quên những chỗ liên quan".
|
|
9
|
+
- **`/bdd` đưa ra các vấn đề refine đã ghi "Có từ trước, để sau"** của UC đang viết, ngay ở lượt 1. Viết được theo BR đang có thì viết, kèm 🤖. Muốn viết đúng phải thêm nghĩa mới vào PRD thì dừng, và gom vào một lần `/prd change`.
|
|
10
|
+
- Cảnh báo kích thước PRD ghi đúng hơn: người đọc cả PRD là các agent refine / review (`/bdd` chỉ đọc một UC).
|
|
11
|
+
|
|
6
12
|
## 0.11.1 — 2026-10-02
|
|
7
13
|
|
|
8
14
|
Sửa vòng lặp *review → change → refine → finding mới*. Lần chạy đầu trên LMS: review gợi ý đổi tên một trạng thái, dẫn tới `change` rồi refine ra 8 finding, tốn khoảng 4,4M token mà không có thay đổi nghiệp vụ nào.
|
package/commands/bdd.md
CHANGED
|
@@ -18,7 +18,7 @@ Tham số: `$ARGUMENTS`
|
|
|
18
18
|
|
|
19
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
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,
|
|
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, đúng các mục của UC khác mà UC này trỏ tới, và các vấn đề refine đã ghi *"Có từ trước, để sau"* cho UC này. **Không đọc cả PRD.** Cần thêm một UC khác thì chỉ đọc `SE uc D UC-xxx`.
|
|
22
22
|
4. Đọc `{specs}/product/glossary.md` nếu có. Viết đúng thuật ngữ.
|
|
23
23
|
|
|
24
24
|
## Bước 2 — Chọn chế độ
|
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.11.
|
|
4
|
+
> Hướng dẫn này viết cho **bản 0.11.2**. 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
|
---
|
package/docs/guide/lenh/bdd.md
CHANGED
|
@@ -29,6 +29,8 @@ AI chỉ đọc **đúng phần PRD cần cho UC này**: Tổng quan, các hành
|
|
|
29
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
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
31
|
|
|
32
|
+
- **Vấn đề PRD còn để sau**: những lỗi mà refine đã thấy trong UC này nhưng chưa sửa. Viết được theo BR đang có thì AI viết, kèm 🤖. Không viết được thì AI dừng UC đó và đề nghị gom vào một lần `/prd change`.
|
|
33
|
+
|
|
32
34
|
Bạn đồng ý, hoặc sửa: *"tách SC02 làm hai"*, *"thiếu nhánh email trống"*.
|
|
33
35
|
|
|
34
36
|
**Lượt 2: ghi và duyệt.**
|
package/package.json
CHANGED
package/ref/bdd/new.md
CHANGED
|
@@ -24,6 +24,10 @@ Chỉ **2 lượt** hỏi-đáp. PRD đã được duyệt và refine, nên khô
|
|
|
24
24
|
|
|
25
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
26
|
|
|
27
|
+
**d. Vấn đề PRD còn để sau.** `SE context` có mục *"Vấn đề PRD còn để sau"* thì đây là lỗi refine đã thấy nhưng chưa sửa. Viết kịch bản là lúc chúng lộ ra, ví dụ AC không kiểm được hoặc một nhánh bị bỏ qua. Với mỗi vấn đề, chọn một trong hai:
|
|
28
|
+
- Viết được kịch bản **chỉ theo các BR đang có**, không phải thêm nghĩa mới: viết theo BR, rồi gắn `🤖` kèm câu *"theo BR…, chờ sửa PRD"*.
|
|
29
|
+
- Muốn viết đúng thì phải thêm nghĩa mới vào PRD: **dừng** UC này, và báo *"Cần `/prd EP-xx change …` trước, cho các vấn đề: …"*. Gom mọi vấn đề như vậy của cả epic vào **một** lần change.
|
|
30
|
+
|
|
27
31
|
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
32
|
|
|
29
33
|
## Lượt 2 — Ghi file
|
package/ref/prd/change.md
CHANGED
|
@@ -30,5 +30,12 @@ Khi PO đồng ý kế hoạch:
|
|
|
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
|
- 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`.
|
|
33
|
-
2.
|
|
34
|
-
|
|
33
|
+
2. **Soát đồng bộ trước khi tăng version.** Lỗi hay gặp nhất của bản sửa là thêm hoặc sửa một dòng mà quên những chỗ liên quan. Lần đo trên LMS: khoảng 20–25% bản sửa sinh ra lỗi mới, và cả 3 lỗi lọt qua refine đều thuộc kiểu này. Với **từng** dòng BR / AC vừa thêm hoặc sửa, đọc lại bằng `SE uc D <UC>` rồi trả lời:
|
|
34
|
+
- **AC kiểm được không?** Kết quả có nhìn thấy được, đánh đạt hay không đạt được không? Có khớp với các BR khác đang áp lên cùng tình huống không? Ví dụ một AC ghi *"vẫn đăng nhập được"* trong khi một BR khác bắt người đó đặt mật khẩu mới trước, thì AC đó không kiểm được.
|
|
35
|
+
- **Phần còn lại của UC đã khớp chưa?** Luồng chính, Điều kiện trước và Kết quả sau. Ví dụ thêm một nhánh BR mới thì Kết quả sau phải nói tới kết quả của nhánh đó.
|
|
36
|
+
- **User flow đã khớp chưa?** Hành trình đi qua UC này có nhánh nào bỏ qua luật mới không?
|
|
37
|
+
- **UC khác có trỏ tới mục này không?** Có thì xem các mục đó có cần sửa theo không.
|
|
38
|
+
|
|
39
|
+
Thiếu chỗ nào thì sửa luôn trong lần này, rồi ghi chỗ đã sửa thêm vào dòng Lịch sử thay đổi.
|
|
40
|
+
3. 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=—`.
|
|
41
|
+
4. 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/refine.md
CHANGED
|
@@ -68,7 +68,8 @@ Phiên chính **không đọc** kết quả chi tiết của các agent. Agent g
|
|
|
68
68
|
- đọc từng finding bằng `SE finding`, đọc UC liên quan bằng `SE uc`;
|
|
69
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
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
|
+
- **soát đồng bộ** từng dòng vừa viết theo bước 2 của `change.md` (AC kiểm được không · Luồng và Kết quả sau · User flow · UC khác trỏ tới). Thiếu thì sửa luôn;
|
|
71
72
|
- 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
|
+
- **chỉ trả về một dòng**: *"áp {k} finding → v{version}; {số BR/AC sửa · thêm · bỏ}; đồng bộ thêm {m} chỗ"*.
|
|
73
74
|
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
75
|
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."*
|
package/tools/spec_edit.py
CHANGED
|
@@ -682,7 +682,8 @@ PRD_SIZE_WARN = 60 * 1024
|
|
|
682
682
|
def size_warning(path):
|
|
683
683
|
size = os.path.getsize(path)
|
|
684
684
|
if size > PRD_SIZE_WARN:
|
|
685
|
-
print("⚠ PRD %d KB (ngưỡng %d KB):
|
|
685
|
+
print("⚠ PRD %d KB (ngưỡng %d KB): mỗi agent refine / review đều đọc toàn bộ PRD, nên mỗi lần đổi PRD đều đắt. "
|
|
686
|
+
"Cân nhắc tách epic thành nhiều PRD nhỏ hơn."
|
|
686
687
|
% (size // 1024, PRD_SIZE_WARN // 1024))
|
|
687
688
|
|
|
688
689
|
|
|
@@ -1071,9 +1072,26 @@ def cmd_context(path, ucs):
|
|
|
1071
1072
|
for c in foreign:
|
|
1072
1073
|
hits = find_item(lines, c)
|
|
1073
1074
|
out.append(lines[hits[0]] if hits else "(không tìm thấy %s trong PRD)" % c)
|
|
1075
|
+
later = deferred_items(refine_path(path), re.compile(r"%s(?!\d)" % re.escape(uc)))
|
|
1076
|
+
if later:
|
|
1077
|
+
out += ["", "## Vấn đề PRD còn để sau (refine ghi \"Có từ trước, để sau\") — xem ref/bdd/new.md mục d"] + later
|
|
1074
1078
|
print("\n".join(out).rstrip())
|
|
1075
1079
|
|
|
1076
1080
|
|
|
1081
|
+
def deferred_items(rpath, mention):
|
|
1082
|
+
"""Các dòng dưới `### Có từ trước, để sau` của file refine có nhắc tới UC (mention là regex mã UC)."""
|
|
1083
|
+
if not os.path.isfile(rpath):
|
|
1084
|
+
return []
|
|
1085
|
+
out, inside = [], False
|
|
1086
|
+
for l in read(rpath).split("\n"):
|
|
1087
|
+
if re.match(r"^#{2,4}\s", l):
|
|
1088
|
+
inside = l.lstrip("#").strip().startswith("Có từ trước")
|
|
1089
|
+
continue
|
|
1090
|
+
if inside and l.startswith("- ") and mention.search(l):
|
|
1091
|
+
out.append(l)
|
|
1092
|
+
return out
|
|
1093
|
+
|
|
1094
|
+
|
|
1077
1095
|
def used_sc(text, uc):
|
|
1078
1096
|
return sorted({int(m.group(3)) for m in SC_ANY.finditer(text) if m.group(2) == uc[3:]})
|
|
1079
1097
|
|