@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,59 +1,85 @@
1
- [← /qc-design-test](17-qc-design-test.md) · [Explain Home](README.md) · [Next: /qc-run-test →](19-qc-run-test.md)
1
+ [← /qc-design-test](17-qc-design-test.md) · [Explain Home](README.md) · [Next: ba trạm script →](19-qc-run-test.md)
2
2
 
3
- # 18 · `/qc-review` — Trạm 4: Cổng review hai chiều (test case & script)
3
+ # 18 · `/qc-review-testcase` + `/qc-review-script` — Trạm 4: Hai cổng review
4
4
 
5
- > **Một câu.** Gate chất lượng của QC: review **test case** (sau design-test) VÀ **script** (sau run-test) chạy hai thời điểm trong dây chuyền.
5
+ > **Một câu.** Gate chất lượng của QC, **hai lệnh riêng**: `/qc-review-testcase` soát test case sau design-test; `/qc-review-script` soát code test sau khi script được sinh.
6
+
7
+ > **Trước Đợt 2 đây là MỘT lệnh `/qc-review` làm cả hai vai và tự đoán vai nào bằng cách so ngày sửa file.** Chính trang này từng ghi ở mục *Góc nhìn tối ưu*: *"Chạy 2 lần cùng một lệnh — người dùng phải nhớ gọi đúng thời điểm… **Cân nhắc tách rõ**"*. Đó là việc đã làm.
6
8
 
7
9
  ---
8
10
 
9
11
  ## Vấn đề giải quyết
10
12
 
11
- Không chạy test kém. Trạm này chặn: (1) test case chưa đủ tốt trước khi biến thành script; (2) script chưa đúng trước khi coi kết quả là chính thức.
13
+ Không chạy test kém. Hai cổng chặn hai thứ khác nhau:
14
+
15
+ 1. **`/qc-review-testcase`** — test case chưa đủ tốt trước khi biến thành script.
16
+ 2. **`/qc-review-script`** — script chưa đúng trước khi coi kết quả chạy là chính thức.
17
+
18
+ Và **cái mà một-lệnh-hai-vai không làm được:** đặt điều kiện tiên quyết cho trạm sau. `REVIEW_<FEATURE>.md` của lệnh cũ không nói nó là kết quả soát vai nào, nên trạm sau không hỏi được *"cái tôi cần đã APPROVED chưa?"*.
12
19
 
13
20
  ---
14
21
 
15
22
  ## Vị trí & tiền đề
16
23
 
17
- - **Vị trí:** Phase QC (trạm 4) — **hai lần**: sau `/qc-design-test` (review case) sau `/qc-run-test` (review script).
24
+ | Lệnh | Chạy sau | Đọc | Ghi |
25
+ |---|---|---|---|
26
+ | `/qc-review-testcase` | `/qc-design-test` | `.Test.md` | `REVIEW_<FEATURE>.md` |
27
+ | `/qc-review-script` | trạm sinh script | code test + Page Object | `REVIEW_SCRIPT_<FEATURE>.md` |
28
+
29
+ **File riêng, không chung.** Hai lượt soát cách nhau vài trạm; chung file thì lượt sau đè bảng chi tiết của lượt trước, và trạm tiêu thụ verdict lại phải đoán — tức mang nguyên vấn đề cũ sang chỗ mới.
18
30
 
19
31
  ---
20
32
 
21
33
  ## Input / Output
22
34
 
23
- **Input:** `.Test.md` (case) hoặc script Python (script) + skill `qa-reviewer`.
35
+ **Input:** `.Test.md` *(vai test case)* hoặc code test + Page Object *(vai script)*, cộng skill `qa-reviewer`.
24
36
 
25
- **Output:** verdict APPROVED / NEEDS_FIX + findings review.
37
+ **Output:** file biên bản riêng của mỗi vai, chứa điểm `XX/100` **một dòng verdict máy đọc được**:
38
+
39
+ ```
40
+ **Verdict:** APPROVED
41
+ **Verdict:** NEEDS_FIX
42
+ ```
43
+
44
+ `APPROVED` khi điểm `≥80` **và** không còn `FAIL` chặn. Đây là **contract**, không phải định dạng cho đẹp — `/qc-automation-assess` loại TC chưa `APPROVED`, `/qc-run-script` dừng khi script chưa `APPROVED`.
26
45
 
27
46
  ---
28
47
 
29
- ## Các bước xử lý (chi tiết)
48
+ ## Các bước xử lý
49
+
50
+ 1. **Role qa-reviewer** — nạp `{qc_skills_dir}/qa-reviewer/`, **đúng bộ của vai mình**.
51
+ 2. **Review focus** — test case: đủ phủ SC, expected cụ thể, trace, `🚫 Block` còn hiệu lực. Script: khớp `.Test.md` 1-1, Page Object gọn, `expect()` thật, **selector bám §4.5.6 chứ không dò DOM**, không hard-code.
52
+ 3. **Self-Review** — nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
53
+ 4. **Verdict** — `APPROVED` → đi tiếp; `NEEDS_FIX` → sửa rồi review lại.
30
54
 
