@educa-corp/sdd-framework 0.7.5 → 0.8.1

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 (62) hide show
  1. package/bin/qc-base-map.json +595 -0
  2. package/bin/self-check.js +146 -0
  3. package/core/FRAMEWORK_VERSION +1 -1
  4. package/core/commands/propose-scenario.md +1 -1
  5. package/core/commands/qc-analyze.md +260 -22
  6. package/core/commands/qc-design-test.md +1 -1
  7. package/core/commands/qc-plan.md +7 -4
  8. package/core/commands/qc-run-test.md +1 -1
  9. package/core/commands/refine-prd.md +47 -20
  10. package/core/commands/report-bug.md +1 -1
  11. package/core/commands/review-context.md +27 -1
  12. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +117 -0
  13. package/core/skills/qc/qa-analyst/acceptance-criteria.md +4 -2
  14. package/core/skills/qc/qa-analyst/business-rules.md +38 -4
  15. package/core/skills/qc/qa-analyst/data-flow.md +5 -3
  16. package/core/skills/qc/qa-analyst/exhaustive-gap-scanner.md +174 -0
  17. package/core/skills/qc/qa-analyst/spec-breakdown.md +9 -7
  18. package/core/skills/qc/qa-analyst/spec-issue-reporter.md +100 -0
  19. package/core/skills/qc/qa-designer/e2e/journey.md +2 -2
  20. package/core/skills/qc/qa-designer/exploratory/charter.md +1 -1
  21. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
  22. package/core/skills/qc/qa-designer/functional/api.md +2 -2
  23. package/core/skills/qc/qa-designer/functional/gui-feature.md +2 -2
  24. package/core/skills/qc/qa-designer/functional/gui-screen.md +2 -2
  25. package/core/skills/qc/qa-designer/integration/api.md +2 -2
  26. package/core/skills/qc/qa-designer/integration/db.md +2 -2
  27. package/core/skills/qc/qa-designer/integration/gui.md +2 -2
  28. package/core/skills/qc/qa-designer/integration/kafka.md +2 -2
  29. package/core/skills/qc/qa-designer/non-functional.md +2 -2
  30. package/core/skills/qc/qa-planner/risk-model.md +106 -0
  31. package/core/skills/qc/qa-planner/test-plan.md +13 -10
  32. package/core/skills/qc/qa-reviewer/script/e2e.md +1 -1
  33. package/core/skills/qc/qa-reviewer/script/exploratory.md +1 -1
  34. package/core/skills/qc/qa-reviewer/script/functional.md +1 -1
  35. package/core/skills/qc/qa-reviewer/script/integration.md +1 -1
  36. package/core/skills/qc/qa-reviewer/script/non-functional.md +1 -1
  37. package/core/skills/qc/qa-reviewer/test-case/e2e.md +1 -1
  38. package/core/skills/qc/qa-reviewer/test-case/exploratory.md +1 -1
  39. package/core/skills/qc/qa-reviewer/test-case/functional.md +1 -1
  40. package/core/skills/qc/qa-reviewer/test-case/integration.md +2 -2
  41. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +1 -1
  42. package/core/skills/qc/qa-runner/e2e.md +1 -1
  43. package/core/skills/qc/qa-runner/exploratory/session.md +1 -1
  44. package/core/skills/qc/qa-runner/functional/api.md +1 -1
  45. package/core/skills/qc/qa-runner/functional/gui-feature.md +1 -1
  46. package/core/skills/qc/qa-runner/functional/gui-screen.md +1 -1
  47. package/core/skills/qc/qa-runner/integration.md +1 -1
  48. package/core/skills/qc/qa-runner/non-functional.md +1 -1
  49. package/core/skills/qc/qa-runner/report/report.md +1 -1
  50. package/core/steps/gap-verify.md +231 -0
  51. package/core/steps/review-fanout.md +27 -1
  52. package/core/templates/project-context.yaml +2 -2
  53. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +2 -2
  54. package/docs/04-reference/commands.md +1 -1
  55. package/docs/explain/03-refine-prd.md +88 -86
  56. package/docs/explain/15-qc-analyze.md +10 -7
  57. package/docs/explain/16-qc-plan.md +2 -2
  58. package/docs/plans/qc-implementation-log.md +1446 -0
  59. package/docs/plans/qc-merge-plan.md +502 -0
  60. package/docs/plans/qc-sync-command.md +358 -0
  61. package/package.json +1 -1
  62. package/core/skills/qc/qa-analyst/DOC_GAPS.template.md +0 -63
