@educa-corp/sdd-framework 0.9.6 → 0.9.8

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 (147) hide show
  1. package/bin/lint-trace.js +4 -4
  2. package/bin/qc-base-map.json +13 -11
  3. package/bin/self-check.js +497 -16
  4. package/bin/trace-schema.json +3226 -2656
  5. package/core/FRAMEWORK_VERSION +1 -1
  6. package/core/commands/amend-prd.md +7 -1
  7. package/core/commands/debug.md +8 -2
  8. package/core/commands/define-product.md +38 -1
  9. package/core/commands/dev-gen-test.md +9 -3
  10. package/core/commands/dev-run-test.md +8 -2
  11. package/core/commands/dev-smoke-test.md +7 -1
  12. package/core/commands/extend-prd.md +7 -1
  13. package/core/commands/fix-bug.md +11 -5
  14. package/core/commands/generate-architecture.md +9 -1
  15. package/core/commands/generate-bdd.md +45 -5
  16. package/core/commands/generate-code.md +43 -4
  17. package/core/commands/generate-design-spec.md +7 -1
  18. package/core/commands/generate-prd.md +9 -1
  19. package/core/commands/generate-spec-manifest.md +7 -1
  20. package/core/commands/generate-tech-docs.md +41 -1
  21. package/core/commands/learn.md +7 -1
  22. package/core/commands/map-testids.md +11 -5
  23. package/core/commands/propose-scenario.md +7 -1
  24. package/core/commands/qc-analyze.md +12 -6
  25. package/core/commands/qc-automation-assess.md +356 -0
  26. package/core/commands/qc-design-script.md +430 -0
  27. package/core/commands/qc-design-test.md +98 -20
  28. package/core/commands/qc-plan.md +9 -3
  29. package/core/commands/qc-report.md +92 -77
  30. package/core/commands/qc-review-script.md +342 -0
  31. package/core/commands/{qc-review.md → qc-review-testcase.md} +86 -54
  32. package/core/commands/qc-run-manualtest.md +401 -0
  33. package/core/commands/qc-run-script.md +421 -0
  34. package/core/commands/refine-prd.md +7 -1
  35. package/core/commands/report-bug.md +9 -3
  36. package/core/commands/review-code.md +9 -3
  37. package/core/commands/review-context.md +11 -3
  38. package/core/commands/review-tech-docs.md +11 -3
  39. package/core/commands/setup-ai-first.md +7 -1
  40. package/core/commands/validate-traces.md +10 -4
  41. package/core/modules/qc-playwright-ts/module.yaml +13 -0
  42. package/core/modules/qc-playwright-ts/stack-profile.yaml +99 -0
  43. package/core/modules/qc-wdio-appium/module.yaml +20 -0
  44. package/core/modules/qc-wdio-appium/stack-profile.yaml +107 -0
  45. package/core/rules/workflow.md +2 -2
  46. package/core/skills/qc/_shared/self-review-principles.md +2 -2
  47. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +1 -1
  48. package/core/skills/qc/qa-analyst/data-flow.md +1 -1
  49. package/core/skills/qc/qa-analyst/spec-issue-reporter.md +1 -1
  50. package/core/skills/qc/qa-automation-assess/matrix.md +123 -0
  51. package/core/skills/qc/qa-designer/e2e/journey.md +1 -1
  52. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
  53. package/core/skills/qc/{qa-runner → qa-designer}/exploratory/session.md +8 -2
  54. package/core/skills/qc/qa-designer/functional/api.md +2 -2
  55. package/core/skills/qc/qa-designer/functional/gui-feature.md +1 -1
  56. package/core/skills/qc/qa-designer/functional/gui-screen.md +1 -1
  57. package/core/skills/qc/qa-designer/functional/job.md +128 -0
  58. package/core/skills/qc/qa-designer/integration/api.md +2 -2
  59. package/core/skills/qc/qa-designer/integration/db.md +2 -2
  60. package/core/skills/qc/qa-designer/integration/gui.md +1 -1
  61. package/core/skills/qc/qa-designer/integration/{kafka.md → queue.md} +21 -5
  62. package/core/skills/qc/qa-designer/non-functional.md +1 -1
  63. package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +17 -0
  64. package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +28 -6
  65. package/core/skills/qc/qa-reviewer/script/_shared/review-rules.md +121 -0
  66. package/core/skills/qc/qa-reviewer/script/api/auth.md +49 -0
  67. package/core/skills/qc/qa-reviewer/script/api/endpoint.md +89 -0
  68. package/core/skills/qc/qa-reviewer/script/api/security.md +46 -0
  69. package/core/skills/qc/qa-reviewer/script/exploratory.md +3 -3
  70. package/core/skills/qc/qa-reviewer/script/mobile/e2e.md +41 -0
  71. package/core/skills/qc/qa-reviewer/script/mobile/functional.md +90 -0
  72. package/core/skills/qc/qa-reviewer/script/mobile/integration.md +41 -0
  73. package/core/skills/qc/qa-reviewer/script/mobile/non-functional.md +43 -0
  74. package/core/skills/qc/qa-reviewer/script/web/e2e.md +46 -0
  75. package/core/skills/qc/qa-reviewer/script/web/functional.md +111 -0
  76. package/core/skills/qc/qa-reviewer/script/web/integration.md +46 -0
  77. package/core/skills/qc/qa-reviewer/script/web/non-functional.md +49 -0
  78. package/core/skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md +1 -1
  79. package/core/skills/qc/qa-reviewer/shared/review-file-template.md +29 -10
  80. package/core/skills/qc/qa-reviewer/test-case/e2e.md +2 -2
  81. package/core/skills/qc/qa-reviewer/test-case/exploratory.md +1 -1
  82. package/core/skills/qc/qa-reviewer/test-case/functional.md +2 -2
  83. package/core/skills/qc/qa-reviewer/test-case/integration.md +2 -2
  84. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +2 -2
  85. package/core/skills/qc/qa-script-designer/_shared/api-conventions.md +94 -0
  86. package/core/skills/qc/qa-script-designer/_shared/file-naming-and-folders.md +109 -0
  87. package/core/skills/qc/qa-script-designer/_shared/mobile-conventions.md +196 -0
  88. package/core/skills/qc/qa-script-designer/_shared/web-conventions.md +257 -0
  89. package/core/skills/qc/qa-script-designer/api/auth.md +43 -0
  90. package/core/skills/qc/qa-script-designer/api/endpoint.md +61 -0
  91. package/core/skills/qc/qa-script-designer/api/security.md +41 -0
  92. package/core/skills/qc/qa-script-designer/mobile/e2e.md +35 -0
  93. package/core/skills/qc/qa-script-designer/mobile/functional/feature.md +32 -0
  94. package/core/skills/qc/qa-script-designer/mobile/functional/screen.md +42 -0
  95. package/core/skills/qc/qa-script-designer/mobile/integration.md +39 -0
  96. package/core/skills/qc/qa-script-designer/mobile/non-functional.md +39 -0
  97. package/core/skills/qc/qa-script-designer/web/e2e.md +36 -0
  98. package/core/skills/qc/qa-script-designer/web/functional/api.md +39 -0
  99. package/core/skills/qc/qa-script-designer/web/functional/gui-feature.md +34 -0
  100. package/core/skills/qc/qa-script-designer/web/functional/gui-screen.md +42 -0
  101. package/core/skills/qc/qa-script-designer/web/integration.md +43 -0
  102. package/core/skills/qc/qa-script-designer/web/non-functional.md +42 -0
  103. package/core/skills/qc/qa-script-runner/mobile/run.md +38 -0
  104. package/core/skills/qc/qa-script-runner/report.md +41 -0
  105. package/core/skills/qc/qa-script-runner/web/run.md +48 -0
  106. package/core/steps/context-loader.md +1 -1
  107. package/core/steps/gate.md +7 -1
  108. package/core/steps/qc-scope.md +45 -2
  109. package/core/steps/qc-stamp.md +4 -4
  110. package/core/steps/report-footer.md +10 -9
  111. package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +1 -1
  112. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +13 -12
  113. package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +3 -3
  114. package/docs/02-concepts/traceability.md +1 -1
  115. package/docs/03-guides/developer.md +1 -1
  116. package/docs/03-guides/tester-qa.md +40 -11
  117. package/docs/04-reference/commands.md +4 -2
  118. package/docs/04-reference/modules.md +2 -1
  119. package/docs/04-reference/trace-schema.md +4 -4
  120. package/docs/explain/17-qc-design-test.md +5 -5
  121. package/docs/explain/18-qc-review.md +42 -20
  122. package/docs/explain/19-qc-run-test.md +13 -10
  123. package/docs/explain/20-qc-report.md +3 -3
  124. package/docs/explain/23-fix-bug.md +2 -2
  125. package/docs/explain/README.md +2 -2
  126. package/docs/plans/qc-surgery/01-checklist.md +86 -21
  127. package/docs/plans/qc-surgery/PLAN_v2.md +295 -0
  128. package/docs/plans/qc-surgery/exec-S-ap-stack-typescript.md +420 -0
  129. package/docs/plans/qc-surgery/exec-S0-guard-cam-stack-cu.md +400 -0
  130. package/docs/plans/qc-surgery/exec-S1-hai-module-thay-qc-playwright.md +267 -0
  131. package/docs/plans/qc-surgery/exec-S2-qa-runner-thanh-script-designer-runner.md +340 -0
  132. package/docs/plans/qc-surgery/exec-S3-viet-lai-tieu-chi-review-script.md +322 -0
  133. package/docs/plans/qc-surgery/exec-S5-an-theo-don-dau-vet-stack-cu.md +292 -0
  134. package/package.json +1 -1
  135. package/core/commands/qc-run-test.md +0 -561
  136. package/core/modules/qc-playwright/stack-profile.yaml +0 -66
  137. package/core/skills/qc/qa-reviewer/script/e2e.md +0 -95
  138. package/core/skills/qc/qa-reviewer/script/functional.md +0 -109
  139. package/core/skills/qc/qa-reviewer/script/integration.md +0 -99
  140. package/core/skills/qc/qa-reviewer/script/non-functional.md +0 -134
  141. package/core/skills/qc/qa-runner/e2e.md +0 -49
  142. package/core/skills/qc/qa-runner/functional/api.md +0 -35
  143. package/core/skills/qc/qa-runner/functional/gui-feature.md +0 -57
  144. package/core/skills/qc/qa-runner/functional/gui-screen.md +0 -61
  145. package/core/skills/qc/qa-runner/integration.md +0 -47
  146. package/core/skills/qc/qa-runner/non-functional.md +0 -49
  147. package/core/skills/qc/qa-runner/report/report.md +0 -37
