@educa-corp/sdd-framework 0.9.5 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/bin/build.js +11 -1
  2. package/bin/lint-trace.js +397 -28
  3. package/bin/self-check.js +623 -16
  4. package/bin/trace-schema.json +3187 -1981
  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 +70 -2
  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 +44 -5
  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 +44 -4
  21. package/core/commands/learn.md +7 -1
  22. package/core/commands/map-testids.md +96 -13
  23. package/core/commands/propose-scenario.md +7 -1
  24. package/core/commands/qc-analyze.md +516 -426
  25. package/core/commands/qc-automation-assess.md +356 -0
  26. package/core/commands/qc-design-script.md +400 -0
  27. package/core/commands/qc-design-test.md +482 -248
  28. package/core/commands/qc-plan.md +141 -94
  29. package/core/commands/qc-report.md +9 -3
  30. package/core/commands/{qc-review.md → qc-review-script.md} +172 -132
  31. package/core/commands/qc-review-testcase.md +409 -0
  32. package/core/commands/qc-run-manualtest.md +401 -0
  33. package/core/commands/{qc-run-test.md → qc-run-script.md} +200 -232
  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 +27 -6
  41. package/core/modules/qc-playwright/stack-profile.yaml +1 -1
  42. package/core/rules/workflow.md +42 -2
  43. package/core/skills/qc/_shared/self-review-principles.md +2 -2
  44. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +10 -2
  45. package/core/skills/qc/qa-analyst/spec-issue-reporter.md +1 -1
  46. package/core/skills/qc/qa-automation-assess/matrix.md +120 -0
  47. package/core/skills/qc/qa-designer/e2e/journey.md +1 -1
  48. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
  49. package/core/skills/qc/qa-designer/functional/api.md +1 -1
  50. package/core/skills/qc/qa-designer/functional/gui-feature.md +1 -1
  51. package/core/skills/qc/qa-designer/functional/gui-screen.md +1 -1
  52. package/core/skills/qc/qa-designer/integration/api.md +1 -1
  53. package/core/skills/qc/qa-designer/integration/db.md +1 -1
  54. package/core/skills/qc/qa-designer/integration/gui.md +1 -1
  55. package/core/skills/qc/qa-designer/integration/kafka.md +1 -1
  56. package/core/skills/qc/qa-designer/non-functional.md +1 -1
  57. package/core/skills/qc/qa-designer/shared/duplicate-check-procedure.md +33 -5
  58. package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +34 -5
  59. package/core/skills/qc/qa-planner/test-plan.md +7 -0
  60. package/core/skills/qc/qa-reviewer/script/e2e.md +1 -1
  61. package/core/skills/qc/qa-reviewer/script/exploratory.md +1 -1
  62. package/core/skills/qc/qa-reviewer/script/functional.md +1 -1
  63. package/core/skills/qc/qa-reviewer/script/integration.md +1 -1
  64. package/core/skills/qc/qa-reviewer/script/non-functional.md +1 -1
  65. package/core/skills/qc/qa-reviewer/shared/review-file-template.md +3 -3
  66. package/core/skills/qc/qa-reviewer/test-case/e2e.md +1 -1
  67. package/core/skills/qc/qa-reviewer/test-case/functional.md +1 -1
  68. package/core/skills/qc/qa-reviewer/test-case/integration.md +1 -1
  69. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +1 -1
  70. package/core/skills/qc/qa-runner/e2e.md +2 -2
  71. package/core/skills/qc/qa-runner/functional/gui-feature.md +4 -4
  72. package/core/skills/qc/qa-runner/functional/gui-screen.md +4 -4
  73. package/core/skills/qc/qa-runner/integration.md +1 -1
  74. package/core/skills/qc/qa-runner/non-functional.md +1 -1
  75. package/core/steps/context-loader.md +1 -1
  76. package/core/steps/gate.md +7 -1
  77. package/core/steps/qc-scope.md +67 -11
  78. package/core/steps/qc-stamp.md +142 -0
  79. package/core/steps/report-footer.md +19 -10
  80. package/core/templates/tech-design.template.md +3 -3
  81. package/docs/01-getting-started/quickstart.md +4 -3
  82. package/docs/02-concepts/architecture.md +14 -0
  83. package/docs/02-concepts/glossary.md +8 -0
  84. package/docs/02-concepts/overview.md +3 -2
  85. package/docs/02-concepts/pipeline-steps/04-bdd.md +1 -1
  86. package/docs/02-concepts/pipeline-steps/05-tech-docs.md +21 -5
  87. package/docs/02-concepts/pipeline-steps/06-code.md +12 -2
  88. package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +1 -1
  89. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +65 -16
  90. package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +3 -3
  91. package/docs/02-concepts/pipeline-steps/README.md +4 -3
  92. package/docs/02-concepts/traceability.md +2 -2
  93. package/docs/03-guides/architect.md +2 -2
  94. package/docs/03-guides/developer.md +6 -3
  95. package/docs/03-guides/tester-qa.md +23 -10
  96. package/docs/04-reference/commands.md +9 -4
  97. package/docs/04-reference/trace-schema.md +5 -5
  98. package/docs/explain/07-generate-tech-docs.md +5 -3
  99. package/docs/explain/08-review-tech-docs.md +15 -3
  100. package/docs/explain/09-generate-code.md +30 -4
  101. package/docs/explain/10-review-code.md +1 -1
  102. package/docs/explain/11-map-testids.md +72 -70
  103. package/docs/explain/12-dev-gen-test.md +1 -1
  104. package/docs/explain/15-qc-analyze.md +14 -2
  105. package/docs/explain/16-qc-plan.md +5 -1
  106. package/docs/explain/17-qc-design-test.md +30 -7
  107. package/docs/explain/18-qc-review.md +43 -17
  108. package/docs/explain/19-qc-run-test.md +38 -12
  109. package/docs/explain/20-qc-report.md +8 -5
  110. package/docs/explain/23-fix-bug.md +2 -2
  111. package/docs/explain/README.md +6 -3
  112. package/docs/plans/qc-surgery/01-checklist.md +70 -17
  113. package/package.json +1 -1
@@ -1,11 +1,13 @@
1
1
  # /review-context — Review PRD hoặc BDD về Chất lượng & Tính nhất quán
2
2
 
3
- **Chế độ phân tích READ-ONLY — ghi file findings, KHÔNG sửa target.**
3
+ **Hai chế độ.** *Phân tích*chỉ đọc target, ghi file findings. *`--resume`* — **áp fix THẲNG vào target và bump version**. Nhãn "read-only" cũ chỉ đúng cho chế độ đầu (sửa 2026-09-16).
4
4
  **Dùng `--resume` để áp dụng các finding được chấp nhận.**
