@educa-corp/sdd-framework 0.9.2 → 0.9.4

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.
Files changed (76) hide show
  1. package/bin/build.js +11 -0
  2. package/bin/qc-base-map.json +119 -49
  3. package/bin/self-check.js +30 -0
  4. package/core/FRAMEWORK_VERSION +1 -1
  5. package/core/commands/qc-analyze.md +85 -75
  6. package/core/commands/qc-design-test.md +144 -25
  7. package/core/commands/qc-plan.md +40 -7
  8. package/core/commands/qc-review.md +74 -7
  9. package/core/commands/qc-run-test.md +21 -1
  10. package/core/commands/setup-ai-first.md +5 -5
  11. package/core/commands/update-framework.md +1 -1
  12. package/core/commands/validate-traces.md +1 -1
  13. package/core/modules/qc-playwright/stack-profile.yaml +3 -3
  14. package/core/rules/workflow.md +1 -1
  15. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +47 -17
  16. package/core/skills/qc/qa-analyst/acceptance-criteria.md +1 -1
  17. package/core/skills/qc/qa-analyst/business-rules.md +2 -2
  18. package/core/skills/qc/qa-analyst/data-flow.md +2 -2
  19. package/core/skills/qc/qa-analyst/spec-breakdown.md +4 -4
  20. package/core/skills/qc/qa-analyst/spec-issue-reporter.md +14 -2
  21. package/core/skills/qc/qa-designer/api/auth-chain.md +155 -0
  22. package/core/skills/qc/qa-designer/api/auth-sequence.md +75 -0
  23. package/core/skills/qc/qa-designer/api/common-headers.md +61 -0
  24. package/core/skills/qc/qa-designer/api/crud-sequence.md +122 -0
  25. package/core/skills/qc/qa-designer/api/endpoint.md +231 -0
  26. package/core/skills/qc/qa-designer/api/http-status-codes.md +102 -0
  27. package/core/skills/qc/qa-designer/e2e/journey.md +13 -8
  28. package/core/skills/qc/qa-designer/exploratory/charter.md +2 -0
  29. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +7 -4
  30. package/core/skills/qc/qa-designer/functional/api.md +87 -18
  31. package/core/skills/qc/qa-designer/functional/gui-feature.md +12 -9
  32. package/core/skills/qc/qa-designer/functional/gui-screen.md +12 -10
  33. package/core/skills/qc/qa-designer/integration/api.md +12 -5
  34. package/core/skills/qc/qa-designer/integration/db.md +12 -6
  35. package/core/skills/qc/qa-designer/integration/gui.md +12 -5
  36. package/core/skills/qc/qa-designer/integration/kafka.md +12 -5
  37. package/core/skills/qc/qa-designer/non-functional.md +12 -5
  38. package/core/skills/qc/qa-designer/shared/action-keywords-glossary.md +91 -0
  39. package/core/skills/qc/qa-designer/shared/duplicate-check-procedure.md +105 -0
  40. package/core/skills/qc/qa-designer/shared/implicit-scenarios.md +22 -0
  41. package/core/skills/qc/qa-designer/shared/precision-rules.md +198 -0
  42. package/core/skills/qc/qa-designer/shared/read-doc-gap-inputs.md +25 -0
  43. package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +93 -0
  44. package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +243 -0
  45. package/core/skills/qc/qa-planner/risk-model.md +1 -1
  46. package/core/skills/qc/qa-planner/test-plan.md +24 -13
  47. package/core/skills/qc/qa-reviewer/script/e2e.md +9 -1
  48. package/core/skills/qc/qa-reviewer/script/exploratory.md +9 -1
  49. package/core/skills/qc/qa-reviewer/script/functional.md +9 -1
  50. package/core/skills/qc/qa-reviewer/script/integration.md +9 -1
  51. package/core/skills/qc/qa-reviewer/script/non-functional.md +9 -1
  52. package/core/skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md +26 -0
  53. package/core/skills/qc/qa-reviewer/shared/review-check-groups.md +207 -0
  54. package/core/skills/qc/qa-reviewer/shared/review-file-template.md +228 -0
  55. package/core/skills/qc/qa-reviewer/test-case/e2e.md +71 -13
  56. package/core/skills/qc/qa-reviewer/test-case/exploratory.md +53 -4
  57. package/core/skills/qc/qa-reviewer/test-case/functional.md +63 -15
  58. package/core/skills/qc/qa-reviewer/test-case/integration.md +64 -12
  59. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +72 -13
  60. package/core/skills/qc/qa-runner/e2e.md +1 -1
  61. package/core/skills/qc/qa-runner/exploratory/session.md +1 -1
  62. package/core/steps/context-loader.md +1 -1
  63. package/core/steps/qc-scope.md +119 -0
  64. package/core/templates/project-context.yaml +3 -1
  65. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +1 -1
  66. package/docs/02-concepts/pipeline-steps/09-validate-traces.md +1 -1
  67. package/docs/04-reference/configuration.md +146 -146
  68. package/docs/04-reference/trace-schema.md +1 -1
  69. package/docs/explain/00-setup-ai-first.md +1 -1
  70. package/docs/explain/15-qc-analyze.md +1 -1
  71. package/docs/explain/16-qc-plan.md +1 -1
  72. package/docs/explain/17-qc-design-test.md +1 -1
  73. package/docs/plans/qc-implementation-log.md +288 -5
  74. package/docs/plans/qc-sync-command.md +2 -1
  75. package/package.json +1 -1
  76. package/scripts/migrate-qc-docs.js +261 -0