@@ -98,9 +98,9 @@ Framework là pipeline **một chiều** — nhưng vẫn cần đường **ph
98
98
  |---|---|---|
99
99
  | `🟢 Open` | `/report-bug` | tester/QC file bug |
100
100
  | `🟡 Fixed` | `/fix-bug` Phase 5.5 | fix đã commit + push |
101
- | `🟢 Closed` | **`/qc-run-test`** | QC chạy lại và `qc_status` của SC liên kết flip `pass` |
101
+ | `🟢 Closed` | **`/qc-run-script`** | QC chạy lại và `qc_status` của SC liên kết flip `pass` |
102
102
 
103
- > **Dev không tự đóng bug của mình** — QC sở hữu verification. `/qc-run-test` đọc `qc_blocked_by` **trước** khi clear nó (cột đó chính là con trỏ tới bug; clear xong là mất đường về).
103
+ > **Dev không tự đóng bug của mình** — QC sở hữu verification. `/qc-run-script` đọc `qc_blocked_by` **trước** khi clear nó (cột đó chính là con trỏ tới bug; clear xong là mất đường về).
104
104
  >
105
105
  > Ngoại lệ có chủ đích: SC pass mà bug còn `🟢 Open` (chưa ai fix) → **không đóng**, giữ `Open` + cảnh báo kiểm tra lại test. Test pass trên bug chưa fix là dấu hiệu **test sai**, không phải bug hết — tự đóng ở đây sẽ chôn một defect thật.