5
5
 
6
6
  ## Gate
7
7
 
8
- *Checkpoint: **không chặn** — read-only (ghi findings vào .agent/review/). Gate Bước 3 bỏ qua CHECKPOINT (Bước 3a).*
8
+ *Checkpoint: **chặn CỨNG** — ghi đè quyết định reviewer: `--full` BỎ QUA findings (mất `status` accepted/modified/rejected của cả một vòng Review Board), và `--resume` áp fix thẳng vào PRD/`.feature` rồi bump version. Cùng hình dạng `/refine-prd`. `--yes` KHÔNG bỏ qua được (gate Bước 3a).*
9
+
10
+ *Mức cứng **chỉ áp** khi file findings ĐÃ TỒN TẠI và có ≥1 finding mang `status` `accepted`/`modified`/`rejected` (tức đã qua Review Board), HOẶC khi chạy với `--full`/`--resume`. Lần phân tích đầu không ghi đè gì — bắt CHECKPOINT cứng ở đó là ồn vô cớ. Cùng khuôn `/map-testids`.*
9
11
 
10
12
  # Gate — Quy trình vào chuẩn cho mọi lệnh
11
13
 
@@ -86,7 +88,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
86
88
 
87
89
  | Mức | Lệnh nào | `--yes` bỏ qua được? |
88
90
  |---|---|:---:|
89
- | **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
91
+ | **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ó) |
90
92
  | **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
91
93
  | **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
92
94
 
@@ -94,6 +96,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
94
96
  `--` 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
95
97
  headless: `claude -p "/generate-code UC1 --yes"`.
96
98
 
99
+ > **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
100
+ > tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
101
+ > ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
102
+ > mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
103
+ > `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
104
+
97
105
  > **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: …*`
98
106
  > 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
99
107
  > **nghĩa là gì**.
@@ -1,11 +1,13 @@
1
1
  # /review-tech-docs — Review Technical Design Document
2
2
 
3
- **Chế độ phân tích READ-ONLY — ghi file findings, KHÔNG sửa target.**
3
+ **Hai chế độ.** *Phân tích*chỉ đọc target, ghi file findings. *`--resume`* — **Phase 2–3 ghi vào thân tech-doc, header (`@trace.bdd_versions` · `@trace.sign_off`), và sổ TSV của MỌI UC mà doc phủ**. Nhãn "read-only" cũ chỉ đúng cho chế độ đầu (sửa 2026-09-16).
4
4
  **Dùng `--resume` để áp dụng các finding được chấp nhận.**
5
5
 
6
6
  ## Gate
7
7
 
8
- *Checkpoint: **không chặn** — read-only (ghi findings vào .agent/review/). Gate Bước 3 bỏ qua CHECKPOINT (Bước 3a).*
8
+ *Checkpoint: **chặn CỨNG** — ghi đè quyết định reviewer (`--full`), và `--resume` Phase 2–3 ghi vào THÂN tech-doc, HEADER (`@trace.sign_off` là xác nhận của NGƯỜI: be_team/fe_team/app_team/sa), và sổ TSV của mọi UC trong `@trace.ucs`. `--yes` KHÔNG bỏ qua được (gate Bước 3a).*
9
+
10
+ *Mức cứng **chỉ áp** khi findings đã có quyết định reviewer, HOẶC khi chạy với `--full`/`--resume`. Lần phân tích đầu đi thẳng.*
9
11
 
10
12
  # Gate — Quy trình vào chuẩn cho mọi lệnh
11
13
 
@@ -86,7 +88,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
86
88
 
87
89
  | Mức | Lệnh nào | `--yes` bỏ qua được? |
88
90
  |---|---|:---:|
89
- | **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
91
+ | **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ó) |
90
92
  | **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
91
93
  | **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
92
94
 
@@ -94,6 +96,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
94
96
  `--` 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
95
97
  headless: `claude -p "/generate-code UC1 --yes"`.
96
98
 
99
+ > **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
100
+ > tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
101
+ > ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
102
+ > mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
103
+ > `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
104
+
97
105
  > **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: …*`
98
106
  > 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
99
107
  > **nghĩa là gì**.
@@ -82,7 +82,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
82
82
 
83
83
  | Mức | Lệnh nào | `--yes` bỏ qua được? |
84
84
  |---|---|:---:|
85
- | **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
85
+ | **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ó) |
86
86
  | **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
87
87
  | **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
88
88
 
@@ -90,6 +90,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
90
90
  `--` 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
91
91
  headless: `claude -p "/generate-code UC1 --yes"`.
92
92
 
93
+ > **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
94
+ > tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
95
+ > ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
96
+ > mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
97
+ > `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
98
+
93
99
  > **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: …*`
94
100
  > 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
95
101
  > **nghĩa là gì**.
@@ -4,7 +4,7 @@ Check read-only độ phủ giữa spec, code, và test — gồm cả PRD versi
4
4
 
5
5
  ## Gate
6
6
 
7
- *Checkpoint: **không chặn** — read-only (ghi trace-report.json + TSV status, không đụng spec/code). Gate Bước 3 bỏ qua CHECKPOINT (Bước 3a).*
7
+ *Checkpoint: **không chặn** — **không phải vì read-only**. Lệnh ghi `trace-report.json`, `.trace-mirror/`, và **append** `trace-history.jsonl`; với `--reconcile-code` còn ghi row TSV `_seams.tsv`. Nó không chặn vì mọi thao tác ghi VÔ ĐIỀU KIỆN đều hoặc dựng lại được, hoặc là `append` — và hai thao tác nguy hơn đều nằm sau `--reconcile-code`. Gate Bước 3 bỏ qua CHECKPOINT (Bước 3a).*
8
8
 
9
9
  # Gate — Quy trình vào chuẩn cho mọi lệnh
10
10
 
@@ -85,7 +85,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
85
85
 
86
86
  | Mức | Lệnh nào | `--yes` bỏ qua được? |
87
87
  |---|---|:---:|
88
- | **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
88
+ | **Không chặn** | `/review-code` · `/validate-traces` · `/debug` **KHÔNG phải vì read-only**: cả ba đều CÓ ghi file. Chúng không chặn vì thao tác ghi của chúng hoặc nằm sau một câu hỏi `(Y/N)`, hoặc nằm sau một cờ, hoặc là `append`/dựng-lại-được | — (vốn không có) |
89
89
  | **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
90
90
  | **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
91
91
 
