@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,27 +1,27 @@
|
|
|
1
|
-
# Sub-Agent
|
|
1
|
+
# Pattern điều phối Sub-Agent
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Dùng bởi các lệnh nặng khi target vượt ngưỡng phức tạp.
|
|
4
|
+
Session chính trở thành một **orchestrator nhẹ** — chỉ điều phối.
|
|
5
|
+
Mỗi đơn vị công việc chạy trong sub-agent riêng với context window mới.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Ngưỡng phức tạp
|
|
10
10
|
|
|
11
|
-
|
|
|
11
|
+
| Tín hiệu | Ngưỡng | Hành động |
|
|
12
12
|
|--------|-----------|--------|
|
|
13
|
-
| UC
|
|
14
|
-
| PRD
|
|
13
|
+
| Số UC trong PRD | > 3 UC | spawn 1 agent cho mỗi UC |
|
|
14
|
+
| Độ dài PRD | > 300 dòng | spawn agent bất kể số UC |
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Nếu vượt **một trong hai** ngưỡng → chuyển sang chế độ orchestration.
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## Orchestrator
|
|
20
|
+
## Các bước của Orchestrator (session chính)
|
|
21
21
|
|
|
22
|
-
###
|
|
22
|
+
### Bước A — Dựng context gọn
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Chỉ trích xuất những gì sub-agent cần — KHÔNG truyền nguyên CLAUDE.md hay nguyên business-dictionary:
|
|
25
25
|
|
|
26
26
|
```json
|
|
27
27
|
{
|
|
@@ -43,49 +43,49 @@ Extract only what sub-agents need — do NOT pass full CLAUDE.md or full busines
|
|
|
43
43
|
"trace_dir": "{paths.trace_dir}",
|
|
44
44
|
"tech_docs_dir": "{paths.tech_docs_dir}"
|
|
45
45
|
},
|
|
46
|
-
"architecture_summary": "<3-5
|
|
46
|
+
"architecture_summary": "<3-5 gạch đầu dòng: thứ tự layer + quy tắc chính>",
|
|
47
47
|
"domains": ["{domain1}", "{domain2}"],
|
|
48
48
|
"banned_terms": ["{term1}", "{term2}"]
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
###
|
|
52
|
+
### Bước B — Trích danh sách UC
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
Quét PRD target tìm các heading `#### {TICKET-ID}-UC{N}:`.
|
|
55
|
+
Dựng list: `[ { uc_id, uc_name, line_start, line_end } ]`
|
|
56
56
|
|
|
57
|
-
###
|
|
57
|
+
### Bước C — Công bố kế hoạch
|
|
58
58
|
|
|
59
59
|
```
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
Agent 1 → {TICKET-ID}-UC1: {UC
|
|
63
|
-
Agent 2 → {TICKET-ID}-UC2: {UC
|
|
60
|
+
Phát hiện độ phức tạp cao — {N} UC / {L} dòng trong {prd_file}
|
|
61
|
+
Đang spawn {N} sub-agent (1 cho mỗi UC)...
|
|
62
|
+
Agent 1 → {TICKET-ID}-UC1: {tên UC}
|
|
63
|
+
Agent 2 → {TICKET-ID}-UC2: {tên UC}
|
|
64
64
|
...
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
###
|
|
67
|
+
### Bước D — Spawn một sub-agent cho mỗi UC
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Dựng payload và gọi Agent tool cho từng UC:
|
|
70
70
|
|
|
71
71
|
```json
|
|
72
72
|
{
|
|
73
73
|
"_agent_mode": true,
|
|
74
74
|
"command": "generate-bdd",
|
|
75
75
|
"uc_id": "{TICKET-ID}-UC{N}",
|
|
76
|
-
"target_file": "{
|
|
76
|
+
"target_file": "{đường dẫn tuyệt đối tới PRD hoặc feature file}",
|
|
77
77
|
"uc_section": { "line_start": {N}, "line_end": {N} },
|
|
78
|
-
"context": { "<
|
|
78
|
+
"context": { "<context gọn từ Bước A>" }
|
|
79
79
|
}
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
> **
|
|
82
|
+
> **Phạm vi lệnh**: Chỉ `/generate-bdd` khởi động chế độ orchestration. `/generate-code` và `/dev-gen-test` có thể chạy như sub-agent (chúng tôn trọng `_agent_mode: true` từ Gate Bước 0), nhưng không spawn thêm sub-agent — phạm vi của chúng vốn đã là một UC duy nhất.
|
|
83
83
|
|
|
84
|
-
Serialize
|
|
84
|
+
Serialize JSON này và truyền làm `$ARGUMENTS` khi gọi lệnh sub-agent.
|
|
85
85
|
|
|
86
|
-
###
|
|
86
|
+
### Bước E — Thu thập và merge kết quả
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
Mỗi sub-agent trả về:
|
|
89
89
|
```json
|
|
90
90
|
{
|
|
91
91
|
"uc_id": "{TICKET-ID}-UC{N}",
|
|
@@ -95,30 +95,30 @@ Each sub-agent returns:
|
|
|
95
95
|
}
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
Merge
|
|
99
|
-
|
|
98
|
+
Merge vào một report duy nhất (theo định dạng report-footer.md).
|
|
99
|
+
Nếu có sub-agent lỗi → liệt kê rõ ràng và đề xuất chạy lại riêng UC đó.
|
|
100
100
|
|
|
101
101
|
---
|
|
102
102
|
|
|
103
|
-
## Sub-Agent
|
|
103
|
+
## Điểm vào của Sub-Agent (các lệnh được gọi)
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
Khi `gate.md Bước 0` phát hiện `_agent_mode: true`:
|
|
106
106
|
|
|
107
|
-
1. Parse
|
|
108
|
-
2. **
|
|
109
|
-
3. **
|
|
110
|
-
4.
|
|
111
|
-
5.
|
|
112
|
-
6.
|
|
107
|
+
1. Parse toàn bộ payload từ `$ARGUMENTS`
|
|
108
|
+
2. **Bỏ qua context-loader.md** — dùng trực tiếp `payload.context`
|
|
109
|
+
3. **Chỉ giới hạn ở `payload.uc_id`** — không xử lý các UC khác trong file
|
|
110
|
+
4. Chỉ đọc section PRD giữa `payload.uc_section.line_start` và `line_end`
|
|
111
|
+
5. Thực thi logic thường của lệnh cho riêng UC này
|
|
112
|
+
6. Trả về JSON kết quả có cấu trúc (định dạng Bước E ở trên)
|
|
113
113
|
|
|
114
114
|
---
|
|
115
115
|
|
|
116
|
-
## Context Window
|
|
116
|
+
## Tiết kiệm Context Window
|
|
117
117
|
|
|
118
|
-
|
|
|
118
|
+
| Chế độ | Nạp gì mỗi session |
|
|
119
119
|
|------|------------------------|
|
|
120
|
-
| Single session (≤ 3 UC) | Full context + full PRD +
|
|
121
|
-
| Orchestrator |
|
|
122
|
-
|
|
|
120
|
+
| Single session (≤ 3 UC) | Full context + full PRD + tất cả UC |
|
|
121
|
+
| Orchestrator | Context gọn + chỉ các heading UC |
|
|
122
|
+
| Mỗi sub-agent | Context gọn + **chỉ 1 section UC** |
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
PRD càng lớn, mức tiết kiệm trên mỗi sub-agent càng nhiều.
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Làm mới panel mirror của Living Docs *(local, chế độ umbrella)*
|
|
2
2
|
|
|
3
|
-
*
|
|
4
|
-
|
|
3
|
+
*Bỏ qua hoàn toàn ở chế độ single-service (không có `services` và không có `setup.spec_source`) — ở đó
|
|
4
|
+
`.trace/` của chính repo CHÍNH LÀ vị trí panel, nên không có gì để mirror.*
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Sau khi cập nhật TSV authoritative tại `{paths.trace_dir}`:
|
|
7
7
|
|
|
8
|
-
**
|
|
9
|
-
`{paths.trace_dir}`
|
|
10
|
-
|
|
11
|
-
commit/push
|
|
12
|
-
1.
|
|
13
|
-
2.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
**Khi `setup.spec_source` được đặt (trace gộp — trường hợp phổ biến):**
|
|
9
|
+
`{paths.trace_dir}` phân giải về `{spec_source}/.trace` — vị trí authoritative duy nhất.
|
|
10
|
+
Lệnh này chạy từ `service_root`, nên thao tác ghi là **liên-repo vào spec submodule**;
|
|
11
|
+
commit/push spec submodule cho lần cập nhật trace (giống như `feedback/`).
|
|
12
|
+
1. Phân giải `panel_mirror = ./.trace` tại **gốc workspace hiện tại**.
|
|
13
|
+
2. Nếu `panel_mirror` phân giải ra path khác với `{paths.trace_dir}`, copy mỗi
|
|
14
|
+
`{UC-ID}.tsv` vừa cập nhật → `{panel_mirror}/{UC-ID}.tsv` (tạo thư mục; ghi đè).
|
|
15
|
+
Không namespace theo service — chỉ có một bộ trace; service sở hữu được mang trong
|
|
16
|
+
`@trace.service` của từng row.
|
|
17
17
|
|
|
18
|
-
**Legacy (
|
|
19
|
-
Copy
|
|
20
|
-
(
|
|
18
|
+
**Legacy (không có `spec_source` — trace theo service):**
|
|
19
|
+
Copy mỗi `{UC-ID}.tsv` vừa cập nhật → `{panel_mirror}/{service-name}/{UC-ID}.tsv`
|
|
20
|
+
(namespace theo `active_service`).
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
**
|
|
24
|
-
`{spec_source}/.living-docs/`)
|
|
25
|
-
|
|
26
|
-
sub-agent.
|
|
22
|
+
Cách này giữ panel Living Docs của workspace đang mở luôn mới **giữa các lần sync** — nó chỉ là
|
|
23
|
+
một **mirror tiện lợi cục bộ**. File `trace-report.json` đã merge (canonical, trong
|
|
24
|
+
`{spec_source}/.living-docs/`) được build lại bởi `/sync` hoặc `/validate-traces`. Với các lệnh
|
|
25
|
+
được orchestrate, làm việc này một lần trong orchestrator sau khi tất cả sub-agent trả về — không phải
|
|
26
|
+
bên trong từng sub-agent.
|
|
@@ -1,56 +1,56 @@
|
|
|
1
1
|
# §1. Project Overview
|
|
2
2
|
|
|
3
3
|
Project : {{PROJECT_NAME}}
|
|
4
|
-
Language : {{LANGUAGE}} #
|
|
5
|
-
Framework : {{FRAMEWORK}} #
|
|
6
|
-
Build : {{BUILD_COMMAND}} #
|
|
7
|
-
Test : {{TEST_COMMAND}} #
|
|
4
|
+
Language : {{LANGUAGE}} # vd: Java 17 / TypeScript / C# / Go
|
|
5
|
+
Framework : {{FRAMEWORK}} # vd: Spring Boot 3.2 / Angular 17 / .NET 8
|
|
6
|
+
Build : {{BUILD_COMMAND}} # vd: mvn clean install -DskipTests / dotnet build / ng build
|
|
7
|
+
Test : {{TEST_COMMAND}} # vd: mvn test / dotnet test / ng test
|
|
8
8
|
Domains : {{COMMA_SEPARATED_DOMAINS}}
|
|
9
9
|
|
|
10
10
|
# §2. Architecture
|
|
11
11
|
|
|
12
|
-
style: "{{ARCH_STYLE}}" #
|
|
12
|
+
style: "{{ARCH_STYLE}}" # vd: Layered / Clean / Hexagonal / Component-based
|
|
13
13
|
|
|
14
14
|
layers: "{{LAYER_STACK}}"
|
|
15
|
-
#
|
|
15
|
+
# Ví dụ:
|
|
16
16
|
# Java/Spring: Controller → Facade → Service → Repository
|
|
17
17
|
# .NET Clean: Presentation → Application → Domain → Infrastructure
|
|
18
18
|
# Angular: Component → Service → HTTP Client → Backend API
|
|
19
19
|
# Go: Handler → UseCase → Repository → Domain
|
|
20
20
|
|
|
21
21
|
rules:
|
|
22
|
-
- "{{ARCH_RULE_1}}" #
|
|
23
|
-
- "{{ARCH_RULE_2}}" #
|
|
24
|
-
- "{{ARCH_RULE_3}}" #
|
|
22
|
+
- "{{ARCH_RULE_1}}" # vd: Controller không được chứa business logic
|
|
23
|
+
- "{{ARCH_RULE_2}}" # vd: Service sở hữu ranh giới transaction
|
|
24
|
+
- "{{ARCH_RULE_3}}" # vd: Repository không được gọi service
|
|
25
25
|
|
|
26
|
-
#
|
|
26
|
+
# Chiều phụ thuộc giữa các layer (layer trong không được phụ thuộc layer ngoài):
|
|
27
27
|
# {{OUTER_LAYER}} → {{MIDDLE_LAYER}} → {{INNER_LAYER}}
|
|
28
28
|
|
|
29
29
|
# §3. Coding Standards
|
|
30
30
|
|
|
31
31
|
naming:
|
|
32
|
-
classes: "{{CLASS_NAMING}}" #
|
|
33
|
-
methods: "{{METHOD_NAMING}}" #
|
|
34
|
-
packages: "{{PACKAGE_NAMING}}" #
|
|
35
|
-
files: "{{FILE_NAMING}}" #
|
|
32
|
+
classes: "{{CLASS_NAMING}}" # vd: PascalCase / PascalCase+Suffix
|
|
33
|
+
methods: "{{METHOD_NAMING}}" # vd: camelCase / PascalCase
|
|
34
|
+
packages: "{{PACKAGE_NAMING}}" # vd: lowercase / lowercase.snake_case
|
|
35
|
+
files: "{{FILE_NAMING}}" # vd: PascalCase.java / kebab-case.ts
|
|
36
36
|
|
|
37
37
|
patterns:
|
|
38
|
-
response_wrapper: "{{RESPONSE_WRAPPER}}" #
|
|
39
|
-
mapping: "{{MAPPING_LIBRARY}}" #
|
|
40
|
-
exception_base: "{{BASE_EXCEPTION}}" #
|
|
38
|
+
response_wrapper: "{{RESPONSE_WRAPPER}}" # vd: ApiResponse<T> / Result<T> / IActionResult
|
|
39
|
+
mapping: "{{MAPPING_LIBRARY}}" # vd: MapStruct / AutoMapper / manual
|
|
40
|
+
exception_base: "{{BASE_EXCEPTION}}" # vd: ResourceNotFoundException / DomainException
|
|
41
41
|
|
|
42
42
|
forbidden:
|
|
43
|
-
- "Magic
|
|
44
|
-
- "
|
|
43
|
+
- "Magic number — dùng hằng số có tên"
|
|
44
|
+
- "Lệnh debug print trong code production"
|
|
45
45
|
- "{{PROJECT_SPECIFIC_FORBIDDEN_PATTERN}}"
|
|
46
46
|
|
|
47
47
|
# §4. API Conventions
|
|
48
48
|
|
|
49
|
-
versioning: "{{API_VERSIONING}}" #
|
|
50
|
-
auth: "{{AUTH_MECHANISM}}" #
|
|
49
|
+
versioning: "{{API_VERSIONING}}" # vd: tiền tố /v1/ / theo header / query param
|
|
50
|
+
auth: "{{AUTH_MECHANISM}}" # vd: JWT Bearer / OAuth2 / API Key
|
|
51
51
|
|
|
52
52
|
http_status:
|
|
53
|
-
get_list: 200 #
|
|
53
|
+
get_list: 200 # danh sách phân trang hoặc đầy đủ
|
|
54
54
|
get_single: 200
|
|
55
55
|
create: 201
|
|
56
56
|
update: 200
|
|
@@ -70,32 +70,32 @@ error_response_format: |
|
|
|
70
70
|
|
|
71
71
|
# §5. Error Handling
|
|
72
72
|
|
|
73
|
-
not_found_exception: "{{NOT_FOUND_EXCEPTION_CLASS}}" #
|
|
74
|
-
validation_exception: "{{VALIDATION_EXCEPTION_CLASS}}" #
|
|
75
|
-
domain_exception: "{{DOMAIN_EXCEPTION_CLASS}}" #
|
|
73
|
+
not_found_exception: "{{NOT_FOUND_EXCEPTION_CLASS}}" # vd: ResourceNotFoundException
|
|
74
|
+
validation_exception: "{{VALIDATION_EXCEPTION_CLASS}}" # vd: ValidationException
|
|
75
|
+
domain_exception: "{{DOMAIN_EXCEPTION_CLASS}}" # vd: DomainException / BusinessRuleViolationException
|
|
76
76
|
|
|
77
|
-
global_handler: "{{GLOBAL_EXCEPTION_HANDLER}}" #
|
|
77
|
+
global_handler: "{{GLOBAL_EXCEPTION_HANDLER}}" # vd: @ControllerAdvice / ExceptionHandlerMiddleware
|
|
78
78
|
|
|
79
79
|
rules:
|
|
80
|
-
- "
|
|
81
|
-
- "Log
|
|
80
|
+
- "Không bao giờ nuốt exception âm thầm"
|
|
81
|
+
- "Log ở mức error kèm full stack trace cho lỗi 5xx"
|
|
82
82
|
- "{{PROJECT_SPECIFIC_ERROR_RULE}}"
|
|
83
83
|
|
|
84
84
|
# §6. Testing Standards
|
|
85
85
|
|
|
86
|
-
unit_test_framework: "{{UNIT_TEST_FW}}" #
|
|
87
|
-
integration_test_framework: "{{IT_TEST_FW}}" #
|
|
86
|
+
unit_test_framework: "{{UNIT_TEST_FW}}" # vd: JUnit 5 + Mockito / xUnit + Moq / Jest
|
|
87
|
+
integration_test_framework: "{{IT_TEST_FW}}" # vd: Spring Boot Test / WebApplicationFactory
|
|
88
88
|
|
|
89
89
|
coverage_targets:
|
|
90
|
-
unit: "{{UNIT_COVERAGE_PCT}}%" #
|
|
91
|
-
integration: "{{IT_COVERAGE_PCT}}%" #
|
|
90
|
+
unit: "{{UNIT_COVERAGE_PCT}}%" # vd: 80%
|
|
91
|
+
integration: "{{IT_COVERAGE_PCT}}%" # vd: phủ các flow chính
|
|
92
92
|
|
|
93
|
-
naming_pattern: "{{TEST_METHOD_NAMING}}" #
|
|
93
|
+
naming_pattern: "{{TEST_METHOD_NAMING}}" # vd: methodName_whenCondition_shouldExpectation
|
|
94
94
|
|
|
95
95
|
rules:
|
|
96
|
-
- "Unit
|
|
97
|
-
- "Integration
|
|
98
|
-
- "
|
|
96
|
+
- "Unit test chỉ mock các dependency trực tiếp"
|
|
97
|
+
- "Integration test phủ happy path + các luồng lỗi chính"
|
|
98
|
+
- "Mọi scenario trong .feature phải có test tương ứng"
|
|
99
99
|
|
|
100
100
|
# §7. Git Conventions
|
|
101
101
|
|
|
@@ -110,4 +110,4 @@ commit_docs: "docs: {description}"
|
|
|
110
110
|
|
|
111
111
|
pr_title: "{{TICKET_PREFIX}}-{N}: {feature name}"
|
|
112
112
|
pr_requires_review: true
|
|
113
|
-
pr_branch_protection: "{{BASE_BRANCH}}" #
|
|
113
|
+
pr_branch_protection: "{{BASE_BRANCH}}" # vd: main / develop
|
|
@@ -41,172 +41,172 @@
|
|
|
41
41
|
| **Service** | {active_service} |
|
|
42
42
|
| **Domain** | {domain} |
|
|
43
43
|
| **Business PRD** | [{TICKET-ID}](./{TICKET-ID}-slug.md) |
|
|
44
|
-
| **Figma** | {
|
|
45
|
-
| **Author** | {PO
|
|
44
|
+
| **Figma** | {link file feature} ({linked}/{N} frame đã link) |
|
|
45
|
+
| **Author** | {tên PO hoặc "AI-assisted"} |
|
|
46
46
|
| **Created** | {YYYY-MM-DD} |
|
|
47
47
|
| **Updated** | {YYYY-MM-DD} |
|
|
48
48
|
|
|
49
49
|
---
|
|
50
50
|
|
|
51
|
-
# 1. Screen Inventory
|
|
51
|
+
# 1. Danh mục màn hình (Screen Inventory)
|
|
52
52
|
|
|
53
|
-
| # |
|
|
53
|
+
| # | Tên màn hình | Điểm vào | Figma Frame (link node-level) | Ghi chú |
|
|
54
54
|
|---|-------------|-------------|-------------------------------|-------|
|
|
55
|
-
| 1 | {
|
|
56
|
-
| 2 | {
|
|
55
|
+
| 1 | {Màn hình 1} | {người dùng đến từ đâu} | [Frame]({node-level url}) | |
|
|
56
|
+
| 2 | {Màn hình 2} | {điểm vào} | ❌ Missing — thêm link node-id | |
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
60
|
-
# 2. Screen Specs
|
|
60
|
+
# 2. Đặc tả màn hình (Screen Specs)
|
|
61
61
|
|
|
62
|
-
##
|
|
62
|
+
## Màn hình 1: {Tên màn hình}
|
|
63
63
|
|
|
64
|
-
**Figma**: [{
|
|
64
|
+
**Figma**: [{Tên frame}]({figma_frame_url})
|
|
65
65
|
|
|
66
66
|
### Layout
|
|
67
67
|
|
|
68
|
-
{Grid / max-width / padding / spacing —
|
|
68
|
+
{Grid / max-width / padding / spacing — tham chiếu design token nếu áp dụng được}
|
|
69
69
|
|
|
70
70
|
### Component Inventory
|
|
71
71
|
|
|
72
|
-
| Component (Figma) | Code Component | Import Path | States |
|
|
72
|
+
| Component (Figma) | Code Component | Import Path | States | Ghi chú |
|
|
73
73
|
|------------------------|----------------|------------------------|---------------------------------|---------|
|
|
74
74
|
| {Figma/Button/Primary} | Button | @/components/ui/Button | default, loading, disabled | |
|
|
75
75
|
| {Figma/Input/Text} | TextInput | @/components/ui/Input | default, focus, error, disabled | |
|
|
76
76
|
|
|
77
77
|
### Screen States
|
|
78
78
|
|
|
79
|
-
| State | Trigger | UI
|
|
79
|
+
| State | Trigger | Hành vi UI |
|
|
80
80
|
|-----------|----------------------------------|----------------------------------------------------------|
|
|
81
|
-
| default |
|
|
82
|
-
| loading | API
|
|
83
|
-
| error | API
|
|
84
|
-
| empty |
|
|
85
|
-
| success | Action
|
|
81
|
+
| default | Màn đã load, có dữ liệu | {Mô tả toàn bộ giao diện đã render} |
|
|
82
|
+
| loading | API đang gọi | {Vị trí và kiểu skeleton / spinner} |
|
|
83
|
+
| error | API thất bại / lỗi validation | {Toast / lỗi inline / màn lỗi + CTA khôi phục} |
|
|
84
|
+
| empty | Không có dữ liệu trả về | {Illustration + CTA — vd: "Chưa có mục nào. Thêm mới →"} |
|
|
85
|
+
| success | Action hoàn tất (nếu có) | {Toast xác nhận / điều hướng / thay đổi giao diện} |
|
|
86
86
|
|
|
87
87
|
### Actions & Navigation
|
|
88
88
|
|
|
89
|
-
| Action | Trigger |
|
|
89
|
+
| Action | Trigger | Kết quả |
|
|
90
90
|
|-----------------|---------------------------|---------------------------------------------------|
|
|
91
|
-
| {
|
|
92
|
-
| {Back/Cancel} |
|
|
91
|
+
| {Tên action} | Tap/click {phần tử} | Điều hướng tới {Màn hình N} / Mở {Tên modal} |
|
|
92
|
+
| {Back/Cancel} | Cử chỉ back / nút | Quay lại {màn trước} mà không lưu |
|
|
93
93
|
|
|
94
94
|
---
|
|
95
95
|
|
|
96
|
-
<!--
|
|
96
|
+
<!-- Lặp lại ## Màn hình N cho mỗi màn bổ sung -->
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
100
|
-
# 3. Interaction Patterns
|
|
100
|
+
# 3. Pattern tương tác (Interaction Patterns)
|
|
101
101
|
|
|
102
|
-
<!-- === WEB
|
|
102
|
+
<!-- === CHỈ WEB — xóa section này cho app === -->
|
|
103
103
|
|
|
104
|
-
## A. Responsive
|
|
104
|
+
## A. Hành vi Responsive *(web)*
|
|
105
105
|
|
|
106
|
-
| Breakpoint | Width |
|
|
106
|
+
| Breakpoint | Width | Thay đổi layout |
|
|
107
107
|
|------------|------------|---------------------------------------------|
|
|
108
|
-
| Mobile | < 768px | {
|
|
109
|
-
| Tablet | 768–1279px | {2
|
|
110
|
-
| Desktop | ≥ 1280px | {
|
|
108
|
+
| Mobile | < 768px | {1 cột, bottom nav, CTA full-width} |
|
|
109
|
+
| Tablet | 768–1279px | {grid 2 cột, sidebar thu gọn} |
|
|
110
|
+
| Desktop | ≥ 1280px | {layout đầy đủ, max-width 1440px} |
|
|
111
111
|
|
|
112
112
|
## B. Hover / Focus / Keyboard *(web)*
|
|
113
113
|
|
|
114
|
-
|
|
|
114
|
+
| Phần tử | Hover | Focus | Keyboard |
|
|
115
115
|
|----------------|-------------------------------|---------------------------------|---------------|
|
|
116
116
|
| Primary button | Background → {color.hover} | Outline 2px {color.focus} | Enter / Space |
|
|
117
117
|
| Text input | Border → {color.border.hover} | Border → {color.primary} | Tab to focus |
|
|
118
118
|
|
|
119
|
-
<!-- === APP
|
|
119
|
+
<!-- === CHỈ APP — xóa section A+B cho app === -->
|
|
120
120
|
|
|
121
|
-
## C.
|
|
121
|
+
## C. Cử chỉ & Điều hướng *(app)*
|
|
122
122
|
|
|
123
|
-
|
|
|
123
|
+
| Cử chỉ | Màn / Phần tử | Hành vi |
|
|
124
124
|
|----------------------|---------------------|---------------------------------------------|
|
|
125
|
-
|
|
|
126
|
-
| Pull-to-refresh | {
|
|
127
|
-
| Swipe
|
|
125
|
+
| Cử chỉ back | Mọi màn | {Quay lại / hiện dialog "Discard changes?"} |
|
|
126
|
+
| Pull-to-refresh | {Tên màn} | Refresh dữ liệu, spinner ở trên cùng |
|
|
127
|
+
| Swipe trái trên row | {List item} | Hiện action {Delete / Archive} |
|
|
128
128
|
|
|
129
129
|
### Navigation Stack *(app)*
|
|
130
130
|
|
|
131
131
|
```
|
|
132
|
-
{
|
|
132
|
+
{vd: BottomTab(Home) → ListPage → DetailPage → EditPage}
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
### Platform Conventions *(app)*
|
|
136
136
|
|
|
137
|
-
|
|
|
137
|
+
| Khía cạnh | iOS | Android |
|
|
138
138
|
|------------------|-------------------------------------------|-------------------------------------|
|
|
139
|
-
| Navigation bar |
|
|
140
|
-
| Bottom sheet | UISheetPresentation, grabber
|
|
141
|
-
| Dialog |
|
|
139
|
+
| Navigation bar | Nút back trên-trái, title canh giữa | Mũi tên Up, title canh trái |
|
|
140
|
+
| Bottom sheet | UISheetPresentation, hiện grabber | BottomSheet, drag handle |
|
|
141
|
+
| Dialog | Action canh phải | Action canh trái |
|
|
142
142
|
|
|
143
143
|
---
|
|
144
144
|
|
|
145
|
-
# 4. Platform Considerations
|
|
145
|
+
# 4. Cân nhắc theo Platform (Platform Considerations)
|
|
146
146
|
|
|
147
|
-
<!-- === WEB
|
|
147
|
+
<!-- === CHỈ WEB === -->
|
|
148
148
|
|
|
149
149
|
## A. Accessibility *(web)*
|
|
150
150
|
|
|
151
|
-
- [ ]
|
|
152
|
-
- [ ] Focus trap
|
|
153
|
-
- [ ]
|
|
154
|
-
- [ ]
|
|
155
|
-
- [ ] WCAG AA
|
|
156
|
-
- [ ]
|
|
151
|
+
- [ ] Mọi phần tử tương tác đều tới được bằng phím Tab — không có keyboard trap
|
|
152
|
+
- [ ] Focus trap bên trong modal
|
|
153
|
+
- [ ] Nút chỉ có icon phải có `aria-label`
|
|
154
|
+
- [ ] Nội dung động thông báo qua `aria-live`
|
|
155
|
+
- [ ] Tương phản WCAG AA: text ≥ 4.5:1, text lớn ≥ 3:1
|
|
156
|
+
- [ ] Input form có label hiển thị (không chỉ dùng placeholder)
|
|
157
157
|
|
|
158
|
-
<!-- === APP
|
|
158
|
+
<!-- === CHỈ APP === -->
|
|
159
159
|
|
|
160
|
-
## B.
|
|
160
|
+
## B. Thiết bị & OS *(app)*
|
|
161
161
|
|
|
162
|
-
- [ ]
|
|
163
|
-
- [ ]
|
|
164
|
-
- [ ]
|
|
165
|
-
- [ ] Deep link: `{scheme}://{host}/{path}` → {
|
|
166
|
-
- [ ]
|
|
167
|
-
- [ ] Offline: {
|
|
168
|
-
- [ ]
|
|
162
|
+
- [ ] Áp dụng safe area insets (trên + dưới) ở mọi màn
|
|
163
|
+
- [ ] Touch target tối thiểu: 44×44pt (iOS) / 48×48dp (Android)
|
|
164
|
+
- [ ] Đã test trên 375pt (iPhone SE) và 360dp (Android nhỏ)
|
|
165
|
+
- [ ] Deep link: `{scheme}://{host}/{path}` → {tên màn}
|
|
166
|
+
- [ ] Permission: {Camera / Location / Notification} — nội dung lý do TBD
|
|
167
|
+
- [ ] Offline: {tên màn} hiện dữ liệu cache + banner; {action} bị disable kèm tooltip
|
|
168
|
+
- [ ] Đã test dark mode — không có màu hardcode
|
|
169
169
|
|
|
170
170
|
---
|
|
171
171
|
|
|
172
|
-
# 5. AC-UI —
|
|
172
|
+
# 5. AC-UI — Tiêu chí chấp nhận về Design
|
|
173
173
|
|
|
174
|
-
>
|
|
175
|
-
>
|
|
174
|
+
> Được **PO + Designer** review và sign off trước khi sinh BDD.
|
|
175
|
+
> Bổ sung cho AC mức nghiệp vụ trong [Business PRD](./{TICKET-ID}-slug.md).
|
|
176
176
|
|
|
177
|
-
| ID |
|
|
177
|
+
| ID | Tiêu chí chấp nhận | Verified by |
|
|
178
178
|
|--------|--------------------------------------------------------------------------|-----------------|
|
|
179
|
-
| AC-UI1 |
|
|
180
|
-
| AC-UI2 |
|
|
181
|
-
| AC-UI3 |
|
|
182
|
-
| AC-UI4 | Empty
|
|
183
|
-
| AC-UI5 | {
|
|
179
|
+
| AC-UI1 | Mọi màn khớp với frame Figma đã duyệt trong dung sai design-system | Designer |
|
|
180
|
+
| AC-UI2 | Trạng thái loading xuất hiện trong vòng 200ms kể từ khi gọi API | QA |
|
|
181
|
+
| AC-UI3 | Mọi thông báo lỗi đều hiển thị, rõ ràng, và kèm CTA khôi phục | PO |
|
|
182
|
+
| AC-UI4 | Empty state có illustration và call-to-action | PO + Designer |
|
|
183
|
+
| AC-UI5 | {Tiêu chí riêng theo platform} | QA |
|
|
184
184
|
|
|
185
185
|
---
|
|
186
186
|
|
|
187
187
|
# Appendix
|
|
188
188
|
|
|
189
|
-
## Figma
|
|
189
|
+
## Tóm tắt Figma
|
|
190
190
|
|
|
191
|
-
|
|
|
191
|
+
| Màn hình | Figma Frame (node-level) | Trạng thái Link / Fetch |
|
|
192
192
|
|------------|--------------------------|--------------------------------|
|
|
193
|
-
| {
|
|
194
|
-
| {
|
|
193
|
+
| {Màn hình 1} | [Link]({node-level url}) | ✅ Đã link & fetch |
|
|
194
|
+
| {Màn hình 2} | — | ❌ Missing — không có link node-id |
|
|
195
195
|
|
|
196
|
-
## Design
|
|
196
|
+
## Design Token đã tham chiếu
|
|
197
197
|
|
|
198
|
-
| Token | Value |
|
|
198
|
+
| Token | Value | Dùng ở |
|
|
199
199
|
|-------------------|----------|----------------------------|
|
|
200
|
-
| `color.primary` | {#hex} |
|
|
201
|
-
| `spacing.md` | {16px} |
|
|
200
|
+
| `color.primary` | {#hex} | Button, link |
|
|
201
|
+
| `spacing.md` | {16px} | Khoảng cách dọc tiêu chuẩn |
|
|
202
202
|
|
|
203
|
-
##
|
|
203
|
+
## Tài liệu tham khảo
|
|
204
204
|
|
|
205
205
|
- [{TICKET-ID}](./{TICKET-ID}-slug.md) — Business PRD
|
|
206
206
|
|
|
207
|
-
## AI
|
|
207
|
+
## Giả định AI
|
|
208
208
|
|
|
209
|
-
- {
|
|
209
|
+
- {Giả định — [AI DRAFT]}
|
|
210
210
|
|
|
211
211
|
---
|
|
212
212
|
|