@educa-corp/sdd-framework 0.9.6 → 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.
Files changed (93) hide show
  1. package/bin/lint-trace.js +4 -4
  2. package/bin/self-check.js +448 -12
  3. package/bin/trace-schema.json +643 -112
  4. package/core/FRAMEWORK_VERSION +1 -1
  5. package/core/commands/amend-prd.md +7 -1
  6. package/core/commands/debug.md +8 -2
  7. package/core/commands/define-product.md +38 -1
  8. package/core/commands/dev-gen-test.md +9 -3
  9. package/core/commands/dev-run-test.md +8 -2
  10. package/core/commands/dev-smoke-test.md +7 -1
  11. package/core/commands/extend-prd.md +7 -1
  12. package/core/commands/fix-bug.md +11 -5
  13. package/core/commands/generate-architecture.md +9 -1
  14. package/core/commands/generate-bdd.md +45 -5
  15. package/core/commands/generate-code.md +43 -4
  16. package/core/commands/generate-design-spec.md +7 -1
  17. package/core/commands/generate-prd.md +9 -1
  18. package/core/commands/generate-spec-manifest.md +7 -1
  19. package/core/commands/generate-tech-docs.md +41 -1
  20. package/core/commands/learn.md +7 -1
  21. package/core/commands/map-testids.md +11 -5
  22. package/core/commands/propose-scenario.md +7 -1
  23. package/core/commands/qc-analyze.md +12 -6
  24. package/core/commands/qc-automation-assess.md +356 -0
  25. package/core/commands/qc-design-script.md +400 -0
  26. package/core/commands/qc-design-test.md +21 -15
  27. package/core/commands/qc-plan.md +9 -3
  28. package/core/commands/qc-report.md +9 -3
  29. package/core/commands/qc-review-script.md +333 -0
  30. package/core/commands/{qc-review.md → qc-review-testcase.md} +84 -53
  31. package/core/commands/qc-run-manualtest.md +401 -0
  32. package/core/commands/qc-run-script.md +414 -0
  33. package/core/commands/refine-prd.md +7 -1
  34. package/core/commands/report-bug.md +9 -3
  35. package/core/commands/review-code.md +9 -3
  36. package/core/commands/review-context.md +11 -3
  37. package/core/commands/review-tech-docs.md +11 -3
  38. package/core/commands/setup-ai-first.md +7 -1
  39. package/core/commands/validate-traces.md +10 -4
  40. package/core/modules/qc-playwright/stack-profile.yaml +1 -1
  41. package/core/rules/workflow.md +2 -2
  42. package/core/skills/qc/_shared/self-review-principles.md +2 -2
  43. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +1 -1
  44. package/core/skills/qc/qa-analyst/spec-issue-reporter.md +1 -1
  45. package/core/skills/qc/qa-automation-assess/matrix.md +120 -0
  46. package/core/skills/qc/qa-designer/e2e/journey.md +1 -1
  47. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
  48. package/core/skills/qc/qa-designer/functional/api.md +1 -1
  49. package/core/skills/qc/qa-designer/functional/gui-feature.md +1 -1
  50. package/core/skills/qc/qa-designer/functional/gui-screen.md +1 -1
  51. package/core/skills/qc/qa-designer/integration/api.md +1 -1
  52. package/core/skills/qc/qa-designer/integration/db.md +1 -1
  53. package/core/skills/qc/qa-designer/integration/gui.md +1 -1
  54. package/core/skills/qc/qa-designer/integration/kafka.md +1 -1
  55. package/core/skills/qc/qa-designer/non-functional.md +1 -1
  56. package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +11 -6
  57. package/core/skills/qc/qa-reviewer/script/e2e.md +1 -1
  58. package/core/skills/qc/qa-reviewer/script/exploratory.md +1 -1
  59. package/core/skills/qc/qa-reviewer/script/functional.md +1 -1
  60. package/core/skills/qc/qa-reviewer/script/integration.md +1 -1
  61. package/core/skills/qc/qa-reviewer/script/non-functional.md +1 -1
  62. package/core/skills/qc/qa-reviewer/shared/review-file-template.md +3 -3
  63. package/core/skills/qc/qa-reviewer/test-case/e2e.md +1 -1
  64. package/core/skills/qc/qa-reviewer/test-case/functional.md +1 -1
  65. package/core/skills/qc/qa-reviewer/test-case/integration.md +1 -1
  66. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +1 -1
  67. package/core/skills/qc/qa-runner/e2e.md +2 -2
  68. package/core/skills/qc/qa-runner/functional/gui-feature.md +3 -3
  69. package/core/skills/qc/qa-runner/functional/gui-screen.md +3 -3
  70. package/core/skills/qc/qa-runner/integration.md +1 -1
  71. package/core/skills/qc/qa-runner/non-functional.md +1 -1
  72. package/core/steps/context-loader.md +1 -1
  73. package/core/steps/gate.md +7 -1
  74. package/core/steps/qc-scope.md +2 -2
  75. package/core/steps/qc-stamp.md +4 -4
  76. package/core/steps/report-footer.md +10 -9
  77. package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +1 -1
  78. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +9 -8
  79. package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +3 -3
  80. package/docs/02-concepts/traceability.md +1 -1
  81. package/docs/03-guides/developer.md +1 -1
  82. package/docs/03-guides/tester-qa.md +8 -7
  83. package/docs/04-reference/commands.md +4 -2
  84. package/docs/04-reference/trace-schema.md +4 -4
  85. package/docs/explain/17-qc-design-test.md +5 -5
  86. package/docs/explain/18-qc-review.md +42 -20
  87. package/docs/explain/19-qc-run-test.md +9 -6
  88. package/docs/explain/20-qc-report.md +3 -3
  89. package/docs/explain/23-fix-bug.md +2 -2
  90. package/docs/explain/README.md +2 -2
  91. package/docs/plans/qc-surgery/01-checklist.md +70 -17
  92. package/package.json +1 -1
  93. package/core/commands/qc-run-test.md +0 -561
@@ -4,7 +4,7 @@ Check read-only độ phủ giữa spec, code, và test — gồm cả PRD versi
4
4
 
5
5
  ## Gate
6
6
 
7
- *Checkpoint: **không chặn** — read-only (ghi trace-report.json + TSV status, không đụng spec/code). Gate Bước 3 bỏ qua CHECKPOINT (Bước 3a).*
7
+ *Checkpoint: **không chặn** — **không phải vì read-only**. Lệnh ghi `trace-report.json`, `.trace-mirror/`, và **append** `trace-history.jsonl`; với `--reconcile-code` còn ghi row TSV `_seams.tsv`. Nó không chặn vì mọi thao tác ghi VÔ ĐIỀU KIỆN đều hoặc dựng lại được, hoặc là `append` — và hai thao tác nguy hơn đều nằm sau `--reconcile-code`. Gate Bước 3 bỏ qua CHECKPOINT (Bước 3a).*
8
8
 
9
9
  # Gate — Quy trình vào chuẩn cho mọi lệnh