@@ -93,6 +93,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
93
93
  `--` khỏi phần resolve target, nên cờ này không ảnh hưởng việc tìm file.) Mở đường chạy
94
94
  headless: `claude -p "/generate-code UC1 --yes"`.
95
95
 
96
+ > **Tên lệnh trong bảng trên có máy canh — `R19`.** Mỗi hàng bảng vừa nêu một mức vừa nêu
97
+ > tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
98
+ > ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
99
+ > mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
100
+ > `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
101
+
96
102
  > **KHÔNG tự suy mức từ bảng này.** Mỗi lệnh **tự khai** mức của nó ở một dòng `*Checkpoint: …*`
97
103
  > ngay dưới `## Gate` của chính nó — đọc dòng đó, đừng suy diễn. Bảng trên chỉ giải thích ba mức
98
104
  > **nghĩa là gì**.
@@ -219,7 +225,7 @@ Lưu `scope` — mọi step sau dùng nó:
219
225
  | Step | Hẹp thế nào |
220
226
  |---|---|
221
227
  | Step 0 / Step 1 | `all_trace_dirs` giữ nguyên, nhưng chỉ đọc TSV **khớp scope**: `{trace_dir}/{domain}/**` · `{trace_dir}/{domain}/{prd-slug}/**` · `{trace_dir}/**/{UC-ID}-*.tsv` |
222
- | Step 1.0 (lint) | truyền `--trace` như cũ — **lint luôn chạy toàn bộ**. Sổ hỏng ở domain khác vẫn là sổ hỏng, và lint rẻ (không LLM) |
228
+ | Step 1.0 (lint) | `--trace` như cũ — **rule SỔ (T1–T14) luôn chạy toàn bộ**: sổ hỏng ở domain khác vẫn là sổ hỏng, và lint rẻ (không LLM). **Rule TECH-DOC (T15/T16/T19/T20) thu hẹp theo `--scope-prd`** — xem dưới |
223
229
  | Step 2b · 3.9 · 4 · 5* · 7 | chỉ các PRD/UC trong scope |
224
230
  | Step 6 · 6b | chỉ ghi lại TSV + mốc của phần trong scope |
225
231
  | Step 8 | ghi `scope` **và** `domain` vào biên bản (xem dưới) |
@@ -280,9 +286,24 @@ Kiểm tra mảng `services` có tồn tại trong `project-context.yaml` không
280
286
  Chạy checker xác định trên mọi trace dir đã phân giải ở Step 0:
281
287
 
282
288
  ```bash
283
- npx @educa-corp/sdd-framework --lint-trace --trace {all_trace_dirs, ngăn cách bởi dấu phẩy} --specs {paths.specs_dir} --code {code_roots, ngăn cách bởi dấu phẩy}
289
+ npx @educa-corp/sdd-framework --lint-trace --trace {all_trace_dirs, ngăn cách bởi dấu phẩy} --specs {paths.specs_dir} --code {code_roots, ngăn cách bởi dấu phẩy} [--scope-prd {domain}/{prd-slug},…]
284
290
  ```
285
291
 
292
+ **`--scope-prd` — truyền khi và chỉ khi lệnh này chạy CÓ SCOPE** *(`--prd` / `--uc` / `--domain`)*.
293
+ Giá trị: `{domain}/{prd-slug}` của mọi PRD trong scope, ngăn bởi dấu phẩy. Không scope → **đừng truyền**.
294
+
295
+ > **Vì sao chỉ thu hẹp rule TECH-DOC, không thu hẹp rule SỔ** *(G87)*. Lập luận gốc — *"sổ hỏng ở
296
+ > domain khác vẫn là sổ hỏng"* — **đúng cho T1–T14**: `.tsv` là dữ liệu **không regenerate được**,
297
+ > hỏng ở đâu cũng là hỏng, và Step 3/6 của lệnh này sẽ **ghi ngược vào sổ**.
298
+ >
299
+ > **T15/T16/T19/T20 canh tech-doc, không canh sổ.** Lý do kia không nối sang được, mà `exit 1` thì
300
+ > chung một cửa — nên một lệnh **có scope** bị chặn bởi lỗi ở **PRD ngoài scope**. Đã xảy ra thật:
301
+ > `/validate-traces --prd FEAT-01-1` dừng vì 30 tech-doc của `learning` và `home-ai-native`.
302
+ >
303
+ > **KHÔNG thu hẹp bằng cách trỏ `--specs` hẹp lại.** `lint-trace` cần `{domain}/{prd-slug}` để tìm
304
+ > `bdd/`; trỏ `--specs` thẳng vào feature-package làm nó **bỏ qua im lặng** và báo **sạch** trên một
305
+ > tech-doc chưa từng được kiểm. Cách lách hiển nhiên nhất cho ra **xanh giả**.
306
+
286
307
  **Dựng `code_roots` — bắt buộc truyền, đây là chìa khoá kho của T14:**
287
308
 
288
309
  | Chế độ | `code_roots` |
@@ -781,7 +802,7 @@ Không tìm thấy seam/stub nào → bỏ qua im lặng.
781
802
  Với mỗi file `.tsv` đã xử lý: ghi `spec_ver`, `status`, `last_updated` đã cập nhật lại disk.
782
803
  Đồng thời **đồng bộ `uc_status` ← `@trace.status`** của file `.feature` tương ứng (header `.feature` là nguồn-sự-thật về duyệt BDD — người đặt `approved` sau khi review sạch, giống PO đặt PRD Metadata `Status`). Nhờ vậy `approved_ucs` trên dashboard phản ánh đúng thay vì luôn = 0.
783
804
  Và **đồng bộ `prd_status` ← `| **Status** |`** của PRD tương ứng (`{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md`) — đối xứng với `uc_status`: PRD Metadata là nguồn-sự-thật về duyệt PRD. Không có bước này thì `prd_status` là **write-once** (chỉ `/generate-bdd` ghi một lần) và sẽ giữ `approved` vĩnh viễn sau khi `/refine-prd` hay `/review-context --fix` reset PRD về `draft`. *(Step 4 đã đọc file PRD này rồi — không phát sinh I/O.)*
784
- **Đừng** sửa `dev_selftest`/`dev_selftest_at` (do `/dev-run-test` sở hữu) hay `qc_status`/`qc_run_at`/`qc_owner`/`qc_blocked_by` (do `/qc-run-test` + `/report-bug` sở hữu); lệnh này chỉ đọc chúng cho report.
805
+ **Đừng** sửa `dev_selftest`/`dev_selftest_at` (do `/dev-run-test` sở hữu) hay `qc_status`/`qc_run_at`/`qc_owner`/`qc_blocked_by` (do `/qc-run-script` + `/qc-run-manualtest` + `/report-bug` sở hữu); lệnh này chỉ đọc chúng cho report.
785
806
 
