@educa-corp/sdd-framework 0.9.3 → 0.9.5

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 (118) hide show
  1. package/bin/build.js +11 -0
  2. package/bin/lint-trace.js +230 -2
  3. package/bin/qc-base-map.json +119 -49
  4. package/bin/self-check.js +54 -0
  5. package/bin/trace-schema.json +58 -4
  6. package/core/FRAMEWORK_VERSION +1 -1
  7. package/core/commands/generate-bdd.md +1 -0
  8. package/core/commands/generate-code.md +39 -2
  9. package/core/commands/generate-tech-docs.md +21 -2
  10. package/core/commands/map-testids.md +88 -8
  11. package/core/commands/qc-analyze.md +429 -472
  12. package/core/commands/qc-design-test.md +251 -207
  13. package/core/commands/qc-plan.md +97 -197
  14. package/core/commands/qc-report.md +76 -60
  15. package/core/commands/qc-review.md +135 -185
  16. package/core/commands/qc-run-test.md +235 -274
  17. package/core/commands/review-tech-docs.md +20 -0
  18. package/core/commands/setup-ai-first.md +5 -5
  19. package/core/commands/update-framework.md +1 -1
  20. package/core/commands/validate-traces.md +1 -1
  21. package/core/modules/qc-playwright/stack-profile.yaml +1 -1
  22. package/core/rules/data-protection.md +52 -0
  23. package/core/rules/workflow.md +1 -1
  24. package/core/skills/qc/_shared/self-review-principles.md +112 -0
  25. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +1 -1
  26. package/core/skills/qc/qa-analyst/spec-breakdown.md +2 -2
  27. package/core/skills/qc/qa-designer/api/auth-chain.md +155 -0
  28. package/core/skills/qc/qa-designer/api/auth-sequence.md +75 -0
  29. package/core/skills/qc/qa-designer/api/common-headers.md +61 -0
  30. package/core/skills/qc/qa-designer/api/crud-sequence.md +122 -0
  31. package/core/skills/qc/qa-designer/api/endpoint.md +231 -0
  32. package/core/skills/qc/qa-designer/api/http-status-codes.md +102 -0
  33. package/core/skills/qc/qa-designer/e2e/journey.md +13 -8
  34. package/core/skills/qc/qa-designer/exploratory/charter.md +2 -0
  35. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +7 -4
  36. package/core/skills/qc/qa-designer/functional/api.md +87 -18
  37. package/core/skills/qc/qa-designer/functional/gui-feature.md +12 -9
  38. package/core/skills/qc/qa-designer/functional/gui-screen.md +12 -10
  39. package/core/skills/qc/qa-designer/integration/api.md +12 -5
  40. package/core/skills/qc/qa-designer/integration/db.md +12 -6
  41. package/core/skills/qc/qa-designer/integration/gui.md +12 -5
  42. package/core/skills/qc/qa-designer/integration/kafka.md +12 -5
  43. package/core/skills/qc/qa-designer/non-functional.md +12 -5
  44. package/core/skills/qc/qa-designer/shared/action-keywords-glossary.md +91 -0
  45. package/core/skills/qc/qa-designer/shared/duplicate-check-procedure.md +105 -0
  46. package/core/skills/qc/qa-designer/shared/implicit-scenarios.md +22 -0
  47. package/core/skills/qc/qa-designer/shared/precision-rules.md +198 -0
  48. package/core/skills/qc/qa-designer/shared/read-doc-gap-inputs.md +25 -0
  49. package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +93 -0
  50. package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +243 -0
  51. package/core/skills/qc/qa-planner/risk-model.md +1 -1
  52. package/core/skills/qc/qa-reviewer/script/e2e.md +9 -1
  53. package/core/skills/qc/qa-reviewer/script/exploratory.md +9 -1
  54. package/core/skills/qc/qa-reviewer/script/functional.md +9 -1
  55. package/core/skills/qc/qa-reviewer/script/integration.md +9 -1
  56. package/core/skills/qc/qa-reviewer/script/non-functional.md +9 -1
  57. package/core/skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md +26 -0
  58. package/core/skills/qc/qa-reviewer/shared/review-check-groups.md +207 -0
  59. package/core/skills/qc/qa-reviewer/shared/review-file-template.md +228 -0
  60. package/core/skills/qc/qa-reviewer/test-case/e2e.md +71 -13
  61. package/core/skills/qc/qa-reviewer/test-case/exploratory.md +53 -4
  62. package/core/skills/qc/qa-reviewer/test-case/functional.md +63 -15
  63. package/core/skills/qc/qa-reviewer/test-case/integration.md +64 -12
  64. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +72 -13
  65. package/core/skills/qc/qa-runner/e2e.md +3 -3
  66. package/core/skills/qc/qa-runner/functional/gui-feature.md +9 -3
  67. package/core/skills/qc/qa-runner/functional/gui-screen.md +9 -3
  68. package/core/skills/qc/qa-runner/integration.md +1 -1
  69. package/core/skills/qc/qa-runner/non-functional.md +1 -1
  70. package/core/skills/spec/SKILL.md +1 -1
  71. package/core/steps/context-loader.md +7 -2
  72. package/core/steps/gap-verify.md +67 -0
  73. package/core/steps/report-footer.md +3 -3
  74. package/core/templates/feature.template +1 -0
  75. package/core/templates/tech-design.template.md +1 -0
  76. package/docs/02-concepts/pipeline-steps/09-validate-traces.md +1 -1
  77. package/docs/04-reference/commands.md +1 -1
  78. package/docs/04-reference/trace-schema.md +39 -1
  79. package/docs/explain/00-setup-ai-first.md +1 -1
  80. package/docs/explain/11-map-testids.md +70 -69
  81. package/docs/plans/qc-implementation-log.md +145 -3
  82. package/docs/plans/qc-surgery/00-nhat-ky.md +497 -0
  83. package/docs/plans/qc-surgery/01-checklist.md +92 -0
  84. package/docs/plans/qc-surgery/02-lo-trinh.md +266 -0
  85. package/docs/plans/qc-surgery/buoc/0-01-testid-attr-co-cho-o.md +157 -0
  86. package/docs/plans/qc-surgery/buoc/0-02-mot-nguon-cho-testid-attr.md +135 -0
  87. package/docs/plans/qc-surgery/buoc/0-03-skill-thoi-day-do-dom.md +167 -0
  88. package/docs/plans/qc-surgery/buoc/0-04-may-canh-hop-dong.md +173 -0
  89. package/docs/plans/qc-surgery/buoc/0-05-don-nhan-cot-va-2b.md +133 -0
  90. package/docs/plans/qc-surgery/buoc/0-06-hop-dong-truoc-code.md +226 -0
  91. package/docs/plans/qc-surgery/buoc/1-01-guard-br-tag.md +156 -0
  92. package/docs/plans/qc-surgery/buoc/1-02-guard-sc-coverage.md +153 -0
  93. package/docs/plans/qc-surgery/buoc/1-03-fail-3-nhan.md +176 -0
  94. package/docs/plans/qc-surgery/buoc/1-04-self-review-dung-chung.md +175 -0
  95. package/docs/plans/qc-surgery/buoc/1-05-spec-la-du-lieu.md +164 -0
  96. package/docs/plans/qc-surgery/buoc/1-06-gap-verify-du-bo.md +162 -0
  97. package/docs/plans/qc-surgery/buoc/README.md +85 -0
  98. package/docs/plans/qc-surgery/exec-d0-b1-testid-attr-header.md +147 -0
  99. package/docs/plans/qc-surgery/exec-d0-b2-thong-nhat-nguon-testid-attr.md +152 -0
  100. package/docs/plans/qc-surgery/exec-d0-b3-sua-skill-probe-dom.md +173 -0
  101. package/docs/plans/qc-surgery/exec-d0-b4-may-canh-4-5-6.md +168 -0
  102. package/docs/plans/qc-surgery/exec-d0-b5-don-nhan-lech.md +196 -0
  103. package/docs/plans/qc-surgery/exec-d0-b6-contract-truoc-code.md +350 -0
  104. package/docs/plans/qc-surgery/exec-d1-b1-guard-br-tag.md +129 -0
  105. package/docs/plans/qc-surgery/exec-d1-b2-guard-sc-coverage.md +159 -0
  106. package/docs/plans/qc-surgery/exec-d1-b3-fail-3-bucket.md +158 -0
  107. package/docs/plans/qc-surgery/exec-d1-b4-self-review-principles.md +145 -0
  108. package/docs/plans/qc-surgery/exec-d1-b5-noi-quy-spec-la-du-lieu.md +156 -0
  109. package/docs/plans/qc-surgery/exec-d1-b6-gap-verify-mo-rong.md +179 -0
  110. package/docs/plans/qc-surgery/exec-d2-b1-tach-qc-review.md +166 -0
  111. package/docs/plans/qc-surgery/exec-d2-b2-tach-qc-run-test-atomic.md +267 -0
  112. package/docs/plans/qc-surgery/exec-d2-b3-qc-automation-assess.md +198 -0
  113. package/docs/plans/qc-surgery/exec-d3-b1-qc-report-gate-decision.md +209 -0
  114. package/docs/plans/qc-surgery/exec-d4-b1-qc-design-testdata.md +146 -0
  115. package/docs/plans/qc-surgery/exec-d4-b2-qc-smoke-test.md +179 -0
  116. package/docs/plans/qc-surgery/exec-d4-b3-qc-metrics-va-lint.md +198 -0
  117. package/docs/plans/qc-surgery/exec-d4-b4-lint-spec-injection.md +199 -0
  118. package/package.json +1 -1
