@educa-corp/sdd-framework 0.6.0 → 0.7.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 (205) 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 +391 -30
  6. package/core/FRAMEWORK_VERSION +1 -1
  7. package/{commands/extend-prd.md → core/commands/amend-prd.md} +205 -173
  8. package/core/commands/dev-run-test.md +47 -9
  9. package/core/commands/extend-prd.md +39 -12
  10. package/core/commands/generate-bdd.md +43 -4
  11. package/core/commands/generate-code.md +33 -0
  12. package/core/commands/generate-tech-docs.md +34 -2
  13. package/core/commands/qc-run-test.md +29 -3
  14. package/core/commands/refine-prd.md +13 -2
  15. package/core/commands/review-context.md +43 -8
  16. package/core/commands/sync.md +105 -1
  17. package/core/commands/validate-traces.md +284 -11
  18. package/core/rules/workflow.md +34 -0
  19. package/core/steps/context-loader.md +26 -5
  20. package/core/templates/feature.template +1 -1
  21. package/docs/02-concepts/architecture.md +36 -0
  22. package/docs/04-reference/commands.md +148 -134
  23. package/docs/04-reference/trace-schema.md +39 -0
  24. package/docs/explain/02b-extend-prd.md +1 -1
  25. package/docs/explain/02c-amend-prd.md +152 -0
  26. package/docs/explain/28-sync.md +25 -0
  27. package/docs/explain/README.md +136 -135
  28. package/package.json +1 -8
  29. package/commands/debug.md +0 -529
  30. package/commands/debug.tmpl +0 -260
  31. package/commands/define-product.md +0 -438
  32. package/commands/define-product.tmpl +0 -225
  33. package/commands/dev-gen-test.md +0 -700
  34. package/commands/dev-gen-test.tmpl +0 -490
  35. package/commands/dev-run-test.md +0 -435
  36. package/commands/dev-run-test.tmpl +0 -225
  37. package/commands/dev-smoke-test.md +0 -374
  38. package/commands/dev-smoke-test.tmpl +0 -217
  39. package/commands/extend-prd.tmpl +0 -273
  40. package/commands/fix-bug.md +0 -519
  41. package/commands/fix-bug.tmpl +0 -197
  42. package/commands/generate-architecture.md +0 -354
  43. package/commands/generate-architecture.tmpl +0 -197
  44. package/commands/generate-bdd.md +0 -923
  45. package/commands/generate-bdd.tmpl +0 -590
  46. package/commands/generate-code.md +0 -859
  47. package/commands/generate-code.tmpl +0 -649
  48. package/commands/generate-design-spec.md +0 -737
  49. package/commands/generate-design-spec.tmpl +0 -524
  50. package/commands/generate-prd.md +0 -722
  51. package/commands/generate-prd.tmpl +0 -226
  52. package/commands/generate-spec-manifest.md +0 -321
  53. package/commands/generate-spec-manifest.tmpl +0 -164
  54. package/commands/generate-tech-docs.md +0 -920
  55. package/commands/generate-tech-docs.tmpl +0 -273
  56. package/commands/learn.md +0 -399
  57. package/commands/learn.tmpl +0 -130
  58. package/commands/map-testids.md +0 -238
  59. package/commands/map-testids.tmpl +0 -81
  60. package/commands/propose-scenario.md +0 -359
  61. package/commands/propose-scenario.tmpl +0 -202
  62. package/commands/qc-analyze.md +0 -269
  63. package/commands/qc-analyze.tmpl +0 -112
  64. package/commands/qc-design-test.md +0 -226
  65. package/commands/qc-design-test.tmpl +0 -69
  66. package/commands/qc-plan.md +0 -206
  67. package/commands/qc-plan.tmpl +0 -49
  68. package/commands/qc-report.md +0 -217
  69. package/commands/qc-report.tmpl +0 -60
  70. package/commands/qc-review.md +0 -210
  71. package/commands/qc-review.tmpl +0 -53
  72. package/commands/qc-run-test.md +0 -326
  73. package/commands/qc-run-test.tmpl +0 -116
  74. package/commands/refine-prd.md +0 -653
  75. package/commands/refine-prd.tmpl +0 -281
  76. package/commands/report-bug.md +0 -305
  77. package/commands/report-bug.tmpl +0 -148
  78. package/commands/review-code.md +0 -415
  79. package/commands/review-code.tmpl +0 -146
  80. package/commands/review-context.md +0 -902
  81. package/commands/review-context.tmpl +0 -530
  82. package/commands/review-tech-docs.md +0 -561
  83. package/commands/review-tech-docs.tmpl +0 -404
  84. package/commands/setup-ai-first.md +0 -602
  85. package/commands/setup-ai-first.tmpl +0 -450
  86. package/commands/sync.md +0 -430
  87. package/commands/sync.tmpl +0 -429
  88. package/commands/update-framework.md +0 -203
  89. package/commands/update-framework.tmpl +0 -202
  90. package/commands/validate-traces.md +0 -1077
  91. package/commands/validate-traces.tmpl +0 -920
  92. package/hooks/data-guard.js +0 -232
  93. package/hooks/settings.json +0 -19
  94. package/modules/android-compose/module.yaml +0 -13
  95. package/modules/android-compose/stack-profile.yaml +0 -57
  96. package/modules/angular/architecture-snippets/component-patterns.md +0 -187
  97. package/modules/angular/module.yaml +0 -6
  98. package/modules/angular/stack-profile.yaml +0 -38
  99. package/modules/context-engineering/architecture-snippets/context-design.md +0 -119
  100. package/modules/context-engineering/module.yaml +0 -9
  101. package/modules/context-engineering/stack-profile.yaml +0 -61
  102. package/modules/dotnet/architecture-snippets/clean-arch.md +0 -160
  103. package/modules/dotnet/module.yaml +0 -6
  104. package/modules/dotnet/stack-profile.yaml +0 -50
  105. package/modules/flutter/module.yaml +0 -14
  106. package/modules/flutter/stack-profile.yaml +0 -59
  107. package/modules/golang/architecture-snippets/domain-layout.md +0 -283
  108. package/modules/golang/module.yaml +0 -6
  109. package/modules/golang/stack-profile.yaml +0 -40
  110. package/modules/ios-swiftui/module.yaml +0 -13
  111. package/modules/ios-swiftui/stack-profile.yaml +0 -55
  112. package/modules/java-spring/architecture-snippets/layered-arch.md +0 -201
  113. package/modules/java-spring/module.yaml +0 -15
  114. package/modules/java-spring/stack-profile.yaml +0 -28
  115. package/modules/nextjs/architecture-snippets/app-router-patterns.md +0 -269
  116. package/modules/nextjs/module.yaml +0 -14
  117. package/modules/nextjs/stack-profile.yaml +0 -74
  118. package/modules/nuxt/module.yaml +0 -14
  119. package/modules/nuxt/stack-profile.yaml +0 -58
  120. package/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +0 -646
  121. package/modules/phaser-game/module.yaml +0 -15
  122. package/modules/phaser-game/stack-profile.yaml +0 -90
  123. package/modules/php-laravel/architecture-snippets/service-repository.md +0 -302
  124. package/modules/php-laravel/module.yaml +0 -15
  125. package/modules/php-laravel/stack-profile.yaml +0 -56
  126. package/modules/qc-playwright/stack-profile.yaml +0 -66
  127. package/modules/react/architecture-snippets/hooks-query-patterns.md +0 -254
  128. package/modules/react/module.yaml +0 -14
  129. package/modules/react/stack-profile.yaml +0 -63
  130. package/modules/react-native/module.yaml +0 -14
  131. package/modules/react-native/stack-profile.yaml +0 -56
  132. package/modules/vue/module.yaml +0 -14
  133. package/modules/vue/stack-profile.yaml +0 -65
  134. package/rules/data-protection.md +0 -80
  135. package/rules/workflow.md +0 -99
  136. package/skills/code/SKILL.md +0 -19
  137. package/skills/code/SKILL.tmpl +0 -19
  138. package/skills/debug/SKILL.md +0 -19
  139. package/skills/debug/SKILL.tmpl +0 -19
  140. package/skills/design-spec/SKILL.md +0 -11
  141. package/skills/design-spec/SKILL.tmpl +0 -11
  142. package/skills/discovery/SKILL.md +0 -14
  143. package/skills/discovery/SKILL.tmpl +0 -14
  144. package/skills/prd/SKILL.md +0 -19
  145. package/skills/prd/SKILL.tmpl +0 -19
  146. package/skills/qc/qa-analyst/DOC_GAPS.template.md +0 -63
  147. package/skills/qc/qa-analyst/acceptance-criteria.md +0 -60
  148. package/skills/qc/qa-analyst/business-rules.md +0 -59
  149. package/skills/qc/qa-analyst/data-flow.md +0 -64
  150. package/skills/qc/qa-analyst/spec-breakdown.md +0 -61
  151. package/skills/qc/qa-designer/e2e/journey.md +0 -41
  152. package/skills/qc/qa-designer/exploratory/charter.md +0 -68
  153. package/skills/qc/qa-designer/exploratory/explore-to-functional.md +0 -43
  154. package/skills/qc/qa-designer/functional/api.md +0 -45
  155. package/skills/qc/qa-designer/functional/gui-feature.md +0 -46
  156. package/skills/qc/qa-designer/functional/gui-screen.md +0 -52
  157. package/skills/qc/qa-designer/integration/api.md +0 -42
  158. package/skills/qc/qa-designer/integration/db.md +0 -39
  159. package/skills/qc/qa-designer/integration/gui.md +0 -40
  160. package/skills/qc/qa-designer/integration/kafka.md +0 -40
  161. package/skills/qc/qa-designer/non-functional.md +0 -40
  162. package/skills/qc/qa-planner/test-plan.md +0 -120
  163. package/skills/qc/qa-reviewer/script/e2e.md +0 -87
  164. package/skills/qc/qa-reviewer/script/exploratory.md +0 -45
  165. package/skills/qc/qa-reviewer/script/functional.md +0 -101
  166. package/skills/qc/qa-reviewer/script/integration.md +0 -91
  167. package/skills/qc/qa-reviewer/script/non-functional.md +0 -126
  168. package/skills/qc/qa-reviewer/test-case/e2e.md +0 -73
  169. package/skills/qc/qa-reviewer/test-case/exploratory.md +0 -43
  170. package/skills/qc/qa-reviewer/test-case/functional.md +0 -76
  171. package/skills/qc/qa-reviewer/test-case/integration.md +0 -69
  172. package/skills/qc/qa-reviewer/test-case/non-functional.md +0 -73
  173. package/skills/qc/qa-runner/e2e.md +0 -49
  174. package/skills/qc/qa-runner/exploratory/session.md +0 -36
  175. package/skills/qc/qa-runner/functional/api.md +0 -35
  176. package/skills/qc/qa-runner/functional/gui-feature.md +0 -51
  177. package/skills/qc/qa-runner/functional/gui-screen.md +0 -55
  178. package/skills/qc/qa-runner/integration.md +0 -47
  179. package/skills/qc/qa-runner/non-functional.md +0 -49
  180. package/skills/qc/qa-runner/report/report.md +0 -37
  181. package/skills/setup-ai-first/SKILL.md +0 -19
  182. package/skills/setup-ai-first/SKILL.tmpl +0 -19
  183. package/skills/spec/SKILL.md +0 -19
  184. package/skills/spec/SKILL.tmpl +0 -19
  185. package/skills/test/SKILL.md +0 -18
  186. package/skills/test/SKILL.tmpl +0 -18
  187. package/steps/business-language.md +0 -56
  188. package/steps/capture-lesson.md +0 -112
  189. package/steps/context-loader.md +0 -406
  190. package/steps/gate.md +0 -151
  191. package/steps/report-footer.md +0 -125
  192. package/steps/review-fanout.md +0 -159
  193. package/steps/spawn-agent.md +0 -129
  194. package/steps/trace-mirror.md +0 -53
  195. package/templates/README.md +0 -70
  196. package/templates/architecture.template.md +0 -394
  197. package/templates/ci/trace-gate.yml +0 -146
  198. package/templates/design-spec.template.md +0 -217
  199. package/templates/feature.template +0 -123
  200. package/templates/hooks/pre-push +0 -61
  201. package/templates/platform-guide.template.md +0 -145
  202. package/templates/prd.template.md +0 -283
  203. package/templates/product-definition.template.md +0 -188
  204. package/templates/project-context.yaml +0 -212
  205. package/templates/tech-design.template.md +0 -490
