@educa-corp/sdd-framework 0.8.0 → 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 +8 -6
  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
@@ -1,4 +1,4 @@
1
- # /refine-prd — Phân tích PRD qua 3 lăng kính review
1
+ # /refine-prd — Phân tích PRD qua 4 lăng kính review
2
2
 
3
3
  > **Ranh giới — lệnh này chỉ áp được fix cho vấn đề mà CHÍNH NÓ tìm ra.** Resume Mode Phase 2 tự
4
4
  > cấm đụng bất kỳ section nào không được một finding chấp nhận trỏ tới, và findings sinh từ việc soi
@@ -259,10 +259,11 @@ vòng không sinh thêm gì mới, *trước khi* ghi file findings.
259
259
 
260
260
  Lệnh gọi cung cấp hai thứ bắt buộc + hai tuỳ chọn:
261
261
  - **DIMENSIONS** — danh sách các chiều review để fan out
262
- (`/refine-prd` → 3 lăng kính; `/review-context` → các P-check hoặc B-check).
262
+ (`/refine-prd` → 4 lăng kính; `/review-context` → các P-check hoặc B-check; `/qc-analyze` → 3 lăng kính quét gap).
263
263
  - **FINDINGS SCHEMA** — dạng YAML mà mỗi finding phải theo (định nghĩa trong lệnh).
264
264
  - **GRANULARITY** *(tuỳ chọn, mặc định `auto`)* — `auto`: chọn độ mịn fan-out theo bảng ngưỡng kích thước ở Phase 1 (hành vi cũ). `per-uc`: **LUÔN** fan-out theo từng UC, **bỏ qua ngưỡng** — dùng cho review cần độ đầy đủ cao (`/refine-prd` truyền cái này để lần đầu đã quét sâu). Lệnh không truyền → `auto` → hành vi không đổi.
265
265
  - **CHANGED_SCOPE** *(tuỳ chọn)* — danh sách UC/section đã thay đổi (review **delta**). Nếu được truyền, Phase 1 chỉ fan-out trên các phạm vi này + PRD-global; Phase 2 critic vẫn quét **toàn doc** làm lưới an toàn. Không truyền → quét toàn bộ như thường.
266
+ - **VERIFY** *(tuỳ chọn, mặc định `off`)* — `on` chèn **Phase 2.5** (`steps/gap-verify.md`) giữa critic và dedup: mỗi finding phải mở lại tài liệu nguồn tự chứng minh trước khi được giữ. Không truyền → hành vi không đổi.
266
267
 
267
268
  > **Bỏ qua ở chế độ sub-agent:** Nếu Gate Bước 0 đã set `_agent_mode: true`, toàn bộ
268
269
  > quy trình này bị **bỏ qua** — orchestrator đã chạy sẵn một dimension/UC cho mỗi
@@ -381,6 +382,31 @@ Ghi lại `convergence_rounds` (số vòng critic đã chạy) cho report.
381
382
 
382
383
  ---
383
384
 
385
+ ## Phase 2.5 — Thẩm định *(chỉ chạy khi `VERIFY = on`)*
386
+
387
+ **Vì sao có bước này.** Phase 1 và Phase 2 chỉ có **một chiều lực**: fan-out mở rộng bề
388
+ ngang, critic lặp cho tới khi không còn gì mới — cả hai đều hỏi *"còn thiếu gì nữa?"*.
389
+ Không có gì hỏi ngược lại *"cái vừa tìm ra có thật không?"*. Nên quy trình này đẩy **recall**
390
+ lên mà **không có gì kéo precision lại**, và càng lặp critic thì tỉ lệ finding bịa càng cao —
391
+ đúng thứ nó tự sinh ra: khẳng định hành vi tài liệu không nêu, trích evidence sai, hoặc gắn
392
+ nhãn vấn đề cho thứ thực ra là chuyện làm-kỹ-hơn.
393
+
394
+ Chạy `steps/gap-verify.md` trên `ALL_FINDINGS` với:
395
+ - `FINDINGS` = `ALL_FINDINGS` (sau Phase 2)
396
+ - `EVIDENCE_ROOT` = `{paths.specs_dir}` — hoặc giá trị lệnh gọi chỉ định
397
+ - `VERDICT_FIELD` = trường trạng thái của FINDINGS SCHEMA mà lệnh định nghĩa
398
+ - `RERATE` = `on`
399
+
400
+ Finding bị `❌ INVALID` / `⚠️ RECLASSIFY` / `🔁 MERGE` **không đi tiếp sang Phase 3** — nhưng
401
+ **KHÔNG bị xoá**: chúng vào file findings với trạng thái đóng + lý do, để người đọc kiểm chứng
402
+ được vì sao chúng bị loại. Ghi lại số liệu verdict cho report.
403
+
404
+ > **Chạy TRƯỚC Phase 3, không phải sau.** Dedup và giải quyết xung đột là việc tốn suy luận;
405
+ > làm nó trên một tập còn lẫn finding bịa là vừa phí, vừa nguy hiểm — một finding ảo có thể
406
+ > "thắng" một finding thật ở bước giữ-cái-severity-cao-hơn.
407
+
408
+ ---
409
+
384
410
  ## Phase 3 — Dedup, giải quyết xung đột, merge
385
411
 
386
412
  Các sub-agent chạy **mù với nhau** (độc lập = độ phủ đa dạng). Chúng không bao giờ
@@ -412,7 +438,7 @@ Convergence: {convergence_rounds} vòng critic — file findings đã đầy đ
412
438
 
413
439
  ---
414
440
 
415
- ## Phân tích — 3 lăng kính (fan out cả ba, rồi hội tụ)
441
+ ## Phân tích — 4 lăng kính (fan out cả bốn, rồi hội tụ)
416
442
 
417
443
  Chạy review qua **Quy trình Review** ở trên (`steps/review-fanout.md`).
418
444
 
@@ -431,22 +457,23 @@ Chạy review qua **Quy trình Review** ở trên (`steps/review-fanout.md`).
431
457
  - **`applied_to_version` có mặt VÀ `==` version PRD hiện tại** → PRD đổi đúng bằng phần lệnh này tự áp, không actor khác động vào → **DELTA**: `CHANGED_SCOPE` = { `uc_id`/`section` của các finding `status: applied` trong findings cũ } ∪ { UC có trong PRD hiện tại nhưng chưa từng xuất hiện ở findings cũ }. Truyền `CHANGED_SCOPE` này vào Quy trình Review.
432
458
  - **`applied_to_version` vắng mặt HOẶC `≠` version hiện tại** → PRD đã bị sửa bởi **actor khác** (lệnh `/review-context`, sửa tay…) sau lần resume này → KHÔNG tin được phạm vi hẹp → **FULL** (KHÔNG truyền `CHANGED_SCOPE`), kèm cảnh báo: `"PRD đổi ngoài tầm theo dõi của findings (applied_to_version={A} ≠ hiện tại={C}); quét lại toàn bộ để khỏi sót UC do người/lệnh khác sửa."`
