@educa-corp/sdd-framework 0.2.6 → 0.2.8
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.
- package/commands/debug.md +4 -1
- package/commands/define-product.md +38 -1
- package/commands/define-product.tmpl +34 -0
- package/commands/dev-gen-test.md +4 -1
- package/commands/dev-run-test.md +4 -1
- package/commands/dev-smoke-test.md +4 -1
- package/commands/fix-bug.md +4 -1
- package/commands/generate-architecture.md +4 -1
- package/commands/generate-bdd.md +4 -1
- package/commands/generate-code.md +80 -26
- package/commands/generate-code.tmpl +76 -25
- package/commands/generate-design-spec.md +4 -1
- package/commands/generate-prd.md +4 -1
- package/commands/generate-spec-manifest.md +4 -1
- package/commands/generate-tech-docs.md +4 -1
- package/commands/learn.md +4 -1
- package/commands/map-testids.md +4 -1
- package/commands/propose-scenario.md +4 -1
- package/commands/qc-analyze.md +4 -1
- package/commands/qc-design-test.md +4 -1
- package/commands/qc-plan.md +4 -1
- package/commands/qc-report.md +4 -1
- package/commands/qc-review.md +4 -1
- package/commands/qc-run-test.md +4 -1
- package/commands/refine-prd.md +4 -1
- package/commands/report-bug.md +4 -1
- package/commands/review-code.md +4 -1
- package/commands/review-context.md +4 -1
- package/commands/review-tech-docs.md +4 -1
- package/commands/setup-ai-first.md +2 -1
- package/commands/validate-traces.md +4 -1
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/debug.md +4 -1
- package/core/commands/define-product.md +38 -1
- package/core/commands/dev-gen-test.md +4 -1
- package/core/commands/dev-run-test.md +4 -1
- package/core/commands/dev-smoke-test.md +4 -1
- package/core/commands/fix-bug.md +4 -1
- package/core/commands/generate-architecture.md +4 -1
- package/core/commands/generate-bdd.md +4 -1
- package/core/commands/generate-code.md +80 -26
- package/core/commands/generate-design-spec.md +4 -1
- package/core/commands/generate-prd.md +4 -1
- package/core/commands/generate-spec-manifest.md +4 -1
- package/core/commands/generate-tech-docs.md +4 -1
- package/core/commands/learn.md +4 -1
- package/core/commands/map-testids.md +4 -1
- package/core/commands/propose-scenario.md +4 -1
- package/core/commands/qc-analyze.md +4 -1
- package/core/commands/qc-design-test.md +4 -1
- package/core/commands/qc-plan.md +4 -1
- package/core/commands/qc-report.md +4 -1
- package/core/commands/qc-review.md +4 -1
- package/core/commands/qc-run-test.md +4 -1
- package/core/commands/refine-prd.md +4 -1
- package/core/commands/report-bug.md +4 -1
- package/core/commands/review-code.md +4 -1
- package/core/commands/review-context.md +4 -1
- package/core/commands/review-tech-docs.md +4 -1
- package/core/commands/setup-ai-first.md +2 -1
- package/core/commands/validate-traces.md +4 -1
- package/core/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +646 -0
- package/core/modules/phaser-game/module.yaml +15 -0
- package/core/modules/phaser-game/stack-profile.yaml +90 -0
- package/core/steps/context-loader.md +2 -0
- package/core/steps/gate.md +2 -1
- package/core/templates/project-context.yaml +6 -0
- package/docs/02-concepts/pipeline-steps/06-code.md +7 -4
- package/docs/03-guides/developer.md +6 -3
- package/docs/explain/09-generate-code.md +41 -3
- package/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +646 -0
- package/modules/phaser-game/module.yaml +15 -0
- package/modules/phaser-game/stack-profile.yaml +90 -0
- package/package.json +1 -1
- package/steps/context-loader.md +2 -0
- package/steps/gate.md +2 -1
- package/templates/project-context.yaml +6 -0
|
@@ -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
|
-
|
|
55
|
+
0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` có 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.
|
|
@@ -439,7 +442,7 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
|
|
|
439
442
|
|
|
440
443
|
Đọc:
|
|
441
444
|
1. Chỉ file `.feature` đã giới hạn scope
|
|
442
|
-
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
|
|
445
|
+
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.
|
|
443
446
|
3. CLAUDE.md §architecture + §coding_standards
|
|
444
447
|
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.
|
|
445
448
|
|
|
@@ -462,7 +465,7 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
|
|
|
462
465
|
- **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.
|
|
463
466
|
- `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.
|
|
464
467
|
|
|
465
|
-
**Tech-doc contract (chỉ backend/system) — DS3:** *áp dụng khi lần sinh này tạo code **backend** — `@trace.platform = system
|
|
468
|
+
**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.*
|
|
466
469
|
|
|
467
470
|
Đị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):
|
|
468
471
|
- **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).
|
|
@@ -481,13 +484,17 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
|
|
|
481
484
|
|
|
482
485
|
## Phase Detection
|
|
483
486
|
|
|
487
|
+
> **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.
|
|
488
|
+
|
|
484
489
|
Parse `$ARGUMENTS` tìm flag `--phase`:
|
|
485
490
|
|
|
486
491
|
| Flag | Ý nghĩa |
|
|
487
492
|
|---|---|
|
|
488
493
|
| `--phase=ui` | FE Phase 1 — sinh UI + layer mock API từ System BDD contract |
|
|
489
494
|
| `--phase=integration` | FE Phase 2 — thay mock adapter bằng lời gọi API thật từ tech docs |
|
|
490
|
-
| *(không có)* | Default — full
|
|
495
|
+
| *(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) |
|
|
496
|
+
|
|
497
|
+
**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.
|
|
491
498
|
|
|
492
499
|
**Nếu `--phase` được set — xác nhận platform:**
|
|
493
500
|
Đọc `@trace.platform` từ header file feature.
|
|
@@ -551,14 +558,21 @@ selection context, và code snippet — những thứ một URL web đơn không
|
|
|
551
558
|
qua Figma MCP và ground UI trên layout, variable, và mapping Code Connect trả về. Ưu tiên
|
|
552
559
|
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.
|
|
553
560
|
|
|
554
|
-
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## Integration Gates — DS4 (contract) · DS5 (reuse)
|
|
564
|
+
|
|
565
|
+
*Áp dụng khi wire API thật: `--phase=integration` **HOẶC** `fe_full`. Bỏ qua `--phase=ui` và default BE.*
|
|
566
|
+
|
|
567
|
+
> **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.
|
|
568
|
+
|
|
555
569
|
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`:
|
|
556
570
|
- **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.
|
|
557
571
|
- **Nguồn endpoint/shape**: §4.1 Endpoints + §4.2 Request-Response + §4.3 Error của cùng doc.
|
|
558
572
|
|
|
559
|
-
**Client contract gate — DS4** *(
|
|
573
|
+
**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.
|
|
560
574
|
|
|
561
|
-
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
|
|
575
|
+
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.
|
|
562
576
|
2. **Kiểm tính đủ của §4.5.4 cho từng method:** có 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".)*
|
|
563
577
|
3. **Phân loại (giống DS3):**
|
|
564
578
|
- **Đủ + `@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.
|
|
@@ -575,8 +589,24 @@ Phân giải design điều khiển adapter từ **tech-doc gộp của PRD** `{
|
|
|
575
589
|
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)
|
|
576
590
|
```
|
|
577
591
|
Chỉ tiếp khi Y. *(Đây là "tư thế BE": trỏ ngược tech-docs thay vì hỏi live từng câu.)*
|
|
578
|
-
|
|
579
|
-
|
|
592
|
+
**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.
|
|
593
|
+
|
|
594
|
+
1. **Định vị mock adapter framework:** tìm `{UC-ID}MockApiAdapter` trong `{paths.src_dir}/{domain}/` (output `--phase=ui`).
|
|
595
|
+
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ó".
|
|
596
|
+
3. **Quyết định reuse-or-new:**
|
|
597
|
+
- **CÓ mock adapter** (luồng 2-pha chuẩn) → tái dùng port/wiring của nó như cũ; **KHÔNG hỏi**.
|
|
598
|
+
- **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:**
|
|
599
|
+
```
|
|
600
|
+
🔎 Thấy {N} phần FE đang tồn tại cho màn của {UC-ID}/{platform}:
|
|
601
|
+
- {path} ({component | service | hook | api-client})
|
|
602
|
+
Wire API thật vào code CÓ SẴN này, hay dựng mới?
|
|
603
|
+
R (reuse) — EXTEND/wire adapter vào component/service đang chạy (khuyến nghị)
|
|
604
|
+
N (new) — dựng adapter/service mới (chỉ khi code cũ không tái dùng được — ghi lý do)
|
|
605
|
+
```
|
|
606
|
+
- **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.
|
|
607
|
+
- **N** → dựng mới, ghi lý do vào report.
|
|
608
|
+
- **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).
|
|
609
|
+
4. Lưu `reuse_target` (hoặc `none`) cho Integration Phase dùng ở bước wire-up.
|
|
580
610
|
|
|
581
611
|
---
|
|
582
612
|
|
|
@@ -606,6 +636,11 @@ Trước khi định vị file, chốt **package đích** theo **Package Layout
|
|
|
606
636
|
|
|
607
637
|
**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ó.
|
|
608
638
|
|
|
639
|
+
**Đặ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:
|
|
640
|
+
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).
|
|
641
|
+
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.
|
|
642
|
+
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).
|
|
643
|
+
|
|
609
644
|
---
|
|
610
645
|
|
|
611
646
|
## Seam & Stub Ledger — nối/lấp chỗ chưa implement *(chống mồ côi)*
|
|
@@ -737,9 +772,10 @@ Domain : {domain}
|
|
|
737
772
|
UC : chỉ {UC-ID} ← các file feature khác trong folder này KHÔNG được đọc
|
|
738
773
|
Tech : {language} / {framework}
|
|
739
774
|
Package : {code_base_package}.{layer} · {by-layer | by-feature} ← feature/UC ở TÊN CLASS, KHÔNG thành package (nếu by-layer)
|
|
740
|
-
Phase : {UI — mock layer | Integration — real API |
|
|
775
|
+
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
|
|
741
776
|
Scenarios: {N} total ({X} new, {Y} drifted, {Z} synced-skip)
|
|
742
777
|
Layer : {từ CLAUDE.md §2}
|
|
778
|
+
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
|
|
743
779
|
|
|
744
780
|
Files:
|
|
745
781
|
CREATE {N} file mới
|
|
@@ -809,7 +845,7 @@ DTOs → Entity/Model → Repository → Service interface → Service impl →
|
|
|
809
845
|
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):
|
|
810
846
|
|
|
811
847
|
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.
|
|
812
|
-
2. **Emit qua attribute platform** (
|
|
848
|
+
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:
|
|
813
849
|
- web (`react`/`nextjs`/`vue`/`angular`) → `data-testid="..."`
|
|
814
850
|
- React Native → `testID="..."`
|
|
815
851
|
- Flutter → `Key('...')` (+ `Semantics(identifier: '...')` khi action cần)
|
|
@@ -849,24 +885,32 @@ Dựng mock từ `mock_source` đã phân giải ở Phase Detection — **shape
|
|
|
849
885
|
|
|
850
886
|
---
|
|
851
887
|
|
|
852
|
-
## Integration Phase (
|
|
888
|
+
## Integration Phase (`--phase=integration` HOẶC `fe_full`)
|
|
853
889
|
|
|
854
|
-
*Bỏ qua hoàn toàn section này nếu `--phase`
|
|
890
|
+
*Bỏ qua hoàn toàn section này nếu KHÔNG phải `--phase=integration` và KHÔNG phải `fe_full` (vd `--phase=ui`, hoặc default BE/`system`).*
|
|
891
|
+
|
|
892
|
+
*Hai chế độ vào section này:*
|
|
893
|
+
- **`--phase=integration`** — đã có mock adapter + UI từ lần `--phase=ui` trước → **thay** mock bằng real (có lật wire-up).
|
|
894
|
+
- **`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).
|
|
855
895
|
|
|
856
896
|
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.
|
|
857
|
-
- **Tính đủ của §4.5.4 đã được cửa DS4
|
|
858
|
-
2.
|
|
859
|
-
|
|
860
|
-
-
|
|
861
|
-
-
|
|
862
|
-
|
|
863
|
-
-
|
|
897
|
+
- **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 mà 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ị.
|
|
898
|
+
2. **Nguồn interface port `{UC-ID}ApiPort`:**
|
|
899
|
+
- `--phase=integration` (có mock) → đọc từ mock adapter có sẵn (output `--phase=ui`). Real adapter implements **cùng** interface → shape port/DTO đã cố định, **không hỏi lại shape**.
|
|
900
|
+
- `reuse_target` (DS5 chọn **R**) → dùng interface/kiểu mà **service/hook có 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).
|
|
901
|
+
- `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.
|
|
902
|
+
3. **Sinh / lắp real API adapter** — theo kết quả **DS5**:
|
|
903
|
+
- **`reuse_target` = none** (greenfield / DS5 chọn N) → sinh file mới `{paths.src_dir}/{domain}/{UC-ID}ApiAdapter.{ext}`, implements `{UC-ID}ApiPort`.
|
|
904
|
+
- **`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.
|
|
905
|
+
- Chung: gọi HTTP thật tới endpoint từ contract tech-doc; map field response sang shape port/service khai báo; tag:
|
|
864
906
|
```
|
|
865
907
|
@trace.implements={UC-ID}-SC{N}
|
|
866
908
|
@trace.tech_doc_revision={đọc từ header tech-doc}
|
|
867
909
|
```
|
|
868
|
-
4. **
|
|
869
|
-
|
|
910
|
+
4. **Wire-up:**
|
|
911
|
+
- `--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.
|
|
912
|
+
- `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.
|
|
913
|
+
- `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).
|
|
870
914
|
|
|
871
915
|
---
|
|
872
916
|
|
|
@@ -885,6 +929,16 @@ Dựng mock từ `mock_source` đã phân giải ở Phase Detection — **shape
|
|
|
885
929
|
{conventions.build_command} # từ project-context.yaml, tối đa 3 retry
|
|
886
930
|
```
|
|
887
931
|
|
|
932
|
+
> **GATE build (BẮT BUỘC):** chỉ khi build **SUCCESS** mới được đi tiếp sang **Write Trace State** và **Commit**.
|
|
933
|
+
> - Fail → sửa lỗi rồi retry (tối đa 3 lần).
|
|
934
|
+
> - **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:
|
|
935
|
+
> ```
|
|
936
|
+
> ❌ Build FAIL sau 3 lần thử — không ghi trace, không commit.
|
|
937
|
+
> Lỗi cuối: {tóm tắt}
|
|
938
|
+
> File đã sinh giữ nguyên trên working tree để bạn sửa tay hoặc chạy /debug.
|
|
939
|
+
> ```
|
|
940
|
+
> Đặt Status badge = ❌ ở report cuối và dừng (bỏ qua Write Trace / Refresh Panel / Commit).
|
|
941
|
+
|
|
888
942
|
## Write Trace State
|
|
889
943
|
|
|
890
944
|
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.)*
|
|
@@ -895,8 +949,8 @@ Cập nhật `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{@trace.platform}.ts
|
|
|
895
949
|
| `implemented_by` | `{ControllerClass}.{methodName}` |
|
|
896
950
|
| `bdd_version` | `@trace.bdd_version` từ header `.feature` |
|
|
897
951
|
| `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 |
|
|
898
|
-
| `fe_tech_doc_revision` | `@trace.revision` của cùng tech-doc gộp, ghi khi sinh FE
|
|
899
|
-
| `fe_phase` | `ui` nếu `--phase=ui` \| `integrated` nếu `--phase=integration`
|
|
952
|
+
| `fe_tech_doc_revision` | `@trace.revision` của cùng tech-doc gộp, ghi khi sinh FE có 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 |
|
|
953
|
+
| `fe_phase` | `ui` nếu `--phase=ui` \| `integrated` nếu `--phase=integration` **hoặc** `fe_full` (đều đã wire real adapter) \| `—` cho BE |
|
|
900
954
|
| `last_updated` | hôm nay `YYYY-MM-DD` |
|
|
901
955
|
|
|
902
956
|
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`).
|
|
@@ -1050,8 +1104,8 @@ Next : {lệnh gợi ý kèm ví dụ tham số}
|
|
|
1050
1104
|
/generate-code Hoàn tất — {UC-ID}
|
|
1051
1105
|
Files: created={N}, extended={M}, filled={F} stub, skipped={K} | Build: SUCCESS
|
|
1052
1106
|
Branch: feature/{TICKET_ID}-{slug}
|
|
1053
|
-
Phase : {UI (mock layer) | Integration (real API) |
|
|
1054
|
-
fe_phase : {ui | integrated | —}
|
|
1107
|
+
Phase : {UI (mock layer) | Integration (real API) | FE full (UI + real API) | BE full}
|
|
1108
|
+
fe_phase : {ui | integrated (—phase=integration | fe_full) | —}
|
|
1055
1109
|
Figma : {Dev Mode MCP local (grounded) | ⚠️ chỉ link web + text spec (không có MCP local) | n/a cho BE} ← chỉ UI FE/App
|
|
1056
1110
|
|
|
1057
1111
|
Next:
|
|
@@ -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
|
|
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
|
|
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,14 +143,21 @@ 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
|
-
|
|
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
|
-
**Client contract gate — DS4** *(
|
|
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.
|
|
148
159
|
|
|
149
|
-
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
|
|
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.
|
|
150
161
|
2. **Kiểm tính đủ của §4.5.4 cho từng method:** có 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".)*
|
|
151
162
|
3. **Phân loại (giống DS3):**
|
|
152
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.
|
|
@@ -163,8 +174,24 @@ Phân giải design điều khiển adapter từ **tech-doc gộp của PRD** `{
|
|
|
163
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)
|
|
164
175
|
```
|
|
165
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.)*
|
|
166
|
-
|
|
167
|
-
|
|
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.
|
|
168
195
|
|
|
169
196
|
---
|
|
170
197
|
|
|
@@ -194,6 +221,11 @@ Trước khi định vị file, chốt **package đích** theo **Package Layout
|
|
|
194
221
|
|
|
195
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ó.
|
|
196
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
|
+
|
|
197
229
|
---
|
|
198
230
|
|
|
199
231
|
## Seam & Stub Ledger — nối/lấp chỗ chưa implement *(chống mồ côi)*
|
|
@@ -325,9 +357,10 @@ Domain : {domain}
|
|
|
325
357
|
UC : chỉ {UC-ID} ← các file feature khác trong folder này KHÔNG được đọc
|
|
326
358
|
Tech : {language} / {framework}
|
|
327
359
|
Package : {code_base_package}.{layer} · {by-layer | by-feature} ← feature/UC ở TÊN CLASS, KHÔNG thành package (nếu by-layer)
|
|
328
|
-
Phase : {UI — mock layer | Integration — real API |
|
|
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
|
|
329
361
|
Scenarios: {N} total ({X} new, {Y} drifted, {Z} synced-skip)
|
|
330
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
|
|
331
364
|
|
|
332
365
|
Files:
|
|
333
366
|
CREATE {N} file mới
|
|
@@ -397,7 +430,7 @@ DTOs → Entity/Model → Repository → Service interface → Service impl →
|
|
|
397
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):
|
|
398
431
|
|
|
399
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.
|
|
400
|
-
2. **Emit qua attribute platform** (
|
|
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:
|
|
401
434
|
- web (`react`/`nextjs`/`vue`/`angular`) → `data-testid="..."`
|
|
402
435
|
- React Native → `testID="..."`
|
|
403
436
|
- Flutter → `Key('...')` (+ `Semantics(identifier: '...')` khi action cần)
|
|
@@ -437,24 +470,32 @@ Dựng mock từ `mock_source` đã phân giải ở Phase Detection — **shape
|
|
|
437
470
|
|
|
438
471
|
---
|
|
439
472
|
|
|
440
|
-
## Integration Phase (
|
|
473
|
+
## Integration Phase (`--phase=integration` HOẶC `fe_full`)
|
|
441
474
|
|
|
442
|
-
*Bỏ qua hoàn toàn section này nếu `--phase`
|
|
475
|
+
*Bỏ qua hoàn toàn section này nếu KHÔNG phải `--phase=integration` và 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).
|
|
443
480
|
|
|
444
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.
|
|
445
|
-
- **Tính đủ của §4.5.4 đã được cửa DS4
|
|
446
|
-
2.
|
|
447
|
-
|
|
448
|
-
-
|
|
449
|
-
-
|
|
450
|
-
|
|
451
|
-
-
|
|
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 mà 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 có 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 mà **service/hook có 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:
|
|
452
491
|
```
|
|
453
492
|
@trace.implements={UC-ID}-SC{N}
|
|
454
493
|
@trace.tech_doc_revision={đọc từ header tech-doc}
|
|
455
494
|
```
|
|
456
|
-
4. **
|
|
457
|
-
|
|
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).
|
|
458
499
|
|
|
459
500
|
---
|
|
460
501
|
|
|
@@ -473,6 +514,16 @@ Dựng mock từ `mock_source` đã phân giải ở Phase Detection — **shape
|
|
|
473
514
|
{conventions.build_command} # từ project-context.yaml, tối đa 3 retry
|
|
474
515
|
```
|
|
475
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
|
+
|
|
476
527
|
## Write Trace State
|
|
477
528
|
|
|
478
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.)*
|
|
@@ -483,8 +534,8 @@ Cập nhật `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{@trace.platform}.ts
|
|
|
483
534
|
| `implemented_by` | `{ControllerClass}.{methodName}` |
|
|
484
535
|
| `bdd_version` | `@trace.bdd_version` từ header `.feature` |
|
|
485
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 |
|
|
486
|
-
| `fe_tech_doc_revision` | `@trace.revision` của cùng tech-doc gộp, ghi khi sinh FE
|
|
487
|
-
| `fe_phase` | `ui` nếu `--phase=ui` \| `integrated` nếu `--phase=integration`
|
|
537
|
+
| `fe_tech_doc_revision` | `@trace.revision` của cùng tech-doc gộp, ghi khi sinh FE có 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 |
|
|
488
539
|
| `last_updated` | hôm nay `YYYY-MM-DD` |
|
|
489
540
|
|
|
490
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`).
|
|
@@ -512,8 +563,8 @@ git commit -m "{commit_format}: {description}"
|
|
|
512
563
|
/generate-code Hoàn tất — {UC-ID}
|
|
513
564
|
Files: created={N}, extended={M}, filled={F} stub, skipped={K} | Build: SUCCESS
|
|
514
565
|
Branch: feature/{TICKET_ID}-{slug}
|
|
515
|
-
Phase : {UI (mock layer) | Integration (real API) |
|
|
516
|
-
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) | —}
|
|
517
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
|
|
518
569
|
|
|
519
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
|
-
|
|
55
|
+
0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` có 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.
|
package/commands/generate-prd.md
CHANGED
|
@@ -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
|
-
|
|
55
|
+
0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` có 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
|
-
|
|
59
|
+
0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` có 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.
|
|
@@ -64,7 +64,8 @@ Hiển thị và chờ phản hồi:
|
|
|
64
64
|
|
|
65
65
|
## Bước 1 — Xác định Target File
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` có 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.)
|
|
68
|
+
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.
|
|
68
69
|
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/`):
|
|
69
70
|
- **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 đó.
|
|
70
71
|
- **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.)*
|
|
@@ -150,6 +151,7 @@ Thực hiện các bước theo đúng thứ tự. Lưu mọi thứ vào bộ nh
|
|
|
150
151
|
- `paths.business_dictionary` → path tới business-dictionary.md
|
|
151
152
|
- `paths.core_entities` → path tới core-entities.md
|
|
152
153
|
- `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/`)
|
|
154
|
+
- `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)
|
|
153
155
|
- `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ổ)
|
|
154
156
|
|
|
155
157
|
Nếu không có section `paths`, dùng các giá trị mặc định:
|
|
@@ -162,6 +164,7 @@ Nếu không có section `paths`, dùng các giá trị mặc định:
|
|
|
162
164
|
- `business_dictionary` = `specs/domain-knowledge/business-dictionary.md`
|
|
163
165
|
- `core_entities` = `specs/domain-knowledge/core-entities.md`
|
|
164
166
|
- `tech_docs_dir` = `specs`
|
|
167
|
+
- `src_dir` = `src`
|
|
165
168
|
- `trace_dir` = `.trace`
|
|
166
169
|
|
|
167
170
|
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.
|