@educa-corp/sdd-framework 0.2.5 → 0.2.7

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 (73) hide show
  1. package/commands/debug.md +4 -1
  2. package/commands/define-product.md +4 -1
  3. package/commands/dev-gen-test.md +4 -1
  4. package/commands/dev-run-test.md +4 -1
  5. package/commands/dev-smoke-test.md +4 -1
  6. package/commands/fix-bug.md +4 -1
  7. package/commands/generate-architecture.md +4 -1
  8. package/commands/generate-bdd.md +4 -1
  9. package/commands/generate-code.md +97 -31
  10. package/commands/generate-code.tmpl +93 -30
  11. package/commands/generate-design-spec.md +4 -1
  12. package/commands/generate-prd.md +4 -1
  13. package/commands/generate-spec-manifest.md +4 -1
  14. package/commands/generate-tech-docs.md +244 -247
  15. package/commands/generate-tech-docs.tmpl +2 -0
  16. package/commands/learn.md +4 -1
  17. package/commands/map-testids.md +4 -1
  18. package/commands/propose-scenario.md +4 -1
  19. package/commands/qc-analyze.md +4 -1
  20. package/commands/qc-design-test.md +4 -1
  21. package/commands/qc-plan.md +4 -1
  22. package/commands/qc-report.md +4 -1
  23. package/commands/qc-review.md +4 -1
  24. package/commands/qc-run-test.md +4 -1
  25. package/commands/refine-prd.md +4 -1
  26. package/commands/report-bug.md +4 -1
  27. package/commands/review-code.md +4 -1
  28. package/commands/review-context.md +4 -1
  29. package/commands/review-tech-docs.md +4 -1
  30. package/commands/setup-ai-first.md +2 -1
  31. package/commands/validate-traces.md +4 -1
  32. package/core/FRAMEWORK_VERSION +1 -1
  33. package/core/commands/debug.md +4 -1
  34. package/core/commands/define-product.md +4 -1
  35. package/core/commands/dev-gen-test.md +4 -1
  36. package/core/commands/dev-run-test.md +4 -1
  37. package/core/commands/dev-smoke-test.md +4 -1
  38. package/core/commands/fix-bug.md +4 -1
  39. package/core/commands/generate-architecture.md +4 -1
  40. package/core/commands/generate-bdd.md +4 -1
  41. package/core/commands/generate-code.md +97 -31
  42. package/core/commands/generate-design-spec.md +4 -1
  43. package/core/commands/generate-prd.md +4 -1
  44. package/core/commands/generate-spec-manifest.md +4 -1
  45. package/core/commands/generate-tech-docs.md +244 -247
  46. package/core/commands/learn.md +4 -1
  47. package/core/commands/map-testids.md +4 -1
  48. package/core/commands/propose-scenario.md +4 -1
  49. package/core/commands/qc-analyze.md +4 -1
  50. package/core/commands/qc-design-test.md +4 -1
  51. package/core/commands/qc-plan.md +4 -1
  52. package/core/commands/qc-report.md +4 -1
  53. package/core/commands/qc-review.md +4 -1
  54. package/core/commands/qc-run-test.md +4 -1
  55. package/core/commands/refine-prd.md +4 -1
  56. package/core/commands/report-bug.md +4 -1
  57. package/core/commands/review-code.md +4 -1
  58. package/core/commands/review-context.md +4 -1
  59. package/core/commands/review-tech-docs.md +4 -1
  60. package/core/commands/setup-ai-first.md +2 -1
  61. package/core/commands/validate-traces.md +4 -1
  62. package/core/steps/context-loader.md +2 -0
  63. package/core/steps/gate.md +2 -1
  64. package/core/templates/project-context.yaml +6 -0
  65. package/core/templates/tech-design.template.md +238 -246
  66. package/docs/02-concepts/pipeline-steps/06-code.md +7 -4
  67. package/docs/03-guides/developer.md +6 -3
  68. package/docs/explain/09-generate-code.md +41 -3
  69. package/package.json +1 -1
  70. package/steps/context-loader.md +2 -0
  71. package/steps/gate.md +2 -1
  72. package/templates/project-context.yaml +6 -0
  73. package/templates/tech-design.template.md +238 -246
@@ -27,7 +27,7 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
27
27
 
28
28
  Đọc:
29
29
  1. Chỉ file `.feature` đã giới hạn scope
30
- 2. Tech-doc gộp của PRD tại `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` (nếu tồn tại) — **tra §10 UC Coverage làm mục lục** để định vị scenario/section của UC đang sinh; **endpoint liên quan = §4.1 entries mà §5 lane của UC này gọi tới** (đừng lấy endpoint/section của UC khác). Từ đó đọc §4 API, §4.5 client, §5 flow của đúng UC này
30
+ 2. Tech-doc gộp của PRD tại `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` (nếu tồn tại) — **tra §10 UC Coverage làm mục lục** để định vị scenario/section của UC đang sinh; **endpoint liên quan = §4.1 entries mà §5 lane của UC này gọi tới** (đừng lấy endpoint/section của UC khác). Từ đó đọc §4 API, §4.5 client, §5 flow của đúng UC này. **Đọc thêm §7 (Security & Authorization)** — luật phân quyền/enforce của UC → áp vào code; **và §8 (Error Handling & Edge Cases)** — mỗi row lỗi/biên phải có nhánh xử lý tương ứng trong code (khớp §4.3 error code), đừng chỉ code happy-path.
31
31
  3. CLAUDE.md §architecture + §coding_standards