786
807
  ### Step 6b — Ghi mốc `spec_baseline` cho lần audit sau
787
808
 
@@ -886,7 +907,7 @@ qc_passing = rows where qc_status == pass
886
907
  qc_failing = rows where qc_status == fail
887
908
  qc_skipped = rows where qc_status == skip
888
909
  qc_not_run = rows where qc_status in (not_run, —)
889
- # qc_status is the OFFICIAL QC automation result (set by /qc-run-test),
910
+ # qc_status is the OFFICIAL QC automation result (set by /qc-run-script + /qc-run-manualtest),
890
911
  # shown alongside — never merged with — dev_selftest.
891
912
  waiting_dev = rows where qc_owner == dev # PM view: QC-found, waiting on dev to fix
892
913
  waiting_po = rows where qc_owner == po # PM view: blocked, waiting on PO to confirm/clarify
@@ -62,5 +62,5 @@ trace_tags:
62
62
  source: "# @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
63
63
  test_type: "# @trace.test_type=functional|integration|e2e|non-functional"
64
64
 
65
- # qc_status: /qc-run-test writes pass|fail|skip|not_run + qc_run_at into {trace_dir}/{UC-ID}.tsv
65
+ # qc_status: /qc-run-script writes pass|fail|skip|not_run + qc_run_at into {trace_dir}/{UC-ID}.tsv
66
66
  # (parallel to dev_selftest), surfaced in Living Docs as the OFFICIAL QC automation result.
@@ -11,7 +11,7 @@ Ba mức, định nghĩa đầy đủ ở `steps/gate.md` Bước 3a — **đây
11
11
 
12
12
  | Mức | Lệnh nào | `--yes` bỏ qua? |
13
13
  |---|---|:---:|
14
- | **Không chặn** | read-only (`/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs`) | — |
14
+ | **Không chặn** | `/review-code` · `/validate-traces` · `/debug` **không** vì read-only (cả ba đều ghi file), mà vì thao tác ghi nằm sau `(Y/N)` / sau một cờ / là `append` | — |
15
15
  | **Chặn thường** | mọi lệnh sinh/sửa artifact | ✅ |
16
16
  | **Chặn CỨNG** | ghi đè file đã có · `--resume` · migrate · prune | ❌ |
17
17
 
@@ -21,6 +21,46 @@ Ba mức, định nghĩa đầy đủ ở `steps/gate.md` Bước 3a — **đây
21
21
  chỉ hai dòng.
22
22
  - `--yes` bỏ qua *chặn thường*, **không** bỏ qua *chặn cứng*, và **không** tắt việc in cờ.
23
23
 
24
+ ## Cờ bỏ qua điều kiện — MỘT tên duy nhất: `--force`
25
+
26
+ > Nguồn máy đọc: `bin/trace-schema.json` → `gate.bypass_flags`. Đổi luật thì **sửa schema TRƯỚC**.
27
+
28
+ Mọi chỗ cho phép *"tôi biết điều kiện này, vẫn muốn chạy"* dùng **`--force`** — không đặt tên riêng
29
+ theo từng lệnh. `--include-draft` đã đổi thành `--force` (2026-09-14); **không giữ alias**.
30
+
31
+ | Cờ | Nghĩa | Bỏ qua gì |
32
+ |---|---|---|
33
+ | `--yes` | *"tôi không ngồi đây để trả lời"* | CHECKPOINT (câu hỏi Y/N) |
34
+ | `--force` | *"tôi biết điều kiện này, vẫn chạy"* | một **điều kiện nghiệp vụ** mà lệnh tự khai |
35
+
36
+ **Hai trục khác nhau, KHÔNG BAO GIỜ gộp.** Gộp là để một lần chạy headless âm thầm vượt mọi điều
37
+ kiện — đúng thứ `steps/qc-scope.md` §4 đã từ chối khi tách `--include-draft` khỏi `--yes`. Đổi **tên**
38
+ không đổi lập luận đó.
39
+
40
+ **Ba điều khoản bắt buộc** — thiếu cái nào thì `--force` thành *"ghi đè tất cả"* và mất hết ý nghĩa:
41
+
42
+ 1. **Phạm vi khai từng lệnh, không bao giờ bao trùm.** Mỗi lệnh tự khai `--force` của nó bỏ qua
43
+ **đúng** điều kiện nào; mọi điều kiện khác vẫn chặn. *Tiền lệ đúng có sẵn: `/generate-code`
44
+ §"`--force` có phạm vi HẸP — đây là ranh giới cứng, không phải khuyến nghị… **KHÔNG** phải ghi
45
+ đè tất cả". Đó là khuôn, không phải ngoại lệ.*
46
+ 2. **Phải khai ra đã bỏ qua gì.** Report in một dòng cho **mỗi** điều kiện bị bỏ qua. *Một cờ chung
47
+ mà im lặng thì người bỏ qua X cũng bỏ qua luôn Y, Z họ chưa từng biết có tồn tại. Tên chung là để
48
+ **dễ nhớ**, không phải để **dễ mù**.*
49
+ 3. **Artifact phải tự khai.** File sinh ra trong lần chạy có `--force` mang một dòng nói nó dựa trên
50
+ điều kiện bị bỏ qua. *Cờ ở dòng lệnh biến mất sau khi lệnh chạy xong; dấu trong file đi cùng file
51
+ tới người đọc sau.*
52
+
53
+ **Không phải mọi điều kiện đều `--force` được.** Điều kiện thuộc lớp **"báo cáo sai"** — bỏ qua nó thì
54
+ lệnh sinh ra một **khẳng định sai** chứ không phải một sản phẩm kém — là **chặn cứng, không cờ nào qua**
55
+ (`gate.bypass_flags.hard_never_forceable`). Phép thử một câu: *"bỏ qua cái này thì tôi nhận về một bản
56
+ kém, hay một bản **dán nhãn sai**?"* — vế sau thì không `--force` được.
57
+
58
+ > **Vì sao gom về một tên (2026-09-14).** Trước đó mỗi chỗ một tên: `--force` (generate-code),
59
+ > `--include-draft` (qc-scope), và `exec-d0-b5` đang đề xuất `--no-testid-contract` *"theo đúng tinh
60
+ > thần `--include-draft`"* — cái thứ ba chưa kịp sinh ra đã thấy nó sẽ là cái thứ ba. Cái giá thật
61
+ > **không phải** gõ sai cờ, mà là **không biết có đường ra**: người dùng gặp cổng chặn, không nhớ lệnh
62
+ > này dùng từ nào, rồi đi sửa spec cho hợp lệ giả thay vì khai báo tường minh rằng mình đang chạy sớm.
63
+
24
64
  > **Vì sao ba mức thay vì "always show" (G41):** bản cũ viết *"**Always** show a CHECKPOINT"*