31
- 1. **Role qa-reviewer** nạp `{qc_skills_dir}/qa-reviewer/`.
32
- 2. **Review focus** — kiểm test case (đủ phủ, đúng SC) hoặc script (đúng logic, selector, không fake-pass).
33
- 3. Verdict: APPROVED → đi tiếp; NEEDS_FIX → sửa rồi review lại.
55
+ > **Self-Review ≠ Guard.** Guard là phép **đếm cơ học**, có hệ quả bắt buộc khi lệch. Self-review là lượt đọc lại **rộng hơn nhưng mềm hơn**, soát ba nhóm lỗi mà phép đếm không bắt được (bịa dữ kiện · lẫn suy đoán với sự thật · bỏ dở giữa chừng). Một bộ nguyên tắc tự soát **không bao giờ** được dùng làm lý do gỡ một Guard.
34
56
 
35
57
  ---
36
58
 
37
59
  ## Checkpoint & Gate
38
60
 
39
- - 🛑 **Cổng hai chiều** — chặn `/qc-run-test` (nếu case chưa duyệt) chặn tạo PR (nếu script chưa duyệt).
61
+ - Cả hai lệnh ở mức **không chặn** chúng chỉ ghi **biên bản**,sinh lại = soát lại.
62
+ - Cổng thật nằm ở **verdict chúng phát ra**, được trạm sau đọc.
40
63
 
41
64
  ---
42
65
 
43
66
  ## Cơ chế đặc biệt
44
67
 
45
- - **Một lệnh, hai vai** — review case review script dùng chung skill, khác focus.
46
- - **Gate thật của QC** — điểm HITL chính trong dây chuyền tự động.
68
+ - **Chân thứ của hợp đồng test-id** — phép so §4.5.6 ↔ `*.Test.md`, mức `warn`, một chiều. Vai này thuộc **`/qc-review-testcase`** *(`bin/trace-schema.json` `testid_fourth_leg.checked_by`)*, vì phép so chạy trên `.Test.md`. Ở trạm script, locator dựng **lúc chạy** từ bảng tươi nên nó tự cứu.
69
+ - **Đọc stamp phiên bản nguồn** — cũng thuộc vai test case *(`qc_artifact_stamp.checked_by`)*.
70
+ - **Điểm có luật chấm** — trừ 5đ mỗi `FAIL`, 2đ mỗi `WARN`; 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 sửa xong có tốt lên không.
71
+ - **Reviewer KHÔNG tự sửa** — chỉ nhận xét và chấm. *Tự sửa rồi tự duyệt là bỏ mất cái cổng.*
47
72
 
48
73
  ---
49
74
 
50
75
  ## 👓 Góc nhìn tối ưu
51
76
 
52
- - **Chạy 2 lần cùng một lệnh** — người dùng phải nhớ gọi đúng thời điểm. Footer "Next" hướng dẫn, nhưng dễ nhầm. Cân nhắc tách hoặc auto-detect giai đoạn.
53
- - **Verdict thủ công** phụ thuộc reviewer; không findings-file như review-context. Đáng xem nên chuẩn hoá.
77
+ - **Verdict vẫn do LLM phát ra** — luật chấm rõ, nhưng không máy nào kiểm lại. Lớp CI cho `T19` *(chân thứ tư)*; phần điểm số thì chưa.
78
+ - **Bộ tiêu chí `script/*` còn phẳng theo tầng.** Khi Đợt 2 bước 2 chốt stack, nó sẽ tách theo nền (`web`/`mobile`) vì tiêu chí khác nhau. Cố ý chưa làm bước 1 — viết tiêu chí cho stack chưa chốt là viết hai lần.
54
79
 
55
80
  ---
56
81
 
57
82
  ## Kết nối
58
83
 
59
- **Trước:** [`/qc-design-test`](17-qc-design-test.md) (case) / [`/qc-run-test`](19-qc-run-test.md) (script) · **Sau:** case APPROVED → [`/qc-run-test`](19-qc-run-test.md); script APPROVED → [`/qc-report`](20-qc-report.md) / PR.
84
+ **Trước:** [`/qc-design-test`](17-qc-design-test.md) *(vai test case)* · [ba trạm script](19-qc-run-test.md) *(vai script)*
85
+ **Sau:** test case `APPROVED` → [ba trạm script](19-qc-run-test.md) · script `APPROVED` → [`/qc-report`](20-qc-report.md) rồi tạo PR
@@ -1,6 +1,6 @@
1
- [← /qc-review](18-qc-review.md) · [Explain Home](README.md) · [Next: /qc-report →](20-qc-report.md)
1
+ [← hai cổng review](18-qc-review.md) · [Explain Home](README.md) · [Next: /qc-report →](20-qc-report.md)
2
2
 
3
- # 19 · `/qc-run-test` — Trạm 5: Sinh & chạy Playwright, ghi `qc_status`
3
+ # 19 · `/qc-design-script` · `/qc-run-script` · `/qc-run-manualtest` — Trạm 5–7: sinh · chạy · chạy tay
4
4
 
