221 lines
13 KiB
Markdown
221 lines
13 KiB
Markdown
---
|
||
name: ba-traceability
|
||
description: Skill xuyên suốt của quy trình BA — dựng và kiểm tra ma trận truy vết yêu cầu (RTM). Dùng để phát hiện yêu cầu bị bỏ quên, user story không có nguồn gốc (scope creep), AC không được test, business rule không được kiểm chứng, và tham chiếu gãy giữa các tài liệu. Kích hoạt khi người dùng nói "kiểm tra coverage", "có sót yêu cầu nào không", "ma trận truy vết", "RTM", "traceability", "rà soát chéo tài liệu BA", "trước khi trình gate", "requirement nào chưa được test". Chạy được ở mọi giai đoạn và có quyền chặn Gate G2, G3, G4.
|
||
---
|
||
|
||
# ⊕ TRACEABILITY — Ma trận truy vết & kiểm tra coverage
|
||
|
||
Skill này không thuộc giai đoạn nào. Nó chạy **sau mỗi giai đoạn** và trả lời đúng một câu
|
||
hỏi: **"có cái gì bị rơi giữa các tài liệu không?"**
|
||
|
||
Nó có **quyền chặn Gate G2, G3, G4**: coverage không đạt thì gate không pass.
|
||
|
||
Output: `RTM_<PROJECT>.md` trong `ba-output/<PROJECT>/00-index/` + báo cáo coverage.
|
||
|
||
## Bốn nguyên tắc bất di bất dịch
|
||
|
||
1. **Không bịa yêu cầu.**
|
||
2. **Không quyết định thay PO.**
|
||
3. **Mọi phát biểu truy vết được** — đây chính là việc của skill này.
|
||
4. **Không ghi đè tài liệu đã qua gate.**
|
||
|
||
🔴 **Nguyên tắc riêng: skill này KHÔNG sửa tài liệu nghiệp vụ.** Nó phát hiện và báo cáo.
|
||
Sửa là việc của skill giai đoạn tương ứng. Tự sửa sẽ che mất vấn đề thay vì giải quyết nó.
|
||
|
||
## Bước 0 — Chốt input rồi dừng lại
|
||
|
||
**Chưa được ghi file.** Làm năm việc rồi **dừng chờ trả lời**:
|
||
|
||
1. **Profile** — đọc `00-index/PROFILE_<PROJECT>.md`. Nó quyết định **phép kiểm nào áp dụng**
|
||
(Bước 2) và **ngưỡng nào bắt buộc** (Bước 5).
|
||
2. **Tài liệu quét được** — bảng `File | Loại | Version | Status | Số ID trích được`.
|
||
3. **Tài liệu thiếu** — loại nào không tìm thấy, và điều đó làm phép kiểm nào **không chạy
|
||
được** (nói rõ, đừng lặng lẽ bỏ phép kiểm đó).
|
||
4. **Mục đích lần chạy** — dựng RTM lần đầu, cập nhật sau một giai đoạn, hay kiểm tra trước
|
||
khi trình gate?
|
||
5. **Hỏi xác nhận** bốn điểm trên.
|
||
|
||
Bỏ qua khi lệnh có `go`.
|
||
|
||
## Thực hiện — 4 bước
|
||
|
||
### Bước 1 — Trích ID từ mọi tài liệu
|
||
|
||
Quét theo quy ước ID ở `../ba-lifecycle/README.md` §4:
|
||
|
||
```bash
|
||
grep -rnoE "(RQ|US|BR|AC|NFR|OQ|DEC|CR|RISK|ASM|GOAL|STK|ROLE|FLD)-[A-Za-z0-9-]+" ba-output/<PROJECT> \
|
||
| sort -u
|
||
```
|
||
|
||
Với mỗi ID ghi lại: **nơi định nghĩa** (tài liệu nào định nghĩa nó) và **nơi tham chiếu**
|
||
(tài liệu nào nhắc tới nó).
|
||
|
||
🔴 Phân biệt hai thứ này là điểm mấu chốt. Một ID được tham chiếu nhiều nơi nhưng **không có
|
||
nơi định nghĩa** là tham chiếu gãy — dev đọc spec thấy "theo BR-021" rồi đi tìm không ra.
|
||
|
||
### Bước 2 — Sáu phép kiểm coverage
|
||
|
||
Điền `templates/rtm.md`. Chạy đủ sáu phép, mỗi phép ra một danh sách:
|
||
|
||
| # | Phép kiểm | Chiều | Phát hiện | Chặn gate |
|
||
|---|---|---|---|---|
|
||
| 1 | Mỗi `RQ` → có ≥1 `US` | xuôi | **Yêu cầu bị bỏ quên** | G2 |
|
||
| 2 | Mỗi `US` → truy về được `RQ` | ngược | **Scope creep** | G2 |
|
||
| 3 | Mỗi `US` → có ≥1 `AC` mỗi nhóm bắt buộc | xuôi | Đặc tả chưa xong | G3 |
|
||
| 4 | Mỗi `BR` → được áp dụng ở ≥1 `US`/`field` | xuôi | Rule mồ côi | G3 |
|
||
| 5 | Mỗi `AC` → có ≥1 test case | xuôi | **AC không được kiểm chứng** | G4 |
|
||
| 6 | Mỗi ID được tham chiếu → có nơi định nghĩa | — | **Tham chiếu gãy** | G2/G3/G4 |
|
||
|
||
**Hai chiều đều quan trọng, và chúng bắt hai loại lỗi khác nhau:**
|
||
|
||
```
|
||
chiều xuôi RQ → US → AC → test case bắt: BỎ SÓT
|
||
chiều ngược test case → AC → US → RQ bắt: LÀM THỪA
|
||
```
|
||
|
||
Chỉ chạy chiều xuôi là bỏ qua toàn bộ scope creep — thứ làm dự án trễ mà không ai giải
|
||
thích được vì sao.
|
||
|
||
**Phép kiểm 3 chặt hơn "có AC"**: mỗi `US` phải có AC ở đủ bốn nhóm (thành công · validation ·
|
||
lỗi hệ thống · phân quyền). US chỉ có AC nhóm 1 ⇒ tính là **chưa phủ**, không phải "đã phủ
|
||
một phần".
|
||
|
||
### Điều chỉnh theo profile
|
||
|
||
| Trục | Ảnh hưởng tới phép kiểm |
|
||
|---|---|
|
||
| `PRODUCT = ml-model` | Phép kiểm 3 **chỉ áp cho hệ thống bao quanh**. Phần dự đoán thay bằng: mỗi `GOAL` chất lượng có ≥1 metric **có ngưỡng**, và mỗi ngưỡng truy về được một chi phí nghiệp vụ |
|
||
| `PRODUCT = data-pipeline` | Thêm phép kiểm: mỗi luồng có ≥1 quy tắc **đối soát nguồn–đích**. Thiếu ⇒ 🔴 chặn G3 |
|
||
| `PRODUCT = batch-job` | Thêm phép kiểm: mỗi job đã trả lời **idempotency** và **thất bại giữa chừng**. Bỏ trống ⇒ 🔴 chặn G3 |
|
||
| `PRODUCT = api-service` | Thêm phép kiểm: mỗi mã lỗi map về ≥1 endpoint, và mỗi endpoint có cột "người gọi nên làm gì" |
|
||
| `RIGOR = light` | Phép kiểm 3 chỉ đòi nhóm 1–2; nhóm 3–4 đòi **nếu** có ghi/xoá dữ liệu hoặc >1 vai trò |
|
||
| `RIGOR = strict` | Thêm phép kiểm: mỗi hành động ghi có dòng trong bảng lưu vết; mỗi mã lỗi có đủ bản dịch |
|
||
|
||
🔴 **Phép kiểm bị bỏ vì profile phải được ghi ra trong báo cáo**, kèm lý do — đừng lặng lẽ
|
||
tính coverage trên tập nhỏ hơn rồi báo 100%.
|
||
|
||
### Bước 3 — Tám phép kiểm nhất quán
|
||
|
||
Ngoài coverage, kiểm tra tài liệu có mâu thuẫn nhau không (6 phép cho mọi loại + 2 phép riêng cho design, `screen`):
|
||
|
||
| # | Phép kiểm | Cách kiểm | Ví dụ lỗi bắt được |
|
||
|---|---|---|---|
|
||
| 1 | **Version lệch** | `SRS` khai `Source: BR_v1.0` nhưng `BR` đã lên v1.2 | SRS viết theo rule cũ |
|
||
| 2 | **Ràng buộc lệch** | Bảng field trong `SRS` vs. bảng ràng buộc trong `API` | UI chặn 20 ký tự, API chặn 50 |
|
||
| 3 | **Mã lỗi lệch** | Mã trong `SRS` §4.1 vs. mã trong `API` §4 | Mã lỗi không endpoint nào sinh ra |
|
||
| 4 | **Trạng thái lệch** | Trạng thái trong `BR` vs. trạng thái dùng trong `SRS`/`RBAC` | RBAC phân quyền cho trạng thái không tồn tại |
|
||
| 5 | **Thành phần lệch** *(screen)* | Tập `C-id`/`F-id` trong `SRS` §2.3.1/§2.3.3 vs. `WF` §3.x.2, `data-c` trong `WF.html` **và** `data-c`/`data-f` trong `HIFI.html` — **hai chiều** | Nút có trong WF (từ prototype) mà SRS không đặc tả hành vi; hoặc SRS có nút mà WF không đặt chỗ |
|
||
| 6 | **Quy ước lệch** *(screen)* | `SRS` §2.3.2/§2.3.6/§4.3 định nghĩa phân trang, trạng thái, định dạng khác `UICONV` mà `UICONV` §12 không có dòng | Hai SRS hai kiểu phân trang; múi giờ hiển thị khác nhau |
|
||
| 7 | **Text lệch** *(screen · design)* | Text của mọi `data-key` trong `HIFI.html` vs. bảng `SRS` §4.2 — phải **nguyên văn** (W5) | Design "làm gọn" nhãn: SRS "Tạo mới", HIFI "Tạo"; message lỗi viết lại |
|
||
| 8 | **Token lệch** *(screen · design)* | Khối `:root`/`ds-components` trong `HIFI` vs. `00-index/ds/`; mã màu thô trong markup HIFI; màu trong `FIGMA/*.svg` ∉ `tokens.json`; `SCR` của SRS §2.1 thiếu trong HIFI/SVG | HIFI dùng `#333` không có trong DS; SVG còn màu cũ sau khi đổi token; màn hình lỗi không có mockup |
|
||
|
||
Phép 1 chạy được bằng máy: so `Source:` trong header với version thật của file được trích dẫn.
|
||
Phép 5 cũng vậy:
|
||
|
||
```bash
|
||
grep -oE "\b[CF][0-9]{2}\b" SRS_<US>*.md | sort -u > /tmp/srs_ids
|
||
grep -oE "\b[CF][0-9]{2}\b|data-c=\"[CF][0-9]{2}\"" WF_<US>*.md WF_<US>*.html | grep -oE "[CF][0-9]{2}" | sort -u > /tmp/wf_ids
|
||
comm -3 /tmp/srs_ids /tmp/wf_ids # phải rỗng
|
||
```
|
||
|
||
Phép 5 (phần `HIFI`), 7 và 8 chạy bằng script của `ba-design` — chép kết quả nguyên văn vào RTM §4:
|
||
|
||
```bash
|
||
node .claude/skills/ba-design/scripts/design-check.mjs \
|
||
--tokens ba-output/<P>/00-index/ds/tokens.json --css ba-output/<P>/00-index/ds/tokens.css \
|
||
--components ba-output/<P>/00-index/ds/components.html \
|
||
--html ba-output/<P>/03-specification/design/HIFI_<US>_v1.0.html \
|
||
--srs ba-output/<P>/03-specification/SRS_<US>_v1.0.md --wf ba-output/<P>/03-specification/WF_<US>_v1.0.md \
|
||
--svg-dir ba-output/<P>/03-specification/design/FIGMA_<US>_v1.0
|
||
```
|
||
|
||
Không chạy được ⇒ ghi "chưa kiểm bằng máy" cho phép 7–8, không báo "không lệch". H3/H4 🔴 ⇒ **chặn G3**.
|
||
|
||
Ngoài ra với `screen`: đọc `WF` §5 — mỗi dòng loại **Tồn tại/Hành vi** có trạng thái ☐ là một
|
||
blocker G3, liệt kê đích danh. `WF` không có §5 hoặc §5 trống không ghi "đã đối chiếu" ⇒ báo
|
||
"chưa đối chiếu prototype", không phải "không lệch".
|
||
|
||
### Bước 4 — `OQ` và `CR` tồn đọng
|
||
|
||
```bash
|
||
grep -rn "OQ-[0-9]" ba-output/<PROJECT> | sort -u
|
||
grep -rn "TBD\|TODO\|???" ba-output/<PROJECT>
|
||
```
|
||
|
||
Với mỗi `OQ` mở: hỏi ai · từ ngày · chặn ID nào · quá hạn bao nhiêu ngày (>5 ngày làm việc
|
||
⇒ 🔴). Với mỗi `CR`: trạng thái · chờ ai · bao lâu rồi.
|
||
|
||
`TBD` trong bảng field hoặc bảng mã lỗi ⇒ **báo là blocker của G3**.
|
||
|
||
## Báo cáo — in đúng năm phần
|
||
|
||
**① Bảng coverage tổng hợp** — mở đầu bằng dòng profile và **danh sách phép kiểm đã bỏ**:
|
||
|
||
```
|
||
Profile: data-pipeline · brownfield · strict
|
||
Phép kiểm bỏ: (không có)
|
||
Phép kiểm thêm: đối soát nguồn–đích · lưu vết mọi hành động ghi
|
||
```
|
||
|
||
| Phép kiểm | Tổng | Đã phủ | Coverage | Ngưỡng | ☐/✅ |
|
||
|---|---|---|---|---|---|
|
||
| RQ → US | 12 | 11 | 91,7% | 100% | 🔴 |
|
||
| US → RQ | 18 | 16 | 88,9% | 100% | 🔴 |
|
||
| US → AC (đủ 4 nhóm) | 18 | 12 | 66,7% | 100% | 🔴 |
|
||
| BR → áp dụng | 24 | 24 | 100% | 100% | ✅ |
|
||
| AC → test case | 96 | — | — | 100% | ⏳ QA chưa viết |
|
||
| Tham chiếu → định nghĩa | 214 | 211 | 98,6% | 100% | 🔴 |
|
||
|
||
**② Danh sách chi tiết từng lỗ hổng** — mỗi dòng nêu đích danh ID, ở tài liệu nào, và
|
||
**skill nào cần chạy để sửa**:
|
||
|
||
```
|
||
🔴 RQ-005 chưa có US nào phủ
|
||
Định nghĩa tại: BRIEF_Settlement_v1.0.md §6
|
||
Sửa bằng: /ba-2-analysis Settlement
|
||
|
||
🔴 BR-021 được tham chiếu ở SRS_US011 §1.3 nhưng không tìm thấy định nghĩa
|
||
Có thể đã bị đổi số hoặc BR_Settlement chưa cập nhật
|
||
Sửa bằng: /ba-2-analysis Settlement --only br
|
||
```
|
||
|
||
**③ Bảng nhất quán** — tám phép kiểm ở Bước 3, mỗi mâu thuẫn một dòng; phép 7–8 kèm dòng kết quả `design-check`.
|
||
|
||
**④ `OQ`/`CR` tồn đọng** — sắp theo số ngày quá hạn giảm dần.
|
||
|
||
**⑤ Kết luận gate**
|
||
|
||
```
|
||
G2: 🔴 CHẶN — RQ-005 chưa phủ, US-018 và US-019 không truy về RQ
|
||
G3: 🔴 CHẶN — 6/18 US thiếu AC nhóm lỗi hệ thống; 4 TBD trong bảng field
|
||
G4: ⏳ Chưa đánh giá được — QA chưa nộp test case
|
||
```
|
||
|
||
Nói thẳng gate nào bị chặn và vì sao. **Không làm tròn lên.** Coverage 99% vẫn là chặn khi
|
||
ngưỡng là 100% — cái 1% đó chính là yêu cầu sẽ lọt ra sản phẩm mà không ai kiểm chứng.
|
||
|
||
## Bẫy thường gặp
|
||
|
||
**Chỉ chạy chiều xuôi.** Bỏ qua toàn bộ scope creep. Chiều ngược mới trả lời được câu
|
||
*"cái này ai yêu cầu?"*.
|
||
|
||
**Coi ID xuất hiện trong tài liệu là đã được phủ.** `SRS` nhắc `BR-021` không có nghĩa là
|
||
`BR-021` đã được hiện thực hoá — phải xem nó được áp vào field/AC nào. Đếm số lần xuất hiện
|
||
là phép đo sai.
|
||
|
||
**Bỏ qua tham chiếu gãy vì "chắc là do đánh nhầm số".** Tham chiếu gãy nghĩa là dev đọc
|
||
spec, thấy "theo BR-021", đi tìm không ra, rồi **tự quyết**. Đó là cách một business rule
|
||
bốc hơi khỏi sản phẩm.
|
||
|
||
**Tự sửa tài liệu khi phát hiện lỗ hổng.** Vi phạm nguyên tắc riêng của skill này. Báo cáo
|
||
và chỉ đúng skill để sửa; tự sửa sẽ che mất vấn đề, và lần sau nó lại xuất hiện.
|
||
|
||
**Làm tròn coverage lên.** 99% vẫn là chặn. Cái 1% đó là một yêu cầu thật, của một người thật.
|
||
|
||
**Bỏ phép kiểm vì profile rồi báo 100%.** `RIGOR = light` bỏ bớt phép kiểm là hợp lệ; **không
|
||
ghi ra là đã bỏ** thì con số 100% trở thành nói dối. Luôn in danh sách phép kiểm đã bỏ.
|
||
|
||
**Chỉ chạy trước gate.** Chạy sau mỗi giai đoạn thì lỗ hổng được phát hiện lúc còn rẻ. Chạy
|
||
lần đầu vào hôm trước ngày họp duyệt thì phát hiện cũng chỉ để hoãn họp.
|