@@ -0,0 +1,93 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-designer/shared/skill-decision-tree.md
6
+ upstream_sha: 57125f0c21512f2abcc55d00420e92c84c95fc8f
7
+ ---
8
+ # Cây Quyết Định — Chọn Skill Đúng
9
+
10
+ > Đọc file này khi không chắc nên dùng skill nào. Trả lời lần lượt các câu hỏi từ trên xuống.
11
+
12
+ ---
13
+
14
+ ## Bước 1 — Đối tượng test là gì?
15
+
16
+ ```
17
+ Đối tượng test
18
+ ├── Hiển thị / validation / state của 1 screen → [A] Xét tiếp Bước 2 (UI vs Integration GUI)
19
+ ├── User thực hiện workflow có mục tiêu nghiệp vụ → [B] Xét tiếp Bước 3 (E2E vs Integration)
20
+ ├── 1 API endpoint (request/response/mã lỗi) → api-testcase-designer
21
+ ├── NFR (performance/security/a11y/i18n) → nfr-testcase-designer
22
+ └── Luồng đa màn nằm trong 1 feature, không xuyên hệ thống → ui-testcase-designer (gui-feature)
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Bước 2 — UI vs Integration GUI
28
+
29
+ **Câu hỏi:** TC này có thể chạy với dữ liệu tĩnh/mock mà vẫn valid không?
30
+
31
+ | Câu trả lời | Skill | Lý do (ISTQB) |
32
+ |---|---|---|
33
+ | **Có** — mock data đủ để verify | `ui-testcase-designer` | Component testing: verify UI behavior độc lập với backend |
34
+ | **Không** — phải có API thật/stub mới verify được | `integration/gui` trong `integration-testcase-designer` | Integration testing: verify contract UI layer ↔ API layer |
35
+
36
+ **Ví dụ phân biệt:**
37
+
38
+ | Tình huống | Skill | Lý do |
39
+ |---|---|---|
40
+ | Dropdown có placeholder, đóng khi click ngoài | UI | Behavior tĩnh, không cần API |
41
+ | Dropdown hiển thị đúng N item từ API response | Integration GUI | Verify data flow API → render |
42
+ | Form validate email format | UI | Client-side validation, không cần server |
43
+ | Form validate email "đã tồn tại" qua API | Integration GUI | Server-side validation = API call |
44
+ | Bảng danh sách render đúng số cột, format | UI | Layout/display |
45
+ | Bảng danh sách phản ánh đúng dữ liệu từ GET /list | Integration GUI | API data → UI sync |
46
+
47
+ ---
48
+
49
+ ## Bước 3 — E2E vs Integration
50
+
51
+ **Câu hỏi:** Chủ thể của test là ai/cái gì?
52
+
53
+ | Câu trả lời | Skill | Lý do (ISTQB) |
54
+ |---|---|---|
55
+ | **User** hoàn thành 1 mục tiêu nghiệp vụ từ đầu đến cuối | `e2e-testcase-designer` | System testing: user journey perspective |
56
+ | **Module A ↔ Module B** trao đổi dữ liệu/contract đúng | `integration-testcase-designer` | Integration testing: system contract perspective |
57
+
58
+ **Câu hỏi phụ để phân biệt rõ hơn:**
59
+
60
+ > "Nếu tôi xóa hết step UI và chỉ test phần trao đổi dữ liệu, TC vẫn còn ý nghĩa không?"
61
+ > - Có → Integration (bản chất là test handshake, UI chỉ là trigger)
62
+ > - Không → E2E (user journey là trọng tâm, không thể tách ra)
63
+
64
+ **Ví dụ phân biệt:**
65
+
66
+ | Tình huống | Skill | Lý do |
67
+ |---|---|---|
68
+ | User đăng ký → nhận email → login → vào dashboard | E2E | User journey hoàn chỉnh, verify goal đạt được |
69
+ | User tạo lớp học → lớp hiện trong danh sách | E2E | End-to-end từ action đến kết quả nhìn thấy |
70
+ | Frontend gọi POST /enroll → DB ghi đúng bản ghi | Integration | Module contract: API ↔ DB, không phụ thuộc UI |
71
+ | Service A gửi event Kafka → Service B xử lý đúng | Integration | System-to-system, không liên quan user |
72
+ | Tạo đơn hàng qua UI → kiểm tra DB có bản ghi | Cả hai? | Nếu mục tiêu là "user đặt hàng thành công" → E2E; nếu mục tiêu là "POST /order ghi DB đúng" → Integration |
73
+
74
+ ---
75
+
76
+ ## Tóm tắt nhanh
77
+
78
+ ```
79
+ Có API thật mới verify được?
80
+ └─ Không → UI
81
+ └─ Có, verify data flow 1 điểm → Integration GUI
82
+ └─ Có, user journey đầu-cuối → E2E
83
+ └─ Có, handshake 2 module/hệ thống → Integration
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Quy tắc ưu tiên khi vẫn còn mơ hồ
89
+
90
+ 1. **UI ưu tiên nhỏ nhất:** viết TC nhỏ nhất có thể verify 1 behavior cụ thể.
91
+ 2. **Integration GUI** khi có server-side behavior: validation, lookup, list.
92
+ 3. **E2E chỉ cho P0/P1 critical path** (ISTQB Test Pyramid: E2E ít nhất, UI/Unit nhiều nhất).
93
+ 4. **Integration** khi tách được khỏi UI và vẫn có giá trị test.
@@ -0,0 +1,243 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-designer/shared/tc-metadata-format.md
6
+ upstream_sha: a31d66a7a8dab19cf821c9102a88282b09e16cb9
7
+ ---
8
+ # TC Metadata Format (Chuẩn chung)
9
+
10
+ ## ⚠️ Nguyên tắc format file TC (BẮT BUỘC — QC yêu cầu)
11
+
12
+ - **TOÀN BỘ file TC viết dạng LIST — KHÔNG dùng bảng Markdown** (không ký tự `|`). Áp dụng cho: Test Steps, Tổng hợp TC, Trace Matrix, TC bị Block, metadata đầu file. *(Chỉ file TC output; tài liệu skill này giữ bảng minh hoạ bình thường.)*
13
+ - **Gom nhóm theo LOẠI test** (không theo luồng nghiệp vụ): thứ tự cố định **GUI → Validation → Functional → Integration → NFR → E2E** (xem §Phân nhóm).
14
+ - Khi tái cấu trúc/đảo nhóm: **GIỮ NGUYÊN mã `TC_<FEATURE>_NNN`**, chỉ đổi vị trí (mã không cần liền mạch theo thứ tự đọc).
15
+ - **App/Web là 2 bộ TC ĐỘC LẬP, mỗi nền chạy FULL business-logic** — trùng logic giữa 2 nền là chủ đích, KHÔNG tính duplicate defect; mỗi file phải độc lập đạt full coverage — mỗi nền một thư mục riêng (`{qc_dir}/{TICKET-ID}/web/` vs `/app/`), và sổ trace cũng tách theo nền.
16
+
17
+ ## ⚠️ Quy tắc "1 bullet Expected = 1 TC ĐỘC LẬP" (BẮT BUỘC — QC yêu cầu, testcase ATOMIC)
18
+
19
+ > **Cập nhật 2026-07-09 (QC chốt — ĐẢO rule cũ):** trước đây cho GỘP nhiều checkpoint cùng-1-hành-vi vào 1 Expected nhiều bullet. **Nay: mỗi Expected chỉ ĐÚNG 1 bullet; mọi TC nhiều bullet phải TÁCH thành nhiều TC độc lập.** KHÔNG còn ngoại lệ "gộp checkpoint".
20
+
21
+ - **Test Steps chỉ chứa hành động.** Mỗi bước là `[Action]` hoặc `[Verify]` THUẦN — **KHÔNG gắn `→ [Expected] ...` ở cuối bước.** Oracle nằm ở `#### Expected Result`.
22
+ - **Atomic = 1 OUTCOME, không chỉ đếm "1 bullet".** Mỗi TC đúng 1 `#### Expected Result` với ĐÚNG 1 bullet. Bullet compound (`A, B`) **chỉ OK khi cùng 1 outcome** (vd "chỉ 5 slide: đúng 5 dots; slide 6,7 không xuất hiện" · "form hiển thị đủ 3 trường"). **Bullet nối bằng `;` kiểu "khẳng-định + phủ-định/outcome độc lập"** (vd "Có lối Đăng nhập**;** KHÔNG có OTP" · "sang routing**;** không OTP") **= 2 outcome → TÁCH tiếp** — soi nhanh khi review: grep bullet chứa `;` + `không/KHÔNG`. Tuyệt đối KHÔNG ≥2 bullet trong 1 Expected.
23
+ - **Nhiều điểm-kiểm / outcome → TÁCH thành nhiều TC ĐỘC LẬP, mỗi TC 1 bullet.** Áp cho MỌI trường hợp: outcome độc lập (BVA/Decision-rule/tiền đề khác) LẪN nhiều checkpoint của **cùng 1 hành vi** (VD "màn hiển thị đủ ô A + nút B + lối C" → **3 TC**, không còn gộp).
24
+ - **⚠️ Chế độ ATOMIC TỐI ĐA (QC chốt 2026-07-14 — GIẢI mâu thuẫn 2 gạch trên):** khi user YÊU CẦU THẲNG "tách nhỏ nhất", **completeness list nổ từng thành phần** (kể cả "form đủ 3 trường" → **3 TC**; thẻ khung giờ đủ 5 field → 5 TC) — tức áp gạch "→ 3 TC", KHÔNG dùng ngoại lệ "compound cùng-1-outcome" cho completeness. **NHƯNG GIỮ 1 TC** cho: *predicate đa-điều-kiện định-nghĩa-1-khái-niệm* ("chưa bắt đầu & ≥10' = slot-hợp-lệ"), *ngưỡng* ("≥44pt·48dp", "WCAG AA ≥4.5:1"), *exclusivity* chọn-một, *qualifier* ("không chỉ bằng màu"). Trước khi thực thi: **hỏi 1 câu chốt ranh giới completeness** (quy mô ~95 vs ~130 TC) + dựng **bản đồ tách** (số mảnh/TC cha) rồi mới ghi. Chi tiết + thủ tục verify: `precision-rules.md §2.1`. (Mặc định lúc SINH MỚI vẫn cho compound cùng-1-outcome; chế độ tối đa chỉ khi user yêu cầu.)
25
+ - **Mỗi TC tách là testcase ĐỘC LẬP** — KHÔNG phải "con", KHÔNG đánh `(1/N)`, KHÔNG suffix `001a/001b`:
26
+ - **Tiêu đề mô tả riêng** self-contained (ngữ cảnh màn/hành vi + điểm được kiểm), heading khớp `**Title:**`.
27
+ - **Giữ FULL Test Steps** — lặp đủ bước để tới trạng thái assert (KHÔNG cắt bước theo từng bullet).
28
+ - Metadata (Feature/Module/Priority/Status/Tags/Trace) + Preconditions **copy nguyên** từ TC gốc.
29
+ - **`#### Teardown` là SECTION riêng, KHÔNG phải bullet Expected.** Khi tách bằng script: parse `#### Teardown` riêng — **đừng nuốt bullet teardown vào `#### Expected Result`** (bug đã gặp → sinh "TC teardown giả" có Expected="Xoá dữ liệu test…", steps↔expected mâu thuẫn, không pass/fail được). Mỗi TC tách **TẠO bản ghi DB** (register/tạo tài khoản mới) phải giữ `#### Teardown` riêng; flow **login trên seed** không cần.
30
+ - **Renumber TUẦN TỰ toàn dải** khi tách. Đổi số cascade → **đồng bộ NGAY**: `Mục lục` (range mỗi nhóm) · `Tổng hợp` (count + priority) · note `· N TC` mỗi Nhóm · `Trace Matrix` (**expand range** cũ thành list id mới) · `TC bị Block` (map id cũ → các id con). Dùng script xác định + backup trước–sau (agent ghi file lớn hay lỗi âm thầm — xem gạch cuối mục này).
31
+ - **Assertion loại-trừ (KHÔNG hiển thị / KHÔNG xảy ra) là oracle THẬT** → mỗi cái là 1 bullet = 1 TC riêng. Khi tách bằng script cơ học, **kiểm lại không đánh rơi** (đối chiếu backup).
32
+ - **Bullet metadata KHÔNG phải outcome.** `- Mobile: \`@pytest.mark.flaky(...)\`` lọt trong Expected là **marker** → loại khỏi phép đếm outcome, **dời ra meta** (`- **Chạy (mobile):** …`). Đếm nhầm marker là "bullet thứ 2" sẽ kết luận SAI rằng file cần tách. Reviewer cờ `[MARKER_IN_EXPECTED]`.
33
+ - **⚠️ Trước khi viết script tách/renumber — biết 5 bẫy này trước.** 5 bug **không throw exception** (script "chạy xong" rồi ghi file hỏng):
34
+ 1. **Double-remap**: transformer vừa *sinh* ID vừa *remap* ID → regex khớp luôn **heading vừa sinh** → ID trùng. **Chỉ remap `preamble` + `tail`, KHÔNG remap phần vừa sinh.**
35
+ 2. **2 namespace ID**: liệt kê namespace TRƯỚC khi rename (vd FEAT-01-2: nội bộ `TC_FEAT-01-2_{APP,WEB}_NNN` remap ĐƯỢC · **master** `TC_NNN`/`TC_FEAT-01-2_NNN` ở BLOCKED/TODO **KHÔNG remap**). Verify: `diff` tập master-ID backup↔new.
36
+ 3. **Replace-section làm rơi dòng chưa mô hình hoá** (dòng `>` note trong Expected). Giữ trailing note.
37
+ 4. **Tiêu đề cha ≠ prefix con**: auto-title `"<heading cha> — <bullet>"` nhân đôi khi heading cha liệt kê cả 2 vế.
38
+ 5. **Invariant phải gồm DIFF ĐỊNH DẠNG**, không chỉ đếm: liên tục ID · 0 trùng · 1 bullet/TC · oracle lossless (diff vs backup) · 0 dead-ref · **0 dòng-trống-kép/nhiễu whitespace** · master-ID không đổi.
39
+ - **Có file ĐÃ atomic sẵn** — phân tích phân bố bullet/TC trước, đừng tách lấy được. Quy trình bền: sửa **source/backup** → **tái sinh** bằng script xác định → verify → sai thì restore.
40
+
41
+ ## Content Oracle — exact-copy phải self-contained + đúng nguồn
42
+
43
+ - Chuỗi text spec-defined mà TC assert (tiêu đề màn, nhãn, copy nút, thông báo lỗi) → **ghi nguyên văn trong Expected Result** để TC tự chứa, người đọc không phải mở spec mới biết kỳ vọng.
44
+ - **BẮT BUỘC kiểm nguồn ĐÚNG feature trước khi chép:** mở design-spec/PRD của **chính feature đó** và xác nhận chuỗi tồn tại. **KHÔNG mượn chuỗi từ feature anh em** — VD copy P2 của FEAT-01-1 là *"Việc tạo **tài khoản** đang tạm thời bị gián đoạn…"* còn FEAT-01-2 là *"Việc tạo **câu hỏi** đang tạm thời bị gián đoạn…"*; chép nhầm → oracle sai.
45
+ - Chuỗi **chưa** có trong PRD/design-spec (chỉ ở Figma / chưa chốt) → **KHÔNG bịa oracle**: để trống + gắn `🚫 Block: [GAP-UC{N}-{nnn}]` hoặc `Status: PENDING`, ghi rõ chờ ai chốt.
46
+ - Cờ "MIỄN coverage / thuộc Design Spec" trong BDD **không** cấm assert nếu PRD/design-spec vẫn enumerate đủ chuỗi — vẫn được đưa vào Expected Result; chỉ hạ về mức generic khi thực sự không có nguồn chốt.
47
+
48
+ ## Metadata (bắt buộc, dạng list)
49
+
50
+ Mỗi trường 1 dòng, không bảng, không emoji dư:
51
+
52
+ ```
53
+ - **Title:** <tên TC ngắn gọn>
54
+ - **Feature:** <tên feature>
55
+ - **Priority:** P0 | P1 | P2
56
+ - **Status:** Draft
57
+ - **Author:** AI
58
+ - **Tags:** <lane>, <loại: smoke|sanity|regression>, <feature-tag>
59
+ - **Trace:** BR-xx (ID gốc trong PRD/BDD ở `{paths.specs_dir}`)
60
+ - **🚫 Block:** [GAP-UC{N}-{nnn}](../DOC_GAP.md) — <lý do> *(chỉ khi có)*
61
+ ```
62
+
63
+ ## Quy tắc Trace & Block
64
+
65
+ - **Trace:** ghi `BR-xx` lấy từ ID trong `{paths.specs_dir}`; không có BR → `⚠️ Chưa có Business Rule`.
66
+ - **🚫 Block:** TC phụ thuộc gap **vẫn viết đủ** + ghi `[GAP-UC{N}-{nnn}] — lý do`; chưa chạy tới khi gap Answered.
67
+
68
+ ## Cấu trúc TC
69
+
70
+ ```markdown
71
+ ### [TC_ID] — [Tên TC]
72
+ - **Title:** ...
73
+ - **Feature:** ...
74
+ - **Priority:** P0|P1|P2
75
+ - **Status:** Draft
76
+ - **Author:** AI
77
+ - **Tags:** ...
78
+ - **Trace:** BR-xx
79
+ - **🚫 Block:** (nếu có)
80
+
81
+ #### Preconditions
82
+ - ...
83
+
84
+ #### Test Data
85
+ - field: giá trị
86
+
87
+ #### Test Steps
88
+ 1. [Action] ... ← chỉ hành động; KHÔNG gắn "→ [Expected] ..."
89
+ 2. [Verify] ... ← chỉ điểm quan sát; oracle nằm ở Expected Result
90
+
91
+ #### Expected Result
92
+ - <1 bullet kết quả cuối cụ thể, đo được — xem §"1 Expected Result / TC">
93
+
94
+ #### Teardown ← CHỈ khi TC tạo/sửa bản ghi hoặc state THẬT
95
+ - <cách cleanup: API DELETE / reset tài khoản test / fixture / `⚠️ Manual teardown required`>
96
+ ```
97
+
98
+ ## Quy tắc Teardown (khi nào CÓ / KHÔNG)
99
+
100
+ - **CÓ Teardown** chỉ khi TC tạo/sửa **bản ghi DB hoặc state thật** tồn tại sau test (vd: ghi phân khúc vào tài khoản test, tạo bản ghi qua API thật).
101
+ - **KHÔNG cần Teardown** khi TC chỉ cấu hình **mock / route intercept / network monitoring** — việc reset mock về default là trách nhiệm của **fixture `conftest.py`** (scope `function` tự teardown mỗi test). Ghi "Reset mock về default" trong từng TC là **thừa** → không thêm.
102
+ - Lane test qua mock hoàn toàn (vd lane UI/E2E khi API SKIP) → hầu hết TC KHÔNG có Teardown; chỉ TC chạm tài khoản/state thật mới có.
103
+
104
+ ## Phân nhóm TC & đánh số nhóm (chuẩn chung)
105
+
106
+ TC trong file được gom theo **nhóm phân loại nội dung** và đánh **số CỐ ĐỊNH theo LOẠI** — số nhóm gắn cứng với loại, loại KHÔNG có TC thì **BỎ TRỐNG số đó** (KHÔNG đánh tuần tự lại). *(QC chốt 2026-07-08 — thay quy ước "liên tục" cũ.)*
107
+
108
+ Gom theo **LOẠI test**, số nhóm CỐ ĐỊNH theo loại, chỉ tạo nhóm THỰC SỰ có TC:
109
+
110
+ 1. **GUI** — UI tĩnh, label, layout, placeholder, icon, trạng thái hiển thị (không đổi state).
111
+ 2. **Validation** — field-level: validate input, EP/BVA, biên, error message, trạng thái nút enabled/disabled theo điều kiện, read-only, ràng buộc.
112
+ 3. **Functional** — nghiệp vụ/luồng: business logic, submit/navigation, decision table, use case hoàn chỉnh.
113
+ 4. **Integration** — bắt tay ≥2 module/dịch vụ (kể cả qua mock): đọc/ghi cross-service, handshake, data flow, contract.
114
+ 5. **NFR** — phi chức năng: performance, a11y/keyboard, WCAG, security, i18n, compatibility.
115
+ 6. **E2E** — journey đầu-cuối nhiều use case.
116
+
117
+ **Quy tắc đánh số & phân nhóm:**
118
+ - Gán số CỐ ĐỊNH theo loại: **GUI=1 · Validation=2 · Functional=3 · Integration=4 · NFR=5 · E2E=6**. Loại KHÔNG có TC → **BỎ TRỐNG số đó**. VD file chỉ có GUI + Validation + Functional + E2E → `Nhóm 1 — GUI` / `Nhóm 2 — Validation` / `Nhóm 3 — Functional` / **`Nhóm 6 — E2E`** (bỏ trống 4 Integration, 5 NFR). **E2E LUÔN là Nhóm 6, NFR luôn 5, Integration luôn 4** — KHÔNG dồn số.
119
+ - Phân vân **Validation vs Functional**: chỉ test trạng thái field/nút/biên → Validation; có luồng/submit/navigation/logic → Functional. **KHÔNG tạo nhóm "Tương tác"/"Happy Path" riêng.**
120
+ - Lane chỉ có functional (API/Integration/NFR, không có GUI) → bỏ nhóm GUI, bắt đầu từ nhóm phù hợp.
121
+ - **GIỮ NGUYÊN mã TC** khi gom/đảo nhóm — chỉ đổi vị trí; mã không cần liền mạch theo thứ tự đọc.
122
+ - Mọi tham chiếu số nhóm trong file (Trace Matrix, ghi chú) phải khớp số CỐ ĐỊNH đã gán.
123
+
124
+ ## Cuối file (bắt buộc)
125
+
126
+ Cả 2 mục dạng LIST (không bảng):
127
+
128
+ ```markdown
129
+ ## Trace Matrix
130
+ - **BR-xx:** TC_001, TC_002
131
+ - **⚠️ BR-yy:** — (Chưa có TC)
132
+
133
+ ## TC bị Block
134
+ - **GAP-03** — TC_005: Chờ openapi.yaml
135
+ ```
136
+
137
+ > Không thêm section `#### Python Test Mapping`. Bỏ nội dung gạch ngang.
138
+
139
+ > ⚠️ **Bổ sung khi Edit thêm TC mới:** nối bullet mới **ngay liền sau bullet cuối** của list (Trace Matrix / TC bị Block), KHÔNG chèn dòng trắng giữa các bullet. Kiểm lại số TC khớp sau khi thêm.
140
+
141
+ ---
142
+
143
+ ## Tài liệu shared liên quan (bắt buộc nạp khi viết TC)
144
+
145
+ | File | Mục đích |
146
+ |---|---|
147
+ | `shared/action-keywords-glossary.md` | Từ điển action keywords chuẩn — Click/Enter/Verify/Assert... |
148
+ | `shared/precision-rules.md` | Quy tắc lượng hóa Expected Result, cấm từ mơ hồ, đơn vị chuẩn |
149
+ | `shared/duplicate-check-procedure.md` | Quy trình kiểm tra TC trùng lặp trước khi viết mới |
150
+ | `shared/implicit-scenarios.md` | Danh sách implicit scenarios cần xét thêm |
151
+ | `shared/skill-decision-tree.md` | Cây quyết định chọn đúng skill |
152
+
153
+ ---
154
+
155
+ ## Gap Escalation Path (Xử lý khi TC bị Block)
156
+
157
+ Khi TC có `🚫 Block: [GAP-UC{N}-{nnn}]` — thực hiện theo timeline:
158
+
159
+ | Thời điểm | Hành động |
160
+ |---|---|
161
+ | **T+0 (phát hiện gap)** | Ghi GAP vào `DOC_GAP.md` — ID, loại, mô tả, tác động, nguồn |
162
+ | **T+2 (2 ngày)** | Chưa có phản hồi → ping QA Lead / PO |
163
+ | **T+5 (5 ngày)** | Vẫn chưa có → ghi **assumption tạm thời** vào TC bị Block |
164
+ | **T+7 (7 ngày)** | Leo thang PO/PM — gap ảnh hưởng sprint delivery |
165
+
166
+ ### Format Assumption khi gap chưa được trả lời (T+5):
167
+
168
+ ```
169
+ ⚠️ Assumption (T+5): API trả về HTTP 422 khi tên lớp trùng — dựa trên pattern UC1.
170
+ Nếu behavior khác → cập nhật Expected Result và re-review.
171
+ ```
172
+
173
+ ### Quy trình khi gap được giải quyết (Answered):
174
+ 1. Cập nhật `DOC_GAP.md`: status → `Answered`, ghi note giải thích.
175
+ 2. Bỏ `🚫 Block` trong TC → cập nhật Expected Result nếu có assumption sai.
176
+ 3. Thông báo `qa-tc-reviewer` review lại TC.
177
+ 4. Nếu answer thay đổi scope → tạo TC mới hoặc split TC hiện tại.
178
+
179
+ ---
180
+
181
+ # Phần riêng của framework *(B12 — không có ở upstream)*
182
+
183
+ Mọi thứ trên là chuẩn của đội QC. Bốn thứ dưới đây là **của framework**, và mọi skill tầng test
184
+ đều theo — đừng lặp lại chúng trong từng skill.
185
+
186
+ ## Hai file TC, chia theo "có qua giao diện"
187
+
188
+ ```
189
+ {qc_artifact_dir}test-cases/
190
+ ├── TC_<FEATURE>.Test.md ← mặc định
191
+ │ ## Nhóm 1 — GUI ## Nhóm 4 — Integration (qua UI)
192
+ │ ## Nhóm 2 — Validation ## Nhóm 5 — NFR
193
+ │ ## Nhóm 3 — Functional ## Nhóm 6 — E2E
194
+ └── TC_<FEATURE>_API.Test.md ← cờ --api
195
+ ## Nhóm 1 — Endpoint
196
+ ## Nhóm 2 — Integration API/DB/Kafka
197
+ ```
198
+
199
+ **Câu hỏi phân file:** *"TC này verify được mà **không cần UI** không?"*
200
+ → **có** = file API · **không** = file giao diện. *(Trùng Bước 2 của `skill-decision-tree.md`.)*
201
+
202
+ ⚠️ **Đuôi file là `.Test.md`, không phải `.md`.** `/qc-run-test` và `/qc-review` tìm `*.Test.md`;
203
+ ghi ra file thiếu phần `.Test` là ghi ra thứ **không trạm nào tìm thấy**, và không có gì báo lỗi.
204
+
205
+ Đánh số `TC_<FEATURE>_NNN` **liên tục toàn file**, không đánh lại theo từng nhóm.
206
+
207
+ ## Trace — hai hệ, ghi cả hai
208
+
209
+ | Trường | Dạng | Vì sao cần |
210
+ |---|---|---|
211
+ | `**Trace:**` | `[BR-xx](../REQUIREMENT_ANALYSIS.md#3-business-rules)` — không có BR → `⚠️ Chưa có Business Rule` | truy về luật nghiệp vụ |
212
+ | `**@trace.verifies:**` | `{UC-ID}-SC{N}` (lấy từ `@trace.scenario` của file `.feature`) | **join key** để `/qc-run-test` ghi `qc_status` theo từng kịch bản vào sổ trace |
213
+
214
+ Một `SC` map được nhiều TC. **Thiếu `@trace.verifies` thì kết quả chạy không vào được sổ** — TC
215
+ vẫn chạy, vẫn pass/fail, nhưng không ai biết nó phủ kịch bản nào.
216
+
217
+ Cuối file: **Trace matrix** (BR ↔ TC ↔ SC) + **danh sách TC bị block** — cả hai **dạng danh
218
+ sách**, không bảng (§Nguyên tắc format file đầu tài liệu này).
219
+
220
+ ## `🚫 Block` trỏ về file gap cấp PRD
221
+
222
+ ```
223
+ - **🚫 Block:** [GAP-UC{N}-{nnn}](../DOC_GAP.md) — <lý do>
224
+ ```
225
+
226
+ `DOC_GAP.md` nằm ở **thư mục cha** của `test-cases/`, nên liên kết đi lên một cấp. Mã gap mang
227
+ UC (`GAP-UC1-001`) vì một file gap phủ cả PRD.
228
+
229
+ ## Dòng `Test-ID attribute`
230
+
231
+ Ghi một dòng ở phần metadata **đầu file**:
232
+
233
+ ```
234
+ Test-ID attribute: {attr}
235
+ ```
236
+
237
+ Đọc `@trace.testid_attr` từ header tech-doc gộp (do `/map-testids` ghi). Bảng §4.5.6 chỉ cho
238
+ **giá trị** test-id; đây là **tên thuộc tính** chứa chúng. `/qc-run-test` cần nó để cấu hình
239
+ locator, `/qc-review` cần nó để biết selector trong script có đúng hợp đồng không.
240
+
241
+ Thiếu field trong tech-doc → ghi `Test-ID attribute: — (thiếu @trace.testid_attr, chạy /map-testids)`.
242
+ **Đừng bỏ trống và đừng tự đoán** — đoán sai thì mọi locator trượt 100%, và trượt vì lý do
243
+ không liên quan gì tới thứ đang test.
@@ -102,5 +102,5 @@ tiền không đáng.
102
102
  |---|---|---|---|---|---|
