spec-lite 1.1.5 → 1.1.6
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/cli.js +4 -0
- package/package.json +1 -1
- package/skills/ado-config/SKILL.md +349 -0
- package/skills/ado-create/SKILL.md +319 -0
- package/skills/ado-update/SKILL.md +295 -0
- package/skills/spec-new/SKILL.md +10 -1
package/bin/cli.js
CHANGED
|
@@ -17,6 +17,10 @@ if (command === 'install') {
|
|
|
17
17
|
cpSync(join(pkgRoot, 'skills'), join(claudeDir, 'skills'), { recursive: true })
|
|
18
18
|
console.log('✓ skills → .claude/skills/')
|
|
19
19
|
|
|
20
|
+
// Copy skills-overview.md → .claude/skills/skills-overview.md
|
|
21
|
+
cpSync(join(pkgRoot, 'skills-overview.md'), join(claudeDir, 'skills', 'skills-overview.md'))
|
|
22
|
+
console.log('✓ skills-overview.md → .claude/skills/skills-overview.md')
|
|
23
|
+
|
|
20
24
|
// Copy templates → .claude/templates/
|
|
21
25
|
cpSync(join(pkgRoot, 'templates'), join(claudeDir, 'templates'), { recursive: true })
|
|
22
26
|
console.log('✓ templates → .claude/templates/')
|
package/package.json
CHANGED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ado-config
|
|
3
|
+
description: Tạo hoặc cập nhật .claude/ado.yaml — lưu thông tin Azure DevOps project (org, project, team members, epic ticket). Dùng khi bắt đầu làm việc với một ADO project hoặc khi cần cập nhật thông tin team.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ado-config
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Tạo hoặc cập nhật `.claude/ado.yaml` — file config ADO project dùng chung cho tất cả các skill `/ado-*`.
|
|
11
|
+
|
|
12
|
+
## When to Use
|
|
13
|
+
|
|
14
|
+
- Lần đầu setup ADO cho project
|
|
15
|
+
- Cần cập nhật thông tin project, thành viên team, hoặc Epic ticket
|
|
16
|
+
|
|
17
|
+
## When NOT to Use
|
|
18
|
+
|
|
19
|
+
- Đã có `.claude/ado.yaml` và không cần thay đổi gì → dùng trực tiếp các skill `/ado-*` khác
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Process
|
|
24
|
+
|
|
25
|
+
### Bước 1: Kiểm tra file hiện tại
|
|
26
|
+
|
|
27
|
+
Kiểm tra xem `.claude/ado.yaml` đã tồn tại chưa.
|
|
28
|
+
|
|
29
|
+
**Nếu chưa tồn tại** → tiến hành collect toàn bộ từ Bước 2.
|
|
30
|
+
|
|
31
|
+
**Nếu đã tồn tại** → đọc file, hiển thị tóm tắt nội dung hiện tại:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
.claude/ado.yaml đã tồn tại:
|
|
35
|
+
|
|
36
|
+
organization: torus-engineering
|
|
37
|
+
project_name: Galaxy GCC (project_code: GAL-GCC)
|
|
38
|
+
team: PE: 1 người | SE: 2 người | DE: 1 người
|
|
39
|
+
epic: [42] [GAL-GCC] Spec Lite Kit
|
|
40
|
+
https://dev.azure.com/torus-engineering/Galaxy GCC/_workitems/edit/42
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Sau đó **bắt buộc** gọi `AskUserQuestion`:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
question: "Bạn muốn cập nhật phần nào?"
|
|
47
|
+
options:
|
|
48
|
+
- label: "Toàn bộ từ đầu"
|
|
49
|
+
description: "Chạy lại tất cả các bước — project, team, epic, environments"
|
|
50
|
+
- label: "Thông tin project"
|
|
51
|
+
description: "Cập nhật organization, project, project_id, project_code"
|
|
52
|
+
- label: "Team members"
|
|
53
|
+
description: "Cập nhật danh sách PE / SE / DE"
|
|
54
|
+
- label: "Epic ticket"
|
|
55
|
+
description: "Tạo mới hoặc thay Epic ticket đang được lưu"
|
|
56
|
+
- label: "Môi trường"
|
|
57
|
+
description: "Cập nhật danh sách environments (dev / stag / prod)"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Tuỳ theo lựa chọn:
|
|
61
|
+
- **"Toàn bộ từ đầu"** → chạy Bước 2 → 3 → 4 → 5 → 6 → 7
|
|
62
|
+
- **"Thông tin project"** → chỉ chạy Bước 2, bỏ qua Bước 3, 4, 5, nhảy thẳng đến Bước 6 → 7 (giữ nguyên `team`, `epic`, `environments` từ file cũ)
|
|
63
|
+
- **"Team members"** → chỉ chạy Bước 3, bỏ qua Bước 2, 4, 5, nhảy thẳng đến Bước 6 → 7 (giữ nguyên `organization/project`, `epic`, `environments` từ file cũ)
|
|
64
|
+
- **"Epic ticket"** → chỉ chạy Bước 4, bỏ qua Bước 2, 3, 5, nhảy thẳng đến Bước 6 → 7 (giữ nguyên `organization/project`, `team`, `environments` từ file cũ)
|
|
65
|
+
- **"Môi trường"** → chỉ chạy Bước 5, bỏ qua Bước 2, 3, 4, nhảy thẳng đến Bước 6 → 7 (giữ nguyên tất cả từ file cũ)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Bước 2: Connect ADO và chọn project
|
|
70
|
+
|
|
71
|
+
**Organization:**
|
|
72
|
+
|
|
73
|
+
**Bắt buộc** gọi tool `AskUserQuestion` — không hỏi bằng plain text. Cấu hình:
|
|
74
|
+
- question: `"Azure DevOps organization name?"`
|
|
75
|
+
- options:
|
|
76
|
+
- label `torus-engineering`, description `Org mặc định — nhấn Enter để chọn`
|
|
77
|
+
- label `ats-technology`
|
|
78
|
+
- System tự thêm option "Type something" cho phép nhập tên org khác hoặc paste full URL
|
|
79
|
+
|
|
80
|
+
Kết quả:
|
|
81
|
+
- User nhấn Enter → chọn `torus-engineering`
|
|
82
|
+
- User dùng ↓ → chọn "Type something" → nhập tên org hoặc paste URL
|
|
83
|
+
|
|
84
|
+
Nếu user nhập full URL (ví dụ `https://dev.azure.com/my-org/...`) → tự extract phần org sau `dev.azure.com/`, bỏ mọi path phía sau.
|
|
85
|
+
|
|
86
|
+
**List projects qua MCP:**
|
|
87
|
+
|
|
88
|
+
Sau khi có organization, gọi MCP tool `mcp__azure-devops__core_list_projects` để lấy danh sách projects trong org đó.
|
|
89
|
+
|
|
90
|
+
Hiển thị numbered list và chờ user nhập số:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
Các project trong org "torus-engineering":
|
|
94
|
+
|
|
95
|
+
1. T-Lead (ID: f95c3b00-b3a8-4405-b062-8471a57cabd6)
|
|
96
|
+
2. C-Blok (ID: 5d57bc02-c656-4be7-981f-4ee5ecf4ba0a)
|
|
97
|
+
3. C-GAL (ID: be587215-de0a-4ea2-952a-d5b635b5d748)
|
|
98
|
+
4. C-GTEL (ID: 06e852f7-83f5-48b6-a83f-81bd665e0187)
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
Nhập số thứ tự project:
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Sau khi user nhập số → tự điền `project_name` và `project_id` từ kết quả MCP. Không hỏi user nhập tay.
|
|
105
|
+
|
|
106
|
+
Nếu MCP call thất bại → thông báo lỗi rõ ràng và hỏi user nhập `project_name` và `project_id` thủ công.
|
|
107
|
+
|
|
108
|
+
**Project Code:**
|
|
109
|
+
> Project code là gì? Đây sẽ là prefix cho mọi ticket trong project.
|
|
110
|
+
> (Ví dụ: `GAL-GCC`, `TORUS-BE`, `VNG-APP` — thường là 2–3 từ viết tắt, ngăn cách bởi dấu gạch ngang)
|
|
111
|
+
|
|
112
|
+
Gợi ý: đề xuất project code dựa trên tên project đã chọn (ví dụ "Galaxy GCC" → `GAL-GCC`). User có thể chấp nhận hoặc nhập lại.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### Bước 3: Nhập team members
|
|
117
|
+
|
|
118
|
+
Hỏi lần lượt từng role. Với mỗi role, nhập email hợp lệ, mỗi người một dòng, Enter trống khi xong:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
PE (Product Engineer) [bắt buộc]:
|
|
122
|
+
> anh.le@atstechnology.vn
|
|
123
|
+
> minh.ngo@atstechnology.vn
|
|
124
|
+
>
|
|
125
|
+
|
|
126
|
+
SE (Software Engineer):
|
|
127
|
+
> b@atstechnology.vn
|
|
128
|
+
>
|
|
129
|
+
|
|
130
|
+
DE (Data Engineer):
|
|
131
|
+
>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Một người có thể đóng nhiều role — nhập lại ở role tương ứng.
|
|
135
|
+
|
|
136
|
+
**PE là bắt buộc** — nếu user để trống, nhắc lại và yêu cầu nhập ít nhất 1 email hợp lệ trước khi tiếp tục.
|
|
137
|
+
|
|
138
|
+
SE và DE không có ai → để trống (ghi array rỗng `[]`).
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### Bước 4: Cấu hình Epic Ticket
|
|
143
|
+
|
|
144
|
+
Epic Ticket là ticket đại diện cho toàn bộ project/product đang được code. Mọi Feature/Story sẽ được link vào Epic này.
|
|
145
|
+
|
|
146
|
+
Hỏi user bằng `AskUserQuestion`:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
question: "Epic Ticket cho project {project_name} ({project_code})?"
|
|
150
|
+
options:
|
|
151
|
+
- label: "Tạo Epic mới"
|
|
152
|
+
description: "Nhập title và mô tả — Claude sẽ tạo Epic trên ADO với prefix [{project_code}]"
|
|
153
|
+
- label: "Nhập ID ticket có sẵn"
|
|
154
|
+
description: "Nhập ID của Epic đã tồn tại trên ADO để validate và lưu vào config"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
#### Option A: Tạo Epic mới
|
|
160
|
+
|
|
161
|
+
**1. Nhập title:**
|
|
162
|
+
> Epic title? (sẽ được prefix thành `[{project_code}] <title>`)
|
|
163
|
+
|
|
164
|
+
Ví dụ user nhập `Spec Lite Kit` → title cuối là `[SDLC-TEST] Spec Lite Kit`.
|
|
165
|
+
|
|
166
|
+
**2. Nhập mô tả:**
|
|
167
|
+
|
|
168
|
+
Hỏi bằng `AskUserQuestion`:
|
|
169
|
+
```
|
|
170
|
+
question: "Mô tả Epic?"
|
|
171
|
+
options:
|
|
172
|
+
- label: "Tự nhập mô tả"
|
|
173
|
+
description: "Nhập nội dung mô tả thủ công"
|
|
174
|
+
- label: "Dùng nội dung từ spec artifact"
|
|
175
|
+
description: "Chỉ định đường dẫn file spec.md / prd.md — Claude sẽ đọc và dùng làm mô tả"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Nếu user chọn **"Dùng nội dung từ spec artifact"**:
|
|
179
|
+
- Hỏi đường dẫn file (ví dụ `specs/integrations/001-implement-auth/spec.md`)
|
|
180
|
+
- Đọc file → dùng toàn bộ nội dung làm description của Epic (format Markdown)
|
|
181
|
+
|
|
182
|
+
Nếu user chọn **"Tự nhập mô tả"**:
|
|
183
|
+
- Hỏi plain text mô tả, có thể để trống
|
|
184
|
+
|
|
185
|
+
**3. Tạo Epic qua MCP:**
|
|
186
|
+
|
|
187
|
+
Trước khi tạo, resolve email của PE đầu tiên thành ADO identity ID bằng `mcp__azure-devops__core_get_identity_ids` (dùng email từ `team.PE[0]`).
|
|
188
|
+
|
|
189
|
+
Gọi `mcp__azure-devops__wit_create_work_item` với:
|
|
190
|
+
- `type`: `Epic`
|
|
191
|
+
- `title`: `[{project_code}] <user_title>`
|
|
192
|
+
- `description`: nội dung đã nhập/đọc
|
|
193
|
+
- `assignedTo`: identity ID của PE đầu tiên trong danh sách
|
|
194
|
+
|
|
195
|
+
Sau khi tạo thành công → lưu `id`, `title`, và `url` vào config. URL được tạo theo format:
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
https://dev.azure.com/{organization}/{project_name}/_workitems/edit/{id}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Nếu resolve identity thất bại → tạo Epic không có assignee, thông báo để user tự assign thủ công trên ADO.
|
|
202
|
+
|
|
203
|
+
Nếu MCP call tạo Epic thất bại → thông báo lỗi và cho phép retry hoặc bỏ qua bước này.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
#### Option B: Nhập ID ticket có sẵn
|
|
208
|
+
|
|
209
|
+
Hỏi user:
|
|
210
|
+
> Nhập ID của Epic ticket (chỉ số, ví dụ: `42`):
|
|
211
|
+
|
|
212
|
+
Sau khi user nhập → **bắt buộc validate qua MCP** bằng `mcp__azure-devops__wit_get_work_item`:
|
|
213
|
+
|
|
214
|
+
**Kiểm tra các điều kiện sau:**
|
|
215
|
+
1. Work item tồn tại trong ADO project đã chọn
|
|
216
|
+
2. `workItemType` phải là `Epic`
|
|
217
|
+
3. Title phải có prefix `[{project_code}]` — nếu không có thì cảnh báo nhưng vẫn cho phép user xác nhận tiếp tục
|
|
218
|
+
|
|
219
|
+
Nếu validation fail (không tồn tại hoặc không phải Epic) → thông báo lỗi cụ thể và cho phép nhập lại.
|
|
220
|
+
|
|
221
|
+
Nếu validation thành công → hiển thị thông tin ticket để user xác nhận:
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
Tìm thấy Epic:
|
|
225
|
+
ID: 42
|
|
226
|
+
Title: [SDLC-TEST] Spec Lite Kit
|
|
227
|
+
State: New
|
|
228
|
+
URL: https://dev.azure.com/torus-engineering/Common/_workitems/edit/42
|
|
229
|
+
|
|
230
|
+
Dùng Epic này? (yes/no)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Sau khi user confirm → lưu `id`, `title`, và `url` vào config. URL được tạo theo format:
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
https://dev.azure.com/{organization}/{project_name}/_workitems/edit/{id}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### Bước 5: Cấu hình môi trường
|
|
242
|
+
|
|
243
|
+
**Bắt buộc** hỏi user bằng `AskUserQuestion` — không cho phép bỏ qua:
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
question: "Project này có bao nhiêu môi trường deploy?"
|
|
247
|
+
options:
|
|
248
|
+
- label: "Production only"
|
|
249
|
+
description: "1 môi trường: prod"
|
|
250
|
+
- label: "Development + Production"
|
|
251
|
+
description: "2 môi trường: dev + prod"
|
|
252
|
+
- label: "Development + Staging + Production"
|
|
253
|
+
description: "3 môi trường: dev + stag + prod"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Lưu kết quả dưới dạng array theo thứ tự từ thấp đến cao:
|
|
257
|
+
|
|
258
|
+
| Lựa chọn | Giá trị lưu |
|
|
259
|
+
|---|---|
|
|
260
|
+
| Production only | `["prod"]` |
|
|
261
|
+
| Development + Production | `["dev", "prod"]` |
|
|
262
|
+
| Development + Staging + Production | `["dev", "stag", "prod"]` |
|
|
263
|
+
|
|
264
|
+
Nếu user chọn "Other" (nhập tay) → parse chuỗi nhập vào (phân cách bởi dấu phẩy, space, hoặc `+`) → normalize thành lowercase array. Ví dụ: `"dev, staging, prod"` → `["dev", "staging", "prod"]`.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### Bước 6: Preview và xác nhận
|
|
269
|
+
|
|
270
|
+
Hiển thị preview YAML sẽ được ghi — **chưa ghi file**:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
Sẽ ghi vào .claude/ado.yaml:
|
|
274
|
+
|
|
275
|
+
organization: torus-engineering
|
|
276
|
+
project_name: Galaxy GCC
|
|
277
|
+
project_code: GAL-GCC
|
|
278
|
+
project_id: "2074c422-31ea-4b9c-9b61-fe0f749fa28d"
|
|
279
|
+
|
|
280
|
+
team:
|
|
281
|
+
PE:
|
|
282
|
+
- anh.le@atstechnology.vn
|
|
283
|
+
- minh.ngo@atstechnology.vn
|
|
284
|
+
SE:
|
|
285
|
+
- b@atstechnology.vn
|
|
286
|
+
- c@atstechnology.vn
|
|
287
|
+
DE:
|
|
288
|
+
- d@atstechnology.vn
|
|
289
|
+
|
|
290
|
+
epic:
|
|
291
|
+
id: 42
|
|
292
|
+
title: "[GAL-GCC] Spec Lite Kit"
|
|
293
|
+
url: "https://dev.azure.com/torus-engineering/Galaxy GCC/_workitems/edit/42"
|
|
294
|
+
|
|
295
|
+
environments:
|
|
296
|
+
- dev
|
|
297
|
+
- stag
|
|
298
|
+
- prod
|
|
299
|
+
|
|
300
|
+
Xác nhận ghi file? (yes/no)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Nếu user yêu cầu chỉnh sửa → cập nhật preview → hỏi lại.
|
|
304
|
+
|
|
305
|
+
Nếu user bỏ qua bước Epic (không muốn cấu hình ngay) → bỏ qua key `epic` trong YAML, không ghi `epic: null`.
|
|
306
|
+
|
|
307
|
+
**Bước 5 (môi trường) là bắt buộc** — không cho phép bỏ qua. Nếu user chưa chọn, nhắc lại trước khi tiếp tục.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### Bước 7: Ghi file
|
|
312
|
+
|
|
313
|
+
Ghi nội dung đã confirm vào `.claude/ado.yaml`.
|
|
314
|
+
|
|
315
|
+
**Kiểm tra .gitignore:**
|
|
316
|
+
|
|
317
|
+
Đọc `.gitignore` ở root project (nếu tồn tại). Nếu có pattern nào match `.claude/ado.yaml` hoặc `.claude/` → **xóa hoặc thêm exception** để đảm bảo file được track bởi git:
|
|
318
|
+
|
|
319
|
+
- Nếu `.gitignore` có dòng `.claude/` → thêm dòng `!.claude/ado.yaml` ngay bên dưới
|
|
320
|
+
- Nếu `.gitignore` có dòng `.claude/ado.yaml` → xóa dòng đó
|
|
321
|
+
|
|
322
|
+
Thông báo kết quả:
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
✓ .claude/ado.yaml đã được tạo/cập nhật
|
|
326
|
+
|
|
327
|
+
{nếu có thay đổi .gitignore}
|
|
328
|
+
✓ .gitignore — đã đảm bảo .claude/ado.yaml được track bởi git
|
|
329
|
+
|
|
330
|
+
Bước tiếp theo:
|
|
331
|
+
- Commit .claude/ado.yaml để share config với team
|
|
332
|
+
- /ado-init → khởi tạo ADO project (tạo boards, iteration, areas...)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Verification
|
|
338
|
+
|
|
339
|
+
Trước khi ghi file, kiểm tra:
|
|
340
|
+
|
|
341
|
+
- [ ] `organization` đã được extract — chỉ là tên org, không phải full URL
|
|
342
|
+
- [ ] `project_name` đã được lưu từ kết quả MCP (tên project gốc từ ADO)
|
|
343
|
+
- [ ] `project_id` có dạng GUID (format: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`)
|
|
344
|
+
- [ ] Mỗi email hợp lệ (có dấu `@`)
|
|
345
|
+
- [ ] `team.PE` có ít nhất 1 email — không được để trống
|
|
346
|
+
- [ ] SE và DE có thể là array rỗng `[]`
|
|
347
|
+
- [ ] Nếu có Epic: `epic.id` là số nguyên, `epic.title` có prefix `[{project_code}]`, `epic.url` là full URL dạng `https://dev.azure.com/{org}/{project_name}/_workitems/edit/{id}`
|
|
348
|
+
- [ ] `environments` là array ít nhất 1 phần tử (bắt buộc), mỗi phần tử là lowercase string không có khoảng trắng, luôn có `prod` ở cuối
|
|
349
|
+
- [ ] User đã confirm preview trước khi ghi file
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ado-create
|
|
3
|
+
description: Tạo Feature và User Story tickets trên ADO từ spec.md của một integration. Set parent là Epic từ ado.yaml, assign cho current user, cập nhật ticket references vào spec.md và frd.md tương ứng.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ado-create
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Đọc `spec.md` của một integration, tạo Feature và User Story tickets trên ADO, rồi ghi ticket ID/title/URL trở lại vào `spec.md` và `frd.md` tương ứng.
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
- `.claude/ado.yaml` phải tồn tại và có `epic.id` (chạy `/ado-config` nếu chưa có)
|
|
15
|
+
- `frd.md` tương ứng phải tồn tại trong `specs/main/features/` cho mỗi feature
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Process
|
|
20
|
+
|
|
21
|
+
### Bước 1: Load config và xác định current user
|
|
22
|
+
|
|
23
|
+
Đọc `.claude/ado.yaml`. Nếu không tồn tại → dừng và báo lỗi:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
Chưa có .claude/ado.yaml. Hãy chạy /ado-config trước.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Xác định current user:** Đọc `git config user.email`. Tìm email này trong toàn bộ `team.PE + team.SE + team.DE` của ado.yaml.
|
|
30
|
+
|
|
31
|
+
**Nếu tìm thấy** → dùng email đó làm assignee.
|
|
32
|
+
|
|
33
|
+
**Nếu không tìm thấy** → hỏi bằng `AskUserQuestion`:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
question: "Bạn là ai trong team? (dùng để assign ticket)"
|
|
37
|
+
options: [mỗi email trong team.PE + team.SE + team.DE thành 1 option]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Sau khi xác định email, resolve thành ADO identity ID bằng `mcp__azure-devops__core_get_identity_ids`.
|
|
41
|
+
|
|
42
|
+
Nếu resolve thất bại → tiếp tục nhưng không set assignee; thông báo để user tự assign trên ADO sau.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### Bước 2: Chọn integration
|
|
47
|
+
|
|
48
|
+
List tất cả thư mục trong `specs/integrations/` trừ `000-scaffold`. Với mỗi thư mục, đọc frontmatter của `spec.md` để lấy `title` và `status`.
|
|
49
|
+
|
|
50
|
+
Hỏi user bằng `AskUserQuestion`:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
question: "Chọn integration để tạo ADO tickets:"
|
|
54
|
+
options:
|
|
55
|
+
- label: "001-implement-auth — Implement Authentication"
|
|
56
|
+
description: "status: draft | features: F-001"
|
|
57
|
+
- label: "002-implement-todo — Implement Todo Management"
|
|
58
|
+
description: "status: draft | features: F-002, F-003"
|
|
59
|
+
- ...
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Sau khi user chọn → đọc toàn bộ `spec.md` của integration đó.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### Bước 3: Parse spec.md
|
|
67
|
+
|
|
68
|
+
Extract từ spec.md:
|
|
69
|
+
|
|
70
|
+
**Features:** Tìm các heading theo pattern `### Feature: <name> (<ID>)`.
|
|
71
|
+
Ví dụ: `### Feature: Đăng ký / Đăng nhập (F-001)` → `{id: "F-001", name: "Đăng ký / Đăng nhập"}`
|
|
72
|
+
|
|
73
|
+
**User Stories:** Tìm các heading theo pattern `#### US-FXXX-YYY — <title>`.
|
|
74
|
+
Ví dụ: `#### US-F001-001 — Đăng ký` → `{code: "US-F001-001", title: "Đăng ký", feature_id: "F-001"}`
|
|
75
|
+
|
|
76
|
+
Với mỗi User Story, thu thập thêm:
|
|
77
|
+
- Câu story: dòng `**<role>** muốn **<want>** để **<goal>**.`
|
|
78
|
+
- `Priority`
|
|
79
|
+
- Tất cả ACs bên dưới (từ `**Acceptance Criteria:**` đến heading tiếp theo)
|
|
80
|
+
|
|
81
|
+
**Kiểm tra đã có ADO ticket chưa:** Ngay sau heading của mỗi Feature / User Story, tìm dòng có format `**ADO:**`. Nếu có → đánh dấu `already_created: true`, lưu lại ID/URL hiện có.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### Bước 4: Preview và xác nhận
|
|
86
|
+
|
|
87
|
+
Hiển thị kế hoạch trước khi tạo — **chưa tạo gì**:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Integration: 001-implement-auth — Implement Authentication
|
|
91
|
+
Assignee: anh.le@torus.vn
|
|
92
|
+
|
|
93
|
+
Sẽ tạo các tickets sau:
|
|
94
|
+
|
|
95
|
+
Feature Tickets (parent: Epic #24241 — [SDLC-TEST] Spec Lite Kit):
|
|
96
|
+
✦ F-001 — Đăng ký / Đăng nhập [NEW]
|
|
97
|
+
|
|
98
|
+
User Story Tickets:
|
|
99
|
+
✦ US-F001-001 — Đăng ký [NEW] → parent: F-001
|
|
100
|
+
✦ US-F001-002 — Đăng nhập [NEW] → parent: F-001
|
|
101
|
+
✦ US-F001-003 — Đăng xuất [NEW] → parent: F-001
|
|
102
|
+
|
|
103
|
+
Skip (đã có ADO ticket):
|
|
104
|
+
✓ F-002 — ... #12345 (đã tạo trước)
|
|
105
|
+
|
|
106
|
+
Tiếp tục tạo? (yes/no)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Nếu user từ chối → dừng không tạo gì.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Bước 5: Tạo Feature Tickets
|
|
114
|
+
|
|
115
|
+
Thực hiện tuần tự với từng Feature chưa có ADO ticket:
|
|
116
|
+
|
|
117
|
+
**5.1 Tìm frd.md:**
|
|
118
|
+
|
|
119
|
+
Map `F-NNN` → tìm thư mục `specs/main/features/` bắt đầu bằng `NNN-`. Đọc `frd.md` trong thư mục đó.
|
|
120
|
+
|
|
121
|
+
Nếu không tìm thấy `frd.md` → cảnh báo, dùng phần mô tả Feature từ `spec.md` làm description thay thế.
|
|
122
|
+
|
|
123
|
+
**5.2 Tạo ticket:**
|
|
124
|
+
|
|
125
|
+
Gọi `mcp__azure-devops__wit_create_work_item` với:
|
|
126
|
+
- `type`: `Feature`
|
|
127
|
+
- `title`: `[{project_code}] [{feature_id}] {feature_name}` — ví dụ: `[SDLC-TEST] [F-001] Đăng ký / Đăng nhập`
|
|
128
|
+
- `description`: toàn bộ nội dung `frd.md` (giữ nguyên format Markdown)
|
|
129
|
+
- `assignedTo`: ADO identity ID của current user (nếu resolve thành công)
|
|
130
|
+
|
|
131
|
+
Sau khi tạo thành công → **ngay lập tức** link parent. Ưu tiên dùng `mcp__azure-devops__wit_add_child_work_items` (parent = Epic ID, child = Feature ticket ID). Nếu tool này không khả dụng, fallback sang `mcp__azure-devops__wit_work_items_link` với:
|
|
132
|
+
- `sourceId`: Feature ticket ID vừa tạo
|
|
133
|
+
- `targetId`: Epic ID từ ado.yaml
|
|
134
|
+
- `relationType`: `System.LinkTypes.Hierarchy-Reverse`
|
|
135
|
+
|
|
136
|
+
**Nếu link parent thất bại:**
|
|
137
|
+
1. Retry một lần
|
|
138
|
+
2. Nếu vẫn fail → đánh dấu Feature này là `orphan` (KHÔNG xóa ticket), ghi vào danh sách cần xử lý thủ công, tiếp tục với Feature tiếp theo. Ticket orphan sẽ được báo cáo nổi bật ở Bước 10.
|
|
139
|
+
|
|
140
|
+
Lưu lại `{id, title, url}`. URL format:
|
|
141
|
+
```
|
|
142
|
+
https://dev.azure.com/{organization}/{project_name}/_workitems/edit/{id}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Nếu tạo ticket thất bại → log lỗi, đánh dấu Feature này là `failed`, skip toàn bộ User Stories thuộc Feature đó, tiếp tục với Feature tiếp theo.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### Bước 6: Tạo User Story Tickets
|
|
150
|
+
|
|
151
|
+
Thực hiện tuần tự với từng User Story chưa có ADO ticket:
|
|
152
|
+
|
|
153
|
+
**6.1 Xác định parent Feature ticket ID:**
|
|
154
|
+
|
|
155
|
+
Lấy Feature ticket ID theo thứ tự ưu tiên:
|
|
156
|
+
1. Feature vừa tạo ở Bước 5 → dùng ID từ kết quả MCP
|
|
157
|
+
2. Feature đã `already_created` → parse ID từ dòng `**ADO:** [#<ID> — ...](url)` trong `spec.md`
|
|
158
|
+
|
|
159
|
+
Nếu Feature đó là `failed` → skip toàn bộ User Stories thuộc Feature đó, báo cáo ở Bước 10.
|
|
160
|
+
Nếu Feature là `orphan` (tạo thành công nhưng link Epic thất bại) → vẫn dùng Feature ID đó làm parent cho User Stories, nhưng đánh dấu chuỗi này cần review thủ công.
|
|
161
|
+
Nếu không đọc được Feature ticket ID từ bất kỳ nguồn nào → skip User Story này với cảnh báo.
|
|
162
|
+
|
|
163
|
+
**6.2 Build description:**
|
|
164
|
+
|
|
165
|
+
```markdown
|
|
166
|
+
**{role}** muốn **{want}** để **{goal}**.
|
|
167
|
+
|
|
168
|
+
**Priority:** {priority}
|
|
169
|
+
|
|
170
|
+
**Acceptance Criteria:**
|
|
171
|
+
|
|
172
|
+
- AC-code
|
|
173
|
+
- **Given** ...
|
|
174
|
+
- **When** ...
|
|
175
|
+
- **Then** ...
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**6.3 Tạo ticket:**
|
|
179
|
+
|
|
180
|
+
Gọi `mcp__azure-devops__wit_create_work_item` với:
|
|
181
|
+
- `type`: `User Story`
|
|
182
|
+
- `title`: `[{project_code}] [{feature_name}] - {US-code} — {story_title}` — ví dụ: `[SDLC-TEST] [Đăng ký / Đăng nhập] - US-F001-001 — Đăng ký`
|
|
183
|
+
- `description`: description đã build ở 6.2
|
|
184
|
+
- `assignedTo`: ADO identity ID của current user
|
|
185
|
+
|
|
186
|
+
Sau khi tạo thành công → **ngay lập tức** link parent. Ưu tiên dùng `mcp__azure-devops__wit_add_child_work_items` (parent = Feature ticket ID, child = User Story ticket ID). Nếu không khả dụng, fallback sang `mcp__azure-devops__wit_work_items_link` với:
|
|
187
|
+
- `sourceId`: User Story ticket ID vừa tạo
|
|
188
|
+
- `targetId`: Feature ticket ID
|
|
189
|
+
- `relationType`: `System.LinkTypes.Hierarchy-Reverse`
|
|
190
|
+
|
|
191
|
+
**Nếu link parent thất bại:**
|
|
192
|
+
1. Retry một lần
|
|
193
|
+
2. Nếu vẫn fail → đánh dấu User Story này là `orphan` (KHÔNG xóa ticket), ghi vào danh sách cần xử lý thủ công, tiếp tục với User Story tiếp theo.
|
|
194
|
+
|
|
195
|
+
Lưu lại `{id, title, url}`.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### Bước 7: Cập nhật spec.md
|
|
200
|
+
|
|
201
|
+
Sau khi tất cả tickets đã được tạo, cập nhật `spec.md`:
|
|
202
|
+
|
|
203
|
+
**Với Feature ticket thành công:** Thêm dòng `**ADO:**` ngay sau heading feature, trên dòng trống đầu tiên:
|
|
204
|
+
|
|
205
|
+
```markdown
|
|
206
|
+
### Feature: Đăng ký / Đăng nhập (F-001)
|
|
207
|
+
**ADO:** [#12345 — [SDLC-TEST] Đăng ký / Đăng nhập](https://dev.azure.com/...)
|
|
208
|
+
|
|
209
|
+
**Feature-level Acceptance Criteria:**
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Với User Story ticket thành công:** Thêm dòng `**ADO:**` ngay sau heading user story:
|
|
213
|
+
|
|
214
|
+
```markdown
|
|
215
|
+
#### US-F001-001 — Đăng ký
|
|
216
|
+
**ADO:** [#12346 — US-F001-001 — Đăng ký](https://dev.azure.com/...)
|
|
217
|
+
|
|
218
|
+
**Nhân viên mới** muốn ...
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Bước 8: Cập nhật prd.md
|
|
224
|
+
|
|
225
|
+
Mở `specs/main/prd.md`. Tìm bảng `## Features`.
|
|
226
|
+
|
|
227
|
+
**Nếu bảng chưa có cột `ADO`:** Thêm cột vào header và separator row:
|
|
228
|
+
|
|
229
|
+
```markdown
|
|
230
|
+
| ID | Feature | Mô tả | Priority | Status | ADO |
|
|
231
|
+
| --- | --- | --- | --- | --- | --- |
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Với mỗi Feature ticket vừa tạo thành công, tìm row tương ứng theo `ID` (ví dụ `F-001`) và thêm link vào cột `ADO`:
|
|
235
|
+
|
|
236
|
+
```markdown
|
|
237
|
+
| F-001 | Đăng ký / Đăng nhập | ... | Must | In Progress | [#12345](url) |
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Nếu cột `ADO` đã tồn tại và row đã có giá trị → **không ghi đè**, bỏ qua.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
### Bước 9: Cập nhật frd.md
|
|
245
|
+
|
|
246
|
+
Với mỗi `frd.md` thuộc integration này:
|
|
247
|
+
|
|
248
|
+
Tìm section `## ADO Tickets` trong file.
|
|
249
|
+
|
|
250
|
+
**Nếu chưa có:** Append vào cuối file:
|
|
251
|
+
|
|
252
|
+
```markdown
|
|
253
|
+
|
|
254
|
+
## ADO Tickets
|
|
255
|
+
|
|
256
|
+
| Type | Code | Ticket |
|
|
257
|
+
|------|------|--------|
|
|
258
|
+
| Feature | F-001 | [#12345 — [SDLC-TEST] Đăng ký / Đăng nhập](url) |
|
|
259
|
+
| User Story | US-F001-001 | [#12346 — US-F001-001 — Đăng ký](url) |
|
|
260
|
+
| User Story | US-F001-002 | [#12347 — US-F001-002 — Đăng nhập](url) |
|
|
261
|
+
| User Story | US-F001-003 | [#12348 — US-F001-003 — Đăng xuất](url) |
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Nếu đã có:** Append các row mới (tickets vừa tạo) vào cuối bảng. Không xóa row cũ.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### Bước 10: Tóm tắt kết quả
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
✓ ADO tickets đã tạo — integration: 001-implement-auth
|
|
272
|
+
|
|
273
|
+
Feature Tickets:
|
|
274
|
+
✓ #12345 — [SDLC-TEST] [F-001] Đăng ký / Đăng nhập
|
|
275
|
+
https://dev.azure.com/torus-engineering/Common/_workitems/edit/12345
|
|
276
|
+
|
|
277
|
+
User Story Tickets:
|
|
278
|
+
✓ #12346 — [SDLC-TEST] [Đăng ký / Đăng nhập] - US-F001-001 — Đăng ký → F-001 #12345
|
|
279
|
+
✓ #12347 — [SDLC-TEST] [Đăng ký / Đăng nhập] - US-F001-002 — Đăng nhập → F-001 #12345
|
|
280
|
+
✓ #12348 — [SDLC-TEST] [Đăng ký / Đăng nhập] - US-F001-003 — Đăng xuất → F-001 #12345
|
|
281
|
+
|
|
282
|
+
Files đã cập nhật:
|
|
283
|
+
✓ specs/integrations/001-implement-auth/spec.md
|
|
284
|
+
✓ specs/main/features/001-auth/frd.md
|
|
285
|
+
✓ specs/main/prd.md
|
|
286
|
+
|
|
287
|
+
{nếu có lỗi tạo ticket}
|
|
288
|
+
✗ US-F001-004 — ... → tạo thất bại: <lý do>
|
|
289
|
+
|
|
290
|
+
{nếu có orphan — cần xử lý thủ công NGAY}
|
|
291
|
+
⚠ ORPHAN — ticket tồn tại nhưng CHƯA có parent:
|
|
292
|
+
#12349 — US-F001-005 — ...
|
|
293
|
+
→ Cần link thủ công: parent = Feature #12345
|
|
294
|
+
→ https://dev.azure.com/torus-engineering/Common/_workitems/edit/12349
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Verification Checklist
|
|
300
|
+
|
|
301
|
+
Trước khi tạo ticket:
|
|
302
|
+
- [ ] `.claude/ado.yaml` tồn tại và `epic.id` là số nguyên hợp lệ
|
|
303
|
+
- [ ] Integration được chọn có `spec.md` chứa ít nhất 1 Feature
|
|
304
|
+
- [ ] `frd.md` tìm được cho mỗi Feature (cảnh báo nếu thiếu, không dừng)
|
|
305
|
+
|
|
306
|
+
Khi tạo ticket:
|
|
307
|
+
- [ ] Feature type là `Feature` — không phải `Epic` hay `User Story`
|
|
308
|
+
- [ ] User Story type là `User Story`
|
|
309
|
+
- [ ] Parent link được thực hiện **ngay sau khi tạo ticket** — không để cuối batch
|
|
310
|
+
- [ ] Nếu parent link fail: retry 1 lần, nếu vẫn fail → đánh dấu `orphan`, báo cáo ở Bước 10, KHÔNG im lặng bỏ qua
|
|
311
|
+
- [ ] `already_created` Feature: lấy ticket ID từ `**ADO:**` trong spec.md để dùng làm parent cho User Stories
|
|
312
|
+
- [ ] Title Feature theo format `[{project_code}] [{feature_id}] {feature_name}`
|
|
313
|
+
- [ ] Title User Story theo format `[{project_code}] [{feature_name}] - {US-code} — {story_title}`
|
|
314
|
+
|
|
315
|
+
Khi cập nhật file:
|
|
316
|
+
- [ ] `**ADO:**` được thêm vào đúng vị trí trong `spec.md` (ngay sau heading, trước nội dung)
|
|
317
|
+
- [ ] Chỉ ghi khi ticket tạo **thành công** — không ghi nếu failed
|
|
318
|
+
- [ ] `frd.md` section `## ADO Tickets` không duplicate row đã tồn tại
|
|
319
|
+
- [ ] `prd.md` cột `ADO` chỉ thêm vào feature row tương ứng — không ghi đè nếu đã có giá trị
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ado-update
|
|
3
|
+
description: Cập nhật trạng thái (state) cho tất cả User Story và Feature tickets trên ADO theo tiến trình deploy/verify qua từng môi trường được cấu hình trong ado.yaml.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ado-update
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Đọc `spec.md` của một integration, kiểm tra ADO tickets đã tồn tại chưa, sau đó cho phép user chọn trạng thái mới để cập nhật đồng loạt toàn bộ User Story tickets — và tuỳ chọn cả Feature tickets.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
- `.claude/ado.yaml` phải tồn tại và có `environments` (chạy `/ado-config` nếu chưa có)
|
|
17
|
+
- Tất cả Feature và User Story trong integration phải đã có ADO ticket (chạy `/ado-create` nếu chưa có)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## State Source
|
|
22
|
+
|
|
23
|
+
State names **không được generate từ `environments`** — chúng được lấy trực tiếp từ ADO bằng `mcp__azure-devops__wit_get_work_item_type`. Mỗi project có thể đặt tên state khác nhau (ví dụ: `dev` có thể là `Deploy Test` thay vì `Deploy Dev`).
|
|
24
|
+
|
|
25
|
+
- **User Story states**: fetch từ ADO work item type `User Story`
|
|
26
|
+
- **Feature states**: fetch từ ADO work item type `Feature`
|
|
27
|
+
|
|
28
|
+
State list hiển thị cho user là danh sách `states` thực tế từ ADO response, **đã qua bước filter theo environments được cấu hình**.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Environment-State Filtering
|
|
33
|
+
|
|
34
|
+
ADO thường định nghĩa state cho mọi environment có thể có (dev, stag, prod). Sau khi fetch, **filter bớt các state không tương ứng với environments trong `.claude/ado.yaml`** trước khi hiển thị cho user.
|
|
35
|
+
|
|
36
|
+
### Quy tắc filter
|
|
37
|
+
|
|
38
|
+
**Bước 1 — Tách state thành 2 nhóm:**
|
|
39
|
+
|
|
40
|
+
- **Nhóm environment-specific**: state khớp pattern `Deploy *` hoặc `Verify *` (ví dụ: Deploy Test, Verify Test, Deploy Stag, Verify Stag, Deploy Prod, Verify Prod)
|
|
41
|
+
- **Nhóm general**: tất cả state còn lại (New, Pending, In Progress, Done, Removed, v.v.) — giữ nguyên, không filter
|
|
42
|
+
|
|
43
|
+
**Bước 2 — Group environment-specific states thành pairs:**
|
|
44
|
+
|
|
45
|
+
Sắp xếp theo thứ tự xuất hiện trong ADO response, group thành cặp `(Deploy X, Verify X)` theo thứ tự:
|
|
46
|
+
- Pair 0 → tương ứng `environments[0]`
|
|
47
|
+
- Pair 1 → tương ứng `environments[1]`
|
|
48
|
+
- Pair N → tương ứng `environments[N]`
|
|
49
|
+
|
|
50
|
+
**Bước 3 — Giữ chỉ các pairs có index nằm trong danh sách environments:**
|
|
51
|
+
|
|
52
|
+
Environments trong config có bao nhiêu phần tử → giữ bấy nhiêu pairs (theo đúng thứ tự). Pairs thừa (tương ứng env không có trong config) → loại bỏ.
|
|
53
|
+
|
|
54
|
+
### Ví dụ
|
|
55
|
+
|
|
56
|
+
Config: `environments: [dev, prod]` → 2 environments
|
|
57
|
+
|
|
58
|
+
ADO trả về states (theo thứ tự): New, Pending, In Progress, Deploy Test, Verify Test, Deploy Stag, Verify Stag, Deploy Prod, Verify Prod, Done, Removed
|
|
59
|
+
|
|
60
|
+
Environment-specific pairs (theo thứ tự ADO):
|
|
61
|
+
- Pair 0: (Deploy Test, Verify Test) → `environments[0]` = dev ✓ giữ
|
|
62
|
+
- Pair 1: (Deploy Stag, Verify Stag) → `environments[1]` = prod ✗ nhưng config[1] = prod, không phải stag → loại
|
|
63
|
+
- Pair 2: (Deploy Prod, Verify Prod) → `environments[2]` = không có (chỉ có 2 env) → loại
|
|
64
|
+
|
|
65
|
+
Vì config có 2 environments → giữ 2 pairs đầu tiên: Pair 0 (dev) và Pair 2 (prod):
|
|
66
|
+
- Pair 0: (Deploy Test, Verify Test) → env[0] = dev ✓
|
|
67
|
+
- Pair 2: (Deploy Prod, Verify Prod) → env[1] = prod ✓
|
|
68
|
+
|
|
69
|
+
State list sau filter: New, Pending, In Progress, Deploy Test, Verify Test, Deploy Prod, Verify Prod, Done, Removed
|
|
70
|
+
|
|
71
|
+
> **Lưu ý về mapping positional:** Tổng số pairs ADO trả về có thể nhiều hơn số environments trong config. Map theo vị trí index trong danh sách pairs: pair thứ 0 → env thứ 0, pair thứ 1 → env thứ 1. Pairs có index ≥ số environments trong config → loại bỏ.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Process
|
|
76
|
+
|
|
77
|
+
### Bước 1: Load config
|
|
78
|
+
|
|
79
|
+
Đọc `.claude/ado.yaml`. Nếu không tồn tại → dừng:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Chưa có .claude/ado.yaml. Hãy chạy /ado-config trước.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Nếu `environments` trống hoặc không tồn tại trong file → dừng:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
.claude/ado.yaml chưa có danh sách environments. Hãy chạy /ado-config để cập nhật.
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Bước 2: Chọn integration
|
|
94
|
+
|
|
95
|
+
List tất cả thư mục trong `specs/integrations/` trừ `000-scaffold`. Với mỗi thư mục, đọc frontmatter của `spec.md` để lấy `title` và `status`.
|
|
96
|
+
|
|
97
|
+
Hỏi user bằng `AskUserQuestion`:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
question: "Chọn integration để cập nhật ADO ticket status:"
|
|
101
|
+
options:
|
|
102
|
+
- label: "001-implement-auth — Implement Authentication"
|
|
103
|
+
description: "status: draft | features: F-001"
|
|
104
|
+
- label: "002-implement-todo — Implement Todo Management"
|
|
105
|
+
description: "status: draft | features: F-002, F-003"
|
|
106
|
+
...
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Sau khi user chọn → đọc toàn bộ `spec.md` của integration đó.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Bước 3: Parse và kiểm tra ADO tickets
|
|
114
|
+
|
|
115
|
+
**Parse spec.md** để extract:
|
|
116
|
+
|
|
117
|
+
**Features:** Tìm heading `### Feature: <name> (<ID>)` hoặc heading Feature tương đương. Sau mỗi heading, tìm dòng `**ADO F-XXX:**` hoặc `**ADO:**` để lấy ticket ID.
|
|
118
|
+
|
|
119
|
+
**User Stories:** Tìm heading `#### US-FXXX-YYY — <title>`. Sau mỗi heading, tìm dòng `**ADO:**` để lấy ticket ID.
|
|
120
|
+
|
|
121
|
+
**Quy tắc parse ADO ticket ID:** Tìm pattern `[#(\d+)` trong dòng `**ADO**` và extract số đó làm ticket ID.
|
|
122
|
+
|
|
123
|
+
**Kiểm tra đầy đủ tickets:**
|
|
124
|
+
|
|
125
|
+
- Nếu **bất kỳ** Feature hoặc User Story nào **chưa có** dòng `**ADO:**` → dừng và báo:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
Integration "002-implement-todo" chưa có đầy đủ ADO tickets.
|
|
129
|
+
|
|
130
|
+
Thiếu tickets:
|
|
131
|
+
✗ F-002 — Quản lý todo (chưa có Feature ticket)
|
|
132
|
+
✗ US-F002-003 — Xóa task (chưa có User Story ticket)
|
|
133
|
+
|
|
134
|
+
Hãy chạy /ado-create trước để tạo đầy đủ tickets.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- Nếu **tất cả** đều có → tiếp tục Bước 4.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### Bước 4: Fetch states từ ADO và hiển thị tickets hiện tại
|
|
142
|
+
|
|
143
|
+
Thực hiện **song song**:
|
|
144
|
+
|
|
145
|
+
1. Gọi `mcp__azure-devops__wit_get_work_items_batch_by_ids` với tất cả ticket IDs (Feature + User Story) để lấy state hiện tại.
|
|
146
|
+
2. Gọi `mcp__azure-devops__wit_get_work_item_type` với `workItemType: "User Story"` để lấy danh sách states thực tế.
|
|
147
|
+
3. Gọi `mcp__azure-devops__wit_get_work_item_type` với `workItemType: "Feature"` để lấy danh sách Feature states thực tế.
|
|
148
|
+
|
|
149
|
+
Extract `states[].name` từ response của mỗi work item type — đây là danh sách state hợp lệ sẽ dùng ở Bước 5 và 7.
|
|
150
|
+
|
|
151
|
+
Hiển thị tóm tắt trạng thái hiện tại:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
Integration: 002-implement-todo — Implement Todo Management
|
|
155
|
+
|
|
156
|
+
User Story Tickets:
|
|
157
|
+
• #24255 — US-F003-001 — Xem Shared Kanban Board [New]
|
|
158
|
+
• #24256 — US-F002-001 — Tạo task mới [New]
|
|
159
|
+
• #24257 — US-F002-002 — Sửa task [Deploy Test]
|
|
160
|
+
• #24258 — US-F002-003 — Xóa task [Verify Test]
|
|
161
|
+
|
|
162
|
+
Feature Tickets:
|
|
163
|
+
• #24253 — F-002 — Quản lý todo [In Development]
|
|
164
|
+
• #24254 — F-003 — Shared dashboard [In Design]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### Bước 5: Chọn state mới cho User Story tickets
|
|
170
|
+
|
|
171
|
+
Dùng danh sách `states[].name` đã fetch từ ADO ở Bước 4, **áp dụng Environment-State Filtering** (xem phần trên) để loại bỏ các state không tương ứng với environments được cấu hình.
|
|
172
|
+
|
|
173
|
+
In ra danh sách đánh số dạng plain text — **không dùng `AskUserQuestion`** vì số state có thể vượt quá 4 options.
|
|
174
|
+
|
|
175
|
+
Ví dụ output với `environments: [dev, prod]` (đã filter bỏ Deploy Stag, Verify Stag):
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
Chọn state mới cho tất cả User Story tickets:
|
|
179
|
+
|
|
180
|
+
1. New
|
|
181
|
+
2. Pending
|
|
182
|
+
3. Committed
|
|
183
|
+
4. In Progress
|
|
184
|
+
5. Deploy Test
|
|
185
|
+
6. Verify Test
|
|
186
|
+
7. Deploy Prod
|
|
187
|
+
8. Verify Prod
|
|
188
|
+
9. Done
|
|
189
|
+
10. Removed
|
|
190
|
+
|
|
191
|
+
Nhập số (1–10):
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Chờ user nhập số. Nếu input không hợp lệ → in lại danh sách và nhắc nhập lại.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
### Bước 6: Xác nhận và cập nhật User Story tickets
|
|
199
|
+
|
|
200
|
+
Hiển thị preview trước khi cập nhật:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
Sẽ cập nhật 4 User Story tickets → "Verify Dev":
|
|
204
|
+
|
|
205
|
+
• #24255 — US-F003-001 — Xem Shared Kanban Board [New] → [Verify Dev]
|
|
206
|
+
• #24256 — US-F002-001 — Tạo task mới [New] → [Verify Dev]
|
|
207
|
+
• #24257 — US-F002-002 — Sửa task [Deploy Dev] → [Verify Dev]
|
|
208
|
+
• #24258 — US-F002-003 — Xóa task [Verify Dev] → (không đổi)
|
|
209
|
+
|
|
210
|
+
Tiếp tục? (yes/no)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Các ticket đã ở đúng state rồi → hiển thị "(không đổi)", không gọi API update.
|
|
214
|
+
|
|
215
|
+
Nếu user xác nhận → gọi `mcp__azure-devops__wit_update_work_item` tuần tự cho từng ticket cần cập nhật:
|
|
216
|
+
- `id`: ticket ID
|
|
217
|
+
- `state`: state mới đã chọn
|
|
218
|
+
|
|
219
|
+
Nếu update thất bại → log lỗi, tiếp tục với ticket tiếp theo, báo cáo ở Bước 8.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Bước 7: Hỏi về Feature tickets
|
|
224
|
+
|
|
225
|
+
Sau khi hoàn tất User Story, hỏi user bằng `AskUserQuestion`:
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
question: "Bạn có muốn cập nhật state cho Feature tickets không?"
|
|
229
|
+
options:
|
|
230
|
+
- label: "Có, cập nhật Feature tickets"
|
|
231
|
+
description: "Chọn state mới và cập nhật tất cả Feature tickets của integration này"
|
|
232
|
+
- label: "Không, bỏ qua"
|
|
233
|
+
description: "Giữ nguyên state hiện tại của Feature tickets"
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Nếu user chọn "Không"** → nhảy thẳng đến Bước 8.
|
|
237
|
+
|
|
238
|
+
**Nếu user chọn "Có":**
|
|
239
|
+
|
|
240
|
+
In danh sách đánh số dạng plain text — **không dùng `AskUserQuestion`** — dùng Feature states đã fetch từ ADO ở Bước 4:
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
Chọn state mới cho tất cả Feature tickets:
|
|
244
|
+
|
|
245
|
+
1. New
|
|
246
|
+
2. In Design
|
|
247
|
+
3. In Development
|
|
248
|
+
4. Done
|
|
249
|
+
5. Removed
|
|
250
|
+
|
|
251
|
+
Nhập số (1–5):
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Chờ user nhập số. Nếu input không hợp lệ → in lại danh sách và nhắc nhập lại.
|
|
255
|
+
|
|
256
|
+
Hiển thị preview giống Bước 6 cho Feature tickets, xác nhận rồi gọi `mcp__azure-devops__wit_update_work_item` cho từng ticket cần cập nhật.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
### Bước 8: Tóm tắt kết quả
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
✓ Cập nhật ADO ticket status — integration: 002-implement-todo
|
|
264
|
+
|
|
265
|
+
User Story Tickets → "Verify Dev":
|
|
266
|
+
✓ #24255 — US-F003-001 — Xem Shared Kanban Board
|
|
267
|
+
✓ #24256 — US-F002-001 — Tạo task mới
|
|
268
|
+
✓ #24257 — US-F002-002 — Sửa task
|
|
269
|
+
— #24258 — US-F002-003 — Xóa task (không đổi — đã là Verify Dev)
|
|
270
|
+
|
|
271
|
+
Feature Tickets → "In Development":
|
|
272
|
+
✓ #24253 — F-002 — Quản lý todo
|
|
273
|
+
— #24254 — F-003 — Shared dashboard (không đổi — đã là In Development)
|
|
274
|
+
|
|
275
|
+
{nếu có lỗi}
|
|
276
|
+
✗ #24260 — US-F002-004 — ... → cập nhật thất bại: <lý do>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Verification Checklist
|
|
282
|
+
|
|
283
|
+
Trước khi cập nhật:
|
|
284
|
+
- [ ] `.claude/ado.yaml` tồn tại và có `environments` là array không rỗng
|
|
285
|
+
- [ ] Tất cả Features và User Stories trong `spec.md` đều có dòng `**ADO:**` với ticket ID hợp lệ
|
|
286
|
+
- [ ] State list lấy từ ADO qua `wit_get_work_item_type` — **không generate từ `environments`**, không hardcode
|
|
287
|
+
- [ ] State list đã qua **Environment-State Filtering**: chỉ hiển thị Deploy/Verify pairs tương ứng với environments trong config; general states giữ nguyên
|
|
288
|
+
- [ ] State selection dùng numbered list plain text — **không dùng `AskUserQuestion`** (số options vượt giới hạn 4)
|
|
289
|
+
- [ ] User đã xem preview và xác nhận trước khi gọi API
|
|
290
|
+
|
|
291
|
+
Khi cập nhật:
|
|
292
|
+
- [ ] Chỉ gọi API update cho ticket **chưa ở đúng state** — không update nếu state không đổi
|
|
293
|
+
- [ ] Gọi tuần tự, không batch update (để xử lý lỗi từng ticket riêng lẻ)
|
|
294
|
+
- [ ] Nếu 1 ticket fail → tiếp tục với ticket tiếp theo, không dừng toàn bộ
|
|
295
|
+
- [ ] Feature tickets chỉ update khi user **chủ động chọn "Có"** ở Bước 7
|
package/skills/spec-new/SKILL.md
CHANGED
|
@@ -87,7 +87,7 @@ Lưu lại lựa chọn section.
|
|
|
87
87
|
|
|
88
88
|
Từ raw requirement, agent xác định features và components liên quan, rồi load các file sau:
|
|
89
89
|
|
|
90
|
-
- `specs/main/prd.md` — đọc Problem Statement, Target Users, Scope, Feature Index, Component Index
|
|
90
|
+
- `specs/main/prd.md` — đọc Problem Statement, Target Users, Scope, Feature Index, Component Index; **đặc biệt ghi nhận cột `ADO` trong bảng Features** — nếu feature đã có ticket ID thì lưu lại `{feature_id → ado_ticket_id, ado_ticket_title, ado_ticket_url}`
|
|
91
91
|
- `specs/main/domain.md` — đọc Glossary và Shared Entities
|
|
92
92
|
- `specs/main/feature/{F-XXX}-{slug}/frd.md` — cho mỗi feature liên quan (nếu file đã tồn tại)
|
|
93
93
|
- `specs/main/component/{C-XXX}-{slug}/crd.md` — cho mỗi component bị touched (nếu file đã tồn tại)
|
|
@@ -163,6 +163,15 @@ Tổng hợp và viết draft `spec.md`:
|
|
|
163
163
|
|
|
164
164
|
**Cấu trúc file**: dùng `.claude/templates/integrations/spec-template.md` làm skeleton, điền nội dung từ interview vào.
|
|
165
165
|
|
|
166
|
+
**ADO references từ prd.md:** Với mỗi Feature heading (`### Feature: <name> (<ID>)`) trong spec.md, nếu feature đó đã có ADO ticket trong `prd.md` → thêm ngay dòng `**ADO:**` bên dưới heading:
|
|
167
|
+
|
|
168
|
+
```markdown
|
|
169
|
+
### Feature: Đăng ký / Đăng nhập (F-001)
|
|
170
|
+
**ADO:** [#12345 — [SDLC-TEST] Đăng ký / Đăng nhập](https://dev.azure.com/...)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Điều này đảm bảo `/ado-create` nhận biết feature đã có ticket và không tạo duplicate.
|
|
174
|
+
|
|
166
175
|
**Cascade Proposals** — agent đề xuất delta cho main artifacts theo các targets sau (chỉ điền nếu thực sự có thay đổi, không thì ghi "Không có thay đổi đề xuất."):
|
|
167
176
|
|
|
168
177
|
### prd.md
|