@@ -1,14 +1,14 @@
1
- ---
2
- version: 1.0
3
- updated: 2026-06-11
4
- ported_from: ai-automation-qc-base
5
- ---
6
-
7
- # /qc-plan — QC Test Plan & Risk Analysis
8
-
9
- > Stage 2 của QC automation pipeline native (qc-analyze → qc-plan → qc-design-test → qc-review → qc-run-test → qc-report). Port từ qa-planner của team QC.
10
-
11
- ## Gate
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-06-11
4
+ ported_from: ai-automation-qc-base
5
+ ---
6
+
7
+ # /qc-plan — QC Test Plan & Risk Analysis
8
+
9
+ > Stage 2 của QC automation pipeline native (qc-analyze → qc-plan → qc-design-test → qc-review → qc-run-test → qc-report). Port từ qa-planner của team QC.
10
+
11
+ ## Gate
12
12
  # Gate — Quy trình vào chuẩn cho mọi lệnh
13
13
 
14
14
  Mọi lệnh PHẢI chạy gate này trước khi thực thi phần logic riêng của nó.
@@ -160,196 +160,96 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
160
160
  - "N" → dừng, hỏi người dùng muốn thay đổi gì.
161
161
  - Có `--yes` và mức *chặn thường* → coi như "Y", **nhưng vẫn IN khối CHECKPOINT** nếu có cờ
