@educa-corp/sdd-framework 0.5.0 → 0.6.0

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 (115) hide show
  1. package/bin/build.js +113 -19
  2. package/bin/gate-trace.js +464 -0
  3. package/bin/index.js +418 -146
  4. package/bin/lint-trace.js +602 -0
  5. package/bin/self-check.js +376 -1
  6. package/bin/trace-schema.json +252 -2
  7. package/commands/debug.md +123 -511
  8. package/commands/debug.tmpl +3 -0
  9. package/commands/define-product.md +86 -510
  10. package/commands/dev-gen-test.md +86 -510
  11. package/commands/dev-run-test.md +86 -510
  12. package/commands/dev-smoke-test.md +86 -510
  13. package/commands/extend-prd.md +89 -510
  14. package/commands/extend-prd.tmpl +3 -0
  15. package/commands/fix-bug.md +118 -509
  16. package/commands/generate-architecture.md +94 -515
  17. package/commands/generate-architecture.tmpl +3 -0
  18. package/commands/generate-bdd.md +85 -509
  19. package/commands/generate-code.md +86 -510
  20. package/commands/generate-design-spec.md +86 -510
  21. package/commands/generate-prd.md +89 -510
  22. package/commands/generate-prd.tmpl +3 -0
  23. package/commands/generate-spec-manifest.md +86 -510
  24. package/commands/generate-tech-docs.md +86 -510
  25. package/commands/learn.md +172 -496
  26. package/commands/learn.tmpl +70 -3
  27. package/commands/map-testids.md +86 -510
  28. package/commands/propose-scenario.md +86 -510
  29. package/commands/qc-analyze.md +86 -510
  30. package/commands/qc-design-test.md +86 -510
  31. package/commands/qc-plan.md +86 -510
  32. package/commands/qc-report.md +86 -510
  33. package/commands/qc-review.md +86 -510
  34. package/commands/qc-run-test.md +86 -510
  35. package/commands/refine-prd.md +99 -520
  36. package/commands/refine-prd.tmpl +3 -0
  37. package/commands/report-bug.md +86 -510
  38. package/commands/review-code.md +123 -511
  39. package/commands/review-code.tmpl +3 -0
  40. package/commands/review-context.md +93 -514
  41. package/commands/review-context.tmpl +3 -0
  42. package/commands/review-tech-docs.md +90 -511
  43. package/commands/review-tech-docs.tmpl +3 -0
  44. package/commands/setup-ai-first.md +166 -138
  45. package/commands/setup-ai-first.tmpl +72 -0
  46. package/commands/sync.md +50 -106
  47. package/commands/sync.tmpl +48 -3
  48. package/commands/update-framework.md +16 -103
  49. package/commands/update-framework.tmpl +14 -0
  50. package/commands/validate-traces.md +153 -511
  51. package/commands/validate-traces.tmpl +67 -1
  52. package/core/FRAMEWORK_VERSION +1 -1
  53. package/core/README.md +20 -0
  54. package/core/commands/debug.md +123 -511
  55. package/core/commands/define-product.md +86 -510
  56. package/core/commands/dev-gen-test.md +86 -510
  57. package/core/commands/dev-run-test.md +86 -510
  58. package/core/commands/dev-smoke-test.md +86 -510
  59. package/core/commands/extend-prd.md +89 -510
  60. package/core/commands/fix-bug.md +118 -509
  61. package/core/commands/generate-architecture.md +94 -515
  62. package/core/commands/generate-bdd.md +85 -509
  63. package/core/commands/generate-code.md +86 -510
  64. package/core/commands/generate-design-spec.md +86 -510
  65. package/core/commands/generate-prd.md +89 -510
  66. package/core/commands/generate-spec-manifest.md +86 -510
  67. package/core/commands/generate-tech-docs.md +86 -510
  68. package/core/commands/learn.md +172 -496
  69. package/core/commands/map-testids.md +86 -510
  70. package/core/commands/propose-scenario.md +86 -510
  71. package/core/commands/qc-analyze.md +86 -510
  72. package/core/commands/qc-design-test.md +86 -510
  73. package/core/commands/qc-plan.md +86 -510
  74. package/core/commands/qc-report.md +86 -510
  75. package/core/commands/qc-review.md +86 -510
  76. package/core/commands/qc-run-test.md +86 -510
  77. package/core/commands/refine-prd.md +99 -520
  78. package/core/commands/report-bug.md +86 -510
  79. package/core/commands/review-code.md +123 -511
  80. package/core/commands/review-context.md +93 -514
  81. package/core/commands/review-tech-docs.md +90 -511
  82. package/core/commands/setup-ai-first.md +166 -138
  83. package/core/commands/sync.md +50 -106
  84. package/core/commands/update-framework.md +16 -103
  85. package/core/commands/validate-traces.md +153 -511
  86. package/core/hooks/data-guard.js +174 -83
  87. package/core/hooks/settings.json +2 -1
  88. package/core/rules/workflow.md +30 -4
  89. package/core/steps/capture-lesson.md +34 -1
  90. package/core/steps/context-loader.md +24 -3
  91. package/core/steps/gate.md +92 -35
  92. package/core/steps/report-footer.md +23 -0
  93. package/core/templates/README.md +24 -1
  94. package/core/templates/ci/trace-gate.yml +146 -0
  95. package/core/templates/hooks/pre-push +61 -0
  96. package/docs/02-concepts/architecture.md +25 -6
  97. package/docs/02-concepts/traceability.md +57 -0
  98. package/docs/03-guides/architect.md +63 -0
  99. package/docs/04-reference/commands.md +1 -1
  100. package/docs/04-reference/model-selection.md +32 -19
  101. package/docs/explain/21-validate-traces.md +2 -1
  102. package/docs/explain/27-learn.md +5 -3
  103. package/hooks/data-guard.js +174 -83
  104. package/hooks/settings.json +2 -1
  105. package/package.json +5 -2
  106. package/rules/workflow.md +30 -4
  107. package/steps/capture-lesson.md +34 -1
  108. package/steps/context-loader.md +24 -3
  109. package/steps/gate.md +92 -35
  110. package/steps/report-footer.md +23 -0
  111. package/templates/README.md +24 -1
  112. package/templates/ci/trace-gate.yml +146 -0
  113. package/templates/hooks/pre-push +61 -0
  114. package/scripts/init.sh +0 -49
  115. package/scripts/upgrade.sh +0 -94