10
10
 
@@ -85,7 +85,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
85
85
 
86
86
  | Mức | Lệnh nào | `--yes` bỏ qua được? |
87
87
  |---|---|:---:|
88
- | **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
88
+ | **Không chặn** | `/review-code` · `/validate-traces` · `/debug` **KHÔNG phải vì read-only**: cả ba đều CÓ ghi file. Chúng không chặn vì thao tác ghi của chúng hoặc nằm sau một câu hỏi `(Y/N)`, hoặc nằm sau một cờ, hoặc là `append`/dựng-lại-được | — (vốn không có) |
89
89
  | **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
90
90
  | **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
91
91
 
@@ -93,6 +93,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
93
93
  `--` khỏi phần resolve target, nên cờ này không ảnh hưởng việc tìm file.) Mở đường chạy
94
94
  headless: `claude -p "/generate-code UC1 --yes"`.
95
95
 
96
+ > **Tên lệnh trong bảng trên có máy canh — `R19`.** Mỗi hàng bảng vừa nêu một mức vừa nêu
97
+ > tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
98
+ > ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
99
+ > mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
100
+ > `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
101
+
96
102
  > **KHÔNG tự suy mức từ bảng này.** Mỗi lệnh **tự khai** mức của nó ở một dòng `*Checkpoint: …*`
97
103
  > ngay dưới `## Gate` của chính nó — đọc dòng đó, đừng suy diễn. Bảng trên chỉ giải thích ba mức
98
104
  > **nghĩa là gì**.
@@ -796,7 +802,7 @@ Không tìm thấy seam/stub nào → bỏ qua im lặng.
796
802
  Với mỗi file `.tsv` đã xử lý: ghi `spec_ver`, `status`, `last_updated` đã cập nhật lại disk.
797
803
  Đồng thời **đồng bộ `uc_status` ← `@trace.status`** của file `.feature` tương ứng (header `.feature` là nguồn-sự-thật về duyệt BDD — người đặt `approved` sau khi review sạch, giống PO đặt PRD Metadata `Status`). Nhờ vậy `approved_ucs` trên dashboard phản ánh đúng thay vì luôn = 0.
798
804
  Và **đồng bộ `prd_status` ← `| **Status** |`** của PRD tương ứng (`{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md`) — đối xứng với `uc_status`: PRD Metadata là nguồn-sự-thật về duyệt PRD. Không có bước này thì `prd_status` là **write-once** (chỉ `/generate-bdd` ghi một lần) và sẽ giữ `approved` vĩnh viễn sau khi `/refine-prd` hay `/review-context --fix` reset PRD về `draft`. *(Step 4 đã đọc file PRD này rồi — không phát sinh I/O.)*
799
- **Đừng** sửa `dev_selftest`/`dev_selftest_at` (do `/dev-run-test` sở hữu) hay `qc_status`/`qc_run_at`/`qc_owner`/`qc_blocked_by` (do `/qc-run-test` + `/report-bug` sở hữu); lệnh này chỉ đọc chúng cho report.
805
+ **Đừng** sửa `dev_selftest`/`dev_selftest_at` (do `/dev-run-test` sở hữu) hay `qc_status`/`qc_run_at`/`qc_owner`/`qc_blocked_by` (do `/qc-run-script` + `/qc-run-manualtest` + `/report-bug` sở hữu); lệnh này chỉ đọc chúng cho report.
800
806
 
801
807
  ### Step 6b — Ghi mốc `spec_baseline` cho lần audit sau
802
808
 
@@ -901,7 +907,7 @@ qc_passing = rows where qc_status == pass
901
907
  qc_failing = rows where qc_status == fail
902
908
  qc_skipped = rows where qc_status == skip
903
909
  qc_not_run = rows where qc_status in (not_run, —)
904
- # qc_status is the OFFICIAL QC automation result (set by /qc-run-test),
910
+ # qc_status is the OFFICIAL QC automation result (set by /qc-run-script + /qc-run-manualtest),
905
911
  # shown alongside — never merged with — dev_selftest.
906
912
  waiting_dev = rows where qc_owner == dev # PM view: QC-found, waiting on dev to fix
907
913
  waiting_po = rows where qc_owner == po # PM view: blocked, waiting on PO to confirm/clarify
@@ -62,5 +62,5 @@ trace_tags:
62
62
  source: "# @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
63
63
  test_type: "# @trace.test_type=functional|integration|e2e|non-functional"
64
64
 
65
- # qc_status: /qc-run-test writes pass|fail|skip|not_run + qc_run_at into {trace_dir}/{UC-ID}.tsv
65
+ # qc_status: /qc-run-script writes pass|fail|skip|not_run + qc_run_at into {trace_dir}/{UC-ID}.tsv
66
66
  # (parallel to dev_selftest), surfaced in Living Docs as the OFFICIAL QC automation result.
@@ -11,7 +11,7 @@ Ba mức, định nghĩa đầy đủ ở `steps/gate.md` Bước 3a — **đây
11
11
 
12
12
  | Mức | Lệnh nào | `--yes` bỏ qua? |
13
13
  |---|---|:---:|
14
- | **Không chặn** | read-only (`/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs`) | — |
14
+ | **Không chặn** | `/review-code` · `/validate-traces` · `/debug` **không** vì read-only (cả ba đều ghi file), mà vì thao tác ghi nằm sau `(Y/N)` / sau một cờ / là `append` | — |
15
15
  | **Chặn thường** | mọi lệnh sinh/sửa artifact | ✅ |
16
16
  | **Chặn CỨNG** | ghi đè file đã có · `--resume` · migrate · prune | ❌ |
17
17
 
@@ -95,7 +95,7 @@ kém, hay một bản **dán nhãn sai**?"* — vế sau thì không `--force`
95
95
  - Field có consumer mà **không có producer** là lỗi chặn build — đó chính là hình dạng
96
96
  của G1 (`@trace.sc_version`: 3 consumer, 0 producer, DRIFT chết mà không ai báo).
97
97
  - **Làm mất hiệu lực ≠ ghi đè.** Cột trace có chủ sở hữu rõ ràng — `dev_selftest`/`dev_selftest_at`
98
- thuộc `/dev-run-test` · `qc_status`/`qc_run_at` thuộc `/qc-run-test` · `test_count`/`test_classes`
98
+ thuộc `/dev-run-test` · `qc_status`/`qc_run_at` thuộc `/qc-run-script` + `/qc-run-manualtest` · `test_count`/`test_classes`
99
99
  thuộc `/dev-gen-test` — và **chỉ chủ được ghi giá trị KHẲNG ĐỊNH** (`pass`/`fail`/số lượng).
100
100
  Nhưng lệnh nào làm giá trị đó **HẾT ĐÚNG** (spec đổi, code đổi) thì **BẮT BUỘC** hạ nó về giá
101
101
  trị "chưa biết" (`not_run` / `—`). Giữ một `pass` đã hết hiệu lực là **báo cáo sai**, không phải