5
5
  > **Một câu.** Biến `.Test.md` đã review thành **Python pytest-playwright**, chạy thật, rồi ghi **`qc_status` chính thức** (có evidence) vào trace TSV.
6
6
 
@@ -8,13 +8,16 @@
8
8
 
9
9
  ## Vấn đề giải quyết
10
10
 
11
+ > **Trước Đợt 2 · b2 đây là MỘT lệnh `/qc-run-test` gánh BỐN việc**: quyết cái nào automate được · viết mã · chạy · phán một kết quả đỏ là lỗi sản phẩm hay lỗi mã test. Bốn quyết định, không chỗ nào dừng giữa chúng — nên không ai soát được mã trước khi nó chạy, và TC **không** automate được (OTP, sinh trắc học) rơi ra ngoài: không trạm nào ghi `qc_status` cho chúng, rồi `/qc-report` chấm cả PRD là FAIL vĩnh viễn. `/qc-run-manualtest` sinh ra để bịt đúng chỗ đó.
12
+
13
+
11
14
  Đây là nơi QC trở thành **chính thức**: chạy test thật trên Playwright, phân loại FAIL (script-bug vs product-gap, **không fake-pass**), và đóng dấu `qc_status` — trạng thái QC authoritative.
12
15
 
13
16
  ---
14
17
 
15
18
  ## Vị trí & tiền đề
16
19
 
17
- - **Vị trí:** Phase QC (trạm 5), sau `/qc-review` (case APPROVED).
20
+ - **Vị trí:** Phase QC, **ba trạm** 5 sinh script · 6 chạy script · 7b chạy tay. `/qc-design-script` chạy sau `/qc-review-testcase` (case APPROVED); `/qc-run-script` chạy sau `/qc-review-script` (script APPROVED).
18
21
  - **Stack:** module `qc-playwright` (Python + pytest-playwright + Page Object) — **độc lập** module dev.
19
22
 
20
23
  ---
@@ -36,20 +39,41 @@
36
39
  1. **Role & stack** — qc-playwright (`stack-profile.yaml`): Python, pytest-playwright fixture, Page Object; mỗi test độc lập; gom theo (role, account) để auth không xen kẽ.
37
40
  2. **Skills** — nạp một file skill `qa-runner` theo layer.
38
41
  3. **Sinh script** từ `.Test.md`; tag `@trace.verifies={UC-ID}-SC{N}`.
39
- 4. **Chạy** phân loại mỗi FAIL: **script-bug** (fix selector/logic) vs **product-gap** (giữ FAIL + evidence, **không bao giờ fake-pass**).
42
+ 4. **Chạy.** Test đỏ **một lần** chưa nói được đỏ cái **chạy lại riêng test đó, tối đa 2 lần**, rồi mới phân loại thành **ba** nhãn:
43
+
44
+ ```
45
+ đỏ → đỏ → đỏ ⇒ NHẤT QUÁN → sang bước điều tra: script-bug | product-gap
46
+ đỏ → xanh ⇒ KHÔNG NHẤT QUÁN → flaky
47
+ đỏ → đỏ → xanh ⇒ KHÔNG NHẤT QUÁN → flaky
48
+ ```
49
+
50
+ | Nhãn | Khi nào | Hệ quả |
51
+ |---|---|---|
52
+ | `script-bug` | Sai locator / logic test / timing / dữ liệu test | QC tự sửa. **Không** mở bug |
53
+ | `product-gap` | Hành vi thật ≠ spec — defect thật | Mở bug qua `/report-bug`. Giữ `fail` + evidence, **không bao giờ fake-pass** |
54
+ | `flaky` | Không nhất quán ở bước chạy lại — **chưa đủ căn cứ** | Cách ly + ghi **nghi vấn** nguyên nhân. **Không** mở bug từ một lần chạy hên xui |
55
+
56
+ **Điều tra bằng bằng chứng, không đoán** — đọc trace/video/log: timeline, DOM snapshot, network, console **tại thời điểm fail**. Không chắc giữa `script-bug` và `product-gap` → **mời Dev cùng xem trace**.
57
+
58
+ 🛑 **Người xác nhận TRƯỚC khi hành động** — lệnh in đề xuất kèm evidence cụ thể rồi **dừng chờ**. **Không ghi `qc_status`** cho scenario nào còn FAIL chưa được xác nhận nhãn.
40
59
  5. **Write Trace State — `qc_status`** (kết quả QC chính thức) + `qc_run_at`, `qc_owner`, `qc_blocked_by`, `last_updated`.
41
60
 
42
61
  ⚠️ **ĐỌC cột `status` TRƯỚC KHI GHI `pass`** *(GAPS-v4 G55, đối xứng `/dev-run-test`)*: row `DRIFT`/`ORPHANED` + test xanh → **`not_run`**, không bao giờ `pass`. `fail` và `skip` ghi bình thường — chỉ giá trị **khẳng định** cần giấy phép.
43
62
 
44
63
  Và ở lệnh này hậu quả đi **xa hơn** `/dev-run-test`: một `pass` sai còn **đóng một bug** (§Đóng bug đã verify). Nên khi hạ về `not_run`, lệnh **KHÔNG** clear `qc_owner`/`qc_blocked_by` và **KHÔNG** chạy bước đóng bug — đóng bug dựa trên một lần QC chạy trên spec đã đổi là đóng sai.