32
32
  4. **(chỉ FE/App)** Design Spec — nạp qua **Guard** bên dưới (gate approved/độ-tươi + sanity), là nguồn của màn hình, component inventory, và link Figma frame từng-màn.
33
33
 
@@ -50,7 +50,7 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
50
50
  - **Sanity-scan** (như generate-bdd bước 2.5): màn thiếu state loading/error/empty, AC-UI không testable, component `[NEW]`/`[TODO]` chưa chốt, còn ❌ Missing frame → cảnh báo trong cùng CHECKPOINT.
51
51
  - `Status: approved` VÀ `Built from PRD` khớp PRD hiện tại VÀ sạch cờ đỏ → dùng làm nguồn màn hình / component / Figma.
52
52
 
53
- **Tech-doc contract (chỉ backend/system) — DS3:** *áp dụng khi lần sinh này tạo code **backend** — `@trace.platform = system`, HOẶC chế độ default (không `--phase`) với `platform_type = backend`. Bỏ qua FE `--phase=ui`/`--phase=integration` (đã có nguồn shape riêng ở Phase Detection).*
53
+ **Tech-doc contract (chỉ backend/system) — DS3:** *áp dụng khi lần sinh này tạo code **backend** — `@trace.platform = system` (nguồn chuẩn quyết BE/FE, xem Phase Detection). Bỏ qua FE (`@trace.platform` = `web`/`app`) FE có nguồn shape riêng ở Phase Detection.*
54
54
 
55
55
  Định vị tech-doc gộp `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md`, kiểm phần backend của UC này (§4.1 Endpoints / §4.2 Request-Response / §4.3 Error):
56
56
  - **Brownfield** — nếu PRD Metadata `API Source: existing`: contract nằm ở Appendix "Existing API Contract" của PRD → nguồn hợp lệ, **bỏ qua DS3** (không cảnh báo).
@@ -69,13 +69,17 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
69
69
 
70
70
  ## Phase Detection
71
71
 
72
+ > **Nguồn chuẩn quyết BE/FE = `@trace.platform` của FILE FEATURE** (`system` → BE · `web`/`app` → FE). KHÔNG dùng `platform_type` (suy từ module) để quyết BE/FE — nó chỉ dùng cho **idiom stack/module** (cú pháp, layer, thư viện). Lý do: repo fullstack một-module (vd Next.js có API route) có `platform_type` cố định một giá trị, nhưng vẫn có cả feature `system` (BE) lẫn `web` (FE) — chỉ tag của chính feature mới đúng.
73
+
72
74
  Parse `$ARGUMENTS` tìm flag `--phase`:
73
75
 
74
76
  | Flag | Ý nghĩa |
75
77
  |---|---|
76
78
  | `--phase=ui` | FE Phase 1 — sinh UI + layer mock API từ System BDD contract |
77
79
  | `--phase=integration` | FE Phase 2 — thay mock adapter bằng lời gọi API thật từ tech docs |
78
- | *(không có)* | Default — full implementation (BE hoặc full-stack không tách mock) |
80
+ | *(không có)* | Default — full: **BE/`system`** → full backend; **FE (`web`/`app`)** **FE full** (sinh UI + wire API thật trong một lần, không qua bước mock) |
81
+
82
+ **Xác định `fe_full`:** khi **KHÔNG** có `--phase` VÀ `@trace.platform` là `web`/`app` → đây là **FE full mode**. Sinh UI **và** wire API thật trong cùng một lần chạy, **bỏ qua** layer mock. Cụ thể: các section **sinh UI** chạy · **Mock API Layer** bị bỏ (chỉ dành `--phase=ui`) · **DS4** và **Integration Phase** VẪN chạy (xem điều kiện của từng section). BE/`system` ở default vẫn là full backend như trước.
79
83
 
80
84
  **Nếu `--phase` được set — xác nhận platform:**
81
85
  Đọc `@trace.platform` từ header file feature.
@@ -139,20 +143,55 @@ selection context, và code snippet — những thứ một URL web đơn không
139
143
  qua Figma MCP và ground UI trên layout, variable, và mapping Code Connect trả về. Ưu tiên
140
144
  component được map Code-Connect hơn là bịa markup; dùng tên token thật, không phải giá trị hardcode.
141
145
 
142
- **Nếu `--phase=integration`:**
146
+ ---
147
+
148
+ ## Integration Gates — DS4 (contract) · DS5 (reuse)
149
+
150
+ *Áp dụng khi wire API thật: `--phase=integration` **HOẶC** `fe_full`. Bỏ qua `--phase=ui` và default BE.*
151
+
152
+ > **Sequencing ở `fe_full`:** hai cổng này chạy **trước** khi UI/adapter được sinh trong cùng lần chạy, nên chúng suy luận từ **BẢN THIẾT KẾ** (design-spec + tech-doc §4.5) — tức *kế hoạch*, KHÔNG phải code đã sinh. "Port do UI định nghĩa" và "mock adapter có sẵn" chỉ tồn tại ở luồng 2-pha (`--phase=integration` chạy sau `--phase=ui`); ở `fe_full` port thật được chốt tại bước Generate về sau.
153
+
143
154
  Phân giải design điều khiển adapter từ **tech-doc gộp của PRD** `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md`:
144
155
  - **Mapping port→endpoint→DTO→error** (ưu tiên): §4.5.4 (API Integration Layer của platform này) — mỗi client method → endpoint có thật.
145
156
  - **Nguồn endpoint/shape**: §4.1 Endpoints + §4.2 Request-Response + §4.3 Error của cùng doc.
146
157
 