@@ -8,7 +8,7 @@ adapted: danh sách lệnh theo pipeline HIỆN TẠI (6 trạm QC) · bổ sung
8
8
  # Self-Review — 3 nhóm lỗi AI cần tự kiểm trước khi in Report
9
9
 
10
10
  Skill **tự chứa**, dùng chung cho các lệnh QC: `qc-analyze` · `qc-plan` · `qc-design-test` ·
11
- `qc-review` · `qc-run-test` · `qc-report` — và hai nhánh phụ `report-bug` · `propose-scenario`.
11
+ `qc-review-testcase` · `qc-run-script` · `qc-report` — và hai nhánh phụ `report-bug` · `propose-scenario`.
12
12
 
13
13
  Mỗi file lệnh có mục `## Self-Review` **riêng**, liệt kê tiêu chí **cụ thể cho output của chính
14
14
  nó**. File này định nghĩa **3 nhóm lỗi gốc** mà mọi tiêu chí cụ thể đó phải phủ được ít nhất một
@@ -36,7 +36,7 @@ Bảng phân định hiện tại — đừng dùng self-review cho những vi
36
36
  | BR mà BDD nhắc nhưng phân tích bỏ sót | **Guard BR-tag** (so với tag `@trace.business_rules`) | `/qc-analyze` |
37
37
  | Scenario chưa có test case nào phủ | **Guard SC coverage** (đếm TC trỏ tới từng SC) | `/qc-design-test` |
38
38
  | Bảng §4.5.6 trỏ SC không tồn tại · header thiếu `@trace.testid_attr` · bảng lệch code | **T15–T18** | `bin/lint-trace.js` |
39
- | Ghi `pass` trên row `DRIFT`/`ORPHANED` | **T12** + `positive_assertion_guards` | `bin/lint-trace.js` + `/qc-run-test` |
39
+ | Ghi `pass` trên row `DRIFT`/`ORPHANED` | **T12** + `positive_assertion_guards` | `bin/lint-trace.js` + `/qc-run-script` |
40
40
  | Sổ trace sai cấu trúc / enum / trùng `sc_id` | **T1–T8** | `bin/lint-trace.js` |
41
41
 
42
42
  Còn lại — **không có nguồn đối chiếu cơ học** — mới là việc của self-review: rủi ro bịa ra,
@@ -11,7 +11,7 @@ upstream_sha: c7ca6cfb798c609f18ffe20a38f64f95c76e1919
11
11
  > Giữ một bản kém hơn làm mặc định là để người không biết có cờ nhận bản kém.
12
12
  >
13
13
  > **Một chỗ CỐ Ý khác upstream:** mức nặng nhất dùng từ **`Blocker`**, không phải `Critical`.
14
- > Lý do: `/qc-run-test` đọc `🔴 Blocker` để đặt *"scenario đang chờ PO"* vào sổ kết quả trace.
14
+ > Lý do: `/qc-run-script` đọc `🔴 Blocker` để đặt *"scenario đang chờ PO"* vào sổ kết quả trace.
15
15
  > Đổi từ là đứt liên kết đó. Ba mức còn lại giữ nguyên upstream.
16
16
  >
17
17
  > **Phạm vi: MỘT file cho cả (PRD × nền)** *(B11)*, không phải một file mỗi UC. Đây là quay về
@@ -18,7 +18,7 @@ có cấu trúc, đủ thông tin để người nhận trả lời được nga
18
18
  > mỗi UC là các hàng phân biệt bằng cột `UC`. Không còn một-file-mỗi-UC.
19
19
  >
20
20
  > **Một chỗ cố ý khác upstream:** mức nặng nhất dùng `🔴 Blocker`, không phải `Critical` —
21
- > `/qc-run-test` đọc đúng từ đó để đặt *"scenario đang chờ PO"* vào sổ trace.
21
+ > `/qc-run-script` đọc đúng từ đó để đặt *"scenario đang chờ PO"* vào sổ trace.
22
22
 
23
23
  ## Đầu vào