45
- 6. **Đóng bug đã verify** chạy **TRƯỚC** bước clear cột (xem dưới).
46
- 7. **Refresh Panel Mirror** Living Docs local.
64
+ `flaky` `qc_status = not_run`, `qc_owner = qc`. Không tạo trạng thái mới: `not_run` đúng nghĩa *"chưa có kết luận"*, và `qc_owner = qc` để nó không rơi vào khoảng không ai nhận.
65
+ 6. **Self-Review** *(mới)*nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
66
+ 7. **Đóng bug đã verify** — chạy **TRƯỚC** bước clear cột (xem dưới).
67
+ 8. **Refresh Panel Mirror** — Living Docs local.
47
68
 
48
69
  ---
49
70
 
50
71
  ## Checkpoint & Gate
51
72
 
52
- - Tiền đề: case đã APPROVED ở `/qc-review`. Script sinh ra → review lại ở `/qc-review` (script) trước PR.
73
+ - Tiền đề: case đã APPROVED ở `/qc-review-testcase`. Script sinh ra → review lại ở `/qc-review-script` trước PR.
74
+ - 🛑 **Xác nhận nhãn FAIL** — cổng chặn được **thêm vào**, trong khi framework vốn đang giảm số cổng chặn (G41). Lý do: **cả hai hướng sai đều không đảo ngược rẻ.** Gắn nhầm `script-bug` cho lỗi sản phẩm thật là **giấu bug** cho tới khi khách gặp; mở bug từ một lần chạy hên xui là **đốt thời gian dev** và làm mòn niềm tin vào QC.
75
+
76
+ > **Đây KHÔNG phải `retries` trong config test runner.** `retries` tự thử lại rồi báo *"passed on retry"* — nó **che** sự không nhất quán. Ở đây chạy **tách biệt từng lần để quan sát**, vì chính sự không nhất quán mới là thông tin cần.
53
77
 
54
78
  ---
55
79
 
@@ -57,6 +81,7 @@
57
81
 
58
82
  - **`qc_status` là trục authoritative** — khác `dev_selftest`; có evidence.
59
83
  - **Không fake-pass** — product-gap giữ nguyên FAIL, đẩy về PO/Dev.
84
+ - **Chạy lại để QUAN SÁT, không để cho qua** — ba nhãn FAIL tách *chưa đủ căn cứ* (`flaky`) ra khỏi *đã đủ căn cứ* (`script-bug` / `product-gap`). Trước đây hai nhãn gộp cả ba tình huống, nên một test hên xui hoặc bị gán bừa `script-bug` (giấu bug), hoặc thành một bug ma gửi cho dev.
60
85
  - **Stack QC tách hẳn dev** — `@trace.verifies` nối script ↔ SC.
61
86
  - **`active_platform` khoá sổ trace** — `qc_status` ghi đúng `{UC-ID}-{platform}.tsv`.
62
87
  - **Chủ sở hữu bước `🟡 Fixed → 🟢 Closed`.** `/report-bug` mở bug (`🟢 Open`), `/fix-bug` đặt `🟡 Fixed`, và **chỉ QC re-verify mới đóng được** — dev không tự đóng bug của mình.
@@ -67,7 +92,7 @@ Khi `qc_status` flip `pass`, lệnh clear `qc_owner`/`qc_blocked_by` về `—`.
67
92
 
68
93
  | `State` của bug | SC vừa `pass` → làm gì |
69
94
  |---|---|
70
- | `🟡 Fixed` | → `🟢 Closed` + dòng `Verified: /qc-run-test {today} — {UC-ID}-SC{N} pass` |
95
+ | `🟡 Fixed` | → `🟢 Closed` + dòng `Verified: /qc-run-script {today} — {UC-ID}-SC{N} pass` |
71
96
  | `🟢 Open` (chưa ai fix) | **KHÔNG đóng.** Giữ `Open` + ghi chú kiểm tra lại test |
72
97
  | `GAP-*` thay vì `BUG-*` | không đụng — spec-gap thuộc PO, không phải QC |
73
98
 
@@ -80,12 +105,13 @@ Bug report đã đổi phải **commit + push** vào spec repo — file local l
80
105
  ## 👓 Góc nhìn tối ưu
81
106
 
82
107
  - **Trạm nặng nhất của QC** — sinh + chạy + phân loại + ghi trace. Chạy thật phụ thuộc môi trường (browser, data, service lên).
