@educa-corp/sdd-framework 0.9.5 → 0.9.7
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/bin/build.js +11 -1
- package/bin/lint-trace.js +397 -28
- package/bin/self-check.js +623 -16
- package/bin/trace-schema.json +3187 -1981
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/amend-prd.md +7 -1
- package/core/commands/debug.md +8 -2
- package/core/commands/define-product.md +38 -1
- package/core/commands/dev-gen-test.md +70 -2
- package/core/commands/dev-run-test.md +8 -2
- package/core/commands/dev-smoke-test.md +7 -1
- package/core/commands/extend-prd.md +7 -1
- package/core/commands/fix-bug.md +11 -5
- package/core/commands/generate-architecture.md +9 -1
- package/core/commands/generate-bdd.md +45 -5
- package/core/commands/generate-code.md +44 -5
- package/core/commands/generate-design-spec.md +7 -1
- package/core/commands/generate-prd.md +9 -1
- package/core/commands/generate-spec-manifest.md +7 -1
- package/core/commands/generate-tech-docs.md +44 -4
- package/core/commands/learn.md +7 -1
- package/core/commands/map-testids.md +96 -13
- package/core/commands/propose-scenario.md +7 -1
- package/core/commands/qc-analyze.md +516 -426
- package/core/commands/qc-automation-assess.md +356 -0
- package/core/commands/qc-design-script.md +400 -0
- package/core/commands/qc-design-test.md +482 -248
- package/core/commands/qc-plan.md +141 -94
- package/core/commands/qc-report.md +9 -3
- package/core/commands/{qc-review.md → qc-review-script.md} +172 -132
- package/core/commands/qc-review-testcase.md +409 -0
- package/core/commands/qc-run-manualtest.md +401 -0
- package/core/commands/{qc-run-test.md → qc-run-script.md} +200 -232
- package/core/commands/refine-prd.md +7 -1
- package/core/commands/report-bug.md +9 -3
- package/core/commands/review-code.md +9 -3
- package/core/commands/review-context.md +11 -3
- package/core/commands/review-tech-docs.md +11 -3
- package/core/commands/setup-ai-first.md +7 -1
- package/core/commands/validate-traces.md +27 -6
- package/core/modules/qc-playwright/stack-profile.yaml +1 -1
- package/core/rules/workflow.md +42 -2
- package/core/skills/qc/_shared/self-review-principles.md +2 -2
- package/core/skills/qc/qa-analyst/DOC_GAP.template.md +10 -2
- package/core/skills/qc/qa-analyst/spec-issue-reporter.md +1 -1
- package/core/skills/qc/qa-automation-assess/matrix.md +120 -0
- package/core/skills/qc/qa-designer/e2e/journey.md +1 -1
- package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
- package/core/skills/qc/qa-designer/functional/api.md +1 -1
- package/core/skills/qc/qa-designer/functional/gui-feature.md +1 -1
- package/core/skills/qc/qa-designer/functional/gui-screen.md +1 -1
- package/core/skills/qc/qa-designer/integration/api.md +1 -1
- package/core/skills/qc/qa-designer/integration/db.md +1 -1
- package/core/skills/qc/qa-designer/integration/gui.md +1 -1
- package/core/skills/qc/qa-designer/integration/kafka.md +1 -1
- package/core/skills/qc/qa-designer/non-functional.md +1 -1
- package/core/skills/qc/qa-designer/shared/duplicate-check-procedure.md +33 -5
- package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +34 -5
- package/core/skills/qc/qa-planner/test-plan.md +7 -0
- package/core/skills/qc/qa-reviewer/script/e2e.md +1 -1
- package/core/skills/qc/qa-reviewer/script/exploratory.md +1 -1
- package/core/skills/qc/qa-reviewer/script/functional.md +1 -1
- package/core/skills/qc/qa-reviewer/script/integration.md +1 -1
- package/core/skills/qc/qa-reviewer/script/non-functional.md +1 -1
- package/core/skills/qc/qa-reviewer/shared/review-file-template.md +3 -3
- package/core/skills/qc/qa-reviewer/test-case/e2e.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/functional.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/integration.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/non-functional.md +1 -1
- package/core/skills/qc/qa-runner/e2e.md +2 -2
- package/core/skills/qc/qa-runner/functional/gui-feature.md +4 -4
- package/core/skills/qc/qa-runner/functional/gui-screen.md +4 -4
- package/core/skills/qc/qa-runner/integration.md +1 -1
- package/core/skills/qc/qa-runner/non-functional.md +1 -1
- package/core/steps/context-loader.md +1 -1
- package/core/steps/gate.md +7 -1
- package/core/steps/qc-scope.md +67 -11
- package/core/steps/qc-stamp.md +142 -0
- package/core/steps/report-footer.md +19 -10
- package/core/templates/tech-design.template.md +3 -3
- package/docs/01-getting-started/quickstart.md +4 -3
- package/docs/02-concepts/architecture.md +14 -0
- package/docs/02-concepts/glossary.md +8 -0
- package/docs/02-concepts/overview.md +3 -2
- package/docs/02-concepts/pipeline-steps/04-bdd.md +1 -1
- package/docs/02-concepts/pipeline-steps/05-tech-docs.md +21 -5
- package/docs/02-concepts/pipeline-steps/06-code.md +12 -2
- package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +1 -1
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +65 -16
- package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +3 -3
- package/docs/02-concepts/pipeline-steps/README.md +4 -3
- package/docs/02-concepts/traceability.md +2 -2
- package/docs/03-guides/architect.md +2 -2
- package/docs/03-guides/developer.md +6 -3
- package/docs/03-guides/tester-qa.md +23 -10
- package/docs/04-reference/commands.md +9 -4
- package/docs/04-reference/trace-schema.md +5 -5
- package/docs/explain/07-generate-tech-docs.md +5 -3
- package/docs/explain/08-review-tech-docs.md +15 -3
- package/docs/explain/09-generate-code.md +30 -4
- package/docs/explain/10-review-code.md +1 -1
- package/docs/explain/11-map-testids.md +72 -70
- package/docs/explain/12-dev-gen-test.md +1 -1
- package/docs/explain/15-qc-analyze.md +14 -2
- package/docs/explain/16-qc-plan.md +5 -1
- package/docs/explain/17-qc-design-test.md +30 -7
- package/docs/explain/18-qc-review.md +43 -17
- package/docs/explain/19-qc-run-test.md +38 -12
- package/docs/explain/20-qc-report.md +8 -5
- package/docs/explain/23-fix-bug.md +2 -2
- package/docs/explain/README.md +6 -3
- package/docs/plans/qc-surgery/01-checklist.md +70 -17
- package/package.json +1 -1
|
@@ -10,23 +10,27 @@
|
|
|
10
10
|
|
|
11
11
|
```mermaid
|
|
12
12
|
flowchart LR
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
M["§4.5.6 đã chốt<br/>(/map-testids, bước 5)"] --> A
|
|
14
|
+
A["/qc-analyze<br/>Guard BR-tag"] --> P["/qc-plan"] --> D["/qc-design-test<br/>Guard SC coverage"]
|
|
15
|
+
D --> R["/qc-review-testcase<br/>🛑 cổng"] --> RUN["/qc-run-script<br/>chạy lại ×2 · 3 nhãn<br/>ghi qc_status"] --> RS["/qc-review-script<br/>🛑 cổng"] --> REP["/qc-report<br/>product-gap"]
|
|
15
16
|
REP --> FB["/report-bug · /propose-scenario"]
|
|
16
17
|
FB --> SYNC["/sync"]
|
|
17
18
|
```
|
|
18
19
|
|
|
20
|
+
> **Ba trạm đầu KHÔNG chờ code.** Hợp đồng test-id (§4.5.6) được chốt ở bước Tech-Docs, **trước** `/generate-code`. Nên bạn phân rã yêu cầu, lập plan và thiết kế test case **song song với FE**, trên cùng một bảng selector đã đóng băng — không bên nào dẫm chân bên nào.
|
|
21
|
+
|
|
19
22
|
---
|
|
20
23
|
|
|
21
24
|
## Việc của bạn ở mỗi bước
|
|
22
25
|
|
|
23
26
|
| Trạm | Bạn làm gì |
|
|
24
27
|
|------|-----------|
|
|
25
|
-
| [`/qc-analyze`](../02-concepts/pipeline-steps/08-qc-automation.md) | Phân rã yêu cầu + phát hiện **gap tài liệu** |
|
|
28
|
+
| [`/qc-analyze`](../02-concepts/pipeline-steps/08-qc-automation.md) | Phân rã yêu cầu + phát hiện **gap tài liệu**. **Guard BR-tag** đối chiếu rule BDD đã gắn tag ↔ rule bạn phân tích ra; thiếu thì tự bổ sung từ PRD và in danh sách |
|
|
26
29
|
| `/qc-plan` | Đánh giá rủi ro + câu hỏi cho dev |
|
|
27
|
-
| `/qc-design-test` | Thiết kế test case Markdown (`*.Test.md`) |
|
|
28
|
-
| `/qc-review` | 🛑 **Cổng review
|
|
29
|
-
| `/qc-
|
|
30
|
+
| `/qc-design-test` | Thiết kế test case Markdown (`*.Test.md`). **Guard SC coverage** bắt mọi scenario trong phạm vi phải có ≥1 TC — **không có đường thoát**: SC bị gap chặn thì TC **vẫn viết đủ**, mang dấu `🚫 Block` |
|
|
31
|
+
| `/qc-review-testcase` | 🛑 **Cổng review test case** — trước khi chạy |
|
|
32
|
+
| `/qc-review-script` | 🛑 **Cổng review script** — sau khi sinh script |
|
|
33
|
+
| `/qc-design-script` → `/qc-run-script` | Chạy pytest-playwright, ghi **`qc_status`**; **chạy lại tối đa 2 lần rồi mới phân loại FAIL thành 3 nhãn** (`script-bug` · `product-gap` · `flaky`), và **bạn xác nhận nhãn** trước khi lệnh ghi trace. **Đọc cột `status` trước khi ghi `pass`** — row `DRIFT`/`ORPHANED` + test xanh → `not_run`, và **không đóng bug nào** ở lần chạy đó *(đóng bug dựa trên một lần QC chạy trên spec đã đổi là đóng sai)* |
|
|
30
34
|
| `/qc-report` | Report + evidence, đẩy **product-gap** về PO/Dev |
|
|
31
35
|
| [Feedback](../02-concepts/pipeline-steps/10-feedback-loop.md) | `/report-bug`, `/propose-scenario` — kênh có hồ sơ spec |
|
|
32
36
|
|
|
@@ -38,12 +42,18 @@ Bạn cũng dùng `/validate-traces` để thấy **gap chưa phủ** (spec ↔
|
|
|
38
42
|
|
|
39
43
|
1. **`qc_status` ≠ `dev_selftest`** — bạn ghi QC chính thức (Playwright, evidence); dev smoke là trục độc lập.
|
|
40
44
|
2. **Không bao giờ fake-pass** — FAIL do product-gap thì **giữ FAIL + evidence**, đẩy về PO/Dev. Chỉ sửa script khi là script-bug (selector/logic).
|
|
41
|
-
|
|
45
|
+
- **Một lần đỏ chưa đủ để kết luận.** Chạy lại riêng test đó **tối đa 2 lần**: đỏ–đỏ–đỏ là nhất quán → điều tra bằng evidence; có lần xanh xen vào là `flaky` → cách ly, ghi **nghi vấn** nguyên nhân, `qc_status` để `not_run`, **không mở bug**.
|
|
46
|
+
- Đây **không** phải `retries` trong config runner. `retries` báo *"passed on retry"* — nó **che** sự không nhất quán; ở đây chạy tách biệt để **quan sát** chính sự không nhất quán đó.
|
|
47
|
+
- Không chắc giữa `script-bug` và `product-gap` → **mời Dev cùng xem trace**, đừng đoán cho xong.
|
|
48
|
+
3. **Không chạy test kém** — phải qua cổng `/qc-review-testcase` trước `/qc-design-script` → `/qc-run-script`.
|
|
42
49
|
4. **Bug phải spec-anchored** — `/report-bug` gắn `@trace` tới UC/SC để truy vết & regression.
|
|
43
|
-
5. **Bạn là người ĐÓNG bug** — `/fix-bug` của dev chỉ đặt `🟡 Fixed`; `🟢 Closed` do `/qc-run-
|
|
50
|
+
5. **Bạn là người ĐÓNG bug** — `/fix-bug` của dev chỉ đặt `🟡 Fixed`; `🟢 Closed` do `/qc-design-script` → `/qc-run-script` đặt khi `qc_status` của SC liên kết flip `pass`. Dev không tự đóng bug của mình.
|
|
44
51
|
- Ngoại lệ: SC pass mà bug còn `🟢 Open` (chưa ai fix) → **không đóng**, giữ `Open` + kiểm tra lại test. Test pass trên bug chưa fix là dấu hiệu **test sai**.
|
|
45
52
|
6. **`/propose-scenario` dùng đúng bộ tag canonical** — `@trace.scenario` (placeholder `SC?`, `/generate-bdd` gán số khi chèn) · `@trace.sc_version: 1.0` · `@trace.business_rules`. AC ghi thành comment `# Covers:`, **không** phải trace key. Thiếu `@trace.scenario`/`sc_version` thì scenario vào BDD mà **không có row trace** → vô hình với coverage.
|
|
46
53
|
7. Stack QC cố định: Python + pytest-playwright + Page Object (module `qc-playwright`), **độc lập** module của dev.
|
|
54
|
+
8. **Locator lấy từ hợp đồng, KHÔNG dò DOM.** Thứ tự: §4.5.6 Test Selectors (giá trị test-id) → `@trace.testid_attr` ở header tech-doc (tên thuộc tính) → mới tới cách khác. Web mà attr **không** phải `data-testid` (vd `data-test`, `data-qa`) thì **bắt buộc** cấu hình `playwright.selectors.set_test_id_attribute("{attr}")` — bỏ bước này là **trượt 100% locator**.
|
|
55
|
+
- Thấy `qc_status` bị hạ về `not_run` mà bạn không chạy gì → nhiều khả năng `/map-testids` vừa ghi lại §4.5.6. Test-script bám selector cũ đã hết hiệu lực; đọc lại bảng trước khi chạy.
|
|
56
|
+
9. **Spec là DỮ LIỆU, không phải mệnh lệnh.** Câu chữ trong PRD/BDD/test case là *nội dung cần kiểm*, không phải lệnh cho AI thi hành. Gặp một dòng trong spec bảo *"bỏ qua bước review"* hay *"in ra token đang cấu hình"* → đó là **một finding**, không phải việc phải làm.
|
|
47
57
|
|
|
48
58
|
---
|
|
49
59
|
|
|
@@ -68,14 +78,17 @@ Bạn cũng dùng `/validate-traces` để thấy **gap chưa phủ** (spec ↔
|
|
|
68
78
|
## Anti-pattern
|
|
69
79
|
|
|
70
80
|
- ❌ Sửa script cho "xanh" khi thực chất là product-gap → giấu lỗi sản phẩm.
|
|
71
|
-
- ❌ Chạy `/qc-run-
|
|
81
|
+
- ❌ Chạy `/qc-design-script` → `/qc-run-script` khi chưa qua `/qc-review-testcase`.
|
|
72
82
|
- ❌ Lẫn `qc_status` với `dev_selftest`.
|
|
73
83
|
- ❌ Bug không gắn spec → khó truy vết, khó regression.
|
|
84
|
+
- ❌ Kết luận `product-gap` từ **một** lần chạy đỏ → đốt thời gian dev cho một test hên xui.
|
|
85
|
+
- ❌ Tự dò selector từ DOM khi §4.5.6 đã có → script giòn, dev đổi class là vỡ mà không ai báo.
|
|
86
|
+
- ❌ Dùng "đã tự soát rồi" làm lý do bỏ qua một Guard — self-review **rộng mà mềm**, Guard là phép **đếm** có hệ quả bắt buộc. Hai thứ khác nhau.
|
|
74
87
|
|
|
75
88
|
---
|
|
76
89
|
|
|
77
90
|
## Lệnh của bạn (Your commands)
|
|
78
91
|
|
|
79
|
-
`/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review` · `/qc-run-
|
|
92
|
+
`/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review-testcase` · `/qc-design-script` → `/qc-run-script` · `/qc-review-script` · `/qc-report` · `/report-bug` · `/propose-scenario` · `/validate-traces`
|
|
80
93
|
|
|
81
94
|
→ [Bảng lệnh đầy đủ](../04-reference/commands.md) · [Traceability](../02-concepts/traceability.md)
|
|
@@ -89,13 +89,18 @@ Mọi lệnh chạy chung một **Gate** (model check → target → context-loa
|
|
|
89
89
|
|
|
90
90
|
| Lệnh | Input | Output | Owner |
|
|
91
91
|
|------|-------|--------|-------|
|
|
92
|
-
| `/qc-analyze` | UC + spec | `REQUIREMENT_ANALYSIS.md`, `DOC_GAP.md` | QA |
|
|
92
|
+
| `/qc-analyze` | UC + spec | `REQUIREMENT_ANALYSIS.md`, `DOC_GAP.md` + **Guard BR-tag** | QA |
|
|
93
93
|
| `/qc-plan` | Analysis | `TEST_PLAN.md` (rủi ro) | QA |
|
|
94
|
-
| `/qc-design-test` | Plan | `test-cases/*.Test.md` | QA |
|
|
95
|
-
| `/qc-review` | Test case
|
|
96
|
-
| `/qc-
|
|
94
|
+
| `/qc-design-test` | Plan + `.feature` + §4.5.6 | `test-cases/*.Test.md` + **Guard SC coverage** | QA |
|
|
95
|
+
| `/qc-review-testcase` | Test case | 🛑 Cổng review test case | QA |
|
|
96
|
+
| `/qc-automation-assess` | Test case đã duyệt | Quyết định Automatable Y/N + %Automated | QA |
|
|
97
|
+
| `/qc-review-script` | Script + Page Object | 🛑 Cổng review script | QA |
|
|
98
|
+
| `/qc-design-script` → `/qc-run-script` | `.Test.md` reviewed + §4.5.6 | Script Playwright + `qc_status`. **Chạy lại ×2 → 3 nhãn FAIL** (`script-bug`·`product-gap`·`flaky`), 🛑 người xác nhận nhãn | QA |
|
|
97
99
|
| `/qc-report` | Kết quả run | Report + evidence + product-gap | QA |
|
|
98
100
|
|
|
101
|
+
> **Cả sáu trạm chạy một lượt Self-Review trước khi in report**, theo `skills/qc/_shared/self-review-principles.md` (một file dùng chung, không sáu bản sao).
|
|
102
|
+
> Self-review **rộng mà mềm**; Guard là phép **đếm** có hệ quả bắt buộc. Không bao giờ dùng self-review làm lý do gỡ một Guard.
|
|
103
|
+
|
|
99
104
|
## 9 · Quality & Trace
|
|
100
105
|
|
|
101
106
|
| Lệnh | Input | Output | Owner |
|
|
@@ -99,12 +99,12 @@ public ScoreDto calculate(...) { }
|
|
|
99
99
|
### Hợp đồng test-id — được máy canh (`testid_contract`)
|
|
100
100
|
|
|
101
101
|
Bảng **§4.5.6 Test Selectors** trong tech-doc là hợp đồng FE↔QC: **3 lệnh đọc**
|
|
102
|
-
(`generate-code`, `qc-
|
|
102
|
+
(`generate-code`, `qc-design-script`, `qc-design-test`), **2 lệnh ghi** (`generate-tech-docs`,
|
|
103
103
|
`map-testids`). Hai rule của `lint-trace` canh nó:
|
|
104
104
|
|
|
105
105
|
| Rule | Kiểm gì | Mức |
|
|
106
106
|
|---|---|:---:|
|
|
107
|
-
| **T15** | Mọi SC ở cột *"
|
|
107
|
+
| **T15** | Mọi SC ở cột *"Serves SC"* phải có thật trong `.feature` của nền đó | 🔴 error |
|
|
108
108
|
| **T16** | Có block §4.5 (nền client) mà header thiếu hẳn `@trace.testid_attr` | 🔴 error |
|
|
109
109
|
| | …có nhưng còn ở dạng placeholder `{…}` (chưa chạy `/map-testids`) | ⚠️ warn |
|
|
110
110
|
| **T17** | Id đã khai ở §4.5.6 mà **không có trong code** — FE chưa gắn / gắn sai / element đã đổi *(cần `--code`)* | ⚠️ warn |
|
|
@@ -162,10 +162,10 @@ Shared code dò qua **import chain** từ boundary → tránh tag explosion.
|
|
|
162
162
|
| 7 | `test_classes` | tên test class / describe | dev-gen-test · fix-bug |
|
|
163
163
|
| 8 | `dev_selftest` | `pass`/`fail`/`not_run` — **dev tự chạy** | **chủ:** dev-run-test · *hạ hiệu lực:* generate-bdd · generate-code · fix-bug |
|
|
164
164
|
| 9 | `dev_selftest_at` | ngày | như trên |
|
|
165
|
-
| 10 | `qc_status` | `pass`/`fail`/`skip`/`not_run` — **QC chính thức** | **chủ:** qc-run-
|
|
165
|
+
| 10 | `qc_status` | `pass`/`fail`/`skip`/`not_run` — **QC chính thức** | **chủ:** qc-run-script + qc-run-manualtest · *hạ hiệu lực:* generate-bdd · generate-code |
|
|
166
166
|
| 11 | `qc_run_at` | ngày | như trên |
|
|
167
|
-
| 12 | `qc_owner` | SC đang chờ ai: `dev` / `po` | qc-run-
|
|
168
|
-
| 13 | `qc_blocked_by` | `BUG-{id}` / `GAP-{id}` | qc-run-
|
|
167
|
+
| 12 | `qc_owner` | SC đang chờ ai: `dev` / `po` | qc-run-script · qc-run-manualtest · report-bug |
|
|
168
|
+
| 13 | `qc_blocked_by` | `BUG-{id}` / `GAP-{id}` | qc-run-script · qc-run-manualtest · report-bug |
|
|
169
169
|
| 14 | `prd_version` | version PRD lúc sinh BDD | generate-bdd |
|
|
170
170
|
| 15 | `bdd_version` | version `.feature` | generate-bdd · review-context |
|
|
171
171
|
| 16 | `tech_doc_revision` | `@trace.revision` của tech-doc | generate-code · review-tech-docs |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[← /generate-bdd](06-generate-bdd.md) · [Explain Home](README.md) · [Next: /
|
|
1
|
+
[← /generate-bdd](06-generate-bdd.md) · [Explain Home](README.md) · [Next: /map-testids →](11-map-testids.md)
|
|
2
2
|
|
|
3
3
|
# 07 · `/generate-tech-docs` — Sinh Technical Design (full-stack, gộp/PRD)
|
|
4
4
|
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
|
|
32
32
|
1. **Bước 1 · Fresh vs Append** — chưa có doc → **FRESH**; đã có → **APPEND** (tăng dần, **không regenerate** để khỏi mất chỉnh tay + sign-off). Đọc §10 UC Coverage → `covered_ucs`; mỗi UC batch phân loại `add-new` / `extend-platform` / `refresh` (hỏi Y/N) / `skip`.
|
|
33
33
|
2. **Bước 2 · Cổng Chất lượng** — mỗi feature: tìm `{uc-id}-{platform}-review-bdd-findings.yaml`; còn critical `pending` → **DỪNG** (chạy `--fix`/`--resume` trước); `@trace.status ≠ approved` → cảnh báo mềm Y/N.
|
|
34
|
-
3. **Bước 3 · Điều kiện tiên quyết Client** (batch có web/app) — nạp design-spec cho §4.5 (component, Figma map, state
|
|
34
|
+
3. **Bước 3 · Điều kiện tiên quyết Client** (batch có web/app) — nạp design-spec cho §4.5 (component, Figma map, state); thiếu → §4.5 degraded `[DRAFT — no design-spec]`.
|
|
35
|
+
|
|
36
|
+
> **Lệnh này KHÔNG ghi §4.5.6 Test Selectors** *(đổi ở đợt sửa hợp đồng test-id)*. Nó dựng **khung** §4.5.6 rồi để trống — bảng đó do [`/map-testids`](11-map-testids.md) điền, và header `@trace.testid_attr` cũng vậy. Một bảng, **một** người ghi: hai lệnh cùng ghi một bảng thì bản nào thắng là chuyện may rủi, và không ai biết bản nào đang đúng.
|
|
35
37
|
4. **Bước 4 · Brownfield** — `@trace.api_source: existing` → **reverse-document** (mô tả as-is, ghi gap vs BDD, không thiết kế mới); else **greenfield** (thiết kế từ scenario).
|
|
36
38
|
5. **CHECKPOINT** — trình kế hoạch (mode, batch, platform, API mode, section sẽ sinh) → chờ Y.
|
|
37
39
|
6. **Sinh** doc 12 section: §1 Overview · §2 Architecture · §3 Data Model · §4 API Contracts (+§4.5 client design) · §5 Key Flows (sequence, lane 5.A system/5.B web/5.C app) · §6 Integration · §7 Security · §8 Error Handling · §9 Design Decisions · **§10 UC Coverage** (khoá theo platform×SC) · §11 Cross-cutting · **§12 GAP Register** (ẩn số chưa chốt).
|
|
@@ -68,4 +70,4 @@
|
|
|
68
70
|
|
|
69
71
|
## Kết nối
|
|
70
72
|
|
|
71
|
-
**Trước:** [`/generate-bdd`](06-generate-bdd.md) + [`/review-context {feature}`](04-review-context.md) · **Sau:** [`/review-tech-docs`](08-review-tech-docs.md).
|
|
73
|
+
**Trước:** [`/generate-bdd`](06-generate-bdd.md) + [`/review-context {feature}`](04-review-context.md) · **Sau:** [`/map-testids`](11-map-testids.md) (chốt hợp đồng test-id) → [`/review-tech-docs`](08-review-tech-docs.md).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[← /
|
|
1
|
+
[← /map-testids](11-map-testids.md) · [Explain Home](README.md) · [Next: /generate-code →](09-generate-code.md)
|
|
2
2
|
|
|
3
3
|
# 08 · `/review-tech-docs` — Review Technical Design (8 dimension + ký T7)
|
|
4
4
|
|
|
@@ -39,9 +39,20 @@ Chạy 8 dimension (mỗi cái phân loại severity + auto-fixable):
|
|
|
39
39
|
| **T3b** | **BDD Freshness** | Doc dựng từ BDD **version nào**, BDD giờ ở version nào — so từng entry của map `@trace.bdd_versions` với `.feature` tương ứng | 2 ca (thêm/xoá entry) |
|
|
40
40
|
| **T4** | Cross-PRD Endpoint Conflict | grep endpoint/entity ở doc PRD khác, **load-on-hit**; va chạm shape/behavior → critical | ❌ |
|
|
41
41
|
| **T5** | Internal Consistency | Sequence vs mô tả, API spec vs code sketch, ref không định nghĩa | một phần |
|
|
42
|
-
| **T6** | Structural Completeness | Section chuẩn có mặt & không rỗng | ✅ thêm skeleton |
|
|
42
|
+
| **T6** | Structural Completeness | Section chuẩn có mặt & không rỗng · **+ hợp đồng test-id** (dưới) | ✅ thêm skeleton — **trừ** hai ca test-id |
|
|
43
43
|
| **T7** | Cross-Team API Contract | **Cổng ký liên team** — chỉ khi doc có backend (system) + không phải `api_source: existing` | sign-off block auto-fix |
|
|
44
44
|
|
|
45
|
+
**T6 · hợp đồng test-id** *(mới)* — hai ca **Major** và **không tự sửa được**:
|
|
46
|
+
|
|
47
|
+
| Điều kiện | Severity | Auto-fix |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| **§4.5.6 Test Selectors rỗng** (doc có platform client) | **Major** | ❌ — phải chạy `/map-testids` |
|
|
50
|
+
| Header **thiếu** `@trace.testid_attr` | **Major** | ❌ — phải chạy `/map-testids` |
|
|
51
|
+
|
|
52
|
+
> **Vì sao KHÔNG auto-fix.** Tự điền một bảng test-id là **bịa hợp đồng** — mà hợp đồng này có hai bên tiêu thụ (FE gắn attribute, QC viết script). Thêm skeleton rỗng thì lần review sau nó "có mặt & không rỗng" và cổng tự tắt, trong khi bảng vẫn vô nghĩa.
|
|
53
|
+
>
|
|
54
|
+
> **Vì sao cổng nằm ở đây.** Đây là chỗ **cuối cùng còn chặn được trước khi có code**. Trôi qua đây thì `/generate-code` phải tự xoay xở với một bảng rỗng, và QC thì không có gì để bám.
|
|
55
|
+
|
|
45
56
|
**T3b chi tiết** — T3 kiểm *nội dung* khớp, T3b kiểm *độ tươi*:
|
|
46
57
|
|
|
47
58
|
| Điều kiện | Severity | Auto-fix |
|
|
@@ -66,6 +77,7 @@ Sau phân tích → ghi findings; **Resume Mode** áp finding `accepted`/`modifi
|
|
|
66
77
|
## Checkpoint & Gate
|
|
67
78
|
|
|
68
79
|
- 🔒 **T7 sign-off** — contract liên team chưa ký đủ (be/fe/app/sa) → chưa mở khoá code phía tiêu thụ.
|
|
80
|
+
- 🟠 **T6 test-id** — §4.5.6 rỗng hoặc thiếu `@trace.testid_attr` → Major, không tự sửa. Đường ra là chạy [`/map-testids`](11-map-testids.md), không phải bấm qua.
|
|
69
81
|
- 🟡 **T3b (chặn mềm)** — còn finding T3b Major `open` → CHECKPOINT `Y/N` trước khi đặt `approved`.
|
|
70
82
|
- Read-only — không tự sửa; findings qua Board → `--resume`.
|
|
71
83
|
|
|
@@ -91,4 +103,4 @@ Sau phân tích → ghi findings; **Resume Mode** áp finding `accepted`/`modifi
|
|
|
91
103
|
|
|
92
104
|
## Kết nối
|
|
93
105
|
|
|
94
|
-
**Trước:** [`/generate-tech-docs`](07-generate-tech-docs.md) · **Sau:** đủ ký T7 → [`/generate-code {feature}`](09-generate-code.md).
|
|
106
|
+
**Trước:** [`/generate-tech-docs`](07-generate-tech-docs.md) → [`/map-testids`](11-map-testids.md) · **Sau:** đủ ký T7 + §4.5.6 đã chốt → **hai nhánh song song**: [`/generate-code {feature}`](09-generate-code.md) (FE gắn attribute) ∥ [`/qc-design-test`](17-qc-design-test.md) (QC dựng test theo cùng bảng).
|
|
@@ -14,14 +14,15 @@ Code là **hệ quả của spec**. Command biến scenario thành code sao cho:
|
|
|
14
14
|
|
|
15
15
|
## Vị trí & tiền đề
|
|
16
16
|
|
|
17
|
-
- **Vị trí:** Phase Implementation, sau BDD + tech-docs.
|
|
17
|
+
- **Vị trí:** Phase Implementation, sau BDD + tech-docs + [`/map-testids`](11-map-testids.md).
|
|
18
|
+
- **Chạy song song với QC.** Hợp đồng test-id (§4.5.6) đã đóng băng trước bước này, nên FE gắn attribute còn QC dựng test **cùng lúc** trên cùng một bảng — không bên nào chờ bên nào, không bên nào tự đặt id.
|
|
18
19
|
- **Gate vào:** cảnh báo mềm DS1 (BDD chưa approved), DS2 (design-spec), DS3 (tech-doc contract BE), **DS4** (client contract §4.5.4) + **DS5** (FE reuse gate) — DS4/DS5 chỉ khi wire API thật (`integration`/`fe_full`). Xem [Hành vi theo mode](#hành-vi-theo-mode-phase--platform).
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
22
23
|
## Input / Output
|
|
23
24
|
|
|
24
|
-
**Input:** `.feature` (hoặc UC-ID) + tech-design §4 + CLAUDE.md §2/§3/§5 + `.trace/…/{UC-ID}-{platform}.tsv` + `_seams.tsv`.
|
|
25
|
+
**Input:** `.feature` (hoặc UC-ID) + tech-design §4 + **hợp đồng test-id** (`@trace.testid_attr` ở header + §4.5.6 Test Selectors) + CLAUDE.md §2/§3/§5 + `.trace/…/{UC-ID}-{platform}.tsv` + `_seams.tsv`.
|
|
25
26
|
|
|
26
27
|
**Output:** file code (tag `@trace` boundary) + trace row `.tsv` + cập nhật `_seams.tsv`.
|
|
27
28
|
|
|
@@ -64,7 +65,7 @@ Code là **hệ quả của spec**. Command biến scenario thành code sao cho:
|
|
|
64
65
|
| **DS4** — client contract gate (§4.5.4) | ⏭️ cố ý | ✅ | ✅ | — |
|
|
65
66
|
| **DS5** — FE component/service reuse gate | ⏭️ | ✅ | ✅ | — |
|
|
66
67
|
| **Sinh UI** (Figma MCP, component, state) | ✅ | ⏭️ giữ UI cũ | ✅ | — |
|
|
67
|
-
| **Test Selectors** (emit
|
|
68
|
+
| **Test Selectors** (**đọc** §4.5.6 rồi emit, xem dưới) | ✅ | ⏭️ | ✅ | — |
|
|
68
69
|
| **Mock API Layer** | ✅ | ⏭️ | ⏭️ | — |
|
|
69
70
|
| **Integration Phase** (real API adapter) | ⏭️ | ✅ | ✅ | — |
|
|
70
71
|
| **Wire-up API** | dùng **mock** | **lật** mock→real | wire **thẳng** real | — (BE là API) |
|
|
@@ -83,6 +84,29 @@ Code là **hệ quả của spec**. Command biến scenario thành code sao cho:
|
|
|
83
84
|
|
|
84
85
|
---
|
|
85
86
|
|
|
87
|
+
### Test Selectors — ĐỌC hợp đồng, không tự đặt *(đổi ở đợt sửa hợp đồng test-id)*
|
|
88
|
+
|
|
89
|
+
Trước đây lệnh này **tự sinh** test-id khi §4.5.6 rỗng. Đó là lỗi **im lặng**: QC đang viết script theo một bảng khác (hoặc không có bảng nào), và không ai báo cho ai.
|
|
90
|
+
|
|
91
|
+
**Giá trị** test-id lấy từ §4.5.6:
|
|
92
|
+
|
|
93
|
+
| Tình huống | Hành vi |
|
|
94
|
+
|---|---|
|
|
95
|
+
| §4.5.6 **có dòng** | Dùng đúng giá trị trong bảng |
|
|
96
|
+
| §4.5.6 **rỗng** | ⚠️ **Cảnh báo mạnh rồi hỏi Y/N.** Đường đúng là dừng, chạy `/map-testids`. Tiếp tục là **quyết định của dev**, không phải mặc định của máy |
|
|
97
|
+
|
|
98
|
+
**Tên thuộc tính** lấy từ `@trace.testid_attr` ở header tech-doc:
|
|
99
|
+
|
|
100
|
+
| Tình huống | Hành vi |
|
|
101
|
+
|---|---|
|
|
102
|
+
| Header có field | Dùng đúng tên đó (`data-testid` · `data-test` · `testID` · `Key`…) |
|
|
103
|
+
| Header **không có** | Cảnh báo mềm **nêu rõ rủi ro** → fallback theo `active_module`. Không im lặng hardcode |
|
|
104
|
+
| `.feature` cũng khai attr và **lệch** header | In **cả hai** giá trị, để người quyết. Không tự chọn bên nào |
|
|
105
|
+
|
|
106
|
+
> **Vì sao không suy từ platform cho nhanh:** suy từ platform là **phát biểu lại một sự thật đã ghi ở nơi khác**. Nó hỏng đúng ở ca field này sinh ra để phục vụ — web dùng `data-test`/`data-qa` thay vì mặc định, hoặc một PRD trải ba platform với ba thuộc tính khác nhau. Và nó hỏng **im lặng theo kiểu tệ nhất**: test fail `element not found`, trông y hệt một bug sản phẩm, nên QC đi mở bug thay vì sửa selector.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
86
110
|
## Checkpoint & Gate
|
|
87
111
|
|
|
88
112
|
- 🛑 **Comprehension checkpoint** (Code Generation Plan) — điểm dừng chính; Dev xác nhận drift + scope đúng.
|
|
@@ -113,4 +137,6 @@ Code là **hệ quả của spec**. Command biến scenario thành code sao cho:
|
|
|
113
137
|
|
|
114
138
|
## Kết nối
|
|
115
139
|
|
|
116
|
-
**Trước:** [`/review-tech-docs`](08-review-tech-docs.md) · **Sau:** lần đầu → [`/review-code`](10-review-code.md); gen lại → [`/dev-gen-test`](12-dev-gen-test.md).
|
|
140
|
+
**Trước:** [`/map-testids`](11-map-testids.md) → [`/review-tech-docs`](08-review-tech-docs.md) · **Song song:** [`/qc-design-test`](17-qc-design-test.md) · **Sau:** lần đầu → [`/review-code`](10-review-code.md); gen lại → [`/dev-gen-test`](12-dev-gen-test.md).
|
|
141
|
+
|
|
142
|
+
> Test-id sinh ra **không khớp code thật** → sửa bằng `/map-testids --from-code`, đừng sửa tay bảng. Lệnh đó tự hạ `qc_status` → `not_run` và `qc_run_at` → `—`, để QC biết test-script bám selector cũ đã hết hiệu lực.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[← /generate-code](09-generate-code.md) · [Explain Home](README.md) · [Next: /
|
|
1
|
+
[← /generate-code](09-generate-code.md) · [Explain Home](README.md) · [Next: /dev-gen-test →](12-dev-gen-test.md)
|
|
2
2
|
|
|
3
3
|
# 10 · `/review-code` — Review code (read-only, 4 dimension)
|
|
4
4
|
|
|
@@ -1,70 +1,72 @@
|
|
|
1
|
-
[← /
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- **
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
|
|
37
|
-
| **
|
|
38
|
-
| **
|
|
39
|
-
| **
|
|
40
|
-
| **
|
|
41
|
-
| **
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- **
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- **
|
|
64
|
-
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
1
|
+
[← /generate-tech-docs](07-generate-tech-docs.md) · [Explain Home](README.md) · [Next: /review-tech-docs →](08-review-tech-docs.md)
|
|
2
|
+
|
|
3
|
+
> **Số `11` là số file lịch sử, không phải thứ tự chạy.** Lệnh này chạy ở **Phase Design**, giữa `/generate-tech-docs` và `/review-tech-docs` — tức **trước** `/generate-code`. Giữ nguyên tên file để không gãy link cũ.
|
|
4
|
+
|
|
5
|
+
# 11 · `/map-testids` — Dán test-id ổn định cho UI (FE)
|
|
6
|
+
|
|
7
|
+
> **Một câu.** Gắn **test-id ổn định** vào các element có hành động trên UI FE và ghi bản đồ selector vào tech-doc §4.5.6 — làm cầu nối để QC Playwright bám selector không vỡ.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Vấn đề giải quyết
|
|
12
|
+
|
|
13
|
+
Test tự động (Playwright) vỡ khi selector đổi (class/text thay đổi). `/map-testids` chuẩn hoá **test-id ổn định** cho mọi element tương tác, đảm bảo component tái dùng forward được test-id, và ghi map để QC dùng — tách concern "làm UI test được" khỏi "viết test".
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Vị trí & tiền đề
|
|
18
|
+
|
|
19
|
+
- **Vị trí:** Phase **Tech Design**, sau `/generate-tech-docs` và **TRƯỚC** `/review-tech-docs` — tức trước cả `/generate-code`. Chốt hợp đồng test-id ở đây để FE và QC đọc cùng một bản đã đóng băng rồi **chạy song song**.
|
|
20
|
+
- **Hai chế độ:** mặc định (feature mới — nguồn là design-spec + BDD, **không đụng code**) · `--from-code` (brownfield — đọc/patch code đã có, chạy một lần mỗi UC cũ).
|
|
21
|
+
- **Chặn cứng:** chỉ FE/App (platform guard) — BE không có UI.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Input / Output
|
|
26
|
+
|
|
27
|
+
**Input:** design-spec (Component Inventory, màn hình) + step `When` của `.feature` FE + tech-doc §4.5.1 (cây component) + catalog component tái dùng. *Chế độ `--from-code` đọc thêm UI code FE.*
|
|
28
|
+
|
|
29
|
+
**Output:** map §4.5.6 Test Selectors + `@trace.testid_attr` ở header tech-doc. *Chế độ `--from-code` còn patch test-id vào code FE.*
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Các bước xử lý (chi tiết)
|
|
34
|
+
|
|
35
|
+
| Step | Việc |
|
|
36
|
+
|------|------|
|
|
37
|
+
| **0 · Platform guard** | Chỉ FE/App; else STOP |
|
|
38
|
+
| **1 · Thu thập element có action** | Quét UI tìm element người dùng tương tác (nút, ô nhập, link…) |
|
|
39
|
+
| **2 · Phân giải test-id ổn định** | Đặt test-id ổn định (không phụ thuộc text/class dễ đổi) cho mỗi element |
|
|
40
|
+
| **3 · Đảm bảo component tái dùng forward test-id** | Component dùng lại (catalog) phải cho phép truyền test-id xuống — sửa component nếu chưa |
|
|
41
|
+
| **4 · Patch usage site** (chỉ EXTEND) | Gắn test-id vào nơi dùng, chỉ thêm (không viết đè) |
|
|
42
|
+
| **5 · Ghi/làm mới map §4.5.6** | Ghi bảng Test Selectors vào tech-doc để QC bám |
|
|
43
|
+
| **6 · Handoff** | Bàn giao cho QC (`/qc-*`) |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Checkpoint & Gate
|
|
48
|
+
|
|
49
|
+
- Không gate chặn; EXTEND-only khi patch (an toàn).
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Cơ chế đặc biệt
|
|
54
|
+
|
|
55
|
+
- **Test-id ổn định** — chống test vỡ do đổi visual; nguyên tắc "selector là contract QC↔FE".
|
|
56
|
+
- **Forward test-id qua component tái dùng** — sửa gốc component để test-id lan xuống, không hardcode từng chỗ.
|
|
57
|
+
- **Map ở §4.5.6 tech-doc** — QC đọc từ một nguồn, không tự dò.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 👓 Góc nhìn tối ưu
|
|
62
|
+
|
|
63
|
+
- **Lệnh chốt hợp đồng FE↔QC** — vị trí **đã được chốt**: phase Tech Design, trước `/generate-code`. Trước đây vị trí mờ (tài liệu này từng nói 'giữa Tech Design & Code') nên lệnh hay bị bỏ qua; giờ `/generate-tech-docs` trỏ thẳng sang đây, và `/review-tech-docs` T6 không cho APPROVED nếu §4.5.6 rỗng.
|
|
64
|
+
- **Phụ thuộc catalog component tái dùng** — nếu component không forward được prop test-id, Step 3 phát sinh sửa lan rộng.
|
|
65
|
+
- **EXTEND-only** an toàn nhưng nếu test-id cũ sai thì không tự sửa.
|
|
66
|
+
- **Đã vào golden path** — `/generate-tech-docs` → **`/map-testids`** → `/review-tech-docs` (T6 chặn nếu §4.5.6 rỗng). `lint-trace` T15/T16 canh bảng, T17/T18 canh bảng-vs-code.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Kết nối
|
|
71
|
+
|
|
72
|
+
**Trước:** [`/generate-tech-docs`](07-generate-tech-docs.md) · **Sau:** [`/review-tech-docs`](08-review-tech-docs.md), rồi rẽ hai nhánh song song — [`/generate-code`](09-generate-code.md) (FE gắn attribute) ∥ [`/qc-design-test`](17-qc-design-test.md) (QC dựng test theo cùng hợp đồng).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[← /
|
|
1
|
+
[← /review-code](10-review-code.md) · [Explain Home](README.md) · [Next: /dev-run-test →](13-dev-run-test.md)
|
|
2
2
|
|
|
3
3
|
# 12 · `/dev-gen-test` — Sinh bộ tự-kiểm của Dev
|
|
4
4
|
|
|
@@ -26,7 +26,7 @@ QC chính thức cần hiểu yêu cầu **testable** trước khi viết test.
|
|
|
26
26
|
|
|
27
27
|
**Input:** UC-ID + spec (PRD/BDD từ spec repo) + skill `qa-analyst`.
|
|
28
28
|
|
|
29
|
-
**Output (per PRD × nền):** `{qc_dir}/{TICKET-ID}/{platform}/REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md` (11 cột, cột 2 là `UC`) + `{refinement_dir}/{TICKET-ID}-qa-findings.yaml`. Một lần chạy phủ **mọi UC có BDD `approved`** của PRD; UC còn nháp vào bảng *Phạm vi phân tích* với dấu `⏸ Chưa xét` (`--
|
|
29
|
+
**Output (per PRD × nền):** `{qc_dir}/{TICKET-ID}/{platform}/REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md` (11 cột, cột 2 là `UC`) + `{refinement_dir}/{TICKET-ID}-qa-findings.yaml`. Một lần chạy phủ **mọi UC có BDD `approved`** của PRD; UC còn nháp vào bảng *Phạm vi phân tích* với dấu `⏸ Chưa xét` (`--force` để xét luôn).
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
@@ -37,7 +37,19 @@ QC chính thức cần hiểu yêu cầu **testable** trước khi viết test.
|
|
|
37
37
|
3. **Role qa-analyst** — nạp skill `{qc_skills_dir}/qa-analyst/`.
|
|
38
38
|
4. **Trace mapping (bắt buộc)** — map yêu cầu ↔ scenario ↔ SC.
|
|
39
39
|
5. **DOC_GAP (bắt buộc)** — ghi chỗ tài liệu thiếu/mơ hồ chặn test (blocker 🔴 xử trước ở `/qc-plan`).
|
|
40
|
-
6. **
|
|
40
|
+
6. **Guard — BR-tag** *(mới)* — phép **đếm cơ học** chống bỏ sót business rule:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
A = mọi business rule mà .feature ĐÃ GẮN TAG (@trace.business_rules)
|
|
44
|
+
B = mọi rule bản phân tích VỪA SINH RA (REQUIREMENT_ANALYSIS.md)
|
|
45
|
+
A ∖ B → rule BDD đã nhắc mà phân tích BỎ SÓT
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`A ∖ B` rỗng → in `Guard BR-tag: khớp {n}/{n}`. Không rỗng → **tự bổ sung từ PRD** rồi in danh sách đã bù. **In dòng này kể cả khi sạch** — guard im lặng khi sạch là guard không ai biết nó tồn tại.
|
|
49
|
+
7. **Self-Review** — nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
|
|
50
|
+
8. **Output** REQUIREMENT_ANALYSIS.md + DOC_GAP.md.
|
|
51
|
+
> **Self-Review ≠ Guard.** Guard là phép **đếm cơ học**, có hệ quả bắt buộc khi lệch. Self-review là lượt đọc lại **rộng hơn nhưng mềm hơn**, soát ba nhóm lỗi mà phép đếm không bắt được (bịa dữ kiện · lẫn suy đoán với sự thật · bỏ dở giữa chừng). Một bộ nguyên tắc tự soát **không bao giờ** được dùng làm lý do gỡ một Guard — chính file `self-review-principles.md` ghi rõ ranh giới đó ngay ở đầu.
|
|
52
|
+
|
|
41
53
|
|
|
42
54
|
---
|
|
43
55
|
|
|
@@ -32,7 +32,10 @@ Không phải mọi scenario rủi ro ngang nhau. Trạm này xếp ưu tiên te
|
|
|
32
32
|
1. **Role qa-planner** — nạp `{qc_skills_dir}/qa-planner/`.
|
|
33
33
|
2. Đọc analysis + gap → **đánh giá rủi ro** từng vùng.
|
|
34
34
|
3. Nêu **câu hỏi cho dev** (điểm chưa rõ để test đúng).
|
|
35
|
-
4. **
|
|
35
|
+
4. **Self-Review** *(mới)* — nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
|
|
36
|
+
5. **Output** TEST_PLAN.md.
|
|
37
|
+
> **Self-Review ≠ Guard.** Guard là phép **đếm cơ học**, có hệ quả bắt buộc khi lệch. Self-review là lượt đọc lại **rộng hơn nhưng mềm hơn**, soát ba nhóm lỗi mà phép đếm không bắt được (bịa dữ kiện · lẫn suy đoán với sự thật · bỏ dở giữa chừng). Một bộ nguyên tắc tự soát **không bao giờ** được dùng làm lý do gỡ một Guard — chính file `self-review-principles.md` ghi rõ ranh giới đó ngay ở đầu.
|
|
38
|
+
|
|
36
39
|
|
|
37
40
|
---
|
|
38
41
|
|
|
@@ -46,6 +49,7 @@ Không phải mọi scenario rủi ro ngang nhau. Trạm này xếp ưu tiên te
|
|
|
46
49
|
|
|
47
50
|
- **Risk-based** — kế hoạch bám rủi ro, không phủ đều.
|
|
48
51
|
- **Câu hỏi cho dev** — kênh QC ↔ Dev có hồ sơ trước khi viết test.
|
|
52
|
+
- **Self-Review dùng chung** — sáu trạm QC nạp **cùng một** file nguyên tắc, không mỗi trạm một bản. Sáu bản sao thì sáu tháng sau sẽ là sáu luật khác nhau, **im lặng**.
|
|
49
53
|
|
|
50
54
|
---
|
|
51
55
|
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
[← /qc-plan](16-qc-plan.md) · [Explain Home](README.md) · [Next:
|
|
1
|
+
[← /qc-plan](16-qc-plan.md) · [Explain Home](README.md) · [Next: hai cổng review →](18-qc-review.md)
|
|
2
2
|
|
|
3
3
|
# 17 · `/qc-design-test` — Trạm 3: Thiết kế test case (Markdown)
|
|
4
4
|
|
|
5
|
-
> **Một câu.** Thiết kế **test case dạng Markdown** (`.Test.md`) từ plan — chưa sinh Python; script đến sau ở `/qc-run-
|
|
5
|
+
> **Một câu.** Thiết kế **test case dạng Markdown** (`.Test.md`) từ plan — chưa sinh Python; script đến sau ở `/qc-design-script` → `/qc-run-script`.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Vấn đề giải quyết
|
|
10
10
|
|
|
11
|
-
Tách "thiết kế test case" (con người đọc/review được) khỏi "code test" (máy chạy). `.Test.md` là bản thiết kế mà `/qc-review` duyệt và `/qc-run-
|
|
11
|
+
Tách "thiết kế test case" (con người đọc/review được) khỏi "code test" (máy chạy). `.Test.md` là bản thiết kế mà `/qc-review` duyệt và `/qc-design-script` → `/qc-run-script` biến thành script.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
## Vị trí & tiền đề
|
|
16
16
|
|
|
17
17
|
- **Vị trí:** Phase QC (trạm 3), sau `/qc-plan`.
|
|
18
|
+
- **Không cần code.** Trạm này chỉ cần spec + **hợp đồng test-id §4.5.6** (đã chốt ở `/map-testids`, trước `/generate-code`). Nên nó chạy **song song với FE**.
|
|
18
19
|
|
|
19
20
|
---
|
|
20
21
|
|
|
21
22
|
## Input / Output
|
|
22
23
|
|
|
23
|
-
**Input:** TEST_PLAN.md + skill `qa-designer` (chọn layer, nạp MỘT file).
|
|
24
|
+
**Input:** TEST_PLAN.md + skill `qa-designer` (chọn layer, nạp MỘT file) + `.feature` (nguồn scenario cho Guard) + **§4.5.6 Test Selectors**.
|
|
24
25
|
|
|
25
26
|
**Output:** `{qc_dir}/{TICKET-ID}/{platform}/test-cases/*.Test.md` (trace mapping bắt buộc). Gọi theo **từng UC**, ghi vào thư mục test-case dùng chung cấp PRD.
|
|
26
27
|
|
|
@@ -31,13 +32,31 @@ Tách "thiết kế test case" (con người đọc/review được) khỏi "cod
|
|
|
31
32
|
1. **Role qa-designer** — chọn layer, nạp một file skill (không nạp cả bộ → tiết kiệm context).
|
|
32
33
|
2. **Conventions** — theo quy ước test-case của QC team.
|
|
33
34
|
3. **Trace mapping (bắt buộc)** — mỗi test case ↔ SC.
|
|
34
|
-
4. **
|
|
35
|
+
4. **Guard — SC coverage** *(mới)* — phép **đếm cơ học**, không phải lượt đọc lại:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
1. Thu SC — mọi @trace.scenario trong .feature của uc_list (đúng nền).
|
|
39
|
+
LOẠI SC của UC mà qc-scope đã lọc ra (⏸ BDD chưa approved).
|
|
40
|
+
2. Thu V — mọi @trace.verifies trong các file *.Test.md VỪA GHI.
|
|
41
|
+
3. Đếm — mỗi SC ∈ tập bước 1 phải có ≥ 1 TC trỏ tới.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
| Kết quả | Hành vi |
|
|
45
|
+
|---|---|
|
|
46
|
+
| Mọi SC đều có ≥1 TC | in `Guard SC coverage: khớp {K}/{K}` |
|
|
47
|
+
| Có SC chưa phủ | **viết bù TC ngay**, rồi in `⚠️ Guard SC coverage: {K}/{total} — đã bù {m} SC: {…}` |
|
|
48
|
+
|
|
49
|
+
**In dòng này kể cả khi sạch** — guard im lặng khi sạch là guard không ai biết nó tồn tại, nên cũng không ai phát hiện khi nó hỏng.
|
|
50
|
+
|
|
51
|
+
5. **Self-Review** — nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
|
|
52
|
+
6. **Output** `.Test.md`.
|
|
35
53
|
|
|
36
54
|
---
|
|
37
55
|
|
|
38
56
|
## Checkpoint & Gate
|
|
39
57
|
|
|
40
|
-
- Không gate ở đây; gate là `/qc-review` kế tiếp.
|
|
58
|
+
- Không gate chặn người ở đây; gate là `/qc-review-testcase` kế tiếp.
|
|
59
|
+
- Nhưng Guard SC coverage **có hệ quả bắt buộc**: thiếu thì lệnh **viết bù** rồi mới báo, không phải chỉ cảnh báo.
|
|
41
60
|
|
|
42
61
|
---
|
|
43
62
|
|
|
@@ -46,6 +65,8 @@ Tách "thiết kế test case" (con người đọc/review được) khỏi "cod
|
|
|
46
65
|
- **Markdown-first** — test case là tài liệu review được trước khi thành code.
|
|
47
66
|
- **Nạp MỘT file skill theo layer** — tối ưu context (chỉ layer cần).
|
|
48
67
|
- **Trace mapping** — giữ test case gắn SC để về sau ghi `qc_status` đúng.
|
|
68
|
+
- **Guard SC coverage KHÔNG có đường thoát.** SC bị gap chặn **vẫn** phải có TC — viết đủ, mang dấu `🚫 Block: [GAP-UC{N}-{nnn}] — lý do`. Gap là thứ được **ghi vào** test case, không phải cái cớ để không viết. Cho phép "bỏ trống có lý do" là dạy hai luật trái nhau trong cùng một lệnh, và cho agent một câu-lý-do-cho-qua.
|
|
69
|
+
- **Guard ≠ Self-Review.** Guard là phép **đếm**, có hệ quả bắt buộc. Self-review là lượt đọc lại rộng hơn nhưng mềm hơn. Không bao giờ dùng self-review làm lý do gỡ Guard.
|
|
49
70
|
|
|
50
71
|
---
|
|
51
72
|
|
|
@@ -53,9 +74,11 @@ Tách "thiết kế test case" (con người đọc/review được) khỏi "cod
|
|
|
53
74
|
|
|
54
75
|
- **Tách design ↔ script** thêm một trạm nhưng cho phép review sớm — đánh đổi giữa số bước và chất lượng gate.
|
|
55
76
|
- **Phụ thuộc convention QC team** — cần đồng bộ khi convention đổi.
|
|
77
|
+
- **Guard đếm sớm, ở chỗ còn sửa được.** `/qc-report` cũng tính design coverage bằng **đúng phép đếm này**, nhưng ở **cuối** — lúc đó chỉ còn kịp báo, không còn kịp viết bù. Cùng một phép đếm, giá trị khác hẳn theo thời điểm.
|
|
78
|
+
- Con số `{K}/{total}` vốn **đã in** ở report từ trước, nhưng **không có phép tính nào đứng sau nó**. Một con số trong báo cáo không chứng minh có phép đo.
|
|
56
79
|
|
|
57
80
|
---
|
|
58
81
|
|
|
59
82
|
## Kết nối
|
|
60
83
|
|
|
61
|
-
**Trước:** [`/qc-plan`](16-qc-plan.md) · **Sau:** [`/qc-review`](18-qc-review.md) (review test case).
|
|
84
|
+
**Trước:** [`/qc-plan`](16-qc-plan.md) · **Sau:** [`/qc-review-testcase`](18-qc-review.md) (review test case).
|