25
65
  > rồi ngay dòng sau lại cấp một ngoại lệ cho lệnh read-only — mà `gate.md` **không hề thực thi**
26
66
  > ngoại lệ đó. Hai file cùng được nạp vào mọi lệnh và nói ngược nhau. Cộng thêm: cổng luôn in
@@ -55,7 +95,7 @@ Ba mức, định nghĩa đầy đủ ở `steps/gate.md` Bước 3a — **đây
55
95
  - Field có consumer mà **không có producer** là lỗi chặn build — đó chính là hình dạng
56
96
  của G1 (`@trace.sc_version`: 3 consumer, 0 producer, DRIFT chết mà không ai báo).
57
97
  - **Làm mất hiệu lực ≠ ghi đè.** Cột trace có chủ sở hữu rõ ràng — `dev_selftest`/`dev_selftest_at`
58
- thuộc `/dev-run-test` · `qc_status`/`qc_run_at` thuộc `/qc-run-test` · `test_count`/`test_classes`
98
+ thuộc `/dev-run-test` · `qc_status`/`qc_run_at` thuộc `/qc-run-script` + `/qc-run-manualtest` · `test_count`/`test_classes`
59
99
  thuộc `/dev-gen-test` — và **chỉ chủ được ghi giá trị KHẲNG ĐỊNH** (`pass`/`fail`/số lượng).
60
100
  Nhưng lệnh nào làm giá trị đó **HẾT ĐÚNG** (spec đổi, code đổi) thì **BẮT BUỘC** hạ nó về giá
61
101
  trị "chưa biết" (`not_run` / `—`). Giữ một `pass` đã hết hiệu lực là **báo cáo sai**, không phải
@@ -8,7 +8,7 @@ adapted: danh sách lệnh theo pipeline HIỆN TẠI (6 trạm QC) · bổ sung
8
8
  # Self-Review — 3 nhóm lỗi AI cần tự kiểm trước khi in Report
9
9
 
10
10
  Skill **tự chứa**, dùng chung cho các lệnh QC: `qc-analyze` · `qc-plan` · `qc-design-test` ·
11
- `qc-review` · `qc-run-test` · `qc-report` — và hai nhánh phụ `report-bug` · `propose-scenario`.
11
+ `qc-review-testcase` · `qc-run-script` · `qc-report` — và hai nhánh phụ `report-bug` · `propose-scenario`.
12
12
 
13
13
  Mỗi file lệnh có mục `## Self-Review` **riêng**, liệt kê tiêu chí **cụ thể cho output của chính
14
14
  nó**. File này định nghĩa **3 nhóm lỗi gốc** mà mọi tiêu chí cụ thể đó phải phủ được ít nhất một
@@ -36,7 +36,7 @@ Bảng phân định hiện tại — đừng dùng self-review cho những vi
36
36
  | BR mà BDD nhắc nhưng phân tích bỏ sót | **Guard BR-tag** (so với tag `@trace.business_rules`) | `/qc-analyze` |
37
37
  | Scenario chưa có test case nào phủ | **Guard SC coverage** (đếm TC trỏ tới từng SC) | `/qc-design-test` |
38
38
  | Bảng §4.5.6 trỏ SC không tồn tại · header thiếu `@trace.testid_attr` · bảng lệch code | **T15–T18** | `bin/lint-trace.js` |
39
- | Ghi `pass` trên row `DRIFT`/`ORPHANED` | **T12** + `positive_assertion_guards` | `bin/lint-trace.js` + `/qc-run-test` |
39
+ | Ghi `pass` trên row `DRIFT`/`ORPHANED` | **T12** + `positive_assertion_guards` | `bin/lint-trace.js` + `/qc-run-script` |
40
40
  | Sổ trace sai cấu trúc / enum / trùng `sc_id` | **T1–T8** | `bin/lint-trace.js` |
41
41
 
42
42
  Còn lại — **không có nguồn đối chiếu cơ học** — mới là việc của self-review: rủi ro bịa ra,
@@ -11,7 +11,7 @@ upstream_sha: c7ca6cfb798c609f18ffe20a38f64f95c76e1919
11
11
  > Giữ một bản kém hơn làm mặc định là để người không biết có cờ nhận bản kém.
12
12
  >
13
13
  > **Một chỗ CỐ Ý khác upstream:** mức nặng nhất dùng từ **`Blocker`**, không phải `Critical`.
14
- > Lý do: `/qc-run-test` đọc `🔴 Blocker` để đặt *"scenario đang chờ PO"* vào sổ kết quả trace.
14
+ > Lý do: `/qc-run-script` đọc `🔴 Blocker` để đặt *"scenario đang chờ PO"* vào sổ kết quả trace.
15
15
  > Đổi từ là đứt liên kết đó. Ba mức còn lại giữ nguyên upstream.
16
16
  >
17
17
  > **Phạm vi: MỘT file cho cả (PRD × nền)** *(B11)*, không phải một file mỗi UC. Đây là quay về
@@ -27,9 +27,17 @@ upstream_sha: c7ca6cfb798c609f18ffe20a38f64f95c76e1919
27
27
  | Nền (platform) | `<web \| app \| system>` |
28
28
  | Tài liệu nguồn | `<đường dẫn PRD>` · `<đường dẫn BDD nếu có>` · `<các file inputs/ liên quan>` |
29
29
  | Ngày phân tích | `<YYYY-MM-DD>` |
30
+ | **Nguồn & phiên bản** | PRD `<vX.Y>` · tech-doc `<rev \| —>` · design-spec `<vX.Y \| —>` |
31
+ | **BDD theo UC** | `<UC-ID>` `<vX.Y>` · `<UC-ID>` `<vX.Y>` … |
30
32
  | Tổng số gap | `<N>` (Blocker: x · High: y · Medium: z · Low: w) |
31
33
  | Trạng thái chung | 🔴 Blocked / 🟠 Cần làm rõ / 🟢 Đủ rõ để thiết kế TC |
32
34
 