147
- Đọc `@trace.status` của doc. Nếu `draft` hoặc `in-review` cảnh báo:
148
- ```
149
- Tech design {TICKET-ID} (UC {UC-ID} / {platform}) đang {status}.
150
- Contract / mapping adapter cònthể đổi.
151
- Tiếp tục đảm bảo BE endpoint đã deploy hoặc confirm mapping thủ công.
152
- ```
153
- Nếu doc **thiếu §4.5.4** (client integration chưa được vẽ cho platform này)cảnh báo: "Chưa §4.5.4 cho {platform} fallback map trực tiếp từ §4.1 endpoint (mapping adapter được infer). Khuyến nghị: chạy `/generate-tech-docs {web|app .feature}` để bổ sung §4.5 trước."
154
- Định vị mock adapter sẵn từ lần chạy `--phase=ui` (tìm `{UC-ID}MockApiAdapter` trong `{paths.src_dir}/{domain}/`).
155
- Nếu không tìm thấy cảnh báo: "Không tìm thấy mock adapter sinh real API adapter từ đầu dùng contract tech-doc."
158
+ **Client contract gate DS4** *(áp dụng khi `--phase=integration` **HOẶC** `fe_full`; KHÔNG áp dụng `--phase=ui` UI vẫn degrade êm qua mock).* Đối xứng với DS3 của BE: soi §4.5.4 **đủ chưa** cho UC/platform này *trước khi* wire adapter thật.
159
+
160
+ 1. **Xác định phạm vi cần:** các client method mà UC NÀY dùng — lấy từ §10 (định vị scenario của UC) → §4.5.4 rows. Nguồn interface port: `{UC-ID}ApiPort` của mock adapter (`--phase=integration`, đã có từ lần `--phase=ui` trước) HOẶC, ở `fe_full`, port do chính lần chạy này định nghĩa lúc sinh UI (§4.5.3 state + §4.5.4) — chưa có mock adapter.
161
+ 2. **Kiểm tính đủ của §4.5.4 cho từng method:** endpoint (resolve được ở §4.1) + map request + response→model + error→UI. *(Khác cảnh báo cũ: cái cũ chỉ bắt "thiếu HẲN §4.5.4"; DS4 bắt cả "thiếu MỘT PHẦN".)*
162
+ 3. **Phân loại (giống DS3):**
163
+ - **Đủ + `@trace.status: approved` + 0 🔴 blocker-GAP (§12) chạm §4.5.4/UC này** → dùng làm nguồn, KHÔNG hỏi.
164
+ - **`@trace.status` = `draft`/`in-review`, HOẶC §12 còn 🔴 blocker `open` chạm UC này**WARN (không chặn): "contract/mapping adapter chưa chốt / còn {n} blocker-GAP open đảm bảo BE endpoint đã deploy hoặc confirm mapping thủ công; thể rework khi §4.5.4 đổi."
165
+ - **Thiếu §4.5.4, HOẶC khuyết một phần cho method UC cần**
166
+ a. Áp **SRC-CHAIN** (xem §Quy tắc nguồn giá trị) lấp phần thiếu từ nguồn khác (§4.1–4.3, PRD, BDD `Then`, core-entities, mock adapter đã sinh).
167
+ b. Phần SRC-CHAIN giải quyết được → tiếp tục.
168
+ c. Phần **thực sự còn trống** → **CHECKPOINT chặn mềm, GỘP mọi gap vào một lần** (mỗi gap ghi rõ "đã tìm ở: {nguồn}"):
169
+ ```
170
+ ⚠️ §4.5.4 chưa đủ cho {UC-ID}/{platform} — {n} mapping còn trống (đã vét SRC-CHAIN):
171
+ - {client method} → {thiếu gì: endpoint/field/error→UI}
172
+ Wire adapter thật với mapping chưa chốt sẽ phải rework.
173
+ Khuyến nghị (front-load): /generate-tech-docs {web|app .feature} → bổ sung §4.5.4 → /review-tech-docs.
174
+ Vẫn wire bây giờ? (Y = best-effort/giữ mock cho phần thiếu · N = dừng, đi hoàn thiện tech-docs)
175
+ ```
176
+ Chỉ tiếp khi Y. *(Đây là "tư thế BE": trỏ ngược tech-docs thay vì hỏi live từng câu.)*
177
+ **FE component/service reuse gate — DS5** *(áp dụng khi `--phase=integration` **HOẶC** `fe_full`; KHÔNG áp dụng `--phase=ui`).* **Phát hiện & tái dùng** code FE đang tồn tại trước khi dựng mới — chống đẻ adapter/service **song song, mồ côi**, không nối vào app đang chạy.
178
+
179
+ 1. **Định vị mock adapter framework:** tìm `{UC-ID}MockApiAdapter` trong `{paths.src_dir}/{domain}/` (output `--phase=ui`).
180
+ 2. **Discovery code FE có sẵn:** quét `{paths.src_dir}` (phạm vi domain/feature) tìm **component / service / hook / api-client** mà các màn của UC này dùng — đối chiếu: component inventory của **design-spec**, path ở tech-doc **§4.5.2**, tên màn/UC. Lập danh sách "đã tồn tại" vs "chưa có".
181
+ 3. **Quyết định reuse-or-new:**
182
+ - **CÓ mock adapter** (luồng 2-pha chuẩn) → tái dùng port/wiring của nó như cũ; **KHÔNG hỏi**.
183
+ - **KHÔNG có mock adapter NHƯNG discovery thấy component/service có sẵn** (brownfield / chạy integration một mình trên app đang chạy) → **CHECKPOINT hỏi, KHÔNG tự dựng mới:**
184
+ ```
185
+ 🔎 Thấy {N} phần FE đang tồn tại cho màn của {UC-ID}/{platform}:
186
+ - {path} ({component | service | hook | api-client})
187
+ Wire API thật vào code CÓ SẴN này, hay dựng mới?
188
+ R (reuse) — EXTEND/wire adapter vào component/service đang chạy (khuyến nghị)
189
+ N (new) — dựng adapter/service mới (chỉ khi code cũ không tái dùng được — ghi lý do)
190
+ ```
191
+ - **R** → set `reuse_target` = các file có sẵn; Integration Phase **EXTEND/wire vào chúng** (áp Quy tắc EXTEND phi-phá-huỷ + Guard sau-ghi ở §File Scan), KHÔNG tạo file song song.
192
+ - **N** → dựng mới, ghi lý do vào report.
193
+ - **KHÔNG có mock adapter VÀ discovery KHÔNG thấy gì** → greenfield thật → sinh real adapter từ đầu dùng contract tech-doc (không cần hỏi).
194
+ 4. Lưu `reuse_target` (hoặc `none`) cho Integration Phase dùng ở bước wire-up.
156
195
 