83
- - **Phân loại script-bug vs product-gap phụ thuộc AI/reviewer** sai loại hoặc giấu lỗi sản phẩm hoặc báo nhầm. Đáng tiêu chí rõ.
84
- - **Selector phụ thuộc `/map-testids`** — nếu chưa map, script giòn.
85
- - **Chạy lại tốn tài nguyên** — cân nhắc scoped run như dev-run-test.
108
+ - **Phân loại vẫn phụ thuộc người đọc evidence** — nhưng giờ có **tiêu chí và thứ tự bắt buộc**: chạy lại ×2 → đọc trace/log → đề xuất nhãn → **người xác nhận**. Chỗ mềm còn lại là ranh giới `script-bug` `product-gap` khi hành vi nằm ở **biên của spec**; đường ra đã ghi **mời Dev cùng xem trace**, không đoán cho xong.
109
+ - **Selector bám hợp đồng `/map-testids`** — §4.5.6 đã được chốt **trước** `/generate-code`, nên trạm này có bảng selector sẵn. Ca còn lại: §4.5.6 rỗng (dự án cũ chưa từng chạy `/map-testids`) script quay về dò DOM và **giòn**.
110
+ - **Chạy lại tốn tài nguyên** — ×2 cho mỗi FAIL chi phí thật. Đánh đổi có chủ đích: rẻ hơn nhiều so với một bug ma gửi cho dev, hoặc một defect thật bị gán `script-bug` rồi chôn.
111
+ - **`flaky` không có cột riêng trong sổ trace** — nó nằm ở `qc_status = not_run` + `qc_owner = qc` + nghi vấn ghi trong report. Cố ý: thêm một giá trị enum mới sẽ kéo theo sửa schema, lint, mọi lệnh đọc cột đó — trong khi `not_run` đã đúng nghĩa *chưa có kết luận*. Cái giá là **không truy được lịch sử flaky bằng máy**, phải đọc report.
86
112
 
87
113
  ---
88
114
 
89
115
  ## Kết nối
90
116
 
91
- **Trước:** [`/qc-review`](18-qc-review.md) (case) · **Sau:** [`/qc-report`](20-qc-report.md) rồi [`/qc-review`](18-qc-review.md) (script).
117
+ **Trước:** [`/qc-review-testcase`](18-qc-review.md) · **Sau:** [`/qc-report`](20-qc-report.md) rồi [`/qc-review-script`](18-qc-review.md) (script).
@@ -1,4 +1,4 @@
1
- [← /qc-run-test](19-qc-run-test.md) · [Explain Home](README.md) · [Next: /validate-traces →](21-validate-traces.md)
1
+ [← ba trạm script](19-qc-run-test.md) · [Explain Home](README.md) · [Next: /validate-traces →](21-validate-traces.md)
2
2
 
3
3
  # 20 · `/qc-report` — Trạm 6: Report + evidence + product-gap
4
4
 
@@ -14,7 +14,7 @@ Kết quả chạy cần được trình bày có bằng chứng và **định t
14
14
 
15
15
  ## Vị trí & tiền đề
16
16
 
17
- - **Vị trí:** Phase QC (trạm 6, cuối), sau `/qc-run-test`.
17
+ - **Vị trí:** Phase QC (trạm 6, cuối), sau `/qc-design-script` → `/qc-run-script`.
18
18
 
19
19
  ---
20
20
 
@@ -30,8 +30,11 @@ Kết quả chạy cần được trình bày có bằng chứng và **định t
30
30
 
31
31
  1. **Role qa-runner/report** — nạp skill report.
32
32
  2. **Procedure** — tổng hợp kết quả run (pass/fail per SC), đính evidence.
33
- 3. Tách **product-gap** → định tuyến về PO/Dev (có thể thành `/report-bug`).
34
- 4. **Output** report.
33
+ 3. Tách **product-gap** → định tuyến về PO/Dev (có thể thành `/report-bug`). Scenario mang nhãn **`flaky`** **không** thành bug — nó là *chưa có kết luận*, `qc_status` để `not_run`.
34
+ 4. **Self-Review** *(mới)* — nạp `skills/qc/_shared/self-review-principles.md`, soát một lượt trước khi in report.
35
+ 5. **Output** report.
36
+ > **Self-Review ≠ Guard.** Guard là phép **đếm cơ học**, có hệ quả bắt buộc khi lệch. Self-review là lượt đọc lại **rộng hơn nhưng mềm hơn**, soát ba nhóm lỗi mà phép đếm không bắt được (bịa dữ kiện · lẫn suy đoán với sự thật · bỏ dở giữa chừng). Một bộ nguyên tắc tự soát **không bao giờ** được dùng làm lý do gỡ một Guard — chính file `self-review-principles.md` ghi rõ ranh giới đó ngay ở đầu.
37
+
35
38
 
36
39
  ---
37
40
 
@@ -58,4 +61,4 @@ Kết quả chạy cần được trình bày có bằng chứng và **định t
58
61
 
59
62
  ## Kết nối
60
63
 
61
- **Trước:** [`/qc-run-test`](19-qc-run-test.md) · **Sau:** [`/validate-traces`](21-validate-traces.md) (làm mới Living Docs); product-gap → [`/report-bug`](25-report-bug.md).
64
+ **Trước:** [ba trạm script](19-qc-run-test.md) · **Sau:** [`/validate-traces`](21-validate-traces.md) (làm mới Living Docs); product-gap → [`/report-bug`](25-report-bug.md).
@@ -35,7 +35,7 @@ Sửa bug ad-hoc dễ tái phát và mất truy vết. Command áp một quy tr
35
35
  4. **Phase 4 · Regression Test** — thêm test tái hiện bug để chống tái phát.