@@ -3,6 +3,9 @@
3
3
  Check read-only độ phủ giữa spec, code, và test — gồm cả PRD version drift.
4
4
 
5
5
  ## Gate
6
+
7
+ *Checkpoint: **không chặn** — read-only (ghi trace-report.json + TSV status, không đụng spec/code). Gate Bước 3 bỏ qua CHECKPOINT (Bước 3a).*
8
+
6
9
  {{include:steps/gate.md}}
7
10
 
8
11
  *Lưu ý: Với lệnh này, target ở Bước 1 là một tên domain hoặc UC-ID cụ thể từ `$ARGUMENTS`. Không có một file đơn để phân giải — lệnh quét nhiều thư mục.*
@@ -38,6 +41,44 @@ Kiểm tra mảng `services` có tồn tại trong `project-context.yaml` không
38
41
 
39
42
  ---
40
43
 
44
+ ### Step 1.0 — Lint sổ trace TRƯỚC khi đọc *(bắt buộc, không bỏ qua được)*
45
+
46
+ Chạy checker xác định trên mọi trace dir đã phân giải ở Step 0:
47
+
48
+ ```bash
49
+ npx @educa-corp/sdd-framework --lint-trace --trace {all_trace_dirs, ngăn cách bởi dấu phẩy} --specs {paths.specs_dir}
50
+ ```
51
+
52
+ *`bin/` sống trong package npm, không được cài vào project — nên `npx` là đường duy nhất. Không có mạng / npx fail → **bỏ qua step này**, in `⚠️ Chưa lint được sổ trace (npx không khả dụng) — kết quả dưới đây chưa được kiểm cấu trúc` vào report, rồi tiếp Step 1. Đừng để nó chặn cả lệnh.*
53
+
54
+ **Exit 0 → tiếp Step 1.**
55
+
56
+ **Exit 1 → DỪNG NGAY.** Đừng nạp, đừng tính `status`, đừng ghi lại gì:
57
+
58
+ ```
59
+ 🔴 SỔ TRACE HỎNG — không phán trạng thái trên dữ liệu này.
60
+
61
+ {nguyên văn output của lint-trace}
62
+
63
+ Vì sao dừng thay vì cố đọc tiếp: Step 3 tính lại `status` rồi Step 6 GHI NGƯỢC
64
+ vào TSV. Chạy tiếp trên một row đã lệch cột sẽ nướng cái lệch đó vào sổ vĩnh viễn —
65
+ và sổ trace là dữ liệu KHÔNG regenerate được.
66
+
67
+ Sửa:
68
+ 1. Xem lần ghi nào làm hỏng : git log -p {file}
69
+ 2. Sửa file (thường là thêm/bớt một dấu tab, hoặc giữ cả hai row sau merge)
70
+ 3. Kiểm lại : npx @educa-corp/sdd-framework --lint-trace
71
+ 4. Rồi chạy lại /validate-traces
72
+ ```
73
+
74
+ > **Vì sao step này tồn tại (G38):** `bin/self-check.js` canh **contract** — nó đọc file lệnh
75
+ > và kiểm "lệnh có gọi đúng tên cột không". Nó không bao giờ mở một `.tsv` thật. Trong khi sổ
76
+ > 24 cột được ghi **bằng tay**, hàng chục lần mỗi feature. Một dấu tab thiếu ở ô 17 dồn mọi ô
77
+ > sau đó sang trái một bậc — ô 21 `status` nhận một ngày tháng — và **trước step này không gì
78
+ > báo lỗi**: lệnh đọc tiếp, in ra số, số chảy vào `trace-report.json` rồi vào dashboard.
79
+
80
+ ---
81
+
41
82
  ### Step 1 — Nạp dữ liệu TSV