157
196
  ---
158
197
 
@@ -182,6 +221,11 @@ Trước khi định vị file, chốt **package đích** theo **Package Layout
182
221
 
183
222
  **Quét module TÁI DÙNG trước khi tạo:** với mỗi layer, kiểm `{code_base_package}.{layer}` đã tồn tại trên disk chưa. Nếu đã có class phục vụ cùng entity/nghiệp vụ → **đặt member mới vào class đó (EXTEND)**, KHÔNG dựng cây layer / class song song. Chỉ tạo mới khi thực sự chưa có.
184
223
 
224
+ **Đặt code FE (`@trace.platform` = web/app):** quy tắc trên là cho BE (Java-style `{package}.{layer}`). FE đặt file theo thứ tự ưu tiên:
225
+ 1. **Path ở tech-doc §4.5.2 (Component File Mapping)** — nếu có, dùng **nguyên văn** đường dẫn cột `Path` (đây là contract đặt file của FE).
226
+ 2. **Else** → gốc `{paths.src_dir}` + quy ước thư mục của module/framework (vd `src/features/{domain}/…` React · `lib/{domain}/…` Flutter). Component/hook/service/adapter của cùng feature nằm gần nhau; **KHÔNG** rải mỗi file một nơi.
227
+ Adapter API mặc định tại `{paths.src_dir}/{domain}/` (khi §4.5.2 không chỉ định). Luôn **quét `{paths.src_dir}` tái dùng** như BE trước khi tạo mới (đồng bộ DS5).
228
+
185
229
  ---
186
230
 
187
231
  ## Seam & Stub Ledger — nối/lấp chỗ chưa implement *(chống mồ côi)*
@@ -313,9 +357,10 @@ Domain : {domain}
313
357
  UC : chỉ {UC-ID} ← các file feature khác trong folder này KHÔNG được đọc
314
358
  Tech : {language} / {framework}
315
359
  Package : {code_base_package}.{layer} · {by-layer | by-feature} ← feature/UC ở TÊN CLASS, KHÔNG thành package (nếu by-layer)
316
- Phase : {UI — mock layer | Integration — real API | Default — full} ← bỏ nếu không flag --phase
360
+ Phase : {UI — mock layer | Integration — real API | FE full UI + real API | BE full} ← FE full = default trên web/app; bỏ dòng này với default BE
317
361
  Scenarios: {N} total ({X} new, {Y} drifted, {Z} synced-skip)
318
362
  Layer : {từ CLAUDE.md §2}
363
+ Client : {chỉ integration/fe_full — reuse: {reuse_target hoặc "dựng mới"} · gaps §4.5.4: {n còn trống hoặc "đủ"}} ← bỏ dòng này với BE / --phase=ui
319
364
 
320
365
  Files:
321
366
  CREATE {N} file mới
@@ -385,7 +430,7 @@ DTOs → Entity/Model → Repository → Service interface → Service impl →
385
430
  Mỗi element **có action** (button, input, link, select, toggle, form-submit) PHẢI mang một **test-id ổn định** để QC định vị trực tiếp (không scan runtime):
386
431
 
387
432
  1. **Nguồn id.** Nếu tech-doc gộp `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` có **§4.5.6 Test Selectors** cho platform này, lấy id **nguyên văn** từ bảng đó (contract). Nếu chưa có (vd `--phase=ui` trước khi §4.5 được vẽ), **sinh id theo quy ước** `{uc-lower}-{screen}-{element}-{type}` (vd `ft001-login-submit-btn`) để QC vẫn có handle ổn định — chúng sẽ được đối chiếu với §4.5.6 của tech-design lúc integration.
388
- 2. **Emit qua attribute platform** (từ `@trace.testid_attr`, hoặc theo module):
433
+ 2. **Emit qua attribute platform** — chọn attribute theo **`active_module`** (bảng dưới, mặc định). Chỉ override khi header `.feature` khai tường minh `@trace.testid_attr={attr}` (hiếm; dùng cho stack lai). Không có khai báo → theo module:
389
434
  - web (`react`/`nextjs`/`vue`/`angular`) → `data-testid="..."`
390
435
  - React Native → `testID="..."`
391
436
  - Flutter → `Key('...')` (+ `Semantics(identifier: '...')` khi action cần)
@@ -425,24 +470,32 @@ Dựng mock từ `mock_source` đã phân giải ở Phase Detection — **shape
425
470
 
426
471
  ---