24
24
 
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: automation-feasibility-matrix
3
+ description: Đánh giá từng test case đã APPROVED là Automatable Y/N, kèm lý do chuẩn hoá và %Automated/Total. Dùng bởi /qc-automation-assess.
4
+ ---
5
+
6
+ # Automation Feasibility Matrix
7
+
8
+ Skill **tự chứa** cho `/qc-automation-assess`: đánh giá từng TC trong `TC_<FEATURE>.Test.md` đã
9
+ qua cổng `/qc-review-testcase` là `Automatable: Y/N`, kèm lý do chuẩn hoá và `%Automated/Total`.
10
+
11
+ ## Khi nào trigger
12
+
13
+ Sau `/qc-review-testcase` — TC đã `APPROVED` và chưa từng qua automation-assess, **hoặc** TC bị
14
+ gắn cờ `🔄 Re-assess` vì scenario nó verify đang `DRIFT` (BDD/spec đã đổi).
15
+
16
+ ## Tiêu chí đánh giá — trả lời TUẦN TỰ, dừng ở câu đầu tiên là "Có"
17
+
18
+ Câu nào trả lời "Có" thì **đó là lý do `N`**, và không cần xét tiếp:
19
+
20
+ 1. **Có bước nào đòi input từ con người / bên thứ ba mà script không tự lấy được?**
21
+ (OTP SMS thật · captcha · chữ ký tay · sinh trắc học trên thiết bị thật)
22
+ → `N`, nhãn **`Cần OTP/captcha thủ công`**
23
+ 2. **Có phụ thuộc hệ thống / thiết bị ngoài tầm kiểm soát của script?**
24
+ (app khác trên máy thật · máy POS vật lý · email/SMS thật không có test inbox)
25
+ → `N`, nhãn **`Phụ thuộc hệ thống ngoài`**
26
+ 3. **UI/flow có đang thay đổi liên tục?** (redesign · A/B test). Script viết hôm nay nhiều khả
27
+ năng vỡ trong < 2 tuần vì một thay đổi UI **đã biết trước**
28
+ → `N`, nhãn **`UI không ổn định`** — ghi rõ mốc dự kiến ổn định để re-assess
29
+ 4. **Element cần thao tác có test-id ổn định không, và dev có cam kết thêm nếu thiếu không?**
30
+ Không có **VÀ** không có cam kết → `N`, nhãn **`Thiếu test-id contract``**
31
+ > Khác với ca *"sẽ có nhưng chưa"* — ca đó vẫn `Y`, ghi chú chờ `IMPROVE-xxx`.
32
+ 5. **ROI có dương không?** Áp công thức dưới; âm rõ ràng → `N`, nhãn **`Effort > ROI`**
33
+ 6. Không rơi vào 1–5 → **`Y`**
34
+
35
+ ## Công thức ROI *(ước lượng nhanh, không cần chính xác tuyệt đối)*
36
+
37
+ ```
38
+ ROI ≈ (tần suất chạy lại × chi phí test tay mỗi lần)
39
+ − (chi phí viết script + chi phí bảo trì dự kiến)
40
+ ```
41
+
42
+ | Tín hiệu ROI **thấp** | Tín hiệu ROI **cao** |
43
+ |---|---|
44
+ | TC chỉ chạy **một lần** (migration một-lần, config set một lần) — viết script tốn hơn chạy tay 1 lần | TC có **nhiều biến thể dữ liệu** (boundary/negative): test tay tốn tuyến tính theo số biến thể, script chạy lại gần như miễn phí |
45
+
46
+ **Thứ tự ưu tiên khi có nhiều TC `Y` mà chưa đủ thời gian làm hết:** `P0` trước, rồi `P1`/`P2`.
47
+ TC `P0` gần như luôn ROI dương và là ứng viên trực tiếp cho smoke suite (`/qc-smoke-test` chạy
48
+ mỗi build).
49
+
50
+ > ⚠️ **`P0` mà rơi vào `N` là tín hiệu đáng chú ý hơn bình thường.** Tính năng lõi không có
51
+ > smoke test tự động là rủi ro cao cho cả mục tiêu *"phát hiện lỗi sớm mỗi build"*. Ghi rõ lý do
52
+ > **và** cân nhắc đề xuất `IMPROVE-xxx` để gỡ rào cản, thay vì chấp nhận `N` vĩnh viễn.
53
+
54
+ ## Tín hiệu ổn định — dùng cho tiêu chí 3
55
+
56
+ | Ổn định | KHÔNG ổn định |
57
+ |---|---|
58
+ | Màn hình đã ship ≥ 1 release, không đổi lớn gần đây | Đang trong sprint thiết kế lại UI |
59
+ | Có test-id contract §4.5.6 đã chốt | Element identify bằng text/class tạm thời |
60
+ | Flow nghiệp vụ ổn định | Business rule đang thử nghiệm (feature flag % rollout) |
61
+
62
+ ## Guard — Re-assessment tự động theo `DRIFT`
63
+
64
+ TC có scenario `@trace.verifies={UC-ID}-SC{N}` mà row đó trong sổ trace đang `status: DRIFT`
65
+ → **re-assess lại từ đầu 6 tiêu chí**, KHÔNG tái dùng phán quyết cũ.
66
+
67
+ Vì sao không tái dùng: spec đổi có thể đổi **cả sáu** câu hỏi — ví dụ một BR mới thêm bước OTP
68
+ biến một TC đang `Y` thành `N`.
69
+
70
+ | Đổi | Xử lý cột `Script file` |
71
+ |---|---|
72
+ | `Y → N` | **GIỮ** path cũ + ghi chú `⚠️ Script đã lỗi thời — cân nhắc gỡ ở lần /qc-design-script kế tiếp`. **KHÔNG tự xoá file** — để người quyết định |
73
+ | `N → Y` | giữ `—`, chờ `/qc-design-script` điền |
74
+
75
+ ## Output format
76
+
77
+ ```markdown
78
+ # Automation Assessment — {TICKET-ID} ({active_platform})
79
+
80
+ | TC ID | UC | Automatable | Lý do (nếu N) | Trace SC | Script file | Ghi chú |
81
+ |---|---|:---:|---|---|---|---|
82
+ | TC_LOGIN_001 | UC1 | Y | — | UC1-SC1 | — *(chưa qua qc-design-script)* | |
83
+ | TC_LOGIN_004 | UC1 | N | Cần OTP/captcha thủ công | UC1-SC4 | — *(không automate)* | Giữ trong bộ manual |
84
+ | TC_LOGIN_002 | UC1 | Y | — | UC1-SC2 | — *(chưa qua qc-design-script)* | 🔄 Re-assess (DRIFT, spec đổi {ngày}) — đã re-check: vẫn Y |
85
+
86
+ **%Automated/Total: {automatable}/{đã đánh giá} = {pct}%**
87
+ **Loại khỏi lượt:** {k} TC của UC chưa APPROVED — {danh sách UC + trạng thái thật}
88
+ ```
89
+
90
+ ### Cột `Script file` — ai ghi, khi nào
91
+
92
+ ```
93
+ /qc-automation-assess → luôn khởi tạo "—" (script chưa tồn tại ở bước này)
94
+ /qc-design-script → ĐIỀN path thật sau khi sinh
95
+ /qc-run-script → ĐỌC cột này để biết chạy file nào — KHÔNG tự suy path
96
+ ```
97
+
98
+ Đây là **chỉ mục ngược duy nhất** từ TC → file code thật; chiều xuôi (code → SC) đã có sẵn qua
99
+ tag `@trace.verifies`. Không có cột này thì `/qc-run-script` phải suy đường dẫn từ quy ước đặt
100
+ tên — suy sai thì chạy sai bộ test, hoặc **chạy 0 test mà vẫn báo xanh**.
101
+
102
+ > **Đường dẫn theo stack HIỆN TẠI** — module `qc-playwright` (Python + pytest-playwright):
103
+ > `tests/<project>/test_<feature>.py` + `pages/<feature>_page.py`, theo
104
+ > `modules/qc-playwright/stack-profile.yaml` §layout.
105
+ >
106
+ > *(Đề xuất gốc của đội QC viết theo TypeScript + Playwright Test / WebdriverIO. Việc đổi stack
107
+ > là một bước RIÊNG, cố ý tách khỏi đợt tách lệnh — xem quyết định F3, Đợt 2 · b2. Khi stack
108
+ > đổi, chỉ đoạn này và `stack-profile.yaml` cần sửa; cơ chế cột `Script file` không đổi.)*
109
+
110
+ ## Nhãn lý do mới phát sinh
111
+
112
+ Không khớp nhãn nào trong 5 nhãn chuẩn → **tạo nhãn mới mô tả đúng lý do** *(đừng ép vào nhãn
113
+ có sẵn)*, rồi liệt kê nó trong report để bổ sung vào danh sách lần sau.
114
+
115
+ > **Vì sao chuẩn hoá nhãn.** Để **đếm được**. *"3 TC không automate vì **thiếu test-id**"* là
116
+ > một tín hiệu hành động được — đi đàm phán với dev. *"3 TC vì lý do kỹ thuật"* thì không.
117
+ >
118
+ > Riêng nhãn `Thiếu test-id contract` nối thẳng với Đợt 0 (hợp đồng test-id §4.5.6): nếu Đợt 0
119
+ > làm đúng thì nhãn này phải **giảm dần theo thời gian** — tức nó đồng thời là **phép đo cho
120
+ > chính Đợt 0**.
@@ -43,4 +43,4 @@ Mỗi journey → 1 TC bám Format; Expected = chuỗi verify point; chuẩn b
43
43
 
44
44
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 6 E2E**. Mỗi journey một TC; tiền điều kiện · kết quả/định tuyến kỳ vọng · BR · phụ thuộc gap · priority ghi dạng trường danh sách.
45
45
 
46
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
46
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -43,4 +43,4 @@ Chuyển draft → TC chính thức bám **format file `TC_<FEATURE>.Test.md`**:
43
43
 
44
44
  Ghi TC đã chuyển thành functional vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 3 Functional**.
45
45
 
46
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
46
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -111,4 +111,4 @@ Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 1 En
111
111
 
112
112
  File này chỉ sinh khi có cờ `--api` hoặc `--all`. Mẫu TC: `../api/endpoint.md` · chuỗi auth: `../api/auth-chain.md` · tra mã: `../api/http-status-codes.md` · header: `../api/common-headers.md`.
113
113
 
114
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
114
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -46,4 +46,4 @@ Liệt kê các màn/route + thứ tự điều hướng · state/dữ liệu tr
46
46
 
47
47
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 3 Functional** (luồng đa màn trong cùng một feature).
48
48
 
49
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
49
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -51,4 +51,4 @@ chức năng (input/action/display/nav) · constraint (required/min-max/format/e
51
51
 
52
52
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 1 GUI** · **Nhóm 2 Validation** · **Nhóm 3 Functional**.
53
53
 
54
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
54
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -46,4 +46,4 @@ Nhóm TC: happy (dữ liệu đúng đầu→cuối) → contract negative (inpu
46
46
 
47
47
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ưu tiên P0 cho định tuyến & tiền-dữ liệu. Chuỗi gọi phụ thuộc nhau: `../api/crud-sequence.md`.
48
48
 
49
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
49
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -42,4 +42,4 @@ Nhóm TC: ghi đúng giá trị (happy) → default/null đúng → update khôn
42
42
 
43
43
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ghi rõ query kiểm tra DB + yêu cầu cleanup; không hardcode ID, chuẩn bị/dọn data qua fixture (3 mức teardown: `../shared/precision-rules.md` §8).
44
44
 
45
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
45
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -44,4 +44,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 4 Integration (qua UI)**. Đây là tầng verify dòng dữ liệu API → giao diện, nên **vẫn thuộc file giao diện**: bỏ UI đi thì TC mất nghĩa.
46
46
 
47
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
47
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -44,4 +44,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Mỗi TC ghi topic, key, payload cần verify + hành vi consumer.
46
46
 
47
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
47
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -44,4 +44,4 @@ Trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào file theo cùng câu hỏi phân file *"verify được mà không cần UI?"*: a11y · responsive · touch-target → `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` **Nhóm 5 NFR**; tải/hiệu năng/bảo mật ở tầng API → `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md`. Mỗi TC ghi tiêu chí đo + ngưỡng + công cụ, đơn vị theo `../shared/precision-rules.md` §3.
46
46
 
47
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
47
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -5,7 +5,12 @@ ported_from: ui-automation-testing
5
5
  upstream_path: skills/qa-tc-designer/shared/tc-metadata-format.md
6
6
  upstream_sha: a31d66a7a8dab19cf821c9102a88282b09e16cb9
7
7
  ---
8
- # TC Metadata Format (Chuẩn chung)
8
+ # TC Metadata Format
9
+
10
+ > **`Automatable` KHÔNG phải một field của `.Test.md`.** Quyết định *"TC này máy chạy được hay
11
+ > phải chạy tay"* sống ở **đúng một chỗ**: `{qc_artifact_dir}AUTOMATION_ASSESSMENT.md`, do
12
+ > `/qc-automation-assess` ghi. Đừng chép giá trị đó vào đây — hai nơi ghi cùng một quyết định
13
+ > thì một nơi sẽ lệch, và lúc đó không ai biết nơi nào đúng. (Chuẩn chung)
9
14
 
10
15
  ## ⚠️ Nguyên tắc format file TC (BẮT BUỘC — QC yêu cầu)
11
16
 
@@ -205,7 +210,7 @@ Mọi thứ trên là chuẩn của đội QC. Bốn thứ dưới đây là **c
205
210
  **Câu hỏi phân file:** *"TC này verify được mà **không cần UI** không?"*
206
211
  → **có** = file API · **không** = file giao diện. *(Trùng Bước 2 của `skill-decision-tree.md`.)*
207
212
 
208
- ⚠️ **Đuôi file là `.Test.md`, không phải `.md`.** `/qc-run-test` và `/qc-review` tìm `*.Test.md`;
213
+ ⚠️ **Đuôi file là `.Test.md`, không phải `.md`.** `/qc-design-script` và `/qc-review-testcase` tìm `*.Test.md`;
209
214
  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.
210
215
 
211
216
  Đánh số `TC_<FEATURE>_NNN` **liên tục toàn file**, không đánh lại theo từng nhóm.
@@ -215,7 +220,7 @@ ghi ra file thiếu phần `.Test` là ghi ra thứ **không trạm nào tìm th
215
220
  | Trường | Dạng | Vì sao cần |
216
221
  |---|---|---|
217
222
  | `**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ụ |