162
162
  🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
163
-
164
-
165
- *Lưu ý: Với lệnh này, target ở Bước 1 là một **TICKET-ID** (mã PRD) — hoặc UC-ID / file feature, cả hai quy về TICKET-ID ở §Phạm vi QC. Đọc output của qc-analyze (`REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md`) từ `{qc_artifact_dir}` và file `.feature` của đúng nền đó.*
166
-
167
- ## Context
163
+
164
+
165
+ *Lưu ý: Với lệnh này, target ở Bước 1 là một **TICKET-ID** (mã PRD) — hoặc UC-ID / file feature, cả hai quy về TICKET-ID ở §Phạm vi QC. Đọc output của qc-analyze (`REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md`) từ `{qc_artifact_dir}` và file `.feature` của đúng nền đó.*
166
+
167
+ ## Context
168
168
  **BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
169
169
  rồi mới tiếp tục phần bên dưới.
170
170
 
171
171
  Bỏ qua bước này thì `{paths.*}`, `{tech_stack.*}`, `{conventions.*}`, guardrail từ
172
172
  `project-lessons`, và routing service (chế độ umbrella) đều **chưa được phân giải** — mọi
173
- placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
174
-
175
- ---
176
-
177
- ## Phạm vi QC
178
-
179
- # QC Scope phân giải phạm vi cho mọi lệnh `qc-*`
180
-
181
- **Chạy TRƯỚC phần logic riêng của lệnh, và SAU `steps/gate.md`.** Bước này chốt bốn thứ mà
182
- cả 6 trạm QC đều cần, để chúng không tự suy mỗi trạm một kiểu:
183
-
184
- | Biến | Là gì |
185
- |---|---|
186
- | `TICKET-ID` | mã PRD — **thư mục artifact QC mang tên này** |
187
- | `active_platform` | `web` \| `app` \| `system` \| … — một QC pass khoá đúng MỘT nền |
188
- | `qc_artifact_dir` | `{paths.qc_dir}/{TICKET-ID}/{active_platform}/` |
189
- | `uc_list` | các UC của (PRD × nền) này, kèm trạng thái BDD từng UC |
190
-
191
- > **Vì sao gom về một chỗ.** Luật phân giải nền từng được copy-paste ở 5 lệnh và câu chữ đã
192
- > lệch nhau. Năm bản của một luật là nơi drift sống: sửa bốn, quên một, và trạm bị quên ghi
193
- > artifact vào sai thư mục **trong im lặng**.
194
-
195
- ---
196
-
197
- ## 1 — `TICKET-ID`
198
-
199
- Artifact QC gom theo **PRD**, không theo UC. Nên mọi trạm phải quy được về `TICKET-ID`:
200
-
201
- | `$ARGUMENTS` là | Cách lấy |
202
- |---|---|
203
- | **UC-ID** (`{TICKET-ID}-UC{N}`) | phần **trước** `-UC` — đúng luật `steps/gate.md` Bước 1 dùng để tìm tech-doc gộp |
204
- | **TICKET-ID** | dùng trực tiếp |
205
- | một **path file** (`.feature` / PRD / design-spec) | phân giải `{domain}` + `{prd-slug}` theo luật `context-loader` Bước 1, rồi lấy `TICKET-ID` từ tên file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder |
206
-
207
- Đối chiếu: `TICKET-ID` suy ra phải khớp tên file PRD thật. Lệch → **DỪNG**, in cả hai giá
208
- trị. (Suy sai `TICKET-ID` là ghi cả một PRD vào sai thư mục — không có bước nào phía sau bắt được.)
209
-
210
- ---
211
-
212
- ## 2 — `active_platform`
213
-
214
- > **PHẢI phân giải TRƯỚC mọi phép đọc `.feature`.** `{UC-ID}-SC{N}` chỉ độc nhất trong
215
- > (UC × nền), nên một UC đa nền có **nhiều file `.feature`** — `bdd/web/`, `bdd/app/`,
216
- > `bdd/system/` — và mỗi file mang `@trace.status` **riêng**: bản web có thể `approved`
217
- > trong khi bản app còn `draft`. Đọc "file `.feature` của UC" khi chưa biết nền là đọc một
218
- > file **bất kỳ trong ba**: báo `approved` trong khi bản đang dùng còn nháp, hoặc chặn oan
219
- > một bản đã duyệt.
220
-
221
- Theo thứ tự, dừng ở cái đầu tiên khớp:
222
-
223
- 1. `$ARGUMENTS` nêu nền (`web`/`app`/`system`/…) → dùng.
224
- 2. Target là một file `.feature` → đọc `# @trace.platform` của nó.
225
- 3. Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/*/` — **đúng một** thư mục nền → dùng nó.
226
- 4. Glob `{paths.qc_dir}/{TICKET-ID}/*/` — **đúng một** thư mục nền đã có artifact → dùng nó.
227
- *(chỉ dùng cho trạm 2–6; trạm `/qc-analyze` là trạm tạo ra thư mục đó nên không có gì để soi.)*
228
- 5. Nhiều nền mà không suy được → hỏi *"QC pass này cho nền nào? (web/app/system)"*.
229
- **Có `--yes`:** không hỏi — DỪNG với lỗi rõ ràng, vì đoán bừa nền là ghi artifact vào sai
230
- thư mục và ghi `qc_status` vào sai sổ trace:
231
- ```
232
- ❌ {TICKET-ID} có {n} nền ({list}) — không suy được nền nào cho QC pass này.
233
- Chạy headless thì phải nêu tường minh: /{lệnh} {TICKET-ID} web --yes
234
- ```
235
-
236
- Lưu `active_platform`. Từ đây, **mọi** phép đọc `.feature` chỉ đọc thư mục
237
- `bdd/{active_platform}/` — không trộn SC chéo nền.
238
-
239
- ---
240
-
241
- ## 3 — `qc_artifact_dir`
242
-
243
- ```
244
- qc_artifact_dir = {paths.qc_dir}/{TICKET-ID}/{active_platform}/
245
- ```
246
-
247
- Chứa: `REQUIREMENT_ANALYSIS.md` · `DOC_GAP.md` · `TEST_PLAN.md` · `test-cases/*.Test.md`
248
- — **mỗi loại đúng MỘT file cho cả PRD**, các UC là mục/hàng bên trong.
249
-
250
- `{paths.qc_dir}` là folder top-level **nhìn thấy** trong repo QC (mặc định `docs/`, **không**
251
- phải `.agent/` ẩn) để đội QC mở và xử lý output dễ dàng. Spec chính thức ở lại spec submodule
252
- của PO — đừng ghi artifact QC vào đó.
253
-
254
- > **Sổ trace KHÔNG theo layout này.** Nó vẫn là `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{active_platform}.tsv`
255
- > — một sổ cho mỗi (UC × nền), vì mỗi hàng là một scenario. Liên kết giữa hai bên đi qua
256
- > **cột `UC`** của bảng gap, không qua đường dẫn file.
257
-
258
- ---
259
-
260
- ## 4 — `uc_list`
261
-
262
- Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/{active_platform}/*.feature`. Mỗi file → một
263
- UC: đọc `# @trace.id` (mã UC) và `# @trace.status` từ header.
264
-
265
- Chia hai nhóm:
266
-
267
- | Nhóm | Điều kiện | Xử lý |
268
- |---|---|---|
269
- | **Trong phạm vi** | `@trace.status: approved` | phân tích / thiết kế / chạy bình thường |
270
- | **Chưa xét** | khác `approved` | **KHÔNG** phân tích; vẫn ghi một hàng vào bảng phạm vi kèm trạng thái thật |
271
-
272
- In bảng phạm vi ra trước khi làm gì:
273
- ```
274
- Phạm vi QC — {TICKET-ID} / {active_platform}
275
- ✅ {UC-ID} {tên UC} approved
276
- ⏸ {UC-ID} {tên UC} draft → chưa xét
277
- → {n} UC trong phạm vi · {m} chưa xét
278
- ```
279
-
280
- **Cờ `--include-draft`:** phân tích cả UC chưa duyệt, nhưng **vẫn in bảng trên** và đánh dấu
281
- trong artifact là dựa trên BDD nháp.
282
-
283
- **Không UC nào `approved` và không có `--include-draft` → DỪNG:**
284
- ```
285
- ❌ {TICKET-ID} ({active_platform}): 0/{n} UC có BDD approved — không có gì để chạy.
286
- Cách đúng: người duyệt đặt `# @trace.status: approved` rồi chạy lại.
287
- Muốn chạy sớm trên BDD nháp (prototype): thêm --include-draft
288
- ```
289
-
290
- > **Vì sao có `--include-draft` chứ không chặn cứng.** QC sớm trên BDD nháp là một cách dùng
291
- > **cố ý được cho phép** từ trước (guard cũ là cảnh báo mềm, không phải chặn). Bỏ hẳn nó là
292
- > lấy đi một năng lực đang có mà không ai khai. Còn để mặc định `approved`-only thì cái
293
- > thường gặp là cái an toàn, và cái sớm phải nói ra.
294
-
295
- > **Vì sao `--yes` không thay được `--include-draft`.** `--yes` nghĩa *"tôi không ngồi đây để
296
- > trả lời"*; `--include-draft` nghĩa *"tôi biết BDD còn nháp và vẫn muốn chạy"*. Gộp hai cái
297
- > là để một lần chạy headless âm thầm phân tích spec chưa chốt rồi bàn giao như thể đã chốt.
298
-
299
-
300
- > **Trạm này chạy CẢ PRD, đúng như trạm 1** *(B11)* — một `TEST_PLAN.md` cho mỗi (PRD × nền).
301
- > `qa-planner/test-plan.md` vốn viết *"Test Plan cho một **feature**"* và template của nó là
302
- > `# Test Plan – <Feature>` với metadata `Feature / Project / Module`: đây là quay về đúng
303
- > tầng mà skill gốc được viết cho.
304
- >
305
- > `uc_list` ở đây **phải khớp** bảng *Phạm vi phân tích* trong `DOC_GAP.md`. Lệch nhau nghĩa là
306
- > BDD đã đổi trạng thái sau lần chạy trạm 1 → nêu ra và khuyên chạy lại `/qc-analyze`, đừng
307
- > âm thầm lập plan cho một tập UC khác với tập đã phân tích.
308
-
309
- ---
310
-
311
- ## Role
312
-
313
- Bạn là **QC Planner** — stage 2. Từ output của qc-analyze, tạo TEST PLAN:
314
- phân tích rủi ro, scenario what-if, scope/strategy test theo từng layer, và `questions-for-dev`
315
- cho mọi gap open/blocker. Bạn trả lời *"rủi ro ở đâu, phải hỏi gì?"* — bạn không
316
- thiết kế test case cụ thể (đó là qc-design-test).
317
-
318
- ## Skills (`{paths.qc_skills_dir}/qa-planner/`)
319
-
320
- - `test-plan.md` — khung plan: scope theo từng test layer (functional / integration /
321
- e2e / non-functional), what-if, entry/exit criteria, và danh sách questions-for-dev
322
- suy ra từ `DOC_GAP.md`.
323
- - `risk-model.md` — **cách tính** mức rủi ro: 7 nguồn rủi ro · khả năng × thiệt hại → P0–P3 ·
324
- và dùng mức đó chia **độ sâu** test. `test-plan.md` có khung bảng `§6`; file này là cách điền.
325
- Nạp cùng lúc, không phải thay thế.
326
-
327
- ## Output
328
-
329
- Ghi **đúng MỘT** test plan cho cả PRD vào `{qc_artifact_dir}TEST_PLAN.md`
330
- (= `{paths.qc_dir}/{TICKET-ID}/{active_platform}/TEST_PLAN.md`). Giới hạn plan trong các
331
- scenario của **các UC trong phạm vi** (`{UC-ID}-SC{N}` từ `.feature` của nền này) để
332
- qc-design-test thiết kế case theo từng scenario.
333
-
334
- Bắt buộc:
335
- - **Bảng `§3 Test items` có cột `UC`** — một plan giờ phủ nhiều UC, không có cột đó thì không
336
- ai biết vùng test nào thuộc UC nào.
337
- - **`§2 Phạm vi`** liệt kê rõ UC `⏸ Chưa xét` ở phần *Out of scope*, kèm lý do (BDD chưa
338
- approved). *Không có dòng này thì một UC bị bỏ trông giống một UC không có gì để test.*
339
- - **`§5 Entry criteria` chặn theo từng UC**, không chặn cả PRD: gap 🔴 Blocker ở UC3 không
340
- dừng việc thiết kế test cho UC1. Ghi `Ready` / `Blocked` cho **mỗi** UC.
341
-
342
- ## Report
173
+ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
174
+
175
+ ---
176
+
177
+ ## Phạm vi QC
178
+
179
+ **BẮT BUỘCđọc `.agent/steps/qc-scope.md` thực thi TOÀN BỘ quy trình trong đó**,
180
+ rồi mới tiếp tục phần bên dưới.
343
181
 
182
+ Nó chốt bốn thứ mà mọi trạm QC đều cần: `TICKET-ID` · `active_platform` ·
183
+ `qc_artifact_dir` · `uc_list` (kèm trạng thái BDD từng UC, và cờ `--include-draft`).
184
+ Bỏ qua thì artifact QC ghi vào **sai thư mục** và `qc_status` ghi vào **sai sổ trace** —
185
+ cả hai đều xảy ra trong im lặng, không có bước nào phía sau bắt được.
186
+
187
+ > **Trạm này chạy CẢ PRD, đúng như trạm 1** *(B11)* — một `TEST_PLAN.md` cho mỗi (PRD × nền).
188
+ > `qa-planner/test-plan.md` vốn viết *"Test Plan cho một **feature**"* và template của nó là
189
+ > `# Test Plan – <Feature>` với metadata `Feature / Project / Module`: đây là quay về đúng
190
+ > tầng mà skill gốc được viết cho.
191
+ >
192
+ > `uc_list` ở đây **phải khớp** bảng *Phạm vi phân tích* trong `DOC_GAP.md`. Lệch nhau nghĩa là
193
+ > BDD đã đổi trạng thái sau lần chạy trạm 1 → nêu ra và khuyên chạy lại `/qc-analyze`, đừng
194
+ > âm thầm lập plan cho một tập UC khác với tập đã phân tích.
195
+
196
+ ---
197
+
198
+ ## Role
199
+
200
+ Bạn là **QC Planner** — stage 2. Từ output của qc-analyze, tạo TEST PLAN:
201
+ phân tích rủi ro, scenario what-if, scope/strategy test theo từng layer, và `questions-for-dev`
202
+ cho mọi gap open/blocker. Bạn trả lời *"rủi ro ở đâu, phải hỏi gì?"* — bạn không
203
+ thiết kế test case cụ thể (đó là qc-design-test).
204
+
205
+ ## Skills (`{paths.qc_skills_dir}/qa-planner/`)
206
+
207
+ - `test-plan.md` — khung plan: scope theo từng test layer (functional / integration /
208
+ e2e / non-functional), what-if, entry/exit criteria, và danh sách questions-for-dev
209
+ suy ra từ `DOC_GAP.md`.
210
+ - `risk-model.md` — **cách tính** mức rủi ro: 7 nguồn rủi ro · khả năng × thiệt hại → P0–P3 ·
211
+ và dùng mức đó chia **độ sâu** test. `test-plan.md` có khung bảng `§6`; file này là cách điền.
212
+ Nạp cùng lúc, không phải thay thế.
213
+
214
+ ## Output
215
+
216
+ Ghi **đúng MỘT** test plan cho cả PRD vào `{qc_artifact_dir}TEST_PLAN.md`
217
+ (= `{paths.qc_dir}/{TICKET-ID}/{active_platform}/TEST_PLAN.md`). Giới hạn plan trong các
218
+ scenario của **các UC trong phạm vi** (`{UC-ID}-SC{N}` từ `.feature` của nền này) để
219
+ qc-design-test thiết kế case theo từng scenario.
220
+
221
+ Bắt buộc:
222
+ - **Bảng `§3 Test items` có cột `UC`** — một plan giờ phủ nhiều UC, không có cột đó thì không
223
+ ai biết vùng test nào thuộc UC nào.
224
+ - **`§2 Phạm vi`** liệt kê rõ UC `⏸ Chưa xét` ở phần *Out of scope*, kèm lý do (BDD chưa
225
+ approved). *Không có dòng này thì một UC bị bỏ trông giống một UC không có gì để test.*
226
+ - **`§5 Entry criteria` chặn theo từng UC**, không chặn cả PRD: gap 🔴 Blocker ở UC3 không
227
+ dừng việc thiết kế test cho UC1. Ghi `Ready` / `Blocked` cho **mỗi** UC.
228
+
229
+ ## Self-Review *(trước khi in Report)*
230
+
231
+ Theo 3 nhóm ở `{paths.qc_skills_dir}/_shared/self-review-principles.md` — **không chép lại ở đây**.
232
+
233
+ - **Bịa:** mỗi dòng rủi ro neo được vào một `BR`/`AC`/`GAP` **có thật** trong
234
+ `REQUIREMENT_ANALYSIS.md`/`DOC_GAP.md` — không phải rủi ro chung chung tự nghĩ ra kiểu *"hiệu
235
+ năng có thể chậm"*? Mỗi `questions-for-dev` suy ra từ một gap cụ thể?
236
+ - **Nhảy bước:** đã đọc **cả hai** file đầu vào (`REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md`) và lọc
237
+ theo cột `UC` — không chỉ đọc file thứ nhất?
238
+ - **Số liệu:** `{risks}`/`{questions}` in ở report = đúng số dòng thật trong `TEST_PLAN.md` vừa
239
+ ghi, không phải đếm nhẩm?
240
+
241
+ ## Report
242
+
344
243
  **Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·
345
- Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
346
-
347
- ```
348
- /qc-plan Hoàn tất — {TICKET-ID} ({active_platform})
349
- Phạm vi: {n} UC trong plan{nếu có: " · ⏸ {m} chưa xét"}
350
- Plan: {risks} rủi ro · {questions} câu hỏi mở cho dev · layers: {list}
351
- File: {paths.qc_dir}/{TICKET-ID}/{active_platform}/TEST_PLAN.md
352
- Sẵn sàng: {danh sách UC Ready} | Chặn: {danh sách UC Blocked + GAP-ID chặn nó}
353
- Next: /qc-design-test {UC-ID} ← thiết kế test case, chạy cho từng UC đã Ready
354
- (gửi questions-for-dev cho PO/Dev cho các UC còn Blocked)
355
- ```
244
+ Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
245
+
246
+ ```
247
+ /qc-plan Hoàn tất — {TICKET-ID} ({active_platform})
248
+ Phạm vi: {n} UC trong plan{nếu có: " · ⏸ {m} chưa xét"}
249
+ Plan: {risks} rủi ro · {questions} câu hỏi mở cho dev · layers: {list}
250
+ File: {paths.qc_dir}/{TICKET-ID}/{active_platform}/TEST_PLAN.md
251
+ Sẵn sàng: {danh sách UC Ready} | Chặn: {danh sách UC Blocked + GAP-ID chặn nó}
252
+ Self-review: { sạch | ⚠️ {n} điểm cần chú ý liệt kê}
253
+ Next: /qc-design-test {UC-ID} ← thiết kế test case, chạy cho từng UC đã Ready
254
+ (gửi questions-for-dev cho PO/Dev cho các UC còn Blocked)
255
+ ```
@@ -1,14 +1,14 @@
1
- ---
2
- version: 1.0
3
- updated: 2026-06-11
4
- ported_from: ai-automation-qc-base
5
- ---
6
-
7
- # /qc-report — QC Test Report & Evidence
8
-
9
- > Stage 6 (cuối) của QC automation pipeline native (qc-analyze → qc-plan → qc-design-test → qc-review → qc-run-test → qc-report). Port từ bước report của qa-runner team QC.
10
-
11
- ## Gate
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-06-11
4
+ ported_from: ai-automation-qc-base
5
+ ---
6
+
7
+ # /qc-report — QC Test Report & Evidence
8
+
9
+ > Stage 6 (cuối) của QC automation pipeline native (qc-analyze → qc-plan → qc-design-test → qc-review → qc-run-test → qc-report). Port từ bước report của qa-runner team QC.
10
+
11
+ ## Gate
12
12
  # Gate — Quy trình vào chuẩn cho mọi lệnh
13
13
 
14
14
  Mọi lệnh PHẢI chạy gate này trước khi thực thi phần logic riêng của nó.
@@ -160,58 +160,74 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
160
160
  - "N" → dừng, hỏi người dùng muốn thay đổi gì.
161
161
  - Có `--yes` và mức *chặn thường* → coi như "Y", **nhưng vẫn IN khối CHECKPOINT** nếu có cờ
162
162
  🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
163
-
164
-
165
- *Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID. Sinh report từ lần chạy `/qc-run-test` gần nhất. Dùng module **qc-playwright** (pytest-html + Playwright Trace — không Allure, không dashboard viết tay).*
166
-
167
- ## Context
163
+
164
+
165
+ *Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID. Sinh report từ lần chạy `/qc-run-test` gần nhất. Dùng module **qc-playwright** (pytest-html + Playwright Trace — không Allure, không dashboard viết tay).*
166
+
167
+ ## Context
168
168
  **BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
169
169
  rồi mới tiếp tục phần bên dưới.
170
170
 
171
171
  Bỏ qua bước này thì `{paths.*}`, `{tech_stack.*}`, `{conventions.*}`, guardrail từ
172
172
  `project-lessons`, và routing service (chế độ umbrella) đều **chưa được phân giải** — mọi
173
- placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
174
-
175
- ---
176
-
177
- ## Role
178
-
179
- Bạn là stage **QC Report** — biến lần chạy gần nhất thành report + evidence chia sẻ được.
180
-
181
- ## Skill (`{paths.qc_skills_dir}/qa-runner/report/`)
182
-
183
- - `report.md` — tự đủ: pytest-html (`--html=reports/<feature>/report.html
184
- --self-contained-html`) + Playwright Trace (`test-results/<nodeid>/trace.zip`, xem qua
185
- `python3 -m playwright show-trace <file>`), kèm screenshot/evidence đính trên FAIL/SKIP.
186
-
187
- ## Procedure
188
-
189
- 1. Định vị artifact của lần chạy gần nhất cho `{UC-ID}` (report pytest-html + trace).
190
- 2. Sinh/làm mới `reports/<feature>/report.html` (self-contained) và đảm bảo mỗi
191
- FAIL/SKIP có trace + screenshot đính kèm.
192
- 3. Tóm tắt TOTAL / PASS / FAIL / SKIP; với mỗi FAIL gồm lệnh `show-trace` và
193
- phân loại là script-bug hay product-gap.
194
- 4. **Bàn giao product-gap về spec (có nhắc).** Với mỗi FAIL phân loại **product-gap**
195
- (defect thật, impl ≠ spec — không phải script-bug), in một
196
- `/report-bug {UC-ID} {one-line expected-vs-actual}` sẵn-chạy để QC file nó vào spec repo dùng chung.
197
- BUG_FLOW của `/report-bug` rồi định tuyến root cause (Code / BDD / PRD / Design / Env). Không bao giờ
198
- fake-pass một product-gap — nó giữ FAIL trong `qc_status` cho tới khi fix + chạy lại. **script-bug
199
- KHÔNG được file** (QC fix script và chạy lại). Liệt kê các lệnh; đừng tự tạo report.
200
-
201
- ## Report
202
-
173
+ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
174
+
175
+ ---
176
+
177
+ ## Role
178
+
179
+ Bạn là stage **QC Report** — biến lần chạy gần nhất thành report + evidence chia sẻ được.
180
+
181
+ ## Skill (`{paths.qc_skills_dir}/qa-runner/report/`)
182
+
183
+ - `report.md` — tự đủ: pytest-html (`--html=reports/<feature>/report.html
184
+ --self-contained-html`) + Playwright Trace (`test-results/<nodeid>/trace.zip`, xem qua
185
+ `python3 -m playwright show-trace <file>`), kèm screenshot/evidence đính trên FAIL/SKIP.
186
+
187
+ ## Procedure
188
+
189
+ 1. Định vị artifact của lần chạy gần nhất cho `{UC-ID}` (report pytest-html + trace).
190
+ 2. Sinh/làm mới `reports/<feature>/report.html` (self-contained) và đảm bảo mỗi
191
+ FAIL/SKIP có trace + screenshot đính kèm.
192
+ 3. Tóm tắt TOTAL / PASS / FAIL / SKIP; với mỗi FAIL gồm lệnh `show-trace` và
193
+ phân loại là script-bug hay product-gap.
194
+ 4. **Bàn giao product-gap về spec (có nhắc).** Với mỗi FAIL phân loại **product-gap**
195
+ (defect thật, impl ≠ spec — không phải script-bug), in một
196
+ `/report-bug {UC-ID} {one-line expected-vs-actual}` sẵn-chạy để QC file nó vào spec repo dùng chung.
197
+ BUG_FLOW của `/report-bug` rồi định tuyến root cause (Code / BDD / PRD / Design / Env). Không bao giờ
198
+ fake-pass một product-gap — nó giữ FAIL trong `qc_status` cho tới khi fix + chạy lại. **script-bug
199
+ KHÔNG được file** (QC fix script và chạy lại). Liệt kê các lệnh; đừng tự tạo report.
200
+
201
+ ## Self-Review *(trước khi in Report)*
202
+
203
+ Theo 3 nhóm ở `{paths.qc_skills_dir}/_shared/self-review-principles.md` — **không chép lại ở đây**.
204
+
205
+ - **Bịa:** mọi con số trong báo cáo trích được về **một dòng cụ thể** của sổ trace / output
206
+ runner / bug report — không nội suy khi thiếu mẫu?
207
+ - **Nhảy bước:** đã tổng hợp trên **toàn bộ** SC trong phạm vi, không chỉ những SC có kết quả
208
+ đẹp? Đã liệt kê cả SC `not_run` và `flaky`, không im lặng bỏ khỏi bảng?
209
+ - **Số liệu:** mọi `%` là phép chia thật **và nói rõ mẫu số**? Chỗ thiếu dữ liệu ghi **"chưa đủ
210
+ dữ liệu"** thay vì điền một số cho đủ bảng?
211
+
212
+ > **Trạm này là nơi số liệu đi ra khỏi đội QC.** Một con số sai ở các trạm trước còn người trong
213
+ > đội nhìn thấy; sai ở đây là đi vào báo cáo cho Lead/PM. Nhóm 3 vì vậy là nhóm nặng nhất ở đây:
214
+ > *"một bảng đầy số sai tệ hơn một bảng có ô trống ghi rõ lý do"*.
215
+
216
+ ## Report
217
+
203
218
  **Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·
204
- Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
205
-
206
- ```
207
- /qc-report Hoàn tất — {UC-ID}
208
- Report: reports/<feature>/report.html (TOTAL {N} · PASS {p} · FAIL {f} · SKIP {s})
209
- Trace : test-results/<nodeid>/trace.zip (python3 -m playwright show-trace <file>)
210
-
211
- Product-gap cần file ({g}): ← chạy các lệnh này để PO/Dev thấy trên /sync (script-bug bị loại)
212
- /report-bug {UC-ID} {gap 1 — expected vs actual}
213
- /report-bug {UC-ID} {gap 2 …}
214
- (không có → skip)
215
-
216
- Next: /validate-traces {UC-ID} làm mới Living Docs (qc_status), rồi tạo PR
217
- ```
219
+ Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
220
+
221
+ ```
222
+ /qc-report Hoàn tất — {UC-ID}
223
+ Report: reports/<feature>/report.html (TOTAL {N} · PASS {p} · FAIL {f} · SKIP {s})
224
+ Trace : test-results/<nodeid>/trace.zip (python3 -m playwright show-trace <file>)
225
+
226
+ Product-gap cần file ({g}): ← chạy các lệnh này để PO/Dev thấy trên /sync (script-bug bị loại)
227
+ /report-bug {UC-ID} {gap 1 — expected vs actual}
228
+ /report-bug {UC-ID} {gap 2 …}
229
+ (không có → skip)
230
+
231
+ Self-review: {✅ sạch | ⚠️ {n} điểm cần chú ý liệt kê}
232
+ Next: /validate-traces {UC-ID} ← làm mới Living Docs (qc_status), rồi tạo PR
233
+ ```