427
472
 
428
- ## Integration Phase (chỉ `--phase=integration`)
473
+ ## Integration Phase (`--phase=integration` HOẶC `fe_full`)
429
474
 
430
- *Bỏ qua hoàn toàn section này nếu `--phase` không phải `integration`.*
475
+ *Bỏ qua hoàn toàn section này nếu KHÔNG phải `--phase=integration` KHÔNG phải `fe_full` (vd `--phase=ui`, hoặc default BE/`system`).*
476
+
477
+ *Hai chế độ vào section này:*
478
+ - **`--phase=integration`** — đã có mock adapter + UI từ lần `--phase=ui` trước → **thay** mock bằng real (có lật wire-up).
479
+ - **`fe_full`** — UI vừa được sinh trong CHÍNH lần chạy này, **không có bước mock** → wire real adapter **thẳng** (không có mock để thay/lật).
431
480
 
432
481
  1. **Đọc integration design.** Trong tech-doc gộp `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md`: ưu tiên §4.5.4 (mapping port→endpoint→DTO→error của platform), dùng §4.1/§4.2/§4.3 làm nguồn endpoint / request-response / error-code. Nếu doc chưa có §4.5.4 cho platform này, trích endpoint + shape + error code trực tiếp từ §4.1–§4.3.
433
- - **Nếu §4/§4.5.4 thiếu bất kỳ chi tiết integration nào (endpoint, field/DTO, error-code, mapping):** ÁP DỤNG **SRC-CHAIN** (xem §Quy tắc nguồn giá trị) vét cạn PRD (Appendix Existing API Contract), design-spec, mệnh đề `Then` của System/platform BDD, `core-entities.md`, **mock adapter đã sinh ở `--phase=ui`** (shape port/DTO đã chốt nguồn shape mạnh nhất, đừng bỏ quên), tech-doc anh em cùng domain — TRƯỚC khi coi là GAP. Skip-if-answered. Chỉ hỏi cái không nguồn nào có, **gộp mọi GAP còn lại vào MỘT checkpoint** (ghi đã tìm đâu). *(Đây là fix cho tình trạng phase=integration hỏi nhiều dù đáp án đã nằm trong tài liệu khác.)*
434
- 2. **Đọc mock adapter có sẵn** interface (`{UC-ID}ApiPort`) từ output `--phase=ui`. Real adapter implements **cùng** interface này → shape port/DTO đã cố định từ mock; **không hỏi lại shape** đã có ở đây.
435
- 3. **Sinh real API adapter** tại `{paths.src_dir}/{domain}/{UC-ID}ApiAdapter.{ext}`:
436
- - Implements cùng interface `{UC-ID}ApiPort` như mock adapter
437
- - Gọi HTTP thật tới endpoint từ contract tech-doc
438
- - Map field response sang cùng shape mock adapter trả về
439
- - Tag traceability:
482
+ - **Tính đủ của §4.5.4 đã được cửa DS4 kiểm + vét SRC-CHAIN + gộp-hỏi TỪ TRƯỚC.** bước này dùng thẳng kết quả đã phân giải của DS4 **KHÔNG mở checkpoint/hỏi lại**. Nếu DS4 kết luận một mapping vẫn trống người đã chọn Y (best-effort) `--phase=integration` giữ mock cho phần đó; `fe_full` để adapter trả stub, tag `@trace.stub`, ghi sổ seam; đừng bịa giá trị.
483
+ 2. **Nguồn interface port `{UC-ID}ApiPort`:**
484
+ - `--phase=integration` (có mock) → đọc từ mock adapter sẵn (output `--phase=ui`). Real adapter implements **cùng** interface → shape port/DTO đã cố định, **không hỏi lại shape**.
485
+ - `reuse_target` (DS5 chọn **R**) → dùng interface/kiểu **service/hook sẵn** đang khai báo; adapter mới phải khớp chữ ký chúng đang gọi (không đổi hợp đồng của code đang chạy).
486
+ - `fe_full` greenfield port do UI vừa sinh trong lần này định nghĩa (§4.5.3/§4.5.4). Không có mock adapter để đọc.
487
+ 3. **Sinh / lắp real API adapter** theo kết quả **DS5**:
488
+ - **`reuse_target` = none** (greenfield / DS5 chọn N) → sinh file mới `{paths.src_dir}/{domain}/{UC-ID}ApiAdapter.{ext}`, implements `{UC-ID}ApiPort`.
489
+ - **`reuse_target` có file** (DS5 chọn R) → **EXTEND vào service/api-client/hook đang chạy** (áp Quy tắc EXTEND phi-phá-huỷ + Guard sau-ghi ở §File Scan): thay lời gọi mock/placeholder bằng lời gọi HTTP thật **tại chỗ**, giữ nguyên mọi member cũ; **KHÔNG** tạo `{UC-ID}ApiAdapter` song song.
490
+ - Chung: gọi HTTP thật tới endpoint từ contract tech-doc; map field response sang shape port/service khai báo; tag:
440
491
  ```
441
492
  @trace.implements={UC-ID}-SC{N}
442
493
  @trace.tech_doc_revision={đọc từ header tech-doc}
443
494
  ```