433
459
 
434
- **DIMENSIONS** = 3 lăng kính dưới đây — fan out một sub-agent cho mỗi lăng kính, mỗi cái quét
460
+ **DIMENSIONS** = 4 lăng kính dưới đây — fan out một sub-agent cho mỗi lăng kính, mỗi cái quét
435
461
  toàn bộ PRD qua đúng lăng kính của nó:
436
462
 
437
- <!-- ─────────────────────────────────────────────────────────────────────────────
438
- LĂNG KÍNH BỊ TẮT (DISABLED — KHÔNG dùng, KHÔNG fan-out agent cho lăng kính này):
439
-
440
- - **Lăng kính QA (tầng nghiệm thu)**: AC có nêu **outcome quan sát/kiểm được** chưa? — **KHÔNG** hỏi "AC đủ chi tiết chưa" (câu đó kéo cơ chế vào AC). Chi tiết cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi vụn) thuộc **BR/BL**: nếu gap là cơ chế → suggestion phải **route sang BR/BL + AC ref**, KHÔNG phình AC. AC có lặp lại nội dung BR (trùng tầng) không → nếu có, đề xuất làm mỏng AC.
463
+ - **Lăng kính QA (tầng nghiệm thu)** *(bật lại 2026-08-25 — xem `docs/plans/qc-implementation-log.md` B8)*: AC có nêu **outcome quan sát/kiểm được** chưa? — **KHÔNG** hỏi "AC đủ chi tiết chưa" (câu đó kéo cơ chế vào AC). Chi tiết cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi vụn) thuộc **BR/BL**: nếu gap là cơ chế → suggestion phải **route sang BR/BL + AC ref**, KHÔNG phình AC. AC có lặp lại nội dung BR (trùng tầng) không → nếu có, đề xuất làm mỏng AC.
441
464
 