35
+ > **Hai hàng `Nguồn & phiên bản` + `BDD theo UC` là hợp đồng máy đọc, không phải ghi chú.**
36
+ > `/qc-plan` và `/qc-design-test` **so** chúng với version hiện tại của spec để biết file này còn
37
+ > khớp không (`steps/qc-stamp.md` · `bin/trace-schema.json` → `qc_artifact_stamp`).
38
+ > `BDD theo UC` phải ghi **từng UC một**: file này phủ cả PRD, mỗi UC là một `.feature` riêng với
39
+ > version riêng — một số duy nhất cho cả file sẽ **sai cho `n−1` UC**.
40
+
33
41
  ---
34
42
 
35
43
  ## Phạm vi phân tích
@@ -43,7 +51,7 @@ upstream_sha: c7ca6cfb798c609f18ffe20a38f64f95c76e1919
43
51
  | `<UC-ID>` | … | `approved` | ✅ | `<n>` |
44
52
  | `<UC-ID>` | … | `draft` | `⏸ Chưa xét` | — |
45
53
 
46
- **Trong phạm vi: `<n>`/`<N>` UC.** Chưa xét: `<danh sách UC-ID>` — chạy lại sau khi BDD được duyệt, hoặc `--include-draft` để xét luôn bản nháp.
54
+ **Trong phạm vi: `<n>`/`<N>` UC.** Chưa xét: `<danh sách UC-ID>` — chạy lại sau khi BDD được duyệt, hoặc `--force` để xét luôn bản nháp.
47
55
 
48
56
  ---
49
57
 
@@ -18,7 +18,7 @@ có cấu trúc, đủ thông tin để người nhận trả lời được nga
18
18
  > mỗi UC là các hàng phân biệt bằng cột `UC`. Không còn một-file-mỗi-UC.
19
19
  >
20
20
  > **Một chỗ cố ý khác upstream:** mức nặng nhất dùng `🔴 Blocker`, không phải `Critical` —
21
- > `/qc-run-test` đọc đúng từ đó để đặt *"scenario đang chờ PO"* vào sổ trace.
21
+ > `/qc-run-script` đọc đúng từ đó để đặt *"scenario đang chờ PO"* vào sổ trace.
22
22
 
23
23
  ## Đầu vào
