@educa-corp/sdd-framework 0.6.0 → 0.7.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 (223) hide show
  1. package/bin/gate-trace.js +25 -2
  2. package/bin/index.js +32 -5
  3. package/bin/lint-trace.js +41 -0
  4. package/bin/self-check.js +430 -3
  5. package/bin/trace-schema.json +418 -31
  6. package/core/FRAMEWORK_VERSION +1 -1
  7. package/{commands/extend-prd.md → core/commands/amend-prd.md} +206 -173
  8. package/core/commands/dev-run-test.md +48 -10
  9. package/core/commands/extend-prd.md +39 -12
  10. package/core/commands/generate-bdd.md +52 -10
  11. package/core/commands/generate-code.md +35 -2
  12. package/core/commands/generate-tech-docs.md +36 -4
  13. package/core/commands/map-testids.md +1 -1
  14. package/core/commands/qc-run-test.md +29 -3
  15. package/core/commands/refine-prd.md +13 -2
  16. package/core/commands/review-context.md +43 -8
  17. package/core/commands/sync.md +105 -1
  18. package/core/commands/validate-traces.md +289 -16
  19. package/core/rules/workflow.md +34 -0
  20. package/core/steps/context-loader.md +27 -6
  21. package/core/templates/feature.template +1 -1
  22. package/core/templates/project-context.yaml +3 -3
  23. package/core/templates/tech-design.template.md +2 -2
  24. package/docs/02-concepts/architecture.md +37 -1
  25. package/docs/02-concepts/overview.md +1 -1
  26. package/docs/02-concepts/pipeline-steps/02-specification.md +13 -7
  27. package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +2 -0
  28. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +1 -0
  29. package/docs/02-concepts/pipeline-steps/09-validate-traces.md +34 -3
  30. package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +10 -1
  31. package/docs/02-concepts/traceability.md +187 -183
  32. package/docs/03-guides/architect.md +13 -4
  33. package/docs/03-guides/developer.md +1 -0
  34. package/docs/03-guides/product-owner.md +89 -72
  35. package/docs/03-guides/tester-qa.md +81 -81
  36. package/docs/04-reference/commands.md +148 -134
  37. package/docs/04-reference/trace-schema.md +45 -1
  38. package/docs/explain/02b-extend-prd.md +1 -1
  39. package/docs/explain/02c-amend-prd.md +152 -0
  40. package/docs/explain/06-generate-bdd.md +1 -1
  41. package/docs/explain/13-dev-run-test.md +15 -1
  42. package/docs/explain/19-qc-run-test.md +91 -87
  43. package/docs/explain/21-validate-traces.md +79 -75
  44. package/docs/explain/28-sync.md +25 -0
  45. package/docs/explain/README.md +136 -135
  46. package/package.json +1 -8
  47. package/commands/debug.md +0 -529
  48. package/commands/debug.tmpl +0 -260
  49. package/commands/define-product.md +0 -438
  50. package/commands/define-product.tmpl +0 -225
  51. package/commands/dev-gen-test.md +0 -700
  52. package/commands/dev-gen-test.tmpl +0 -490
  53. package/commands/dev-run-test.md +0 -435
  54. package/commands/dev-run-test.tmpl +0 -225
  55. package/commands/dev-smoke-test.md +0 -374
  56. package/commands/dev-smoke-test.tmpl +0 -217
  57. package/commands/extend-prd.tmpl +0 -273
  58. package/commands/fix-bug.md +0 -519
  59. package/commands/fix-bug.tmpl +0 -197
  60. package/commands/generate-architecture.md +0 -354
  61. package/commands/generate-architecture.tmpl +0 -197
  62. package/commands/generate-bdd.md +0 -923
  63. package/commands/generate-bdd.tmpl +0 -590
  64. package/commands/generate-code.md +0 -859
  65. package/commands/generate-code.tmpl +0 -649
  66. package/commands/generate-design-spec.md +0 -737
  67. package/commands/generate-design-spec.tmpl +0 -524
  68. package/commands/generate-prd.md +0 -722
  69. package/commands/generate-prd.tmpl +0 -226
  70. package/commands/generate-spec-manifest.md +0 -321
  71. package/commands/generate-spec-manifest.tmpl +0 -164
  72. package/commands/generate-tech-docs.md +0 -920
  73. package/commands/generate-tech-docs.tmpl +0 -273
  74. package/commands/learn.md +0 -399
  75. package/commands/learn.tmpl +0 -130
  76. package/commands/map-testids.md +0 -238
  77. package/commands/map-testids.tmpl +0 -81
  78. package/commands/propose-scenario.md +0 -359
  79. package/commands/propose-scenario.tmpl +0 -202
  80. package/commands/qc-analyze.md +0 -269
  81. package/commands/qc-analyze.tmpl +0 -112
  82. package/commands/qc-design-test.md +0 -226
  83. package/commands/qc-design-test.tmpl +0 -69
  84. package/commands/qc-plan.md +0 -206
  85. package/commands/qc-plan.tmpl +0 -49
  86. package/commands/qc-report.md +0 -217
  87. package/commands/qc-report.tmpl +0 -60
  88. package/commands/qc-review.md +0 -210
  89. package/commands/qc-review.tmpl +0 -53
  90. package/commands/qc-run-test.md +0 -326
  91. package/commands/qc-run-test.tmpl +0 -116
  92. package/commands/refine-prd.md +0 -653
  93. package/commands/refine-prd.tmpl +0 -281
  94. package/commands/report-bug.md +0 -305
  95. package/commands/report-bug.tmpl +0 -148
  96. package/commands/review-code.md +0 -415
  97. package/commands/review-code.tmpl +0 -146
  98. package/commands/review-context.md +0 -902
  99. package/commands/review-context.tmpl +0 -530
  100. package/commands/review-tech-docs.md +0 -561
  101. package/commands/review-tech-docs.tmpl +0 -404
  102. package/commands/setup-ai-first.md +0 -602
  103. package/commands/setup-ai-first.tmpl +0 -450
  104. package/commands/sync.md +0 -430
  105. package/commands/sync.tmpl +0 -429
  106. package/commands/update-framework.md +0 -203
  107. package/commands/update-framework.tmpl +0 -202
  108. package/commands/validate-traces.md +0 -1077
  109. package/commands/validate-traces.tmpl +0 -920
  110. package/hooks/data-guard.js +0 -232
  111. package/hooks/settings.json +0 -19
  112. package/modules/android-compose/module.yaml +0 -13
  113. package/modules/android-compose/stack-profile.yaml +0 -57
  114. package/modules/angular/architecture-snippets/component-patterns.md +0 -187
  115. package/modules/angular/module.yaml +0 -6
  116. package/modules/angular/stack-profile.yaml +0 -38
  117. package/modules/context-engineering/architecture-snippets/context-design.md +0 -119
  118. package/modules/context-engineering/module.yaml +0 -9
  119. package/modules/context-engineering/stack-profile.yaml +0 -61
  120. package/modules/dotnet/architecture-snippets/clean-arch.md +0 -160
  121. package/modules/dotnet/module.yaml +0 -6
  122. package/modules/dotnet/stack-profile.yaml +0 -50
  123. package/modules/flutter/module.yaml +0 -14
  124. package/modules/flutter/stack-profile.yaml +0 -59
  125. package/modules/golang/architecture-snippets/domain-layout.md +0 -283
  126. package/modules/golang/module.yaml +0 -6
  127. package/modules/golang/stack-profile.yaml +0 -40
  128. package/modules/ios-swiftui/module.yaml +0 -13
  129. package/modules/ios-swiftui/stack-profile.yaml +0 -55
  130. package/modules/java-spring/architecture-snippets/layered-arch.md +0 -201
  131. package/modules/java-spring/module.yaml +0 -15
  132. package/modules/java-spring/stack-profile.yaml +0 -28
  133. package/modules/nextjs/architecture-snippets/app-router-patterns.md +0 -269
  134. package/modules/nextjs/module.yaml +0 -14
  135. package/modules/nextjs/stack-profile.yaml +0 -74
  136. package/modules/nuxt/module.yaml +0 -14
  137. package/modules/nuxt/stack-profile.yaml +0 -58
  138. package/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +0 -646
  139. package/modules/phaser-game/module.yaml +0 -15
  140. package/modules/phaser-game/stack-profile.yaml +0 -90
  141. package/modules/php-laravel/architecture-snippets/service-repository.md +0 -302
  142. package/modules/php-laravel/module.yaml +0 -15
  143. package/modules/php-laravel/stack-profile.yaml +0 -56
  144. package/modules/qc-playwright/stack-profile.yaml +0 -66
  145. package/modules/react/architecture-snippets/hooks-query-patterns.md +0 -254
  146. package/modules/react/module.yaml +0 -14
  147. package/modules/react/stack-profile.yaml +0 -63
  148. package/modules/react-native/module.yaml +0 -14
  149. package/modules/react-native/stack-profile.yaml +0 -56
  150. package/modules/vue/module.yaml +0 -14
  151. package/modules/vue/stack-profile.yaml +0 -65
  152. package/rules/data-protection.md +0 -80
  153. package/rules/workflow.md +0 -99
  154. package/skills/code/SKILL.md +0 -19
  155. package/skills/code/SKILL.tmpl +0 -19
  156. package/skills/debug/SKILL.md +0 -19
  157. package/skills/debug/SKILL.tmpl +0 -19
  158. package/skills/design-spec/SKILL.md +0 -11
  159. package/skills/design-spec/SKILL.tmpl +0 -11
  160. package/skills/discovery/SKILL.md +0 -14
  161. package/skills/discovery/SKILL.tmpl +0 -14
  162. package/skills/prd/SKILL.md +0 -19
  163. package/skills/prd/SKILL.tmpl +0 -19
  164. package/skills/qc/qa-analyst/DOC_GAPS.template.md +0 -63
  165. package/skills/qc/qa-analyst/acceptance-criteria.md +0 -60
  166. package/skills/qc/qa-analyst/business-rules.md +0 -59
  167. package/skills/qc/qa-analyst/data-flow.md +0 -64
  168. package/skills/qc/qa-analyst/spec-breakdown.md +0 -61
  169. package/skills/qc/qa-designer/e2e/journey.md +0 -41
  170. package/skills/qc/qa-designer/exploratory/charter.md +0 -68
  171. package/skills/qc/qa-designer/exploratory/explore-to-functional.md +0 -43
  172. package/skills/qc/qa-designer/functional/api.md +0 -45
  173. package/skills/qc/qa-designer/functional/gui-feature.md +0 -46
  174. package/skills/qc/qa-designer/functional/gui-screen.md +0 -52
  175. package/skills/qc/qa-designer/integration/api.md +0 -42
  176. package/skills/qc/qa-designer/integration/db.md +0 -39
  177. package/skills/qc/qa-designer/integration/gui.md +0 -40
  178. package/skills/qc/qa-designer/integration/kafka.md +0 -40
  179. package/skills/qc/qa-designer/non-functional.md +0 -40
  180. package/skills/qc/qa-planner/test-plan.md +0 -120
  181. package/skills/qc/qa-reviewer/script/e2e.md +0 -87
  182. package/skills/qc/qa-reviewer/script/exploratory.md +0 -45
  183. package/skills/qc/qa-reviewer/script/functional.md +0 -101
  184. package/skills/qc/qa-reviewer/script/integration.md +0 -91
  185. package/skills/qc/qa-reviewer/script/non-functional.md +0 -126
  186. package/skills/qc/qa-reviewer/test-case/e2e.md +0 -73
  187. package/skills/qc/qa-reviewer/test-case/exploratory.md +0 -43
  188. package/skills/qc/qa-reviewer/test-case/functional.md +0 -76
  189. package/skills/qc/qa-reviewer/test-case/integration.md +0 -69
  190. package/skills/qc/qa-reviewer/test-case/non-functional.md +0 -73
  191. package/skills/qc/qa-runner/e2e.md +0 -49
  192. package/skills/qc/qa-runner/exploratory/session.md +0 -36
  193. package/skills/qc/qa-runner/functional/api.md +0 -35
  194. package/skills/qc/qa-runner/functional/gui-feature.md +0 -51
  195. package/skills/qc/qa-runner/functional/gui-screen.md +0 -55
  196. package/skills/qc/qa-runner/integration.md +0 -47
  197. package/skills/qc/qa-runner/non-functional.md +0 -49
  198. package/skills/qc/qa-runner/report/report.md +0 -37
  199. package/skills/setup-ai-first/SKILL.md +0 -19
  200. package/skills/setup-ai-first/SKILL.tmpl +0 -19
  201. package/skills/spec/SKILL.md +0 -19
  202. package/skills/spec/SKILL.tmpl +0 -19
  203. package/skills/test/SKILL.md +0 -18
  204. package/skills/test/SKILL.tmpl +0 -18
  205. package/steps/business-language.md +0 -56
  206. package/steps/capture-lesson.md +0 -112
  207. package/steps/context-loader.md +0 -406
  208. package/steps/gate.md +0 -151
  209. package/steps/report-footer.md +0 -125
  210. package/steps/review-fanout.md +0 -159
  211. package/steps/spawn-agent.md +0 -129
  212. package/steps/trace-mirror.md +0 -53
  213. package/templates/README.md +0 -70
  214. package/templates/architecture.template.md +0 -394
  215. package/templates/ci/trace-gate.yml +0 -146
  216. package/templates/design-spec.template.md +0 -217
  217. package/templates/feature.template +0 -123
  218. package/templates/hooks/pre-push +0 -61
  219. package/templates/platform-guide.template.md +0 -145
  220. package/templates/prd.template.md +0 -283
  221. package/templates/product-definition.template.md +0 -188
  222. package/templates/project-context.yaml +0 -212
  223. package/templates/tech-design.template.md +0 -490