218
- | `**@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 |
223
+ | `**@trace.verifies:**` | `{UC-ID}-SC{N}` (lấy từ `@trace.scenario` của file `.feature`) | **join key** để `/qc-run-script` ghi `qc_status` theo từng kịch bản vào sổ trace |
219
224
 
220
225
  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
221
226
  vẫn chạy, vẫn pass/fail, nhưng không ai biết nó phủ kịch bản nào.
@@ -241,7 +246,7 @@ Nguồn & phiên bản: BDD {UC-ID} `<vX.Y>` · tech-doc `<rev | —>`
241
246
  ```
242
247
 
243
248
  Lấy `<vX.Y>` từ `| **Version** |` ở header `.feature` của **chính UC này**, và `<rev>` từ header
244
- tech-doc gộp. `/qc-review` và `/qc-run-test` **so** khối này với version hiện tại để biết bộ TC còn
249
+ tech-doc gộp. `/qc-review-testcase` và `/qc-design-script` **so** khối này với version hiện tại để biết bộ TC còn
245
250
  khớp spec không (`steps/qc-stamp.md` · `bin/trace-schema.json` → `qc_artifact_stamp`).
246
251
 
247
252
  **Vì sao cần, khi sổ trace đã có `qc_status`.** `/generate-bdd` hạ `qc_status → not_run` khi spec đổi