444
- 4. **Lật wire-up**: chuyển DI binding / env flag để service/hook dùng `{UC-ID}ApiAdapter` (thật) thay vì mock.
445
- 5. **KHÔNG xoá mock adapter** — giữ lại cho unit test.
495
+ 4. **Wire-up:**
496
+ - `--phase=integration` (có mock) → **lật** DI binding / env flag để service/hook dùng adapter thật thay vì mock. **KHÔNG xoá mock adapter** — giữ cho unit test.
497
+ - `reuse_target` (DS5 chọn R) → wiring đã nằm trong chính component/service có sẵn (đã EXTEND ở bước 3) → **không thêm binding song song**; chỉ chỉnh cấu hình bật đường thật nếu code cũ có cờ mock.
498
+ - `fe_full` greenfield → wire service/hook thẳng vào `{UC-ID}ApiAdapter` (thật); không sinh mock adapter (unit test dùng stub/fake tại chỗ khi cần).
446
499
 
447
500
  ---
448
501
 
@@ -461,6 +514,16 @@ Dựng mock từ `mock_source` đã phân giải ở Phase Detection — **shape
461
514
  {conventions.build_command} # từ project-context.yaml, tối đa 3 retry
462
515
  ```
463
516
 
517
+ > **GATE build (BẮT BUỘC):** chỉ khi build **SUCCESS** mới được đi tiếp sang **Write Trace State** và **Commit**.
518
+ > - Fail → sửa lỗi rồi retry (tối đa 3 lần).
519
+ > - **Vẫn fail sau 3 retry → DỪNG.** KHÔNG ghi trace, KHÔNG commit (trace/repo không được nói "đã xong" khi chưa build được). Xuất:
520
+ > ```
521
+ > ❌ Build FAIL sau 3 lần thử — không ghi trace, không commit.
522
+ > Lỗi cuối: {tóm tắt}
523
+ > File đã sinh giữ nguyên trên working tree để bạn sửa tay hoặc chạy /debug.
524
+ > ```
525
+ > Đặt Status badge = ❌ ở report cuối và dừng (bỏ qua Write Trace / Refresh Panel / Commit).
526
+
464
527
  ## Write Trace State
465
528
 
466
529
  Cập nhật `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{@trace.platform}.tsv` — với mỗi scenario đã implement, tìm row có sẵn theo `sc_id` và chỉ cập nhật các cột sau. *(Umbrella + `spec_source`: `trace_dir` phân giải về `{spec_source}/.trace` — lệnh này chạy từ `service_root` nhưng ghi trace row vào **spec repo** (liên-repo); commit/push spec submodule cho lần cập nhật trace, cùng với push code 2 tầng.)*
@@ -471,8 +534,8 @@ Cập nhật `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{@trace.platform}.ts
471
534
  | `implemented_by` | `{ControllerClass}.{methodName}` |
472
535
  | `bdd_version` | `@trace.bdd_version` từ header `.feature` |
473
536
  | `tech_doc_revision` | `@trace.revision` từ tech-doc gộp `{TICKET-ID}-tech-design.md` (§4 backend đã điều khiển codegen của UC này), hoặc `—` nếu chưa có doc |
474
- | `fe_tech_doc_revision` | `@trace.revision` của cùng tech-doc gộp, ghi khi sinh FE với `--phase=integration` (adapter được wire theo §4.5.4); `—` cho BE, hoặc cho FE `--phase=ui` / chưa có §4.5.4 |
475
- | `fe_phase` | `ui` nếu `--phase=ui` \| `integrated` nếu `--phase=integration` \| `—` nếu không flag phase |
537
+ | `fe_tech_doc_revision` | `@trace.revision` của cùng tech-doc gộp, ghi khi sinh FE wire adapter theo §4.5.4 (`--phase=integration` **hoặc** `fe_full`); `—` cho BE, hoặc cho FE `--phase=ui` / chưa có §4.5.4 |
538
+ | `fe_phase` | `ui` nếu `--phase=ui` \| `integrated` nếu `--phase=integration` **hoặc** `fe_full` (đều đã wire real adapter) \| `—` cho BE |
476
539
  | `last_updated` | hôm nay `YYYY-MM-DD` |
477
540
 
478
541
  Giữ nguyên mọi cột khác (`sc_title`, `spec_ver`, `prd_version`, `prd_status`, `uc_status`, `test_count`, `test_classes`, `dev_selftest`, `dev_selftest_at`, `qc_status`, `qc_run_at`, `qc_owner`, `qc_blocked_by`).
@@ -500,8 +563,8 @@ git commit -m "{commit_format}: {description}"
500
563
  /generate-code Hoàn tất — {UC-ID}
501
564
  Files: created={N}, extended={M}, filled={F} stub, skipped={K} | Build: SUCCESS
502
565
  Branch: feature/{TICKET_ID}-{slug}
503
- Phase : {UI (mock layer) | Integration (real API) | Default (full)}
504
- fe_phase : {ui | integrated | —}
566
+ Phase : {UI (mock layer) | Integration (real API) | FE full (UI + real API) | BE full}
567
+ fe_phase : {ui | integrated (—phase=integration | fe_full) | —}
505
568
  Figma : {Dev Mode MCP local (grounded) | ⚠️ chỉ link web + text spec (không có MCP local) | n/a cho BE} ← chỉ UI FE/App
506
569
 
507
570
  Next:
@@ -52,7 +52,8 @@ Hiển thị và chờ phản hồi:
52
52
 
53
53
  ## Bước 1 — Xác định Target File
54
54
 