24
24
 
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: automation-feasibility-matrix
3
+ description: Đánh giá từng test case đã APPROVED là Automatable Y/N, kèm lý do chuẩn hoá và %Automated/Total. Dùng bởi /qc-automation-assess.
4
+ ---
5
+
6
+ # Automation Feasibility Matrix
7
+
8
+ Skill **tự chứa** cho `/qc-automation-assess`: đánh giá từng TC trong `TC_<FEATURE>.Test.md` đã
9
+ qua cổng `/qc-review-testcase` là `Automatable: Y/N`, kèm lý do chuẩn hoá và `%Automated/Total`.
10
+
11
+ ## Khi nào trigger
12
+
13
+ Sau `/qc-review-testcase` — TC đã `APPROVED` và chưa từng qua automation-assess, **hoặc** TC bị
14
+ gắn cờ `🔄 Re-assess` vì scenario nó verify đang `DRIFT` (BDD/spec đã đổi).
15
+
16
+ ## Tiêu chí đánh giá — trả lời TUẦN TỰ, dừng ở câu đầu tiên là "Có"
17
+
18
+ Câu nào trả lời "Có" thì **đó là lý do `N`**, và không cần xét tiếp:
19
+
20
+ 1. **Có bước nào đòi input từ con người / bên thứ ba mà script không tự lấy được?**
21
+ (OTP SMS thật · captcha · chữ ký tay · sinh trắc học trên thiết bị thật)
22
+ → `N`, nhãn **`Cần OTP/captcha thủ công`**
23
+ 2. **Có phụ thuộc hệ thống / thiết bị ngoài tầm kiểm soát của script?**
24
+ (app khác trên máy thật · máy POS vật lý · email/SMS thật không có test inbox)
25
+ → `N`, nhãn **`Phụ thuộc hệ thống ngoài`**
26
+ 3. **UI/flow có đang thay đổi liên tục?** (redesign · A/B test). Script viết hôm nay nhiều khả
27
+ năng vỡ trong < 2 tuần vì một thay đổi UI **đã biết trước**
28
+ → `N`, nhãn **`UI không ổn định`** — ghi rõ mốc dự kiến ổn định để re-assess
29
+ 4. **Element cần thao tác có test-id ổn định không, và dev có cam kết thêm nếu thiếu không?**
30
+ Không có **VÀ** không có cam kết → `N`, nhãn **`Thiếu test-id contract``**
31
+ > Khác với ca *"sẽ có nhưng chưa"* — ca đó vẫn `Y`, ghi chú chờ `IMPROVE-xxx`.
32
+ 5. **ROI có dương không?** Áp công thức dưới; âm rõ ràng → `N`, nhãn **`Effort > ROI`**
33
+ 6. Không rơi vào 1–5 → **`Y`**
34
+
35
+ ## Công thức ROI *(ước lượng nhanh, không cần chính xác tuyệt đối)*
36
+
37
+ ```
38
+ ROI ≈ (tần suất chạy lại × chi phí test tay mỗi lần)
39
+ − (chi phí viết script + chi phí bảo trì dự kiến)
40
+ ```
41
+
42
+ | Tín hiệu ROI **thấp** | Tín hiệu ROI **cao** |
43
+ |---|---|
44
+ | TC chỉ chạy **một lần** (migration một-lần, config set một lần) — viết script tốn hơn chạy tay 1 lần | TC có **nhiều biến thể dữ liệu** (boundary/negative): test tay tốn tuyến tính theo số biến thể, script chạy lại gần như miễn phí |
45
+
46
+ **Thứ tự ưu tiên khi có nhiều TC `Y` mà chưa đủ thời gian làm hết:** `P0` trước, rồi `P1`/`P2`.
47
+ TC `P0` gần như luôn ROI dương và là ứng viên trực tiếp cho smoke suite (`/qc-smoke-test` chạy
48
+ mỗi build).
49
+
50
+ > ⚠️ **`P0` mà rơi vào `N` là tín hiệu đáng chú ý hơn bình thường.** Tính năng lõi không có
51
+ > smoke test tự động là rủi ro cao cho cả mục tiêu *"phát hiện lỗi sớm mỗi build"*. Ghi rõ lý do
52
+ > **và** cân nhắc đề xuất `IMPROVE-xxx` để gỡ rào cản, thay vì chấp nhận `N` vĩnh viễn.
53
+
54
+ ## Tín hiệu ổn định — dùng cho tiêu chí 3
55
+
56
+ | Ổn định | KHÔNG ổn định |
57
+ |---|---|
58
+ | Màn hình đã ship ≥ 1 release, không đổi lớn gần đây | Đang trong sprint thiết kế lại UI |
59
+ | Có test-id contract §4.5.6 đã chốt | Element identify bằng text/class tạm thời |
60
+ | Flow nghiệp vụ ổn định | Business rule đang thử nghiệm (feature flag % rollout) |
61
+
62
+ ## Guard — Re-assessment tự động theo `DRIFT`
63
+
64
+ TC có scenario `@trace.verifies={UC-ID}-SC{N}` mà row đó trong sổ trace đang `status: DRIFT`
65
+ → **re-assess lại từ đầu 6 tiêu chí**, KHÔNG tái dùng phán quyết cũ.
66
+
67
+ Vì sao không tái dùng: spec đổi có thể đổi **cả sáu** câu hỏi — ví dụ một BR mới thêm bước OTP
68
+ biến một TC đang `Y` thành `N`.
69
+
70
+ | Đổi | Xử lý cột `Script file` |
71
+ |---|---|
72
+ | `Y → N` | **GIỮ** path cũ + ghi chú `⚠️ Script đã lỗi thời — cân nhắc gỡ ở lần /qc-design-script kế tiếp`. **KHÔNG tự xoá file** — để người quyết định |
73
+ | `N → Y` | giữ `—`, chờ `/qc-design-script` điền |
74
+
75
+ ## Output format
76
+
77
+ ```markdown
78
+ # Automation Assessment — {TICKET-ID} ({active_platform})
79
+
80
+ | TC ID | UC | Automatable | Lý do (nếu N) | Trace SC | Script file | Ghi chú |
81
+ |---|---|:---:|---|---|---|---|
82
+ | TC_LOGIN_001 | UC1 | Y | — | UC1-SC1 | — *(chưa qua qc-design-script)* | |
83
+ | TC_LOGIN_004 | UC1 | N | Cần OTP/captcha thủ công | UC1-SC4 | — *(không automate)* | Giữ trong bộ manual |
84
+ | TC_LOGIN_002 | UC1 | Y | — | UC1-SC2 | — *(chưa qua qc-design-script)* | 🔄 Re-assess (DRIFT, spec đổi {ngày}) — đã re-check: vẫn Y |
85
+
86
+ **%Automated/Total: {automatable}/{đã đánh giá} = {pct}%**
87
+ **Loại khỏi lượt:** {k} TC của UC chưa APPROVED — {danh sách UC + trạng thái thật}
88
+ ```
89
+
90
+ ### Cột `Script file` — ai ghi, khi nào
91
+
92
+ ```
93
+ /qc-automation-assess → luôn khởi tạo "—" (script chưa tồn tại ở bước này)
94
+ /qc-design-script → ĐIỀN path thật sau khi sinh
95
+ /qc-run-script → ĐỌC cột này để biết chạy file nào — KHÔNG tự suy path
96
+ ```
97
+
98
+ Đây là **chỉ mục ngược duy nhất** từ TC → file code thật; chiều xuôi (code → SC) đã có sẵn qua
99
+ tag `@trace.verifies`. Không có cột này thì `/qc-run-script` phải suy đường dẫn từ quy ước đặt
100
+ tên — suy sai thì chạy sai bộ test, hoặc **chạy 0 test mà vẫn báo xanh**.
101
+
102
+ > **Đường dẫn theo stack HIỆN TẠI** — module `qc-playwright` (Python + pytest-playwright):
103
+ > `tests/<project>/test_<feature>.py` + `pages/<feature>_page.py`, theo
104
+ > `modules/qc-playwright/stack-profile.yaml` §layout.
105
+ >
106
+ > *(Đề xuất gốc của đội QC viết theo TypeScript + Playwright Test / WebdriverIO. Việc đổi stack
107
+ > là một bước RIÊNG, cố ý tách khỏi đợt tách lệnh — xem quyết định F3, Đợt 2 · b2. Khi stack
108
+ > đổi, chỉ đoạn này và `stack-profile.yaml` cần sửa; cơ chế cột `Script file` không đổi.)*
109
+
110
+ ## Nhãn lý do mới phát sinh
111
+
112
+ Không khớp nhãn nào trong 5 nhãn chuẩn → **tạo nhãn mới mô tả đúng lý do** *(đừng ép vào nhãn
113
+ có sẵn)*, rồi liệt kê nó trong report để bổ sung vào danh sách lần sau.
114
+
115
+ > **Vì sao chuẩn hoá nhãn.** Để **đếm được**. *"3 TC không automate vì **thiếu test-id**"* là
116
+ > một tín hiệu hành động được — đi đàm phán với dev. *"3 TC vì lý do kỹ thuật"* thì không.
117
+ >
118
+ > Riêng nhãn `Thiếu test-id contract` nối thẳng với Đợt 0 (hợp đồng test-id §4.5.6): nếu Đợt 0
119
+ > làm đúng thì nhãn này phải **giảm dần theo thời gian** — tức nó đồng thời là **phép đo cho
120
+ > chính Đợt 0**.
@@ -43,4 +43,4 @@ Mỗi journey → 1 TC bám Format; Expected = chuỗi verify point; chuẩn b
43
43
 
44
44
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 6 E2E**. Mỗi journey một TC; tiền điều kiện · kết quả/định tuyến kỳ vọng · BR · phụ thuộc gap · priority ghi dạng trường danh sách.
45
45
 
46
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
46
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -43,4 +43,4 @@ Chuyển draft → TC chính thức bám **format file `TC_<FEATURE>.Test.md`**:
43
43
 
44
44
  Ghi TC đã chuyển thành functional vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 3 Functional**.
45
45
 
46
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
46
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -111,4 +111,4 @@ Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 1 En
111
111
 
112
112
  File này chỉ sinh khi có cờ `--api` hoặc `--all`. Mẫu TC: `../api/endpoint.md` · chuỗi auth: `../api/auth-chain.md` · tra mã: `../api/http-status-codes.md` · header: `../api/common-headers.md`.
113
113
 
114
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
114
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -46,4 +46,4 @@ Liệt kê các màn/route + thứ tự điều hướng · state/dữ liệu tr
46
46
 
47
47
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 3 Functional** (luồng đa màn trong cùng một feature).
48
48
 
49
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
49
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -51,4 +51,4 @@ chức năng (input/action/display/nav) · constraint (required/min-max/format/e
51
51
 
52
52
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 1 GUI** · **Nhóm 2 Validation** · **Nhóm 3 Functional**.
53
53
 
54
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
54
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -46,4 +46,4 @@ Nhóm TC: happy (dữ liệu đúng đầu→cuối) → contract negative (inpu
46
46
 
47
47
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ưu tiên P0 cho định tuyến & tiền-dữ liệu. Chuỗi gọi phụ thuộc nhau: `../api/crud-sequence.md`.
48
48
 
49
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
49
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -42,4 +42,4 @@ Nhóm TC: ghi đúng giá trị (happy) → default/null đúng → update khôn
42
42
 
43
43
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ghi rõ query kiểm tra DB + yêu cầu cleanup; không hardcode ID, chuẩn bị/dọn data qua fixture (3 mức teardown: `../shared/precision-rules.md` §8).
44
44
 
45
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
45
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -44,4 +44,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 4 Integration (qua UI)**. Đây là tầng verify dòng dữ liệu API → giao diện, nên **vẫn thuộc file giao diện**: bỏ UI đi thì TC mất nghĩa.
46
46
 
47
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
47
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -44,4 +44,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Mỗi TC ghi topic, key, payload cần verify + hành vi consumer.
46
46
 
47
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
47
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -44,4 +44,4 @@ Trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào file theo cùng câu hỏi phân file *"verify được mà không cần UI?"*: a11y · responsive · touch-target → `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` **Nhóm 5 NFR**; tải/hiệu năng/bảo mật ở tầng API → `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md`. Mỗi TC ghi tiêu chí đo + ngưỡng + công cụ, đơn vị theo `../shared/precision-rules.md` §3.
46
46
 
47
- **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
47
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
@@ -25,20 +25,31 @@ Hai TC là **trùng** khi **cả 3** điều kiện sau đều giống nhau:
25
25
 
26
26
  ## Quy trình kiểm tra (3 bước)
27
27
 
28
- ### Bước 1 — Grep title keywords trong file TC hiện tại
28
+ ### Bước 1 — Grep title keywords trong CẢ THƯ MỤC `test-cases/`
29
29
 
30
- Trước khi viết TC mới, tìm kiếm title keywords trong toàn bộ file:
30
+ Trước khi viết TC mới, tìm title keywords trong **mọi** file `.Test.md` — **không chỉ file đang mở**:
31
31
 
32
32
  ```bash
