@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
@@ -0,0 +1,39 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ ---
5
+
6
+ # Gen Script — API (dùng chung mọi platform)
7
+
8
+ Skill sinh script test API thuần (không qua UI), dùng `@playwright/test` `APIRequestContext`.
9
+ Test API **không phân biệt platform gọi nó là web hay mobile** — backend là một, nên file này
10
+ dùng chung cho cả pipeline web và mobile (không có bản mobile riêng).
11
+
12
+ ## Khi nào trigger
13
+ - Convert TC API (output `qa-designer/functional/api.md`), TC Automatable=Y, `TC_<FEATURE>.md` đã approve.
14
+
15
+ ## Khi KHÔNG trigger
16
+ - Test qua UI → `functional/gui-screen.md`/mobile tương ứng · tích hợp đa thành phần → `integration.md`
17
+
18
+ ## Quy ước riêng (ngoài Locator/Wait/Assertion chung — API không có locator)
19
+ - Client API gói trong fixture Playwright (`test.extend`) — base URL + auth header từ
20
+ `process.env.*`, KHÔNG rải request rời rạc trong test.
21
+ - Assertion: status code **và** field response (JSON path) — không chỉ status code.
22
+ - Test độc lập: tạo data qua API → dùng → cleanup qua API (`test.afterEach`), không phụ thuộc
23
+ thứ tự chạy.
24
+
25
+ ## Phase 1 — Clarify
26
+ Base URL/auth/role theo `TEST_DATA_PLAN.md`; client fixture đã có chưa.
27
+
28
+ ## Phase 2 — Generate
29
+ Mỗi TC Automatable=Y → 1 test gọi endpoint với request từ `TEST_DATA_PLAN.md`; assert status +
30
+ field. Nhóm `test.describe`: happy → validation → auth → not-found → edge.
31
+
32
+ ## Phase 3 — Self-Verify
33
+ ```bash
34
+ npx tsc --noEmit
35
+ npx playwright test automation/tests/{TICKET-ID}/functional/api/<feature>-<scenario>.spec.ts --list
36
+ ```
37
+
38
+ ## Output
39
+ `automation/tests/{TICKET-ID}/functional/api/<feature>-<scenario>.spec.ts` + client fixture (`fixtures/api-client.ts`) nếu mới.
@@ -0,0 +1,34 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ ---
5
+
6
+ # Gen Script — Web Functional GUI Feature (đa màn hình)
7
+
8
+ Skill sinh script cho feature span ≥2 màn. **Đọc `_shared/web-conventions.md` trước.**
9
+
10
+ ## Khi nào trigger
11
+ - Convert TC feature đa-màn (output `qa-designer/functional/gui-feature.md`), TC Automatable=Y,
12
+ `TC_<FEATURE>.md` đã approve.
13
+
14
+ ## Khi KHÔNG trigger
15
+ - Gọn 1 màn → `functional/gui-screen.md` · đầu-cuối xuyên hệ thống ngoài → `e2e.md`
16
+
17
+ ## Phase 1 — Clarify
18
+ Liệt kê các màn/Page Object cần; state truyền giữa màn (giá trị nhập màn A hiển thị đúng ở
19
+ màn B); data từ `TEST_DATA_PLAN.md`.
20
+
21
+ ## Phase 2 — Generate
22
+ Mỗi Page Object action điều hướng **trả về PO màn kế tiếp** (`return new NextPage(this.page)`)
23
+ — test chuỗi `const p2 = await p1.doAction()`. Phủ đúng TC Automatable=Y (đếm khớp
24
+ `AUTOMATION_ASSESSMENT.md`). Assert **sau mỗi chặng có side-effect**, không chỉ ở bước cuối
25
+ (xem Common Pitfall #4 trong `_shared/web-conventions.md`).
26
+
27
+ ## Phase 3 — Self-Verify
28
+ ```bash
29
+ npx tsc --noEmit
30
+ npx playwright test automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts --list
31
+ ```
32
+
33
+ ## Output
34
+ Script + nhiều Page Object (mỗi màn) trong `automation/pages/{TICKET-ID}/...`.
@@ -0,0 +1,42 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ ---
5
+
6
+ # Gen Script — Web Functional GUI Screen (1 màn hình)
7
+
8
+ Skill sinh script cho 1 màn hình đơn. **Đọc `_shared/web-conventions.md` trước** (Locator
9
+ Strategy, Page Object, Wait/Assertion, Common Pitfalls) — file này chỉ có phần sinh-script
10
+ riêng của layer.
11
+
12
+ ## Khi nào trigger
13
+ - Convert TC functional 1 màn (output `qa-designer/functional/gui-screen.md`), TC đã
14
+ `Automatable: Y` (từ `AUTOMATION_ASSESSMENT.md`) và `TC_<FEATURE>.md` đã approve.
15
+
16
+ ## Khi KHÔNG trigger
17
+ - Feature đa-màn → `functional/gui-feature.md` · API thuần → `functional/api.md`
18
+
19
+ ## Phase 1 — Clarify
20
+ Đọc `TC_<FEATURE>.md` (chỉ TC Automatable=Y) + `TEST_DATA_PLAN.md`. Page Object cho màn này đã có
21
+ chưa → tạo mới nếu chưa. Đọc bảng test-id §4.5.6 tech-doc gộp cho màn này.
22
+
23
+ ## Phase 2 — Generate
24
+ **Phủ đúng các TC Automatable=Y** — đếm TC trong `AUTOMATION_ASSESSMENT.md` có `Y` cho màn
25
+ này = số `test(...)` phải sinh (không hơn, không kém). TC Automatable=Y nhưng phát hiện rào
26
+ cản kỹ thuật lúc viết → `test.fixme('TC_xxx — {lý do}')` + ghi `IMPROVE-xxx` (xem command
27
+ `/qc-design-script` §Testability Improvement List), không âm thầm bỏ qua.
28
+
29
+ Nhóm theo `test.describe`: GUI (hiển thị/enable-disable) → Functional (input/validation/action).
30
+ Data lấy từ `TEST_DATA_PLAN.md` (theo `TD-xxx` map ở cột "Dùng bởi").
31
+
32
+ ## Phase 3 — Self-Verify (trước khi báo Human approve)
33
+ ```bash
34
+ npx tsc --noEmit
35
+ npx playwright test automation/tests/{TICKET-ID}/<screen>.spec.ts --list
36
+ ```
37
+ Số test liệt kê = số TC Automatable=Y của màn này. Thiếu → quay lại Phase 2.
38
+
39
+ ## Output
40
+ `automation/tests/{TICKET-ID}/<screen-slug>.spec.ts` +
41
+ `automation/pages/{TICKET-ID}/<screen-slug>.page.ts` (mới nếu cần —
42
+ xem quy tắc slug/kiểm tra tồn tại trước khi tạo ở `_shared/file-naming-and-folders.md`).
@@ -0,0 +1,43 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ ---
5
+
6
+ # Gen Script — Web Integration (API↔DB↔service↔queue↔UI)
7
+
8
+ **Đọc `_shared/web-conventions.md` trước.**
9
+
10
+ ## Khi nào trigger
11
+ - Convert TC integration (output `qa-designer/integration/*`), TC Automatable=Y.
12
+
13
+ ## Khi KHÔNG trigger
14
+ - Chỉ 1 endpoint/UI đơn → `functional/*` · hành trình đầu-cuối → `e2e.md`
15
+
16
+ ## Quy ước riêng — không mock (nguyên tắc quan trọng nhất của integration test)
17
+ Mock API/DB trong integration test biến nó thành **unit test trá hình** — không còn verify
18
+ được tích hợp thật. Luôn gọi network/DB thật trên môi trường test:
19
+ - **GUI↔Backend**: `page.waitForResponse(url)` để capture request/response thật khi thao tác UI.
20
+ - **DB**: client DB thật (qua fixture, connection string từ `process.env.*`), verify trực tiếp
21
+ bảng/cột — không chỉ verify qua UI hiển thị đúng (UI có thể cache sai mà DB đã đúng, hoặc
22
+ ngược lại).
23
+ - **Kafka/queue**: producer/consumer thật trong fixture, verify payload nhận được, không
24
+ giả lập message.
25
+
26
+ ## Phase 1 — Clarify
27
+ Chuỗi tích hợp & chặng cần verify; client/fixture (API/DB/Kafka) đã có chưa; data từ
28
+ `TEST_DATA_PLAN.md`.
29
+
30
+ ## Phase 2 — Generate
31
+ Mỗi TC → 1 test theo data flow: action → verify từng chặng (response → DB → event → UI).
32
+ Nhóm: happy → contract-negative (4xx/5xx + UI hiển thị đúng message) → concurrency (mô tả rõ
33
+ số request đồng thời, assert không race condition — vd unique constraint giữ nguyên).
34
+
35
+ ## Phase 3 — Self-Verify
36
+ ```bash
37
+ npx tsc --noEmit
38
+ npx playwright test automation/tests/{TICKET-ID}/integration/<feature>-<scenario>.spec.ts --list
39
+ ```
40
+ (Cần môi trường staging/DB/Kafka test khả dụng để chạy thật sau khi generate.)
41
+
42
+ ## Output
43
+ Script + client/fixture (DB/Kafka/API) trong `automation/tests/{TICKET-ID}/integration/` + `fixtures/`.
@@ -0,0 +1,42 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ ---
5
+
6
+ # Gen Script — Web Non-Functional (Performance/Security/Accessibility/Compatibility)
7
+
8
+ **Đọc `_shared/web-conventions.md` trước** (locator/wait/assertion nền tảng vẫn áp dụng).
9
+
10
+ ## Khi nào trigger
11
+ - Convert TC non-functional (output `qa-designer/non-functional.md`), TC Automatable=Y, có
12
+ **ngưỡng đo cụ thể** trong `TC_<FEATURE>.md`.
13
+
14
+ ## Công cụ theo loại
15
+
16
+ | Loại | Công cụ | Assert |
17
+ |---|---|---|
18
+ | **Performance** | `performance.timing`/`page.evaluate` đo, hoặc tích hợp k6/Artillery cho load thật | Ngưỡng cụ thể (`expect(elapsed).toBeLessThan(2000)`), không assert mơ hồ |
19
+ | **Security** | Payload injection trong constant/fixture; test trên môi trường test, KHÔNG production | Status 4xx + không tạo được record + response không lộ PII |
20
+ | **Accessibility** | `@axe-core/playwright` (`AxeBuilder`) | `expect(results.violations).toHaveLength(0)` hoặc filter đúng WCAG level (`wcag2a`/`wcag2aa`) |
21
+ | **Compatibility** | Playwright `projects` trong config (chromium/firefox/webkit), hoặc device emulation | Mỗi project = 1 target trong TC; không hardcode 1 browser |
22
+
23
+ ## Quy ước riêng
24
+ - Assertion **luôn có ngưỡng cụ thể khớp TC gốc** — không tự đặt ngưỡng khác, không
25
+ `expect(response).toBeTruthy()` mơ hồ.
26
+ - Đo elapsed time: bắt đầu/kết thúc rõ ràng, **không** bao gồm thời gian fixture setup.
27
+ - Test cần môi trường đặc biệt (load server, scanner) → `test.skip(!envReady, 'lý do')`.
28
+
29
+ ## Phase 1 — Clarify
30
+ Loại + ngưỡng + công cụ; môi trường/tải mẫu; data đặc biệt từ `TEST_DATA_PLAN.md`.
31
+
32
+ ## Phase 2 — Generate
33
+ Mỗi TC → 1 test đo + assert ngưỡng; đánh dấu test cần môi trường riêng bằng tag `@slow`.
34
+
35
+ ## Phase 3 — Self-Verify
36
+ ```bash
37
+ npx tsc --noEmit
38
+ npx playwright test automation/tests/{TICKET-ID}/non-functional/<feature>-<scenario>.spec.ts --list
39
+ ```
40
+
41
+ ## Output
42
+ `automation/tests/{TICKET-ID}/non-functional/<feature>-<scenario>.spec.ts` + helper đo/scan (`utils/measure.ts`).
@@ -0,0 +1,38 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ new_in: QC-Workflow-Proposal (8-phase)
5
+ ---
6
+
7
+ # Run — Mobile (WebdriverIO + Appium)
8
+
9
+ Skill **tự chứa** cho `/qc-run-script` khi `active_platform = app`.
10
+
11
+ ## Lệnh chạy
12
+
13
+ ```bash
14
+ npx wdio run wdio.conf.ts --spec mobile-automation/test/specs/{TICKET-ID}/...
15
+ ```
16
+
17
+ Video/screenshot on-fail cấu hình qua `afterTest` hook trong `wdio.conf.ts` (chụp screenshot
18
+ khi `passed === false`; ghi video nếu dùng service `wdio-video-reporter` hoặc quay màn hình
19
+ qua `driver.saveRecordingScreen`/tương đương simulator/emulator).
20
+
21
+ ## Đọc kết quả trước khi đề xuất phân loại Fail
22
+
23
+ Với mỗi FAIL, xem screenshot/video tại thời điểm fail + log Appium server (`appium.log`)
24
+ trước khi đoán:
25
+
26
+ | Dấu hiệu | Khả năng cao là |
27
+ |---|---|
28
+ | Element "not found" nhưng screenshot cho thấy nó **hiển thị rõ trên màn hình** | **script-bug** — sai `ValueKey`/locator, hoặc app chưa bật `Semantics` đúng cho driver `FlutterIntegration` đọc |
29
+ | Log Appium báo `automationName` không khớp app (vd dùng `UiAutomator2` cho app Flutter không bật accessibility) | **script-bug** — sai cấu hình driver, xem `_shared/mobile-conventions.md` §0 |
30
+ | Hành động đúng (tap đúng nút, đúng data) nhưng app **không phản hồi đúng spec** (không điều hướng, không lưu data) | **product-gap** |
31
+ | Permission dialog native chặn action, test không xử lý | **script-bug** — thiếu xử lý dialog, không phải bug sản phẩm |
32
+ | Fail chỉ xảy ra trên 1 device/OS version cụ thể | Có thể **product-gap** riêng cho compatibility đó — không quy chung là flaky |
33
+
34
+ ## Retry trước khi kết luận (bắt buộc — bước 0 của gate phân loại Fail)
35
+ Mobile vốn có độ trễ/nhiễu cao hơn web (cold start, animation, tốc độ máy) — trước khi đề xuất
36
+ phân loại bất kỳ Fail nào, chạy lại riêng test đó tối đa 2 lần trên cùng device/emulator. Kết
37
+ quả không nhất quán → đề xuất `flaky` (xem `/qc-run-script` §Phân loại mỗi Fail), không phải
38
+ script-bug/product-gap ngay.
@@ -0,0 +1,41 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ source: upstream/qc-base-new/Automation-Standards.md §1 + OQ-01 · Mobile-Automation-Standards.md §1 (Approved)
5
+ ---
6
+
7
+ # Report skill — TypeScript stack (Playwright HTML Report / WDIO Allure Report)
8
+
9
+ Skill **tự chứa** cho `/qc-report`. Báo cáo do **công cụ sinh** — Playwright HTML Report (web·system) hoặc Allure v2.x (app) — **không** dashboard tự viết.
10
+
11
+ ## Web — Playwright HTML Report + Trace Viewer
12
+
13
+ ```bash
14
+ npx playwright test automation/tests/{TICKET-ID}/... --reporter=html
15
+ npx playwright show-report # mở report HTML tương tác
16
+ npx playwright show-trace test-results/<nodeid>/trace.zip # debug 1 test cụ thể
17
+ ```
18
+
19
+ - Report HTML mặc định ở `playwright-report/` (self-contained, mở trực tiếp trong browser).
20
+ - Mỗi test fail có sẵn trace + screenshot đính kèm (cấu hình qua
21
+ `use: { trace: 'on-first-retry', screenshot: 'only-on-failure' }` trong `playwright.config.ts`).
22
+
23
+ ## Mobile — WebdriverIO Allure Report
24
+
25
+ ```bash
26
+ npx wdio run wdio.conf.ts --spec ...
27
+ npx allure generate ./allure-results --clean -o ./allure-report
28
+ npx allure open ./allure-report
29
+ ```
30
+
31
+ - Cần reporter `@wdio/allure-reporter` khai trong `wdio.conf.ts` (`reporters: ['allure']`).
32
+ - Screenshot/video on-fail đính kèm tự động vào report qua `afterTest` hook (xem
33
+ `qa-script-runner/mobile/run.md`).
34
+
35
+ ## Nguyên tắc chung (cả hai platform)
36
+ - Evidence trung thực: report phản ánh đúng lần chạy gần nhất, không chỉnh sửa số liệu.
37
+ - FAIL giữ nguyên trạng thái thật cho tới khi fix + chạy lại — **không fake-pass**.
38
+ - `playwright-report/`, `test-results/`, `allure-results/`, `allure-report/` đã gitignore
39
+ (artifact nặng) — không commit vào repo.
40
+ - Tóm tắt bắt buộc: **TOTAL / PASS / FAIL / SKIP / FLAKY** + duration, và với mỗi FAIL: phân
41
+ loại đã xác nhận (script-bug/product-gap/flaky) từ `/qc-run-script`, kèm `BUG-{id}` nếu đã file.
@@ -0,0 +1,48 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-09
4
+ new_in: QC-Workflow-Proposal (8-phase)
5
+ ---
6
+
7
+ # Run — Web (Playwright Test)
8
+
9
+ Skill **tự chứa** cho `/qc-run-script` khi `active_platform = web`.
10
+
11
+ ## Lệnh chạy
12
+
13
+ ```bash
14
+ npx playwright test automation/tests/{TICKET-ID}/... --reporter=html,list
15
+ ```
16
+
17
+ Trace tự động bật qua `playwright.config.ts` (`use: { trace: 'on-first-retry' }` hoặc `'on'`
18
+ nếu muốn trace mọi lần) → mỗi test có `test-results/<nodeid>/trace.zip` khi fail.
19
+
20
+ ## Đọc kết quả trước khi đề xuất phân loại Fail
21
+
22
+ Với mỗi FAIL, **mở trace trước khi đoán**:
23
+
24
+ ```bash
25
+ npx playwright show-trace test-results/<nodeid>/trace.zip
26
+ ```
27
+
28
+ Trace viewer cho: timeline hành động, DOM snapshot tại từng bước, network request/response,
29
+ console log. Dấu hiệu phân biệt:
30
+
31
+ | Dấu hiệu trong trace | Khả năng cao là |
32
+ |---|---|
33
+ | Locator "not found" nhưng DOM snapshot cho thấy element **có tồn tại** với selector khác | **script-bug** — selector sai/lỗi thời do UI đổi cấu trúc, không phải bug sản phẩm |
34
+ | Element thực sự **không xuất hiện** sau hành động đúng spec (nút bấm không có phản hồi, API trả lỗi mà spec nói phải thành công) | **product-gap** — hành vi thực tế ≠ spec |
35
+ | Timeout chờ network response, response **không bao giờ tới** | **product-gap** nếu spec yêu cầu response — hoặc **script-bug** nếu URL/endpoint chờ sai |
36
+ | Assertion so giá trị: actual đúng theo spec nhưng expected trong test viết sai | **script-bug** |
37
+ | Flaky ngẫu nhiên (pass khi chạy lẻ, fail khi chạy song song) | **script-bug** — thiếu cách ly data/test independence, xem `_shared/web-conventions.md` §Common Pitfalls #5-6 |
38
+
39
+ Không kết luận nếu bằng chứng không đủ rõ — báo "không chắc, cần điều tra thêm" thay vì đoán.
40
+
41
+ ## Retry trước khi kết luận (bắt buộc — bước 0 của gate phân loại Fail)
42
+ Trước khi đề xuất phân loại bất kỳ Fail nào, chạy lại riêng test đó tối đa 2 lần:
43
+ ```bash
44
+ npx playwright test <file> -g "<title>" --repeat-each=1
45
+ ```
46
+ Kết quả không nhất quán (fail→pass hoặc ngược lại) → đề xuất `flaky`, không phải
47
+ script-bug/product-gap (xem `/qc-run-script` §Phân loại mỗi Fail). Chỉ khi fail **nhất quán**
48
+ qua các lần retry mới tiếp tục điều tra để phân biệt script-bug/product-gap.
@@ -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.
@@ -77,7 +77,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
77
77
 
78
78
  | Mức | Lệnh nào | `--yes` bỏ qua được? |
79
79
  |---|---|:---:|
80
- | **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
80
+ | **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ó) |
81
81
  | **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