@@ -0,0 +1,358 @@
1
+ # Plan — lệnh sync skill QC từ upstream vào framework
2
+
3
+ > Tài liệu này là **phần 2** của [`qc-merge-plan.md`](qc-merge-plan.md).
4
+ > Plan kia trả lời *"gộp cái gì, và ba quyết định nào đang chặn"*.
5
+ > Plan này trả lời *"về sau QC sửa skill thì làm sao đưa vào framework mà không vỡ"*.
6
+
7
+ | | |
8
+ |---|---|
9
+ | Snapshot | `upstream/qc-base/` — 82 file, 10.008 dòng, **không ship** (ngoài `package.json` `files`) |
10
+ | Upstream | `D:\projects\ui-automation-testing` @ `596149f` (git repo thật → pin được) |
11
+ | Đích | `skills/qc/qa-*` (35 file) + 6 lệnh `commands/qc-*.tmpl` |
12
+ | Trạng thái | plan — chưa code |
13
+
14
+ ---
15
+
16
+ ## 1 · Vì sao đây không phải copy file
17
+
18
+ Ba lý do, xếp theo độ khó tăng dần.
19
+
20
+ ### (a) Ánh xạ không phải 1:1
21
+
22
+ ```
23
+ upstream framework
24
+ qa-tc-analyst (1 agent) ─┬──► /qc-analyze (trạm 1) + skills/qc/qa-analyst/
25
+ 23 skill └──► /qc-plan (trạm 2) + skills/qc/qa-planner/
26
+ ```
27
+
28
+ Một đơn vị upstream nở ra hai đơn vị framework. `test-plan.md` của `qa-tc-analyst`
29
+ đã nằm ở `qa-planner/`. Copy theo thư mục là sai ngay từ bước đầu.
30
+
31
+ ### (b) File được **adapt**, không phải copy
32
+
33
+ Cả 4 file trùng tên đều khác nội dung, và khác có chủ ý:
34
+
35
+ | | upstream | framework | framework thêm gì |
36
+ |---|---|---|---|
37
+ | `business-rules` | 90 dòng | 59 | `{paths.qc_dir}` · rào *"chỉ trả 2 file"* |
38
+ | `acceptance-criteria` | 57 | 60 | như trên |
39
+ | `data-flow` | 61 | 64 | như trên |
40
+ | `spec-breakdown` | 58 | 61 | như trên |
41
+
42
+ Copy đè = **xoá sạch phần adapt**. Và `business-rules` bản upstream **dài hơn 31 dòng** —
43
+ nên chiều ngược lại cũng đúng: bản framework có thể đã cắt mất nội dung thật, không chỉ đổi path.
44
+
45
+ ### (c) Đây là bài toán **merge ba chiều**, và hiện đang thiếu một chiều
46
+
47
+ Khi QC sửa `business-rules.md`, có ba bản:
48
+
49
+ ```
50
+ BASE THEIRS OURS
51
+ bản upstream mà bản upstream mới bản framework
52
+ framework đã port từ đã adapt
53
+ │ │ │
54
+ └────────── diff A ───────┘ │
55
+ "QC đã đổi gì" │
56
+ └──────────────────── diff B ──────────────────────┘
57
+ "ta đã adapt gì"
58
+
59
+ Không có BASE ⇒ không phân biệt được A với B
60
+ ⇒ mọi merge đều là đoán
61
+ ```
62
+
63
+ **`upstream/qc-base/` chính là BASE** — nhưng chỉ khi nó được **pin**: ghi lại nó ứng với
64
+ commit upstream nào. Một thư mục snapshot không có pin thì chỉ là "một bản copy cũ nào đó",
65
+ không dùng làm base merge được.
66
+
67
+ > **Đây là lý do kiến trúc của toàn bộ plan này:** lệnh cần dựng không phải lệnh copy,
68
+ > mà là một **vendor-branch merge tool có pin**.
69
+
70
+ ---
71
+
72
+ ## 2 · Ba tạo tác phải có trước khi viết lệnh
73
+
74
+ ### 2.1 · Pin — `upstream/qc-base/.pin.json`
75
+
76
+ ```json
77
+ {
78
+ "upstream": {
79
+ "repo": "ui-automation-testing",
80
+ "url": "<git remote>",
81
+ "ref": "main",
82
+ "commit": "596149f",
83
+ "captured_at": "2026-08-24"
84
+ },
85
+ "files": {
86
+ "skills/qa-tc-analyst/business-rules.md": "sha1…",
87
+ "skills/qa-tc-analyst/gap-verifier.md": "sha1…"
88
+ }
89
+ }
90
+ ```
91
+
92
+ Hash từng file, không chỉ commit. Lý do: snapshot có thể bị sửa tay (ai đó "sửa nhanh một
93
+ dòng trong `upstream/`"), và lúc đó base không còn là base. Hash bắt được, commit thì không.
94
+
95
+ ### 2.2 · Bản đồ ánh xạ — `bin/qc-base-map.json`
96
+
97
+ Đây là tạo tác quan trọng nhất. Mỗi entry trả lời: file upstream này đi đâu, adapt thế nào,
98
+ ai chịu trách nhiệm.
99
+
100
+ ```json
101
+ {
102
+ "map": [
103
+ {
104
+ "upstream": "skills/qa-tc-analyst/business-rules.md",
105
+ "targets": ["skills/qc/qa-analyst/business-rules.md"],
106
+ "adapt": ["path-placeholders", "two-file-guard"],
107
+ "state": "ported",
108
+ "base_sha": "sha1 của bản upstream đã port từ"
109
+ },
110
+ {
111
+ "upstream": "skills/qa-tc-analyst/gap-verifier.md",
112
+ "targets": ["steps/gap-verify.md"],
113
+ "adapt": ["path-placeholders", "generalize-doc-gap-to-findings"],
114
+ "state": "planned",
115
+ "note": "P0 — dùng chung cho refine-prd / review-context / qc-analyze"
116
+ },
117
+ {
118
+ "upstream": "skills/qa-tc-designer/manual-excel-testcase.md",
119
+ "targets": [],
120
+ "state": "skipped",
121
+ "why": "README upstream khai đã bỏ nhánh manual-Excel; file còn sót"
122
+ },
123
+ {
124
+ "upstream": "skills/qa-gate/styled-report-template.py",
125
+ "targets": [],
126
+ "state": "undecided",
127
+ "why": "script thật, không phải prompt — framework QC hiện 100% markdown-first"
128
+ }
129
+ ]
130
+ }
131
+ ```
132
+
133
+ **Bốn `state`, và cái thứ tư là cái quan trọng:**
134
+
135
+ | state | Nghĩa |
136
+ |---|---|
137
+ | `ported` | đã đưa vào, có `base_sha` để merge lần sau |
138
+ | `planned` | đã quyết sẽ đưa, chưa làm |
139
+ | `skipped` | **cố ý** không đưa, có lý do ghi lại |
140
+ | `undecided` | chưa ai quyết ← **đây là hàng đợi việc** |
141
+
142
+ File upstream **không có entry nào** = bị bỏ quên trong im lặng. Đó là failure mode duy nhất
143
+ mà bản đồ này tồn tại để chặn — và §5 để máy canh nó.
144
+
145
+ ### 2.3 · Luật adapt dạng **dữ liệu**, không phải người nhớ
146
+
147
+ ```json
148
+ {
149
+ "adapt_rules": {
150
+ "path-placeholders": [
151
+ { "from": "inputs/free-trial-spec/specs/", "to": "{paths.specs_dir}/" },
152
+ { "from": "docs/<feature>/", "to": "{paths.qc_dir}/{UC-ID}/{active_platform}/" },
153
+ { "from": "inputs/", "to": "{paths.specs_dir}/", "note": "khái niệm nguồn-evidence" }
154
+ ],
155
+ "two-file-guard": { "kind": "append-block", "block": "…rào 'chỉ trả 2 file'…" },
156
+ "orchestrator-to-agent-mode": {
157
+ "kind": "manual",
158
+ "why": "upstream nhận routing plan từ qa-orchestrator; framework dùng gate Bước 0 _agent_mode. Không map máy được."
159
+ }
160
+ }
161
+ }
162
+ ```
163
+
164
+ Ba loại luật: **thay chuỗi** (máy làm) · **chèn block** (máy làm) · **`manual`** (buộc người
165
+ xem, lệnh dừng lại hỏi). Loại thứ ba là chỗ tránh được cái bẫy "tool tự tin adapt sai".
166
+
167
+ > **37 file upstream hardcode `inputs/…`** — đây là khối lượng chính của `path-placeholders`.
168
+
169
+ ---
170
+
171
+ ## 3 · Chia việc: script làm phần cơ học, lệnh làm phần phán đoán
172
+
173
+ Framework đã có tiền lệ cho cách chia này: `bin/lint-trace.js` (script, chạy được trong CI)
174
+ vs `/validate-traces` (LLM, không chạy được trong CI thường). Áp đúng khuôn đó.
175
+
176
+ ```
177
+ bin/qc-sync.js /sync-qc-base (lệnh markdown)
178
+ ───────────────────────────── ────────────────────────────────
179
+ hash + so pin "thay đổi này thuộc trạm 1 hay trạm 2?"
180
+ diff ba chiều "skill mới này có thuộc phạm vi framework?"
181
+ áp adapt_rules loại string/block áp adapt_rules loại `manual`
182
+ bookkeeping pin + base_sha đọc diff, quyết giữ/bỏ phần adapt của ta
183
+ phát hiện entry thiếu / mồ côi viết lại đoạn cần diễn đạt theo giọng framework
184
+ in báo cáo máy-đọc-được CHECKPOINT trước khi ghi
185
+ ───────────────────────────── ────────────────────────────────
186
+ deterministic · CI-able · --dry-run cần người · cần ngữ cảnh · có gate
187
+ ```
188
+
189
+ Nguyên tắc: **script không bao giờ tự ghi vào `skills/qc/qa-*` hay `commands/`
190
+ khi có `manual` rule hoặc conflict.** Nó dựng patch + báo; lệnh mới là chỗ quyết.
191
+
192
+ ---
193
+
194
+ ## 4 · Sáu lệnh con
195
+
196
+ Framework không dùng sub-command thật — nó dùng cờ trên một lệnh (`--resume`, `--fix`,
197
+ `--full`). Giữ đúng quy ước đó:
198
+
199
+ ```
200
+ /sync-qc-base [--status] [--pull] [--diff] [--port] [--adopt] [--verify]
201
+ ```
202
+
203
+ | Cờ | Trả lời câu | Đọc | Ghi | Chặn |
204
+ |---|---|---|---|---|
205
+ | `--status` *(mặc định)* | "upstream đi trước ta bao nhiêu?" | pin, snapshot, map, upstream | — | không |
206
+ | `--pull` | "lấy bản upstream mới về snapshot" | upstream git | `upstream/qc-base/` + `.pin.json` | không¹ |
207
+ | `--diff` | "QC đổi gì, ta adapt gì, có đè nhau không?" | 3 chiều | — | không |
208
+ | `--port` | "đưa thay đổi upstream vào file framework" | 3 chiều + adapt_rules | `skills/qc/qa-*`, `commands/*.tmpl` | **CỨNG** |
209
+ | `--adopt` | "nhận một skill upstream CHƯA có trong map" | snapshot + map | map entry + file đích mới | **CỨNG** |
210
+ | `--verify` | "pin/map/frontmatter còn khớp nhau không?" | tất cả | — | không |
211
+
212
+ ¹ `--pull` không chặn vì nó chỉ đụng `upstream/` — nhưng nó **phải** cảnh báo nếu snapshot
213
+ đang bị sửa tay (hash lệch pin), vì lúc đó base sắp bị ghi đè mất.
214
+
215
+ ### Chi tiết từng cờ
216
+
217
+ **`--status`** — bức ảnh một màn hình:
218
+ ```
219
+ Snapshot : 596149f (2026-08-24) Upstream: a3f21c8 (2026-09-02) → đi trước 7 commit
220
+ Đổi : 12 file
221
+ ├─ 4 ported → cần --port
222
+ ├─ 2 planned → chưa làm, không ảnh hưởng
223
+ ├─ 1 skipped → bỏ qua đúng chủ ý
224
+ └─ 5 KHÔNG CÓ TRONG MAP ← chạy --adopt hoặc khai skipped
225
+ Framework: 1 file đã bị sửa tay sau lần port (base_sha lệch) → --diff xem trước
226
+ ```
227
+
228
+ **`--pull`** — làm mới snapshot. Không đụng framework. Ba việc: fetch/checkout ref,
229
+ ghi lại `.pin.json`, và **giữ bản pin cũ** thành `.pin.prev.json` — vì merge ba chiều lần
230
+ `--port` sau cần BASE là bản *trước khi* pull.
231
+
232
+ > Đây là chỗ dễ sai nhất của cả thiết kế: `--pull` mà không lưu base cũ thì `--port`
233
+ > mất chiều thứ ba, và ta quay về đúng vấn đề §1(c).
234
+
235
+ **`--diff`** — bề mặt review. Mỗi file đổi, in ba khối: QC đổi gì · ta adapt gì · hai cái
236
+ có chạm nhau không. Chạm nhau = conflict thật, cần người.
237
+
238
+ **`--port`** — merge + adapt + ghi. Chặn CỨNG (`--yes` không bỏ được) vì nó ghi đè file
239
+ framework đã có. Với mỗi file: 3-way merge → áp `adapt_rules` string/block → gặp rule
240
+ `manual` hoặc conflict thì **để lại** vào file findings, không tự quyết → cập nhật
241
+ `base_sha` cho các file đã port sạch.
242
+
243
+ **`--adopt`** — đường vào cho skill upstream mới (và cho **P1** của plan kia: 18 skill của
244
+ `qa-tc-analyst` chưa có đều đi qua đây). Việc nó làm: hỏi đích (`skills/qc/…`? `steps/`?
245
+ một `commands/*.tmpl`?), hỏi `adapt` nào áp, dựng bản adapt đầu tiên, tạo entry map với
246
+ `state: ported` + `base_sha`.
247
+
248
+ **`--verify`** — invariant check, chạy được trong CI:
249
+
250
+ | Kiểm | Bắt lỗi gì |
251
+ |---|---|
252
+ | mọi file snapshot có entry trong map | **skill upstream bị bỏ quên im lặng** |
253
+ | entry map trỏ tới file tồn tại (cả 2 phía) | map lỗi thời sau khi upstream đổi tên |
254
+ | `base_sha` của entry `ported` khớp một file snapshot | base đã trôi, merge lần sau sẽ sai |
255
+ | frontmatter `upstream_path` + `upstream_sha` của file đích khớp map | file đích bị sửa tay ngoài luồng |
256
+ | `skills/qc/qa-*` không còn chuỗi `inputs/` sót | adapt làm nửa vời |
257
+ | lệnh `qc-*` không trỏ vào skill đã mất | **đúng lỗi vừa xảy ra hôm nay** |
258
+
259
+ ---
260
+
261
+ ## 5 · Rule máy canh — `R16`
262
+
263
+ `--verify` là lệnh người gọi. Nhưng framework này có một nguyên tắc lặp lại năm lần trong
264
+ loạt GAP: *luật đúng, viết rõ, và không ai canh*. Nên phần **cốt lõi** của `--verify` phải
265
+ thành rule trong `bin/self-check.js`, fail build:
266
+
267
+ ```
268
+ R16 — snapshot upstream và framework không được trôi khỏi nhau trong im lặng
269
+
270
+ a) mọi file trong upstream/qc-base/ phải có entry trong bin/qc-base-map.json
271
+ → thiếu entry = bị bỏ quên. state `skipped` là câu trả lời hợp lệ; VẮNG MẶT thì không.
272
+ b) mọi entry `state: ported` phải có base_sha, và base_sha phải khớp file snapshot
273
+ c) mọi target của entry `ported` phải tồn tại
274
+ d) mọi lệnh qc-* trỏ vào {paths.qc_skills_dir}/X phải có X tồn tại trong skills/qc/
275
+ ```
276
+
277
+ **(d) là rule đáng lẽ đã chặn sự cố hôm nay** — 35 file skill bị xoá, `self-check` xanh,
278
+ `build` xanh, `.agent` vẫn chạy được nên dogfood không phát hiện, và installer thì sẽ
279
+ *chủ động xoá* chúng ở project người dùng. Ba tầng che nhau, không tầng nào bắt.
280
+
281
+ `R16(d)` **đáng làm ngay, độc lập với toàn bộ plan này.**
282
+
283
+ ---
284
+
285
+ ## 6 · Luồng điển hình
286
+
287
+ ```
288
+ QC push skill mới
289
+
290
+
291
+ /sync-qc-base --status "đi trước 7 commit, 12 file đổi, 5 chưa có trong map"
292
+
293
+
294
+ /sync-qc-base --pull snapshot: 596149f → a3f21c8 (giữ .pin.prev.json)
295
+
296
+
297
+ /sync-qc-base --diff đọc: QC đổi gì · ta adapt gì · chỗ nào chạm nhau
298
+
299
+ ├──► 5 file chưa có trong map
300
+ │ │
301
+ │ ▼
302
+ │ /sync-qc-base --adopt quyết đích + adapt cho từng cái
303
+
304
+
305
+ /sync-qc-base --port CHECKPOINT CỨNG → merge + adapt → conflict ra findings
306
+
307
+
308
+ node bin/self-check.js R16 xanh
309
+ node bin/build.js 41/41
310
+
311
+
312
+ /sync-qc-base --verify invariant sạch
313
+ ```
314
+
315
+ ---
316
+
317
+ ## 7 · Phase triển khai
318
+
319
+ | Phase | Việc | Phụ thuộc |
320
+ |---|---|---|
321
+ | **S0** | **`R16(d)`** — rule chặn "lệnh qc-* trỏ vào skill không tồn tại" | không · **làm ngay** |
322
+ | **S1** | Dựng `.pin.json` cho snapshot hiện tại (`596149f`) + hash 82 file | không |
323
+ | **S2** | Dựng `bin/qc-base-map.json` — 82 entry. Phần lớn là `undecided`, 5 là `ported` (4 analyst + test-plan), phần còn lại phân loại dần | S1 |
324
+ | **S3** | `bin/qc-sync.js` — `--status` + `--verify` trước (read-only, rẻ, có giá trị ngay) | S1, S2 |
325
+ | **S4** | `R16(a)(b)(c)` vào `self-check.js` | S2 |
326
+ | **S5** | `--pull` + `--diff` (vẫn read-only với framework) | S3 |
327
+ | **S6** | `--adopt` — rồi dùng chính nó chạy **P1** của plan kia (18 skill analyst) | S5 |
328
+ | **S7** | `--port` — merge ba chiều. Phần khó nhất, làm cuối | S6 |
329
+
330
+ > **Thứ tự này có chủ ý:** mọi thứ read-only xong trước, ghi-file để sau cùng.
331
+ > `--status` + `--verify` đã trả giá trị (biết mình đang lệch bao nhiêu) trước khi
332
+ > viết một dòng logic merge nào.
333
+
334
+ Và `--adopt` (S6) đứng **trước** `--port` (S7) vì `--adopt` là việc phải làm ngay
335
+ (18 skill đang chờ), còn `--port` chỉ cần khi QC push lần sửa đầu tiên.
336
+
337
+ ---
338
+
339
+ ## 8 · Câu chưa quyết
340
+
341
+ | # | Câu | Ghi chú |
342
+ |---|---|---|
343
+ | 1 | `upstream/qc-base/` **track git hay không?** | Nên track — cần nó làm BASE và cần diff được qua lịch sử. Đổi lại: +10k dòng vào repo. |
344
+ | 2 | Snapshot lấy bằng **copy tay** hay **git submodule**? | Submodule đúng bản chất hơn nhưng `--pull` phức tạp hơn, và submodule *là* moving target trong khi BASE cần đóng băng. Copy + pin đơn giản hơn, tôi nghiêng về nó. |
345
+ | 3 | `bin/qc-base-map.json` hay gộp vào `bin/trace-schema.json`? | Tách riêng: đây không phải contract về trace. Nhưng `self-check.js` phải đọc cả hai. |
346
+ | 4 | 2 file `.py` của `qa-gate` xử sao? | `state: undecided`. Framework QC hiện 100% markdown-first — nhận script là đổi một nguyên tắc. |
347
+ | 5 | `ported_from: ai-automation-qc-base` đang **sai tên repo** (thật là `ui-automation-testing`) | Sửa luôn khi thêm `upstream_path` + `upstream_sha` vào frontmatter. |
348
+ | 6 | `shared/` của upstream — framework có nhận khái niệm này? | `qa-tc-designer/shared/` 7 file dùng chung. Framework hiện "mỗi skill tự đủ". Nhận `shared/` là đổi kiến trúc skill. |
349
+ | 7 | `read-doc-gap-inputs.md` tồn tại **2 bản khác nội dung** (designer + reviewer) | Trùng tên khác ruột — chọn sai là sai im lặng. Phải chốt 1 bản, hoặc map thành 2 entry riêng. |
350
+
351
+ ---
352
+
353
+ ## Liên quan
354
+
355
+ - [`qc-implementation-log.md`](qc-implementation-log.md) — nhật ký triển khai, viết cho người không cần biết code
356
+
357
+ - [`qc-merge-plan.md`](qc-merge-plan.md) — gộp cái gì, ba quyết định đang chặn (§5), plan P0–P4
358
+ - `--adopt` (S6 ở đây) **chính là** P1 của plan kia — không phải hai việc, là một việc có công cụ
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@educa-corp/sdd-framework",
3
- "version": "0.7.5",
3
+ "version": "0.8.1",
4
4
  "description": "Spec Driven Development workflow framework for Claude Code",
5
5
  "bin": {
6
6
  "sdd-framework": "./bin/index.js"
@@ -1,63 +0,0 @@
1
- ---
2
- version: 1.1
3
- updated: 2026-06-11
4
- ported_from: ai-automation-qc-base
5
- ---
6
-
7
- # Gap Analysis – <FEATURE>
8
-
9
- > File ghi lại các **khoảng trống của tài liệu** mà `qa-analyst` phát hiện sau khi
10
- > phân tích. Là đầu vào để hỏi dev/BA và cho `qa-planner`. Mỗi gap có ID `GAP-xx`
11
- > để business rule (BR-xx), acceptance criteria (AC-xx) và test case trace ngược về.
12
-
13
- | Trường | Giá trị |
14
- |---|---|
15
- | Feature | `<FEATURE>` |
16
- | Project / Service | `<project or service name / domain>` |
17
- | Tài liệu nguồn | `<đường dẫn / link PRD / user story>` |
18
- | Người phân tích | qa-analyst |
19
- | Ngày phân tích | `<YYYY-MM-DD>` |
20
- | Tổng số gap | `<N>` (Blocker: x · High: y · Medium: z · Low: w) |
21
- | Trạng thái chung | 🔴 Blocked / 🟡 Cần làm rõ / 🟢 Đủ rõ để thiết kế TC |
22
-
23
- ---
24
-
25
- ## Bảng Gap
26
-
27
- | ID | Loại | Mô tả gap | Vị trí (mục/nguồn) | Ảnh hưởng (chức năng / BR / AC) | Mức độ | Người trả lời | Trạng thái | Câu trả lời |
28
- |---|---|---|---|---|---|---|---|---|
29
- | GAP-01 | MISSING | … | spec §x | chức năng A / BR-02 | 🔴 Blocker | Dev/BA | Open | — |
30
- | GAP-02 | AMBIGUOUS | … | mockup màn hình Y | AC-03 | 🟠 High | BA | Open | — |
31
- | GAP-03 | CONTRADICTORY | … | §2 vs §5 | BR-04 | 🟠 High | BA | Open | — |
32
- | GAP-04 | ASSUMPTION | … (giả định AI tự đưa, cần xác nhận) | — | chức năng B | 🟡 Medium | Dev | Open | — |
33
-
34
- ### Loại gap
35
- - **MISSING** – thông tin/chức năng/field/rule chưa được mô tả.
36
- - **AMBIGUOUS** – mô tả mơ hồ, có ≥ 2 cách hiểu.
37
- - **CONTRADICTORY** – các phần tài liệu mâu thuẫn nhau.
38
- - **ASSUMPTION** – giả định do qa-analyst tự suy ra, cần dev/BA xác nhận.
39
- - **OPEN QUESTION** – câu hỏi mở cần trả lời trước khi thiết kế/triển khai.
40
-
41
- ### Mức độ
42
- 🔴 Blocker (chặn thiết kế TC) · 🟠 High · 🟡 Medium · 🟢 Low
43
-
44
- ---
45
-
46
- ## Quy ước cập nhật
47
- - `qa-analyst` tạo & điền gap khi phân tích; **không tự bịa câu trả lời** cho gap Blocker.
48
- - Khi có phản hồi dev/BA: điền cột *Câu trả lời*, đổi *Trạng thái* → `Answered`.
49
- - Còn gap 🔴 Blocker `Open` ⇒ **chưa** chuyển sang `qa-designer`; đẩy sang `qa-planner`
50
- (skill `questions-for-dev`) để chốt câu hỏi.
51
-
52
- ---
53
-
54
- ## ⚠️ Checklist bắt buộc trước khi lưu file
55
-
56
- Trước khi lưu `DOC_GAPS.md`, kiểm tra **từng hàng** trong bảng gap:
57
-
58
- - [ ] **9 cột đủ** – đúng thứ tự: `ID | Loại | Mô tả gap | Vị trí (mục/nguồn) | Ảnh hưởng (chức năng / BR / AC) | Mức độ | Người trả lời | Trạng thái | Câu trả lời`
59
- - [ ] **Cột Vị trí không rỗng** – phải có tham chiếu cụ thể đến mục trong tài liệu nguồn (vd `§3 UC4 BR25`, `Appendix B loại 7`, `§4.b Screen 3`). Đây là cột hay bị bỏ thiếu nhất → gây lệch toàn bộ cột sau.
60
- - [ ] **Cột Ảnh hưởng = BR/AC references** – KHÔNG phải mức độ severity. Ví dụ đúng: `BR25, BR26 / AC-F01-33`. Nếu thấy "Blocker" / "High" ở đây → đang bị lệch cột.
61
- - [ ] **Cột Mức độ có emoji** – bắt buộc dùng: `🔴 Blocker` / `🟠 High` / `🟡 Medium` / `🟢 Low`. Không được ghi text thuần.
62
- - [ ] **Cột Người trả lời = vai trò** (PO / BA / Dev / Design / Content / DPO / QC Lead). Nếu thấy "Open" ở đây → đang bị lệch cột.
63
- - [ ] **Cột Trạng thái = Open / Answered**. Nếu thấy "—" ở đây → đang bị lệch cột.