@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,14 +1,18 @@
1
- ---
2
- version: 1.0
3
- updated: 2026-06-11
4
- ported_from: ai-automation-qc-base
5
- ---
6
-
7
- # /qc-review — QC Review Gate (test case & script)
8
-
9
- > Stage 4 của QC automation pipeline native (qc-analyze → qc-plan → qc-design-test qc-review qc-run-test qc-report). Port từ qa-reviewer của team QC. Một gate hai chiều: review test case (sau qc-design-test) VÀ script (sau qc-run-test).
10
-
11
- ## Gate
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-16
4
+ ported_from: ai-automation-qc-base
5
+ ---
6
+
7
+ # /qc-review-script — QC Review Gate: script
8
+
9
+ > Soát **code test + Page Object** đã sinh: khớp `.Test.md`, cấu trúc Page Object, assertion,
10
+ > selector, hard-code. Cặp với `/qc-review-testcase` — hai lệnh, hai vai, không còn đoán.
11
+
12
+ ## Gate
13
+
14
+ *Checkpoint: **không chặn** — lệnh ghi `REVIEW_SCRIPT_<FEATURE>.md`, là BIÊN BẢN của một lượt soát: sinh lại = soát lại, không trạng thái nào tích luỹ. Xem §Chạy lại.*
15
+
12
16
  # Gate — Quy trình vào chuẩn cho mọi lệnh
13
17
 
14
18
  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ó.
@@ -88,7 +92,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
88
92
 
89
93
  | Mức | Lệnh nào | `--yes` bỏ qua được? |
90
94
  |---|---|:---:|
91
- | **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
95
+ | **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ó) |
92
96
  | **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
93
97
  | **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
94
98
 
@@ -96,6 +100,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
96
100
  `--` 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
97
101
  headless: `claude -p "/generate-code UC1 --yes"`.
98
102
 
103
+ > **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
104
+ > tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
105
+ > ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
106
+ > mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
107
+ > `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
108
+
99
109
  > **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: …*`
100
110
  > 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
101
111
  > **nghĩa là gì**.
@@ -160,134 +170,164 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
160
170
  - "N" → dừng, hỏi người dùng muốn thay đổi gì.
161
171
  - 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