82
82
  | **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
83
83
 
@@ -85,6 +85,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
85
85
  `--` 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
86
86
  headless: `claude -p "/generate-code UC1 --yes"`.
87
87
 
88
+ > **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
89
+ > tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
90
+ > ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
91
+ > mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
92
+ > `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
93
+
88
94
  > **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: …*`
89
95
  > 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
90
96
  > **nghĩa là gì**.
@@ -58,6 +58,49 @@ Theo thứ tự, dừng ở cái đầu tiên khớp:
58
58
  Lưu `active_platform`. Từ đây, **mọi** phép đọc `.feature` chỉ đọc thư mục
59
59
  `bdd/{active_platform}/` — không trộn SC chéo nền.
60
60
 
61
+ > **Nền `system` còn MỘT câu hỏi nữa, và nó ở trạm 3.** `system` không đồng nghĩa với API — nó
62
+ > còn chứa **job tự chạy** và **consumer hàng đợi**, hai thứ không có endpoint nào. Khi không suy
63
+ > được, `/qc-design-test` hỏi QC rồi ghi câu trả lời vào `Tags` của TC. Xem
64
+ > `/qc-design-test` §Nền `system`. Ghi ở đây để người đọc luật nền biết **còn một câu chưa xong**,
65
+ > chứ không phải phân giải xong nền là hết.
66
+
67
+ ### 2b — Nền → module QC → lane skill *(bảng DUY NHẤT, đừng chép lại ở lệnh)*
68
+
69
+ | `active_platform` | module QC | `layout` | lane skill |
70
+ |---|---|---|---|
71
+ | `web` · `webview` | `qc-playwright-ts` | `layout.web` — `automation/` | `qa-script-designer/web/*` |
72
+ | `app` · `app-ios` · `app-android` | `qc-wdio-appium` | `layout.mobile` — `mobile-automation/` | `qa-script-designer/mobile/*` |
73
+ | `system` + lane `api` | `qc-playwright-ts` | `layout.api` — `api-automation/` | `qa-script-designer/api/*` |
74
+ | `system` + lane `job` · `queue` | `qc-playwright-ts` | `layout.api` — `api-automation/` | ⚠️ **chưa có lane script** — xem dưới |
75
+
76
+ > **Vì sao bảng này ở đây chứ không ở lệnh.** Cùng lý do mục §2 tồn tại: luật phân giải nền
77
+ > từng được copy-paste ở 5 lệnh rồi câu chữ lệch nhau. Ba lệnh script trỏ vào đây, **không
78
+ > chép lại**.
79
+ >
80
+ > **Vì sao KHÔNG có key cấu hình riêng.** Từng có một lời hứa `tech_stack.qc_module` trong
81
+ > comment của module cũ, nhưng nó **chưa bao giờ được cài** — và không nên cài: `active_platform`
82
+ > đã trả lời xong câu này ở §2 và đã **khoá cho cả pass QC**. Một field thứ hai là hai đáp án
83
+ > cho một câu hỏi, và khi chúng lệch nhau thì artifact ghi vào thư mục của nền này trong khi
84
+ > script sinh theo layout của nền kia — hỏng **im lặng**.
85
+ >
86
+ > 🔴 **`system` KHÔNG đồng nghĩa với API — sửa 2026-09-17 sau ca thật LESS-22.** Quyết định
87
+ > `S-API` ánh xạ `system → lane api` vô điều kiện, và nó **sai**: `system` còn chứa **job tự
88
+ > chạy** *(không ai gọi)* và **consumer hàng đợi** *(nằm chờ message)*. Cả ba tài liệu chuẩn dùng
89
+ > để chốt `S-API` đều **chỉ nói về API**, nên không ai thấy hai hình dạng kia.
90
+ >
91
+ > **Tầng thiết kế TC đã có đủ ba** *(trạm 3 hỏi QC rồi ghi lane — xem `/qc-design-test` §Nền
92
+ > `system`)*: `functional/api` · `functional/job` · `integration/queue`.
93
+ >
94
+ > **Tầng sinh script mới có một** — `qa-script-designer/api/*`. Lane `job` và `queue` chạy tới
95
+ > trạm 6 thì **chưa có skill**. Đây là **lỗ đã biết, ghi ra thay vì để trạm 6 lặng lẽ dùng lane
96
+ > `api`**: gặp TC lane `job`/`queue`, trạm 6 phải **DỪNG** và nói rõ chưa hỗ trợ, không được
97
+ > sinh API Object cho một thứ không có endpoint.
98
+
99
+ > **`web` và `system` dùng chung module, khác `layout`.** Đó là chủ ý: cùng Playwright + TS
100
+ > *(AD-API-001 — "tái dùng infrastructure với Web testing")*, nên tách làm hai module là khai
101
+ > dãy phiên bản hai lần. Nhưng **API Object ≠ Page Object** và `api-automation/` là thư mục
102
+ > gốc riêng, nên `layout` và lane skill phải tách.
103
+
61
104
  ---