106
106
 
@@ -149,7 +149,7 @@ QC phát hiện: link reset vẫn dùng được sau khi đổi mật khẩu
149
149
  → trace: test_count +2, dev_selftest → not_run
150
150
  → BUG-217 State: 🟡 Fixed
151
151
  /dev-run-test AUTH-UC2 → dev_selftest → pass
152
- /qc-run-test AUTH-UC2 → qc_status SC1 → pass
152
+ /qc-run-script AUTH-UC2 → qc_status SC1 → pass
153
153
  → BUG-217 State: 🟢 Closed (verified)
154
154
  /learn "luôn invalidate one-time token sau khi dùng"
155
155
  → project-lessons.md (nạp lại lần sau)
@@ -42,7 +42,7 @@ Chỉ tag `@trace` ở **boundary**, không tag mọi file → tránh **tag expl
42
42
  | `status` | `/generate-code`, `/validate-traces` | OK / GAP / DRIFT / UNTRACKED |
43
43
  | `implemented_by` | `/generate-code` | File code hiện thực SC |
44
44
  | `dev_selftest` | `/dev-run-test` | Smoke của **dev** |
45
- | `qc_status` | `/qc-run-test`, `/report-bug`, **`/map-testids`** | Trạng thái QC **chính thức** (Playwright). `/map-testids` **chỉ hạ về `not_run`**, không bao giờ ghi giá trị khẳng định — xem ô "Làm mất hiệu lực" dưới |
45
+ | `qc_status` | `/qc-run-script` + `/qc-run-manualtest`, `/report-bug`, **`/map-testids`** | Trạng thái QC **chính thức** (Playwright). `/map-testids` **chỉ hạ về `not_run`**, không bao giờ ghi giá trị khẳng định — xem ô "Làm mất hiệu lực" dưới |
46
46
  | `bdd_version` / `spec_ver` | spec | Version để phát hiện drift |
47
47
  | `service` *(cột 23)* | `/generate-bdd` | Đội/submodule sở hữu SC — nguồn của `by_service` trên dashboard |
48
48
  | `design_spec_version` *(cột 24)* | `/generate-bdd` | Version design-spec lúc sinh BDD *(FE/App; `—` cho backend)* |
@@ -88,7 +88,7 @@ public TokenDto login(...) { }
88
88
  - ❌ Để AI tự review code nó vừa sinh.
89
89
  - ❌ Tạo PR khi `/validate-traces` còn cờ 🔴 (`SEAM_UNWIRED` · `STUB_UNRESOLVED` · `ORPHANED` · `TRACE_ORPHAN`) — build xanh không chứng minh luồng ghép chạy đúng.
90
90
  - ❌ Coi FE `fe_phase = ui` là xong vì status đã `OK` — test đang chạy trên **mock**.
91
- - ❌ Tự đóng bug mình vừa fix — `/fix-bug` chỉ đặt `🟡 Fixed`; `🟢 Closed` là của `/qc-run-test`.
91
+ - ❌ Tự đóng bug mình vừa fix — `/fix-bug` chỉ đặt `🟡 Fixed`; `🟢 Closed` là của `/qc-run-script`.
92
92
 
93
93
  ---
94
94
 
@@ -9,14 +9,39 @@
9
9
  ## Chuỗi bước của bạn (Your path)
10
10
 
11
11
  ```mermaid
12
- flowchart LR
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<br/>🛑 cổng"] --> RUN["/qc-run-test<br/>chạy lại ×2 · 3 nhãn<br/>ghi qc_status"] --> REP["/qc-report<br/>product-gap"]
12
+ flowchart TD
13
+ M["§4.5.6 đã chốt/map-testids, bước 5"] --> A
14
+
15
+ A["1 · /qc-analyze 🛑<br/>Guard BR-tag"] --> P["2 · /qc-plan"]
16
+ P --> D["3 · /qc-design-test 🛑<br/>Guard SC coverage"]
17
+ D --> R["4 · /qc-review-testcase<br/>Verdict: APPROVED / NEEDS_FIX"]
18
+ R -- NEEDS_FIX --> D
19
+ R -- APPROVED --> AS["5 · /qc-automation-assess 🛑<br/>Automatable Y/N + nhãn lý do<br/>%Automated/Total"]
20
+
21
+ AS -- "Automatable: Y" --> DS["6 · /qc-design-script 🛑<br/>sinh script · điền cột Script file"]
22
+ AS -- "Automatable: N" --> MT["8b · /qc-run-manualtest<br/>hỏi TỪNG TC · ghi NGAY từng câu"]
23
+
24
+ DS --> RS["7 · /qc-review-script<br/>Verdict: APPROVED / NEEDS_FIX"]
25
+ RS -- NEEDS_FIX --> DS
26
+ RS -- APPROVED --> RUN["8 · /qc-run-script<br/>đọc cột Script file<br/>chạy lại ×2 · 3 nhãn<br/>đóng bug 🟡 → 🟢"]
27
+
28
+ RUN -- "ghi qc_status" --> TSV[("sổ trace<br/>UC-ID-platform.tsv")]
29
+ MT -- "ghi qc_status" --> TSV
30
+ TSV --> REP["9 · /qc-report<br/>product-gap"]
31
+
16
32
  REP --> FB["/report-bug · /propose-scenario"]
17
33
  FB --> SYNC["/sync"]
18
34
  ```
19
35
 
36
+ > **Hai nhánh gặp lại ở SỔ TRACE.** TC máy chạy được đi nhánh `Y` (trạm 6→7→8); TC phải chạy tay
37
+ > đi thẳng sang **8b**. Cả hai ghi vào **cùng một cột `qc_status`** — đó là lý do `/qc-report` đọc
38
+ > được **một** con số coverage cho cả hai. Không có trạm 8b thì mọi TC `Automatable: N` nằm
39
+ > `not_run` vĩnh viễn và report chấm cả PRD là **FAIL**, không cách nào sửa.
40
+
41
+ > **🛑 = chặn CỨNG (`--yes` không bỏ qua được) — nhưng cả bốn đều chỉ nổ khi ĐÃ CÓ THỨ ĐỂ MẤT:**
42
+ > `DOC_GAP.md` / `.Test.md` / bảng đánh giá / file script **đã tồn tại**. Chạy một lượt đầu trọn
43
+ > vẹn: **0 cổng cứng nổ**.
44
+
20
45
  > **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