55
- 1. Nếu `$ARGUMENTS` được cung cấp trỏ tới một file tồn tại dùng trực tiếp làm target.
55
+ 0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` thể lẫn các `--flag` (vd `--phase=integration`, `--comment`, `--fix`). **Loại bỏ mọi token bắt đầu bằng `--`** ra khỏi phần dùng để tìm target — chỉ giữ phần path/UC-ID/ticket. (Các flag đó do phần logic riêng của lệnh parse ở bước sau, KHÔNG phải tên file.)
56
+ 1. Nếu `$ARGUMENTS` (đã tách cờ) được cung cấp và trỏ tới một file tồn tại → dùng trực tiếp làm target.
56
57
  2. Nếu `$ARGUMENTS` là một **UC-ID / ticket ID / tên rút gọn** (không có path) → phân giải thành file bằng cách glob theo bố cục feature-package. `{prd-slug}` lúc này **chưa biết**, nên dùng wildcard `*` cho segment đó, và `**` đệ quy dưới `bdd/` để phủ hết các thư mục con theo platform (`bdd/web/`, `bdd/app/`, `bdd/system/`):
57
58
  - **Lệnh BDD** (target là `.feature`): `{specs_dir}/{domain}/*/bdd/**/{UC-ID}*.feature` — hoặc `{specs_dir}/*/*/bdd/**/{UC-ID}*.feature` nếu domain cũng chưa biết. Nếu lệnh ngụ ý một platform/scope cụ thể (vd: system tech-doc cần BDD `system/`), ưu tiên kết quả trong thư mục con platform đó.
58
59
  - **Lệnh PRD** (target là file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder, cạnh `bdd/`): `{specs_dir}/{domain}/*/{TICKET-ID}*.md` nếu biết TICKET-ID; nếu không, `{specs_dir}/{domain}/*/*.md` (khớp feature folder có id tương ứng), hoặc `{specs_dir}/*/*/*.md` nếu domain cũng chưa biết. *(Glob `*/*.md` ở cấp gốc folder chỉ khớp PRD — tech-docs/design-spec `.md` nằm sâu hơn trong thư mục con.)*
@@ -138,6 +139,7 @@ Thực hiện các bước theo đúng thứ tự. Lưu mọi thứ vào bộ nh
138
139
  - `paths.business_dictionary` → path tới business-dictionary.md
139
140
  - `paths.core_entities` → path tới core-entities.md
140
141
  - `paths.tech_docs_dir` → gốc tài liệu kỹ thuật (gộp với specs_dir trong bố cục feature-package — tech-docs nằm dưới `{specs_dir}/{domain}/{prd-slug}/tech-docs/`)
142
+ - `paths.src_dir` → gốc mã nguồn (nơi generate-code đặt & quét code; nguồn chính cho FE + phạm vi reuse-scan của DS5)
141
143
  - `paths.trace_dir` → thư mục trạng thái trace; cấu trúc: `.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv` (mỗi UC × platform một sổ)
142
144
 
143
145
  Nếu không có section `paths`, dùng các giá trị mặc định:
@@ -150,6 +152,7 @@ Nếu không có section `paths`, dùng các giá trị mặc định:
150
152
  - `business_dictionary` = `specs/domain-knowledge/business-dictionary.md`
151
153
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
152
154
  - `tech_docs_dir` = `specs`
155
+ - `src_dir` = `src`
153
156
  - `trace_dir` = `.trace`
154
157
 
155
158
  Lưu ý: Trong bố cục feature-package, `specs_dir` là gốc thống nhất. Mọi loại spec artifact (PRD, BDD, tech-docs, design-spec) đều nằm dưới `{specs_dir}/{domain}/{prd-slug}/`. `prd-slug` là tên folder feature-package, không phải một biến config riêng.
@@ -52,7 +52,8 @@ Hiển thị và chờ phản hồi:
52
52
 
53
53
  ## Bước 1 — Xác định Target File
54
54
 
55
- 1. Nếu `$ARGUMENTS` được cung cấp trỏ tới một file tồn tại dùng trực tiếp làm target.
55
+ 0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` thể lẫn các `--flag` (vd `--phase=integration`, `--comment`, `--fix`). **Loại bỏ mọi token bắt đầu bằng `--`** ra khỏi phần dùng để tìm target — chỉ giữ phần path/UC-ID/ticket. (Các flag đó do phần logic riêng của lệnh parse ở bước sau, KHÔNG phải tên file.)
56
+ 1. Nếu `$ARGUMENTS` (đã tách cờ) được cung cấp và trỏ tới một file tồn tại → dùng trực tiếp làm target.
56
57
  2. Nếu `$ARGUMENTS` là một **UC-ID / ticket ID / tên rút gọn** (không có path) → phân giải thành file bằng cách glob theo bố cục feature-package. `{prd-slug}` lúc này **chưa biết**, nên dùng wildcard `*` cho segment đó, và `**` đệ quy dưới `bdd/` để phủ hết các thư mục con theo platform (`bdd/web/`, `bdd/app/`, `bdd/system/`):
57
58
  - **Lệnh BDD** (target là `.feature`): `{specs_dir}/{domain}/*/bdd/**/{UC-ID}*.feature` — hoặc `{specs_dir}/*/*/bdd/**/{UC-ID}*.feature` nếu domain cũng chưa biết. Nếu lệnh ngụ ý một platform/scope cụ thể (vd: system tech-doc cần BDD `system/`), ưu tiên kết quả trong thư mục con platform đó.
58
59
  - **Lệnh PRD** (target là file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder, cạnh `bdd/`): `{specs_dir}/{domain}/*/{TICKET-ID}*.md` nếu biết TICKET-ID; nếu không, `{specs_dir}/{domain}/*/*.md` (khớp feature folder có id tương ứng), hoặc `{specs_dir}/*/*/*.md` nếu domain cũng chưa biết. *(Glob `*/*.md` ở cấp gốc folder chỉ khớp PRD — tech-docs/design-spec `.md` nằm sâu hơn trong thư mục con.)*
@@ -138,6 +139,7 @@ Thực hiện các bước theo đúng thứ tự. Lưu mọi thứ vào bộ nh
138
139
  - `paths.business_dictionary` → path tới business-dictionary.md
139
140
  - `paths.core_entities` → path tới core-entities.md
140
141
  - `paths.tech_docs_dir` → gốc tài liệu kỹ thuật (gộp với specs_dir trong bố cục feature-package — tech-docs nằm dưới `{specs_dir}/{domain}/{prd-slug}/tech-docs/`)
142
+ - `paths.src_dir` → gốc mã nguồn (nơi generate-code đặt & quét code; nguồn chính cho FE + phạm vi reuse-scan của DS5)
141
143
  - `paths.trace_dir` → thư mục trạng thái trace; cấu trúc: `.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv` (mỗi UC × platform một sổ)
142
144
 
143
145
  Nếu không có section `paths`, dùng các giá trị mặc định:
@@ -150,6 +152,7 @@ Nếu không có section `paths`, dùng các giá trị mặc định:
150
152
  - `business_dictionary` = `specs/domain-knowledge/business-dictionary.md`
151
153
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
152
154
  - `tech_docs_dir` = `specs`
155
+ - `src_dir` = `src`
153
156
  - `trace_dir` = `.trace`
154
157
 
155
158
  Lưu ý: Trong bố cục feature-package, `specs_dir` là gốc thống nhất. Mọi loại spec artifact (PRD, BDD, tech-docs, design-spec) đều nằm dưới `{specs_dir}/{domain}/{prd-slug}/`. `prd-slug` là tên folder feature-package, không phải một biến config riêng.
@@ -56,7 +56,8 @@ Hiển thị và chờ phản hồi:
56
56
 
57
57
  ## Bước 1 — Xác định Target File
58
58
 
59
- 1. Nếu `$ARGUMENTS` được cung cấp trỏ tới một file tồn tại dùng trực tiếp làm target.
59
+ 0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` thể lẫn các `--flag` (vd `--phase=integration`, `--comment`, `--fix`). **Loại bỏ mọi token bắt đầu bằng `--`** ra khỏi phần dùng để tìm target — chỉ giữ phần path/UC-ID/ticket. (Các flag đó do phần logic riêng của lệnh parse ở bước sau, KHÔNG phải tên file.)
60
+ 1. Nếu `$ARGUMENTS` (đã tách cờ) được cung cấp và trỏ tới một file tồn tại → dùng trực tiếp làm target.
60
61
  2. Nếu `$ARGUMENTS` là một **UC-ID / ticket ID / tên rút gọn** (không có path) → phân giải thành file bằng cách glob theo bố cục feature-package. `{prd-slug}` lúc này **chưa biết**, nên dùng wildcard `*` cho segment đó, và `**` đệ quy dưới `bdd/` để phủ hết các thư mục con theo platform (`bdd/web/`, `bdd/app/`, `bdd/system/`):
61
62
  - **Lệnh BDD** (target là `.feature`): `{specs_dir}/{domain}/*/bdd/**/{UC-ID}*.feature` — hoặc `{specs_dir}/*/*/bdd/**/{UC-ID}*.feature` nếu domain cũng chưa biết. Nếu lệnh ngụ ý một platform/scope cụ thể (vd: system tech-doc cần BDD `system/`), ưu tiên kết quả trong thư mục con platform đó.
62
63
  - **Lệnh PRD** (target là file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder, cạnh `bdd/`): `{specs_dir}/{domain}/*/{TICKET-ID}*.md` nếu biết TICKET-ID; nếu không, `{specs_dir}/{domain}/*/*.md` (khớp feature folder có id tương ứng), hoặc `{specs_dir}/*/*/*.md` nếu domain cũng chưa biết. *(Glob `*/*.md` ở cấp gốc folder chỉ khớp PRD — tech-docs/design-spec `.md` nằm sâu hơn trong thư mục con.)*
@@ -143,6 +144,7 @@ Thực hiện các bước theo đúng thứ tự. Lưu mọi thứ vào bộ nh
143
144
  - `paths.business_dictionary` → path tới business-dictionary.md
144
145
  - `paths.core_entities` → path tới core-entities.md
145
146
  - `paths.tech_docs_dir` → gốc tài liệu kỹ thuật (gộp với specs_dir trong bố cục feature-package — tech-docs nằm dưới `{specs_dir}/{domain}/{prd-slug}/tech-docs/`)
147
+ - `paths.src_dir` → gốc mã nguồn (nơi generate-code đặt & quét code; nguồn chính cho FE + phạm vi reuse-scan của DS5)
146
148
  - `paths.trace_dir` → thư mục trạng thái trace; cấu trúc: `.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv` (mỗi UC × platform một sổ)
147
149
 
148
150
  Nếu không có section `paths`, dùng các giá trị mặc định:
@@ -155,6 +157,7 @@ Nếu không có section `paths`, dùng các giá trị mặc định:
155
157
  - `business_dictionary` = `specs/domain-knowledge/business-dictionary.md`
156
158
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
157
159
  - `tech_docs_dir` = `specs`
160
+ - `src_dir` = `src`
158
161
  - `trace_dir` = `.trace`
159
162
 
160
163
  Lưu ý: Trong bố cục feature-package, `specs_dir` là gốc thống nhất. Mọi loại spec artifact (PRD, BDD, tech-docs, design-spec) đều nằm dưới `{specs_dir}/{domain}/{prd-slug}/`. `prd-slug` là tên folder feature-package, không phải một biến config riêng.