@@ -1,23 +1,32 @@
1
- # /extend-prd — Thêm yêu cầu mới vào PRD đã duyệt
1
+ # /amend-prd — Sửa tại chỗ một yêu cầu đã duyệt trong PRD
2
2
 
3
- > **Ranh giới với `/refine-prd` — đọc trước khi chọn lệnh:**
3
+ > **Nhánh thứ — đọc bảng này trước khi chọn lệnh:**
4
4
  >
5
- > | Lệnh | Câu hỏi nó trả lời | Nguồn đầu vào |
5
+ > | Tình huống | Lệnh | Thao tác ghi |
6
6
  > |---|---|---|
7
- > | `/refine-prd` | *"PRD hiện tại có **vấn đề** gì?"* | 3 lăng kính review soi nội dung ĐANG CÓ |
8
- > | **`/extend-prd`** | *"PRD hiện tại **thiếu** cái mới?"* | PO + hòm thư `prd-change-requests/` |
7
+ > | PRD **chưa có** | `/generate-prd` | **Write** cả file |
8
+ > | PRD đã có, **thêm** UC/AC/BR mới | `/extend-prd` | **Edit add-only** — output là superset chặt |
9
+ > | PRD đã có, **sửa vấn đề review chỉ ra** | `/refine-prd` → Review Board → `--resume` | Edit trong phạm vi finding |
10
+ > | **PRD đã có, PO muốn ĐỔI một yêu cầu đang đúng cú pháp** | **`/amend-prd`** | **Edit tại chỗ** — output **KHÔNG** phải superset |
9
11
  >