42
83
 
43
84
  **Umbrella mode:** đọc tất cả file `{trace_dir}/**/*.tsv` từ mọi dir trong `all_trace_dirs`. Với mỗi TSV, gắn tag row với tên service gốc.
@@ -303,6 +344,19 @@ by_service = map {service → {total_scs, coded_scs, tested_scs, drift_cou
303
344
  # Trả lời câu số MỘT của dự án nhiều đội: "đội nào còn bao nhiêu việc".
304
345
  # Trước khi có cột 23, trace gộp (spec_source) KHÔNG mang thông tin sở hữu ở
305
346
  # cấp row nên câu này không trả lời được. Bỏ qua map này ở single-service.
347
+ by_platform = map {platform → {total_scs, coded_scs, tested_scs, drift_count}} — gom theo
348
+ platform (lấy từ TÊN FILE sổ `{UC-ID}-{platform}.tsv`, cùng nguồn với field
349
+ `platform` của mỗi scenario ở Step 8)
350
+ # CHỈ tạo ô cho platform THỰC SỰ có scenario — dự án chỉ có `web` thì chỉ một ô.
351
+ # Trả lời "web xong bao nhiêu %, system xong bao nhiêu %" — câu thường ngày khi
352
+ # làm FE và BE song song. Trước đó KHÔNG trả lời được từ `summary`: `by_service`
353
+ # là bảng chia nhóm DUY NHẤT, mà cột `service` là `—` ở mọi row của dự án
354
+ # single-service ⇒ nó gộp tất cả vào MỘT ô, và platform hoàn toàn vô hình.
355
+ # Đây là hình dạng của G33: dữ liệu có ở cấp row (G48 vừa thêm `platform` vào
356
+ # từng scenario) nhưng KHÔNG có ô tổng ⇒ dashboard chỉ đọc `summary` thì mù.
357
+ # Bắt dashboard tự duyệt prds[].ucs[].scenarios[] mà cộng lại chính là cái bẫy
358
+ # G33 đã chỉ ra: người viết dashboard đọc `summary`, thấy đủ, rồi tưởng xong.
359
+ # KHÔNG thay `by_service` — hai TRỤC khác nhau, cùng hữu ích ở umbrella nhiều đội.
306
360
  seam_unwired_count = số seam bị cờ SEAM_UNWIRED (hàng thật đã có nhưng consumer còn wire vào stub — Step 5b)
307
361
  seam_pending_count = số seam bị cờ SEAM_PENDING (owner UC chưa gen — ⓘ chưa phải lỗi; PM dùng để xếp thứ tự gen)
308
362
  stub_unresolved_count = số stub bị cờ STUB_UNRESOLVED (method còn trắng dù owner đã gen / có hàm song song — Step 5b)
@@ -396,6 +450,11 @@ Schema:
396
450
  "<service path, e.g. user-service>": {
397
451
  "total_scs": 0, "coded_scs": 0, "tested_scs": 0, "drift_count": 0
398
452
  }
453
+ },
454
+ "by_platform": {
455
+ "<web | app | system — CHỈ platform thực sự có scenario>": {
456
+ "total_scs": 0, "coded_scs": 0, "tested_scs": 0, "drift_count": 0
457
+ }
399
458
  }
400
459
  },