@@ -259,8 +264,8 @@ Test-ID attribute: {attr}
259
264
  ```
260
265
 
261
266
  Đọc `@trace.testid_attr` từ header tech-doc gộp (do `/map-testids` ghi). Bảng §4.5.6 chỉ cho
262
- **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
263
- locator, `/qc-review` cần nó để biết selector trong script có đúng hợp đồng không.
267
+ **giá trị** test-id; đây là **tên thuộc tính** chứa chúng. `/qc-design-script` cần nó để cấu hình
268
+ locator, `/qc-review-script` cần nó để biết selector trong script có đúng hợp đồng không.
264
269
 
265
270
  Thiếu field trong tech-doc → ghi `Test-ID attribute: — (thiếu @trace.testid_attr, chạy /map-testids)`.
266
271
  **Đừ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
@@ -92,4 +92,4 @@ Severity: 🔴 fix ngay (missing cleanup, dữ liệu không verify cross-module
92
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
93
  Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
94
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`.
95
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-design-script`.
@@ -47,7 +47,7 @@ Review session note sau khi test, coaching QC cải thiện kỹ năng.
47
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
48
  Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
49
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`.
50
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-design-script`.
51
51
  Mỗi tiêu chí: ✅/⚠️/❌ + feedback cụ thể
52
52
  Top 3 improvement suggestions (coaching tone)
53
53
  Đề xuất charter tiếp theo nếu chưa đủ coverage
@@ -106,4 +106,4 @@ Severity: 🔴 fix ngay (sai logic, POM breach, silent fail) · 🟠 quan trọn
106
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
107
  Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
108
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`.
109
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-design-script`.
@@ -96,4 +96,4 @@ Severity: 🔴 fix ngay (mock thay real call, missing DB verify, no cleanup) ·
96
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
97
  Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
98
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`.
99
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-design-script`.
@@ -131,4 +131,4 @@ Severity: 🔴 fix ngay (assertion không có ngưỡng, gọi production endpoi
131
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
132
  Khuôn + quy tắc ghi: `../shared/review-file-template.md`.
133
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`.
134
+ **KHÔNG tự sửa code** — chỉ nêu `file:line` + cách sửa. Người sửa là `/qc-design-script`.
@@ -31,7 +31,7 @@ upstream_sha: bd596393ecc016cbea106835681a4979c0a9ca0e
31
31
  giữa tài-liệu-nền-cũ và PRD đã duyệt là **lệch đồng bộ, KHÔNG chặn** — không phải mâu thuẫn
32
32
  chặn. *(Khung "gap thật = QA KHÔNG tự quyết được" — xem `steps/gap-verify.md`.)*
33
33
  - **KHÔNG tự sửa** kịch bản hay code. Chỉ nhận xét, chấm điểm, và nêu cụ thể sửa gì. Người sửa là
34
- trạm 3 (`/qc-design-test`) hoặc trạm 5 (`/qc-run-test`).
34
+ trạm 3 (`/qc-design-test`) hoặc trạm 5 (`/qc-run-script`).
35
35
 
36
36
  ## Kiểm tra cấu trúc TC (bắt buộc mỗi vòng)
37
37
 
@@ -126,7 +126,7 @@ soát:
126
126
  ```
127
127
 
128
128
  ⚠️ **Tên file review KHÔNG có đuôi `.Test.md`.** Đuôi đó là của file test case; gắn vào file
129
- review sẽ làm `/qc-run-test` nhặt nó lên như một file test case rồi cố sinh script từ một bảng
129
+ review sẽ làm `/qc-design-script` nhặt nó lên như một file test case rồi cố sinh script từ một bảng
130
130
  điểm.
131
131
 
132
132
  - **Chưa tồn tại** → `Write` toàn bộ khuôn bên dưới, điền hàng của tầng vừa soát, các tầng khác
@@ -147,7 +147,7 @@ review sẽ làm `/qc-run-test` nhặt nó lên như một file test case rồi
147
147
  ```markdown
148
148
  # Review Report — <FEATURE>
149
149
 
150
- > Sinh bởi /qc-review. Cập nhật sau mỗi vòng soát. Bảng Tổng quan tích luỹ theo vòng.
150
+ > Sinh bởi /qc-review-testcase hoặc /qc-review-script (mỗi vai một file). Cập nhật sau mỗi vòng soát. Bảng Tổng quan tích luỹ theo vòng.
151
151
 
152
152
  ## Tổng quan
153
153
 
@@ -12,7 +12,7 @@ Review bộ TC end-to-end và đánh giá chất lượng.
12
12
 
13
13
  ## Khi nào trigger
14
14
  - "review TC E2E cho [Feature]" / "check coverage E2E"
15
- - Sau khi qa-designer/e2e/journey xong, trước khi /qc-run-test
15
+ - Sau khi qa-designer/e2e/journey xong, trước khi /qc-design-script
16
16
 
17
17
  ## Khi KHÔNG trigger
18
18
  - Review TC functional 1 màn → `test-case/functional`
@@ -12,7 +12,7 @@ Review bộ functional TC và đánh giá chất lượng.
12
12
 
13
13
  ## Khi nào trigger
14
14
  - "review TC cho [Feature]" / "check coverage"
15
- - Sau khi qa-designer xong, trước khi PO approve hoặc trước khi /qc-run-test
15
+ - Sau khi qa-designer xong, trước khi PO approve hoặc trước khi /qc-design-script
16
16
 
17
17
  ## Khi KHÔNG trigger
18
18
  - Review Python script → dùng qa-reviewer
@@ -12,7 +12,7 @@ Review bộ TC tích hợp (GUI↔Backend, API, DB) và đánh giá chất lư
12
12
 
13
13
  ## Khi nào trigger
14
14
  - "review TC integration cho [Feature]" / "check TC tích hợp"