10
- > `/refine-prd` **không** thêm được UC/AC/BR mới tự cấm Resume Mode Phase 2 (*"không thay đổi
11
- > bất kỳ section nào không được tham chiếu bởi một finding được chấp nhận"*), findings của nó sinh
12
- > từ việc soi PRD hiện nên **không đường nào để một yêu cầu MỚI đi vào**.
12
+ > ** sao phải lệnh riêng (GAPS-v4 G54).** Ba lệnh kia đều **từ chối đúng việc này**:
13
+ > `/generate-prd` chỉ một cổng chặn-cứng rồi vẫn ghi đè (mất changelog, **đánh số lại BR**,
14
+ > phá `@trace.business_rules` trong mọi `.feature` đã sinh) · `/extend-prd` chỉ **add-only**, luật
15
+ > Bước 5 §3 đòi output là *"superset chặt"* · `/refine-prd` tự cấm đụng section nào không được một
16
+ > finding trỏ tới, và findings sinh từ việc soi PRD hiện có nên **không có đường nào để một ý định
17
+ > MỚI của PO đi vào**.
13
18
  >
14
- > **Vì sao là lệnh riêng, không phải `/generate-prd --extend`:** hai chế độ ngược nhau về thao tác ghi
15
- > `/generate-prd` **Write cả file**, lệnh này **chỉ Edit add-only**. Trộn vào một `.tmpl` chính
16
- > hình dạng của G9 (một file, hai hành vi, người đọc chọn nhầm).
19
+ > Trước lệnh này, hành vi hợp duy nhất còn lại **mở file `.md` ra gõ** — và đó là con đường
20
+ > DUY NHẤT framework không nhìn thấy: mọi drift detector so **nhãn version**, không so **nội dung**
21
+ > (0 content hash trong toàn bộ codebase). Sửa tay không bump version ⇒ **0 cờ**, không 🔴 không 🟠
22
+ > không ⓘ. Nên nhánh thiếu không phải một tiện ích còn nợ; nó là **điểm mù mà chính thiết kế tạo ra**.
23
+ >
24
+ > **`/validate-traces` canh cửa sau** bằng cờ `PRD_UNTRACKED_EDIT` (schema → `spec_edit_detection`):
25
+ > nội dung PRD đổi mà `Version` không đổi ⇒ có người đi cửa sau. Cửa chính là lệnh này.
17
26
 
18
27
  ## Gate
19
28
 
20
- *Checkpoint: **chặn CỨNG** — sửa PRD đã DUYỆT. `--yes` KHÔNG bỏ qua được (gate Bước 3a).*
29
+ *Checkpoint: **chặn CỨNG** — SỬA TẠI CHỖ một AC/BR/UC đã duyệt — thao tác ghi DUY NHẤT trong framework được phép làm output KHÔNG phải superset của bản cũ. `--yes` KHÔNG bỏ qua được (gate Bước 3a).*
21
30
 
22
31
  # Gate — Quy trình vào chuẩn cho mọi lệnh
23
32
 
@@ -172,7 +181,7 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
172
181
  🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
173
182
 
174
183
 
175
- *Lưu ý: Với lệnh này, target ở Bước 1 là **file PRD đã tồn tại** `{TICKET-ID}-{prd-slug}.md` (file `.md` duy nhất ở gốc feature folder). Nếu `$ARGUMENTS` rỗng → liệt kê `{specs_dir}/*/*/*.md` và hỏi. **Không tìm thấy file PRD → DỪNG** và chỉ sang `/generate-prd` (feature mới thì đi từ discovery, không phải từ đây).*
184
+ *Lưu ý: Với lệnh này, target ở Bước 1 là **file PRD đã tồn tại** `{TICKET-ID}-{prd-slug}.md` (file `.md` duy nhất ở gốc feature folder). `$ARGUMENTS` rỗng → liệt kê `{specs_dir}/*/*/*.md` và hỏi. **Không tìm thấy file PRD → DỪNG** và chỉ sang `/generate-prd`.*
176
185
 
177
186
  ## Context
178
187
  **BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
@@ -184,7 +193,7 @@ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
184
193
 
185
194
  ---
186
195
 
187
- ## Ngôn ngữ nghiệp vụ *(áp cho mọi text mới: UC, AC, BR, Business Logic, Scope)*
196
+ ## Ngôn ngữ nghiệp vụ *(áp cho mọi text được sửa: AC, BR, Business Logic, Scope)*
188
197
  # Business Language Guard — chặn thuật ngữ kỹ thuật rò vào tài liệu nghiệp vụ
189
198
 
190
199
  Tài liệu nghiệp vụ (PRD, product-definition) mô tả **WHAT** — chỉ ngôn ngữ nghiệp vụ. Guard này chạy **mỗi khi viết hoặc sửa** prose (gen mới, áp fix `--resume`, hiệu chỉnh): **quét và xử lý** các thuật ngữ kỹ thuật/UI phổ thông bên dưới **trước khi ghi**.
@@ -245,190 +254,209 @@ Các từ như `cờ / flag`, `biến / trường / field`, `giá trị / value`
245
254
 
246
255
  ---
247
256
 
248
- ## Bước 1 — Nạp trạng thái PRD hiện
257
+ ## Bước 1 — Nạp PRD **PO khai tường minh** cái cần sửa
249
258
 
250
259
  Đọc target PRD, trích và lưu:
251
260
 
252
261
  | Giá trị | Nguồn | Dùng để |
253
262
  |---|---|---|
254
- | `current_version` | Metadata `\| **Version** \|` | tính version mới ở Bước 6 |
255
- | `current_status` | Metadata `\| **Status** \|` | cảnh báo nếu đang `draft` (xem dưới) |
256
- | `max_uc` | số UC lớn nhất trong §3 | UC mới = `max_uc + 1` |
257
- | `max_br` | số BR lớn nhất **trên TOÀN PRD** | BR mới = `max_br + 1` |
258
- | `max_ac` | số AC lớn nhất trong §2 | AC mới = `max_ac + 1` |
259
- | `existing_ucs` | danh sách UC-ID + tên | phát hiện va chạm ở Bước 3 · báo "UC không đổi" ở Bước 7 |
263
+ | `current_version` | Metadata `\| **Version** \|` | tính version mới ở Bước 5 |
264
+ | `current_status` | Metadata `\| **Status** \|` | cảnh báo nếu chưa `approved` |
265
+ | `existing_ucs` | danh sách UC-ID + tên | phân giải UC sở hữu · kiểm va chạm |
266
+ | `all_br` | mọi BR-ID + nội dung, theo UC sở hữu (bảng BR §3) | phân giải `BR{n}` → UC |
267
+ | `all_ac` | mọi AC-ID + nội dung, theo UC sở hữu (dòng `**AC liên quan:**`) | phân giải `AC{n}` → UC |
260
268
  | `changelog_rows` | bảng `# Change Log` | biết PRD đã đi qua những gì |
261
- | `api_source` | Metadata `API Source` | quyết cần hỏi contract cho phần thêm không |
262
- | `bdd_generated` | glob `{specs_dir}/{domain}/{prd-slug}/bdd/*/{TICKET-ID}-UC*.feature` | **cảnh báo BR ID churn** + route ở Bước 7 |
263
-
264
- **Guard — PRD đang `draft`:** nếu `current_status != approved` → cảnh báo mềm, không chặn:
265
- ```
266
- ⚠️ PRD đang ở Status: {status} (chưa approved).
267
- Thêm yêu cầu lên một PRD chưa chốt sẽ trộn hai việc: phần chưa duyệt + phần mới.
268
- Cân nhắc hoàn tất review vòng hiện tại trước (/review-context → PO duyệt).
269
- Vẫn thêm bây giờ? (Y/N)
270
- ```
271
-
272
- **Guard — BDD đã sinh:** nếu `bdd_generated` không rỗng, hiện danh sách và nêu rõ hệ quả:
273
- ```
274
- ℹ️ {n} file BDD đã sinh cho PRD này: {danh sách UC × platform}
275
- Lệnh này CHỈ đánh số nối tiếp (UC{max_uc+1}, BR{max_br+1}) — KHÔNG bao giờ đánh lại
276
- ID cũ, nên các liên kết @trace.business_rules hiện có KHÔNG bị ảnh hưởng.
277
- Sau khi thêm: chỉ cần /generate-bdd cho UC MỚI; các UC cũ không phải gen lại
278
- (/validate-traces sẽ xếp chúng vào ⓘ PRD_STALE_REF, không phải 🟠 PRD_DRIFT).
279
- ```
269
+ | `bdd_generated` | glob `{specs_dir}/{domain}/{prd-slug}/bdd/*/{TICKET-ID}-UC*.feature` | tính blast radius Bước 6 |
280
270
 
281
- ---
271
+ ### `amend_targets` — **BẮT BUỘC, không suy đoán**
282
272
 
283
- ## Bước 2 Nạp hòm thư `prd-change-requests/`
273
+ PO phải nêu **chính xác ID** cần sửa. Đây là ràng buộc cứng nhất của lệnh: ID được khai
274
+ **trở thành `{changelog_scope}`** ở Bước 5, và cũng là **danh sách duy nhất** mà guard sau-ghi ở
275
+ Bước 4 cho phép nội dung thay đổi.
284
276
 
285
- *Đây là **consumer** mà hàng đợi này thiếu suốt từ đầu: `/propose-scenario` Case B ghi vào đó, `/sync` thông báo lúc-đến, `/validate-traces` Step 7b đếm và nhắc — nhưng **không lệnh nào drain**. Đây là chỗ đó.*
277
+ Nhận `amend_targets` theo thứ tự:
286
278
 
287
- Quét `{paths.prd_change_requests_dir}/*.md` (mặc định `{spec_source}/feedback/prd-change-requests/`; **không** quét `archived/`). Thư mục vắng/rỗng bỏ qua **im lặng**.
279
+ 1. Từ `$ARGUMENTS` nếu PO đã nêu (vd `/amend-prd PAY01 UC3-BR8`).
280
+ 2. Nếu không, **hỏi** — kèm danh sách để PO chọn, đừng để PO gõ mò:
281
+ ```
282
+ Sửa gì trong {TICKET-ID}? (nhập ID, cách nhau bằng dấu phẩy)
288
283
 
289
- Lọc theo PRD này: khớp `{TICKET-ID}` trong tên file hoặc field `UC / Ticket` của metadata request.
284
+ UC3 "Xuất báo cáo"
285
+ BR8 tối đa 5 file mỗi lần
286
+ BR9 chỉ xuất được đơn đã duyệt
287
+ AC5 người dùng xuất được nhiều đơn trong một lần
288
+ UC4 …
289
+ ```
290
+ 3. **KHÔNG tự suy** target từ một mô tả mơ hồ (*"sửa cái giới hạn file ấy"*). Trình danh sách ứng
291
+ viên rồi để PO chốt. Đoán sai ở đây là sửa sai một yêu cầu đã duyệt.
290
292
 
291
- | `Status` của request | Xử lý |
292
- |---|---|
293
- | `accepted` | Đưa `Requested behavior` + `Suggested AC` vào làm **nguyên liệu** cho Bước 3. **KHÔNG chèn thẳng vào PRD** — đây là yêu cầu nghiệp vụ, phải qua PO chốt AC/BR đúng tầng. |
294
- | `Open` (chưa ai xử) | **Trình cho PO ngay ở CHECKPOINT** kèm số ngày chờ: *"có {n} request chưa xử lý, đưa vào lần này không?"*. PO chọn từng cái. |
295
- | `rejected` / `incorporated` | Bỏ qua. |
293
+ Với **mỗi** target, phân giải **UC sở hữu** ngay (dùng `all_br` / `all_ac`) lưu vào
294
+ `affected_ucs`. ID không phân giải được về UC nào → **DỪNG**, báo ID sai; đừng sửa mò.
296
295
 
297
- Lưu danh sách request sẽ xử (`incoming_requests`) Bước 6.5 sẽ đóng dấu chúng.
296
+ ### Hai chế độ những lệnh này **KHÔNG** làm
298
297
 
299
- ---
298
+ | Chế độ | Cờ | Làm gì |
299
+ |---|---|---|
300
+ | **Sửa nội dung** *(mặc định)* | — | Đổi nội dung của ID đã có. ID **giữ nguyên**. |
301
+ | **Khai tử tại chỗ** | `--retire {ID}` | Đánh dấu ID là không còn hiệu lực **NHƯNG GIỮ NGUYÊN row/ID** (xem Bước 4). |
300
302
 
301
- ## Bước 3Discovery delta *(CHỈ phần thêm)*
303
+ **Ngoài phạm viroute đi chỗ khác, đừng làm ở đây:**
302
304
 
303
- *Tái dùng đúng các phase của `/define-product` áp dụng được cho một phần thêm. **KHÔNG** lặp Phase 0 (Knowledge Sync — bối cảnh hệ thống đã có trong PRD), Phase 2 (User Flow toàn feature), Phase 7 (Validation Report toàn feature).*
305
+ | PO muốn | Lệnh đúng | sao không phải lệnh này |
306
+ |---|---|---|
307
+ | Thêm UC/AC/BR mới | `/extend-prd` | Nó có Discovery delta + đánh số nối tiếp. Lệnh này **không đánh số mới** bao giờ |
308
+ | **XOÁ HẲN** một dòng BR/AC/UC | *(không có, và có chủ ý)* | Xoá row làm `@trace.business_rules` trong mọi `.feature` đã sinh trỏ vào ID không còn ⇒ đúng hình dạng `TRACE_ORPHAN`. Dùng `--retire` — nó đạt cùng mục đích nghiệp vụ mà **không** phá liên kết |
309
+ | Sửa lỗi mà `/refine-prd` vừa chỉ ra | `/refine-prd --resume` | Nó đã có findings + `applied_to_version` để theo dõi delta |
304
310
 
305
- **Áp Discovery Contract của `/define-product`:** input của PO (kể cả nội dung request ở Bước 2) là **nguyên liệu thô**, KHÔNG phải câu trả lời thay phỏng vấn. Item đã phủ trình bản nháp `🤖 trích từ input` rồi hỏi PO xác nhận/sửa; chỉ khi PO chốt mới nâng thành `✅ PO xác nhận`. **Không có luật skip-if-answered.**
311
+ **Guard PRD chưa `approved`:** nếu `current_status != approved`cảnh báo mềm, không chặn:
312
+ ```
313
+ ⚠️ PRD đang ở Status: {status} (chưa approved).
314
+ Sửa một yêu cầu CHƯA được duyệt thì thường không cần lệnh này — cứ hoàn tất vòng review
315
+ hiện tại (/review-context → /refine-prd → PO duyệt) là nội dung sẽ đúng.
316
+ Vẫn sửa tại chỗ bây giờ? (Y/N)
317
+ ```
306
318
 
307
- | Phase | Nội dung | Ghi chú |
308
- |---|---|---|
309
- | **3.1** | **Định nghĩa phần thêm** — bối cảnh · vấn đề · phạm vi in/out · actor · pre/post-condition | Tương ứng Phase 1 của `/define-product`, thu hẹp vào phần mới |
310
- | **3.2** | **Va chạm với cái đã có** ⭐ | Xem dưới — đây là phase KHÔNG có trong `/define-product` |
311
- | **3.3** | **Business Rule** cho phần thêm | Phase 4 |
312
- | **3.4** | **Business Logic** | Phase 5 |
313
- | **3.5** | **Acceptance Criteria** | Phase 6 — giữ tầng: AC = outcome quan sát được + ref BR, cơ chế nằm ở BR/BL |
319
+ ---
314
320
 
315
- ### 3.2 — Kiểm va chạm *(bắt buộc, không bỏ qua)*
321
+ ## Bước 2 — Kiểm va chạm *(bắt buộc, không bỏ qua)*
316
322
 
317
- *`/define-product` không phase này vì lúc đó chưa có gì để va chạm. đây thì va chạm âm thầm cách một PRD tự mâu thuẫn.*
323
+ *Tái dùng đúng **Bước 3.2** của `/extend-prd`, đảo hướng: đó câu hỏi"phần THÊM làm cái
324
+ sai không"; ở đây là "cái SỬA có làm phần còn lại sai không". Cùng ba câu, cùng lý do — va chạm âm
325
+ thầm là cách một PRD tự mâu thuẫn.*
318
326
 
319
- Đối chiếu phần thêm với `existing_ucs` + toàn bộ BR hiện có, hỏi PO ba câu:
327
+ Với **mỗi** target, đối chiếu nội dung mới với toàn bộ PRD hỏi PO:
320
328
 
321
- 1. **Mâu thuẫn rule:** phần thêm có làm một BR hiện trở nên sai/không đủ không? *(vd BR cũ nói "tối đa 5 file", phần mới cần 20)* → nếu có, đây là **sửa BR cũ**, không phải thêm BR mới. Ghi rõ để Bước 5 sửa đúng chỗ và Bước 6 tính bump **major**.
322
- 2. **Trùng lặp:** phần thêm đã được một UC/AC hiện phủ một phần chưa? → nếu có, hỏi PO: **mở rộng UC cũ** hay **tạo UC mới**. Đừng tự quyết.
323
- 3. **Phụ thuộc:** phần thêm cần dữ liệu/năng lực từ UC khác hoặc service khác không? bổ sung vào **§1c Phụ thuộc liên service**.
329
+ 1. **Mâu thuẫn ngược:** giá trị/hành vi mới có làm một BR **khác** trở nên sai hoặc không đủ không?
330
+ *(BR8 nâng 5→20, nhưng BR12 nói "gộp tối đa 5 file vào một hoá đơn")* → nếu có, **BR12 cũng phải
331
+ vào `amend_targets`**. Đây do bước này không bỏ qua được: sửa một nửa của một cặp ràng buộc
332
+ là tạo một PRD tự mâu thuẫn, và không cờ nào bắt được mâu thuẫn nội bộ của tài liệu.
333
+ 2. **AC lệch theo:** AC nào đang ref target này có còn diễn tả đúng outcome không? → nếu không, AC đó
334
+ vào `amend_targets`.
335
+ 3. **Phụ thuộc liên service:** thay đổi có đụng cam kết ở **§1c** không? → cập nhật §1c (mức nghiệp vụ).
324
336
 
325
- Kết quả 3.2 quyết định hình dạng thay đổi:
337
+ Mỗi câu trả lời "có" **mở rộng `amend_targets`** — và `affected_ucs` mở rộng theo. Chốt lại danh sách
338
+ trước khi sang CHECKPOINT.
326
339
 
327
- | Kết quả | Bước 5 làm gì |
328
- |---|---|
329
- | Thuần thêm mới | Append UC/AC/BR mới. Không đụng nội dung cũ. |
330
- | Có sửa BR cũ | Sửa **tại chỗ** BR đó (Edit) **+** append phần mới. Nêu rõ trong changelog. |
331
- | Mở rộng UC cũ | Append AC/BR mới **vào UC đó**, không tạo UC mới. |
340
+ ### CHECKPOINT trước khi ghi
332
341
 
333
- **CHECKPOINT** trước khi ghi:
334
342
  ```
335
- CHECKPOINT — Extend PRD {TICKET-ID}
343
+ CHECKPOINT — Amend PRD {TICKET-ID}
336
344
  ─────────────────────────────────────────────────
337
- PRD : v{current_version} ({current_status}) — {n} UC hiện có
338
- Thêm : UC{max_uc+1} "{tên}" [hoặc: mở rộng UC{k}]
339
- +{n} AC (AC{max_ac+1}…) · +{m} BR (BR{max_br+1}…)
340
- Sửa cái cũ : {danh sách BR/AC bị sửa do va chạm — hoặc "không"}
341
- Từ request : {danh sách file request được đưa vào hoặc "không"}
342
- Version : {current} {new} ({major|minor}) · Status → draft
343
- BDD ảnh hưởng: cần /generate-bdd cho UC mới; {n} UC KHÔNG phải gen lại
345
+ PRD : v{current_version} ({current_status}) — {n} UC
346
+ Sửa : UC3-BR8 "tối đa 5 file""tối đa 20 file"
347
+ UC3-AC5 {tóm tắt thay đổi}
348
+ Khai tử : {UC4-BR15 (--retire) | không}
349
+ Va chạm : {UC5-BR12 cũng phải sửa (mâu thuẫn với BR8 mới) | không}
350
+ UC ảnh hưởng: UC3, UC5 ← sẽ {changelog_scope}
351
+ Version : v{current} v{new} ({major|minor}) · Status draft
352
+
353
+ Sau khi ghi, các UC trên BẮT BUỘC:
354
+ /generate-bdd → /generate-code → /dev-gen-test → /dev-run-test
355
+ ❌ KHÔNG dùng --realign-prd-version cho chúng (nội dung đổi thật)
356
+
357
+ BDD đã sinh sẽ lỗi thời: {danh sách UC × platform}
344
358
 
345
359
  Tiếp tục? (Y/N)
346
360
  ```
347
361
 
348
362
  ---
349
363
 
350
- ## Bước 4Đánh số nối tiếp *(TUYỆT ĐỐI không đánh lại)*
364
+ ## Bước 3Altitude: sửa đúng tầng
351
365
 
352
- | Loại | Quy tắc |
353
- |---|---|
354
- | UC | `UC{max_uc + 1}`, tăng dần |
355
- | BR | `{TICKET-ID}-UC{n}-BR{max_br + 1}` **`max_br` tính trên TOÀN PRD**, không reset theo UC |
356
- | AC | `AC{max_ac + 1}` |
357
-
358
- > **Đây ràng buộc cứng nhất của lệnh này.** Đánh lại ID kể cả để "cho gọn" sẽ phá:
359
- > - `@trace.business_rules` trong mọi `.feature` đã sinh (BR ID churn)
360
- > - dòng "AC liên quan" của từng UC
361
- > - mọi cross-reference `[TICKET-ID](./file.md)` từ PRD khác trỏ tới AC/BR cụ thể
362
- >
363
- > Số bị bỏ trống (do UC bị xoá ở version trước) **để trống vĩnh viễn**. Đừng lấp lại — ID đã từng
364
- > tồn tại có thể còn bị tham chiếu ở BDD, code, bug report, hoặc PRD khác.
366
+ *Giống `/extend-prd` Bước 5 `/refine-prd` Phase 2 — nêu lại vì đây là chỗ dễ trôi nhất khi sửa
367
+ tại chỗ: PO thường mô tả thay đổi bằng cơ chế, và cách rẻ nhất là nhét cơ chế vào AC.*
368
+
369
+ | Tầng | Chứa | KHÔNG chứa |
370
+ |---|---|---|
371
+ | **AC** | outcome **quan sát/kiểm được** + ref `_(BR: …)_` | số lần retry, timeout, tên cờ, nhánh lỗi vụn, và **không lặp lại nội dung BR nó ref** |
372
+ | **BR** | quy tắc nghiệp vụ (WHAT) giá trị, giới hạn, điều kiện | chi tiết kỹ thuật triển khai |
373
+ | **Business Logic** | trình tự nghiệp vụ (HOW **nghiệp vụ**) | API, cấu trúc dữ liệu, thư viện |
374
+
375
+ Thay đổi **cơ chế** PO đang muốn nhét vào AC → **route xuống BR/BL**, AC chỉ giữ outcome + ref.
376
+
377
+ **Chạy Business Language Guard trên MỌI text mới TRƯỚC khi ghi.**
365
378
 
366
379
  ---
367
380
 
368
- ## Bước 5 — Ghi vào PRD *(Edit add-only, KHÔNG Write)*
381
+ ## Bước 4 — Ghi *(Edit tại chỗ · guard sau-ghi ĐẢO NGƯỢC)*
369
382
 
370
- > **Kỷ luật EXTEND copy nguyên từ `/generate-code` §File Scan, cùng lý do:**
383
+ > **Đây chỗ lệnh này khác MỌI thao tác ghi khác trong framework.** `/extend-prd` guard bằng
384
+ > *"output là **superset chặt** của bản cũ"*. Ở đây output **cố ý KHÔNG** phải superset — nên guard
385
+ > phải đảo: **mọi thứ giữ nguyên NGOẠI TRỪ đúng các ID trong `amend_targets`.**
371
386
  >
372
- > 1. **Đọc lại file trên disk NGAY TRƯỚC khi ghi** (không dựa vào bản nạp Bước 1 thể đã đổi).
373
- > 2. **CHỈ dùng Edit để THÊM.** **CẤM tuyệt đối Write cả file.** Đây là nguyên nhân số 1 xoá nghiệp vụ đã duyệt.
374
- > 3. Output PHẢI là **superset chặt** của bản cũ: **mọi** UC, AC, BR, row bảng, dòng changelog, cross-reference cũ **còn nguyên si** — trừ đúng những chỗ Bước 3.2 kết luận là "sửa BR cũ", và chỉ đúng những chỗ đó.
375
- > 4. **Guard sau-ghi (bắt buộc):** đọc lại file vừa ghi, đối chiếu với bản trước khi sửa. Kiểm: mọi UC-ID cũ · mọi BR-ID cũ · mọi AC cũ · mọi row `# Change Log` cũ **vẫn còn**. Nếu **mất bất kỳ cái nào** → **DỪNG NGAY, khôi phục file về bản cũ** (`git checkout -- {file}` nếu đã commit, hoặc hoàn tác edit), báo:
376
- > ```
377
- > ❌ EXTEND làm mất {UC/AC/BR/changelog row} — đã chặn clobber.
378
- > File đã khôi phục. Sửa lại theo add-only rồi chạy lại.
379
- > ```
380
- > **KHÔNG** tiếp tục sang Bước 6.
381
-
382
- Vị trí ghi từng loại nội dung:
383
-
384
- | Nội dung | Đặt ở đâu |
385
- |---|---|
386
- | UC mới | **Cuối §3**, sau UC hiện có cuối cùng. Đủ Actor · Description · Pre-condition · Post-condition · bảng BR · dòng "AC liên quan" |
387
- | AC mới | **Cuối §2**, kèm ref `_(BR: …)_` trỏ về BR tương ứng |
388
- | BR mới | Bảng BR của UC sở hữu. **Giữ đúng hình dạng bảng hiện có** (3 cột hay đã mở cột) — đừng đổi hình dạng ở lệnh này |
389
- | Phụ thuộc mới | **§1c Phụ thuộc liên service** — append, mức nghiệp vụ |
390
- | Màn hình mới | **§4b Wireframe** — nguồn coverage cho `/generate-bdd` C.1 |
391
- | Quy ước mới dùng ≥2 chỗ | **§1d**, khai MỘT LẦN, AC/BR trỏ tới thay vì chép |
387
+ > Guard yếu hơn không được: một lệnh được phép sửa nội dung đã duyệt không rào chính xác
388
+ > đúng cái `/generate-prd` bị chặn-cứng để tránh.
392
389
 
393
- **Altitude khi viết** *(giống `/refine-prd` Phase 2)*: AC = **outcome quan sát/kiểm được + ref BR**, KHÔNG chứa cơ chế (số lần retry, timeout, tên cờ, nhánh lỗi vụn) cơ chế nằm ở BR/BL. AC không lặp lại nội dung BR ref.
390
+ 1. **Đọc lại file trên disk NGAY TRƯỚC khi ghi** — không dựa vào bản nạp Bước 1.
391
+ 2. **CHỈ dùng Edit.** **CẤM tuyệt đối Write cả file.**
392
+ 3. **KHÔNG đánh số lại bất kỳ ID nào.** Không thêm ID mới (đó là `/extend-prd`). Không xoá row.
393
+ 4. Chế độ `--retire {ID}`: **giữ nguyên row và ID**, đổi nội dung thành dạng khai tử rõ ràng —
394
+ `~~{nội dung cũ}~~ **(không còn hiệu lực từ v{new})**` — và thêm một dòng nêu lý do nghiệp vụ.
395
+ *Không xoá row vì `@trace.business_rules` trong `.feature` đã sinh đang trỏ vào ID này; xoá nó
396
+ biến một liên kết hợp lệ thành `TRACE_ORPHAN` 🔴.*
394
397
 
395
- **Chạy Business Language Guard trên MỌI text mới TRƯỚC khi ghi** đừng để phần thêm kéo thuật ngữ kỹ thuật/UI vào một PRD đang sạch.
398
+ ### Guard sau-ghi *(bắt buộcDỪNG nếu fail)*
396
399
 
397
- ---
400
+ Đọc lại file vừa ghi, đối chiếu với bản trước khi sửa. Kiểm **hai chiều**:
401
+
402
+ | Chiều | Kiểm gì | Fail nghĩa là |
403
+ |---|---|---|
404
+ | **Bảo toàn** | Mọi UC-ID · BR-ID · AC-ID · row `# Change Log` cũ **vẫn còn** (kể cả ID vừa `--retire`) | Đã xoá thứ không được xoá |
405
+ | **Giới hạn** | **Mọi** nội dung đã đổi đều thuộc một ID trong `amend_targets` — **không có** chỗ nào khác đổi | Đã sửa lan ra ngoài phạm vi PO chốt |
398
406
 
399
- ## Bước 6 Bump version & ghi changelog
407
+ Fail bất kỳ chiều nào **DỪNG NGAY, khôi phục file về bản cũ** (`git checkout -- {file}` nếu đã
408
+ commit, hoặc hoàn tác edit), báo:
409
+ ```
410
+ ❌ AMEND vi phạm phạm vi — đã chặn.
411
+ {Mất: UC3-BR9 | Sửa ngoài phạm vi: UC7-BR22 (không có trong amend_targets)}
412
+ File đã khôi phục. Chỉ sửa đúng ID đã chốt rồi chạy lại.
413
+ ```
414
+ **KHÔNG** tiếp tục sang Bước 5.
400
415
 
401
- *Tái dùng **nguyên** `### Phase 3` của `/refine-prd`. Không viết lại luật ở đây — dòng changelog là **contract**: `/generate-bdd` Version Check đọc nó để quyết cập nhật hẹp (Y) hay gen lại toàn bộ (F), và `/validate-traces` Step 4/5 đọc nó để lọc `PRD_DRIFT` 🟠 vs `PRD_STALE_REF` ⓘ. Viết kiểu khác là làm hỏng cả hai.*
416
+ > ** sao chiều "Giới hạn" quan trọng bằng chiều "Bảo toàn":** `{changelog_scope}` Bước 5 dựng từ
417
+ > `amend_targets`. Nếu bản ghi lỡ sửa một UC không có trong danh sách đó, thì changelog **không nêu**
418
+ > UC ấy ⇒ `/validate-traces` xếp nó vào ⓘ `PRD_STALE_REF` ⇒ `--realign-prd-version` **mở cửa** và dán
419
+ > nhãn version lại lên một thay đổi chưa ai implement. Đúng hình dạng G53, chỉ đến từ một hướng khác.
420
+
421
+ ---
422
+
423
+ ## Bước 5 — Bump version & ghi changelog
402
424
 
403
425
  1. Loại bump:
404
- - **major** (X.0 → X+1.0): thêm UC mới · sửa BR cũ theo hướng breaking · tái cấu trúc scope. *(Thêm UC là major theo định nghĩa của `/refine-prd` Phase 3.)*
405
- - **minor** (x.Y x.Y+1): chỉ thêm AC/BR vào UC đã có, không đổi hành vi cũ.
406
- 2. Cập nhật Metadata: `Version` = mới · `Updated` = hôm nay · **`Status` = `draft`** *(thêm yêu cầu = phải duyệt lại)*.
426
+ - **major** (X.0 → X+1.0): đổi hành vi theo hướng **breaking** · `--retire` một BR/AC · tái cấu
427
+ trúc scope. *(Đổi một giới hạn nghiệp vụ 5→20 **major** code hiện tại đang chặn ở 5, tức
428
+ đang sai so với spec mới.)*
429
+ - **minor** (x.Y → x.Y+1): làm rõ diễn đạt mà **không** đổi hành vi nghiệm thu được.
430
+ 2. Cập nhật Metadata: `Version` = mới · `Updated` = hôm nay · **`Status` = `draft`**
431
+ *(yêu cầu đã duyệt vừa đổi ⇒ con dấu duyệt cũ hết hiệu lực — đồng bộ `/refine-prd`, `/extend-prd`.)*
407
432
  3. Thêm row lên **đầu** bảng `# Change Log`:
408
433
  ```
409
- | {new_version} | {today} | {tóm tắt — BẮT BUỘC nêu UC/AC/BR bị ảnh hưởng} |
434
+ | {new_version} | {today} | {changelog_scope} |
410
435
  ```
411
- **Ví dụ đúng:** `thêm UC7 (xuất nhiều file): AC12-AC14, BR21-BR23; sửa BR8 (nâng giới hạn 5→20)`
412
- **Ví dụ SAI:** `cập nhật theo yêu cầu mới` ← mơ hồ `/generate-bdd` sẽ khuyến nghị gen lại **toàn bộ**, và `/validate-traces` sẽ gắn `PRD_DRIFT` 🟠 cho **mọi** UC thay vì chỉ UC mới. Một dòng viết ẩu làm mất cả hai bộ lọc.
413
- 4. Cập nhật dòng đầu section: `> Hiện tại: **v{new}** ({today}) · Lịch sử đầy đủ → [changelog](./changelog/{TICKET-ID}-{prd-slug}.changelog.md)`
414
- 5. **Rollover** (cửa sổ trượt 5 row): bảng `# Change Log` vượt **5** row chuyển mọi row vượt 5 (cũ nhất) sang **đầu** bảng của `{specs_dir}/{domain}/{prd-slug}/changelog/{TICKET-ID}-{prd-slug}.changelog.md`; PRD giữ 5 row gần nhất. Tạo dir + file theo skeleton của `/refine-prd` Phase 3 nếu chưa có.
415
-
416
- ---
417
-
418
- ## Bước 6.5 — Đóng dấu request đã xử lý
436
+ **`{changelog_scope}` mỗi mệnh đề mở đầu bằng UC SỞ HỮU** *(contract:
437
+ `bin/trace-schema.json` → `changelog_row_contract`)*. Nguồn: `affected_ucs` đã chốt Bước 2
438
+ tức **UC sở hữu của từng ID trong `amend_targets`**. Ngăn nhau bằng `;`. Thay đổi §1c/§1d
439
+ (không thuộc UC nào) → `PRD-global`.
419
440
 
420
- Với mỗi file trong `incoming_requests` đã được PO chốt và nội dung đã ghi vào PRD:
441
+ **Ví dụ đúng**
442
+ ```
443
+ | 2.0 | 2026-08-19 | UC3: sửa BR8 (giới hạn 5→20 file), AC5 theo đó; UC5: sửa BR12 (bỏ ràng buộc gộp 5) |
444
+ | 3.0 | 2026-08-22 | UC4: khai tử BR15 (không còn yêu cầu duyệt hai cấp) |
445
+ ```
421
446
 
422
- 1. Đặt `Status: incorporated` trong file request.
423
- 2. Thêm dòng `Incorporated into: v{new_version}`để lần sau tra được yêu cầu nào vào version nào.
424
- 3. Chuyển file sang `{paths.prd_change_requests_dir}/archived/` (tạo dir nếu cần).
425
- 4. **Commit + push** spec repo (giống `feedback/` — xem `/propose-scenario` Step 5): `git add feedback/prd-change-requests/ && git commit -m "po(prd-change): {TICKET-ID} — incorporated into v{new}" && git push`. Không có quyền push → mở PR/MR và in fallback.
447
+ ⚠️ **BR/AC không bao giờ đứng một mình.** `sửa BR8` (thiếu `UC3:`) nêu đủ ID để **không** bị coi
448
+ hồ, nhưng consumer khớp theo **UC** nên UC3 rơi vào `--realign` dán nhãn lại lên
449
+ đúng thay đổi này. **Lệnh này producer dễ mắc lỗi đó nhất**, vì đầu vào của nó *là* một BR-ID.
426
450
 
427
- Request mà PO **không** chốt lần này → **để nguyên** `Status: Open`. `/validate-traces` Step 7b sẽ tiếp tục nhắc kèm số ngày chờ.
451
+ ⚠️ **KHÔNG dùng hậu tố `[no-behavior]` lệnh này.** dành cho fix producer **chứng minh
452
+ được** là thuần cấu trúc (`changelog_row_contract.neutral_checks`). Lệnh này tồn tại để đổi **nội
453
+ dung nghiệp vụ** — theo định nghĩa là có đổi hành vi.
454
+ 4. Cập nhật dòng đầu section: `> Hiện tại: **v{new}** ({today}) · Lịch sử đầy đủ → [changelog](./changelog/{TICKET-ID}-{prd-slug}.changelog.md)`
455
+ 5. **Rollover** (cửa sổ trượt 5 row) — theo đúng quy ước `/refine-prd` Phase 3.
428
456
 
429
457
  ---
430
458
 
431
- ## Bước 7 — Report
459
+ ## Bước 6 — Report
432
460
 
433
461
  **Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·
434
462
  Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
@@ -436,51 +464,55 @@ Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
436
464
  Ví dụ footer cho lệnh này:
437
465
 
438
466
  ```
439
- /extend-prd Đã thêm — {TICKET-ID} {tên feature}
467
+ /amend-prd Đã sửa — {TICKET-ID} {tên feature}
468
+
469
+ Version : v1.3 → v2.0 (major) · Status → draft
470
+ Sửa : UC3-BR8 "tối đa 5 file" → "tối đa 20 file"
471
+ UC3-AC5 diễn đạt lại outcome theo BR8 mới
472
+ UC5-BR12 bỏ ràng buộc gộp 5 (va chạm với BR8 mới — Bước 2 câu 1)
473
+ Khai tử : không
474
+ Changelog : | 2.0 | 2026-08-19 | UC3: sửa BR8 (giới hạn 5→20 file), AC5 theo đó; UC5: sửa BR12 |
475
+
476
+ Guard sau-ghi : ✅ Bảo toàn — {n} UC · {m} AC · {k} BR · {j} changelog row cũ còn nguyên
477
+ ✅ Giới hạn — 0 chỗ đổi ngoài amend_targets
440
478
 
441
- Version : v{old} v{new} ({major|minor}) · Status draft
442
- Thêm : UC{N} "{tên}" · AC{a}-AC{b} · BR{c}-BR{d}
443
- Sửa cũ : {BR8 nâng giới hạn 5→20 | không}
444
- Request : {2 file archived/ (incorporated v{new}) | không}
445
- Changelog : | v{new} | {today} | thêm UC{N}: AC{a}-AC{b}, BR{c}-BR{d}; sửa BR8 |
479
+ 🔴 UC PHẢI làm lại (nội dung đổi thật): UC3, UC5
480
+ /generate-bdd {prd-file} BDD hiện tại đang nghiệm thu giới hạn 5
481
+ /generate-code {UC-ID} ← code đang chặn 5
482
+ /dev-gen-test → /dev-run-test test đang assert 5 và vẫn PASS
483
+ TUYỆT ĐỐI KHÔNG --realign-prd-version cho UC3/UC5 đó dán nhãn lên thay đổi
484
+ chưa ai implement.
446
485
 
447
- Guard sau-ghi : {n} UC · {m} AC · {k} BR · {j} changelog row cũ — còn nguyên
486
+ BDD sẽ lỗi thời: bdd/system/{TICKET-ID}-UC3.feature · bdd/web/{TICKET-ID}-UC3.feature
448
487
 
449
- UC KHÔNG đổi ({n}): {UC1, UC2, UC3…}
450
- KHÔNG cần /generate-bdd hay /generate-code cho các UC này.
451
- /validate-traces sẽ xếp chúng vào ⓘ PRD_STALE_REF (nhãn version cũ, nội dung không đổi).
452
- Sạch bằng: /validate-traces --realign-prd-version {UC-ID}
488
+ UC KHÔNG đổi ({n}): {UC1, UC2, UC4…}
489
+ PRD_STALE_REF. Sạch bằng: /validate-traces --realign-prd-version {UC-ID}
453
490
 
454
- ⚠️ Status đã reset về draft — phần thêm chưa được duyệt.
491
+ ⚠️ Status đã reset về draft — thay đổi chưa được duyệt lại.
455
492
 
456
493
  ---
457
494
  Status : ✅ Complete
458
495
  Output Artifacts:
459
- updated {paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md (v{new})
496
+ updated {paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md (v2.0)
460
497
  updated {paths.specs_dir}/{domain}/{prd-slug}/changelog/… (nếu có rollover)
461
- updated {paths.prd_change_requests_dir}/archived/… (nếu có request)
462
498
  Pipeline : Discovery → [PRD ◀ bạn ở đây] → Design Spec → BDD → Tech Design → Code → Dev Self-Check → QC → Trace Audit
463
- Next : /refine-prd {prd-file} soi phần vừa thêm qua 3 lăng kính
464
- /review-context {prd-file} ← kiểm chất lượng trước khi sinh BDD
465
- khi sạch critical, PO đặt Status: approved, rồi:
466
- • Feature CÓ màn hình → /generate-design-spec {prd-file} (design-spec sẽ tự
467
- phát hiện lỗi thời vs PRD mới và bắt sign-off lại) rồi /generate-bdd
468
- • Thuần backend → /generate-bdd {prd-file} thẳng
469
- → CHỈ gen BDD/code cho UC MỚI. UC cũ: dùng --realign-prd-version.
499
+ Next : /review-context {prd-file} kiểm chất lượng phần vừa sửa
500
+ khi sạch critical, PO đặt Status: approved
501
+ /generate-bdd {prd-file} ← CHỈ cho UC3, UC5
470
502
  ```
471
503
 
472
504
  ---
473
505
 
474
506
  ## Quality Checklist *(kiểm trước khi ghi)*
475
507
 
476
- - [ ] **Không đánh lại BẤT KỲ ID cũ nào** — UC/AC/BR mới đều `max + 1`; số bị bỏ trống vẫn để trống
477
- - [ ] `max_br` tính trên **toàn PRD**, không reset theo UC
478
- - [ ] Guard sau-ghi đã chạyPASS: mọi UC/AC/BR/changelog row còn nguyên
479
- - [ ] Bước 3.2 đã hỏi đủ 3 câu va chạm (mâu thuẫn rule · trùng lặp · phụ thuộc)
480
- - [ ] Mỗi AC mới ≥1 ref `_(BR: …)_`; mỗi UC mới dòng "AC liên quan"; hai chiều khớp nhau
481
- - [ ] Dòng changelog **nêu rõ UC/AC/BR** không hồ *(contract cho `/generate-bdd` + bộ lọc `PRD_STALE_REF`)*
508
+ - [ ] `amend_targets` do **PO khai tường minh** — không suy từ tả hồ
509
+ - [ ] Mỗi target đã phân giải được **UC sở hữu**; ID không phân giải được → đã DỪNG
510
+ - [ ] Bước 2 đã hỏi đủ 3 câu va chạm, và mọi ID phát sinh **đã được thêm** vào `amend_targets`
511
+ - [ ] **KHÔNG** đánh số lại ID nào · **KHÔNG** thêm ID mới · **KHÔNG** xoá row nào
512
+ - [ ] `--retire` giữ nguyên row + ID (chỉ đổi nội dung sang dạng khai tử)
513
+ - [ ] Guard sau-ghi PASS **cả hai chiều**: Bảo toàn **và** Giới hạn
514
+ - [ ] Altitude đúng tầng: cơ chế nằm ở BR/BL, AC chỉ outcome + ref
515
+ - [ ] `{changelog_scope}`: mỗi mệnh đề **mở đầu bằng UC sở hữu**; **không** BR/AC đứng một mình; **không** `[no-behavior]`
482
516
  - [ ] `Status` đã reset về `draft`
483
- - [ ] Hình dạng bảng BR giữ nguyên như cũ (không đổi 3-cột ↔ mở-cột ở lệnh này)
484
517
  - [ ] Không có banned term; 0 thuật ngữ kỹ thuật/UI trong text mới
485
- - [ ] Request đã xử `incorporated` + `archived/` + commit; request chưa xử → giữ `Open`
486
- - [ ] Report nêu rõ danh sách **UC không đổi** + route `--realign-prd-version` cho chúng
518
+ - [ ] Report nêu **UC PHẢI làm lại** kèm lệnh, **cấm tường minh** `--realign` cho chúng
@@ -341,17 +341,55 @@ report Living Docs ở spec module (qua `/sync` + `/validate-traces`). Các file
341
341
  Cập nhật **sổ của platform đang test** `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv` (`{platform}` = platform của code/`.feature` đang test — `system` cho backend, `web`/`app` cho FE/App; nếu `domain`/`prd_slug` không phân giải được từ spec target, định vị TSV bằng cách glob `{paths.trace_dir}/**/{UC-ID}-{platform}.tsv` — nó được tạo trước đó bởi `/generate-bdd`) — cho mỗi scenario row (khớp `sc_id` qua tag
342
342
  `@trace.verifies={UC-ID}-SC{N}` của test). *(Umbrella + `spec_source`: `trace_dir` là `{spec_source}/.trace` — test chạy từ `service_root` nhưng update `dev_selftest` ghi vào **spec repo**; commit/push spec submodule cho nó.)*
343
343
 
344
- | Cột | Giá trị |
345
- |--------|-------|
346
- | `dev_selftest` | `pass` nếu mọi test của SC này pass · `fail` nếu cái fail · `not_run` nếu test của nó bị skip/vắng |
347
- | `dev_selftest_at` | hôm nay `YYYY-MM-DD` |
348
- | `last_updated` | hôm nay `YYYY-MM-DD` |
344
+ ### ĐỌC cột `status` của row TRƯỚC KHI GHI *(bắt buộc)*
345
+
346
+ *Contract: `bin/trace-schema.json` `positive_assertion_guards`. Dữ liệu đãtrong sổ không phát sinh I/O.*
347
+
348
+ `pass` **không** mang nghĩa *"test đã chạy và xanh"*. Nó mang nghĩa **"scenario này đã được nghiệm thu theo spec HIỆN TẠI"**. Nên trước khi ghi nó, đọc `status` của đúng row đó:
349
+
350
+ | `status` của row | `dev_selftest` ghi gì | `dev_selftest_at` |
351
+ |---|---|---|
352
+ | `OK` · `GAP` · `UNTRACKED` | `pass` nếu mọi test của SC này pass · `fail` nếu có cái fail · `not_run` nếu test bị skip/vắng | hôm nay |
353
+ | **`DRIFT`** | test **pass** → **`not_run`** *(KHÔNG ghi `pass`)* · test **fail** → **`fail`** như thường | `—` nếu ghi `not_run`; hôm nay nếu ghi `fail` |
354
+ | **`ORPHANED`** | **`not_run`** — scenario đã bị xoá khỏi `.feature`, không còn gì để nghiệm thu | `—` |
355
+
356
+ `last_updated` = hôm nay, mọi trường hợp.
357
+
358
+ **Tin xấu luôn hợp lệ.** Đây là guard cho lời khẳng định **DƯƠNG**, không phải lệnh *"bỏ qua kết quả khi DRIFT"*. Test đỏ trên row DRIFT vẫn là thông tin thật và phải được ghi. Chỉ `pass` cần giấy phép.
359
+
360
+ **Khi ghi `not_run` vì `DRIFT`/`ORPHANED`, in ngay:**
361
+ ```
362
+ ⚠️ {sc_id} — test XANH nhưng row đang {DRIFT | ORPHANED}, nên KHÔNG ghi pass.
363
+ {DRIFT: spec đã đổi sau lần codegen (spec_ver {a} ≠ gen_ver {b}) — test hiện tại đang
364
+ nghiệm thu một hành vi không còn tồn tại.
365
+ Làm: /generate-code {UC-ID} → /dev-gen-test {UC-ID} → chạy lại lệnh này.}
366
+ {ORPHANED: scenario đã bị xoá khỏi .feature nhưng code+test còn. Xử theo /validate-traces.}
367
+ ```
368
+
369
+ > **Vì sao bước này bắt buộc (GAPS-v4 G55).** Bản cũ ghi `pass` chỉ dựa vào *test có xanh không*, và
370
+ > khai `dev_selftest` **trực giao** với `status`. Trực giao về *kết quả chạy* thì đúng — nhưng
371
+ > **không** trực giao về *quyền được khẳng định*.
372
+ >
373
+ > Chuỗi hỏng, mọi mắt nối đều là hành vi framework tự chỉ định: PO đổi AC → `/generate-bdd` đặt
374
+ > `status = DRIFT` và **hạ** `dev_selftest → not_run` (kèm cảnh báo *"test của SC này viết cho spec
375
+ > cũ"*) → sáng sau dev chạy lệnh này theo thói quen, **chưa** `/generate-code`, **chưa**
376
+ > `/dev-gen-test` → test cũ + code cũ xanh hết → ghi `pass` + **ngày hôm nay**.
377
+ >
378
+ > Tức **lệnh kế tiếp trong vòng lặp dev bình thường dựng lại đúng cái tín hiệu `/generate-bdd` vừa
379
+ > hạ xuống.** README §Philosophy: *"Một tín hiệu đã hết đúng phải bị hạ xuống, không được giữ"* —
380
+ > ở đây còn tệ hơn *giữ*: nó **tái phát hành** với dấu ngày mới.
381
+ >
382
+ > Và thứ duy nhất chở tín hiệu *"test đã lỗi thời"* là **một dòng terminal** từ một lần chạy có thể
383
+ > đã xảy ra tuần trước, trong session của người khác: sổ có 24 cột và **không cột nào** giữ *"test
384
+ > được viết cho `spec_ver` nào"*. Dev không có cách nào biết. Đọc `status` là cách rẻ nhất để biết.
385
+ >
386
+ > **Tầng thứ hai độc lập:** `lint-trace` **T12** bắt đúng trạng thái này ở sổ thật (`status` ∈
387
+ > {DRIFT, ORPHANED} mà `dev_selftest`/`qc_status` = `pass`), bất kể lệnh nào ghi ra — kể cả sổ sửa
388
+ > tay hoặc sổ sinh bởi version framework cũ hơn.
349
389
 
350
390
  Giữ nguyên mọi cột khác — đặc biệt **không bao giờ** đụng `qc_status`/`qc_run_at`
351
- (kết quả QC automation chính thức, do `/qc-run-test` sở hữu). `dev_selftest` (dev smoke)
352
- và `qc_status` (QC chính thức) là hai tín hiệu riêng. `dev_selftest`/`dev_selftest_at` cũng
353
- trực giao với `status` (OK/GAP/DRIFT/UNTRACKED/ORPHANED): `status` theo dõi *coverage*, `dev_selftest`
354
- theo dõi *kết quả chạy* gần nhất của dev.
391
+ (kết quả QC automation chính thức, do `/qc-run-test` sở hữu; guard riêng cùng loại).
392
+ `dev_selftest` (dev smoke) và `qc_status` (QC chính thức) là hai tín hiệu riêng.
355
393
 
356
394
  ## Refresh Panel Mirror
357
395
  # Làm mới panel mirror của Living Docs *(local)*