401
460
  "prds": [
@@ -415,6 +474,7 @@ Schema:
415
474
  "scenarios": [
416
475
  {
417
476
  "sc_id": "<e.g. PAY-UC01-SC1>",
477
+ "platform": "web | app | system",
418
478
  "sc_title": "<title>",
419
479
  "spec_ver": "<current version from .feature>",
420
480
  "gen_ver": "<version at codegen time>",
@@ -596,6 +656,11 @@ Schema:
596
656
  ```
597
657
 
598
658
  **Rules:**
659
+ - **`by_platform` là bắt buộc** (nếu có ít nhất một scenario). Cùng hình dạng `by_service`, khoá **động** — một ô cho mỗi platform tìm thấy, không phải một ô cố định cho mỗi giá trị vocabulary. Thêm platform thứ tư vào vocabulary thì nó tự có ô, không cần sửa gì ở đây.
660
+ > Đây là lý do `by_platform` **không cần** một rule `self-check` riêng: khác cờ audit (mỗi cờ cần một counter mang tên riêng, nên R7 phải canh từng cái), ở đây không có gì để lệch.
661
+ - **`platform` (bắt buộc, mỗi scenario):** lấy từ **tên file sổ** `{UC-ID}-{platform}.tsv` — Step 2 đã đọc nó để tìm đúng `.feature`. Giá trị: `web` | `app` | `system`.
662
+ > **Vì sao bắt buộc (G48):** `sc_id` **một mình không định danh được** một scenario. Chính Step 2 phát biểu điều đó: *"sc_id trùng số giữa các platform là 2 scenario khác nhau"*. Sổ TSV giải quyết bằng tên file; JSON thì làm phẳng mọi platform vào chung một cây `scenarios[]`, nên thiếu field này thì `AUTH-UC1-SC1` của web và của app **không phân biệt được** — panel hiện trùng lặp hoặc đè nhau, và không ai trả lời được *"SC1 của app xong chưa"*.
663
+ > Bất đối xứng cũ: `issues.orphaned[]` và `issues.fe_techdoc_drift[]` **đã** mang `platform`; chỉ cây dữ liệu chính là không.
599
664
  - `implemented_by`: dùng `null` (không phải `"—"`) trong JSON khi không có giá trị
600
665
  - `test_count`: dùng integer `0` (không phải `"—"`) khi không có test
601
666
  - `test_classes`: dùng `[]` (không phải `"—"`) khi không có test class
@@ -671,11 +736,12 @@ mỗi scenario row mang service sở hữu ở **cột `service`** (cột 23, do
671
736
 
672
737
  **Rotate:** file vượt **2000 dòng** → đổi tên thành `trace-history.{YYYY-MM}.jsonl` rồi bắt đầu file mới. Đừng xoá.
673
738
 
674
- **Bốn ràng buộc — đây là phần dễ làm sai:**
739
+ **Năm ràng buộc — đây là phần dễ làm sai:**
675
740
 
676
741
  | Ràng buộc | Vì sao |
677
742
  |---|---|
678
743
  | Ghi **CHỈ** vào `{paths.trace_dir}` (nơi authoritative). **KHÔNG** copy sang `{panel_mirror}` hay `{living_docs_dir}` | Nó là dữ liệu tích luỹ, không phải thứ regenerate được. Nhân bản nó ra chỗ sinh-ra là tạo hai lịch sử lệch nhau. |
744
+ | Dòng vừa append **PHẢI kết thúc bằng newline** — file không bao giờ được kết thúc giữa dòng | File này là append-only và được merge bằng `merge=union` (xem `{paths.trace_dir}/.gitattributes`). Thiếu newline cuối thì lần append sau — hoặc một lần union merge — **nối hai bản ghi JSON thành một dòng**, và dòng đó không parse được. `--lint-trace` T8 bắt, nhưng đây là ca phòng được bằng một ký tự. |
679
745
  | File này **PHẢI được commit** cùng TSV | Nó là **dữ liệu**, không phải mirror. Regenerate lại không được — mất là mất vĩnh viễn. ⚠️ Đừng để nó dính vào luật gitignore của `.living-docs/` hay panel mirror; hai cái đó là bản sinh ra, cái này thì không. |
680
746
  | **Không đụng** TSV và `trace-report.json` | TSV là bảng **trạng thái** — giữ nó phẳng. Lịch sử là file riêng, format riêng, vòng đời riêng. `trace-report.json` là contract với panel VS Code. |
681
747
  | **Không lệnh nào được ra quyết định dựa trên file này** | Nó để **quan sát**, không phải để gác cổng. Một cái cổng phụ thuộc file có thể bị xoá là cổng dở. Cổng chặn PR vẫn chỉ là 4 cờ 🔴. |
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
package/core/README.md CHANGED
@@ -29,6 +29,26 @@ Từ v0.4.2, `--init` **phát hiện và cứu** các file đó:
29
29
  - Danh sách file bị ghi đè được in ra ngay sau bước cài
30
30
  - `.agent/.install-manifest.json` ghi hash của đúng những gì lần cài trước đã ghi — nhờ đó lệnh phân biệt được **bạn sửa file** với **framework tự đổi file giữa hai version** (một phép so nội dung thuần sẽ flag cả hai, và mỗi lần nâng cấp lại báo oan hàng chục file)
31
31
 
32
+ ## Nâng cấp cũng GỠ file, không chỉ thêm
33
+
34
+ Từ v0.5.1, `--init` gỡ những file framework **không còn ship** — trước đó nó chỉ copy, nên một
35
+ lệnh bị bỏ ở version mới nằm lại trong `.agent/commands/` và `.claude/commands/` **vĩnh viễn**:
36
+ vẫn hiện trong menu `/`, vẫn chạy được, vẫn mang logic version cũ, kể cả khi framework đã bỏ nó
37
+ *vì nó sai*.
38
+
39
+ Một file chỉ bị gỡ khi **cả ba** đúng:
40
+
41
+ 1. có trong manifest lần cài trước → do framework đặt vào, không phải bạn tạo
42
+ 2. không còn trong bản mới → framework đã bỏ
43
+ 3. hash khớp manifest → **còn nguyên bản**, gỡ đi không mất gì
44
+
45
+ Đúng (1)+(2) mà **bạn đã sửa** file đó → **giữ lại** + backup + báo ra. Thà để lại một file lạc
46
+ còn hơn xoá thứ ai đó đã bỏ công viết.
47
+
48
+ `.claude/commands/` cũng được quản như vậy — cộng thêm: nếu project bạn **đã có sẵn** một slash
49
+ command trùng tên (`/debug`, `/sync`, `/learn` là những cái hay trùng), bản cũ của nó được backup
50
+ vào `.agent/.overwritten-{YYYYMMDD}-shortcuts/` và bạn được báo, thay vì bị đè im lặng.
51
+
32
52
  Nên thêm vào `.gitignore` của project:
33
53
 
34
54
  ```gitignore