36
36
  5. **Phase 4.5 · Cập nhật sổ trace** — regression test phải hiện lên coverage (xem dưới).
37
37
  6. **Phase 5 · Build & Commit** — build verify; umbrella **push 2 tầng** (Tầng 1: fix branch trong service submodule nơi code sống; Tầng 2: umbrella pointer).
38
- 7. **Phase 5.5 · Đặt `🟡 Fixed`** — nếu fix một `{BUG-ID}` đã file. **Không** đặt `Closed` — bước đó thuộc `/qc-run-test`.
38
+ 7. **Phase 5.5 · Đặt `🟡 Fixed`** — nếu fix một `{BUG-ID}` đã file. **Không** đặt `Closed` — bước đó thuộc `/qc-design-script` → `/qc-run-script`.
39
39
  8. **Phase 6 · Đề xuất Lesson** — nếu lỗi tái diễn → `capture-lesson` (L1–L5).
40
40
 
41
41
  ### Phase 4.5 — vì sao `/fix-bug` phải ghi sổ trace
@@ -49,7 +49,7 @@ Sửa bug ad-hoc dễ tái phát và mất truy vết. Command áp một quy tr
49
49
  | `dev_selftest` → `not_run` · `dev_selftest_at` → `—` | code vừa đổi nên tín hiệu self-test cũ hết hiệu lực |
50
50
  | `last_updated` | hôm nay |
51
51
 
52
- **Hai nhóm cột cấm đụng:** `qc_*` (QC sở hữu — `/qc-run-test` flip khi re-verify **và** chính nó đóng bug) · `spec_ver`/`gen_ver` (**fix bug không đổi spec** — đụng vào là tạo `DRIFT` giả).
52
+ **Hai nhóm cột cấm đụng:** `qc_*` (QC sở hữu — `/qc-design-script` → `/qc-run-script` flip khi re-verify **và** chính nó đóng bug) · `spec_ver`/`gen_ver` (**fix bug không đổi spec** — đụng vào là tạo `DRIFT` giả).
53
53
 
54
54
  Vì `dev_selftest` bị reset, Next của lệnh là **`/dev-run-test`** để lấy lại tín hiệu xanh, rồi mới tạo PR.
55
55
 