@@ -1,70 +0,0 @@
1
- # templates/ — build-time skeletons
2
-
3
- > **Nếu bạn đang mở thư mục này ở `.agent/templates/` trong một project: sửa file ở đây KHÔNG có tác dụng.**
4
-
5
- ## Vì sao
6
-
7
- Các skeleton trong thư mục này được `{{include}}` **nướng cứng vào file lệnh lúc `npm run build`**:
8
-
9
- ```
10
- templates/feature.template
11
- ↓ {{include:templates/feature.template}} ← bin/build.js, thay thế văn bản lúc build
12
- commands/generate-bdd.md
13
- ↓ copy vào core/ → mirror sang .agent/
14
- .agent/commands/generate-bdd.md ← LỆNH THẬT SỰ CHẠY (đã chứa sẵn skeleton)
15
- .agent/templates/feature.template ← bản tham khảo, KHÔNG lệnh nào đọc
16
- ```
17
-
18
- Không lệnh nào đọc một path template lúc chạy. `paths.feature_template` / `paths.prd_template` từng tồn tại trong `project-context.yaml` nhưng chưa bao giờ có tác dụng — đã được gỡ bỏ (xem `GAPS.md` G9).
19
-
20
- **Thêm nữa:** `.agent/` là vùng bị ghi đè. `/update-framework` chạy `npx … --init`, và `--init` copy `core/` → `.agent/` **vô điều kiện** (`bin/index.js` → `installCore`). File duy nhất được giữ lại là `.agent/project-context.yaml`. Nên mọi chỉnh sửa ở `.agent/templates/` sẽ **biến mất** ở lần nâng cấp kế tiếp — từ v0.4.2 thì không còn im lặng: bản cũ được lưu vào `.agent/.overwritten-{version}-{date}/` và được liệt kê ra (`GAPS.md` G24). Nhưng vẫn phải áp lại bằng tay mỗi version, nên đây không phải chỗ để đặt thay đổi.
21
-
22
- ---
23
-
24
- ## Ngoại lệ: `ci/` và `hooks/` — template để COPY RA, không phải để build
25
-
26
- Hai thư mục này **không** giống phần còn lại của `templates/`. Chúng không được `{{include}}` vào lệnh nào, và **không** được đọc lúc chạy. Chúng là file **hoàn chỉnh, dùng ngay**, chờ một người copy ra khỏi `.agent/`:
27
-
28
- | File | Copy tới | Làm gì |
29
- |---|---|---|
30
- | `ci/trace-gate.yml` | `.github/workflows/` của project | Chặn PR khi trace có cờ 🔴 (`--gate-trace`) |
31
- | `hooks/pre-push` | `.git/hooks/pre-push` (rồi `chmod +x`) | Chặn push khi sổ trace hỏng cấu trúc (`--lint-trace`) |
32
-
33
- ```bash
34
- # từ gốc project
35
- mkdir -p .github/workflows && cp .agent/templates/ci/trace-gate.yml .github/workflows/
36
- cp .agent/templates/hooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push
37
- ```
38
-
39
- **Phải copy RA, không dùng tại chỗ** — vì đúng cái lý do cả file README này nói: `.agent/` bị ghi đè mỗi lần nâng cấp, và `.git/hooks/` thì git không bao giờ chạy từ chỗ khác. Copy ra rồi thì chúng là file của project: sửa tuỳ ý, nâng cấp framework không đụng tới.
40
-
41
- Vì sao chúng tồn tại → `GAPS-v3.md` G39: framework phát hiện được một lớp lỗi mà build xanh + test xanh không thấy, nhưng trước đó việc phát hiện phụ thuộc vào có người tự nguyện chạy một lệnh chat. Hai file này là chỗ nó chặn bằng máy.
42
-
43
- ## Muốn đổi cấu trúc artifact sinh ra thì làm gì
44
-
45
- Sửa file trong **repo framework** rồi build lại:
46
-
47
- ```bash
48
- # trong repo sdd-framework
49
- vim templates/feature.template # hoặc prd.template.md, tech-design.template.md, …
50
- npm run build # inline lại vào commands/*.md + core/ + .agent/
51
- ```
52
-
53
- Rồi phát hành version mới; project chạy `/update-framework` để nhận.
54
-
55
- ## File nào ở đây đi vào đâu
56
-
57
- | Template | Được include vào | Trở thành |
58
- |---|---|---|
59
- | `feature.template` | `commands/generate-bdd.tmpl` | mỗi file `.feature` |
60
- | `prd.template.md` | `commands/generate-prd.tmpl` | mỗi PRD |
61
- | `tech-design.template.md` | `commands/generate-tech-docs.tmpl` | tech-doc gộp / PRD |
62
- | `design-spec.template.md` | `commands/generate-design-spec.tmpl` | design-spec / platform |
63
- | `architecture.template.md` | `commands/generate-architecture.tmpl` | tài liệu kiến trúc |
64
- | `product-definition.template.md` | `commands/define-product.tmpl` | product definition |
65
- | `platform-guide.template.md` | (tham khảo) | — |
66
- | `project-context.yaml` | **không** include — được copy thẳng làm file config khởi tạo | `.agent/project-context.yaml` |
67
- | `ci/trace-gate.yml` | **không** include — người dùng copy ra | `.github/workflows/trace-gate.yml` |
68
- | `hooks/pre-push` | **không** include — người dùng copy ra | `.git/hooks/pre-push` |
69
-
70
- > Lưu ý `project-context.yaml` là ngoại lệ duy nhất: nó **được** copy ra làm file thật của project, và **được bảo vệ** khỏi ghi đè khi nâng cấp (chỉ tạo nếu chưa tồn tại).
@@ -1,394 +0,0 @@
1
- ---
2
- last_verified: {{YYYY-MM-DD}}
3
- verified_by: {{AUTHOR}}
4
- ---
5
-
6
- # {{SYSTEM_NAME}} — Bối cảnh Kiến trúc (Architecture Context)
7
-
8
- > Nguồn chân lý duy nhất (single source of truth) về kiến trúc hệ thống — phục vụ cả bối cảnh sinh code (AI agents) lẫn các vấn đề vận hành (triển khai, CI/CD, NFR).
9
- >
10
- > HƯỚNG DẪN DÙNG TEMPLATE:
11
- > - Điền các `{{PLACEHOLDER}}`, xoá comment hướng dẫn (`<!-- ... -->`) sau khi điền.
12
- > - Không cần điền tay: nên chạy `/generate-architecture` để tự hút từ config/tài liệu/code + phỏng vấn, rồi con người verify.
13
- >
14
- > PHÂN TẦNG (tier) — mỗi mục có marker `<!-- tier: core|conditional|ops -->`:
15
- > - **core** — luôn điền. Kiến trúc nền mà mọi feature cần.
16
- > - **conditional** — chỉ giữ nếu hệ thống thực sự có (multi-tenant, message bus, sharding…). Không dùng → để dạng STUB hoặc xoá hẳn.
17
- > - **ops** — vận hành, chỉ để người đọc. AI **KHÔNG** nạp khi sinh code/tech-design.
18
- >
19
- > ĐIỀN DẦN: không phải điền hết một lần. Mục chưa làm để dạng STUB rồi lấp sau bằng `/generate-architecture --section=<slug>`:
20
- > ```
21
- > ## Multi-tenant <!-- tier: conditional --> <!-- status: stub -->
22
- > > ⏳ Chưa tài liệu hoá. Chạy `/generate-architecture --section=multi-tenant` khi cần, hoặc điền tay.
23
- > ```
24
-
25
- <!-- ════════════════════ CORE (luôn điền) ════════════════════ -->
26
-
27
- ## Công nghệ sử dụng (Tech Stack) <!-- tier: core -->
28
-
29
- | Tầng | Công nghệ | Phiên bản / Ghi chú |
30
- |---|---|---|
31
- | Backend | {{BACKEND_TECH}} | {{VERSION}} |
32
- | Frontend | {{FRONTEND_TECH}} | {{VERSION}} |
33
- | ORM / Truy cập dữ liệu | {{ORM}} | {{VERSION}} |
34
- | Database | {{DATABASE}} | {{PRIMARY_STORE_NOTE}} |
35
- | Caching | {{CACHE}} | {{CACHE_NOTE}} |
36
- | Event Bus / Messaging | {{MESSAGING}} | {{MESSAGING_NOTE}} |
37
- | API Gateway | {{GATEWAY}} | {{GATEWAY_NOTE}} |
38
- | Kiểm thử | {{TEST_STACK}} | {{TEST_NOTE}} |
39
- <!-- Thêm/bớt dòng theo thực tế. Cột Ghi chú nên ghi ràng buộc cụ thể AI cần biết (vd: "dùng cho mọi màn hình list", "thư viện private wrapper"). -->
40
-
41
- ## Các tầng kiến trúc (Architecture Layers) <!-- tier: core -->
42
-
43
- Kiểu kiến trúc: `{{ARCH_STYLE}}` <!-- vd: Layered / Clean / Hexagonal / Component-based -->
44
-
45
- ```
46
- {{LAYER_DIAGRAM}}
47
- ```
48
- <!-- Ví dụ Clean Architecture:
49
- ┌──────────────────────────────────────┐
50
- │ Presentation │ Controllers, Middleware
51
- ├──────────────────────────────────────┤
52
- │ Application │ Use Cases, DTOs, Interfaces
53
- ├──────────────────────────────────────┤
54
- │ Domain │ Entities, Value Objects, Events
55
- ├──────────────────────────────────────┤
56
- │ Infrastructure │ ORM, Cache, Messaging
57
- └──────────────────────────────────────┘
58
- -->
59
-
60
- ### Chiều phụ thuộc
61
- - {{OUTER}} → {{MIDDLE}} → {{INNER}} ← {{INFRASTRUCTURE}}
62
- - {{INNER_LAYER}} có **zero** phụ thuộc ngoài.
63
- - Infrastructure hiện thực các interface do Application/Domain định nghĩa.
64
- - Tầng trong KHÔNG được phụ thuộc tầng ngoài.
65
-
66
- ## Quy ước đặt tên <!-- tier: core -->
67
-
68
- | Thành phần | Quy ước | Ví dụ |
69
- |---|---|---|
70
- | Entity | {{ENTITY_CONV}} | {{EXAMPLE}} |
71
- | Value Object | {{VO_CONV}} | {{EXAMPLE}} |
72
- | Interface | {{INTERFACE_CONV}} | {{EXAMPLE}} |
73
- | Use Case Command | {{COMMAND_CONV}} | {{EXAMPLE}} |
74
- | Use Case Query | {{QUERY_CONV}} | {{EXAMPLE}} |
75
- | Handler | {{HANDLER_CONV}} | {{EXAMPLE}} |
76
- | DTO | {{DTO_CONV}} | {{EXAMPLE}} |
77
- | Controller | {{CONTROLLER_CONV}} | {{EXAMPLE}} |
78
- | DI Extension | {{DI_EXT_CONV}} | {{EXAMPLE}} |
79
- | Class test | {{TEST_CLASS_CONV}} | {{EXAMPLE}} |
80
- | Method test | {{TEST_METHOD_CONV}} | {{EXAMPLE}} |
81
-
82
- > Quy ước đặt tên của frontend / từng repo → xem `.ai-project-guide.md` tương ứng.
83
-
84
- ## Định dạng response API chuẩn <!-- tier: core -->
85
-
86
- ```{{LANG}}
87
- // Thành công
88
- {{SUCCESS_WRAPPER}}
89
- → {{SUCCESS_JSON_SHAPE}}
90
-
91
- // Thất bại
92
- {{FAILURE_WRAPPER}}
93
- → {{FAILURE_JSON_SHAPE}}
94
- ```
95
-
96
- ## Quy ước API <!-- tier: core -->
97
-
98
- | Khía cạnh | Quy ước |
99
- |---|---|
100
- | Base URL | {{BASE_URL}} |
101
- | Versioning | {{VERSIONING}} <!-- vd: URL path /v1/, theo header, query param --> |
102
- | Đặt tên URL | {{URL_NAMING}} <!-- vd: kebab-case --> |
103
- | Phân trang | {{PAGINATION}} <!-- vd: ?page=1&pageSize=20 → meta{...} --> |
104
- | Lọc | {{FILTERING}} |
105
- | Sắp xếp | {{SORTING}} |
106
- | Định dạng ngày | {{DATE_FORMAT}} <!-- vd: ISO 8601 --> |
107
- | Ngừng hỗ trợ (Deprecation) | {{DEPRECATION_POLICY}} |
108
-
109
- ### Các endpoint chính theo service <!-- [TUỲ CHỌN] -->
110
-
111
- | Service | Endpoints |
112
- |---|---|
113
- | {{SERVICE}} | {{ENDPOINTS}} |
114
-
115
- > Tài liệu API đầy đủ: {{API_DOCS_LOCATION}} <!-- vd: /swagger cho mỗi service -->
116
-
117
- ## Quy ước Database <!-- tier: core -->
118
-
119
- - **Migration**: {{MIGRATION_STRATEGY}} <!-- vd: code-first mỗi service -->
120
- - **Đặt tên**: {{DB_NAMING}} <!-- vd: PascalCase cho entity, snake_case cho cột -->
121
- - **Soft Delete**: {{SOFT_DELETE_RULE}}
122
- - **Cột audit**: {{AUDIT_COLUMNS}} <!-- vd: CreatedAt NOT NULL, ModifiedAt nullable -->
123
- - **Xử lý đồng thời**: {{CONCURRENCY_MECHANISM}} <!-- vd: ROWVERSION / optimistic lock -->
124
- - **Quy ước ID**: {{PK_TYPE}} <!-- vd: bigint (không dùng Guid) -->
125
-
126
- ### Quy ước Migration <!-- [TUỲ CHỌN] khi dùng SQL migration thủ công -->
127
- - **Vị trí**: {{MIGRATION_LOCATION}}
128
- - **Đặt tên**: {{MIGRATION_NAMING}} <!-- vd: V{YYYYMMDD}_{NN}_{description}.sql -->
129
- - **Tính idempotent**: {{IDEMPOTENCY_RULE}} <!-- vd: dùng guard IF NOT EXISTS -->
130
-
131
- <!-- ════════════════════ CONDITIONAL (chỉ giữ nếu hệ thống có) ════════════════════ -->
132
-
133
- ## Luồng dữ liệu tổng quan <!-- tier: conditional -->
134
-
135
- <!-- Mô tả 1-2 câu bản chất luồng dữ liệu của hệ thống (vd: "hệ tổng hợp dữ liệu: master data ở hệ ngoài, config/transaction ở DB local, gộp tại runtime"). -->
136
- {{DATA_FLOW_SUMMARY}}
137
-
138
- ```
139
- {{DATA_FLOW_DIAGRAM}}
140
- ```
141
- <!-- Vẽ ASCII: Clients → Gateway → Services → điểm composition ở Application → Infrastructure (API ngoài / DB / cache / bus).
142
- Ghi rõ phương thức auth của từng client và các điểm composition quan trọng. -->
143
-
144
- ### Phân loại nguồn dữ liệu <!-- [TUỲ CHỌN] khi dữ liệu đến từ nhiều nguồn (API ngoài + DB local) -->
145
-
146
- | Dữ liệu | Nguồn | Cách truy cập | Caching |
147
- |---|---|---|---|
148
- | {{DATA}} | {{SOURCE}} | {{PATH}} | {{TTL_OR_DASH}} |
149
-
150
- ### Giao tiếp giữa các service <!-- [TUỲ CHỌN] khi multi-service -->
151
-
152
- ```
153
- {{SERVICE_A}} ──{{PROTOCOL}}──▶ {{SERVICE_B}} ({{VIA_CLIENT}})
154
- ```
155
-
156
- > **Endpoint nội bộ** ({{INTERNAL_ROUTE_PREFIX}}): {{INTERNAL_AUTH_MECHANISM}} — vd: header shared-secret + IP whitelist. Xem §Luồng Xác thực.
157
-
158
- ## Repositories & Hướng dẫn nền tảng <!-- tier: conditional --> <!-- chỉ giữ nếu là hệ multi-repo -->
159
-
160
- | Repository | Stack | Platform Guide |
161
- |---|---|---|
162
- | `{{repo-name}}/` | {{STACK_SUMMARY}} | `{{repo-name}}/.ai-project-guide.md` |
163
-
164
- > **Cấu trúc thư mục, scan path, quy ước namespace, code pattern** → xem `.ai-project-guide.md` của từng repo.
165
- > File này tập trung vào **kiến trúc cắt ngang** dùng chung cho mọi repo.
166
-
167
- ## Phân loại Entity <!-- tier: conditional --> <!-- khi hệ thống tích hợp dữ liệu từ hệ ngoài -->
168
-
169
- Entity được chia thành các nhóm sau. Mọi code, tài liệu, và BDD spec PHẢI dùng các thuật ngữ này nhất quán.
170
-
171
- | Nhóm | Thuật ngữ | Lưu ở DB? | ORM quản lý? | Truy cập qua | Ví dụ |
172
- |---|---|---|---|---|---|
173
- | **DB Entity** | `[entity] entity` | CÓ | CÓ | {{DB_REPO_INTERFACE}} | {{EXAMPLES}} |
174
- | **Model nguồn-API** | `[entity] model` | KHÔNG | KHÔNG — POCO/DTO | {{API_SERVICE_INTERFACE}} | {{EXAMPLES}} |
175
- | **Projection Entity** | `[entity] projection` | CÓ | CÓ | {{PROJECTION_REPO}} | {{EXAMPLES}} |
176
-
177
- **Quy tắc:**
178
- - Model nguồn-API KHÔNG có bảng DB, KHÔNG migration — là POCO/DTO được populate từ API ngoài.
179
- - {{ID_RULE}} <!-- vd: Model nguồn-API Id = external ID; DB entity Id = tự sinh -->
180
- - {{PROJECT_SPECIFIC_RULE}}
181
-
182
- ## Phân loại truy cập dữ liệu — Ranh giới các tầng <!-- tier: conditional --> <!-- khi gộp dữ liệu nhiều nguồn (API ngoài + DB) -->
183
-
184
- Cách các tầng truy cập dữ liệu và ranh giới giữa chúng:
185
-
186
- ```
187
- {{ACCESS_TREE}}
188
- ```
189
- <!-- Ví dụ:
190
- Handler / Controller
191
- ├── IProductCatalogService (Application — điểm gộp DUY NHẤT)
192
- │ ├── IProductService (Infrastructure — API ngoài)
193
- │ └── IDisplayConfigRepository (Infrastructure — DB)
194
- └── IOrderRepository (Infrastructure — DB, inject trực tiếp)
195
- -->
196
-
197
- | Tầng | Mục đích | Sở hữu | Ví dụ |
198
- |---|---|---|---|
199
- | **{{API_SERVICE_LAYER}}** (Infrastructure) | Gọi API ngoài; tự quản cache/retry/circuit-breaker/mapping | Model nguồn-API | {{EXAMPLES}} |
200
- | **{{DB_REPO_LAYER}}** (Infrastructure) | Thao tác DB local; repository pattern chuẩn | DB entity | {{EXAMPLES}} |
201
- | **{{APP_SERVICE_LAYER}}** (Application) | Gộp dữ liệu nhiều nguồn; điểm composition duy nhất | Domain object đã enrich | {{EXAMPLES}} |
202
- | **{{HANDLER_LAYER}}** (Presentation/Application) | Điều phối use-case; mapping request→response | — | {{EXAMPLES}} |
203
-
204
- **Quy tắc Injection (BẮT BUỘC tuân theo):**
205
- 1. {{RULE_1}} <!-- vd: Service gọi API ngoài chỉ inject vào Application Service, KHÔNG inject thẳng vào Handler -->
206
- 2. {{RULE_2}}
207
- 3. {{RULE_3}}
208
-
209
- ## Trách nhiệm của từng service <!-- tier: conditional --> <!-- khi multi-service -->
210
-
211
- | Service | Domain | Trách nhiệm chính |
212
- |---|---|---|
213
- | {{SERVICE}} | {{DOMAIN}} | {{RESPONSIBILITIES}} |
214
-
215
- ## Mô hình đăng ký DI <!-- tier: conditional -->
216
-
217
- Mỗi feature đăng ký dependency qua extension method / module:
218
- ```{{LANG}}
219
- {{DI_REGISTRATION_EXAMPLE}}
220
- ```
221
-
222
- ## Mô hình Multi-tenant <!-- tier: conditional --> <!-- khi một hệ thống phục vụ nhiều khách hàng/chi nhánh, dữ liệu tách riêng -->
223
-
224
- Mọi entity (trừ {{GLOBAL_ENTITIES}}) PHẢI có `{{TENANT_KEY}}`. {{ISOLATION_MECHANISM}} đảm bảo cách ly:
225
- ```{{LANG}}
226
- {{QUERY_FILTER_EXAMPLE}}
227
- ```
228
-
229
- Truy cập tenant context qua: `{{TENANT_CONTEXT_ACCESSOR}}` <!-- các field: TenantId, AppId, UserId... -->
230
-
231
- ## Phân giải định danh — External ID vs Internal ID <!-- tier: conditional --> <!-- khi tích hợp hệ ngoài có ID riêng -->
232
-
233
- Hệ thống tích hợp với {{EXTERNAL_SYSTEM}}. Mỗi entity ngoài có ID riêng, **KHÔNG trùng** với internal ID. Hai hệ ID này phải luôn được phân biệt rõ.
234
-
235
- | | DB Entity (local) | Model nguồn-API (ngoài) |
236
- |---|---|---|
237
- | **`Id`** | {{INTERNAL_ID_RULE}} (tự sinh) | Gán từ response hệ ngoài — KHÔNG tự sinh |
238
- | **`ExternalId`** | Lưu ID hệ ngoài để tham chiếu chéo | Không áp dụng — `Id` chính là external ID |
239
-
240
- ### Quy tắc bắt buộc
241
- 1. {{RULE_1}} <!-- vd: DB Entity Id luôn tự sinh, TUYỆT ĐỐI KHÔNG gán external ID vào Id -->
242
- 2. {{RULE_2}}
243
- 3. {{RULE_3}}
244
-
245
- ### Anti-pattern (CẤM)
246
- ```{{LANG}}
247
- // ❌ SAI — {{ANTIPATTERN_DESC}}
248
- {{BAD_EXAMPLE}}
249
-
250
- // ✅ ĐÚNG
251
- {{GOOD_EXAMPLE}}
252
- ```
253
-
254
- ## API Gateway <!-- tier: conditional -->
255
-
256
- | Trách nhiệm | Chi tiết |
257
- |---|---|
258
- | Xác minh chữ ký / auth | {{DETAIL}} |
259
- | Rate limiting | {{DETAIL}} |
260
- | Xử lý CORS | {{DETAIL}} |
261
- | Định tuyến request | {{DETAIL}} |
262
- | Cân bằng tải | {{DETAIL}} |
263
- | IP whitelist | {{DETAIL}} |
264
-
265
- **Nguyên tắc thiết kế:** Stateless, không chứa business logic, scale ngang được.
266
-
267
- ## Chiến lược Caching <!-- tier: conditional -->
268
-
269
- **Mô hình**: {{CACHE_PATTERN}} <!-- vd: Cache-Aside (read-through) -->
270
- **Định dạng key**: {{KEY_FORMAT}} <!-- vd: {entity}:{tenantId}:{id} -->
271
-
272
- | Loại dữ liệu | TTL | Cách invalidate |
273
- |---|---|---|
274
- | {{DATA}} | {{TTL}} | {{INVALIDATION}} |
275
-
276
- ## Event Bus <!-- tier: conditional -->
277
-
278
- > **Trạng thái:** {{STATUS}} <!-- vd: đã cấp hạ tầng nhưng chưa implement / đã chạy production -->
279
-
280
- **Nguyên tắc thiết kế:**
281
- - {{PARTITIONING}} <!-- vd: partition theo TenantId để đảm bảo thứ tự trong mỗi tenant -->
282
- - {{DELIVERY_GUARANTEE}} <!-- vd: at-least-once + theo dõi idempotency -->
283
- - {{DLQ_RETRY}} <!-- vd: DLQ {topic}.dlq, retry 3 lần với exponential backoff -->
284
-
285
- ## Sharding <!-- tier: conditional -->
286
-
287
- - {{SHARD_STRATEGY}} <!-- vd: mô hình Shard Registry + cache -->
288
- - {{SHARD_RESOLVER}} <!-- vd: IShardResolver: cache → Registry DB → tự gán -->
289
-
290
- ## Feature Toggle <!-- tier: conditional -->
291
-
292
- Hệ thống dùng {{FEATURE_TOGGLE_TOOL}} cho feature flag lúc runtime.
293
-
294
- | Điều kiện | Hành vi |
295
- |---|---|
296
- | Toggle bị tắt | {{BEHAVIOR}} <!-- thường: fail-open / cho phép -->|
297
- | Lỗi khi đánh giá | {{BEHAVIOR}} <!-- thường: fail-open để sự cố không khoá user -->|
298
- | Flag trả về false | {{BEHAVIOR}} |
299
-
300
- ## Luồng Xác thực <!-- tier: conditional -->
301
-
302
- ### {{AUTH_METHOD}} <!-- vd: JWT Bearer / API Key (HMAC) / OAuth2 / Token Exchange -->
303
-
304
- ```
305
- {{AUTH_FLOW_STEPS}}
306
- ```
307
- <!-- Liệt kê tuần tự các bước middleware xử lý: extract → verify → resolve → build context.
308
- Nếu có nhiều luồng auth (S2S, browser, internal), mô tả từng luồng. -->
309
-
310
- **Quy tắc chính:**
311
- - {{AUTH_RULE_1}}
312
- - {{AUTH_RULE_2}}
313
-
314
- **Middleware pipeline:**
315
- ```
316
- {{ROUTE_PATTERN}} → {{MIDDLEWARE_OR_BYPASS}}
317
- {{HEALTH_ROUTE}} → bypass (health probe)
318
- ```
319
-
320
- <!-- ════════════════════ OPS (chỉ người đọc — AI không nạp khi sinh code) ════════════════════ -->
321
-
322
- ## Observability (Khả năng quan sát) <!-- tier: ops -->
323
-
324
- ### Ghi log (Logging)
325
- - Thư viện: {{LOGGING_LIB}}
326
- - Định dạng: {{LOG_FORMAT}} <!-- vd: Compact JSON -->
327
- - Sink: {{LOG_SINKS}} <!-- vd: file xoay vòng theo ngày, giữ 30 ngày; console chỉ khi dev -->
328
- - **Correlation ID**: {{CORRELATION_MECHANISM}} <!-- vd: X-Correlation-Id đẩy vào log context -->
329
- - Mức log: {{LOG_LEVELS}}
330
-
331
- ### Metrics <!-- [TUỲ CHỌN] -->
332
-
333
- | Metric | Loại | Mô tả |
334
- |---|---|---|
335
- | {{METRIC}} | {{TYPE}} | {{DESC}} |
336
-
337
- ### Distributed Tracing <!-- [TUỲ CHỌN] -->
338
- - {{TRACING_TOOL}} — {{PROPAGATION_SCOPE}} <!-- vd: OpenTelemetry, propagate qua HTTP + messaging -->
339
-
340
- ### Health Check
341
- ```{{LANG}}
342
- {{HEALTH_CHECK_REGISTRATION}}
343
- ```
344
- - `{{LIVENESS_ROUTE}}` — liveness (chỉ tự kiểm tra)
345
- - `{{READINESS_ROUTE}}` — readiness (phụ thuộc: DB + cache + bus)
346
-
347
- ## Triển khai & DevOps <!-- tier: ops -->
348
-
349
- ### Chiến lược môi trường
350
-
351
- | Môi trường | Mục đích | Hạ tầng |
352
- |---|---|---|
353
- | Development | {{PURPOSE}} | {{INFRA}} |
354
- | Staging | {{PURPOSE}} | {{INFRA}} |
355
- | Production | {{PURPOSE}} | {{INFRA}} |
356
-
357
- ### CI/CD Pipeline
358
- ```
359
- {{PIPELINE_STAGES}}
360
- ```
361
- <!-- vd: Code Push → Build → Unit Test → Integration Test → Docker Build → Push Registry → Deploy Staging → Smoke → Duyệt tay → Production -->
362
-
363
- ### Quản lý cấu hình
364
-
365
- | Loại cấu hình | Lưu ở | Ví dụ |
366
- |---|---|---|
367
- | App Settings | {{STORAGE}} | {{EXAMPLE}} |
368
- | Secrets | {{SECRET_STORE}} | {{EXAMPLE}} <!-- secret production TUYỆT ĐỐI KHÔNG commit vào repo -->|
369
- | Biến môi trường | {{ENV_STORE}} | {{EXAMPLE}} |
370
-
371
- ## Chiến lược kiểm thử <!-- tier: ops -->
372
-
373
- | Cấp độ | Phạm vi | Công cụ |
374
- |---|---|---|
375
- | Unit Test | {{SCOPE}} | {{TOOLS}} |
376
- | Integration Test | {{SCOPE}} | {{TOOLS}} |
377
- | Functional Test | {{SCOPE}} | {{TOOLS}} |
378
- | Load Test | {{SCOPE}} | {{TOOLS}} |
379
-
380
- - Đặt tên: {{TEST_NAMING}} <!-- vd: MethodName_Scenario_ExpectedResult -->
381
- - {{CI_TEST_RULE}} <!-- vd: CI chạy unit + integration mỗi PR -->
382
-
383
- ## Yêu cầu phi chức năng (NFR) <!-- tier: ops -->
384
-
385
- | Yêu cầu | Mục tiêu |
386
- |---|---|
387
- | Khả năng mở rộng | {{TARGET}} |
388
- | Tính sẵn sàng | {{TARGET}} <!-- vd: SLA uptime 99.9% -->|
389
- | Triển khai | {{TARGET}} <!-- vd: zero-downtime, rolling update -->|
390
- | Tính nhất quán | {{TARGET}} |
391
- | Độ trễ | {{TARGET}} <!-- vd: API p95 < 200ms -->|
392
- | Thông lượng | {{TARGET}} |
393
- | Lưu trữ dữ liệu | {{TARGET}} |
394
- | Sao lưu | {{TARGET}} |
@@ -1,146 +0,0 @@
1
- # ─────────────────────────────────────────────────────────────────────────────
2
- # SDD Framework — Trace Gate (GitHub Actions)
3
- #
4
- # COPY file này vào .github/workflows/ của project. Nó KHÔNG tự chạy từ
5
- # .agent/templates/ — mọi thứ trong .agent/ là bản sinh ra, bị ghi đè mỗi lần
6
- # /update-framework.
7
- #
8
- # VÌ SAO CẦN (GAPS-v3 G39): framework phát hiện được một lớp lỗi mà build xanh +
9
- # test từng-UC xanh KHÔNG thấy — luồng ghép chạy vào hàm rỗng (SEAM_UNWIRED,
10
- # STUB_UNRESOLVED), hoặc code trỏ vào scenario đã bị xoá (ORPHANED, TRACE_ORPHAN).
11
- # Nhưng trước G39 việc phát hiện đó phụ thuộc vào có người TỰ NGUYỆN chạy
12
- # /validate-traces trong Claude Code rồi đọc report bằng mắt. Cái gì không chặn
13
- # thì sau sprint thứ ba không ai làm. Đây là chỗ nó chặn.
14
- #
15
- # GIỚI HẠN — đọc trước khi tin:
16
- # Job này chứng minh "report khớp SỔ, và sổ không có cờ 🔴".
17
- # Nó KHÔNG chứng minh "sổ khớp CODE" — việc đó cần quét tag trong source, đọc
18
- # .feature, so version, tức cần /validate-traces (một lệnh LLM, không chạy được
19
- # trong CI thường). Nên nó bắt ca phổ biến "quên chạy lại /validate-traces",
20
- # nhưng KHÔNG bắt ca "sửa code mà không đụng sổ".
21
- # Muốn bịt nốt: xem job `require-fresh-audit` ở cuối file.
22
- # ─────────────────────────────────────────────────────────────────────────────
23
-
24
- name: Trace Gate
25
-
26
- on:
27
- pull_request:
28
- push:
29
- branches: [main, master, develop]
30
-
31
- jobs:
32
- trace-gate:
33
- runs-on: ubuntu-latest
34
- steps:
35
- - uses: actions/checkout@v4
36
- with:
37
- # Cần lịch sử để job require-fresh-audit so được diff. Bỏ nếu không dùng job đó.
38
- fetch-depth: 0
39
- # Spec/trace nằm trong submodule (umbrella + spec_source)? Bỏ comment:
40
- # submodules: recursive
41
-
42
- - uses: actions/setup-node@v4
43
- with:
44
- node-version: '20'
45
-
46
- # ── 1. Cấu trúc sổ ───────────────────────────────────────────────────────
47
- # Sổ trace 24 cột do LLM ghi bằng tay. Một dấu tab thiếu dồn mọi ô sang trái
48
- # và ô `status` nhận một ngày tháng — trước G38 không gì báo. Bước này chặn.
49
- # Cũng bắt marker conflict git lọt vào sổ (T7) và sổ thiếu luật merge (T10).
50
- - name: Lint sổ trace
51
- run: npx -y @educa-corp/sdd-framework@latest --lint-trace
52
-
53
- # ── 2. Cổng chặn PR ──────────────────────────────────────────────────────
54
- # --gate-trace tự chạy lại lint ở tầng G1, nên bước 1 ở trên là để có log
55
- # riêng dễ đọc khi đỏ. Muốn gọn thì bỏ bước 1 và chỉ giữ bước này.
56
- - name: Trace gate (cờ 🔴 chặn PR)
57
- run: npx -y @educa-corp/sdd-framework@latest --gate-trace
58
-
59
- # ── 3. (tuỳ chọn) Đưa kết quả vào PR summary ─────────────────────────────
60
- - name: Ghi kết quả vào job summary
61
- if: always()
62
- run: |
63
- npx -y @educa-corp/sdd-framework@latest --gate-trace --json --warn-only \
64
- > gate.json || true
65
- {
66
- echo '## Trace Gate'
67
- echo '```json'
68
- cat gate.json
69
- echo '```'
70
- } >> "$GITHUB_STEP_SUMMARY"
71
-
72
- # ───────────────────────────────────────────────────────────────────────────
73
- # Ép audit phải TƯƠI khi thứ report đang KHẲNG ĐỊNH bị đổi.
74
- #
75
- # Bịt cái lỗ mà trace-gate không bịt được: gate chứng minh "report khớp SỔ",
76
- # không chứng minh "sổ khớp CODE" — việc đó cần /validate-traces, một lệnh LLM
77
- # không chạy được ở đây. Nên job này dùng một PROXY: không verify được thì ĐÒI
78
- # BẰNG CHỨNG có người vừa verify.
79
- #
80
- # ĐO BẰNG TAG, KHÔNG BẰNG `src/**`:
81
- # Framework có luật boundary-only tagging — chỉ Controller/Handler/Middleware/
82
- # Steps mang tag @trace; Entity/Repository/DTO/Interface/Base KHÔNG. Nên câu
83
- # hỏi "PR có sửa src/ không?" chặn cả PR chỉ thêm một field vào DTO — một file
84
- # không mang lời khẳng định trace nào. Cái gì báo oan thì bị tắt, rồi mất luôn
85
- # phần thật sự cần chặn.
86
- # Câu hỏi đúng: "PR có chạm dòng nào mang tag mà report đang khẳng định không?"
87
- #
88
- # sửa log trong Controller → cho qua (bản `src/**` cũ: chặn oan)
89
- # thêm field vào DTO → cho qua (bản cũ: chặn oan)
90
- # thêm method + @implements → CHẶN
91
- # lấp một @trace.stub → CHẶN
92
- #
93
- # KHÔNG cần sửa gì theo layout project — tag là tag, ở đâu cũng vậy.
94
- #
95
- # BẢY TAG dưới đây là NGUỒN của đúng 4 cờ chặn PR. Chúng được khai trong
96
- # bin/trace-schema.json → gate.audit_invalidating_tags, và self-check R10 fail
97
- # build nếu file này không nhắc đủ — tag đổi tên mà đây không biết thì grep
98
- # không khớp gì, job LUÔN XANH, và cổng mù trong im lặng.
99
- #
100
- # GIỚI HẠN ĐÃ BIẾT: đổi tên class (AuthService → AuthenticationService) không
101
- # chạm dòng tag ⇒ job này bỏ lọt, dù cột implemented_by giờ trỏ vào tên không
102
- # còn. Chấp nhận có chủ ý: ca đó ít gặp và KHÔNG im lặng (/validate-traces lần
103
- # sau báo ngay), còn báo oan thì xảy ra mỗi ngày.
104
- # Muốn chặt hơn (bắt cả rename, giá là chặn cả việc sửa log trong Controller):
105
- # đổi bước dưới thành — lấy danh sách file đã đổi, rồi `grep -l` bảy tag đó
106
- # TRÊN NỘI DUNG FILE thay vì trên diff.
107
- # ───────────────────────────────────────────────────────────────────────────
108
- require-fresh-audit:
109
- if: github.event_name == 'pull_request'
110
- runs-on: ubuntu-latest
111
- steps:
112
- - uses: actions/checkout@v4
113
- with: { fetch-depth: 0 }
114
-
115
- - name: Đổi thứ report khẳng định thì audit phải đổi theo
116
- shell: bash
117
- run: |
118
- BASE="origin/${{ github.base_ref }}"
119
-
120
- # 7 tag sinh ra 4 cờ chặn PR — khai ở bin/trace-schema.json,
121
- # gate.audit_invalidating_tags (self-check R10 canh danh sách này khớp).
122
- TAGS='@trace\.(implements|verifies|seam_port|seam_pending|stub|stub_owner|stub_for)'
123
-
124
- # Chạm dòng mang tag = report có thể đã hết đúng. -U0 để chỉ lấy dòng thật đổi.
125
- touched=$(git diff -U0 "$BASE"...HEAD | grep -E "^[+-].*${TAGS}" | head -5 || true)
126
- audit=$(git diff --name-only "$BASE"...HEAD | grep -E 'trace-report\.json$' | head -1 || true)
127
-
128
- if [ -n "$touched" ] && [ -z "$audit" ]; then
129
- echo "::error::PR đổi tag trace nhưng không kèm trace-report.json được sinh lại."
130
- echo ""
131
- echo "Những dòng này đã đổi:"
132
- echo "$touched" | sed 's/^/ /'
133
- echo ""
134
- echo "Trace gate chỉ chứng minh 'report khớp SỔ'. Tag vừa đổi mà chưa audit lại"
135
- echo "thì mọi cờ 🔴 trong report nói về trạng thái TRƯỚC khi bạn sửa."
136
- echo ""
137
- echo "Chạy trong Claude Code: /validate-traces"
138
- echo "Rồi commit: {trace_dir}/trace-report.json + *.tsv"
139
- exit 1
140
- fi
141
-
142
- if [ -n "$touched" ]; then
143
- echo "✅ Tag trace có đổi, và audit đã được sinh lại cùng PR."
144
- else
145
- echo "✅ PR không chạm tag nào mà report đang khẳng định — audit vẫn còn đúng."
146
- fi