442
- CÁCH THÊM LẠI QA (khi cần bật lại giai đoạn sau):
443
- 1. Chuyển bullet QA ở trên ra khỏi block comment này, đặt lên đầu danh sách DIMENSIONS.
444
- 2. Đổi "3 lăng kính"/"cả ba" "4 lăng kính"/"cả bốn" ở: dòng tiêu đề (# /refine-prd),
445
- heading "## Phân tích", câu "DIMENSIONS = N lăng kính", và steps/review-fanout.md.
446
- 3. Thêm "QA" lại vào enum của `lens:` trong FINDINGS SCHEMA + vào `by_lens`.
447
- 4. Thêm "QA" lại vào ghi chú "phán đoán DEV/SA/PO" ở LƯU Ý của schema.
448
- 5. Rebuild: node bin/build.js
449
- ───────────────────────────────────────────────────────────────────────────── -->
465
+ > **Phạm vi lăng kính QA — hẹp có chủ ý, đừng nới.** Nó hỏi về **HÌNH THỨC** của AC (*"phát biểu này kiểm chứng được không?"* · *"có lặp tầng không?"*), **KHÔNG** về **NỘI DUNG** (*"còn thiếu gì?"*).
466
+ >
467
+ > Lý do là thời điểm: ở đây **chỉ có PRD** — design-spec, BDD, tech-doc đều chưa tồn tại. Nên không thể phân biệt *"PRD thiếu X"* với *"PRD cố ý để X cho design-spec"*, phép kiểm *"đã trả lời ở tài liệu khác chưa?"* **không tài liệu khác để tra**.
468
+ >
469
+ > Số liệu thật (14 lần chạy repo QC): review chỉ-đọc-PRD ra **14 gap** trung bình, review đủ 4 nguồn ra **9,4** — khoảng 5 gap chênh lệch là câu hỏi mà tài liệu sau **trả lời hộ**. Nới lăng kính này sang câu hỏi nội dung là cố tình sinh ra 5 gap đó rồi gửi PO.
470
+ >
471
+ > Câu hỏi nội dung thuộc `/qc-analyze` (3 lăng kính: xử lý lỗi · giao diện · dữ liệu & cấu hình), nơi đã có đủ 4 nguồn để tra.
472
+ >
473
+ > **CÁCH TẮT LẠI QA** *(nếu cần)*: gỡ bullet QA ở trên · đổi `4 lăng kính`/`cả bốn` → `3`/`cả ba` ở
474
+ > dòng tiêu đề, heading `## Phân tích`, câu `DIMENSIONS = N lăng kính`, và `steps/review-fanout.md` ·
475
+ > gỡ `QA` khỏi enum `lens:` + `by_lens` + ghi chú `phán đoán QA/DEV/SA/PO` · sửa
476
+ > `docs/explain/03-refine-prd.md` cho khớp · rebuild `node bin/build.js`.
450
477
 
451
478
  > **Nguyên tắc chung cho DEV & SA — đọc bằng mắt kỹ thuật, VIẾT bằng lời nghiệp vụ.**
452
479
  > Hai lăng kính này dùng con mắt kỹ thuật để **phát hiện chỗ nghiệp vụ mô tả thiếu/mơ hồ/mâu thuẫn đến mức sẽ chặn triển khai** — mục tiêu là **làm rõ vấn đề nghiệp vụ để sau này xử lý được về mặt kỹ thuật**. **KHÔNG** đưa góc nhìn kỹ thuật vào PRD, **KHÔNG** đề xuất giải pháp/cơ chế kỹ thuật. Mọi `finding` và `suggestion` phải **thuần nghiệp vụ** (tuân Business Language Guard): mô tả *cái nghiệp vụ còn thiếu/chưa rõ* và *hỏi cần làm rõ gì*, chứ không nói *làm thế nào về kỹ thuật*.
@@ -483,7 +510,7 @@ status: "pending_review"
483
510
 
484
511
  findings:
485
512
  - id: "F001"
486
- lens: "DEV" # DEV | SA | PO
513
+ lens: "DEV" # QA | DEV | SA | PO
487
514
  severity: "major" # critical | major | minor
488
515
  section: "§2. Acceptance Criteria" # nhãn heading/section dạng người đọc
489
516
  uc_id: "{TICKET-ID}-UC{N}" # UC mà finding thuộc về; "" nếu PRD-global (scope, metrics, problem statement)
@@ -499,8 +526,8 @@ findings:
499
526
  # true = AI tự tin cao vào suggestion này; Review Board có thể hiển thị nút "quick accept"
500
527
  # false = cần human đọc kỹ và ghi quyết định trước khi accept
501
528
  # Resume Mode luôn áp dụng theo status (accepted|modified), bất kể auto_fixable.
502
- # LƯU Ý: /refine-prd CỐ Ý không có `--fix` mode (khác /review-context) — finding 3 lăng kính
503
- # là phán đoán DEV/SA/PO, phải qua người duyệt ở Board; auto_fixable ở đây CHỈ là gợi ý
529
+ # LƯU Ý: /refine-prd CỐ Ý không có `--fix` mode (khác /review-context) — finding 4 lăng kính
530
+ # là phán đoán QA/DEV/SA/PO, phải qua người duyệt ở Board; auto_fixable ở đây CHỈ là gợi ý
504
531
  # quick-accept cho Board, KHÔNG để máy tự áp.
505
532
  status: "pending"
506
533
  applied_via: ""
@@ -516,7 +543,7 @@ findings:
516
543
  summary:
517
544
  total_findings: {N}
518
545
  by_severity: { critical: {N}, major: {N}, minor: {N} }
519
- by_lens: { DEV: {N}, SA: {N}, PO: {N} }
546
+ by_lens: { QA: {N}, DEV: {N}, SA: {N}, PO: {N} }
520
547
  recommendation: "APPROVED_WITH_MINOR_CHANGES | NEEDS_REVISION | BLOCKED"
521
548
  # Rule: critical ≥ 1 → BLOCKED
522
549
  # critical = 0, major ≥ 1 → NEEDS_REVISION
@@ -1,7 +1,7 @@
1
1
  # /report-bug — File một Bug có trace-spec (cho Tester & QC)
2
2
 
3
3
  Dành cho **tester và QC** — gồm cả **product-gap** lòi ra từ pipeline `/qc-*`
4
- (`/qc-run-test` FAIL phân loại product-gap, hoặc một spec-defect blocker `DOC_GAPS` từ
4
+ (`/qc-run-test` FAIL phân loại product-gap, hoặc một spec-defect blocker `DOC_GAP` từ
5
5
  `/qc-analyze`). Sinh một bug report có cấu trúc với đầy đủ spec context, phân loại layer
6
6
  khả nghi, và lưu lại để handoff cho team dev.
7
7
 
@@ -267,10 +267,11 @@ vòng không sinh thêm gì mới, *trước khi* ghi file findings.
267
267
 
268
268
  Lệnh gọi cung cấp hai thứ bắt buộc + hai tuỳ chọn:
269
269
  - **DIMENSIONS** — danh sách các chiều review để fan out
270
- (`/refine-prd` → 3 lăng kính; `/review-context` → các P-check hoặc B-check).
270
+ (`/refine-prd` → 4 lăng kính; `/review-context` → các P-check hoặc B-check; `/qc-analyze` → 3 lăng kính quét gap).
271
271
  - **FINDINGS SCHEMA** — dạng YAML mà mỗi finding phải theo (định nghĩa trong lệnh).
272
272
  - **GRANULARITY** *(tuỳ chọn, mặc định `auto`)* — `auto`: chọn độ mịn fan-out theo bảng ngưỡng kích thước ở Phase 1 (hành vi cũ). `per-uc`: **LUÔN** fan-out theo từng UC, **bỏ qua ngưỡng** — dùng cho review cần độ đầy đủ cao (`/refine-prd` truyền cái này để lần đầu đã quét sâu). Lệnh không truyền → `auto` → hành vi không đổi.
273
273
  - **CHANGED_SCOPE** *(tuỳ chọn)* — danh sách UC/section đã thay đổi (review **delta**). Nếu được truyền, Phase 1 chỉ fan-out trên các phạm vi này + PRD-global; Phase 2 critic vẫn quét **toàn doc** làm lưới an toàn. Không truyền → quét toàn bộ như thường.
274
+ - **VERIFY** *(tuỳ chọn, mặc định `off`)* — `on` chèn **Phase 2.5** (`steps/gap-verify.md`) giữa critic và dedup: mỗi finding phải mở lại tài liệu nguồn tự chứng minh trước khi được giữ. Không truyền → hành vi không đổi.
274
275
 
275
276
  > **Bỏ qua ở chế độ sub-agent:** Nếu Gate Bước 0 đã set `_agent_mode: true`, toàn bộ
276
277
  > quy trình này bị **bỏ qua** — orchestrator đã chạy sẵn một dimension/UC cho mỗi
@@ -389,6 +390,31 @@ Ghi lại `convergence_rounds` (số vòng critic đã chạy) cho report.
389
390
 
390
391
  ---
391
392
 
393
+ ## Phase 2.5 — Thẩm định *(chỉ chạy khi `VERIFY = on`)*
394
+
395
+ **Vì sao có bước này.** Phase 1 và Phase 2 chỉ có **một chiều lực**: fan-out mở rộng bề
396
+ ngang, critic lặp cho tới khi không còn gì mới — cả hai đều hỏi *"còn thiếu gì nữa?"*.
397
+ Không có gì hỏi ngược lại *"cái vừa tìm ra có thật không?"*. Nên quy trình này đẩy **recall**
398
+ lên mà **không có gì kéo precision lại**, và càng lặp critic thì tỉ lệ finding bịa càng cao —
399
+ đúng thứ nó tự sinh ra: khẳng định hành vi tài liệu không nêu, trích evidence sai, hoặc gắn
400
+ nhãn vấn đề cho thứ thực ra là chuyện làm-kỹ-hơn.
401
+
402
+ Chạy `steps/gap-verify.md` trên `ALL_FINDINGS` với:
403
+ - `FINDINGS` = `ALL_FINDINGS` (sau Phase 2)
404
+ - `EVIDENCE_ROOT` = `{paths.specs_dir}` — hoặc giá trị lệnh gọi chỉ định
405
+ - `VERDICT_FIELD` = trường trạng thái của FINDINGS SCHEMA mà lệnh định nghĩa
406
+ - `RERATE` = `on`
407
+
408
+ Finding bị `❌ INVALID` / `⚠️ RECLASSIFY` / `🔁 MERGE` **không đi tiếp sang Phase 3** — nhưng
409
+ **KHÔNG bị xoá**: chúng vào file findings với trạng thái đóng + lý do, để người đọc kiểm chứng
410
+ được vì sao chúng bị loại. Ghi lại số liệu verdict cho report.
411
+
412
+ > **Chạy TRƯỚC Phase 3, không phải sau.** Dedup và giải quyết xung đột là việc tốn suy luận;
413
+ > làm nó trên một tập còn lẫn finding bịa là vừa phí, vừa nguy hiểm — một finding ảo có thể
414
+ > "thắng" một finding thật ở bước giữ-cái-severity-cao-hơn.
415
+
416
+ ---
417
+
392
418
  ## Phase 3 — Dedup, giải quyết xung đột, merge
393
419
 
394
420
  Các sub-agent chạy **mù với nhau** (độc lập = độ phủ đa dạng). Chúng không bao giờ
@@ -0,0 +1,117 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-08-25
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-analyst/spec-issue-reporter/DOC_GAPS.template.md
6
+ upstream_sha: c7ca6cfb798c609f18ffe20a38f64f95c76e1919
7
+ ---
8
+
9
+ > **Template DUY NHẤT cho file gap của `/qc-analyze`** *(B9 — hợp nhất 2026-08-25)*.
10
+ > Bản 9 cột cũ đã bỏ: nó thiếu đúng hai thứ PO cần — cột *Giao cho đội* và ô câu hỏi 4 phần.
11
+ > Giữ một bản kém hơn làm mặc định là để người không biết có cờ nhận bản kém.
12
+ >
13
+ > **Một chỗ CỐ Ý khác upstream:** mức nặng nhất dùng từ **`Blocker`**, không phải `Critical`.
14
+ > Lý do: `/qc-run-test` đọc `🔴 Blocker` để đặt *"scenario đang chờ PO"* vào sổ kết quả trace.
15
+ > Đổi từ là đứt liên kết đó. Ba mức còn lại giữ nguyên upstream.
16
+
17
+ # DOC GAP -- <UC>: <Tên UC>
18
+
19
+ | Trường | Giá trị |
20
+ |---|---|
21
+ | Feature | `<FEATURE>` |
22
+ | UC | `<UC> — <Tên UC>` |
23
+ | Tài liệu nguồn | `<đường dẫn PRD>` · `<đường dẫn BDD nếu có>` · `<các file inputs/ liên quan>` |
24
+ | Ngày phân tích | `<YYYY-MM-DD>` |
25
+ | Tổng số gap | `<N>` (Blocker: x · High: y · Medium: z · Low: w) |
26
+ | Trạng thái chung | 🔴 Blocked / 🟠 Cần làm rõ / 🟢 Đủ rõ để thiết kế TC |
27
+
28
+ ---
29
+
30
+ ## Tài liệu đầu vào đã đọc để phân tích
31
+
32
+ > Liệt kê **đầy đủ** mọi file đã đọc để dựng phân tích gap (spec chính + mọi ref-link + transitive 1-hop). Đây là căn cứ độ phủ — mọi file đã mở đều phải có mặt, KHÔNG bỏ sót. Đường dẫn tính từ `{paths.specs_dir}`.
33
+
34
+ | # | Đường dẫn (từ `{paths.specs_dir}`) | Vai trò | Phiên bản |
35
+ |---|---|---|---|
36
+ | 1 | `<đường dẫn spec chính>` | **Spec chính** | `<vX.Y>` |
37
+ | 2 | `<đường dẫn ref>` | Ref bắt buộc — `<lý do>` | `—` |
38
+ | ... | ... | Transitive 1-hop — `<feature liền kề / dịch vụ tiêu thụ>` | `—` |
39
+
40
+ **Tổng: `<N>` tài liệu.** Lane API: `<có → liệt kê openapi.yaml/*.dbml/tdd | không có → SKIP, không đọc, không bịa endpoint>` *(chỉ áp khi framework đã nhận trục lane — xem B5)*. Không dùng làm evidence: Change log · Appendix · mục Giả định AI.
41
+
42
+ ---
43
+
44
+ | ID | Loại | Vấn đề cần confirm | Câu hỏi / Lý do cần confirm & Gợi ý | Trích đoạn tài liệu (Evidence) | Giao cho đội | Mức độ | Người trả lời | Trạng thái | Câu trả lời |
45
+ |---|---|---|---|---|---|---|---|---|---|
46
+ | GAP-<UC>-001 | MISSING / AMBIGUOUS / CONTRADICTORY / ASSUMPTION | Tiêu đề ngắn mô tả vấn đề | **Bối cảnh:** Ngữ cảnh dẫn đến gap này.<br/>**Vấn đề:** Điều gì chưa được spec hoặc mâu thuẫn.<br/>**Tại sao quan trọng:** Hậu quả nếu không làm rõ.<br/>**Gợi ý:** Ai cần làm gì để giải quyết. | `<đường dẫn file spec>` `<TÊN-BR hoặc AC gốc trong PRD, ví dụ FEAT-01-2-UC4-BR11>`: trích nguyên văn | Dev / PO / BA / Design | 🔴 Blocker | | Open | |
47
+
48
+ ---
49
+
50
+ ## Ưu tiên xử lý
51
+
52
+ | Mức độ | Gap ID |
53
+ |---|---|
54
+ | 🔴 Blocker | GAP-<UC>-00x · ... |
55
+ | 🟠 High | GAP-<UC>-00x · ... |
56
+ | 🟡 Medium | GAP-<UC>-00x · ... |
57
+ | ⚪ Low | GAP-<UC>-00x · ... |
58
+
59
+ **Cần chốt trước khi viết test case:**
60
+ - GAP-<UC>-00x: <lý do block>
61
+
62
+ ---
63
+
64
+ ## Chú thích (Legend)
65
+
66
+ ### Loại Gap
67
+
68
+ | Loại | Mô tả |
69
+ |---|---|
70
+ | MISSING | Thông tin, chức năng, quy tắc, hoặc kịch bản chưa được mô tả trong bất kỳ tài liệu nào trong `{paths.specs_dir}`. |
71
+ | AMBIGUOUS | Mô tả mơ hồ, có thể hiểu theo nhiều cách, hoặc thiếu chi tiết để viết kịch bản kiểm thử. |
72
+ | CONTRADICTORY | Hai hoặc nhiều tài liệu trong `{paths.specs_dir}` mô tả cùng một hành vi nhưng mâu thuẫn nhau. |
73
+ | ASSUMPTION | Giả định do nhóm QA tự suy luận từ tài liệu trong `{paths.specs_dir}`, chưa được PO/Dev xác nhận tường minh. |
74
+
75
+ ### Mức độ
76
+
77
+ | Mức | Ý nghĩa |
78
+ |---|---|
79
+ | 🔴 Blocker | Chặn viết kịch bản kiểm thử hoặc lập trình — không thể tiến hành nếu chưa có câu trả lời. |
80
+ | 🟠 High | Ảnh hưởng đến nhiều kịch bản kiểm thử hoặc logic nghiệp vụ chính — cần giải quyết trước khi viết test case. |
81
+ | 🟡 Medium | Ảnh hưởng đến một số kịch bản cụ thể — cần giải quyết trước sprint kiểm thử. |
82
+ | ⚪ Low | Ít ảnh hưởng — có thể ghi giả định tạm thời và xử lý trong sprint review. |
83
+
84
+ ### Giao cho đội
85
+
86
+ | Ký hiệu | Đội |
87
+ |---|---|
88
+ | Dev | Đội phát triển (Frontend + Backend) |
89
+ | Architect | Kiến trúc sư hệ thống |
90
+ | PO | Product Owner |
91
+ | BA | Business Analyst |
92
+ | Design | Đội thiết kế UX/UI |
93
+ | Analytics | Nhóm dữ liệu / phân tích |
94
+
95
+ ---
96
+
97
+ ## ⚠️ Checklist bắt buộc trước khi lưu file
98
+
99
+ Trước khi lưu file gap, kiểm tra **từng hàng** trong bảng gap:
100
+
101
+ - [ ] **Có section `Tài liệu đầu vào đã đọc để phân tích`** – bảng liệt kê **đầy đủ** mọi file đã đọc (spec chính + ref-link + transitive 1-hop), có đường dẫn `{paths.specs_dir}`, vai trò, phiên bản; ghi tổng số + trạng thái lane API. KHÔNG bỏ sót file nào đã mở.
102
+ - [ ] **10 cột đủ** – đúng thứ tự: `ID | Loại | Vấn đề cần confirm | Câu hỏi / Lý do cần confirm & Gợi ý | Trích đoạn tài liệu (Evidence) | Giao cho đội | Mức độ | Người trả lời | Trạng thái | Câu trả lời`
103
+ - [ ] **Cột 3 = `Vấn đề cần confirm`** – KHÔNG viết tắt thành `Vấn đề`
104
+ - [ ] **Cột 4 = `Câu hỏi / Lý do cần confirm & Gợi ý`** – bắt buộc có đủ 4 phần, tách bằng `<br/>`:
105
+ ```
106
+ **Bối cảnh:** ...<br/>**Vấn đề:** ...<br/>**Tại sao quan trọng:** ...<br/>**Gợi ý:** ...
107
+ ```
108
+ Không viết 4 mục liên tiếp trên cùng một dòng.
109
+ - [ ] **Cột 5 = `Trích đoạn tài liệu (Evidence)`** – KHÔNG viết tắt thành `Evidence`; dẫn nguyên văn + đường dẫn file `{paths.specs_dir}`; **dùng PRD source ID** (ví dụ `FEAT-01-2-UC4-BR11`), KHÔNG dùng internal analysis ID (ví dụ `BR-UC4-12`)
110
+ - [ ] **Cột Mức độ** (cột 7) – bắt buộc dùng emoji: `🔴 Blocker` / `🟠 High` / `🟡 Medium` / `⚪ Low`. Không được ghi text thuần.
111
+ - [ ] **Cột Giao cho đội** (cột 6) – dùng: `Dev` / `PO` / `BA` / `Design` / `Architect` / `Analytics` hoặc kết hợp. Nếu thấy "Open" ở đây → đang bị lệch cột.
112
+ - [ ] **Cột Người trả lời = vai trò** (PO / BA / Dev / Design / ...). Nếu thấy "Open" ở đây → đang bị lệch cột.
113
+ - [ ] **Cột Trạng thái** = `Open` / `Resolved` / `Out of Scope` / `Re-scoped → Covered`
114
+ - [ ] **Trạng thái chung** trong metadata có emoji: `🔴 Blocked` / `🟠 Cần làm rõ` / `🟢 Đủ rõ để thiết kế TC`
115
+ - [ ] **Có đủ 3 section cuối**: Ưu tiên xử lý · Chú thích (Legend) với bảng đầy đủ
116
+ - [ ] **KHÔNG có section "Change log"** và **KHÔNG có section "AI Assumptions"**
117
+ - [ ] **Evidence chỉ từ `{paths.specs_dir}`** – không dùng file trong `{paths.qc_dir}` nội bộ (TC_*.md, REQUIREMENT_ANALYSIS*.md, DOC_GAP*.md khác)
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  version: 1.0
3
3
  updated: 2026-06-11
4
- ported_from: ai-automation-qc-base
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-analyst/acceptance-criteria.md
6
+ upstream_sha: 516f35cf78102d27aa5639bfb2818274399800c0
5
7
  ---
6
8
 
7
9
  # Acceptance Criteria — Sinh tiêu chí chấp nhận
@@ -52,7 +54,7 @@ Mỗi AC gắn mã trace: chức năng + BR-xx để TC sau này map 1-1.
52
54
  ## Output
53
55
 
54
56
  Ghi vào **mục Acceptance Criteria** của `{paths.qc_dir}/{UC-ID}/REQUIREMENT_ANALYSIS.md`
55
- (KHÔNG tạo file riêng — qc-analyze chỉ trả 2 file: `REQUIREMENT_ANALYSIS.md` + `DOC_GAPS.md`):
57
+ (KHÔNG tạo file riêng — qc-analyze chỉ trả 2 file: `REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md`):
56
58
 
57
59
  - Danh sách AC dạng Given/When/Then, có mã trace về chức năng, business rule (BR-xx)
58
60
  và scenario chính thức `{UC-ID}-SC{N}` của `.feature`.
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  version: 1.0
3
- updated: 2026-06-11
4
- ported_from: ai-automation-qc-base
3
+ updated: 2026-08-25
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-analyst/business-rules.md
6
+ upstream_sha: 0d5f01257c30182d1c98835303640775d360a3da
5
7
  ---
6
8
 
7
9
  # Business Rules — Trích xuất luật nghiệp vụ
@@ -25,6 +27,38 @@ Trích xuất và liệt kê toàn bộ business rule, điều kiện và ràng
25
27
  1. Đọc spec đã bóc tách (output của spec-breakdown) hoặc tài liệu gốc.
26
28
  2. Quét tìm: điều kiện ("nếu… thì…"), ràng buộc field, giới hạn (min/max, rate limit),
27
29
  quy tắc phân quyền, công thức tính, quy tắc trạng thái, default value.
30
+ 3. **Checklist ràng buộc field — kiểm tra TẤT CẢ field (kể cả tuỳ chọn / optional):**
31
+ - [ ] `minlength` / `maxlength` — PRD có nêu không? Nếu không → GAP (MISSING)
32
+ - [ ] Ký tự được phép — chữ, số, tiếng Việt có dấu, ký tự đặc biệt, khoảng trắng?
33
+ - [ ] Trim khoảng trắng đầu/cuối — có hay không?
34
+ - [ ] Format đặc biệt — email, SĐT, ngày tháng, v.v.
35
+ > ⚠️ **Field tuỳ chọn (optional) vẫn phải kiểm tra đủ 4 mục trên.** "Không bắt buộc nhập" KHÔNG đồng nghĩa với "không có ràng buộc". Đây là nguồn gốc hay bị bỏ sót khi phân tích.
36
+
37
+ 4. **Checklist đặc biệt — hay bị bỏ sót khi đọc BDD/PRD:**
38
+
39
+ **a. Routing table — đọc cả 2 chiều:**
40
+ - [ ] Với MỖI rule "nếu đủ điều kiện → bỏ qua / nếu thiếu → vào": đánh dấu cả 2 nhánh cần test
41
+ - [ ] Routing table N loại tài khoản × M màn → duyệt từng ô, không bỏ dòng nào
42
+
43
+ **b. Liệt kê hết variant:**
44
+ - [ ] Spec đề cập nhiều provider/platform/giá trị liệt kê (Google/Facebook, Lớp 1-6...)? → ghi từng variant ra
45
+ - [ ] Với mỗi variant: behavior hoặc content có khác nhau không? Nếu có → đánh dấu cần TC riêng
46
+
47
+ **c. Telemetry/event analytics:**
48
+ - [ ] Liệt kê TẤT CẢ event name được nhắc trong BDD/PRD cho UC này
49
+ - [ ] Với mỗi event: trigger khác nhau? → cần TC riêng
50
+ - [ ] Có field nhạy cảm (SĐT, PII) KHÔNG ĐƯỢC vào event? → cần TC verify âm riêng
51
+
52
+ **d. Privacy/security assertions âm:**
53
+ - [ ] Spec có nói "KHÔNG ghi", "KHÔNG hiển thị", "chỉ đọc", "KHÔNG vào event"? → ghi ra, cần TC riêng
54
+ - [ ] "Read-only + che X/hiện Y" → 2 TC riêng: (1) hiển thị đúng che/hiện, (2) không chỉnh sửa được
55
+
56
+ **e. Validation kế thừa từ UC/AC khác:**
57
+ - [ ] Spec có reference "chuẩn hoá theo ACx", "logic tương tự UCy", "validation như màn Z"? → đọc UC/AC đó
58
+ - [ ] Liệt kê TẤT CẢ scenario normalization của UC nguồn chưa có trong UC hiện tại
59
+
60
+ **f. AC có sub-cases:**
61
+ - [ ] Mỗi AC dạng "(1)...→...; (2)...→...; (3)...→..." → đếm số sub-cases, mỗi sub-case 1 TC
28
62
 
29
63
  ---
30
64
 
@@ -50,10 +84,10 @@ Với rule có nhiều điều kiện kết hợp → gợi ý dựng **Decision
50
84
  ## Output
51
85
 
52
86
  Ghi vào **mục Business Rules** của `{paths.qc_dir}/{UC-ID}/REQUIREMENT_ANALYSIS.md`
53
- (KHÔNG tạo file riêng — qc-analyze chỉ trả 2 file: `REQUIREMENT_ANALYSIS.md` + `DOC_GAPS.md`):
87
+ (KHÔNG tạo file riêng — qc-analyze chỉ trả 2 file: `REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md`):
54
88
 
55
89
  - Bảng business rule có ID (BR-xx) để TC trace ngược về.
56
90
  - Gợi ý các rule cần Decision Table / BVA khi sang qa-designer.
57
91
 
58
- Rule MÂU THUẪN / KHÔNG RÕ → ghi vào `{paths.qc_dir}/{UC-ID}/DOC_GAPS.md`
92
+ Rule MÂU THUẪN / KHÔNG RÕ → ghi vào `{paths.qc_dir}/{UC-ID}/DOC_GAP.md`
59
93
  (loại CONTRADICTORY / AMBIGUOUS, cột "Ảnh hưởng" trỏ BR-xx).
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  version: 1.0
3
3
  updated: 2026-06-11
4
- ported_from: ai-automation-qc-base
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-analyst/data-flow.md
6
+ upstream_sha: fc0fc3d0f8010e3fb266c16b132eff1b23641a8f
5
7
  ---
6
8
 
7
9
  # Data Flow — Phân tích luồng dữ liệu
@@ -53,7 +55,7 @@ Thể hiện luồng dạng bước tuần tự hoặc sơ đồ text:
53
55
  ## Output
54
56
 
55
57
  Ghi vào **mục Data Flow** của `{paths.qc_dir}/{UC-ID}/REQUIREMENT_ANALYSIS.md`
56
- (KHÔNG tạo file riêng — qc-analyze chỉ trả 2 file: `REQUIREMENT_ANALYSIS.md` + `DOC_GAPS.md`):
58
+ (KHÔNG tạo file riêng — qc-analyze chỉ trả 2 file: `REQUIREMENT_ANALYSIS.md` + `DOC_GAP.md`):
57
59
 
58
60
  - Sơ đồ/list luồng dữ liệu cho mỗi kịch bản chính.
59
61
  - Danh sách integration point + state change + failure point.
@@ -61,4 +63,4 @@ Ghi vào **mục Data Flow** của `{paths.qc_dir}/{UC-ID}/REQUIREMENT_ANALYSIS.
61
63
  - Dữ liệu/trạng thái cần chuẩn bị & cleanup → đầu vào fixture cho qa-runner.
62
64
 
63
65
  Chặng nào luồng/hành vi chưa rõ (vd lỗi xử lý ra sao, retry, partial commit) →
64
- ghi vào `{paths.qc_dir}/{UC-ID}/DOC_GAPS.md` (loại MISSING / OPEN QUESTION).
66
+ ghi vào `{paths.qc_dir}/{UC-ID}/DOC_GAP.md` (loại MISSING / OPEN QUESTION).
@@ -0,0 +1,174 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-08-25
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-analyst/exhaustive-gap-scanner.md
6
+ upstream_sha: b3f5aa112ec2fb93100d8945a3fa3d5fe904eb26
7
+ port_completeness: partial
8
+ ---
9
+
10
+ # Exhaustive Gap Scanner — 5 chiều quét gap
11
+
12
+ Năm **lăng kính** để quét gap tài liệu. Mỗi lăng kính chỉ lo phần mình và **mù với các
13
+ lăng kính khác** — đó là điều làm độ phủ cao hơn một lượt đọc tuần tự, nơi phần cuối tài liệu
14
+ luôn bị lướt.
15
+
16
+ > **Bốn trong năm chiều đang BẬT** ở `/qc-analyze`: `D2` · `D3` · `D4` · `D5`*(thu hẹp)*.
17
+ > Chỉ `D1` tắt. File này khai *nội dung* các chiều; việc *chạy* chúng thuộc
18
+ > `steps/review-fanout.md`.
19
+
20
+ ## Chiều nào đang bật
21
+
22
+ | Chiều | Trạng thái | Bằng chứng *(kiểm từng câu hỏi — xem `docs/plans/qc-implementation-log.md` §Kiểm chứng 31 câu hỏi)* |
23
+ |---|---|---|
24
+ | `D1` Luật nghiệp vụ | ⏸️ **tắt** | **4/5 câu đã có chỗ hỏi, và hỏi cụ thể hơn** — `business-rules.md` hỏi *"min/max · ký tự cho phép · trim · định dạng"* thay vì *"ngưỡng đã chốt chưa"* |
25
+ | `D2` Xử lý lỗi | ✅ **bật** | **4/6 câu KHÔNG AI HỎI** — không kỹ năng nào chuyên về *"hết số lần thử lại thì đi đâu"* |
26
+ | `D3` Giao diện | ✅ **bật** | **1/8 phủ tốt, 3 hở hẳn** — không ai đối chiếu chữ trên nút giữa các tài liệu |
27
+ | `D4` Dữ liệu & cấu hình | ✅ **bật** | **6/6 câu KHÔNG AI HỎI** — chiều đáng giá nhất |
28
+ | `D5` Đối chiếu chéo | ✅ **bật, THU HẸP** | **2/4 cặp đang hở** — cả hai dính `design-spec/`. Hai cặp còn lại đã có người làm → bỏ. Xem §Phạm vi ở D5 |
29
+
30
+ > **`D5` từng bị tắt, và đó là quyết định SAI.** Lý do tắt ban đầu — *"trùng nhiều"* — đúng một
31
+ > nửa: nó phủ **bốn** cặp tài liệu, và chỉ **hai** cặp đã có người làm. Hai cặp còn lại
32
+ > (`PRD ↔ design-spec/` và `bdd/ ↔ design-spec/`) **không ai đối chiếu nội dung**.
33
+ >
34
+ > Sai vì suy từ ấn tượng thay vì đếm danh sách. Bảng kiểm chứng 31 câu hỏi trong nhật ký là thứ
35
+ > đáng lẽ phải làm **trước** khi quyết.
36
+
37
+ > **Chi phí:** bật cả 5 (không thu hẹp) tốn ~5–6 lần token so với không bật. Cấu hình hiện tại —
38
+ > 3 chiều đầy đủ + `D5` thu hẹp — vào khoảng **~3,5 lần**. `D5` rẻ hơn một chiều thường vì nó chỉ
39
+ > so 2 cặp, và `design-spec/` thì trạm QC **đã đọc từ trước**.
40
+
41
+ ## Cố ý KHÔNG port nửa còn lại
42
+
43
+ Bản upstream tự cài lại toàn bộ cơ chế fan-out bằng tay: một Coordinator kiểm kê tài liệu,
44
+ dựng SPAWN PLAN, gọi song song 5 agent, rồi consolidate + dedup + đánh ID.
45
+
46
+ Framework **đã có đúng cơ chế đó** ở `steps/review-fanout.md` — và bản của framework còn có
47
+ thêm hai thứ upstream không có: vòng **completeness-critic** lặp tới khi hai vòng liền không
48
+ sinh gì mới, và **agent cap** gom batch khi fan-out quá rộng.
49
+
50
+ Port cả phần điều phối = nuôi hai bản cài đặt của cùng một thứ, rồi chúng trôi khỏi nhau.
51
+ Nên file này **chỉ giữ phần nội dung** (5 mandate), phần điều phối để `review-fanout` lo.
52
+
53
+ *Ghi vào `port_completeness: partial` ở frontmatter — khi đồng bộ ngược sau này, đừng hiểu
54
+ phần thiếu là "ta cố ý xoá nội dung".*
55
+
56
+ ---
57
+
58
+ ## Ràng buộc nguồn *(áp cho cả 5 chiều)*
59
+
60
+ - Chỉ dùng **spec repo** (`{paths.specs_dir}`) làm evidence. KHÔNG dùng artifact nội bộ do
61
+ chính pipeline sinh ra (`{paths.qc_dir}/**` — test-case, test-plan, file gap khác).
62
+ - **Bỏ qua** section **Change Log** · **Appendix** · **Giả định AI / AI Assumptions** trong mọi
63
+ tài liệu. Evidence CHỈ lấy từ thân bài: AC · BR · UC · Wireframe · Screen Spec · Scenario.
64
+ - **KHÔNG bịa** endpoint, bảng, field, hay tài liệu không tồn tại.
65
+
66
+ ---
67
+
68
+ ## Năm chiều
69
+
70
+ Truyền vào `steps/review-fanout.md` làm `DIMENSIONS`. Chiều nào không có tài liệu đầu vào
71
+ tương ứng thì **bỏ hẳn** — không tạo gap rỗng, không nhắc tới nó trong output.
72
+
73
+ ### D1 · Luật nghiệp vụ *(⏸️ TẮT ở `/qc-analyze` — xem bảng trên)*
74
+ - Logic rẽ nhánh: điều kiện đã đủ chưa? Thiếu nhánh nào?
75
+ - Ngưỡng / ràng buộc: đã chốt số cụ thể hay còn để ngỏ?
76
+ - Ngoại lệ: trường hợp biên nào chưa được xử lý trong spec?
77
+ - Rule mâu thuẫn giữa các tài liệu?
78
+ - Chỗ nào người viết test **buộc phải giả định** vì spec không rõ?
79
+
80
+ ### D2 · Xử lý lỗi *(✅ bật)*
81
+ - Quá hạn (timeout) → hành vi là gì?
82
+ - Số lần thử lại đã spec chưa? Khoảng cách giữa các lần?
83
+ - Thử lại hết số lần → hệ thống làm gì?
84
+ - Hàng đợi lỗi: ai xử lý? Có cảnh báo cho người vận hành không?
85
+ - Với **từng loại lỗi**: màn nào hiện, người dùng làm được gì tiếp?
86
+ - Khôi phục: người dùng thử lại được không? Luồng đi tiếp hay bị chặn?
87
+
88
+ ### D3 · Giao diện *(✅ bật — bỏ hẳn nếu không có BDD / design-spec / wireframe)*
89
+ - **Trạng thái màn**: thiếu state nào? (đang tải · rỗng · lỗi · thành công · một phần · vô hiệu)
90
+ - **Chữ & nhãn**: text nút/tiêu đề/thông báo/gợi ý có nhất quán trong cùng tài liệu và **giữa**
91
+ các tài liệu không?
92
+ - **Điều hướng**: từ mỗi màn, đi tiếp được đâu và quay lại được đâu? Đã spec đủ mọi đường chưa?
93
+ - **Kiểm tra & phản hồi**: rule validate đã spec? Thông báo lỗi/thành công đã có **nội dung
94
+ cụ thể** chưa?
95
+ - **Trạng thái biên**: màn trống, danh sách rỗng, quá hạn, kết quả 0 — trải nghiệm thế nào?
96
+ - **UI đã bị gỡ**: component/popup/màn còn trong design-spec nhưng PRD/BDD đã bỏ?
97
+ - **Đa nền** *(nếu có)*: hành vi trên các nền/breakpoint có nhất quán không?
98
+ - **Tài nguyên hiển thị**: loại asset (animation/ảnh/video) và tiêu chí hiển thị đã xác định chưa?
99
+
100
+ ### D4 · Dữ liệu & cấu hình *(✅ bật — bỏ hẳn nếu không có bảng tính điểm / dữ liệu mẫu / cờ tính năng / spec môi trường)*
101
+ - Bảng điểm / rule tính toán / bảng ánh xạ: có **đủ dữ liệu để tự kiểm chứng kết quả tính** không?
102
+ - Dữ liệu mẫu: có ví dụ đủ để dựng môi trường test không?
103
+ - Cấu hình đổi **giữa lúc đang chạy** thì hành vi là gì? Chốt giá trị tại thời điểm nào?
104
+ - Phụ thuộc môi trường: service, hàng đợi, DB cần thiết đã được spec cho môi trường test chưa?
105
+ - Việc dựng dữ liệu có phụ thuộc thứ còn để ngỏ hoặc chưa làm không?
106
+ - Cờ tính năng: cờ nào ảnh hưởng hành vi cần test? Giá trị mặc định ở môi trường test là gì?
107
+
108
+ ### D5 · Đối chiếu chéo tài liệu *(✅ bật — THU HẸP còn 2 cặp, xem dưới)*
109
+
110
+ > **Nhiệm vụ của chiều này là PHÁT HIỆN cặp lệch + gắn HƯỚNG thô. KHÔNG tự chốt loại cuối** —
111
+ > việc phân loại và lọc báo-oan do `steps/gap-verify.md` làm (T5 xác định hướng, T3b xác định
112
+ > mâu thuẫn thật). Chiều này chỉ đưa bằng chứng *"X nói khác/thiếu/thừa so với Y"*.
113
+
114
+ #### PHẠM VI — chỉ hai cặp, không phải bốn
115
+
116
+ Bản upstream so **mọi cặp** tài liệu trong feature package. Ở framework, hai cặp đã có chỗ khác
117
+ làm — so lại là nhân đôi công việc và PO nhận hai câu hỏi cho một vấn đề.
118
+
119
+ | Cặp | Ở framework | |
120
+ |---|---|---|
121
+ | **PRD ↔ `design-spec/`** | **không ai so nội dung** — `/generate-bdd` chỉ kiểm `Built from PRD` (số phiên bản). Cùng phiên bản mà nội dung lệch thì lọt | ✅ **SO** |
122
+ | **`bdd/{platform}/` ↔ `design-spec/`** | không ai | ✅ **SO** |
123
+ | PRD ↔ `bdd/` | `/review-context` **B1** đã làm (AC/BR nào chưa có scenario) | ❌ bỏ |
124
+ | PRD · `bdd/` ↔ `tech-docs/` | `/qc-analyze` §Đối chiếu tài liệu kỹ thuật đã làm (6 mục) | ❌ bỏ |
125
+
126
+ > **Cả hai cặp SO đều dính `design-spec/`** — tức phần **Designer vẽ**. Đây là artifact duy nhất
127
+ > trong feature package mà **không tài liệu nào đối chiếu nội dung với nó**.
128
+ >
129
+ > `design-spec/` ≠ `tech-docs/`: cái đầu là *giao diện người dùng thấy*, cái sau là *hợp đồng hệ
130
+ > thống*. `tech-docs/` đã được phủ ở §Đối chiếu tài liệu kỹ thuật của `/qc-analyze`.
131
+
132
+ Trạm QC **đã đọc `design-spec/`** từ trước (nó nằm trong danh sách nguồn). Nên chiều này không
133
+ nạp thêm file nào — chỉ bắt nó **so** thay vì chỉ **đọc**.
134
+
135
+ #### Bốn hướng lệch
136
+
137
+ Lấy **PRD làm gốc**, đối chiếu **thân bài** (KHÔNG đọc Change Log):
138
+
139
+ | Hướng | Nghĩa | Ai xử lý |
140
+ |---|---|---|
141
+ | **THIẾU** *(design-spec < PRD)* | PRD có màn / trạng thái / hành vi mà `design-spec/` **không** mô tả | Designer bổ sung |
142
+ | **THỪA** *(design-spec > PRD)* | `design-spec/` **tự thêm** màn/nút/hành vi mà PRD không định nghĩa | **PO chốt**: giữ (rồi định nghĩa hệ quả vào PRD) hay gỡ |
143
+ | **MÂU THUẪN** | cùng một hành vi/giá trị/chữ nhưng hai tài liệu nói khác nhau | PO + Designer |
144
+ | **LỆCH-REF** | `design-spec/` trích số/tên BR·AC đã đổi nghĩa — mở đúng BR/AC đó trong PRD **hiện tại**: ref không còn, hoặc mang nghĩa khác | PO |
145
+
146
+ > **THIẾU vs THỪA phải phân biệt đúng** — đây là lỗi framing hay gặp nhất, và hai hướng xử lý
147
+ > **ngược nhau**. Gọi *"thiết kế thiếu"* trong khi thiết kế **thừa** là đặt sai đề bài cho cả PO
148
+ > lẫn Designer: một bên tưởng phải vẽ thêm, một bên đáng lẽ phải quyết giữ hay gỡ.
149
+
150
+ #### Với cặp `bdd/` ↔ `design-spec/` — soi gì
151
+
152
+ - Kịch bản test đi qua một **trạng thái màn** mà `design-spec/` không có (`loading`/`error`/`empty`)?
153
+ - Kịch bản test tác động lên một **thành phần giao diện** không có trong Component Inventory?
154
+ - `design-spec/` mô tả một **đường điều hướng** mà không kịch bản nào đi qua?
155
+
156
+ *(Chiều này chỉ chạy khi feature có `design-spec/`. Feature `system` không có → bỏ hẳn cặp này.)*
157
+
158
+ ---
159
+
160
+ ## Sau khi quét — BẮT BUỘC thẩm định
161
+
162
+ Fan-out càng rộng thì gap bịa càng nhiều: đây là cơ chế **đẩy recall**, tự nó không có gì
163
+ kéo precision. Chạy `steps/gap-verify.md` trên tập gap trước khi bàn giao — đó là nửa còn lại.
164
+
165
+ **Hai cách gọi, tuỳ lệnh:**
166
+
167
+ | Lệnh gọi có | Thẩm định chạy ở đâu |
168
+ |---|---|
169
+ | `VERIFY = on` | tự động ở `review-fanout` Phase 2.5 — dùng khi fan-out là **nguồn gap duy nhất** |
170
+ | `VERIFY = off` | lệnh gọi tự chạy `gap-verify` **sau khi gộp** — dùng khi còn nguồn gap khác |
171
+
172
+ `/qc-analyze` dùng cách thứ hai: gap đến từ **cả** 4 kỹ năng phân tích **và** fan-out, nên phải
173
+ gộp trước rồi mới thẩm định một lần. Thẩm định hai tập rời thì phép kiểm `T6` (*"hai gap cùng gốc
174
+ thì gộp lại"*) không bắt được trùng lặp chéo nguồn.