46
 
22
47
  ---
@@ -28,8 +53,12 @@ flowchart LR
28
53
  | [`/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 |
29
54
  | `/qc-plan` | Đánh giá rủi ro + câu hỏi cho dev |
30
55
  | `/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` | 🛑 **Cổng review** case & script trước khi chạy |
32
- | `/qc-run-test` | 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`), **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 đóng sai)* |
56
+ | `/qc-review-testcase` | **Cổng review test case.** Ghi `**Verdict:** APPROVED`/`NEEDS_FIX` trạm sau ĐỌC dòng này, nên nó là contract chứ không phải định dạng cho đẹp |
57
+ | `/qc-automation-assess` | Quyết định **cái nào máy chạy, cái nào phải tay** `Automatable: Y/N` kèm **nhãn do chuẩn hoá** (để đếm được: *"3 TC thiếu test-id"* hành động được, *"3 TC do kỹ thuật"* thì không). Ra `%Automated/Total`. TC của UC chưa `APPROVED` bị **loại khỏi lượt liệt ra** mẫu số chỉ gồm TC đã xét |
58
+ | `/qc-design-script` | Sinh script **chỉ cho `Automatable: Y`**, gắn tag `@smoke`/`@regression` theo `Priority`, rồi **điền cột `Script file`** — chỉ mục ngược duy nhất TC → file code |
59
+ | `/qc-review-script` | **Cổng review script** — biên bản **riêng** `REVIEW_SCRIPT_<FEATURE>.md`, không chung file với cổng test case |
60
+ | `/qc-run-manualtest` | Chạy tay TC `Automatable: N`. Lệnh **hỏi từng TC** và **ghi ngay sau mỗi câu trả lời** *(chạy lại thì tự resume)* — không đọc file checklist, vì một file điền tay là nguồn thứ hai có thể trôi. `pass` **bắt buộc kèm bằng chứng** vào `MANUAL_EVIDENCE.md` |
61
+ | `/qc-run-script` | **Đọc cột `Script file`** để biết chạy file nào — không tự suy đường dẫn. Chạy script TypeScript, 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)* |
33
62
  | `/qc-report` | Report + evidence, đẩy **product-gap** về PO/Dev |
34
63
  | [Feedback](../02-concepts/pipeline-steps/10-feedback-loop.md) | `/report-bug`, `/propose-scenario` — kênh có hồ sơ spec |
35
64
 
