@educa-corp/sdd-framework 0.4.0 → 0.5.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 (158) hide show
  1. package/bin/build.js +9 -0
  2. package/bin/index.js +115 -4
  3. package/bin/self-check.js +354 -0
  4. package/bin/trace-schema.json +1199 -0
  5. package/commands/debug.md +19 -12
  6. package/commands/define-product.md +19 -12
  7. package/commands/dev-gen-test.md +53 -19
  8. package/commands/dev-run-test.md +55 -20
  9. package/commands/dev-run-test.tmpl +2 -1
  10. package/commands/dev-smoke-test.md +19 -12
  11. package/commands/extend-prd.md +907 -0
  12. package/commands/extend-prd.tmpl +270 -0
  13. package/commands/fix-bug.md +101 -15
  14. package/commands/fix-bug.tmpl +29 -3
  15. package/commands/generate-architecture.md +19 -12
  16. package/commands/generate-bdd.md +174 -48
  17. package/commands/generate-bdd.tmpl +107 -18
  18. package/commands/generate-code.md +122 -29
  19. package/commands/generate-code.tmpl +69 -10
  20. package/commands/generate-design-spec.md +19 -12
  21. package/commands/generate-prd.md +44 -12
  22. package/commands/generate-prd.tmpl +25 -0
  23. package/commands/generate-spec-manifest.md +19 -12
  24. package/commands/generate-tech-docs.md +22 -15
  25. package/commands/generate-tech-docs.tmpl +2 -2
  26. package/commands/learn.md +19 -12
  27. package/commands/map-testids.md +19 -12
  28. package/commands/propose-scenario.md +91 -15
  29. package/commands/propose-scenario.tmpl +72 -3
  30. package/commands/qc-analyze.md +19 -12
  31. package/commands/qc-design-test.md +20 -12
  32. package/commands/qc-design-test.tmpl +1 -0
  33. package/commands/qc-plan.md +19 -12
  34. package/commands/qc-report.md +19 -12
  35. package/commands/qc-review.md +19 -12
  36. package/commands/qc-run-test.md +88 -22
  37. package/commands/qc-run-test.tmpl +35 -3
  38. package/commands/refine-prd.md +19 -12
  39. package/commands/report-bug.md +19 -12
  40. package/commands/review-code.md +60 -14
  41. package/commands/review-code.tmpl +41 -2
  42. package/commands/review-context.md +62 -16
  43. package/commands/review-context.tmpl +43 -4
  44. package/commands/review-tech-docs.md +50 -14
  45. package/commands/review-tech-docs.tmpl +31 -2
  46. package/commands/setup-ai-first.md +26 -16
  47. package/commands/setup-ai-first.tmpl +7 -4
  48. package/commands/sync.md +43 -18
  49. package/commands/sync.tmpl +37 -14
  50. package/commands/update-framework.md +43 -4
  51. package/commands/update-framework.tmpl +37 -0
  52. package/commands/validate-traces.md +481 -49
  53. package/commands/validate-traces.tmpl +462 -37
  54. package/core/FRAMEWORK_VERSION +1 -1
  55. package/core/README.md +56 -0
  56. package/core/commands/debug.md +19 -12
  57. package/core/commands/define-product.md +19 -12
  58. package/core/commands/dev-gen-test.md +53 -19
  59. package/core/commands/dev-run-test.md +55 -20
  60. package/core/commands/dev-smoke-test.md +19 -12
  61. package/core/commands/extend-prd.md +907 -0
  62. package/core/commands/fix-bug.md +101 -15
  63. package/core/commands/generate-architecture.md +19 -12
  64. package/core/commands/generate-bdd.md +174 -48
  65. package/core/commands/generate-code.md +122 -29
  66. package/core/commands/generate-design-spec.md +19 -12
  67. package/core/commands/generate-prd.md +44 -12
  68. package/core/commands/generate-spec-manifest.md +19 -12
  69. package/core/commands/generate-tech-docs.md +22 -15
  70. package/core/commands/learn.md +19 -12
  71. package/core/commands/map-testids.md +19 -12
  72. package/core/commands/propose-scenario.md +91 -15
  73. package/core/commands/qc-analyze.md +19 -12
  74. package/core/commands/qc-design-test.md +20 -12
  75. package/core/commands/qc-plan.md +19 -12
  76. package/core/commands/qc-report.md +19 -12
  77. package/core/commands/qc-review.md +19 -12
  78. package/core/commands/qc-run-test.md +88 -22
  79. package/core/commands/refine-prd.md +19 -12
  80. package/core/commands/report-bug.md +19 -12
  81. package/core/commands/review-code.md +60 -14
  82. package/core/commands/review-context.md +62 -16
  83. package/core/commands/review-tech-docs.md +50 -14
  84. package/core/commands/setup-ai-first.md +26 -16
  85. package/core/commands/sync.md +43 -18
  86. package/core/commands/update-framework.md +43 -4
  87. package/core/commands/validate-traces.md +481 -49
  88. package/core/modules/android-compose/stack-profile.yaml +1 -1
  89. package/core/modules/flutter/stack-profile.yaml +1 -1
  90. package/core/modules/ios-swiftui/stack-profile.yaml +1 -1
  91. package/core/modules/java-spring/stack-profile.yaml +1 -1
  92. package/core/modules/nextjs/stack-profile.yaml +1 -1
  93. package/core/modules/nuxt/stack-profile.yaml +1 -1
  94. package/core/modules/phaser-game/stack-profile.yaml +1 -1
  95. package/core/modules/php-laravel/stack-profile.yaml +1 -1
  96. package/core/modules/qc-playwright/stack-profile.yaml +1 -1
  97. package/core/modules/react/stack-profile.yaml +1 -1
  98. package/core/modules/react-native/stack-profile.yaml +1 -1
  99. package/core/modules/vue/stack-profile.yaml +1 -1
  100. package/core/rules/workflow.md +29 -0
  101. package/core/steps/gate.md +13 -8
  102. package/core/steps/report-footer.md +6 -4
  103. package/core/steps/trace-mirror.md +34 -7
  104. package/core/templates/README.md +47 -0
  105. package/core/templates/feature.template +14 -11
  106. package/core/templates/project-context.yaml +26 -14
  107. package/core/templates/tech-design.template.md +1 -1
  108. package/docs/01-getting-started/installation.md +18 -1
  109. package/docs/01-getting-started/what-is-sdd.md +4 -2
  110. package/docs/02-concepts/architecture.md +27 -3
  111. package/docs/02-concepts/pipeline-steps/02-specification.md +39 -3
  112. package/docs/02-concepts/pipeline-steps/04-bdd.md +24 -2
  113. package/docs/02-concepts/pipeline-steps/05-tech-docs.md +18 -1
  114. package/docs/02-concepts/pipeline-steps/06-code.md +35 -4
  115. package/docs/02-concepts/pipeline-steps/09-validate-traces.md +137 -12
  116. package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +59 -3
  117. package/docs/02-concepts/roles-and-hitl.md +1 -1
  118. package/docs/02-concepts/traceability.md +126 -94
  119. package/docs/03-guides/developer.md +20 -4
  120. package/docs/03-guides/product-owner.md +72 -68
  121. package/docs/03-guides/tester-qa.md +81 -70
  122. package/docs/04-reference/commands.md +134 -105
  123. package/docs/04-reference/configuration.md +146 -94
  124. package/docs/04-reference/trace-schema.md +145 -37
  125. package/docs/explain/02-generate-prd.md +80 -78
  126. package/docs/explain/02b-extend-prd.md +125 -0
  127. package/docs/explain/03-refine-prd.md +86 -86
  128. package/docs/explain/04-review-context.md +18 -1
  129. package/docs/explain/06-generate-bdd.md +23 -0
  130. package/docs/explain/08-review-tech-docs.md +20 -5
  131. package/docs/explain/10-review-code.md +36 -2
  132. package/docs/explain/19-qc-run-test.md +87 -67
  133. package/docs/explain/21-validate-traces.md +74 -68
  134. package/docs/explain/23-fix-bug.md +19 -3
  135. package/docs/explain/26-propose-scenario.md +70 -63
  136. package/docs/explain/README.md +135 -134
  137. package/modules/android-compose/stack-profile.yaml +1 -1
  138. package/modules/flutter/stack-profile.yaml +1 -1
  139. package/modules/ios-swiftui/stack-profile.yaml +1 -1
  140. package/modules/java-spring/stack-profile.yaml +1 -1
  141. package/modules/nextjs/stack-profile.yaml +1 -1
  142. package/modules/nuxt/stack-profile.yaml +1 -1
  143. package/modules/phaser-game/stack-profile.yaml +1 -1
  144. package/modules/php-laravel/stack-profile.yaml +1 -1
  145. package/modules/qc-playwright/stack-profile.yaml +1 -1
  146. package/modules/react/stack-profile.yaml +1 -1
  147. package/modules/react-native/stack-profile.yaml +1 -1
  148. package/modules/vue/stack-profile.yaml +1 -1
  149. package/package.json +5 -4
  150. package/rules/workflow.md +29 -0
  151. package/scripts/migrate-bdd-platform.js +286 -0
  152. package/steps/gate.md +13 -8
  153. package/steps/report-footer.md +6 -4
  154. package/steps/trace-mirror.md +34 -7
  155. package/templates/README.md +47 -0
  156. package/templates/feature.template +14 -11
  157. package/templates/project-context.yaml +26 -14
  158. package/templates/tech-design.template.md +1 -1