33
- # Tìm TC có chứa từ khóa scenario sắp viết
34
- grep -i "<từ_khóa_scenario>" {qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md
33
+ # Tìm TC có chứa từ khóa scenario sắp viết — QUÉT CẢ THƯ MỤC
34
+ grep -ril "<từ_khóa_scenario>" {qc_artifact_dir}test-cases/*.Test.md
35
35
  ```
36
36
 
37
37
  Ví dụ: Sắp viết TC "Nhập email không hợp lệ":
38
38
  ```bash
39
- grep -i "email\|invalid\|không hợp lệ" {qc_artifact_dir}test-cases/TC_LOGIN.Test.md
39
+ grep -ril "email\|invalid\|không hợp lệ" {qc_artifact_dir}test-cases/*.Test.md
40
40
  ```
41
41
 
42
+ > **Vì sao quét cả thư mục, không chỉ file đang mở** *(G75)*. Thư mục `test-cases/` dùng chung cho
43
+ > **cả PRD** — mọi UC, và cả hai file giao diện/API của cùng một feature. `/qc-design-test` §Skills
44
+ > dặn riêng: *"**trùng chéo UC** giờ mới thực sự xảy ra vì mọi UC dùng chung một thư mục"*. Quét một
45
+ > file là mù đúng loại trùng lặp hay xảy ra nhất.
46
+ >
47
+ > **Và nó từng mù cùng chỗ với một lỗi khác.** Khi G62 còn sống (`Guard SC coverage` chỉ đếm file
48
+ > *"vừa ghi"*, nên lần chạy `--api` nhân bản TC giao diện sang file API), quy trình này là cơ chế
49
+ > **được dựng lên để bắt** đúng loại trùng đó — và nó **im lặng**, vì phạm vi quét của nó **cũng** là
50
+ > *"file hiện tại"*. Hai cơ chế độc lập chia nhau **cùng một giả định phạm vi** thì **không phải hai
51
+ > lớp bảo vệ — chúng là một lớp, đếm hai lần.**
52
+
42
53
  ### Bước 2 — So sánh preconditions + test data
43
54
 
44
55
  Nếu grep tìm thấy TC tương tự, so sánh:
@@ -59,6 +70,23 @@ Nếu grep tìm thấy TC tương tự, so sánh:
59
70
  | Cùng condition, khác platform (Web/App) | **KHÔNG trùng** — mỗi nền một thư mục (`{qc_dir}/{TICKET-ID}/web/` vs `/app/`) và mỗi nền phải tự đạt full coverage. Trùng logic giữa hai nền là **chủ đích** |
60
71
  | Không tìm thấy tương tự | Viết TC mới bình thường |
61
72
 
73
+ **Tìm thấy ở FILE KHÁC — ba nhánh, không gộp làm một** *(G75)*:
74
+
75
+ | Tìm thấy ở | Hành động |
76
+ |---|---|
77
+ | **Cùng file** đang mở | Như bảng trên |
78
+ | **File khác, CÙNG UC** — vd `TC_<FEATURE>_API.Test.md` vs `TC_<FEATURE>.Test.md` | **KHÔNG chép sang.** Kiểm lại §Câu hỏi phân file (*"TC này verify được mà không cần UI không?"*): TC đang nằm **đúng chỗ** thì để yên, đừng nhân bản |
79
+ | **File khác, UC KHÁC** | **KHÔNG viết lại.** Trỏ `@trace.verifies` về SC của UC đang làm và đếm vào ô `Trùng: {j} trùng chéo UC` ở report |
80
+
81
+ > **Nhánh giữa là lớp thứ hai chặn G62.** G62 (`Guard SC coverage` chỉ đếm file *"vừa ghi"*) đã được
82
+ > sửa ở tầng guard — mẫu số/tử số. Nhánh này chặn cùng ca đó ở tầng skill: nếu vì bất kỳ lý do gì mà
83
+ > một TC giao diện sắp được viết vào file API, bước này bắt được.
84
+ >
85
+ > **Nhánh cuối làm ô `{j}` có phép đo đứng sau.** `/qc-design-test` §Report đã có sẵn ô
86
+ > `Trùng: {k} TC bỏ vì trùng ({j} trùng chéo UC …)`. Khi Bước 1 chỉ quét một file thì `{j}` **luôn
87
+ > bằng 0** — một con số không có phép tính, đúng thứ `buoc/1-02` §B5 cảnh báo: *"một con số trong báo
88
+ > cáo KHÔNG chứng minh có phép đo"*.
89
+
62
90
  ---
63
91
 
64
92
  ## Trường hợp đặc biệt