62
105
 
63
106
  ## 3 — `qc_artifact_dir`
@@ -114,7 +157,7 @@ và đánh dấu trong artifact là dựa trên BDD nháp. *(Tên cờ chung cho
114
157
 
115
158
  ### 4b — Cổng cấp UC: **cái UC vừa được gọi tên** có làm được không?
116
159
 
117
- Bốn lệnh nhận target là **UC-ID** — `/qc-design-test` · `/qc-review` · `/qc-run-test` · `/qc-report`
160
+ Bảy lệnh nhận target là **UC-ID** — `/qc-design-test` · `/qc-review-testcase` · `/qc-review-script` · `/qc-design-script` · `/qc-run-script` · `/qc-run-manualtest` · `/qc-report`
118
161
  — phải đối chiếu target với **bảng vừa in ở trên**. Hai lệnh cấp PRD (`/qc-analyze` · `/qc-plan`)
119
162
  **bỏ qua mục này**: target của chúng là `TICKET-ID`, và cổng 4a đã trả lời đúng câu hỏi của chúng.
120
163
 
@@ -141,7 +184,7 @@ Bốn lệnh nhận target là **UC-ID** — `/qc-design-test` · `/qc-review`
141
184
  > đi thẳng vào một spec chưa ai duyệt.
142
185
  >
143
186
  > Cái giá không dừng ở "thiết kế trên bản nháp". `Guard SC coverage` của trạm 3 sẽ **khẳng định**
144
- > `khớp K/K` trên spec chưa duyệt, và `/qc-run-test` sẽ ghi `qc_status = pass` **chính thức** vào sổ
187
+ > `khớp K/K` trên spec chưa duyệt, và `/qc-run-script` sẽ ghi `qc_status = pass` **chính thức** vào sổ
145
188
  > trace cho nó. Đó là **báo cáo sai** — `rules/workflow.md` §*"ai KHẲNG ĐỊNH một giá trị dương phải
146
189
  > được phép khẳng định"*.
147
190
  >
@@ -17,7 +17,7 @@ Câu chưa ai trả lời là *"**tài liệu thiết kế test** còn khớp kh
17
17
 
18
18
  | Tín hiệu | Nghĩa | Việc phải làm |
19
19
  |---|---|---|
20
- | `qc_status = not_run` | kết quả cũ hết hiệu lực | **chạy lại** `/qc-run-test` |
20
+ | `qc_status = not_run` | kết quả cũ hết hiệu lực | **chạy lại** `/qc-run-script` |
21
21
  | **stamp lệch** | TC/gap/plan mô tả spec cũ | **viết lại** — `/qc-analyze` hoặc `/qc-design-test` |
22
22
 
23
23
  Thiếu vế sau thì người ta thấy `not_run` và **chạy lại** — đúng phản xạ, sai việc. Một bộ TC lỗi thời
@@ -111,8 +111,8 @@ Với mỗi artifact mà lệnh này đọc:
111
111
 
112
112
  | Trạm | Lệch thì | Vì sao |
113
113
  |---|---|---|
114
- | `/qc-plan` · `/qc-design-test` · `/qc-review` | **⚠️ cảnh báo, đi tiếp** | Cùng họ `TECHDOC_DRIFT`/`BDD_DRIFT` — 13/17 cờ audit không chặn. Thiết kế TC trên bản hơi cũ vẫn ra sản phẩm dùng được; chặn ở đây là **ồn** |
115
- | `/qc-run-test` | **chặn `pass`, KHÔNG chặn chạy** | Lớp **báo cáo sai** |
114
+ | `/qc-plan` · `/qc-design-test` · `/qc-review-testcase` | **⚠️ cảnh báo, đi tiếp** | Cùng họ `TECHDOC_DRIFT`/`BDD_DRIFT` — 13/17 cờ audit không chặn. Thiết kế TC trên bản hơi cũ vẫn ra sản phẩm dùng được; chặn ở đây là **ồn** |
115
+ | `/qc-run-script` | **chặn `pass`, KHÔNG chặn chạy** | Lớp **báo cáo sai** |
116
116
 
117
117
  ```
118
118
  ⚠️ Stamp lệch — {file} dựng trên {nguồn} {ver_cũ}, hiện tại {ver_mới}.
@@ -120,7 +120,7 @@ Với mỗi artifact mà lệnh này đọc:
120
120
  Nên chạy lại: {lệnh} (đi tiếp vẫn được, nhưng {hệ quả cụ thể})
121
121
  ```
122
122
 
123
- **`/qc-run-test` — nhập vào cơ chế đã có, không phát minh cơ chế mới.** Stamp lệch xử lý **y hệt**
123
+ **`/qc-run-script` — nhập vào cơ chế đã có, không phát minh cơ chế mới.** Stamp lệch xử lý **y hệt**
124
124
  row `DRIFT`/`ORPHANED` của `positive_assertion_guards` + lint **T12** (G55): test vẫn chạy, nhưng
125
125
  xanh → ghi `not_run` chứ **không** ghi `pass`, và **không đóng bug nào** ở lần chạy đó.
126
126
 
@@ -54,9 +54,9 @@ Discovery → PRD → [Design Spec] → BDD → Tech Design ─┬─ Code → D
54
54
  ```
55
55
 
56
56
  **Sơ đồ rẽ đôi, không phải một dòng thẳng.** `/map-testids` chốt hợp đồng test-id §4.5.6 ở Tech
57
- Design, nên **Code** và **QC Design** (`/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review`)
57
+ Design, nên **Code** và **QC Design** (`/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review-testcase`)
58
58
  đọc cùng một bản đã đóng băng và **chạy song song, không chờ nhau**. Hai nhánh gặp lại ở **QC Run**
59
- (`/qc-run-test` → `/qc-report`) — trạm duy nhất cần code chạy được.
59
+ (`/qc-run-script` → `/qc-report`) — trạm duy nhất cần code chạy được.
60
60
 
61
61
  Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **phase của nó** trong sơ đồ trên:
62
62
 
@@ -69,8 +69,8 @@ Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **pha
69
69
  | Tech Design | `/generate-tech-docs` · `/map-testids` · `/review-tech-docs` |
70
70
  | Code | `/generate-code` · `/review-code` |
71
71
  | Dev Self-Check | `/dev-gen-test` · `/dev-run-test` · `/dev-smoke-test` |
72
- | QC Design | `/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review` |
73
- | QC Run | `/qc-run-test` · `/qc-report` |
72
+ | QC Design | `/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review-testcase` · `/qc-automation-assess` |
73
+ | QC Run | `/qc-design-script` · `/qc-review-script` · `/qc-run-script` · `/qc-run-manualtest` · `/qc-report` |
74
74
  | Trace Audit | `/validate-traces` |
75
75
 
76
76
  Với **lệnh review**, thêm vòng review 3 bước và đánh dấu bước hiện tại, vd:
@@ -97,10 +97,11 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
97
97
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` nếu APPROVED; sinh lại nếu NEEDS_FIX |
98
98
  | /qc-analyze | `/qc-plan {TICKET-ID} {platform}` — **cấp PRD**, không phải `{UC-ID}` (xử lý các gap blocker 🔴 trước) |
99
99
  | /qc-plan | `/qc-design-test {UC-ID}` |
100
- | /qc-design-test | `/qc-review {UC-ID}` (review test-case) |
101
- | /qc-review (test-case) | `/qc-run-test {UC-ID}` nếu APPROVED; sửa TC nếu NEEDS_FIX |
102
- | /qc-run-test | `/qc-report {UC-ID}` rồi `/qc-review {UC-ID}` (review script) |
103
- | /qc-review (script) | `/qc-report {UC-ID}` rồi tạo PR nếu APPROVED |
100
+ | /qc-design-test | `/qc-review-testcase {UC-ID}` |
101
+ | /qc-automation-assess | `/qc-design-script {TICKET-ID}` (Automatable: Y) · `/qc-run-manualtest {UC-ID}` (N) |
102
+ | /qc-review-testcase | `/qc-automation-assess {TICKET-ID}` nếu `APPROVED` hoặc `APPROVED_WITH_SUGGESTIONS`; sửa TC bằng `/qc-design-test` nếu `REVISION_REQUIRED` · `REJECTED` |
103
+ | /qc-run-script | `/qc-run-manualtest {UC-ID}` (TC Automatable: N) rồi `/qc-report {UC-ID}` |
104
+ | /qc-review-script | `/qc-report {UC-ID}` rồi tạo PR nếu `APPROVED` hoặc `APPROVED_WITH_SUGGESTIONS`; sửa script nếu `REVISION_REQUIRED` · `REJECTED` |
104
105
  | /qc-report | `/validate-traces {UC-ID}` để làm mới Living Docs (qc_status) |
105
106
  | /generate-tech-docs | `/map-testids {UC-ID}` — chốt hợp đồng test-id §4.5.6 **trước** khi review |
106
107
  | /map-testids | `/review-tech-docs {tech-design-file}` (review CẢ hợp đồng vừa ghi) |
@@ -112,7 +113,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
112
113
  | /review-code | `/dev-smoke-test {UC-ID}` hoặc tạo PR |
113
114
  | /dev-smoke-test | Tạo PR và link tới ticket |
114
115
  | /validate-traces | **Cờ 🔴 trước (chặn PR):** SEAM_UNWIRED → nối binding sang class thật, xoá/thay stub · STUB_UNRESOLVED → `/generate-code {owner_uc}` (lấp logic tại chỗ + xoá hàm song song) · ORPHANED/TRACE_ORPHAN → quyết định thủ công (xoá code+test, đưa scenario trở lại `.feature`, hoặc sửa `sc_id` của tag). **Rồi:** DRIFT/UNTRACKED → `/generate-code {UC-ID}` · BDD_DRIFT → `/generate-code {feature-file}` · tech-doc lỗi thời vs BDD → `/generate-tech-docs` → `/review-tech-docs` · PRD drift → `/generate-bdd {prd-file}` · GAP → `/dev-gen-test {UC-ID}`. **Chỉ tạo PR khi mọi cờ 🔴 = 0** |
115
- | /fix-bug | `/dev-run-test {UC-ID}` (dev_selftest vừa reset về not_run) → tạo PR; nếu fix một `{BUG-ID}` → QC chạy `/qc-run-test {UC-ID}` để verify + đóng bug |
116
+ | /fix-bug | `/dev-run-test {UC-ID}` (dev_selftest vừa reset về not_run) → tạo PR; nếu fix một `{BUG-ID}` → QC chạy `/qc-run-script {UC-ID}` để verify + đóng bug |
116
117
  | /debug | `/fix-bug {ticket-id}` nếu cần sửa |
117
118
  | /report-bug | Gửi cho dev (`/fix-bug {BUG-ID}`); nếu thiếu coverage → `/propose-scenario {UC-ID}` |
118
119
  | /propose-scenario | **Case A** (thiếu scenario cho AC có sẵn) → báo PO/Dev review trong `feedback/bdd-proposals/`; `/generate-bdd` tự chèn khi `Status: accepted`. **Case B** (requirement mới) → `feedback/prd-change-requests/` — PO phải đưa vào PRD trước, KHÔNG tự vào BDD được; `/validate-traces` nhắc lại kèm số ngày chờ chừng nào `Status: Open` |
@@ -25,7 +25,7 @@ Trước khi đẩy sang QC chính thức, Dev cần một vòng **kiểm nhanh
25
25
 
26
26
  > **`dev_selftest` ≠ `qc_status`.** Hai trục **độc lập**: dev smoke (nhanh, tự kiểm) vs QC chính thức (Playwright, evidence). Không lấn quyền nhau.
27
27
  >
28
- > ⚠️ **Nhưng "độc lập" chỉ đúng với `status` về KẾT QUẢ CHẠY, không đúng về QUYỀN KHẲNG ĐỊNH** *(GAPS-v4 G55)*. `pass` mang nghĩa *"scenario này đã được nghiệm thu theo spec **hiện tại**"* — nên trên row `DRIFT`/`ORPHANED`, `/dev-run-test` và `/qc-run-test` **không được** ghi `pass`; chúng hạ về `not_run`. `fail`/`skip` thì ghi bình thường. `lint-trace` **T12** bắt trạng thái `DRIFT + pass` ở sổ thật, bất kể ai ghi ra.
28
+ > ⚠️ **Nhưng "độc lập" chỉ đúng với `status` về KẾT QUẢ CHẠY, không đúng về QUYỀN KHẲNG ĐỊNH** *(GAPS-v4 G55)*. `pass` mang nghĩa *"scenario này đã được nghiệm thu theo spec **hiện tại**"* — nên trên row `DRIFT`/`ORPHANED`, `/dev-run-test` và `/qc-run-script` và `/qc-run-manualtest` **không được** ghi `pass`; chúng hạ về `not_run`. `fail`/`skip` thì ghi bình thường. `lint-trace` **T12** bắt trạng thái `DRIFT + pass` ở sổ thật, bất kể ai ghi ra.
29
29
 
30
30
  ---
31
31
 
@@ -3,13 +3,13 @@
3
3
  # Bước 8 · QC Automation — Dây chuyền kiểm thử 6 trạm (QC Pipeline)
4
4
 
5
5
  > **Tóm tắt.** Dây chuyền QC tự động 6 trạm: phân rã yêu cầu → lập kế hoạch → thiết kế test case → review → chạy Playwright → report. Ghi `qc_status` **chính thức** + evidence.
6
- > **Commands:** `/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review` → `/qc-run-test` → `/qc-report`
6
+ > **Commands:** `/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review-testcase` → `/qc-automation-assess` → `/qc-design-script` → `/qc-review-script` → `/qc-run-script` → `/qc-report`
7
7
 
8
8
  | | |
9
9
  |---|---|
10
10
  | **Giai đoạn** | QC Automation |
11
11
  | **Owner** | 👤 QA / Tester |
12
- | **Đầu vào** | **Trạm 1–4:** spec (PRD/BDD `approved`) + **hợp đồng test-id §4.5.6** (đóng băng ở bước 5) — **chưa cần code**.<br/>**Trạm 5 `/qc-run-test` thêm:** code đã chạy được — **trạm duy nhất** cần |
12
+ | **Đầu vào** | **Trạm 1–4:** spec (PRD/BDD `approved`) + **hợp đồng test-id §4.5.6** (đóng băng ở bước 5) — **chưa cần code**.<br/>**Trạm 6–8 `/qc-design-script` · `/qc-run-script` thêm:** code đã chạy được — **hai trạm duy nhất** cần |
13
13
  | **Đầu ra** | Test case, script Playwright, `qc_status`, evidence, product-gap |
14
14
  | **HITL** | 🟠 Vừa — cổng review case & script trước khi chạy |
15
15
 
@@ -17,11 +17,11 @@
17
17
 
18
18
  ## Mục đích (Purpose)
19
19
 
20
- Đây là **kiểm thử chính thức** (khác với dev smoke). Dùng module **`qc-playwright`** (Python + pytest-playwright + Page Object) — độc lập với module implementation của dev. Bước này:
20
+ Đây là **kiểm thử chính thức** (khác với dev smoke). Dùng module QC theo nền — **`qc-playwright-ts`** (web·system) hoặc **`qc-wdio-appium`** (app), phân giải ở `steps/qc-scope.md` §2b — độc lập với module implementation của dev. Bước này:
21
21
 
22
22
  - Phân rã yêu cầu thành test case bám scenario, phát hiện **gap tài liệu**.
23
23
  - Chạy test thật, ghi **`qc_status` chính thức** + **evidence**.
24
- ⚠️ Nhưng `/qc-run-test` **đọc cột `status` trước khi ghi `pass`** *(GAPS-v4 G55)*: row `DRIFT`/`ORPHANED` + test xanh → hạ về `not_run`, và **không** đóng bug nào ở lần chạy đó. `fail`/`skip` ghi bình thường.
24
+ ⚠️ Nhưng `/qc-run-script` và `/qc-run-manualtest` **đọc cột `status` trước khi ghi `pass`** *(GAPS-v4 G55)*: row `DRIFT`/`ORPHANED` + test xanh → hạ về `not_run`, và **không** đóng bug nào ở lần chạy đó. `fail`/`skip` ghi bình thường.
25
25
  - Phân loại FAIL thành **ba** nhãn — `script-bug` · `product-gap` · `flaky` — **sau khi đã chạy lại tối đa 2 lần**. Một test đỏ **một lần** chưa nói được nó đỏ vì cái gì.
26
26
  - Đẩy **product-gap** ngược về PO/Dev.
27
27
 
@@ -32,15 +32,15 @@
32
32
  - **UC-ID** + platform (QC pass khoá 1 platform).
33
33
  - Spec: PRD / `.feature` (từ spec repo, qua `spec_source`).
34
34
  - **Hợp đồng test-id**: `@trace.testid_attr` (header tech-doc, **tên** thuộc tính) + §4.5.6 Test Selectors (**giá trị** test-id, cột *Serves SC* là chỉ mục ngược). Đã chốt ở [bước 5](05-tech-docs.md) **trước khi có code**.
35
- - Code đã sinh & chạy được — **chỉ `/qc-run-test` cần**. Bốn trạm đầu (`/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review`) chạy **song song với FE** vì chỉ cần spec + hợp đồng test-id. Đó là chỗ hai nhánh của [bước 5](05-tech-docs.md) gặp lại.
36
- - `qc_dir` (working docs của QC) + module `qc-playwright`.
35
+ - Code đã sinh & chạy được — **chỉ `/qc-design-script` và `/qc-run-script` cần**. Bốn trạm đầu (`/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review-testcase`) chạy **song song với FE** vì chỉ cần spec + hợp đồng test-id. Đó là chỗ hai nhánh của [bước 5](05-tech-docs.md) gặp lại.
36
+ - `qc_dir` (working docs của QC) + module QC theo nền (`qc-playwright-ts` · `qc-wdio-appium`).
37
37
 
38
38
  ## Output (Đầu ra)
39
39
 
40
40
  | Artifact | Nội dung |
41
41
  |----------|----------|
42
42
  | `docs/{TICKET-ID}/{platform}/…` | `REQUIREMENT_ANALYSIS.md`, `DOC_GAP.md`, `TEST_PLAN.md`, `test-cases/*.Test.md` — **mỗi loại đúng một file cho cả (PRD × nền)**, các UC là hàng/mục bên trong (cột `UC`) |
43
- | Script Python pytest-playwright | Sinh từ `.Test.md` đã review |
43
+ | Script TypeScript (`*.spec.ts`) | Sinh từ `.Test.md` đã review |
44
44
  | Cột `qc_status` trong `.trace/…/{UC-ID}-{platform}.tsv` | Trạng thái QC **chính thức** |
45
45
  | Evidence + report | `/qc-report` — kèm product-gap đẩy về PO/Dev |
46
46
 
@@ -75,8 +75,9 @@ Dây chuyền **6 trạm**, output trạm trước là input trạm sau:
75
75
  | 1 | `/qc-analyze` | Phân rã yêu cầu + phát hiện **gap tài liệu** (`DOC_GAP.md`) | **Guard BR-tag** |
76
76
  | 2 | `/qc-plan` | Đánh giá **rủi ro** + câu hỏi cho dev (`TEST_PLAN.md`) | — |
77
77
  | 3 | `/qc-design-test` | Thiết kế **test case** dạng Markdown (`*.Test.md`) | **Guard SC coverage** |
78
- | 4 | `/qc-review` | 🛑 **Cổng review** hai chiều: test case & script trước khi chạy | — |
79
- | 5 | `/qc-run-test` | Sinh & chạy **pytest-playwright**, ghi **`qc_status`** chính thức | **chạy lại ×2 + 3 nhãn FAIL** |
78
+ | 4 | `/qc-review-testcase` | 🛑 **Cổng review test case** verdict `APPROVED`/`NEEDS_FIX` điều kiện tiên quyết của trạm sau | — |
79
+ | 6 | `/qc-review-script` | 🛑 **Cổng review script** biên bản riêng `REVIEW_SCRIPT_<FEATURE>.md` | |
80
+ | 5–8 | `/qc-design-script` · `/qc-run-script` | Sinh rồi chạy **script TypeScript**, ghi **`qc_status`** chính thức | **chạy lại ×2 + 3 nhãn FAIL** |
80
81
  | 6 | `/qc-report` | Report + **evidence**, đẩy **product-gap** về PO/Dev | — |
81
82
 
82
83
  ### Hai Guard cơ học — chống bỏ sót **im lặng**
@@ -120,14 +121,14 @@ Cả sáu trạm nạp chung `skills/qc/_shared/self-review-principles.md` và c
120
121
 
121
122
  > ⚠️ **Self-review KHÔNG thay Guard.** Guard là phép **đếm cơ học**, có hệ quả bắt buộc. Self-review là lượt đọc lại **rộng hơn nhưng mềm hơn**. 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 — file đó ghi rõ ranh giới này ngay ở đầu.
122
123
 
123
- - Stack QC bắt buộc theo `modules/qc-playwright/stack-profile.yaml`: Python + pytest-playwright + Page Object; mỗi test độc lập; gom theo (role, account) để auth không xen kẽ.
124
+ - Stack QC bắt buộc theo `stack-profile.yaml` của module đã phân giải (§2b): TypeScript + Playwright Test (web·system) / WebdriverIO + Appium (app); mỗi test độc lập; gom theo (role, account) để auth không xen kẽ.
124
125
  - **Locator lấy từ hợp đồng, không dò DOM**: thứ tự ưu tiên là §4.5.6 → `@trace.testid_attr` → mới tới các cách khác. Skill `qa-runner` đã bỏ hết chỉ dẫn "dò DOM trước".
125
126
 
126
127
  ---
127
128
 
128
129
  ## HITL / Gate
129
130
 
130
- - 🛑 `/qc-review` — **cổng review** case & script: không chạy test kém.
131
+ - 🛑 `/qc-review-testcase` · `/qc-review-script` — **hai cổng review riêng**: không chạy test kém, và trạm sau đọc được verdict của ĐÚNG vai nó cần.
131
132
  - 🛑 **Xác nhận phân loại FAIL** — mỗi FAIL phải được người chốt nhãn trước khi ghi `qc_status`. Đây là cổng chặn hiếm hoi được **thêm vào** (framework vốn đang giảm số cổng), vì **cả hai hướng sai đều không đảo ngược rẻ**.
132
133
  - **Không fake-pass**: FAIL là product-gap → giữ nguyên FAIL + evidence, đẩy về PO/Dev.
133
134
 
@@ -137,7 +138,7 @@ Cả sáu trạm nạp chung `skills/qc/_shared/self-review-principles.md` và c
137
138
 
138
139
  - ❌ Lẫn `qc_status` với `dev_selftest` — hai trục độc lập.
139
140
  - ❌ Sửa script cho "xanh" khi thực chất là product-gap → giấu lỗi sản phẩm.
140
- - ❌ Chạy `/qc-run-test` khi chưa qua cổng `/qc-review`.
141
+ - ❌ Chạy `/qc-design-script` khi chưa qua cổng `/qc-review-testcase`.
141
142
  - ❌ **Kết luận từ một lần chạy đỏ** — chưa loại nhiễu thì chưa phân biệt được `flaky` với lỗi thật.
142
143
  - ❌ **Tự dò selector từ DOM** thay vì đọc §4.5.6 — script giòn, dev đổi một class là vỡ mà không ai báo.
143
144
  - ❌ Dùng self-review làm lý do **bỏ qua** một Guard.