15
- - Sau khi qa-designer/integration/* xong, trước khi /qc-run-test
15
+ - Sau khi qa-designer/integration/* xong, trước khi /qc-design-script
16
16
 
17
17
  ## Khi KHÔNG trigger
18
18
  - Review TC functional 1 màn/endpoint → `test-case/functional`
@@ -12,7 +12,7 @@ Review bộ TC phi chức năng (performance, security, accessibility, compatibi
12
12
 
13
13
  ## Khi nào trigger
14
14
  - "review TC non-functional cho [Feature]" / "check TC hiệu năng/bảo mật/accessibility"
15
- - Sau khi qa-designer/non-functional xong, trước khi /qc-run-test
15
+ - Sau khi qa-designer/non-functional xong, trước khi /qc-design-script
16
16
 
17
17
  ## Khi KHÔNG trigger
18
18
  - Review TC chức năng → `test-case/functional`
@@ -30,7 +30,7 @@ Journey còn phụ thuộc gap → tạo test `@pytest.mark.skip(reason="GAP-UC{
30
30
 
31
31
  ## Phase 3 — Verify
32
32
  `py_compile` + `pytest --collect-only -q` · chạy (môi trường staging + CRM) · cập nhật Status TC.
33
- **Phân loại FAIL — 3 nhãn, luật ở `/qc-run-test` §Chạy lại trước khi kết luận** (chạy lại ×2 trước, rồi người xác nhận; **không chép lại luật ở đây**). Đặc thù E2E: journey fail vì 1 bước feature chưa wire = `product-gap` (giữ FAIL/skip + bằng chứng), không phải lỗi script; sai selector/state → `script-bug`. Journey dài qua nhiều bước **dễ ra `flaky` hơn test đơn lẻ** — một bước chậm bất thường là đủ; nên đừng vội gọi `product-gap` khi chưa chạy lại.
33
+ **Phân loại FAIL — 3 nhãn, luật ở `/qc-run-script` §Chạy lại trước khi kết luận** (chạy lại ×2 trước, rồi người xác nhận; **không chép lại luật ở đây**). Đặc thù E2E: journey fail vì 1 bước feature chưa wire = `product-gap` (giữ FAIL/skip + bằng chứng), không phải lỗi script; sai selector/state → `script-bug`. Journey dài qua nhiều bước **dễ ra `flaky` hơn test đơn lẻ** — một bước chậm bất thường là đủ; nên đừng vội gọi `product-gap` khi chưa chạy lại.
34
34
 
35
35
  ## Output
36
36
  Script `tests/<project>/e2e/test_<feature>.py` + Page Object/client tái dùng. Bàn giao `qa-reviewer`.
@@ -46,4 +46,4 @@ Report = **Playwright Trace viewer + pytest-html** (KHÔNG Allure, KHÔNG dashbo
46
46
  - HTML report: `reports/<feature>/report.html` (self-contained, mở trực tiếp).
47
47
  - Trace từng test (debug step-by-step): `python3 -m playwright show-trace test-results/<nodeid>/trace.zip`.
48
48
  - Tóm tắt: **TOTAL / PASS / FAIL / SKIP** + duration.
49
- 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-test` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
49
+ 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-script` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
@@ -22,7 +22,7 @@ Skill **tự chứa**: convert `.Test.md` feature span ≥2 màn → Python pyte
22
22
 
23
23
  ## Phase 1 — Clarify
24
24
  Đọc `.Test.md` · liệt kê các màn/PO cần · state truyền giữa màn · fixture dựng tiền điều kiện (data qua nhiều bước).
25
- **Locator: đọc hợp đồng TRƯỚC, dò DOM là bước cuối.** Thứ tự bắt buộc (luật đầy đủ + lý do ở `/qc-run-test` §Role & stack — **không chép lại ở đây**):
25
+ **Locator: đọc hợp đồng TRƯỚC, dò DOM là bước cuối.** Thứ tự bắt buộc (luật đầy đủ + lý do ở `/qc-design-script` §Role & stack — **không chép lại ở đây**):
26
26
 
27
27
  1. **Test-id contract** — bảng *Test Selectors* §4.5.6 của tech-doc gộp, lọc theo cột "Serves SC" khớp SC của UC này. TÊN thuộc tính đọc từ `@trace.testid_attr` ở header tech-doc (đừng suy từ platform). Feature đa màn: một UC chạm nhiều màn nhưng **vẫn một bảng §4.5.6** cho cả platform — lọc theo SC, không theo màn.
28
28
  2. **Role + accessible name** — cho element có action mà §4.5.6 chưa phủ.
@@ -38,7 +38,7 @@ Phủ TC điều hướng forward/back/giữ-reset state. Data từ `test_data/`
38
38
  ## Phase 3 — Verify
39
39
  `py_compile` + `pytest --collect-only -q` (**số collect = tổng TC**; thiếu → sinh nốt) · chạy · cập nhật Status TC (verify KHÔNG còn Draft) · in mapping.
40
40
  **Gom nhóm role/account** tự áp qua `utils/test_ordering.py` (root conftest); fixture auth mới → `register_auth_fixtures([...])`. ⚠️ Run dài bị **WSL suspend** có thể gây flaky login/timeout → re-run TC đó + merge report.
41
- **Phân loại FAIL — 3 nhãn, luật ở `/qc-run-test` §Chạy lại trước khi kết luận** (chạy lại ×2 trước, rồi người xác nhận; **không chép lại ở đây**). Đặc thù đa màn: sai selector/logic → `script-bug`, sửa & chạy lại; feature chưa wire/defect **đỏ nhất quán** → `product-gap`, giữ FAIL + ghi bằng chứng vào khối "Kết quả thực thi" đầu `.Test.md`, không fake-pass. **State truyền giữa màn là nguồn `flaky` phổ biến** — điều hướng nhanh hơn/chậm hơn một nhịp là đủ đổi kết quả; ghi nghi vấn đó vào phần nguyên nhân.
41
+ **Phân loại FAIL — 3 nhãn, luật ở `/qc-run-script` §Chạy lại trước khi kết luận** (chạy lại ×2 trước, rồi người xác nhận; **không chép lại ở đây**). Đặc thù đa màn: sai selector/logic → `script-bug`, sửa & chạy lại; feature chưa wire/defect **đỏ nhất quán** → `product-gap`, giữ FAIL + ghi bằng chứng vào khối "Kết quả thực thi" đầu `.Test.md`, không fake-pass. **State truyền giữa màn là nguồn `flaky` phổ biến** — điều hướng nhanh hơn/chậm hơn một nhịp là đủ đổi kết quả; ghi nghi vấn đó vào phần nguyên nhân.
42
42
 
43
43
  ## Output
44
44
  Script + nhiều Page Object (mỗi màn) trong `pages/<project>/...`. Bàn giao `qa-reviewer` (script).
@@ -54,4 +54,4 @@ Report = **Playwright Trace viewer + pytest-html** (KHÔNG Allure, KHÔNG dashbo
54
54
  - HTML report: `reports/<feature>/report.html` (self-contained, mở trực tiếp).
55
55
  - Trace từng test (debug step-by-step): `python3 -m playwright show-trace test-results/<nodeid>/trace.zip`.
56
56
  - Tóm tắt: **TOTAL / PASS / FAIL / SKIP** + duration.
57
- 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-test` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
57
+ 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-script` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
@@ -23,7 +23,7 @@ Skill **tự chứa**: convert `.Test.md` (1 màn) → Python pytest + Playwrigh
23
23
 
24
24
  ## Phase 1 — Clarify
25
25
  Đọc `.Test.md` (confirm Reviewed) · platform (web Playwright/mobile) · Page Object đã có chưa → tạo nếu cần · fixture setup data?
26
- **Locator: đọc hợp đồng TRƯỚC, dò DOM là bước cuối.** Thứ tự bắt buộc (luật đầy đủ + lý do ở `/qc-run-test` §Role & stack — **không chép lại ở đây**):
26
+ **Locator: đọc hợp đồng TRƯỚC, dò DOM là bước cuối.** Thứ tự bắt buộc (luật đầy đủ + lý do ở `/qc-design-script` §Role & stack — **không chép lại ở đây**):
27
27
 
28
28
  1. **Test-id contract** — bảng *Test Selectors* §4.5.6 của tech-doc gộp, lọc theo cột "Serves SC" khớp SC của UC này. TÊN thuộc tính đọc từ `@trace.testid_attr` ở header tech-doc (đừng suy từ platform).
29
29
  2. **Role + accessible name** — cho element có action mà §4.5.6 chưa phủ.
@@ -41,7 +41,7 @@ Map nhóm GUI→`TestFeatureUI`, Functional→`TestFeatureFunctional`, Negative
41
41
  **Gom nhóm role/account**: thứ tự chạy đã tự gom cùng (role, account) liền nhau qua `utils/test_ordering.py` (hook ở root conftest) — fixture auth mới thì `register_auth_fixtures([...])`.
42
42
  ⚠️ Run dài có thể bị **WSL suspend** (máy ngủ) làm vài TC lỗi login/timeout = flaky (không phải gap SP) → re-run đúng các TC đó + merge vào report (xem `report/report.md`).
43
43
  **Verify KHÔNG còn Draft**: `grep -c "Status: Draft" <file>.Test.md` = 0 trước khi bàn giao.
44
- **Mỗi FAIL phân loại theo 3 nhãn — luật ở `/qc-run-test` §Chạy lại trước khi kết luận** (chạy lại ×2 trước, rồi người xác nhận; **không chép lại ở đây**). Đặc thù màn đơn: sai selector/expectation → `script-bug`, sửa script & chạy lại; feature không phản hồi sau timeout **và đỏ nhất quán qua các lần chạy lại** → `product-gap`, giữ FAIL + ghi bằng chứng (không fake-pass); timeout **chỉ xảy ra một số lần** → `flaky`, đừng ghi `fail`.
44
+ **Mỗi FAIL phân loại theo 3 nhãn — luật ở `/qc-run-script` §Chạy lại trước khi kết luận** (chạy lại ×2 trước, rồi người xác nhận; **không chép lại ở đây**). Đặc thù màn đơn: sai selector/expectation → `script-bug`, sửa script & chạy lại; feature không phản hồi sau timeout **và đỏ nhất quán qua các lần chạy lại** → `product-gap`, giữ FAIL + ghi bằng chứng (không fake-pass); timeout **chỉ xảy ra một số lần** → `flaky`, đừng ghi `fail`.
45
45
 
46
46
  ## Output
47
47
  Script `tests/<project>/.../test_<screen>.py` + Page Object `pages/<project>/.../<Screen>Page.py` (nếu mới).
@@ -58,4 +58,4 @@ Report = **Playwright Trace viewer + pytest-html** (KHÔNG Allure, KHÔNG dashbo
58
58
  - HTML report: `reports/<feature>/report.html` (self-contained, mở trực tiếp).
59
59
  - Trace từng test (debug step-by-step): `python3 -m playwright show-trace test-results/<nodeid>/trace.zip`.
60
60
  - Tóm tắt: **TOTAL / PASS / FAIL / SKIP** + duration.
61
- 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-test` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
61
+ 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-script` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
@@ -44,4 +44,4 @@ Report = **Playwright Trace viewer + pytest-html** (KHÔNG Allure, KHÔNG dashbo
44
44
  - HTML report: `reports/<feature>/report.html` (self-contained, mở trực tiếp).
45
45
  - Trace từng test (debug step-by-step): `python3 -m playwright show-trace test-results/<nodeid>/trace.zip`.
46
46
  - Tóm tắt: **TOTAL / PASS / FAIL / SKIP** + duration.
47
- 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-test` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
47
+ 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-script` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu vào Status/khối kết quả của `.Test.md`.
@@ -46,4 +46,4 @@ Report = **Playwright Trace viewer + pytest-html** (KHÔNG Allure, KHÔNG dashbo
46
46
  - HTML report: `reports/<feature>/report.html` (self-contained, mở trực tiếp) + số đo thực tế.
47
47
  - Trace từng test (debug step-by-step): `python3 -m playwright show-trace test-results/<nodeid>/trace.zip`.
48
48
  - Tóm tắt: **TOTAL / PASS / FAIL / SKIP** + duration.
49
- 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-test` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu + số đo vào Status/khối kết quả của `.Test.md`.
49
+ 3. TC Fail → mở trace tương ứng để xem timeline/DOM snapshot/network, phân loại theo **3 nhãn** (`script-bug` · `product-gap` · `flaky`) — luật đầy đủ + bước chạy lại ×2 ở `/qc-run-script` §Chạy lại trước khi kết luận, **không chép lại ở đây**; ghi mô tả lỗi tiếng Việt dễ hiểu + số đo vào Status/khối kết quả của `.Test.md`.
@@ -190,7 +190,7 @@ services:
190
190
  - Override `paths.bug_reports_dir` → `{spec_source}/feedback/bug-reports`
191
191
  - Override `paths.bdd_proposals_dir` → `{spec_source}/feedback/bdd-proposals`
192
192
  - Override `paths.prd_change_requests_dir` → `{spec_source}/feedback/prd-change-requests`
193
- - Override `paths.trace_dir` → `{spec_source}/.trace` — **luôn khi `spec_source` được đặt.** Trace TSV được gộp vào spec repo (một nơi authoritative duy nhất, không tách theo service) để PM/PO có một chỗ duy nhất quản lý trạng thái. Cấu trúc bên trong: `.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv`. Các lệnh phía code (`/generate-code`, `/dev-run-test`, `/qc-run-test`) chạy từ `service_root` nhưng **ghi trace row của chúng vào `{spec_source}/.trace/{domain}/{prd-slug}/`** — giống như chúng đã push `feedback/` vào đó. *(`.trace` theo service chỉ khi không có `spec_source`.)*
193
+ - Override `paths.trace_dir` → `{spec_source}/.trace` — **luôn khi `spec_source` được đặt.** Trace TSV được gộp vào spec repo (một nơi authoritative duy nhất, không tách theo service) để PM/PO có một chỗ duy nhất quản lý trạng thái. Cấu trúc bên trong: `.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv`. Các lệnh phía code (`/generate-code`, `/dev-run-test`, `/qc-run-script`) chạy từ `service_root` nhưng **ghi trace row của chúng vào `{spec_source}/.trace/{domain}/{prd-slug}/`** — giống như chúng đã push `feedback/` vào đó. *(`.trace` theo service chỉ khi không có `spec_source`.)*
194
194
  - Override `paths.refinement_dir` → `{spec_source}/.agent/review` — **luôn khi `spec_source` được đặt.** Findings review (`/refine-prd`, `/review-context`, `/review-tech-docs`) là artifact liên-team *về* tài liệu trong spec repo (PRD/BDD/tech-design) — thuộc cùng khu vực ghi với `.trace/` và `feedback/`. Các lệnh review chạy từ working dir của service (BE repo) nhưng **ghi findings vào `{spec_source}/.agent/review/`**, KHÔNG phải `.agent/review` của service repo. Bên trong flat, phân biệt bằng tên file đã prefix `{prd-slug}`/`{UC-ID}`/`{TICKET-ID}`. *(`.agent/review` theo service chỉ khi không có `spec_source`.)*
195
195
 
196
196
  > **Vì sao đặt dưới `spec_source`:** PRD, BDD, tech-docs, design-spec, domain knowledge, feedback của tester, **trạng thái coverage `.trace/`**, **và findings review `.agent/review/`** đều là **artifact liên team** — chúng nằm trong **spec repo dùng chung** theo bố cục feature-package để mọi umbrella (FE/App/BE) và PM đọc từ một nguồn qua `/sync`. Trong bố cục feature-package, một folder `specs/{domain}/{prd-slug}/` gom tất cả loại artifact của một PRD, giúp spec repo tự đủ và dễ điều hướng theo feature. Service submodule chỉ chứa **code** (+ tooling build/test). `.trace/`, `.agent/review/` và `feedback/` là khu vực **ghi** của dev/QC/reviewer trong spec repo. Ở chế độ single-service (không có `spec_source`), mọi thứ mặc định dưới gốc repo — vẫn là một repo.