@edupia-tutor/spec-driven-docs 0.14.0 → 0.14.2
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/bin/index.js +12 -1
- package/commands/debug.md +436 -436
- package/commands/debug.tmpl +111 -111
- package/commands/define-product.md +350 -345
- package/commands/define-product.tmpl +69 -64
- package/commands/dev-gen-test.md +365 -365
- package/commands/dev-gen-test.tmpl +63 -63
- package/commands/dev-run-test.md +376 -376
- package/commands/dev-run-test.tmpl +74 -74
- package/commands/dev-smoke-test.md +341 -341
- package/commands/dev-smoke-test.tmpl +60 -60
- package/commands/fix-bug.md +403 -403
- package/commands/fix-bug.tmpl +78 -78
- package/commands/generate-bdd.md +513 -513
- package/commands/generate-bdd.tmpl +211 -211
- package/commands/generate-code.md +481 -483
- package/commands/generate-code.tmpl +179 -181
- package/commands/generate-design-spec.md +497 -497
- package/commands/generate-design-spec.tmpl +220 -220
- package/commands/generate-prd.md +452 -400
- package/commands/generate-prd.tmpl +50 -200
- package/commands/generate-spec-manifest.md +340 -340
- package/commands/generate-spec-manifest.tmpl +59 -59
- package/commands/generate-tech-docs.md +365 -365
- package/commands/generate-tech-docs.tmpl +84 -84
- package/commands/learn.md +347 -347
- package/commands/learn.tmpl +22 -22
- package/commands/map-testids.md +322 -322
- package/commands/map-testids.tmpl +41 -41
- package/commands/propose-scenario.md +335 -335
- package/commands/propose-scenario.tmpl +54 -54
- package/commands/qc-analyze.md +323 -324
- package/commands/qc-analyze.tmpl +42 -43
- package/commands/qc-design-test.md +304 -304
- package/commands/qc-design-test.tmpl +23 -23
- package/commands/qc-plan.md +297 -297
- package/commands/qc-plan.tmpl +16 -16
- package/commands/qc-report.md +302 -302
- package/commands/qc-report.tmpl +21 -21
- package/commands/qc-review.md +298 -298
- package/commands/qc-review.tmpl +17 -17
- package/commands/qc-run-test.md +337 -337
- package/commands/qc-run-test.tmpl +35 -35
- package/commands/refine-prd.md +428 -430
- package/commands/refine-prd.tmpl +62 -62
- package/commands/report-bug.md +351 -351
- package/commands/report-bug.tmpl +70 -70
- package/commands/review-code.md +364 -364
- package/commands/review-code.tmpl +39 -39
- package/commands/review-context.md +578 -580
- package/commands/review-context.tmpl +212 -212
- package/commands/review-tech-docs.md +427 -427
- package/commands/review-tech-docs.tmpl +146 -146
- package/commands/setup-ai-first.md +239 -239
- package/commands/setup-ai-first.tmpl +133 -133
- package/commands/sync.md +145 -145
- package/commands/sync.tmpl +93 -93
- package/commands/update-framework.md +88 -88
- package/commands/update-framework.tmpl +36 -36
- package/commands/validate-traces.md +381 -381
- package/commands/validate-traces.tmpl +100 -100
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/debug.md +436 -436
- package/core/commands/define-product.md +350 -345
- package/core/commands/dev-gen-test.md +365 -365
- package/core/commands/dev-run-test.md +376 -376
- package/core/commands/dev-smoke-test.md +341 -341
- package/core/commands/fix-bug.md +403 -403
- package/core/commands/generate-bdd.md +513 -513
- package/core/commands/generate-code.md +481 -483
- package/core/commands/generate-design-spec.md +497 -497
- package/core/commands/generate-prd.md +452 -400
- package/core/commands/generate-spec-manifest.md +340 -340
- package/core/commands/generate-tech-docs.md +365 -365
- package/core/commands/learn.md +347 -347
- package/core/commands/map-testids.md +322 -322
- package/core/commands/propose-scenario.md +335 -335
- package/core/commands/qc-analyze.md +323 -324
- package/core/commands/qc-design-test.md +304 -304
- package/core/commands/qc-plan.md +297 -297
- package/core/commands/qc-report.md +302 -302
- package/core/commands/qc-review.md +298 -298
- package/core/commands/qc-run-test.md +337 -337
- package/core/commands/refine-prd.md +428 -430
- package/core/commands/report-bug.md +351 -351
- package/core/commands/review-code.md +364 -364
- package/core/commands/review-context.md +578 -580
- package/core/commands/review-tech-docs.md +427 -427
- package/core/commands/setup-ai-first.md +239 -239
- package/core/commands/sync.md +145 -145
- package/core/commands/update-framework.md +88 -88
- package/core/commands/validate-traces.md +381 -381
- package/core/skills/code/SKILL.md +389 -389
- package/core/skills/debug/SKILL.md +391 -391
- package/core/skills/design-spec/SKILL.md +318 -318
- package/core/skills/discovery/SKILL.md +7 -547
- package/core/skills/prd/SKILL.md +298 -394
- package/core/skills/setup-ai-first/SKILL.md +80 -80
- package/core/skills/spec/SKILL.md +178 -178
- package/core/skills/test/SKILL.md +604 -604
- package/core/steps/capture-lesson.md +44 -44
- package/core/steps/context-loader.md +175 -175
- package/core/steps/gate.md +54 -54
- package/core/steps/report-footer.md +52 -52
- package/core/steps/review-fanout.md +85 -87
- package/core/steps/spawn-agent.md +45 -45
- package/core/steps/trace-mirror.md +21 -21
- package/core/templates/architecture.template.md +37 -37
- package/core/templates/design-spec.template.md +77 -77
- package/core/templates/platform-guide.template.md +47 -47
- package/core/templates/prd.template.md +107 -232
- package/core/templates/product-definition.template.md +101 -88
- package/core/templates/project-context.yaml +2 -2
- package/docs/01-getting-started/core-concepts.md +1 -1
- package/docs/01-getting-started/quickstart.md +7 -7
- package/docs/02-guides/developer/bdd-and-trace.md +1 -1
- package/docs/02-guides/developer/scenarios.md +5 -5
- package/docs/02-guides/product-owner/handoff-checklist.md +1 -1
- package/docs/02-guides/product-owner/scenarios.md +23 -23
- package/docs/02-guides/tester/bug-reporting.md +2 -2
- package/docs/02-guides/tester/reading-specs.md +2 -2
- package/docs/02-guides/tester/scenarios.md +1 -1
- package/docs/02-guides/tester/spec-manifest.md +3 -3
- package/docs/02-guides/tester/workflow.md +1 -1
- package/docs/03-concepts/architecture.md +3 -3
- package/docs/03-concepts/pipeline.md +3 -3
- package/docs/04-operations/publishing.md +20 -3
- package/docs/04-operations/sync-and-update.md +5 -5
- package/docs/05-reference/command-cheatsheet.md +2 -2
- package/docs/05-reference/commands.md +8 -8
- package/package.json +1 -1
- package/scripts/migrate-specs.js +5 -3
- package/scripts/rename-prd-files.js +174 -0
- package/skills/code/SKILL.md +389 -389
- package/skills/code/SKILL.tmpl +56 -56
- package/skills/debug/SKILL.md +391 -391
- package/skills/debug/SKILL.tmpl +60 -60
- package/skills/design-spec/SKILL.md +318 -318
- package/skills/design-spec/SKILL.tmpl +37 -37
- package/skills/discovery/SKILL.md +7 -547
- package/skills/discovery/SKILL.tmpl +7 -140
- package/skills/prd/SKILL.md +298 -394
- package/skills/prd/SKILL.tmpl +40 -151
- package/skills/setup-ai-first/SKILL.md +80 -80
- package/skills/setup-ai-first/SKILL.tmpl +28 -28
- package/skills/spec/SKILL.md +178 -178
- package/skills/spec/SKILL.tmpl +20 -20
- package/skills/test/SKILL.md +604 -604
- package/skills/test/SKILL.tmpl +44 -44
- package/steps/capture-lesson.md +44 -44
- package/steps/context-loader.md +175 -175
- package/steps/gate.md +54 -54
- package/steps/report-footer.md +52 -52
- package/steps/review-fanout.md +85 -87
- package/steps/spawn-agent.md +45 -45
- package/steps/trace-mirror.md +21 -21
- package/templates/architecture.template.md +37 -37
- package/templates/design-spec.template.md +77 -77
- package/templates/platform-guide.template.md +47 -47
- package/templates/prd.template.md +107 -232
- package/templates/product-definition.template.md +101 -88
- package/templates/project-context.yaml +2 -2
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
# /generate-design-spec —
|
|
1
|
+
# /generate-design-spec — Sinh Design Specification (FE / App)
|
|
2
2
|
|
|
3
3
|
## Gate
|
|
4
4
|
{{include:steps/gate.md}}
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
*Lưu ý: Với lệnh này, target file là một Business PRD (`{TICKET-ID}-{prd-slug}.md` — file `.md` ở gốc feature folder) dưới `{paths.specs_dir}/{domain}/{prd-slug}/`. Phân giải từ `$ARGUMENTS` hoặc liệt kê thư mục và hỏi. Chỉ hỗ trợ PRD của FE và mobile — PRD của BE sẽ bị từ chối ở bước Platform Check.*
|
|
7
7
|
|
|
8
8
|
## Context
|
|
9
9
|
{{include:steps/context-loader.md}}
|
|
10
10
|
|
|
11
|
-
*
|
|
11
|
+
*Context bổ sung cho lệnh này: Đọc toàn bộ PRD target. Trích xuất: **TICKET-ID**, **domain**, **tên feature**, **Service** và **Module** từ metadata PRD (row `| **Service** |` và `| **Module** |`), User Flow (Section 4a), và tên màn hình Wireframe (Section 4b).*
|
|
12
12
|
|
|
13
|
-
*
|
|
14
|
-
- *
|
|
15
|
-
- *
|
|
16
|
-
- *
|
|
13
|
+
*Quy tắc trích xuất Service (giống /generate-prd):*
|
|
14
|
+
- *Nếu metadata PRD có `| **Service** |` → dùng làm `active_service` và `| **Module** |` làm `active_module`.*
|
|
15
|
+
- *Nếu vắng VÀ `services` được định nghĩa trong `project-context.yaml` → hỏi: "Design Spec này dành cho service nào?" (chỉ liệt kê service FE/App, chờ chọn).*
|
|
16
|
+
- *Nếu dự án single-service → `active_service = "default"`, `active_module = tech_stack.module`.*
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
20
|
## Platform Check
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Dùng `active_module` và `platform_type` suy ra từ context loading:
|
|
23
23
|
|
|
24
|
-
1.
|
|
24
|
+
1. Nếu `platform_type = "backend"` → **STOP**. Xuất:
|
|
25
25
|
```
|
|
26
|
-
❌ Design Spec
|
|
27
|
-
|
|
26
|
+
❌ Design Spec chỉ dành cho platform FE và mobile.
|
|
27
|
+
Với service BE, API contract thuộc về Business PRD (Use Case → section Business Logic).
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
2.
|
|
30
|
+
2. Nếu `platform_type = "web-frontend"` → set `active_platform = "web"`.
|
|
31
31
|
|
|
32
|
-
3.
|
|
33
|
-
- `flutter`
|
|
32
|
+
3. Nếu `platform_type = "mobile"`:
|
|
33
|
+
- `flutter` hoặc `react-native` → set `active_platform = "app"`
|
|
34
34
|
- `ios-swiftui` → set `active_platform = "app-ios"`
|
|
35
35
|
- `android-compose` → set `active_platform = "app-android"`
|
|
36
36
|
|
|
37
|
-
4.
|
|
37
|
+
4. Nếu `platform_type = "unknown"` → hỏi: "Design Spec này dành cho platform nào?"
|
|
38
38
|
```
|
|
39
39
|
Options:
|
|
40
40
|
1 — web (React / Next.js / Vue / Angular)
|
|
@@ -42,15 +42,15 @@ Using `active_module` and `platform_type` derived from context loading:
|
|
|
42
42
|
3 — app-ios (iOS SwiftUI)
|
|
43
43
|
4 — app-android (Android Compose)
|
|
44
44
|
```
|
|
45
|
-
|
|
45
|
+
Chờ chọn. Map lựa chọn sang `active_platform` và suy ra `active_module` nếu được.
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
49
|
## Screen Discovery
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
Từ Section 4 của PRD (User Flow + Wireframe), trích xuất mọi tên screen / page / modal được nhắc tới.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Trình bày danh sách và hỏi PO xác nhận:
|
|
54
54
|
|
|
55
55
|
```
|
|
56
56
|
Screens detected from PRD:
|
|
@@ -58,59 +58,59 @@ Screens detected from PRD:
|
|
|
58
58
|
2. {Screen name 2}
|
|
59
59
|
...
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
Đây đã đủ các màn cho platform {active_platform} chưa?
|
|
62
|
+
Thêm màn còn thiếu, bỏ màn không áp dụng, hoặc xác nhận bằng Y.
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Chờ xác nhận. Lưu danh sách đã xác nhận là `screen_list`.
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
69
|
-
## Figma Frame Links *(
|
|
69
|
+
## Figma Frame Links *(bắt buộc — một link node-level đọc được cho mỗi màn)*
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
**node-level
|
|
74
|
-
|
|
75
|
-
link
|
|
71
|
+
Một Design Spec chỉ tốt ngang với design mà nó trỏ tới. AI **không đọc được link file
|
|
72
|
+
trần** (`figma.com/design/{fileKey}/...` không có `node-id`) — nó cần một
|
|
73
|
+
**link node-level tới từng frame cụ thể** để fetch layout, component, và token thật của
|
|
74
|
+
frame đó qua Figma MCP. Vậy nên thu thập một link **mỗi màn**, không phải một
|
|
75
|
+
link cho cả feature.
|
|
76
76
|
|
|
77
|
-
**
|
|
77
|
+
**Hỏi PO, liệt kê mọi màn trong `screen_list`:**
|
|
78
78
|
|
|
79
79
|
```
|
|
80
|
-
|
|
80
|
+
Dán link Figma frame cho từng màn bên dưới.
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
(
|
|
82
|
+
Trong Figma: chọn frame → chuột phải → "Copy link to selection"
|
|
83
|
+
(URL phải chứa ?node-id=... — đó là link per-frame mà AI đọc được)
|
|
84
84
|
|
|
85
85
|
1. {Screen 1} : ____
|
|
86
86
|
2. {Screen 2} : ____
|
|
87
87
|
...
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
Nếu một màn chưa có design, gõ none cho màn đó.
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
**
|
|
92
|
+
**Với mỗi câu trả lời:**
|
|
93
93
|
|
|
94
|
-
1. **Validate format** —
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
- `none` → `figma_frames[{screen}] = "TBD"`,
|
|
94
|
+
1. **Validate format** — URL phải khớp `figma.com/design/{fileKey}/...?node-id={nodeId}`.
|
|
95
|
+
- Hợp lệ → lưu thành `figma_frames[{screen}] = {url}`, parse ra `fileKey` + `nodeId`.
|
|
96
|
+
- Link file **không có `node-id`** → từ chối: "Link này trỏ tới cả file, không phải một frame. Copy lại qua chuột phải → Copy link to selection." Hỏi lại màn đó.
|
|
97
|
+
- `none` → `figma_frames[{screen}] = "TBD"`, đánh dấu màn đó ❌ Missing.
|
|
98
98
|
|
|
99
|
-
2. **Fetch
|
|
100
|
-
(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
(permission / not found) →
|
|
99
|
+
2. **Fetch frame qua Figma MCP** (chỉ với link hợp lệ) — gọi `get_design_context`
|
|
100
|
+
(và `get_screenshot` khi hữu ích) với `fileKey` + `nodeId` đã parse để đọc
|
|
101
|
+
layout, tên component, và design token thật. Đặt mọi Screen Spec dựa trên dữ liệu
|
|
102
|
+
đã fetch này; **đừng** bịa layout mà frame không thể hiện. Nếu fetch thất bại
|
|
103
|
+
(permission / not found) → coi màn đó là ❌ Missing và ghi chú lỗi fetch.
|
|
104
104
|
|
|
105
|
-
3.
|
|
106
|
-
|
|
105
|
+
3. Suy ra `figma_url` mức feature = link file (không có `node-id`) chung của các
|
|
106
|
+
frame, cho row Metadata. Nếu các frame trải nhiều file, liệt kê từng cái.
|
|
107
107
|
|
|
108
|
-
**
|
|
109
|
-
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
-
|
|
113
|
-
|
|
108
|
+
**Gate bắt buộc (không abort — sinh ra draft):**
|
|
109
|
+
- Nếu **bất kỳ** màn nào ❌ Missing → spec được sinh dưới dạng **draft** với các màn đó
|
|
110
|
+
được gắn cờ, nhưng `Status` vẫn là `draft` và **sign-off / `/generate-bdd` bị chặn** cho tới khi
|
|
111
|
+
mọi màn có link frame đọc được, đã fetch. Ghi `missing_frames = [screens]`.
|
|
112
|
+
- Thêm một AI Assumption cho mỗi màn thiếu: "Không có Figma frame đọc được cho {screen} — spec
|
|
113
|
+
của màn này chỉ là text và không được sign off cho tới khi thêm link `node-id`."
|
|
114
114
|
|
|
115
115
|
---
|
|
116
116
|
|
|
@@ -124,58 +124,58 @@ Platform : {active_platform}
|
|
|
124
124
|
Module : {active_module}
|
|
125
125
|
Service : {active_service}
|
|
126
126
|
Domain : {domain}
|
|
127
|
-
Screens : {N} — {
|
|
128
|
-
Figma : {linked}/{N}
|
|
127
|
+
Screens : {N} — {screen_list ngăn cách bởi dấu phẩy}
|
|
128
|
+
Figma : {linked}/{N} màn có link frame đọc được{; missing: missing_frames ngăn cách bởi dấu phẩy}
|
|
129
129
|
Output path : {paths.specs_dir}/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{active_platform}-{slug}.md
|
|
130
130
|
|
|
131
|
-
{
|
|
132
|
-
⚠️ {count}
|
|
133
|
-
text
|
|
131
|
+
{Nếu missing_frames khác rỗng}:
|
|
132
|
+
⚠️ {count} màn không có link Figma frame đọc được — các màn này sẽ được sinh dưới dạng
|
|
133
|
+
draft chỉ-text và spec không thể sign off cho tới khi thêm link node-id.
|
|
134
134
|
|
|
135
135
|
Generate? (Y/N)
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
Chờ Y rõ ràng trước khi tiếp tục.
|
|
139
139
|
|
|
140
140
|
---
|
|
141
141
|
|
|
142
142
|
## Generation Rules
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
**Component mapping (C.M —
|
|
147
|
-
-
|
|
148
|
-
- ✅ Matched →
|
|
149
|
-
- ⚠️ Matched
|
|
150
|
-
- ❌
|
|
151
|
-
-
|
|
152
|
-
|
|
153
|
-
**
|
|
154
|
-
- Section 3 (Interaction Patterns)
|
|
155
|
-
- `web` →
|
|
156
|
-
- `app` / `app-ios` / `app-android` →
|
|
157
|
-
-
|
|
158
|
-
|
|
159
|
-
**Figma grounding (
|
|
160
|
-
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
-
|
|
164
|
-
Spec
|
|
165
|
-
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
**Screen states (
|
|
169
|
-
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
144
|
+
Áp dụng các quy tắc này nhất quán khi sinh mọi section:
|
|
145
|
+
|
|
146
|
+
**Component mapping (C.M — bắt buộc):**
|
|
147
|
+
- Với mỗi component được tham chiếu, kiểm tra `figma-components/{active_module}.md` (đã nạp trong context).
|
|
148
|
+
- ✅ Matched → dùng đúng `Code Component` và `Import Path` từ catalog.
|
|
149
|
+
- ⚠️ Matched nhưng `[TODO]` → đánh dấu ô component là `[TODO — implementation pending]`.
|
|
150
|
+
- ❌ Không có trong catalog → đánh dấu `[NEW — confirm with designer before generating code]`.
|
|
151
|
+
- Không bao giờ bịa tên component hay import path.
|
|
152
|
+
|
|
153
|
+
**Section thích ứng theo platform:**
|
|
154
|
+
- Section 3 (Interaction Patterns) và Section 4 (Platform Considerations) thích ứng theo `active_platform`:
|
|
155
|
+
- `web` → gồm responsive breakpoint, trạng thái hover/focus, keyboard navigation, accessibility.
|
|
156
|
+
- `app` / `app-ios` / `app-android` → gồm gesture, safe area, touch target tối thiểu, navigation pattern, deep link, permission, hành vi offline.
|
|
157
|
+
- Chỉ sinh section liên quan tới `active_platform`. Bỏ hẳn section của platform kia.
|
|
158
|
+
|
|
159
|
+
**Figma grounding (bắt buộc):**
|
|
160
|
+
- Với mỗi màn có frame đã fetch (`figma_frames[screen]` là link hợp lệ), dựa Layout,
|
|
161
|
+
Component Inventory, và Screen States trên **dữ liệu Figma đã fetch** — tên component thật,
|
|
162
|
+
token thật, cấu trúc frame thật. Đừng mâu thuẫn hay bịa layout.
|
|
163
|
+
- Dùng đúng URL `figma_frames[screen]` từng-màn trong Screen Inventory, header mỗi Screen
|
|
164
|
+
Spec, và Figma Summary — không bao giờ dùng fragment giả `{figma_url}#screen1`.
|
|
165
|
+
- Với màn ❌ Missing: sinh draft chỉ-text từ PRD, thêm tiền tố vào Screen Spec
|
|
166
|
+
`> [DRAFT — no Figma frame; do not sign off]`, và để ô Figma là ❌ Missing.
|
|
167
|
+
|
|
168
|
+
**Screen states (bắt buộc mỗi màn):**
|
|
169
|
+
- Mỗi màn phải mô tả tối thiểu: `default`, `loading`, `error`.
|
|
170
|
+
- Thêm `empty` khi màn có thể hiển thị trạng thái không dữ liệu.
|
|
171
|
+
- Thêm `success` khi một action hoàn tất tạo ra trạng thái xác nhận riêng biệt.
|
|
172
|
+
- Nếu một state không áp dụng → đánh dấu `N/A` kèm lý do ngắn.
|
|
173
173
|
|
|
174
174
|
---
|
|
175
175
|
|
|
176
176
|
## Generate
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
Ghi `{paths.specs_dir}/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{active_platform}-{slug}.md`:
|
|
179
179
|
|
|
180
180
|
````markdown
|
|
181
181
|
# {TICKET-ID} {Feature Name} — Design Spec [{active_platform}]
|
|
@@ -193,42 +193,42 @@ Write `{paths.specs_dir}/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec
|
|
|
193
193
|
| **Module** | {active_module} |
|
|
194
194
|
| **Service** | {active_service} |
|
|
195
195
|
| **Domain** | {domain} |
|
|
196
|
-
| **Business PRD** | [{TICKET-ID}]({
|
|
197
|
-
| **Figma** | {figma_url —
|
|
198
|
-
| **Author** | {PO
|
|
196
|
+
| **Business PRD** | [{TICKET-ID}](../{TICKET-ID}-{prd-slug}.md) |
|
|
197
|
+
| **Figma** | {figma_url — link file feature} ({linked}/{N} frame đã link) |
|
|
198
|
+
| **Author** | {tên PO hoặc "AI-assisted"} |
|
|
199
199
|
| **Created** | {YYYY-MM-DD} |
|
|
200
200
|
| **Updated** | {YYYY-MM-DD} |
|
|
201
201
|
|
|
202
202
|
---
|
|
203
203
|
|
|
204
|
-
# 1. Screen Inventory
|
|
204
|
+
# 1. Danh mục màn hình (Screen Inventory)
|
|
205
205
|
|
|
206
|
-
| # |
|
|
206
|
+
| # | Tên màn hình | Điểm vào | Figma Frame | Ghi chú |
|
|
207
207
|
|---|-------------|-------------|-------------|-------|
|
|
208
|
-
| 1 | {
|
|
209
|
-
| 2 | {
|
|
208
|
+
| 1 | {Màn hình 1} | {người dùng đến từ đâu — vd: tap CTA ở Home} | [Frame]({figma_frames[Screen 1]}) | |
|
|
209
|
+
| 2 | {Màn hình 2} | {điểm vào} | [Frame]({figma_frames[Screen 2]}) / ❌ Missing | |
|
|
210
210
|
|
|
211
211
|
---
|
|
212
212
|
|
|
213
|
-
# 2. Screen Specs
|
|
213
|
+
# 2. Đặc tả màn hình (Screen Specs)
|
|
214
214
|
|
|
215
215
|
<!--
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
Lặp lại block này cho mỗi màn trong Screen Inventory.
|
|
217
|
+
Mỗi màn phải có: Layout, Component Inventory, Screen States, Actions & Navigation.
|
|
218
218
|
-->
|
|
219
219
|
|
|
220
|
-
##
|
|
220
|
+
## Màn hình 1: {Tên màn hình}
|
|
221
221
|
|
|
222
|
-
**Figma**: [{
|
|
222
|
+
**Figma**: [{Tên frame}]({figma_frames[Screen 1]}) <!-- ❌ Missing → thêm tiền tố cho màn này `> [DRAFT — no Figma frame; do not sign off]` -->
|
|
223
223
|
|
|
224
224
|
### Layout
|
|
225
225
|
|
|
226
|
-
{
|
|
227
|
-
|
|
226
|
+
{Mô tả layout: số cột grid, container max-width, thứ tự section, padding, giá trị spacing chính.
|
|
227
|
+
Tham chiếu design token nếu áp dụng được (vd: `spacing.md = 16px`, `color.surface`).}
|
|
228
228
|
|
|
229
229
|
### Component Inventory
|
|
230
230
|
|
|
231
|
-
| Component (Figma) | Code Component | Import Path | States |
|
|
231
|
+
| Component (Figma) | Code Component | Import Path | States | Ghi chú |
|
|
232
232
|
|---------------------|-----------------|------------------------|---------------------------------|--------------------|
|
|
233
233
|
| {Figma/Button/Primary} | Button | @/components/ui/Button | default, loading, disabled | |
|
|
234
234
|
| {Figma/Input/Text} | TextInput | @/components/ui/Input | default, focus, error, disabled | |
|
|
@@ -236,171 +236,171 @@ Write `{paths.specs_dir}/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec
|
|
|
236
236
|
|
|
237
237
|
### Screen States
|
|
238
238
|
|
|
239
|
-
| State | Trigger | UI
|
|
239
|
+
| State | Trigger | Hành vi UI |
|
|
240
240
|
|-----------|-------------------------------------|--------------------------------------------------------------|
|
|
241
|
-
| default |
|
|
242
|
-
| loading | API
|
|
243
|
-
| error | API
|
|
244
|
-
| empty | API
|
|
245
|
-
| success | Action
|
|
241
|
+
| default | Màn đã load, có dữ liệu | {Mô tả toàn bộ giao diện đã render} |
|
|
242
|
+
| loading | API đang gọi | {Layout skeleton / vị trí spinner — tham chiếu component} |
|
|
243
|
+
| error | API thất bại hoặc lỗi validation | {Toast / message inline / màn lỗi — copy chính xác TBD} |
|
|
244
|
+
| empty | API trả về list rỗng / không dữ liệu | {Illustration empty state + text CTA — vd: "Chưa có order. Bắt đầu mua sắm →"} |
|
|
245
|
+
| success | Action hoàn tất (nếu áp dụng) | {Message xác nhận / điều hướng / thay đổi trạng thái} |
|
|
246
246
|
|
|
247
247
|
### Actions & Navigation
|
|
248
248
|
|
|
249
|
-
| Action | Trigger |
|
|
249
|
+
| Action | Trigger | Kết quả |
|
|
250
250
|
|-----------------|--------------------------------|-------------------------------------------------|
|
|
251
|
-
| {
|
|
252
|
-
| {
|
|
253
|
-
| {Back / Cancel} |
|
|
251
|
+
| {Tên action} | Tap/click {tên phần tử} | Điều hướng tới {Màn hình N} / Mở {Tên modal} |
|
|
252
|
+
| {Tên action} | Swipe trái trên {list item} | Hiện xác nhận xoá |
|
|
253
|
+
| {Back / Cancel} | Cử chỉ back / nút Cancel | Quay lại {màn trước} mà không lưu |
|
|
254
254
|
|
|
255
255
|
---
|
|
256
256
|
|
|
257
|
-
<!--
|
|
257
|
+
<!-- Lặp lại block ## Màn hình N cho mỗi màn bổ sung -->
|
|
258
258
|
|
|
259
259
|
---
|
|
260
260
|
|
|
261
|
-
# 3. Interaction Patterns
|
|
261
|
+
# 3. Pattern tương tác (Interaction Patterns)
|
|
262
262
|
|
|
263
263
|
<!--
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
Platform web: gồm section A + B. Bỏ section C.
|
|
265
|
+
Platform app: gồm section C. Bỏ section A + B.
|
|
266
266
|
-->
|
|
267
267
|
|
|
268
|
-
<!-- ═══════════════════════════ WEB
|
|
268
|
+
<!-- ═══════════════════════════ CHỈ WEB ═══════════════════════════ -->
|
|
269
269
|
|
|
270
|
-
## A. Responsive
|
|
270
|
+
## A. Hành vi Responsive *(chỉ web)*
|
|
271
271
|
|
|
272
|
-
| Breakpoint | Width |
|
|
272
|
+
| Breakpoint | Width | Thay đổi layout |
|
|
273
273
|
|------------|------------|----------------------------------------------------|
|
|
274
|
-
| Mobile | < 768px | {
|
|
275
|
-
| Tablet | 768–1279px | {2
|
|
276
|
-
| Desktop | ≥ 1280px | {
|
|
274
|
+
| Mobile | < 768px | {1 cột, bottom navigation bar, CTA full-width} |
|
|
275
|
+
| Tablet | 768–1279px | {grid 2 cột, sidebar thu gọn, tab navigation} |
|
|
276
|
+
| Desktop | ≥ 1280px | {layout đầy đủ, sidebar hiển thị, max-width 1440px}|
|
|
277
277
|
|
|
278
|
-
## B. Hover / Focus / Keyboard *(web
|
|
278
|
+
## B. Hover / Focus / Keyboard *(chỉ web)*
|
|
279
279
|
|
|
280
|
-
|
|
|
280
|
+
| Phần tử | Trạng thái Hover | Trạng thái Focus | Phím tắt |
|
|
281
281
|
|----------------|-------------------------------|---------------------------------|-------------------|
|
|
282
282
|
| Primary button | Background → {color.hover} | Outline 2px {color.focus} | Enter / Space |
|
|
283
|
-
| Text input | Border → {color.border.hover} | Border → {color.primary}, label
|
|
284
|
-
| Dropdown |
|
|
283
|
+
| Text input | Border → {color.border.hover} | Border → {color.primary}, label nổi | Tab to focus |
|
|
284
|
+
| Dropdown | Highlight nền | Giống hover + ring | Phím mũi tên điều hướng |
|
|
285
285
|
|
|
286
|
-
<!-- ═══════════════════════════ APP
|
|
286
|
+
<!-- ═══════════════════════════ CHỈ APP ═══════════════════════════ -->
|
|
287
287
|
|
|
288
|
-
## C.
|
|
288
|
+
## C. Cử chỉ & Điều hướng *(chỉ app)*
|
|
289
289
|
|
|
290
|
-
|
|
|
290
|
+
| Cử chỉ | Màn / Phần tử | Hành vi |
|
|
291
291
|
|-------------------|---------------------------|-------------------------------------------------------|
|
|
292
|
-
|
|
|
293
|
-
| Pull-to-refresh | {
|
|
294
|
-
| Swipe
|
|
295
|
-
| Long press | {
|
|
296
|
-
| Pinch / zoom | {Image viewer} | Scale
|
|
292
|
+
| Cử chỉ back (iOS swipe-right / Android back) | Mọi màn | {Quay lại màn trước / Hiện dialog "Discard changes?"} |
|
|
293
|
+
| Pull-to-refresh | {Tên màn} | Refresh dữ liệu, spinner ở trên cùng |
|
|
294
|
+
| Swipe trái trên row | {Tên list item} | Hiện action {Delete / Archive} |
|
|
295
|
+
| Long press | {Tên phần tử} | {Context menu / chế độ chọn} |
|
|
296
|
+
| Pinch / zoom | {Image viewer} | Scale ảnh, double-tap để reset |
|
|
297
297
|
|
|
298
|
-
### Navigation Pattern *(app
|
|
298
|
+
### Navigation Pattern *(chỉ app)*
|
|
299
299
|
|
|
300
300
|
```
|
|
301
|
-
{
|
|
301
|
+
{Vẽ navigation stack cho feature này, vd:
|
|
302
302
|
BottomTab(Home) → FeatureListPage → FeatureDetailPage → EditPage
|
|
303
303
|
BottomTab(Home) → FeatureListPage ↘ (modal) CreatePage
|
|
304
304
|
}
|
|
305
305
|
```
|
|
306
306
|
|
|
307
|
-
Entry: {
|
|
308
|
-
Exit: {
|
|
307
|
+
Entry: {người dùng vào feature này thế nào — tab / deeplink / push từ màn khác}
|
|
308
|
+
Exit: {người dùng rời thế nào — back stack / chuyển tab / deeplink out}
|
|
309
309
|
|
|
310
|
-
### Platform Conventions *(app
|
|
310
|
+
### Platform Conventions *(chỉ app)*
|
|
311
311
|
|
|
312
|
-
|
|
|
312
|
+
| Khía cạnh | Hành vi iOS | Hành vi Android |
|
|
313
313
|
|--------------------------|-----------------------------------------|-----------------------------------------|
|
|
314
|
-
| Navigation bar | {
|
|
315
|
-
| Sheet / bottom modal | {UISheetPresentation, grabber
|
|
316
|
-
| Alert / confirm dialog | {UIAlertController,
|
|
314
|
+
| Navigation bar | {Nút back trên-trái, title canh giữa} | {Mũi tên Up trên-trái, title canh trái} |
|
|
315
|
+
| Sheet / bottom modal | {UISheetPresentation, hiện grabber} | {BottomSheet, drag handle} |
|
|
316
|
+
| Alert / confirm dialog | {UIAlertController, action canh phải} | {Material AlertDialog, action canh trái}|
|
|
317
317
|
| Loading indicator | {UIActivityIndicatorView, center} | {CircularProgressIndicator} |
|
|
318
318
|
| Toast / snackbar | {Custom toast, bottom center} | {Material Snackbar, bottom} |
|
|
319
319
|
|
|
320
320
|
---
|
|
321
321
|
|
|
322
|
-
# 4. Platform Considerations
|
|
322
|
+
# 4. Cân nhắc theo Platform (Platform Considerations)
|
|
323
323
|
|
|
324
324
|
<!--
|
|
325
|
-
Web:
|
|
325
|
+
Web: gồm section A. App: gồm section B. Bỏ section không áp dụng.
|
|
326
326
|
-->
|
|
327
327
|
|
|
328
|
-
<!-- ═══════════════════════════ WEB
|
|
328
|
+
<!-- ═══════════════════════════ CHỈ WEB ═══════════════════════════ -->
|
|
329
329
|
|
|
330
|
-
## A. Accessibility *(web
|
|
330
|
+
## A. Accessibility *(chỉ web)*
|
|
331
331
|
|
|
332
|
-
- [ ]
|
|
333
|
-
- [ ] Focus trap
|
|
334
|
-
- [ ]
|
|
335
|
-
- [ ]
|
|
336
|
-
- [ ]
|
|
337
|
-
- [ ]
|
|
338
|
-
- [ ]
|
|
332
|
+
- [ ] Mọi phần tử tương tác tới được bằng phím Tab — không có keyboard trap
|
|
333
|
+
- [ ] Focus trap bên trong modal dialog (Tab chỉ chạy vòng trong modal)
|
|
334
|
+
- [ ] Nút chỉ-icon có `aria-label` mô tả hành động
|
|
335
|
+
- [ ] Cập nhật nội dung động (loading → loaded) thông báo qua `aria-live`
|
|
336
|
+
- [ ] Tương phản màu đạt WCAG AA: text ≥ 4.5:1, text lớn ≥ 3:1
|
|
337
|
+
- [ ] Input form có label hiển thị (không chỉ placeholder)
|
|
338
|
+
- [ ] Message lỗi liên kết với input qua `aria-describedby`
|
|
339
339
|
|
|
340
|
-
<!-- ═══════════════════════════ APP
|
|
340
|
+
<!-- ═══════════════════════════ CHỉ APP ═══════════════════════════ -->
|
|
341
341
|
|
|
342
|
-
## B.
|
|
342
|
+
## B. Thiết bị & OS *(chỉ app)*
|
|
343
343
|
|
|
344
|
-
- [ ]
|
|
345
|
-
- [ ]
|
|
346
|
-
- [ ]
|
|
347
|
-
- [ ] Deep link entry: `{scheme}://{host}/{path}` →
|
|
348
|
-
- [ ] Permission
|
|
349
|
-
- {Permission}:
|
|
350
|
-
- [ ]
|
|
351
|
-
- {
|
|
352
|
-
- {
|
|
353
|
-
- [ ] Dark mode:
|
|
344
|
+
- [ ] Áp dụng safe area insets ở mọi màn — trên (status bar) và dưới (home indicator)
|
|
345
|
+
- [ ] Touch target tối thiểu: 44×44pt (iOS) / 48×48dp (Android)
|
|
346
|
+
- [ ] Đã test trên màn nhỏ: rộng 375pt (iPhone SE) / rộng 360dp (Android phổ biến)
|
|
347
|
+
- [ ] Deep link entry: `{scheme}://{host}/{path}` → vào {tên màn} với {param} đã điền sẵn
|
|
348
|
+
- [ ] Permission gate: {liệt kê permission cần — Camera / Location / Notification}
|
|
349
|
+
- {Permission}: yêu cầu ở {tên màn} với copy lý do: "{copy TBD}"
|
|
350
|
+
- [ ] Hành vi offline / không mạng:
|
|
351
|
+
- {Tên màn}: hiện dữ liệu cache + banner offline
|
|
352
|
+
- {Tên action}: disable nút, hiện tooltip "Requires connection"
|
|
353
|
+
- [ ] Dark mode: mọi màn đã test dark mode — không có màu hardcode
|
|
354
354
|
|
|
355
355
|
---
|
|
356
356
|
|
|
357
|
-
# 5. AC-UI —
|
|
357
|
+
# 5. AC-UI — Tiêu chí chấp nhận về Design
|
|
358
358
|
|
|
359
|
-
>
|
|
360
|
-
>
|
|
359
|
+
> Được **PO + Designer** cùng review và sign off trước khi sinh BDD.
|
|
360
|
+
> Bổ sung cho (không thay thế) AC mức nghiệp vụ trong [Business PRD]({prd-path}).
|
|
361
361
|
|
|
362
|
-
| ID |
|
|
362
|
+
| ID | Tiêu chí chấp nhận | Verified by |
|
|
363
363
|
|--------|--------------------------------------------------------------------------------|-----------------|
|
|
364
|
-
| AC-UI1 |
|
|
365
|
-
| AC-UI2 |
|
|
366
|
-
| AC-UI3 |
|
|
367
|
-
| AC-UI4 | Empty
|
|
368
|
-
| AC-UI5 | {
|
|
369
|
-
| AC-UI6 | {
|
|
370
|
-
| AC-UI7 | {
|
|
364
|
+
| AC-UI1 | Mọi màn khớp frame Figma đã duyệt trong dung sai design-system | Designer |
|
|
365
|
+
| AC-UI2 | Skeleton/spinner loading xuất hiện trong 200ms kể từ khi gọi API | QA |
|
|
366
|
+
| AC-UI3 | Mọi message lỗi đều hiển thị, rõ ràng, và kèm action khôi phục | PO |
|
|
367
|
+
| AC-UI4 | Empty state có illustration và call-to-action rõ ràng | PO + Designer |
|
|
368
|
+
| AC-UI5 | {Riêng platform — vd web: "Mọi màn pass kiểm tra tương phản WCAG AA"} | QA |
|
|
369
|
+
| AC-UI6 | {Riêng platform — vd app: "Cử chỉ back ở mọi màn quay về đúng màn trước"} | QA |
|
|
370
|
+
| AC-UI7 | {Tiêu chí UI riêng của feature từ section wireframe của Business PRD} | PO |
|
|
371
371
|
|
|
372
372
|
---
|
|
373
373
|
|
|
374
374
|
# Appendix
|
|
375
375
|
|
|
376
|
-
## Figma
|
|
376
|
+
## Tóm tắt Figma
|
|
377
377
|
|
|
378
|
-
|
|
|
378
|
+
| Màn hình | Figma Frame | Trạng thái Link / Fetch |
|
|
379
379
|
|-----------------|--------------------------------------|--------------------------------------|
|
|
380
|
-
| {
|
|
381
|
-
| {
|
|
380
|
+
| {Màn hình 1} | [Link]({figma_frames[Screen 1]}) | ✅ Đã link & fetch |
|
|
381
|
+
| {Màn hình 2} | — | ❌ Missing — không có link node-id |
|
|
382
382
|
|
|
383
|
-
## Design
|
|
383
|
+
## Design Token đã tham chiếu
|
|
384
384
|
|
|
385
|
-
| Token | Value |
|
|
385
|
+
| Token | Value | Dùng ở |
|
|
386
386
|
|-----------------------|---------------|---------------------------------|
|
|
387
|
-
| `color.primary` | {#hex} | Primary
|
|
388
|
-
| `color.surface` | {#hex} |
|
|
389
|
-
| `spacing.md` | {16px / 4} |
|
|
390
|
-
| `typography.heading2` | {font/size} |
|
|
387
|
+
| `color.primary` | {#hex} | Primary button, link, active state |
|
|
388
|
+
| `color.surface` | {#hex} | Nền card |
|
|
389
|
+
| `spacing.md` | {16px / 4} | Khoảng cách dọc tiêu chuẩn |
|
|
390
|
+
| `typography.heading2` | {font/size} | Title màn hình |
|
|
391
391
|
|
|
392
|
-
##
|
|
392
|
+
## Tài liệu tham khảo
|
|
393
393
|
|
|
394
|
-
- [{TICKET-ID}]({prd-path}) — Business PRD (
|
|
395
|
-
- {[
|
|
394
|
+
- [{TICKET-ID}]({prd-path}) — Business PRD (nguồn của AC, UC, BR)
|
|
395
|
+
- {[Design Spec khác](./other-ds.md) — nếu feature này dùng chung màn}
|
|
396
396
|
|
|
397
|
-
## AI
|
|
397
|
+
## Giả định AI
|
|
398
398
|
|
|
399
|
-
>
|
|
400
|
-
> PO
|
|
399
|
+
> Mỗi giả định dưới đây được đưa ra vì input PO chưa đầy đủ.
|
|
400
|
+
> PO phải review và confirm trước khi sign-off.
|
|
401
401
|
|
|
402
|
-
- {
|
|
403
|
-
- {
|
|
402
|
+
- {Giả định 1 — [AI DRAFT]}
|
|
403
|
+
- {Một dòng cho mỗi màn ❌ Missing: "Không có Figma frame đọc được cho {screen} — draft chỉ-text; chặn sign-off cho tới khi thêm link node-id."}
|
|
404
404
|
|
|
405
405
|
---
|
|
406
406
|
|
|
@@ -412,27 +412,27 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
|
|
|
412
412
|
|
|
413
413
|
<!--
|
|
414
414
|
NEXT STEPS:
|
|
415
|
-
1.
|
|
416
|
-
2.
|
|
417
|
-
3. PO + Designer sign off:
|
|
418
|
-
4.
|
|
415
|
+
1. Điền các link Figma frame còn ❌ Missing (link node-id) — chạy lại để fetch & ground chúng.
|
|
416
|
+
2. Chia sẻ với Designer — xác minh link Figma, cập nhật component inventory.
|
|
417
|
+
3. PO + Designer sign off: đổi Status → "approved" (chỉ cho phép khi 0 màn ❌ Missing).
|
|
418
|
+
4. Chạy /generate-bdd "{prd-file}" — BDD dùng AC-UI từ spec này cho FE scenario.
|
|
419
419
|
-->
|
|
420
420
|
````
|
|
421
421
|
|
|
422
422
|
---
|
|
423
423
|
|
|
424
|
-
## Quality Checklist *(
|
|
424
|
+
## Quality Checklist *(kiểm tra trước khi ghi)*
|
|
425
425
|
|
|
426
|
-
- [ ]
|
|
427
|
-
- [ ]
|
|
428
|
-
- [ ]
|
|
429
|
-
- [ ]
|
|
430
|
-
- [ ]
|
|
431
|
-
- [ ] AC-UI
|
|
432
|
-
- [ ]
|
|
433
|
-
- [ ]
|
|
434
|
-
- [ ]
|
|
435
|
-
- [ ]
|
|
426
|
+
- [ ] Mọi màn trong Screen Inventory có Screen Spec đầy đủ ở Section 2
|
|
427
|
+
- [ ] Mọi màn có tối thiểu các state: default, loading, error
|
|
428
|
+
- [ ] Mọi component Figma đã map trong Component Inventory — chưa map thì gắn cờ `[NEW]` hoặc `[TODO]`
|
|
429
|
+
- [ ] Chỉ sinh section liên quan platform ở Section 3 (không có section web trong doc app, và ngược lại)
|
|
430
|
+
- [ ] Chỉ sinh section liên quan platform ở Section 4
|
|
431
|
+
- [ ] Các mục AC-UI testable (pass/fail rõ ràng, không phải "looks good")
|
|
432
|
+
- [ ] Link cross-reference Business PRD là relative path hợp lệ
|
|
433
|
+
- [ ] Mọi màn có link Figma frame node-level (`?node-id=`) — và các màn có link đã được fetch qua Figma MCP và dùng để ground spec
|
|
434
|
+
- [ ] Mỗi màn ❌ Missing được gắn cờ trong spec (`> [DRAFT — no Figma frame...]`), liệt kê trong Figma Summary, và có một AI Assumption
|
|
435
|
+
- [ ] Nếu bất kỳ màn nào ❌ Missing → Status giữ `draft` và Output bên dưới chặn `/generate-bdd`
|
|
436
436
|
|
|
437
437
|
---
|
|
438
438
|
|
|
@@ -440,25 +440,25 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
|
|
|
440
440
|
|
|
441
441
|
{{include:steps/report-footer.md}}
|
|
442
442
|
|
|
443
|
-
{
|
|
443
|
+
{Nếu missing_frames rỗng}:
|
|
444
444
|
```
|
|
445
|
-
/generate-design-spec
|
|
445
|
+
/generate-design-spec Hoàn tất — {TICKET-ID} [{active_platform}]
|
|
446
446
|
---
|
|
447
|
-
Status : ✅ Complete —
|
|
447
|
+
Status : ✅ Complete — cả {N} màn đã link & fetch từ Figma
|
|
448
448
|
Output Artifacts:
|
|
449
449
|
created {paths.specs_dir}/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{active_platform}-{slug}.md (v1.0)
|
|
450
|
-
Next :
|
|
451
|
-
→ /generate-bdd {prd-file} (
|
|
450
|
+
Next : Chia sẻ với Designer → PO + Designer sign-off (Status: approved)
|
|
451
|
+
→ /generate-bdd {prd-file} (sinh BDD theo service; đọc AC-UI từ Design Spec)
|
|
452
452
|
```
|
|
453
453
|
|
|
454
|
-
{
|
|
454
|
+
{Nếu missing_frames khác rỗng}:
|
|
455
455
|
```
|
|
456
|
-
/generate-design-spec
|
|
456
|
+
/generate-design-spec Hoàn tất (DRAFT) — {TICKET-ID} [{active_platform}]
|
|
457
457
|
---
|
|
458
|
-
Status : ⚠️ Warnings — {count}
|
|
458
|
+
Status : ⚠️ Warnings — {count} màn không có link Figma frame đọc được: {missing_frames ngăn cách bởi dấu phẩy}
|
|
459
459
|
Output Artifacts:
|
|
460
460
|
created {paths.specs_dir}/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{active_platform}-{slug}.md (v1.0, draft)
|
|
461
|
-
Next : 🔒 Sign-off & /generate-bdd
|
|
462
|
-
1.
|
|
463
|
-
2.
|
|
461
|
+
Next : 🔒 Sign-off & /generate-bdd bị CHẶN cho tới khi mọi màn có link Figma node-id.
|
|
462
|
+
1. Trong Figma: chọn mỗi frame còn thiếu → chuột phải → Copy link to selection
|
|
463
|
+
2. Chạy lại /generate-design-spec {prd-file} → AI fetch & ground các frame mới
|
|
464
464
|
```
|