172
  🔴/⚠️ (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 (`active_platform` + `qc_artifact_dir` do §Phạm vi QC phân giải). Phát hiện review mode từ `$ARGUMENTS`/context: review test-case `.Test.md` (sau design) hoặc review Python script (sau run). Đọc artifact từ `{qc_artifact_dir}` source test/page-object đã sinh.*
166
-
167
- ## Context
173
+
174
+
175
+ *Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID (`active_platform` + `qc_artifact_dir` do §Phạm vi QC phân giải). Đọc **code test + Page Object** của UC, và đọc `.Test.md` chỉ để **đối chiếu 1-1** KHÔNG soát nội dung `.Test.md`, đó việc của `/qc-review-testcase`.*
176
+
177
+ ## Context
168
178
  **BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
169
179
  rồi mới tiếp tục phần bên dưới.
170
180
 
171
181
  Bỏ qua bước này thì `{paths.*}`, `{tech_stack.*}`, `{conventions.*}`, guardrail từ
172
182
  `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
- ## Phạm vi QC
176
-
183
+ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
184
+
185
+ ## Phạm vi QC
186
+
177
187
  **BẮT BUỘC — đọc `.agent/steps/qc-scope.md` và thực thi TOÀN BỘ quy trình trong đó**,
178
188
  rồi mới tiếp tục phần bên dưới.
179
189
 
180
190
  Nó chốt bốn thứ mà mọi trạm QC đều cần: `TICKET-ID` · `active_platform` ·
181
- `qc_artifact_dir` · `uc_list` (kèm trạng thái BDD từng UC, và cờ `--include-draft`).
191
+ `qc_artifact_dir` · `uc_list` (kèm trạng thái BDD từng UC, và cờ `--force`).
182
192
  Bỏ qua thì artifact QC ghi vào **sai thư mục** và `qc_status` ghi vào **sai sổ trace** —
183
- cả hai đều xảy ra trong im lặng, không có bước nào phía sau bắt được.
184
-
185
- > **Trạm này vẫn gọi theo TỪNG UC** *(B11)* — thiết kế và chạy test **thật sự** làm tăng dần
186
- > theo UC, nên giữ khả năng làm UC1 khi UC3 chưa xong là đúng. Chỉ **chỗ đọc/ghi** đổi: mọi
187
- > artifact nằm chung ở `{qc_artifact_dir}` cấp PRD, không còn một thư mục mỗi UC.
188
- >
189
- > Nên `DOC_GAP.md` / `TEST_PLAN.md` đọc được đây phủ **cả PRD**: **lọc theo cột `UC`** để lấy
190
- > phần của UC đang làm. Đừng coi toàn bộ bảng gap là của UC này — sẽ chặn oan.
191
-
192
- ---
193
-
194
-
195
- ---
196
-
197
- ## Role
198
-
199
- Bạn **QC Reviewer** — gate review dùng chung, chạy hai lần trong pipeline:
200
- 1. **Sau qc-design-test** → review test-case `.Test.md` (coverage, độ rõ ràng, trace).
201
- 2. **Sau qc-run-test** → review Python script / Page Object đã sinh.
202
-
203
- Phát hiện mode: nếu artifact target là `.Test.md` → review test-case; nếu file Python test/PO
204
- tồn tại cho UC và mới hơn → review script. Nếu mơ hồ, hỏi.
205
-
206
- ## Skills (`{paths.qc_skills_dir}/qa-reviewer/`)
207
-
208
- **Nạp trước nhưng đúng vai:**
209
-
210
- | File | Vai nào | Cho gì |
211
- |---|---|---|
212
- | `shared/read-doc-gap-inputs.md` | **cả hai** | Nạp **đủ** mọi tài liệu nguồn theo bảng *Tài liệu đầu vào đã đọc* của `DOC_GAP.md` — soát mù thì kết luận "0 lỗi" là vô nghĩa |
213
- | `shared/review-file-template.md` | **cả hai** | Khuôn file kết quả · thang điểm `XX/100` · luật ghi file · nguyên tắc *mặc định hoài nghi* |
214
- | ↳ §*Kiểm tra cấu trúc TC* của file đó | **chỉ vai 1** | Tầng kiểm các luật của trạm 3: ATOMIC 1-bullet · không ký tự `\|` · cụm từ mơ hồ · teardown đúng chỗ · marker ≠ oracle |
215
- | `shared/review-check-groups.md` | **chỉ vai 1** | **7 nhóm kiểm tra** chạy tuần tự · registry 46 nhãn lỗi · **7 mẫu-hay-thiếu** của Nhóm 6 · nền tảng ISTQB · anti-pattern |
216
-
217
- > ⚠️ **Vai 2 (soát code) KHÔNG nạp 7 nhóm kiểm tra.** Chúng kiểm **cấu trúc file test case** —
218
- > áp vào file Python là bảo reviewer đi tìm `#### Expected Result` trong một Page Object, rồi
219
- > gắn nhãn lỗi cho thứ đáng lẽ không có ở đó. Vai 2 dùng bộ tiêu chí riêng ở `script/*.md`.
220
-
221
- **Rồi chọn theo vai + tầng, nạp MỘT file:**
222
- - Soát test-case: `test-case/{functional,e2e,integration,non-functional,exploratory}.md`
223
- - Soát script: `script/{functional,e2e,integration,non-functional,exploratory}.md`
224
-
225
- ## Review focus
226
-
227
- - **Test-case:** mọi `{UC-ID}-SC{N}` đã phủ? happy + negative + boundary? expected cụ thể? trace (`BR-xx` + `@trace.verifies` SC) mặt? không TC orphan?
228
- - **Script:** khớp `.Test.md` 1-1? Page Object 3 lớp + BasePage gọn? `expect()` không phải bare assert? không hard-code URL/cred/timeout, không `time.sleep`, không Allure? selector theo priority (data-testid→role→…)? 100% TC đã script (không còn Draft)?
229
-
230
- Sinh findings (mức độ + vị trí + cách sửa), chấm điểm, ra verdict.
231
-
232
- **KHÔNG tự sửa** file TC hay code. Chỉ nhận xét chấm điểm người sửa `/qc-design-test`
233
- (vai 1) hoặc `/qc-run-test` (vai 2). *Reviewer tự sửa rồi tự duyệt là bỏ mất cái cổng.*
234
-
235
- ## Output
236
-
237
- Ghi vào **`{qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md`** — đứng **cạnh** file TC vừa soát:
238
-
239
- ```
240
- {qc_artifact_dir}test-cases/
241
- ├── TC_<FEATURE>.Test.md
242
- ├── REVIEW_<FEATURE>.md ← soát file trên
243
- ├── TC_<FEATURE>_API.Test.md
244
- └── REVIEW_<FEATURE>_API.md ← soát file trên
245
- ```
246
-
247
- ⚠️ **Tên file review KHÔNG có đuôi `.Test.md`.** Đuôi đó là của file test case; gắn vào file
248
- review sẽ làm `/qc-run-test` nhặt nó lên như một file test case rồi cố sinh script từ một bảng điểm.
249
-
250
- Khuôn đầy đủ + quy tắc ghi: `shared/review-file-template.md`. Ba điều bắt buộc:
251
-
252
- - **Điểm `XX/100`** trừ mỗi `FAIL`, 2đ mỗi `WARN`. Verdict **suy ra được**:
253
- `≥80` không còn `FAIL` chặn `APPROVED`; ngược lại `NEEDS_FIX`.
254
- - **Bảng Tổng quan THÊM một hàng mỗi vòng**, không ghi đè đó cách duy nhất thấy được điểm
255
- tăng không. Các bảng chi tiết thì ghi đè phần của tầng mình.
256
- - **Hai vai ghi vào CÙNG một file**, phân biệt bằng cột `Tầng`. Chúng cách nhau một trạm, nên
257
- hàng của vai sau **không được ghi đè** hàng của vai trước.
258
-
259
- > **Vì sao cổng này phải ghi ra file** *(B13)*. Trước đây lệnh chỉ nói *"sinh findings"* không
260
- > nói ghi đâu, dạng gì, và điểm là `A/B/C/D` **không có luật chấm**. Hệ quả: hai người soát ra
261
- > hai kết quả, và **vòng 2 không so được với vòng 1** — tức không ai biết sửa xong có tốt lên
262
- > không. Một cổng không để lại dấu vết đo được thì không phải cổng, nó là một lượt đọc.
263
-
264
- ## Self-Review *(trước khi in Report)*
265
-
266
- Theo 3 nhóm ở `{paths.qc_skills_dir}/_shared/self-review-principles.md` — **không chép lại ở đây**.
267
-
268
- - **Bịa:** mỗi finding trỏ được về **dòng cụ thể** trong artifact đang soát — không phải nhận xét
269
- chung chung? **cấm dùng chính field `quote` của finding làm bằng chứng cho nó** — mở lại file
270
- đọc lại đoạn đó.
271
- - **Nhảy bước:** đã đi hết bộ tiêu chí của **đúng vai** (test-case hay script), không trộn hai
272
- bộ? Verdict `APPROVED` phát ra **sau** khi soát đủ, không phải "trông ổn"?
273
- - **Số liệu:** số finding theo mức (critical/major/minor) = đếm thật trên file findings vừa ghi?
274
-
275
- > **Verdict của lệnh này cổng cho trạm sau.** Một `APPROVED` phát ra sớm không chỉ sai ở đây —
276
- > nó mở đường cho `/qc-run-test` sinh script từ một bộ TC chưa đạt. Đây là chỗ self-review đắt
277
- > nhất nếu bỏ qua.
278
-
279
- ## Report
280
-
193
+ cả hai đều xảy ra trong im lặng, không có bước nào phía sau bắt được.
194
+
195
+ ---
196
+
197
+ ## Role
198
+
199
+ Bạn **QC Reviewer vai script**. Soát code test sau trạm sinh script.
200
+
201
+ > **Vì sao lệnh này tồn tại tách riêng** *(Đợt 2 · b1)*. Trước đây `/qc-review` làm cả hai vai và
202
+ > **tự đoán** vai nào bằng cách so ngày sửa file. Hậu quả nặng nhất không phải đoán sai — mà là
203
+ > **trạm sau không đặt được điều kiện tiên quyết**: `REVIEW_<FEATURE>.md` không nói nó là kết quả
204
+ > soát test case hay soát script, nên `/qc-run-script` không hỏi được *"script đã APPROVED chưa?"*.
205
+
206
+ **KHÔNG tự sửa** code test hay Page Object. Chỉ nhận xét, chấm điểm, ra verdict — người sửa là
207
+ trạm sinh script. *Reviewer tự sửa rồi tự duyệt là bỏ mất cái cổng.*
208
+
209
+ ## Skills (`{paths.qc_skills_dir}/qa-reviewer/`)
210
+
211
+ **Nạp trước:**
212
+
213
+ | File | Cho |
214
+ |---|---|
215
+ | `shared/read-doc-gap-inputs.md` | Nạp **đủ** mọi tài liệu nguồn theo bảng *Tài liệu đầu vào đã đọc* của `DOC_GAP.md` — soát mù thì kết luận "0 lỗi" là vô nghĩa |
216
+ | `shared/review-file-template.md` | Khuôn file kết quả · thang điểm `XX/100` · luật ghi file · nguyên tắc *mặc định hoài nghi* |
217
+
218
+ **Rồi chọn theo tầng, nạp MỘT file:**
219
+ `script/{functional,e2e,integration,non-functional,exploratory}.md`
220
+
221
+ > ⚠️ **KHÔNG nạp `shared/review-check-groups.md` và §*Kiểm tra cấu trúc TC*.** Hai thứ đó kiểm
222
+ > **cấu trúc file test case** áp vào một Page Object bảo reviewer đi tìm `#### Expected Result`
223
+ > trong code, rồi gắn nhãn lỗi cho thứ đáng lẽ không đó.
224
+ >
225
+ > *Ghi chú Đợt 2 · b2:* bộ `script/*` hiện **phẳng theo tầng**. Khi bước 2 chốt stack, sẽ tái
226
+ > cấu trúc thành `script/{web,mobile}/*` — tiêu chí soát khác nhau theo nền. **Cố ý chưa làm ở
227
+ > bước này**: viết tiêu chí cho một stack chưa chốt viết hai lần.
228
+
229
+ ---
230
+
231
+ ## Review focus
232
+
233
+ - **Khớp `.Test.md` 1-1?** Mỗi TC có đúng một test tương ứng; không test mồ côi, không TC bị bỏ.
234
+ - **Page Object 3 lớp + BasePage gọn?** Logic điều hướng không rò vào file test.
235
+ - **`expect()` chứ không phải bare assert?** Assertion phải nói được nó kỳ vọng gì khi đỏ.
236
+ - **Không hard-code** URL · credential · timeout. Không `sleep` cố định. Không Allure.
237
+ - **Selector theo thứ tự ưu tiên** (`data-testid` role → …), lấy từ §4.5.6 chứ không DOM.
238
+ - **100% TC đã script** không còn TC trạng thái `Draft`.
239
+
240
+ Sinh findings (mức độ + vị trí + cách sửa), chấm điểm, ra verdict.
241
+
242
+ > **Chân thứ của hợp đồng test-id KHÔNG kiểm đây.** Phép so §4.5.6 `*.Test.md` chạy trên
243
+ > file test case, nên nó thuộc `/qc-review-testcase` *(`bin/trace-schema.json`
244
+ > `testid_fourth_leg.checked_by`)*. Ở trạm script, locator dựng **lúc chạy** từ bảng tươi — nó tự
245
+ > cứu, và đó là lý do chân này chưa bao giờ cần canh ở đây.
246
+
247
+ ## Output
248
+
249
+ Ghi vào **`{qc_artifact_dir}test-cases/REVIEW_SCRIPT_<FEATURE>.md`** — **file riêng**, không chung
250
+ với biên bản soát test case:
251
+
252
+ ```
253
+ {qc_artifact_dir}test-cases/
254
+ ├── TC_<FEATURE>.Test.md
255
+ ├── REVIEW_<FEATURE>.md ← /qc-review-testcase
256
+ └── REVIEW_SCRIPT_<FEATURE>.md ← lệnh này
257
+ ```
258
+
259
+ ⚠️ **Tên file review KHÔNG có đuôi `.Test.md`.** Đuôi đó là của file test case; gắn vào file
260
+ review sẽ làm trạm sau nhặt lên như một file test case rồi cố sinh script từ một bảng điểm.
261
+
262
+ > **Vì sao tách file thay chung một file phân biệt bằng cột `Tầng`** *(Đợt 2 · b1 · E2)*. Hai
263
+ > lượt soát cách nhau vài trạm. Chung file thì lượt sau **đè** bảng chi tiết của lượt trước, và
264
+ > quan trọng hơn: trạm tiêu thụ verdict phải đọc được verdict của **đúng vai cần** chung file
265
+ > thì lại phải đoán, tức mang nguyên vấn đề sang một chỗ mới.
266
+
267
+ ### Verdict hợp đồng máy đọc được
268
+
269
+ File **phải** chứa đúng một dòng theo khuôn này, §Tổng quan:
270
+
271
+ ```
272
+ **Verdict:** APPROVED
273
+ ```
274
+ hoặc
275
+ ```
276
+ **Verdict:** NEEDS_FIX
277
+ ```
278
+
279
+ `APPROVED` khi **điểm `≥80` không còn `FAIL` chặn**; ngược lại `NEEDS_FIX`.
280
+
281
+ > **Đây contract, không phải định dạng cho đẹp.** `/qc-run-script` (Đợt 2 · b2) **DỪNG** khi
282
+ > verdict `NEEDS_FIX` hoặc chưa file này. Đổi chuỗi này làm trạm đó mù — nên nếu phải
283
+ > đổi, đổi cả hai nơi trong cùng một commit.
284
+
285
+ ### Chạy lại ghi đè đây AN TOÀN, đây do
286
+
287
+ `REVIEW_SCRIPT_<FEATURE>.md` **biên bản của một lần soát**. Sinh lại = **soát lại**, đúng bản
288
+ chất của nó — không có trạng thái nào tích luỹ qua các lần chạy, không ô nào người điền tay vào sau.
289
+
290
+ *Khai máy đọc: `bin/trace-schema.json` → `artifact_writers.enrolled.qc-review-script.has_human_content = false`
291
+ — và **R18 ép khai `why`** chính vì một ngoại lệ có chủ ý trông y hệt một chỗ sót.*
292
+
293
+ > **⚠️ Khai lại nếu điều này hết đúng.** Có ai bắt đầu ghi vào biên bản thứ **không sinh lại được** —
294
+ > chữ ký duyệt, một quyết định *"chấp nhận rủi ro"* — thì lệnh này **phải** lên
295
+ > `checkpoint_levels.hard` và có §Chạy lại như `/qc-analyze`.
296
+ >
297
+ > *Lưu ý ngược lại: code test mà trạm này **soát** thì **có** phần QC sửa tay, và trạm sinh script
298
+ > đã ở mức `hard` vì đúng lý do đó (G77). Trạm này chỉ an toàn ở phần nó **ghi**, không phải phần
299
+ > nó **đọc**.*
300
+
301
+ Khuôn đầy đủ + quy tắc ghi: `shared/review-file-template.md`. Hai điều bắt buộc:
302
+
303
+ - **Điểm `XX/100`** — trừ 5đ mỗi `FAIL`, 2đ mỗi `WARN`. Verdict **suy ra được** theo luật ở trên.
304
+ - **Bảng Tổng quan THÊM một hàng mỗi vòng**, không ghi đè — đó là cách duy nhất thấy được điểm
305
+ có tăng không. Các bảng chi tiết thì ghi đè phần của vòng mình.
306
+
307
+ ## Self-Review *(trước khi in Report)*
308
+
309
+ Theo 3 nhóm ở `{paths.qc_skills_dir}/_shared/self-review-principles.md` — **không chép lại ở đây**.
310
+
311
+ - **Bịa:** mỗi finding trỏ được về **file + dòng cụ thể** trong code đang soát? Và **cấm dùng chính
312
+ field `quote` của finding làm bằng chứng cho nó** — mở lại file đọc lại đoạn đó.
313
+ - **Nhảy bước:** đã đi hết bộ tiêu chí `script/*`, **không** trộn tiêu chí test case vào? Verdict
314
+ `APPROVED` phát ra **sau** khi soát đủ, không phải vì "trông ổn"?
315
+ - **Số liệu:** số finding theo mức (critical/major/minor) = đếm thật trên file vừa ghi?
316
+
317
+ > **Verdict của lệnh này là cổng cho trạm chạy.** Một `APPROVED` phát ra sớm cho chạy một bộ script
318
+ > chưa đạt, và kết quả chạy đó đi thẳng vào `/qc-report` thành số liệu người ta tin.
319
+
320
+ ## Report
321
+
281
322
  **Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·
282
- Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
283
-
284
- ```
285
- /qc-review Hoàn tất — {UC-ID} ({soát test-case | soát script}) vòng #{N}
286
- Điểm : {XX}/100 ({fail} FAIL × −5đ · {warn} WARN × −2đ){nếu có vòng trước: " ← vòng #{N-1}: {YY}/100"}
287
- Verdict: {APPROVED | NEEDS_FIX} — {n} findings ({crit} chặn)
288
- File : {qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md (thêm 1 hàng vào bảng Tổng quan)
289
- Self-review: {✅ sạch | ⚠️ {n} điểm cần chú ý — liệt kê}
290
- Next (test-case APPROVED): /qc-run-test {UC-ID}
291
- Next (script APPROVED) : /qc-report {UC-ID} rồi tạo PR
292
- (NEEDS_FIX → fix artifact bị gắn cờ, rồi chạy lại /qc-review {UC-ID})
293
- ```
323
+ Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
324
+
325
+ ```
326
+ /qc-review-script Hoàn tất — {UC-ID} vòng #{N}
327
+ Điểm : {XX}/100 ({fail} FAIL × −5đ · {warn} WARN × −2đ){nếu có vòng trước: " ← vòng #{N-1}: {YY}/100"}
328
+ Verdict: {APPROVED | NEEDS_FIX} — {n} findings ({crit} chặn)
329
+ File : {qc_artifact_dir}test-cases/REVIEW_SCRIPT_<FEATURE>.md (thêm 1 hàng vào bảng Tổng quan)
330
+ Self-review: {✅ sạch | ⚠️ {n} điểm cần chú ý — liệt kê}
331
+ Next (APPROVED) : /qc-report {UC-ID} rồi tạo PR
332
+ (NEEDS_FIX → sửa script bị gắn cờ, rồi chạy lại lệnh này)
333
+ ```