@@ -0,0 +1,1199 @@
1
+ {
2
+ "$comment": [
3
+ "NGUỒN-SỰ-THẬT MÁY ĐỌC cho contract trace của framework. bin/self-check.js đối chiếu",
4
+ "file này với commands/*.tmpl + steps/*.md mỗi lần `npm run build`, và FAIL build khi lệch.",
5
+ "",
6
+ "Vì sao tồn tại: 19/23 GAP trong GAPS.md là cùng một lỗi — contract được phát biểu lại",
7
+ "bằng prose ở nhiều lệnh rồi lệch nhau qua từng lần sửa. Ca thuần khiết nhất là",
8
+ "@trace.sc_version: 3 consumer, 0 producer, tồn tại qua nhiều version mà không lệnh nào,",
9
+ "không cổng nào, không test nào phát hiện. Rule R1 dưới đây bắt đúng lớp lỗi đó.",
10
+ "",
11
+ "ĐỔI CONTRACT: sửa file này TRƯỚC, rồi mới sửa lệnh. Build fail nếu lệnh lệch schema.",
12
+ "Bản dành cho người đọc: docs/04-reference/trace-schema.md (giữ đồng bộ với file này).",
13
+ "",
14
+ "Định dạng JSON chứ không YAML vì package.json có ZERO dependency (npx chạy không cần",
15
+ "install) — thêm js-yaml chỉ để đọc một file cấu hình build-time là không đáng."
16
+ ],
17
+ "actors": {
18
+ "$comment": "Tên logic → file nguồn. self-check tìm chuỗi field trong các file này.",
19
+ "generate-bdd": "commands/generate-bdd.tmpl",
20
+ "generate-code": "commands/generate-code.tmpl",
21
+ "generate-tech-docs": "commands/generate-tech-docs.tmpl",
22
+ "generate-prd": "commands/generate-prd.tmpl",
23
+ "generate-design-spec": "commands/generate-design-spec.tmpl",
24
+ "review-context": "commands/review-context.tmpl",
25
+ "review-tech-docs": "commands/review-tech-docs.tmpl",
26
+ "review-code": "commands/review-code.tmpl",
27
+ "validate-traces": "commands/validate-traces.tmpl",
28
+ "dev-gen-test": "commands/dev-gen-test.tmpl",
29
+ "dev-run-test": "commands/dev-run-test.tmpl",
30
+ "dev-smoke-test": "commands/dev-smoke-test.tmpl",
31
+ "qc-run-test": "commands/qc-run-test.tmpl",
32
+ "report-bug": "commands/report-bug.tmpl",
33
+ "propose-scenario": "commands/propose-scenario.tmpl",
34
+ "fix-bug": "commands/fix-bug.tmpl",
35
+ "refine-prd": "commands/refine-prd.tmpl",
36
+ "extend-prd": "commands/extend-prd.tmpl",
37
+ "sync": "commands/sync.tmpl",
38
+ "setup-ai-first": "commands/setup-ai-first.tmpl",
39
+ "generate-spec-manifest": "commands/generate-spec-manifest.tmpl",
40
+ "qc-analyze": "commands/qc-analyze.tmpl",
41
+ "qc-design-test": "commands/qc-design-test.tmpl",
42
+ "map-testids": "commands/map-testids.tmpl",
43
+ "debug": "commands/debug.tmpl",
44
+ "design-spec-template": "templates/design-spec.template.md",
45
+ "context-loader": "steps/context-loader.md",
46
+ "gate": "steps/gate.md",
47
+ "report-footer": "steps/report-footer.md",
48
+ "feature-template": "templates/feature.template",
49
+ "prd-template": "templates/prd.template.md",
50
+ "tech-design-template": "templates/tech-design.template.md"
51
+ },
52
+ "tags": [
53
+ {
54
+ "name": "@trace.sc_version",
55
+ "artifact": ".feature",
56
+ "scope": "scenario",
57
+ "shape": "semver-lite (1.0, 1.1)",
58
+ "written_by": [
59
+ "generate-bdd",
60
+ "feature-template"
61
+ ],
62
+ "bumped_by": [
63
+ "generate-bdd",
64
+ "review-context"
65
+ ],
66
+ "read_by": [
67
+ "generate-bdd",
68
+ "validate-traces",
69
+ "review-context"
70
+ ],
71
+ "why": "Tín hiệu DUY NHẤT cho DRIFT (spec_ver != gen_ver). Không có producer = DRIFT chết."
72
+ },
73
+ {
74
+ "name": "@trace.bdd_version",
75
+ "artifact": ".feature",
76
+ "scope": "file",
77
+ "shape": "semver-lite scalar",
78
+ "written_by": [
79
+ "generate-bdd",
80
+ "feature-template"
81
+ ],
82
+ "bumped_by": [
83
+ "generate-bdd",
84
+ "review-context"
85
+ ],
86
+ "read_by": [
87
+ "generate-bdd",
88
+ "generate-code",
89
+ "generate-tech-docs",
90
+ "validate-traces",
91
+ "review-tech-docs",
92
+ "review-context"
93
+ ],
94
+ "why": "Drift cấp file (Background/dataset/business-definition) mà sc_version không thấy."
95
+ },
96
+ {
97
+ "name": "@trace.bdd_versions",
98
+ "artifact": "tech-design.md",
99
+ "scope": "file",
100
+ "shape": "map theo platform (system=1.5, web=1.9)",
101
+ "written_by": [
102
+ "generate-tech-docs",
103
+ "tech-design-template"
104
+ ],
105
+ "read_by": [
106
+ "generate-code",
107
+ "validate-traces",
108
+ "review-tech-docs"
109
+ ],
110
+ "why": "Số NHIỀU, cố ý khác @trace.bdd_version (scalar) — cùng tên cho hai kiểu dữ liệu làm vỡ parser generic."
111
+ },
112
+ {
113
+ "name": "@trace.platform",
114
+ "artifact": ".feature",
115
+ "scope": "file",
116
+ "required": "always",
117
+ "values_from": "platform",
118
+ "written_by": [
119
+ "generate-bdd",
120
+ "feature-template"
121
+ ],
122
+ "read_by": [
123
+ "generate-code",
124
+ "generate-tech-docs",
125
+ "review-context",
126
+ "context-loader"
127
+ ],
128
+ "why": "Quyết BE/FE ở generate-code (cấm fallback platform_type) + tên sổ trace + lookup design-spec. Lưu ý: validate-traces và report-bug KHÔNG đọc tag này — chúng suy platform từ TÊN FILE .tsv ({UC-ID}-{platform}.tsv), nên không phải consumer của tag."
129
+ },
130
+ {
131
+ "name": "@trace.prd_version",
132
+ "artifact": ".feature + code",
133
+ "scope": "file + method",
134
+ "written_by": [
135
+ "generate-bdd",
136
+ "generate-code",
137
+ "feature-template"
138
+ ],
139
+ "read_by": [
140
+ "generate-bdd",
141
+ "validate-traces",
142
+ "review-context"
143
+ ],
144
+ "why": "Nguồn của PRD_DRIFT (validate-traces Step 4 so 3 tầng: PRD file, TSV, tag trong code)."
145
+ },
146
+ {
147
+ "name": "@trace.implements",
148
+ "artifact": "code",
149
+ "scope": "method",
150
+ "shape": "{UC-ID}-SC{N}",
151
+ "written_by": [
152
+ "generate-code",
153
+ "setup-ai-first"
154
+ ],
155
+ "read_by": [
156
+ "validate-traces",
157
+ "review-code",
158
+ "dev-gen-test",
159
+ "dev-smoke-test",
160
+ "fix-bug"
161
+ ],
162
+ "why": "Khoá chính của trace ở tầng code. Tra bằng khớp chuỗi CHÍNH XÁC → cấm trỏ thư mục."
163
+ },
164
+ {
165
+ "name": "@trace.source",
166
+ "artifact": "code",
167
+ "scope": "method",
168
+ "shape": "{specs_dir}/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature",
169
+ "written_by": [
170
+ "generate-code",
171
+ "setup-ai-first"
172
+ ],
173
+ "read_by": [
174
+ "review-code"
175
+ ],
176
+ "why": "Con trỏ ngược về spec. PHẢI gồm segment {platform}."
177
+ },
178
+ {
179
+ "name": "@trace.tech_doc_revision",
180
+ "artifact": "code",
181
+ "scope": "method",
182
+ "written_by": [
183
+ "generate-code"
184
+ ],
185
+ "read_by": [
186
+ "review-code"
187
+ ],
188
+ "why": "Ghi revision tech-doc mà method này được sinh theo. BẤT ĐỐI XỨNG ĐÃ BIẾT: validate-traces Step 5 tính TECHDOC_DRIFT từ cột TSV tech_doc_revision chứ không từ tag này (khác Step 4, có so tag @trace.prd_version trong code). Nên hiện chỉ review-code kiểm sự CÓ MẶT của nó. Muốn đối xứng thì Step 5 phải đọc thêm tag trong code."
189
+ },
190
+ {
191
+ "name": "@trace.verifies",
192
+ "artifact": "test",
193
+ "scope": "method",
194
+ "shape": "{UC-ID}-SC{N}",
195
+ "written_by": [
196
+ "dev-gen-test",
197
+ "qc-run-test",
198
+ "fix-bug"
199
+ ],
200
+ "read_by": [
201
+ "validate-traces",
202
+ "review-code",
203
+ "dev-run-test",
204
+ "qc-run-test"
205
+ ],
206
+ "why": "Khớp test → sc_id khi ghi test_count/dev_selftest/qc_status."
207
+ },
208
+ {
209
+ "name": "@trace.scenario",
210
+ "artifact": ".feature",
211
+ "scope": "scenario",
212
+ "shape": "{UC-ID}-SC{N}",
213
+ "written_by": [
214
+ "generate-bdd",
215
+ "propose-scenario",
216
+ "feature-template"
217
+ ],
218
+ "read_by": [
219
+ "generate-bdd",
220
+ "review-context"
221
+ ],
222
+ "why": "Sinh sc_id cho row TSV. Thiếu nó = scenario vô hình với toàn bộ coverage."
223
+ },
224
+ {
225
+ "name": "@trace.status",
226
+ "artifact": ".feature + tech-design.md",
227
+ "scope": "file",
228
+ "values_from": "approval_status",
229
+ "written_by": [
230
+ "feature-template",
231
+ "review-context",
232
+ "review-tech-docs",
233
+ "generate-tech-docs",
234
+ "tech-design-template"
235
+ ],
236
+ "read_by": [
237
+ "generate-code",
238
+ "validate-traces",
239
+ "review-tech-docs"
240
+ ],
241
+ "why": "Cổng duyệt: DS1 của generate-code, và uc_status sync từ đây."
242
+ },
243
+ {
244
+ "name": "@trace.revision",
245
+ "artifact": "tech-design.md",
246
+ "scope": "file",
247
+ "shape": "integer",
248
+ "written_by": [
249
+ "generate-tech-docs",
250
+ "review-tech-docs",
251
+ "tech-design-template"
252
+ ],
253
+ "read_by": [
254
+ "generate-code",
255
+ "validate-traces"
256
+ ],
257
+ "why": "Nguồn của tech_doc_revision + TECHDOC_DRIFT."
258
+ },
259
+ {
260
+ "name": "@trace.api_source",
261
+ "artifact": ".feature + tech-design.md",
262
+ "scope": "file",
263
+ "written_by": [
264
+ "generate-bdd",
265
+ "tech-design-template"
266
+ ],
267
+ "read_by": [
268
+ "review-tech-docs",
269
+ "review-context"
270
+ ],
271
+ "why": "existing → bỏ cổng T7 + skip System BDD Synthesis S1-S3."
272
+ },
273
+ {
274
+ "name": "@trace.stub",
275
+ "artifact": "code",
276
+ "scope": "method",
277
+ "written_by": [
278
+ "generate-code"
279
+ ],
280
+ "read_by": [
281
+ "validate-traces",
282
+ "review-code"
283
+ ],
284
+ "why": "Method trắng nội-feature. Nguồn của STUB_UNRESOLVED."
285
+ },
286
+ {
287
+ "name": "@trace.mock_for",
288
+ "artifact": "code",
289
+ "scope": "class",
290
+ "written_by": [
291
+ "generate-code"
292
+ ],
293
+ "read_by": [
294
+ "generate-code"
295
+ ],
296
+ "why": "Đánh dấu layer mock của FE `--phase=ui` thuộc UC nào. `--phase=integration` dò lại chính tag này để biết mock nào phải thay bằng adapter thật — vừa ghi vừa đọc bởi cùng lệnh ở HAI phase khác nhau, đó là đúng."
297
+ },
298
+ {
299
+ "name": "@trace.mock_source",
300
+ "artifact": "code",
301
+ "scope": "class",
302
+ "values": "contract | system-bdd",
303
+ "written_by": [
304
+ "generate-code"
305
+ ],
306
+ "read_by": [
307
+ "generate-code"
308
+ ],
309
+ "why": "Shape của mock suy từ đâu. `system-bdd` = infer từ behavior (KHÔNG phải full request/response shape) → phase integration phải dự kiến điều chỉnh; `contract` = lấy từ §4 tech-doc, khớp sẵn."
310
+ },
311
+ {
312
+ "name": "@trace.system_bdd",
313
+ "artifact": "code",
314
+ "scope": "class",
315
+ "written_by": [
316
+ "generate-code"
317
+ ],
318
+ "read_by": [],
319
+ "allow_no_reader": "Con trỏ tới System BDD mà mock được dựng theo. Nhãn truy vết cho người đọc + reviewer; không có consumer tự động (phase integration route bằng @trace.mock_for/@trace.mock_source).",
320
+ "why": "Ghi mock này dựng theo file System BDD nào."
321
+ },
322
+ {
323
+ "name": "@trace.be_contract",
324
+ "artifact": "code",
325
+ "scope": "class",
326
+ "written_by": [
327
+ "generate-code"
328
+ ],
329
+ "read_by": [],
330
+ "allow_no_reader": "CHỈ có khi mock_source=contract — ghi tech-doc nào cấp shape. Nhãn truy vết, không có consumer tự động.",
331
+ "why": "Con trỏ tới tech-doc cấp shape cho mock."
332
+ },
333
+ {
334
+ "name": "@trace.root_cause",
335
+ "artifact": "code",
336
+ "scope": "method",
337
+ "written_by": [
338
+ "fix-bug"
339
+ ],
340
+ "read_by": [],
341
+ "allow_no_reader": "Nhãn cho người đọc code — mô tả ngắn nguyên nhân gốc của bug đã fix. Cùng nhóm với @trace.fixes.",
342
+ "why": "Ghi lại nguyên nhân gốc tại chỗ sửa."
343
+ },
344
+ {
345
+ "name": "@trace.regression",
346
+ "artifact": "test",
347
+ "scope": "method",
348
+ "written_by": [
349
+ "fix-bug"
350
+ ],
351
+ "read_by": [],
352
+ "allow_no_reader": "Đánh dấu test hồi quy sinh kèm bản fix. Nhãn cho người đọc; test_count/test_classes trong TSV mới là đường máy đọc (G7).",
353
+ "why": "Nhận diện test hồi quy của một ticket."
354
+ },
355
+ {
356
+ "name": "@trace.title",
357
+ "artifact": ".feature",
358
+ "scope": "file",
359
+ "written_by": [
360
+ "feature-template"
361
+ ],
362
+ "read_by": [
363
+ "review-context"
364
+ ],
365
+ "why": "Tên feature dạng người đọc. review-context B5 Nhóm B chỉ kiểm CÓ MẶT, không kiểm giá trị."
366
+ },
367
+ {
368
+ "name": "@trace.author",
369
+ "artifact": ".feature",
370
+ "scope": "file",
371
+ "written_by": [
372
+ "feature-template"
373
+ ],
374
+ "read_by": [
375
+ "review-context"
376
+ ],
377
+ "why": "Nguồn gốc file (`AI-generated`). Chỉ kiểm có mặt — xem @trace.title."
378
+ },
379
+ {
380
+ "name": "@trace.created_at",
381
+ "artifact": ".feature",
382
+ "scope": "file",
383
+ "written_by": [
384
+ "feature-template"
385
+ ],
386
+ "read_by": [
387
+ "review-context"
388
+ ],
389
+ "why": "Ngày tạo file. Chỉ kiểm có mặt — xem @trace.title. KHÁC last_updated của TSV (cái đó là trạng thái, cái này là gốc)."
390
+ },
391
+ {
392
+ "name": "@trace.generated_at",
393
+ "artifact": "tech-design.md",
394
+ "scope": "file",
395
+ "written_by": [
396
+ "tech-design-template"
397
+ ],
398
+ "read_by": [],
399
+ "allow_no_reader": "Ngày sinh tech-doc. Drift của tech-doc đo bằng @trace.revision (integer), KHÔNG bằng ngày — nên field này thuần thông tin cho người đọc.",
400
+ "why": "Ngày sinh tech-doc, dạng người đọc."
401
+ },
402
+ {
403
+ "name": "@trace.business_rules",
404
+ "artifact": ".feature",
405
+ "scope": "scenario",
406
+ "shape": "{TICKET-ID}-UC{N}-BR{m}, …",
407
+ "written_by": [
408
+ "generate-bdd",
409
+ "feature-template",
410
+ "propose-scenario"
411
+ ],
412
+ "read_by": [
413
+ "review-context"
414
+ ],
415
+ "$reader_note": "generate-tech-docs đọc BR ID từ THÂN scenario (`BR{m}`), không đọc tag này — nên nó không phải consumer.",
416
+ "why": "Link scenario ↔ Business Rule của PRD. BR đánh số LIÊN TỤC toàn PRD (không reset theo UC — G14), nên ID ở đây phải lấy NGUYÊN từ PRD §3. Mở cột bảng BR trên PRD đã có BDD sẽ làm churn ID và phá link này."
417
+ },
418
+ {
419
+ "name": "@trace.dataset",
420
+ "artifact": ".feature",
421
+ "scope": "file",
422
+ "$producer_note": "CHỈ feature-template — nó được {{include}} nướng cứng vào generate-bdd lúc build, nên generate-bdd không nhắc tên field này ở prose của chính nó. Khai thêm generate-bdd sẽ làm R3 fail.",
423
+ "written_by": [
424
+ "feature-template"
425
+ ],
426
+ "read_by": [
427
+ "review-context",
428
+ "validate-traces"
429
+ ],
430
+ "why": "File testdata dùng chung của feature. Đổi nó là thay đổi CẤP FILE mà sc_version không thấy — chính vì vậy Step 5c liệt nó vào nguồn của BDD_DRIFT."
431
+ },
432
+ {
433
+ "name": "@trace.prd",
434
+ "artifact": ".feature",
435
+ "scope": "file",
436
+ "shape": "{TICKET-ID}",
437
+ "$producer_note": "CHỈ feature-template — xem @trace.dataset.",
438
+ "written_by": [
439
+ "feature-template"
440
+ ],
441
+ "read_by": [
442
+ "review-context"
443
+ ],
444
+ "why": "Con trỏ ngược .feature → PRD. Mang TICKET-ID chứ không phải path, vì tech-doc và trace cũng khoá theo TICKET-ID."
445
+ },
446
+ {
447
+ "name": "@trace.platforms",
448
+ "artifact": "tech-design.md",
449
+ "scope": "file",
450
+ "shape": "danh sách platform",
451
+ "written_by": [
452
+ "generate-tech-docs",
453
+ "tech-design-template"
454
+ ],
455
+ "read_by": [
456
+ "review-tech-docs"
457
+ ],
458
+ "why": "Số NHIỀU, cố ý khác @trace.platform (scalar, ở .feature) — cùng lý do như bdd_version vs bdd_versions (G15): tech-doc là doc GỘP phủ nhiều platform."
459
+ },
460
+ {
461
+ "name": "@trace.test_type",
462
+ "artifact": "test",
463
+ "scope": "method",
464
+ "written_by": [
465
+ "dev-gen-test"
466
+ ],
467
+ "read_by": [],
468
+ "allow_no_reader": "NHÃN CHẾT — phát hiện khi khai schema (G30 lô 3). /dev-gen-test dán nó lên mọi test class nhưng KHÔNG lệnh nào đọc: dev-run-test chạy theo test_command của project, qc-* dùng stack riêng. Giữ vì nó là nhãn hữu ích cho người đọc code và là chỗ móc sẵn nếu sau này muốn chạy test theo loại (vd chỉ chạy unit ở pre-commit). Nếu 6 tháng nữa vẫn không consumer nào → bỏ hẳn thay vì để nợ.",
469
+ "why": "Phân loại test (unit/integration/e2e…). Hiện chỉ là nhãn cho người đọc."
470
+ },
471
+ {
472
+ "name": "@trace.testid_attr",
473
+ "artifact": "tech-design.md",
474
+ "scope": "file",
475
+ "written_by": [
476
+ "map-testids"
477
+ ],
478
+ "read_by": [
479
+ "generate-code",
480
+ "qc-run-test",
481
+ "qc-design-test"
482
+ ],
483
+ "$history_note": "G30 lô 3 phát hiện field này TỰ MÔ TẢ là contract FE↔QC nhưng chỉ nửa FE (generate-code) đọc — QC tự suy tên thuộc tính từ platform. G37 nối nửa QC: qc-run-test đọc để CẤU HÌNH test-id attribute (Playwright get_by_test_id mặc định dò `data-testid`; dự án dùng `data-test`/`data-qa` sẽ trượt 100% locator nếu không set), qc-design-test ghi lại vào metadata .Test.md để reviewer đối chiếu.",
484
+ "why": "Tên thuộc tính test-id của stack — contract FE↔QC. FE emit theo nó (generate-code), QC cấu hình locator theo nó (qc-run-test). Suy từ platform thay vì đọc field = phát biểu lại sự thật đã ghi ở nơi khác, và hỏng IM LẶNG: test fail 'element not found' trông y hệt bug sản phẩm."
485
+ },
486
+ {
487
+ "name": "@trace.domain",
488
+ "artifact": ".feature + tech-design.md",
489
+ "scope": "file",
490
+ "written_by": [
491
+ "generate-bdd",
492
+ "feature-template",
493
+ "tech-design-template"
494
+ ],
495
+ "read_by": [
496
+ "context-loader",
497
+ "review-context",
498
+ "review-tech-docs",
499
+ "generate-spec-manifest",
500
+ "setup-ai-first"
501
+ ],
502
+ "why": "Khoá ĐỊNH TUYẾN. context-loader Bước 1.5 đọc nó từ frontmatter target để chọn service submodule — sai là ghi code/trace nhầm repo mà không báo gì."
503
+ },
504
+ {
505
+ "name": "@trace.id",
506
+ "artifact": ".feature + tech-design.md",
507
+ "scope": "file",
508
+ "shape": "{TICKET-ID}-UC{N}",
509
+ "written_by": [
510
+ "feature-template",
511
+ "tech-design-template"
512
+ ],
513
+ "read_by": [
514
+ "generate-code",
515
+ "generate-tech-docs",
516
+ "qc-analyze",
517
+ "review-context"
518
+ ],
519
+ "why": "UC-ID của file. generate-code đọc nó để chốt Scope Lock (implement ĐÚNG UC này, không lan sang .feature khác)."
520
+ },
521
+ {
522
+ "name": "@trace.module",
523
+ "artifact": ".feature + tech-design.md",
524
+ "scope": "file",
525
+ "written_by": [
526
+ "feature-template",
527
+ "tech-design-template"
528
+ ],
529
+ "read_by": [
530
+ "dev-gen-test",
531
+ "generate-tech-docs",
532
+ "review-context"
533
+ ],
534
+ "why": "Stack module của service sở hữu. dev-gen-test dùng để chọn test pattern. Giá trị `unknown` ở spec repo mode là HỢP LỆ — review-context không được flag."
535
+ },
536
+ {
537
+ "name": "@trace.ucs",
538
+ "artifact": "tech-design.md",
539
+ "scope": "file",
540
+ "shape": "danh sách UC-ID",
541
+ "written_by": [
542
+ "generate-tech-docs",
543
+ "tech-design-template"
544
+ ],
545
+ "read_by": [
546
+ "review-tech-docs",
547
+ "gate"
548
+ ],
549
+ "why": "Tech-doc là doc GỘP cấp PRD — đây là danh sách UC nó phủ. Cần vì tên file mang {TICKET-ID} chứ không mang {UC-ID} (G10): gate phải tách TICKET-ID rồi glob, và dùng field này để biết doc có phủ UC đang hỏi không."
550
+ },
551
+ {
552
+ "name": "@trace.seam_port",
553
+ "artifact": "code",
554
+ "scope": "class",
555
+ "written_by": [
556
+ "generate-code"
557
+ ],
558
+ "read_by": [
559
+ "review-code"
560
+ ],
561
+ "why": "Tên port mà class stub đang giả lập. Đi CẶP với @trace.seam_pending — review-code kiểm cả hai phải có mặt cùng dòng `PENDING` trong _seams.tsv. validate-traces Step 5b nhận diện seam qua @trace.seam_pending + cột `name` của sổ, KHÔNG đọc tag này."
562
+ },
563
+ {
564
+ "name": "@trace.stub_owner",
565
+ "artifact": "code",
566
+ "scope": "method",
567
+ "written_by": [
568
+ "generate-code"
569
+ ],
570
+ "read_by": [
571
+ "validate-traces",
572
+ "review-code"
573
+ ],
574
+ "why": "UC lẽ ra phải lấp method trắng này. Step 5b hỏi 'owner đã gen chưa' để quyết STUB_PENDING (ⓘ) vs STUB_UNRESOLVED (🔴 chặn PR). Mất tag = mất luôn phép phân biệt đó → hoặc báo động oan mọi stub, hoặc bỏ sót hàm trắng mồ côi."
575
+ },
576
+ {
577
+ "name": "@trace.stub_for",
578
+ "artifact": "code",
579
+ "scope": "method",
580
+ "written_by": [
581
+ "generate-code"
582
+ ],
583
+ "read_by": [
584
+ "validate-traces",
585
+ "review-code"
586
+ ],
587
+ "why": "Trách nhiệm mà method trắng này đang giữ chỗ. Step 5b dùng nó để dò 'có hàm THẬT song song cùng trách nhiệm không' — dấu hiệu Fill-before-create đã trượt (BDD owner đẻ hàm mới thay vì lấp hàm cũ)."
588
+ },
589
+ {
590
+ "name": "@trace.sign_off",
591
+ "artifact": "tech-design.md",
592
+ "scope": "file",
593
+ "written_by": [
594
+ "review-tech-docs"
595
+ ],
596
+ "read_by": [
597
+ "review-tech-docs"
598
+ ],
599
+ "why": "Cổng T7 — xác nhận cross-team của tech-doc system BDD. Vừa ghi vừa đọc bởi cùng một lệnh là ĐÚNG (nó là sổ trạng thái nội bộ của cổng đó, không phải contract liên lệnh). LƯU Ý: tech-design.template.md KHÔNG phát ra field này — review-tech-docs tự thêm khi thiếu, nên template không phải producer."
600
+ },
601
+ {
602
+ "name": "@trace.seam_pending",
603
+ "artifact": "code",
604
+ "scope": "class",
605
+ "written_by": [
606
+ "generate-code"
607
+ ],
608
+ "read_by": [
609
+ "validate-traces",
610
+ "review-code"
611
+ ],
612
+ "why": "Port cross-UC chưa có hàng thật. Nguồn của SEAM_UNWIRED."
613
+ },
614
+ {
615
+ "name": "@trace.service",
616
+ "artifact": ".feature",
617
+ "scope": "file",
618
+ "written_by": [
619
+ "generate-bdd",
620
+ "feature-template"
621
+ ],
622
+ "read_by": [
623
+ "generate-bdd",
624
+ "dev-gen-test",
625
+ "generate-tech-docs",
626
+ "review-context"
627
+ ],
628
+ "why": "Nguồn DUY NHẤT của cột TSV `service` (cột 23) — trace gộp không tách theo service nên thiếu tag này là mất hẳn thông tin sở hữu ở cấp row. BẮT BUỘC mọi mode từ v0.4.3 (trước đó feature.template chủ động bỏ ở spec repo mode, và review-context xếp nó vào Nhóm C có-điều-kiện)."
629
+ },
630
+ {
631
+ "name": "@trace.design_spec_version",
632
+ "artifact": "code",
633
+ "scope": "method",
634
+ "written_by": [
635
+ "generate-code"
636
+ ],
637
+ "read_by": [
638
+ "validate-traces",
639
+ "review-code"
640
+ ],
641
+ "why": "Nguồn của DESIGNSPEC_DRIFT (Step 5d). CHỈ FE/App — bỏ hẳn dòng tag với system/backend."
642
+ },
643
+ {
644
+ "name": "@trace.fixes",
645
+ "artifact": "code",
646
+ "scope": "method",
647
+ "written_by": [
648
+ "fix-bug"
649
+ ],
650
+ "read_by": [],
651
+ "allow_no_reader": "Nhãn cho người đọc code, không có consumer tự động."
652
+ }
653
+ ],
654
+ "tsv_columns": [
655
+ {
656
+ "n": 1,
657
+ "name": "sc_id",
658
+ "written_by": [
659
+ "generate-bdd"
660
+ ],
661
+ "read_by": [
662
+ "validate-traces",
663
+ "generate-code",
664
+ "dev-gen-test",
665
+ "dev-run-test",
666
+ "qc-run-test",
667
+ "report-bug",
668
+ "fix-bug"
669
+ ]
670
+ },
671
+ {
672
+ "n": 2,
673
+ "name": "sc_title",
674
+ "written_by": [
675
+ "generate-bdd"
676
+ ],
677
+ "read_by": [
678
+ "validate-traces"
679
+ ]
680
+ },
681
+ {
682
+ "n": 3,
683
+ "name": "spec_ver",
684
+ "written_by": [
685
+ "generate-bdd",
686
+ "validate-traces",
687
+ "review-context"
688
+ ],
689
+ "read_by": [
690
+ "validate-traces",
691
+ "generate-code"
692
+ ]
693
+ },
694
+ {
695
+ "n": 4,
696
+ "name": "gen_ver",
697
+ "written_by": [
698
+ "generate-code"
699
+ ],
700
+ "read_by": [
701
+ "validate-traces",
702
+ "generate-bdd"
703
+ ]
704
+ },
705
+ {
706
+ "n": 5,
707
+ "name": "implemented_by",
708
+ "written_by": [
709
+ "generate-code"
710
+ ],
711
+ "read_by": [
712
+ "validate-traces",
713
+ "generate-bdd"
714
+ ]
715
+ },
716
+ {
717
+ "n": 6,
718
+ "name": "test_count",
719
+ "written_by": [
720
+ "dev-gen-test",
721
+ "fix-bug"
722
+ ],
723
+ "read_by": [
724
+ "validate-traces",
725
+ "generate-bdd"
726
+ ]
727
+ },
728
+ {
729
+ "n": 7,
730
+ "name": "test_classes",
731
+ "written_by": [
732
+ "dev-gen-test",
733
+ "fix-bug"
734
+ ],
735
+ "read_by": [
736
+ "validate-traces",
737
+ "generate-bdd"
738
+ ]
739
+ },
740
+ {
741
+ "n": 8,
742
+ "name": "dev_selftest",
743
+ "$invalidated_by_comment": [
744
+ "PRODUCER vs INVALIDATOR — hai vai khác nhau, cùng nằm trong written_by.",
745
+ "Chủ sở hữu (ghi giá trị KHẲNG ĐỊNH pass/fail): dev-run-test.",
746
+ "Invalidator (chỉ được hạ về not_run/— khi giá trị cũ HẾT ĐÚNG): generate-bdd (spec đổi),",
747
+ "generate-code (lấp stub hoặc sửa method do DRIFT), fix-bug (code đổi), dev-gen-test (test mới).",
748
+ "Luật đầy đủ: rules/workflow.md §Trace Contract — 'Làm mất hiệu lực ≠ ghi đè'.",
749
+ "Vì sao cần: giữ một 'pass' sinh ra từ spec đã bị sửa là BÁO CÁO SAI. Trước G28 chỉ",
750
+ "nhánh lấp-stub hạ cờ, nên chuỗi spec-đổi → DRIFT → regen → OK kết thúc bằng dashboard",
751
+ "xanh hoàn toàn trên một hành vi chưa từng được test."
752
+ ],
753
+ "written_by": [
754
+ "dev-run-test",
755
+ "dev-gen-test",
756
+ "generate-code",
757
+ "generate-bdd",
758
+ "fix-bug"
759
+ ],
760
+ "read_by": [
761
+ "validate-traces",
762
+ "qc-run-test"
763
+ ]
764
+ },
765
+ {
766
+ "n": 9,
767
+ "name": "dev_selftest_at",
768
+ "$comment": "Chủ: dev-run-test. Invalidator (hạ về —): generate-bdd · generate-code · fix-bug. Xem dev_selftest.",
769
+ "written_by": [
770
+ "dev-run-test",
771
+ "generate-code",
772
+ "generate-bdd",
773
+ "fix-bug"
774
+ ],
775
+ "read_by": [
776
+ "validate-traces",
777
+ "qc-run-test"
778
+ ]
779
+ },
780
+ {
781
+ "n": 10,
782
+ "name": "qc_status",
783
+ "$comment": "Chủ (ghi pass/fail/skip): qc-run-test — DUY NHẤT. Invalidator (chỉ hạ về not_run khi spec/code vừa đổi): generate-bdd · generate-code. Xem dev_selftest + rules/workflow.md 'Làm mất hiệu lực ≠ ghi đè'.",
784
+ "written_by": [
785
+ "qc-run-test",
786
+ "generate-bdd",
787
+ "generate-code"
788
+ ],
789
+ "read_by": [
790
+ "validate-traces",
791
+ "dev-run-test",
792
+ "generate-code",
793
+ "report-bug",
794
+ "fix-bug"
795
+ ]
796
+ },
797
+ {
798
+ "n": 11,
799
+ "name": "qc_run_at",
800
+ "$comment": "Chủ: qc-run-test. Invalidator (hạ về —): generate-bdd · generate-code. Xem qc_status.",
801
+ "written_by": [
802
+ "qc-run-test",
803
+ "generate-bdd",
804
+ "generate-code"
805
+ ],
806
+ "read_by": [
807
+ "validate-traces",
808
+ "dev-run-test",
809
+ "generate-code"
810
+ ]
811
+ },
812
+ {
813
+ "n": 12,
814
+ "name": "qc_owner",
815
+ "written_by": [
816
+ "qc-run-test",
817
+ "report-bug"
818
+ ],
819
+ "read_by": [
820
+ "validate-traces",
821
+ "generate-code",
822
+ "fix-bug"
823
+ ]
824
+ },
825
+ {
826
+ "n": 13,
827
+ "name": "qc_blocked_by",
828
+ "written_by": [
829
+ "qc-run-test",
830
+ "report-bug"
831
+ ],
832
+ "read_by": [
833
+ "validate-traces",
834
+ "generate-code",
835
+ "qc-run-test"
836
+ ]
837
+ },
838
+ {
839
+ "n": 14,
840
+ "name": "prd_version",
841
+ "written_by": [
842
+ "generate-bdd"
843
+ ],
844
+ "read_by": [
845
+ "validate-traces",
846
+ "generate-code"
847
+ ]
848
+ },
849
+ {
850
+ "n": 15,
851
+ "name": "bdd_version",
852
+ "written_by": [
853
+ "generate-bdd",
854
+ "review-context"
855
+ ],
856
+ "read_by": [
857
+ "validate-traces"
858
+ ]
859
+ },
860
+ {
861
+ "n": 16,
862
+ "name": "tech_doc_revision",
863
+ "written_by": [
864
+ "generate-code",
865
+ "review-tech-docs"
866
+ ],
867
+ "read_by": [
868
+ "validate-traces",
869
+ "generate-bdd"
870
+ ]
871
+ },
872
+ {
873
+ "n": 17,
874
+ "name": "fe_tech_doc_revision",
875
+ "written_by": [
876
+ "generate-code"
877
+ ],
878
+ "read_by": [
879
+ "validate-traces",
880
+ "generate-bdd",
881
+ "review-tech-docs"
882
+ ]
883
+ },
884
+ {
885
+ "n": 18,
886
+ "name": "prd_status",
887
+ "written_by": [
888
+ "generate-bdd",
889
+ "validate-traces"
890
+ ],
891
+ "read_by": [
892
+ "validate-traces"
893
+ ]
894
+ },
895
+ {
896
+ "n": 19,
897
+ "name": "uc_status",
898
+ "written_by": [
899
+ "generate-bdd",
900
+ "validate-traces",
901
+ "review-context"
902
+ ],
903
+ "read_by": [
904
+ "validate-traces",
905
+ "generate-code"
906
+ ]
907
+ },
908
+ {
909
+ "n": 20,
910
+ "name": "fe_phase",
911
+ "written_by": [
912
+ "generate-code",
913
+ "generate-bdd"
914
+ ],
915
+ "read_by": [
916
+ "validate-traces"
917
+ ]
918
+ },
919
+ {
920
+ "n": 21,
921
+ "name": "status",
922
+ "written_by": [
923
+ "validate-traces",
924
+ "generate-bdd"
925
+ ],
926
+ "read_by": [
927
+ "validate-traces",
928
+ "generate-code",
929
+ "dev-run-test",
930
+ "qc-run-test"
931
+ ]
932
+ },
933
+ {
934
+ "n": 23,
935
+ "name": "service",
936
+ "$comment": [
937
+ "Đội/submodule sở hữu scenario. Nguồn: @trace.service của header .feature.",
938
+ "VÌ SAO TỒN TẠI (G31): validate-traces Step 0 và trace-mirror.md đều khẳng định trace gộp",
939
+ "'không cần tách theo service vì mỗi row mang @trace.service' — nhưng TSV KHÔNG có cột nào",
940
+ "cho nó và JSON report cũng không. Ở đúng chế độ phổ biến nhất (umbrella + spec_source),",
941
+ "trace hoàn toàn không trả lời được 'scenario này thuộc đội nào' — câu hỏi số MỘT của một",
942
+ "dự án nhiều đội. Nghịch lý: nhánh LEGACY (trace tách theo service) thì CÓ gắn field service",
943
+ "vào JSON; nhánh 'phổ biến' thì không. Cột này làm lời khẳng định kia thành sự thật.",
944
+ "Giá trị: path service | 'multi' (chưa chốt) | 'unresolved' (routing sai) | '—' (single-service)."
945
+ ],
946
+ "written_by": [
947
+ "generate-bdd"
948
+ ],
949
+ "read_by": [
950
+ "validate-traces"
951
+ ]
952
+ },
953
+ {
954
+ "n": 24,
955
+ "name": "design_spec_version",
956
+ "$comment": [
957
+ "Version design-spec tại thời điểm sinh BDD. Nguồn: | **Version** | của design-spec.",
958
+ "VÌ SAO TỒN TẠI (G32): design-spec điều khiển CẢ BDD FE/App (Screen States + AC-UI) LẪN code",
959
+ "FE (màn hình, component inventory, Figma frame) — nhưng là artifact upstream DUY NHẤT không",
960
+ "có cột TSV, không có tag trong code, không có cờ drift. Nó tự bảo vệ một chiều (reset draft",
961
+ "khi PRD đổi), còn chiều 'designer sửa design-spec SAU KHI BDD/code đã sinh' thì không gì bắt.",
962
+ "GAPS.md G2 mở đầu bằng 'tầng BDD là tầng DUY NHẤT không có cờ drift' — câu đó đúng lúc viết,",
963
+ "vì bảng kiểm kê chỉ tính PRD/BDD/tech-doc/code. Design-spec không nằm trong bảng nên không ai đếm.",
964
+ "'—' cho system/backend và khi sinh BDD mà không có design-spec."
965
+ ],
966
+ "written_by": [
967
+ "generate-bdd"
968
+ ],
969
+ "read_by": [
970
+ "validate-traces"
971
+ ]
972
+ },
973
+ {
974
+ "n": 22,
975
+ "name": "last_updated",
976
+ "written_by": [
977
+ "generate-bdd",
978
+ "generate-code",
979
+ "dev-gen-test",
980
+ "dev-run-test",
981
+ "qc-run-test",
982
+ "review-context",
983
+ "review-tech-docs",
984
+ "fix-bug"
985
+ ],
986
+ "read_by": [
987
+ "validate-traces"
988
+ ]
989
+ }
990
+ ],
991
+ "aux_tables": [
992
+ {
993
+ "$comment": [
994
+ "Bảng phụ ngoài TSV chính. Nằm ngoài SoT cho tới G30 — dù nó là NGUỒN của hai cờ 🔴",
995
+ "chặn PR (SEAM_UNWIRED, STUB_UNRESOLVED). Đổi tên/thứ tự cột mà không ai bắt được."
996
+ ],
997
+ "name": "_seams.tsv",
998
+ "path": "{trace_dir}/{domain}/{prd-slug}/_seams.tsv",
999
+ "columns": [
1000
+ "kind",
1001
+ "name",
1002
+ "consumer_uc",
1003
+ "owner_uc",
1004
+ "artifact",
1005
+ "binding",
1006
+ "status",
1007
+ "last_updated"
1008
+ ],
1009
+ "written_by": [
1010
+ "generate-code",
1011
+ "validate-traces"
1012
+ ],
1013
+ "read_by": [
1014
+ "validate-traces",
1015
+ "review-code"
1016
+ ],
1017
+ "column_actors": [
1018
+ "generate-code",
1019
+ "validate-traces"
1020
+ ],
1021
+ "$column_actors_note": "Chỉ hai lệnh này thao tác ở MỨC CỘT (ghi/parse từng field). review-code là consumer ở MỨC BẢNG — nó chỉ kiểm 'có dòng PENDING tương ứng trong sổ không', không đọc tên cột. Tách ra để R3 đừng đòi review-code nhắc đủ 8 tên cột."
1022
+ }
1023
+ ],
1024
+ "queues": [
1025
+ {
1026
+ "$comment": [
1027
+ "Hàng đợi feedback từ tester/QC. Khai ở đây để R1 bắt được ca 'hàng đợi mất consumer'",
1028
+ "y như nó bắt field mất producer — đó chính là hình dạng của G26."
1029
+ ],
1030
+ "name": "bug-reports",
1031
+ "path_key": "bug_reports_dir",
1032
+ "written_by": [
1033
+ "report-bug"
1034
+ ],
1035
+ "read_by": [
1036
+ "fix-bug",
1037
+ "qc-run-test"
1038
+ ]
1039
+ },
1040
+ {
1041
+ "name": "bdd-proposals",
1042
+ "path_key": "bdd_proposals_dir",
1043
+ "written_by": [
1044
+ "propose-scenario"
1045
+ ],
1046
+ "read_by": [
1047
+ "generate-bdd"
1048
+ ]
1049
+ },
1050
+ {
1051
+ "name": "prd-change-requests",
1052
+ "path_key": "prd_change_requests_dir",
1053
+ "written_by": [
1054
+ "propose-scenario",
1055
+ "extend-prd"
1056
+ ],
1057
+ "read_by": [
1058
+ "extend-prd",
1059
+ "validate-traces"
1060
+ ],
1061
+ "$roles_note": "extend-prd là consumer DRAIN thật (Bước 2 đọc request accepted làm nguyên liệu; Bước 6.5 đóng dấu incorporated + chuyển sang archived/ + commit) — nên nó vừa read vừa write. validate-traces Step 7b chỉ ĐẾM và nhắc (không drain). G26 đóng đủ 3 phần từ đây."
1062
+ }
1063
+ ],
1064
+ "vocabularies": {
1065
+ "$comment": "Mọi giá trị phải xuất hiện ở ít nhất một actor — giá trị chết là dấu hiệu contract lệch.",
1066
+ "trace_status": {
1067
+ "values": [
1068
+ "OK",
1069
+ "DRIFT",
1070
+ "GAP",
1071
+ "UNTRACKED",
1072
+ "ORPHANED"
1073
+ ],
1074
+ "column": "status"
1075
+ },
1076
+ "platform": {
1077
+ "values": [
1078
+ "web",
1079
+ "app",
1080
+ "system"
1081
+ ]
1082
+ },
1083
+ "approval_status": {
1084
+ "values": [
1085
+ "draft",
1086
+ "in-review",
1087
+ "approved"
1088
+ ]
1089
+ },
1090
+ "fe_phase": {
1091
+ "values": [
1092
+ "ui",
1093
+ "integrated"
1094
+ ],
1095
+ "column": "fe_phase"
1096
+ },
1097
+ "seam_status": {
1098
+ "values": [
1099
+ "PENDING",
1100
+ "READY",
1101
+ "RESOLVED"
1102
+ ]
1103
+ },
1104
+ "audit_flags": {
1105
+ "values": [
1106
+ "PRD_DRIFT",
1107
+ "PRD_STALE_REF",
1108
+ "BDD_DRIFT",
1109
+ "TECHDOC_DRIFT",
1110
+ "TECHDOC_STALE_REF",
1111
+ "FE_TECHDOC_DRIFT",
1112
+ "TECHDOC_STALE_VS_BDD",
1113
+ "DESIGNSPEC_DRIFT",
1114
+ "DESIGNSPEC_STALE_VS_BDD",
1115
+ "TRACE_ORPHAN",
1116
+ "SEAM_UNWIRED",
1117
+ "STUB_UNRESOLVED",
1118
+ "SEAM_PENDING",
1119
+ "STUB_PENDING"
1120
+ ]
1121
+ }
1122
+ },
1123
+ "path_keys": {
1124
+ "$comment": "Key phải có trong templates/project-context.yaml VÀ được dùng bởi ít nhất một actor. Key khai mà không ai dùng = key chết (GAPS.md G17).",
1125
+ "config_file": "templates/project-context.yaml",
1126
+ "ignore_unused": [
1127
+ "specs_dir",
1128
+ "src_dir",
1129
+ "trace_dir",
1130
+ "tech_docs_dir",
1131
+ "lessons_file"
1132
+ ]
1133
+ },
1134
+ "forbidden_patterns": [
1135
+ {
1136
+ "pattern": "bdd/{UC-ID}.feature",
1137
+ "reason": "@trace.source thiếu segment {platform}. Layout thật: bdd/{platform}/{UC-ID}-{slug}.feature",
1138
+ "gap": "G8"
1139
+ },
1140
+ {
1141
+ "pattern": "{UC-ID}*-tech-design",
1142
+ "reason": "Glob không bao giờ khớp: tech-doc là doc GỘP cấp PRD, tên mang {TICKET-ID} chứ không mang {UC-ID}",
1143
+ "gap": "G10",
1144
+ "except": {
1145
+ "steps/gate.md": "Trích dẫn pattern trong cảnh báo tại chỗ: \"Đừng glob {UC-ID}*-tech-design*.md — nó nở thành ... và không bao giờ khớp\""
1146
+ }
1147
+ },
1148
+ {
1149
+ "pattern": "{prd-slug}/{UC-ID}.tsv",
1150
+ "reason": "Tên sổ trace thiếu -{platform}. Một sổ cho mỗi UC × platform",
1151
+ "gap": "G18"
1152
+ },
1153
+ {
1154
+ "pattern": "@trace.uc=",
1155
+ "reason": "Từ vựng ĐÃ KHAI TỬ (G11). Số UC đã nằm trong `sc_id` (`{UC-ID}-SC{N}`) nên tag riêng là thừa và gây nhập nhằng với `@trace.ucs` (danh sách UC của tech-doc). Ba file dưới được phép chứa vì chúng đang MAP NGƯỢC nó sang canonical rồi strip — không phải phát ra nó.",
1156
+ "gap": "G11/G30",
1157
+ "except": {
1158
+ "commands/generate-bdd.tmpl": "Đường backward-compat khi nhặt proposal cũ từ feedback/bdd-proposals/",
1159
+ "commands/propose-scenario.tmpl": "Ghi chú cho tester đừng dùng lại format cũ",
1160
+ "commands/review-context.tmpl": "B5 auto-fix: map tag lạc sang canonical rồi strip"
1161
+ }
1162
+ },
1163
+ {
1164
+ "pattern": "@trace.ac=",
1165
+ "reason": "Từ vựng ĐÃ KHAI TỬ (G11) — thay bằng dòng `# Covers: AC{N}`. Xem @trace.uc=.",
1166
+ "gap": "G11/G30",
1167
+ "except": {
1168
+ "commands/generate-bdd.tmpl": "Đường backward-compat cho proposal cũ",
1169
+ "commands/propose-scenario.tmpl": "Ghi chú format cũ",
1170
+ "commands/review-context.tmpl": "B5 auto-fix map sang `# Covers:`"
1171
+ }
1172
+ },
1173
+ {
1174
+ "pattern": "claude-opus-4",
1175
+ "reason": "Hardcode version model — dùng \"model Opus mới nhất\" để không phải sửa framework mỗi lần lên model",
1176
+ "gap": "G21"
1177
+ },
1178
+ {
1179
+ "pattern": "{paths.feature_template}",
1180
+ "reason": "Key chết: template được {{include}} nướng cứng lúc build, lệnh không đọc path template lúc chạy",
1181
+ "gap": "G17"
1182
+ },
1183
+ {
1184
+ "pattern": "{paths.prd_template}",
1185
+ "reason": "Key chết — xem G9/G17",
1186
+ "gap": "G17"
1187
+ },
1188
+ {
1189
+ "pattern": "{paths.trace_report}",
1190
+ "reason": "Key chết và trỏ sai: report thật là {trace_dir}/trace-report.json",
1191
+ "gap": "G17"
1192
+ },
1193
+ {
1194
+ "pattern": "{paths.templates_dir}",
1195
+ "reason": "Key chết — xem G17",
1196
+ "gap": "G17"
1197
+ }
1198
+ ]
1199
+ }