@@ -44,12 +73,12 @@ Bạn cũng dùng `/validate-traces` để thấy **gap chưa phủ** (spec ↔
44
73
  - **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**.
45
74
  - Đâ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 đó.
46
75
  - Không chắc giữa `script-bug` và `product-gap` → **mời Dev cùng xem trace**, đừng đoán cho xong.
47
- 3. **Không chạy test kém** — phải qua cổng `/qc-review` trước `/qc-run-test`.
76
+ 3. **Không chạy test kém** — phải qua cổng `/qc-review-testcase` trước `/qc-design-script`, và qua `/qc-review-script` trước `/qc-run-script`.
48
77
  4. **Bug phải spec-anchored** — `/report-bug` gắn `@trace` tới UC/SC để truy vết & regression.
49
- 5. **Bạn là người ĐÓNG bug** — `/fix-bug` của dev chỉ đặt `🟡 Fixed`; `🟢 Closed` do `/qc-run-test` đặt khi `qc_status` của SC liên kết flip `pass`. Dev không tự đóng bug của mình.
78
+ 5. **Bạn là người ĐÓNG bug** — `/fix-bug` của dev chỉ đặt `🟡 Fixed`; `🟢 Closed` do `/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.
50
79
  - 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**.
51
80
  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.
52
- 7. Stack QC cố định: Python + pytest-playwright + Page Object (module `qc-playwright`), **độc lập** module của dev.
81
+ 7. Stack QC: TypeScript + Playwright Test (web·system) / WebdriverIO + Appium (app) module chọn theo nền ở `steps/qc-scope.md` §2b, **độc lập** module của dev.
53
82
  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**.
54
83
  - 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.
55
84
  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.
@@ -77,7 +106,7 @@ Bạn cũng dùng `/validate-traces` để thấy **gap chưa phủ** (spec ↔
77
106
  ## Anti-pattern
78
107
 
79
108
  - ❌ Sửa script cho "xanh" khi thực chất là product-gap → giấu lỗi sản phẩm.
80
- - ❌ Chạy `/qc-run-test` khi chưa qua `/qc-review`.
109
+ - ❌ Chạy `/qc-design-script` khi chưa qua `/qc-review-testcase`, hoặc `/qc-run-script` khi chưa qua `/qc-review-script`.
81
110
  - ❌ Lẫn `qc_status` với `dev_selftest`.
82
111
  - ❌ Bug không gắn spec → khó truy vết, khó regression.
83
112
  - ❌ 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.
@@ -88,6 +117,6 @@ Bạn cũng dùng `/validate-traces` để thấy **gap chưa phủ** (spec ↔
88
117
 
89
118
  ## Lệnh của bạn (Your commands)
90
119
 
91
- `/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review` · `/qc-run-test` · `/qc-report` · `/report-bug` · `/propose-scenario` · `/validate-traces`
120
+ `/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review-testcase` · `/qc-automation-assess` · `/qc-design-script` · `/qc-review-script` · `/qc-run-script` · `/qc-run-manualtest` · `/qc-report` · `/report-bug` · `/propose-scenario` · `/validate-traces`
92
121
 
93
122
  → [Bảng lệnh đầy đủ](../04-reference/commands.md) · [Traceability](../02-concepts/traceability.md)
@@ -92,8 +92,10 @@ Mọi lệnh chạy chung một **Gate** (model check → target → context-loa
92
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
94
  | `/qc-design-test` | Plan + `.feature` + §4.5.6 | `test-cases/*.Test.md` + **Guard SC coverage** | QA |
95
- | `/qc-review` | Test case/script | 🛑 Cổng review | QA |
96
- | `/qc-run-test` | `.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 |
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` | `.Test.md` reviewed + bảng Automatable | 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
 
99
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).
@@ -35,7 +35,8 @@
35
35
 
36
36
  | Module | Vai trò |
37
37
  |--------|---------|
38
- | `qc-playwright` | QC automation — Python + pytest-playwright + Page Object |
38
+ | `qc-playwright-ts` | QC automation web + API Playwright Test + TypeScript (`layout.web` · `layout.api`) |
39
+ | `qc-wdio-appium` | QC automation app — WebdriverIO v9 + Appium v2 + UiAutomator2, TypeScript |
39
40
  | `context-engineering` | Hỗ trợ context-loader |
40
41
 
41
42
  ---
@@ -99,7 +99,7 @@ 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-run-test`, `qc-design-test`), **2 lệnh ghi** (`generate-tech-docs`,
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 |
@@ -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-test · *hạ hiệu lực:* generate-bdd · generate-code |
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-test · report-bug |
168
- | 13 | `qc_blocked_by` | `BUG-{id}` / `GAP-{id}` | qc-run-test · report-bug |
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,14 +1,14 @@
1
- [← /qc-plan](16-qc-plan.md) · [Explain Home](README.md) · [Next: /qc-review →](18-qc-review.md)
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-test`.
5
+ > **Một câu.** Thiết kế **test case dạng Markdown** (`.Test.md`) từ plan — chưa sinh script; script đến sau ở `/qc-design-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-test` biến thành script.
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` biến thành script.
12
12
 
13
13
  ---
14
14
 
@@ -55,7 +55,7 @@ Tách "thiết kế test case" (con người đọc/review được) khỏi "cod
55
55
 
56
56
  ## Checkpoint & Gate
57
57
 
58
- - Không gate chặn người ở đâ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
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.
60
60
 
61
61
  ---
@@ -81,4 +81,4 @@ Tách "thiết kế test case" (con người đọc/review được) khỏi "cod
81
81
 
82
82
  ## Kết nối
83
83
 
84
- **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).
@@ -1,63 +1,85 @@
1
- [← /qc-design-test](17-qc-design-test.md) · [Explain Home](README.md) · [Next: /qc-run-test →](19-qc-run-test.md)
1
+ [← /qc-design-test](17-qc-design-test.md) · [Explain Home](README.md) · [Next: ba trạm script →](19-qc-run-test.md)
2
2
 
3
- # 18 · `/qc-review` — Trạm 4: Cổng review hai chiều (test case & script)
3
+ # 18 · `/qc-review-testcase` + `/qc-review-script` — Trạm 4: Hai cổng review
4
4
 
5
- > **Một câu.** Gate chất lượng của QC: review **test case** (sau design-test) VÀ **script** (sau run-test) chạy hai thời điểm trong dây chuyền.
5
+ > **Một câu.** Gate chất lượng của QC, **hai lệnh riêng**: `/qc-review-testcase` soát test case sau design-test; `/qc-review-script` soát code test sau khi script được sinh.
6
+
7
+ > **Trước Đợt 2 đây là MỘT lệnh `/qc-review` làm cả hai vai và tự đoán vai nào bằng cách so ngày sửa file.** Chính trang này từng ghi ở mục *Góc nhìn tối ưu*: *"Chạy 2 lần cùng một lệnh — người dùng phải nhớ gọi đúng thời điểm… **Cân nhắc tách rõ**"*. Đó là việc đã làm.
6
8
 
7
9
  ---
8
10
 
9
11
  ## Vấn đề giải quyết
10
12
 
11
- Không chạy test kém. Trạm này chặn: (1) test case chưa đủ tốt trước khi biến thành script; (2) script chưa đúng trước khi coi kết quả là chính thức.
13
+ Không chạy test kém. Hai cổng chặn hai thứ khác nhau:
14
+
15
+ 1. **`/qc-review-testcase`** — test case chưa đủ tốt trước khi biến thành script.
16
+ 2. **`/qc-review-script`** — script chưa đúng trước khi coi kết quả chạy là chính thức.
17
+
18
+ Và **cái mà một-lệnh-hai-vai không làm được:** đặt điều kiện tiên quyết cho trạm sau. `REVIEW_<FEATURE>.md` của lệnh cũ không nói nó là kết quả soát vai nào, nên trạm sau không hỏi được *"cái tôi cần đã APPROVED chưa?"*.
12
19
 
13
20
  ---
14
21
 
15
22
  ## Vị trí & tiền đề
16
23
 
17
- - **Vị trí:** Phase QC (trạm 4) — **hai lần**: sau `/qc-design-test` (review case) sau `/qc-run-test` (review script).
24
+ | Lệnh | Chạy sau | Đọc | Ghi |
25
+ |---|---|---|---|
26
+ | `/qc-review-testcase` | `/qc-design-test` | `.Test.md` | `REVIEW_<FEATURE>.md` |
27
+ | `/qc-review-script` | trạm sinh script | code test + Page Object | `REVIEW_SCRIPT_<FEATURE>.md` |
28
+
29
+ **File riêng, không chung.** Hai lượt soát cách nhau vài trạm; chung file thì lượt sau đè bảng chi tiết của lượt trước, và trạm tiêu thụ verdict lại phải đoán — tức mang nguyên vấn đề cũ sang chỗ mới.
18
30
 
19
31
  ---
20
32
 
21
33
  ## Input / Output
22
34
 
23
- **Input:** `.Test.md` (case) hoặc script Python (script) + skill `qa-reviewer`.
35
+ **Input:** `.Test.md` *(vai test case)* hoặc code test + Page Object *(vai script)*, cộng skill `qa-reviewer`.
36
+
37
+ **Output:** file biên bản riêng của mỗi vai, chứa điểm `XX/100` và **một dòng verdict máy đọc được**:
38
+
39
+ ```
40
+ **Verdict:** APPROVED
41
+ **Verdict:** NEEDS_FIX
42
+ ```
24
43
 
25
- **Output:** verdict APPROVED / NEEDS_FIX + findings review.
44
+ `APPROVED` khi điểm `≥80` **và** không còn `FAIL` chặn. Đây là **contract**, không phải định dạng cho đẹp — `/qc-automation-assess` loại TC chưa `APPROVED`, `/qc-run-script` dừng khi script chưa `APPROVED`.
26
45
 
27
46
  ---
28
47
 
29
- ## Các bước xử lý (chi tiết)
48
+ ## Các bước xử lý
30
49
 
31
- 1. **Role qa-reviewer** — nạp `{qc_skills_dir}/qa-reviewer/`.
32
- 2. **Review focus** — kiểm test case (đủ phủ, đúng SC) hoặc script (đúng logic, **selector bám §4.5.6 chứ không dò DOM**, không fake-pass).
33
- 3. **Self-Review** *(mới)* — nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
34
- 4. Verdict: APPROVED → đi tiếp; NEEDS_FIX → sửa rồi review lại.
35
- > **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.
50
+ 1. **Role qa-reviewer** — nạp `{qc_skills_dir}/qa-reviewer/`, **đúng bộ của vai mình**.
51
+ 2. **Review focus** — test case: đủ phủ SC, expected cụ thể, trace, `🚫 Block` còn hiệu lực. Script: khớp `.Test.md` 1-1, Page Object gọn, `expect()` thật, **selector bám §4.5.6 chứ không dò DOM**, không hard-code.
52
+ 3. **Self-Review** — nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
53
+ 4. **Verdict** — `APPROVED` → đi tiếp; `NEEDS_FIX` → sửa rồi review lại.
36
54
 
55
+ > **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.
37
56
 
38
57
  ---
39
58
 
40
59
  ## Checkpoint & Gate
41
60
 
42
- - 🛑 **Cổng hai chiều** — chặn `/qc-run-test` (nếu case chưa duyệt) chặn tạo PR (nếu script chưa duyệt).
61
+ - Cả hai lệnh ở mức **không chặn** chúng chỉ ghi **biên bản**,sinh lại = soát lại.
62
+ - Cổng thật nằm ở **verdict chúng phát ra**, được trạm sau đọc.
43
63
 
44
64
  ---
45
65
 
46
66
  ## Cơ chế đặc biệt
47
67
 
48
- - **Một lệnh, hai vai** — review case review script dùng chung skill, khác focus.
49
- - **Gate thật của QC** — điểm HITL chính trong dây chuyền tự động.
50
- - **Review script thì soát cả nguồn selector** script lấy locator từ §4.5.6 Test Selectors, hay tự DOM? DOMscript giòn: dev đổi một class vỡ, **không ai báo**.
68
+ - **Chân thứ của hợp đồng test-id** — phép so §4.5.6 ↔ `*.Test.md`, mức `warn`, một chiều. Vai này thuộc **`/qc-review-testcase`** *(`bin/trace-schema.json` `testid_fourth_leg.checked_by`)*, vì phép so chạy trên `.Test.md`. Ở trạm script, locator dựng **lúc chạy** từ bảng tươi nên nó tự cứu.
69
+ - **Đọc stamp phiên bản nguồn** — cũng thuộc vai test case *(`qc_artifact_stamp.checked_by`)*.
70
+ - **Điểm có luật chấm** trừ mỗi `FAIL`, mỗi `WARN`; bảng Tổng quan **thêm một hàng mỗi vòng**, không ghi đè. Đócách duy nhất thấy được sửa xong tốt lên không.
71
+ - **Reviewer KHÔNG tự sửa** — chỉ nhận xét và chấm. *Tự sửa rồi tự duyệt là bỏ mất cái cổng.*
51
72
 
52
73
  ---
53
74
 
54
75
  ## 👓 Góc nhìn tối ưu
55
76
 
56
- - **Chạy 2 lần cùng một lệnh** — người dùng phải nhớ gọi đúng thời điểm. Footer "Next" hướng dẫn, nhưng dễ nhầm. Cân nhắc tách hoặc auto-detect giai đoạn.
57
- - **Verdict thủ công** phụ thuộc reviewer; không findings-file như review-context. Đáng xem nên chuẩn hoá.
77
+ - **Verdict vẫn do LLM phát ra** — luật chấm rõ, nhưng không máy nào kiểm lại. Lớp CI cho `T19` *(chân thứ tư)*; phần điểm số thì chưa.
78
+ - **Bộ tiêu chí `script/*` còn phẳng theo tầng.** Khi Đợt 2 bước 2 chốt stack, nó sẽ tách theo nền (`web`/`mobile`) vì tiêu chí khác nhau. Cố ý chưa làm bước 1 — viết tiêu chí cho stack chưa chốt là viết hai lần.
58
79
 
59
80
  ---
60
81
 
61
82
  ## Kết nối
62
83
 
63
- **Trước:** [`/qc-design-test`](17-qc-design-test.md) (case) / [`/qc-run-test`](19-qc-run-test.md) (script) · **Sau:** case APPROVED → [`/qc-run-test`](19-qc-run-test.md); script APPROVED → [`/qc-report`](20-qc-report.md) / PR.
84
+ **Trước:** [`/qc-design-test`](17-qc-design-test.md) *(vai test case)* · [ba trạm script](19-qc-run-test.md) *(vai script)*
85
+ **Sau:** test case `APPROVED` → [ba trạm script](19-qc-run-test.md) · script `APPROVED` → [`/qc-report`](20-qc-report.md) rồi tạo PR
@@ -1,21 +1,24 @@
1
- [← /qc-review](18-qc-review.md) · [Explain Home](README.md) · [Next: /qc-report →](20-qc-report.md)
1
+ [← hai cổng review](18-qc-review.md) · [Explain Home](README.md) · [Next: /qc-report →](20-qc-report.md)
2
2
 
3
- # 19 · `/qc-run-test` — Trạm 5: Sinh & chạy Playwright, ghi `qc_status`
3
+ # 19 · `/qc-design-script` · `/qc-run-script` · `/qc-run-manualtest` — Trạm 5–7: sinh · chạy · chạy tay
4
4
 
5
- > **Một câu.** Biến `.Test.md` đã review thành **Python pytest-playwright**, chạy thật, rồi ghi **`qc_status` chính thức** (có evidence) vào trace TSV.
5
+ > **Một câu.** Biến `.Test.md` đã review thành **script TypeScript**, chạy thật, rồi ghi **`qc_status` chính thức** (có evidence) vào trace TSV.
6
6
 
7
7
  ---
8
8
 
9
9
  ## Vấn đề giải quyết
10
10
 
11
+ > **Trước Đợt 2 · b2 đây là MỘT lệnh `/qc-run-test` gánh BỐN việc**: quyết cái nào automate được · viết mã · chạy · phán một kết quả đỏ là lỗi sản phẩm hay lỗi mã test. Bốn quyết định, không chỗ nào dừng giữa chúng — nên không ai soát được mã trước khi nó chạy, và TC **không** automate được (OTP, sinh trắc học) rơi ra ngoài: không trạm nào ghi `qc_status` cho chúng, rồi `/qc-report` chấm cả PRD là FAIL vĩnh viễn. `/qc-run-manualtest` sinh ra để bịt đúng chỗ đó.
12
+
13
+
11
14
  Đây là nơi QC trở thành **chính thức**: chạy test thật trên Playwright, phân loại FAIL (script-bug vs product-gap, **không fake-pass**), và đóng dấu `qc_status` — trạng thái QC authoritative.
12
15
 
13
16
  ---
14
17
 
15
18
  ## Vị trí & tiền đề
16
19
 
17
- - **Vị trí:** Phase QC (trạm 5), sau `/qc-review` (case APPROVED).
18
- - **Stack:** module `qc-playwright` (Python + pytest-playwright + Page Object) — **độc lập** module dev.
20
+ - **Vị trí:** Phase QC, **ba trạm** 5 sinh script · 6 chạy script · 7b chạy tay. `/qc-design-script` chạy sau `/qc-review-testcase` (case APPROVED); `/qc-run-script` chạy sau `/qc-review-script` (script APPROVED).
21
+ - **Stack:** module QC theo nền (`qc-playwright-ts` · `qc-wdio-appium`, xem `steps/qc-scope.md` §2b) — **độc lập** module dev.
19
22
 
20
23
  ---
21
24
 
@@ -23,7 +26,7 @@
23
26
 
24
27
  **Input:** `.Test.md` đã review + skill `qa-runner` + bảng Test Selectors §4.5.6 (**giá trị** test-id, từ `/map-testids`) + **`@trace.testid_attr`** ở header tech-doc (**tên thuộc tính** chứa chúng).
25
28
 
26
- **Output:** script Python + kết quả + cột `qc_status` trong `.trace/…/{UC-ID}-{platform}.tsv` + panel mirror (`.trace-mirror/`).
29
+ **Output:** script TypeScript + kết quả + cột `qc_status` trong `.trace/…/{UC-ID}-{platform}.tsv` + panel mirror (`.trace-mirror/`).
27
30
 
28
31
  > **`@trace.testid_attr` — đọc, KHÔNG suy từ platform.** §4.5.6 cho **giá trị** test-id; field này cho **tên thuộc tính** chứa chúng. `get_by_test_id()` của Playwright mặc định dò `data-testid` **nhưng cấu hình được** — dự án dùng `data-test`/`data-qa` thì phải `set_test_id_attribute("{attr}")` trước, không thì **trượt 100% locator**.
29
32
  >
@@ -33,7 +36,7 @@
33
36
 
34
37
  ## Các bước xử lý (chi tiết)
35
38
 
36
- 1. **Role & stack** — qc-playwright (`stack-profile.yaml`): Python, pytest-playwright fixture, Page Object; mỗi test độc lập; gom theo (role, account) để auth không xen kẽ.
39
+ 1. **Role & stack** — module theo nền (`stack-profile.yaml`): TypeScript, Playwright/WDIO fixture, Page/Screen/API Object; mỗi test độc lập; gom theo (role, account) để auth không xen kẽ.
37
40
  2. **Skills** — nạp một file skill `qa-runner` theo layer.
38
41
  3. **Sinh script** từ `.Test.md`; tag `@trace.verifies={UC-ID}-SC{N}`.
39
42
  4. **Chạy.** Test đỏ **một lần** chưa nói được nó đỏ vì cái gì → **chạy lại riêng test đó, tối đa 2 lần**, rồi mới phân loại thành **ba** nhãn:
@@ -67,7 +70,7 @@
67
70
 
68
71
  ## Checkpoint & Gate
69
72
 
70
- - Tiền đề: case đã APPROVED ở `/qc-review`. Script sinh ra → review lại ở `/qc-review` (script) trước PR.
73
+ - Tiền đề: case đã APPROVED ở `/qc-review-testcase`. Script sinh ra → review lại ở `/qc-review-script` trước PR.
71
74
  - 🛑 **Xác nhận nhãn FAIL** — cổng chặn được **thêm vào**, trong khi framework vốn đang giảm số cổng chặn (G41). Lý do: **cả hai hướng sai đều không đảo ngược rẻ.** Gắn nhầm `script-bug` cho lỗi sản phẩm thật là **giấu bug** cho tới khi khách gặp; mở bug từ một lần chạy hên xui là **đốt thời gian dev** và làm mòn niềm tin vào QC.
72
75
 
73
76
  > **Đây KHÔNG phải `retries` trong config test runner.** `retries` tự thử lại rồi báo *"passed on retry"* — nó **che** sự không nhất quán. Ở đây chạy **tách biệt từng lần để quan sát**, vì chính sự không nhất quán mới là thông tin cần.
@@ -89,7 +92,7 @@ Khi `qc_status` flip `pass`, lệnh clear `qc_owner`/`qc_blocked_by` về `—`.
89
92
 
90
93
  | `State` của bug | SC vừa `pass` → làm gì |
91
94
  |---|---|
92
- | `🟡 Fixed` | → `🟢 Closed` + dòng `Verified: /qc-run-test {today} — {UC-ID}-SC{N} pass` |
95
+ | `🟡 Fixed` | → `🟢 Closed` + dòng `Verified: /qc-run-script {today} — {UC-ID}-SC{N} pass` |
93
96
  | `🟢 Open` (chưa ai fix) | **KHÔNG đóng.** Giữ `Open` + ghi chú kiểm tra lại test |
94
97
  | `GAP-*` thay vì `BUG-*` | không đụng — spec-gap thuộc PO, không phải QC |
95
98
 
@@ -111,4 +114,4 @@ Bug report đã đổi phải **commit + push** vào spec repo — file local l
111
114
 
112
115
  ## Kết nối
113
116
 
114
- **Trước:** [`/qc-review`](18-qc-review.md) (case) · **Sau:** [`/qc-report`](20-qc-report.md) rồi [`/qc-review`](18-qc-review.md) (script).
117
+ **Trước:** [`/qc-review-testcase`](18-qc-review.md) · **Sau:** [`/qc-report`](20-qc-report.md) rồi [`/qc-review-script`](18-qc-review.md) (script).
@@ -1,4 +1,4 @@
1
- [← /qc-run-test](19-qc-run-test.md) · [Explain Home](README.md) · [Next: /validate-traces →](21-validate-traces.md)
1
+ [← ba trạm script](19-qc-run-test.md) · [Explain Home](README.md) · [Next: /validate-traces →](21-validate-traces.md)
2
2
 
3
3
  # 20 · `/qc-report` — Trạm 6: Report + evidence + product-gap
4
4
 
@@ -14,7 +14,7 @@ Kết quả chạy cần được trình bày có bằng chứng và **định t
14
14
 
15
15
  ## Vị trí & tiền đề
16
16
 
17
- - **Vị trí:** Phase QC (trạm 6, cuối), sau `/qc-run-test`.
17
+ - **Vị trí:** Phase QC (trạm 6, cuối), sau `/qc-run-script` và `/qc-run-manualtest`.
18
18
 
19
19
  ---
20
20
 
@@ -61,4 +61,4 @@ Kết quả chạy cần được trình bày có bằng chứng và **định t
61
61
 
62
62
  ## Kết nối
63
63
 
64
- **Trước:** [`/qc-run-test`](19-qc-run-test.md) · **Sau:** [`/validate-traces`](21-validate-traces.md) (làm mới Living Docs); product-gap → [`/report-bug`](25-report-bug.md).
64
+ **Trước:** [ba trạm script](19-qc-run-test.md) · **Sau:** [`/validate-traces`](21-validate-traces.md) (làm mới Living Docs); product-gap → [`/report-bug`](25-report-bug.md).
@@ -35,7 +35,7 @@ Sửa bug ad-hoc dễ tái phát và mất truy vết. Command áp một quy tr
35
35
  4. **Phase 4 · Regression Test** — thêm test tái hiện bug để chống tái phát.
36
36
  5. **Phase 4.5 · Cập nhật sổ trace** — regression test phải hiện lên coverage (xem dưới).
37
37
  6. **Phase 5 · Build & Commit** — build verify; umbrella **push 2 tầng** (Tầng 1: fix branch trong service submodule nơi code sống; Tầng 2: umbrella pointer).
38
- 7. **Phase 5.5 · Đặt `🟡 Fixed`** — nếu fix một `{BUG-ID}` đã file. **Không** đặt `Closed` — bước đó thuộc `/qc-run-test`.
38
+ 7. **Phase 5.5 · Đặt `🟡 Fixed`** — nếu fix một `{BUG-ID}` đã file. **Không** đặt `Closed` — bước đó thuộc `/qc-run-script`.
39
39
  8. **Phase 6 · Đề xuất Lesson** — nếu lỗi tái diễn → `capture-lesson` (L1–L5).
40
40
 
41
41
  ### Phase 4.5 — vì sao `/fix-bug` phải ghi sổ trace
@@ -49,7 +49,7 @@ Sửa bug ad-hoc dễ tái phát và mất truy vết. Command áp một quy tr
49
49
  | `dev_selftest` → `not_run` · `dev_selftest_at` → `—` | code vừa đổi nên tín hiệu self-test cũ hết hiệu lực |
50
50
  | `last_updated` | hôm nay |
51
51
 
52
- **Hai nhóm cột cấm đụng:** `qc_*` (QC sở hữu — `/qc-run-test` flip khi re-verify **và** chính đóng bug) · `spec_ver`/`gen_ver` (**fix bug không đổi spec** — đụng vào là tạo `DRIFT` giả).
52
+ **Hai nhóm cột cấm đụng:** `qc_*` (QC sở hữu — `/qc-run-script` và `/qc-run-manualtest` flip khi re-verify; riêng `/qc-run-script` đóng bug) · `spec_ver`/`gen_ver` (**fix bug không đổi spec** — đụng vào là tạo `DRIFT` giả).
53
53
 
54
54
  Vì `dev_selftest` bị reset, Next của lệnh là **`/dev-run-test`** để lấy lại tín hiệu xanh, rồi mới tạo PR.
55
55
 
@@ -117,8 +117,8 @@ Kết thúc bằng: **Status badge** (✅/❌/⚠️) · **Output Artifacts** (f
117
117
  - [15 · `/qc-analyze`](15-qc-analyze.md)
118
118
  - [16 · `/qc-plan`](16-qc-plan.md)
119
119
  - [17 · `/qc-design-test`](17-qc-design-test.md)
120
- - [18 · `/qc-review`](18-qc-review.md)
121
- - [19 · `/qc-run-test`](19-qc-run-test.md)
120
+ - [18 · `/qc-review-testcase` + `/qc-review-script`](18-qc-review.md)
121
+ - [19 · `/qc-design-script` · `/qc-run-script` · `/qc-run-manualtest`](19-qc-run-test.md)
122
122
  - [20 · `/qc-report`](20-qc-report.md)
123
123
 
124
124
  ### Phase Trace & Quality