103
103
  | … | 2 · tiền | Cao | Cao | **P0** | functional/api + giá trị biên; e2e luồng thanh toán |
104
104
 
105
- Mỗi dòng rủi ro phải **trỏ được về BR-xx hoặc GAP-xx** đã có ở `REQUIREMENT_ANALYSIS.md` /
105
+ Mỗi dòng rủi ro phải **trỏ được về `BR-xx` hoặc `GAP-UC{N}-{nnn}`** đã có ở `REQUIREMENT_ANALYSIS.md` /
106
106
  `DOC_GAP.md` — rủi ro không neo vào yêu cầu nào là rủi ro tự nghĩ ra.
@@ -8,11 +8,14 @@ upstream_sha: f259b4d123c565a42ba6c6ec96980a8e4c66284f
8
8
 
9
9
  # Lập Test Plan
10
10
 
11
- Tổng hợp **output của qa-analyst** thành **Test Plan** cho một feature.
11
+ Tổng hợp **output của qa-analyst** thành **Test Plan** cho một feature — tức **một plan cho cả
12
+ (PRD × nền)**, các UC là các hàng bên trong.
12
13
 
13
14
  **Đầu vào (bắt buộc, chỉ 2 nguồn — đúng 2 file qa-analyst trả ra):**
14
- 1. `{paths.qc_dir}/{UC-ID}/REQUIREMENT_ANALYSIS.md` — chức năng, BR-xx, AC-xx, data flow (qa-analyst).
15
- 2. `{paths.qc_dir}/{UC-ID}/DOC_GAP.md` bảng gap GAP-xx, mức độ, gap Blocker (qa-analyst).
15
+ 1. `{qc_artifact_dir}REQUIREMENT_ANALYSIS.md` — chức năng, BR-xx, AC-xx, data flow của **mọi UC
16
+ trong phạm vi**, kèm mục *Mâu thuẫn chéo UC* (qa-analyst).
17
+ 2. `{qc_artifact_dir}DOC_GAP.md` — bảng gap 11 cột `GAP-UC{N}-{nnn}`, mức độ, gap Blocker, và
18
+ bảng *Phạm vi phân tích* (qa-analyst). **Lọc cột `UC`** khi cần phần của một UC cụ thể.
16
19
 