@@ -98,12 +98,15 @@ Kết thúc bằng: **Status badge** (✅/❌/⚠️) · **Output Artifacts** (f
98
98
  - [05 · `/generate-design-spec`](05-generate-design-spec.md)
99
99
  - [06 · `/generate-bdd`](06-generate-bdd.md)
100
100
  - [07 · `/generate-tech-docs`](07-generate-tech-docs.md)
101
+ - [**11** · `/map-testids`](11-map-testids.md) ← **chốt hợp đồng test-id, TRƯỚC code**
101
102
  - [08 · `/review-tech-docs`](08-review-tech-docs.md)
102
103
 
104
+ > Danh sách này xếp theo **thứ tự chạy**, không theo số file. `/map-testids` giữ số `11` vì lý do lịch sử — giữ tên file để không gãy link cũ.
105
+ > §4.5.6 chốt ở đây là lý do **Phase Implementation** và **Phase QC Automation** chạy được **song song**.
106
+
103
107
  ### Phase Implementation
104
108
  - [09 · `/generate-code`](09-generate-code.md)
105
109
  - [10 · `/review-code`](10-review-code.md)
106
- - [11 · `/map-testids`](11-map-testids.md)
107
110
 
108
111
  ### Phase Dev Self-Test
109
112
  - [12 · `/dev-gen-test`](12-dev-gen-test.md)
@@ -114,8 +117,8 @@ Kết thúc bằng: **Status badge** (✅/❌/⚠️) · **Output Artifacts** (f
114
117
  - [15 · `/qc-analyze`](15-qc-analyze.md)
115
118
  - [16 · `/qc-plan`](16-qc-plan.md)
116
119
  - [17 · `/qc-design-test`](17-qc-design-test.md)
117
- - [18 · `/qc-review`](18-qc-review.md)
118
- - [19 · `/qc-run-test`](19-qc-run-test.md)
120
+ - [18 · `/qc-review-testcase` + `/qc-review-script`](18-qc-review.md)
121
+ - [19 · `/qc-design-script` · `/qc-run-script` · `/qc-run-manualtest`](19-qc-run-test.md)
119
122
  - [20 · `/qc-report`](20-qc-report.md)
120
123
 
121
124
  ### Phase Trace & Quality
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Checklist 20 bước — đợt đại phẫu QC
3
- updated: 2026-09-11
3
+ updated: 2026-09-16
4
4
  ---
5
5
 
6
6
  # Checklist — đang ở đâu
@@ -19,9 +19,9 @@ updated: 2026-09-11
19
19
 
20
20
  ```bash
21
21
  node bin/build.js # đúc .tmpl → .md → core/
22
- node bin/self-check.js # R1–R16
22
+ node bin/self-check.js # R1–R18 (R17/R18 thêm ở 0.9.6)
23
23
  node test/run.js # gồm test ngân sách dung lượng core/commands
24
- node bin/lint-trace.js # T1–T14 trên sổ trace thật
24
+ node bin/lint-trace.js # T1–T20 trên sổ trace thật (T19/T20 thêm ở 0.9.6)
25
25
  ```
26
26
 
27
27
  ---
@@ -73,20 +73,73 @@ node bin/lint-trace.js # T1–T14 trên sổ trace thật
73
73
 
74
74
  ---
75
75
 
76
- ## Việc dọn bắt buộc — kèm Đợt 2, bỏ là self-check đỏ
76
+ ## Việc dọn bắt buộc — đo lại tại HEAD 0.9.6
77
77
 
78
- | | Việc | Lượng |
79
- |:-:|---|---|
80
- | [ ] | Sửa file skill còn gọi `TC_<FEATURE>.md` thay `.Test.md` | 14 file |
81
- | [ ] | Sửa tham chiếu skill treo `qa-script-runner/report/coverage-evaluator.md` | 1 chỗ |
82
- | [ ] | Bổ nhãn `*Checkpoint: …*` cho lệnh còn thiếu | 6 file |
83
- | [ ] | Gỡ comment provenance 10+ dòng ở đầu file lệnh → chuyển vào `bin/qc-base-map.json` | 12 file |
84
- | [ ] | Thay gate cắt tay (5.4 KB) bằng `{{include:steps/gate.md}}` (11.1 KB) | 12 file |
78
+ > **Bốn trong năm dòng đã xong từ trước mà chưa ai tích.** Cột *Ghi* là số của lần lập bảng
79
+ > (2026-09-11); cột *Đo lại* là số đếm thật trên `commands/*.tmpl` + `skills/` ngày 2026-09-15,
80
+ > **đo trước khi sửa file này** xem cách đếm ở cuối mục. Để nguyên `[ ]` thì người sau đi làm
81
+ > lại bốn việc đã xong.
85
82
 
86
- ## Câu còn phải chốt với chị QC
83
+ | | Việc | Ghi | Đo lại 2026-09-15 |
84
+ |:-:|---|---|---|
85
+ | [x] | Sửa file skill còn gọi `TC_<FEATURE>.md` thay `.Test.md` | 14 file | **0 file.** Đúng 2 chỗ còn chuỗi đó, **cả hai** trong `qc-design-test` và là **phản ví dụ có chủ ý** — *"ghi ra thứ không trạm nào tìm thấy"*. Đừng `grep` rồi báo lỗi lại |
86
+ | [x] | Sửa tham chiếu skill treo `qa-script-runner/report/coverage-evaluator.md` | 1 chỗ | **Không phải lỗi — chưa bao giờ hỏng.** Mọi tham chiếu nằm gọn trong `upstream/qc-base/`, và `upstream/qc-base/skills/qa-gate/coverage-evaluator.md` có thật. Không có commit sửa nào để đi tìm |
87
+ | [ ] | Bổ nhãn `*Checkpoint: …*` cho lệnh còn thiếu | 6 file | **18 file** — chỉ 15/33 lệnh có nhãn; số cũ nhỏ hơn thực tế 3 lần *(lần lập bảng đếm trên tập lệnh QC rồi ghi như thể đếm toàn bộ 33 lệnh)*. **Không lệnh nào trong 18 đó được miễn**: cả 5 lệnh mức `none` — `review-code` `validate-traces` `debug` `review-context` `review-tech-docs` — đều ĐÃ có nhãn. 18 là nợ thật |
88
+ | [x] | Gỡ comment provenance 10+ dòng ở đầu file lệnh → `bin/qc-base-map.json` | 12 file | **0 file.** Không tmpl nào còn khối `<!-- -->` ở đầu; provenance rút còn đúng 1 dòng `ported_from:` ở 6 lệnh QC, phần còn lại đã nằm trong `bin/qc-base-map.json` (snapshot `596149f`) |
89
+ | [x] | Thay gate cắt tay (5.4 KB) bằng `{{include:steps/gate.md}}` (11.1 KB) | 12 file | **0 lệnh còn gate cắt tay.** 31/33 tmpl dùng `{{include:steps/gate.md}}`. Hai lệnh còn lại — `sync`, `update-framework` — không phải cắt tay: chúng **không có gate nào cả**, xem cảnh báo dưới |
90
+
91
+ > ⚠️ **Phát sinh khi đo — KHÔNG thuộc đợt dọn này.** `sync` và `update-framework` đều GHI file
92
+ > (`{service.path}/.agent/project-context.yaml`, `{living_docs_dir}/trace-report.json`, và
93
+ > `--init` copy đè cả `.agent/`) nhưng **không include gate và không có tên trong
94
+ > `gate.checkpoint_levels`** → rơi vào mặc định `normal`, mức lỏng nhất. Đây đúng hình dạng lỗi
95
+ > mà R18 sinh ra để bắt (G67 · G77 · G78 · G79). Xử ở việc **khai nốt registry
96
+ > `artifact_writers`**, không phải ở đây.
97
+
98
+ <details>
99
+ <summary>Cách đếm — chạy lại được, ra đúng số trên</summary>
100
+
101
+ ```bash
102
+ # 1 — gate: 31 file có include; 2 file thiếu là sync, update-framework
103
+ grep -l "include:steps/gate.md" commands/*.tmpl | wc -l
104
+
105
+ # 2 — TC_<FEATURE>.md: đúng 2 hit, cả hai trong qc-design-test (phản ví dụ)
106
+ grep -rn 'TC_<FEATURE>.md' skills/ commands/
87
107
 
88
- | | Câu hỏi | Chặn bước nào |
89
- |:-:|---|---|
90
- | [ ] | `/qc-run-manualtest` ghi kết quả test tay thế nào — nhập từng TC, hay đọc từ file checklist? | d2-b2 |
91
- | [ ] | Smoke suite đặt tên (không được nhầm `/dev-smoke-test` đã có) | d4-b2 |
92
- | [ ] | Ngưỡng dung lượng chốt bao nhiêu (đo lại sau d2-b2, ước ~1313 KB) | d2-b2 |
108
+ # 3 coverage-evaluator: file đích tồn tại ⇒ tham chiếu không treo
109
+ ls upstream/qc-base/skills/qa-gate/coverage-evaluator.md
110
+
111
+ # 4 nhãn Checkpoint: 15 / 18 thiếu trên 33 lệnh
112
+ for f in commands/*.tmpl; do grep -qE '^s**Checkpoint:' "$f" || basename "$f" .tmpl; done | wc -l
113
+
114
+ # 5 — provenance: 0 dòng <!-- ở đầu tmpl
115
+ head -30 commands/*.tmpl | grep -c '^<!--'
116
+ ```
117
+
118
+ **Vì sao mục này phải mang theo cách đếm:** không máy nào canh file kế hoạch. `self-check` canh
119
+ schema, `lint-trace` canh sổ trace, `test/run.js` canh build — cả ba xanh trong lúc bảng này sai
120
+ bốn dòng. Ghi kết quả đo mà không ghi cách đo thì người sau vẫn phải đo lại từ đầu, tức ô tích
121
+ không tiết kiệm được gì.
122
+
123
+ </details>
124
+
125
+ ## Câu đã chốt với chị QC *(2026-09-16)*
126
+
127
+ | | Câu hỏi | Trả lời | Chặn bước nào |
128
+ |:-:|---|---|---|
129
+ | [x] | `/qc-run-manualtest` ghi kết quả test tay thế nào — nhập từng TC, hay đọc từ file checklist? | **Nhập từng TC.** Nguyên văn: *"ghi kết quả test tay em nhé. Chị sợ đọc checklist mà lệch thông tin lại ghi kết quả sai."* | d2-b2 — **hết chặn** |
130
+ | [x] | Smoke suite đặt tên gì (không được nhầm `/dev-smoke-test` đã có) | **`/qc-smoke-test`** — đúng quy ước hai làn `qc-`/`dev-` | d4-b2 — **hết chặn** |
131
+ | [x] | Ngưỡng dung lượng chốt bao nhiêu | **Không cần hỏi — đo được.** `1309 / 1450 KB` sau d2-b1 (còn 141 KB). Đo lại sau khi viết 3 lệnh của d2-b2 | d2-b2 |
132
+
133
+ > **Vì sao câu 1 quan trọng hơn vẻ ngoài của nó.** Phương án *"đọc file checklist"* nghe tiện hơn
134
+ > (điền offline, nhiều người điền dần), và đó là phương án được khuyến nghị lúc đầu. Chị QC chỉ ra
135
+ > một rủi ro nặng hơn sự tiện: một file điền tay là **nguồn thứ hai có thể trôi** — TC bị đánh số
136
+ > lại sau một lần `/qc-design-test`, TC mới thêm, dòng cũ còn sót — và khi nó lệch thì lệnh ghi
137
+ > `qc_status` cho **đúng SC sai**. Kiểu hỏng đó là **Nói dối** (sổ trace báo `pass` cho scenario
138
+ > chưa ai chạy); cái giá của phương án hỏi-từng-TC chỉ là **Ồn**. Đổi một rủi ro nói dối lấy một
139
+ > rủi ro phiền là đúng chiều, và cùng họ với `positive_assertion_guards` — luật đã có sẵn để
140
+ > **không bao giờ** ghi `pass` khi dữ liệu nền không chắc.
141
+ >
142
+ > **Điều chỉnh giữ nguyên tính an toàn đó:** lệnh **ghi ngay vào sổ trace sau mỗi câu trả lời**,
143
+ > không gom cuối phiên; chạy lại thì chỉ hỏi những SC còn `not_run` — tức **tự resume**. Như vậy
144
+ > sổ trace là nguồn duy nhất (không artifact trung gian nào để trôi) mà vẫn làm được nhiều buổi,
145
+ > nhiều người. Mỗi lần ghi kèm người chạy + ngày, khớp luật *"`pass` phải có bằng chứng"*.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@educa-corp/sdd-framework",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "description": "Spec Driven Development workflow framework for Claude Code",
5
5
  "bin": {
6
6
  "sdd-framework": "./bin/index.js"