17
20
  ## Khi nào trigger
18
21
  - "lập test plan cho [Feature]" / "viết test plan"
@@ -56,14 +59,16 @@ Tổng hợp **output của qa-analyst** thành **Test Plan** cho một feature.
56
59
 
57
60
  ## Output — Template `TEST_PLAN.md`
58
61
 
59
- Đặt tại `{paths.qc_dir}/{UC-ID}/TEST_PLAN.md`:
62
+ Đặt tại `{qc_artifact_dir}TEST_PLAN.md`:
60
63
 
61
64
  ```markdown
62
- # Test Plan – <Feature>
65
+ # Test Plan – <TICKET-ID> <Tên feature> / <nền>
63
66
 
64
67
  | Trường | Giá trị |
65
68
  |---|---|
66
- | Feature / Project / Module | … |
69
+ | Feature / Project / Module | `<TICKET-ID>` — … |
70
+ | Nền (platform) | `<web \| app \| system>` |
71
+ | UC trong phạm vi | `<UC-ID>` · `<UC-ID>` … (`⏸ chưa xét`: `<UC-ID>`) |
67
72
  | Người lập | qa-planner |
68
73
  | Ngày / Phiên bản | … |
69
74
  | Nguồn | REQUIREMENT_ANALYSIS · DOC_GAP |
@@ -72,16 +77,20 @@ Tổng hợp **output của qa-analyst** thành **Test Plan** cho một feature.
72
77
  Mục tiêu test của feature (1–3 câu).
73
78
 
74
79
  ## 2. Phạm vi
75
- - **In scope:** chức năng/BR được test.
76
- - **Out of scope:** phần để tài liệu/feature khác; nội dung gạch ngang đã loại.
80
+ - **In scope:** chức năng/BR được test, **theo từng UC** (`<UC-ID>`: …).
81
+ - **Out of scope:** phần để tài liệu/feature khác; nội dung gạch ngang đã loại; và **UC
82
+ `⏸ Chưa xét`** (BDD chưa `approved`) — liệt kê rõ mã UC + lý do. *Không ghi ra thì một UC bị
83
+ bỏ trông giống một UC không có gì để test.*
77
84
 
78
85
  ## 3. Test items theo vùng & độ ưu tiên
79
86
  Bảng — mỗi vùng kèm rule chi tiết + metadata:
80
87
 
81
- | # | Vùng test | Rule chi tiết | Layer (qa-designer) | Loại test | Pri | Ước lượng |
82
- |---|---|---|---|---|---|---|
83
- | ① | <vùng> | **BR-xx:** … <br>**BR-yy:** … | functional/gui-screen | Functional/Negative | P0 | n |
84
- | … | … | … | … | … | … | … |
88
+ | # | UC | Vùng test | Rule chi tiết | Layer (qa-designer) | Loại test | Pri | Ước lượng |
89
+ |---|---|---|---|---|---|---|---|
90
+ | ① | `<UC-ID>` | <vùng> | **BR-xx:** … <br>**BR-yy:** … | functional/gui-screen | Functional/Negative | P0 | n |
91
+ | … | … | … | … | … | … | … | … |
92
+
93
+ *Cột `UC` bắt buộc — một plan phủ nhiều UC, không có nó thì không ai biết vùng test nào của UC nào.*
85
94
 
86
95
  > Tổng ước lượng sơ bộ: ~N test case (+ E2E).
87
96
 
@@ -98,7 +107,9 @@ Kỹ thuật áp dụng: EP+BVA, Decision Table (cho logic điều kiện), stat
98
107
  integration, negative/exploratory; tự động hoá theo `CLAUDE.md` (Playwright + pytest-playwright + Trace + pytest-html).
99
108
 
100
109
  ## 5. Tiêu chí Vào / Ra
101
- - **Entry:** gap Blocker (trong DOC_GAP) đã Answered; doc phụ thuộc sẵn sàng; môi trường + tài khoản role.
110
+ - **Entry (chấm theo TỪNG UC, không chấm cả PRD):** gap 🔴 Blocker của **UC đó** (lọc cột `UC`
111
+ trong DOC_GAP) đã Answered; doc phụ thuộc sẵn sàng; môi trường + tài khoản role.
112
+ Ghi `Ready`/`Blocked` cho mỗi UC — blocker ở UC3 không dừng thiết kế test UC1.
102
113
  - **Exit:** pass P0=100%, P1≥95%; không còn defect Blocker/Critical; mọi BR/AC được trace; báo cáo pytest-html + Playwright Trace.
103
114
 
104
115
  ## 6. Rủi ro (risk-based)
@@ -84,4 +84,12 @@ F. CONVENTION:
84
84
 
85
85
  Mỗi issue: `file:line` | severity | mô tả | suggestion fix.
86
86
  Severity: 🔴 fix ngay (missing cleanup, dữ liệu không verify cross-module, shortcut journey) · 🟠 quan trọng (timeout thiếu, assertion chỉ ở bước cuối) · 🟡 nhỏ (style, docstring/title sai).
87
- Score: A/B/C/D · Top 5 issue cần fix trước merge.
87
+ **Điểm `XX/100`** ánh xạ mức độ sang điểm trừ: 🔴 = `FAIL` (−5đ) · 🟠 = `WARN` (−2đ) ·
88
+ 🟡 = ghi nhận, không trừ. ≥80 đạt · 60–79 cần cải thiện · <60 không đạt.
89
+ **Verdict:** `≥80` VÀ không còn 🔴 → **`APPROVED`**; ngược lại **`NEEDS_FIX`**.
90
+
91
+ **Ghi vào `{qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md`** — thêm một hàng vào bảng Tổng quan
92
+ (cột `Tầng` phân biệt vai soát-code với vai soát-kịch-bản; **không ghi đè** hàng của vai kia).
93
+ Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
94
+
95
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-run-test`.
@@ -39,7 +39,15 @@ Review session note sau khi test, coaching QC cải thiện kỹ năng.
39
39
 
40
40
  ## Output
41
41
 
42
- Score: A (excellent) / B (good) / C (needs improvement) / D (redo)
42
+ **Điểm `XX/100`** ánh xạ mức độ sang điểm trừ: 🔴 = `FAIL` (−5đ) · 🟠 = `WARN` (−2đ) ·
43
+ 🟡 = ghi nhận, không trừ. ≥80 đạt · 60–79 cần cải thiện · <60 không đạt.
44
+ **Verdict:** `≥80` VÀ không còn 🔴 → **`APPROVED`**; ngược lại **`NEEDS_FIX`**.
45
+
46
+ **Ghi vào `{qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md`** — thêm một hàng vào bảng Tổng quan
47
+ (cột `Tầng` phân biệt vai soát-code với vai soát-kịch-bản; **không ghi đè** hàng của vai kia).
48
+ Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
49
+
50
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-run-test`.
43
51
  Mỗi tiêu chí: ✅/⚠️/❌ + feedback cụ thể
44
52
  Top 3 improvement suggestions (coaching tone)
45
53
  Đề xuất charter tiếp theo nếu chưa đủ coverage
@@ -98,4 +98,12 @@ empty step `:pass` · test gọi `_private()` · Counter≠Pagination → xfail
98
98
 
99
99
  Mỗi issue: file:line | severity | mô tả | suggestion fix.
100
100
  Severity: 🔴 fix ngay (sai logic, POM breach, silent fail) · 🟠 quan trọng (fragile selector, wrong column, missing assert) · 🟡 nhỏ (style, thừa wait, orphan constant).
101
- Score: A/B/C/D · Top 5 issue cần fix trước.
101
+ **Điểm `XX/100`** ánh xạ mức độ sang điểm trừ: 🔴 = `FAIL` (−5đ) · 🟠 = `WARN` (−2đ) ·
102
+ 🟡 = ghi nhận, không trừ. ≥80 đạt · 60–79 cần cải thiện · <60 không đạt.
103
+ **Verdict:** `≥80` VÀ không còn 🔴 → **`APPROVED`**; ngược lại **`NEEDS_FIX`**.
104
+
105
+ **Ghi vào `{qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md`** — thêm một hàng vào bảng Tổng quan
106
+ (cột `Tầng` phân biệt vai soát-code với vai soát-kịch-bản; **không ghi đè** hàng của vai kia).
107
+ Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
108
+
109
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-run-test`.
@@ -88,4 +88,12 @@ F. CONVENTION:
88
88
 
89
89
  Mỗi issue: `file:line` | severity | mô tả | suggestion fix.
90
90
  Severity: 🔴 fix ngay (mock thay real call, missing DB verify, no cleanup) · 🟠 quan trọng (thiếu error state, hardcode ID, timeout ngắn) · 🟡 nhỏ (style, marker thiếu sub-domain).
91
- Score: A/B/C/D · Top 5 issue cần fix trước merge.
91
+ **Điểm `XX/100`** ánh xạ mức độ sang điểm trừ: 🔴 = `FAIL` (−5đ) · 🟠 = `WARN` (−2đ) ·
92
+ 🟡 = ghi nhận, không trừ. ≥80 đạt · 60–79 cần cải thiện · <60 không đạt.
93
+ **Verdict:** `≥80` VÀ không còn 🔴 → **`APPROVED`**; ngược lại **`NEEDS_FIX`**.
94
+
95
+ **Ghi vào `{qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md`** — thêm một hàng vào bảng Tổng quan
96
+ (cột `Tầng` phân biệt vai soát-code với vai soát-kịch-bản; **không ghi đè** hàng của vai kia).
97
+ Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
98
+
99
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-run-test`.
@@ -123,4 +123,12 @@ def test_compatibility(browser_name, playwright):
123
123
 
124
124
  Mỗi issue: `file:line` | severity | mô tả | suggestion fix.
125
125
  Severity: 🔴 fix ngay (assertion không có ngưỡng, gọi production endpoint, hardcode credential) · 🟠 quan trọng (ngưỡng không khớp TC, thiếu parametrize, không teardown data) · 🟡 nhỏ (style, marker thiếu sub-domain, docstring thiếu ngưỡng).
126
- Score: A/B/C/D · Top 5 issue cần fix trước merge.
126
+ **Điểm `XX/100`** ánh xạ mức độ sang điểm trừ: 🔴 = `FAIL` (−5đ) · 🟠 = `WARN` (−2đ) ·
127
+ 🟡 = ghi nhận, không trừ. ≥80 đạt · 60–79 cần cải thiện · <60 không đạt.
128
+ **Verdict:** `≥80` VÀ không còn 🔴 → **`APPROVED`**; ngược lại **`NEEDS_FIX`**.
129
+
130
+ **Ghi vào `{qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md`** — thêm một hàng vào bảng Tổng quan
131
+ (cột `Tầng` phân biệt vai soát-code với vai soát-kịch-bản; **không ghi đè** hàng của vai kia).
132
+ Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
133
+
134
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-run-test`.
@@ -0,0 +1,26 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-reviewer/shared/read-doc-gap-inputs.md
6
+ upstream_sha: 3caa1562399ef1167ac2dc620add2c6c729e55df
7
+ ---
8
+
9
+ # Thủ tục: Nạp TOÀN BỘ tài liệu input từ DOC_GAP (BẮT BUỘC trước khi review TC)
10
+
11
+ > Mục tiêu: reviewer phải đọc **đúng bộ tài liệu nguồn mà `/qc-analyze` đã dùng** để dựng TEST_PLAN + DOC_GAP — không chỉ file domain. Chỉ khi nắm đủ ngữ cảnh nguồn mới bắt được TC hiểu sai nghiệp vụ, thiếu case, hoặc trace sai spec.
12
+
13
+ ## Các bước
14
+
15
+ 1. **Tìm file DOC_GAP** tại `{qc_artifact_dir}DOC_GAP.md` — **một file cho cả PRD**, các UC là các hàng phân biệt bằng cột `UC`. Không có → chạy `/qc-analyze {TICKET-ID} {platform}` trước; **đừng soát TC trên ngữ cảnh thiếu** (soát mù thì kết luận "0 lỗi" là vô nghĩa).
16
+ 2. **`Read` toàn bộ DOC_GAP.** Định vị mục **`## Tài liệu đầu vào đã đọc để phân tích`** — bảng liệt kê **đầy đủ** file nguồn (cột "Đường dẫn", tính từ `{paths.specs_dir}/`), kèm vai trò & phiên bản.
17
+ 3. **`Read` TỪNG file trong bảng đó** — ghép prefix `{paths.specs_dir}/` vào đường dẫn ở cột. Đọc HẾT, không bỏ sót dòng nào (spec chính + ref bắt buộc + transitive 1-hop). Nếu bảng liệt kê phiên bản, kiểm tra file hiện tại khớp; lệch phiên bản → ghi chú vào REVIEW.
18
+ 4. **Đối chiếu chéo:** file nào có mặt ở header DOC_GAP ("Tài liệu nguồn (spec chính)"/"Coverage Attestation") mà thiếu trong bảng → vẫn đọc.
19
+ 5. Chỉ sau khi đã nạp xong toàn bộ input + file domain (`business-dictionary.md`, `product-definition/`) mới bắt đầu review — dùng chúng làm chuẩn đối chiếu để phán quyết `APPROVED` / `NEEDS_FIX`.
20
+
21
+ ## Nguyên tắc
22
+
23
+ - **Chuẩn đối chiếu = tài liệu nguồn**, không phải suy đoán riêng của reviewer. Mọi nhận xét "TC hiểu sai/thiếu case" phải chỉ được về đoạn spec cụ thể trong các file đã đọc.
24
+ - **Không đọc thiếu:** nếu DOC_GAP nói "Tổng: N tài liệu" thì phải mở đủ N.
25
+ - Gap còn `Open` trong DOC_GAP: TC chạm vùng đó phải phản ánh đúng (đánh dấu blocked/assumption), không được coi như spec đã rõ.
26
+ - Lane API: nếu DOC_GAP ghi SKIP → không đòi hỏi TC endpoint không tồn tại.