@relipa/ai-flow-kit 0.2.0-beta.1 → 0.2.0-beta.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/aiflow.js +8 -4
- package/custom/skills/ba-skills/skill-ba-initial-analysis-template-v1.md +7 -5
- package/custom/skills/ba-skills/skill-ba-initial-analysis-v1.md +6 -1
- package/custom/skills/ba-skills/skill-ba-qna-template-v1.md +6 -5
- package/custom/skills/ba-skills/skill-ba-qna-v1.md +17 -5
- package/custom/skills/create-system-requirement/SKILL.md +104 -26
- package/custom/skills/ingest-data/SKILL.md +3 -3
- package/custom/templates/shared/create-spec-workflow.md +93 -31
- package/custom/templates/shared/gate-workflow.md +2 -2
- package/docs/common/CHANGELOG.md +10 -0
- package/package.json +1 -1
- package/scripts/link-resolver.js +8 -4
- package/scripts/task.js +25 -8
package/bin/aiflow.js
CHANGED
|
@@ -212,7 +212,8 @@ program
|
|
|
212
212
|
Examples:
|
|
213
213
|
$ ak fetch-links "https://company.backlog.com/view/PROJ-10"
|
|
214
214
|
$ ak fetch-links "https://company.backlog.com/view/PROJ-10#comment-456"
|
|
215
|
-
$ ak fetch-links "https://company.backlog.com/document/
|
|
215
|
+
$ ak fetch-links "https://company.backlog.com/document/0193b335c62173de9547bab5dd0b5324" Backlog Document (ingest-data)
|
|
216
|
+
$ ak fetch-links "https://company.backlog.com/document/PROJ/e/0193b335c62173de9547bab5dd0b5324" Backlog Document share link (newer format)
|
|
216
217
|
$ ak fetch-links "https://company.backlog.com/alias/wiki/1234" Backlog Wiki (ingest-data)
|
|
217
218
|
$ ak fetch-links "https://company.atlassian.net/browse/PROJ-10"
|
|
218
219
|
$ ak fetch-links "https://company.atlassian.net/browse/PROJ-10?focusedCommentId=789"
|
|
@@ -584,13 +585,14 @@ function checkAndInstallAiflowGlobal() {
|
|
|
584
585
|
// ── gate (telemetry for gate workflow events) ─────────────────
|
|
585
586
|
program
|
|
586
587
|
.command('gate <number> <action>')
|
|
587
|
-
.description('Log a gate workflow event (start|approved) — called by AI during gate workflow')
|
|
588
|
+
.description('Log a gate workflow event (start|approved|skip) — called by AI during gate workflow')
|
|
588
589
|
.option('--ticket <id>', 'ticket ID')
|
|
589
590
|
.option('--ai-tool <tool>', 'AI tool name')
|
|
591
|
+
.option('--reason <text>', 'why this gate was skipped (only used with action=skip)')
|
|
590
592
|
.action((number, action, options) => {
|
|
591
593
|
const gateNum = parseInt(number);
|
|
592
594
|
if (isNaN(gateNum) || gateNum < 1 || gateNum > 5) return;
|
|
593
|
-
if (!['start', 'approved'].includes(action)) return;
|
|
595
|
+
if (!['start', 'approved', 'skip'].includes(action)) return;
|
|
594
596
|
|
|
595
597
|
if (action === 'start') {
|
|
596
598
|
console.log(chalk.cyan(`\n [aiflow] Gate ${gateNum} environment check:`));
|
|
@@ -610,7 +612,7 @@ program
|
|
|
610
612
|
|
|
611
613
|
// Keep task-state.json currentGate in sync (silent — never blocks the AI)
|
|
612
614
|
if (ticketId) {
|
|
613
|
-
updateTaskGateState(ticketId, gateNum, action).catch(() => {});
|
|
615
|
+
updateTaskGateState(ticketId, gateNum, action, { reason: options.reason }).catch(() => {});
|
|
614
616
|
}
|
|
615
617
|
|
|
616
618
|
if (action === 'approved') {
|
|
@@ -618,6 +620,8 @@ program
|
|
|
618
620
|
console.log(chalk.yellow(` Pro-Tip: To avoid context pollution, it's recommended to start a fresh chat session.`));
|
|
619
621
|
console.log(chalk.gray(` Run: aiflow task next${ticketId ? ` --ticket ${ticketId}` : ''} to save progress,`));
|
|
620
622
|
console.log(chalk.gray(` then open a NEW chatbox and type "continue".\n`));
|
|
623
|
+
} else if (action === 'skip') {
|
|
624
|
+
console.log(chalk.cyan(`\n Gate ${gateNum} skipped${options.reason ? `: ${options.reason}` : ''}`));
|
|
621
625
|
}
|
|
622
626
|
});
|
|
623
627
|
|
|
@@ -22,9 +22,11 @@ Mẫu tài liệu này được sử dụng để trình bày kết quả phân
|
|
|
22
22
|
|
|
23
23
|
## 5. Bảng Phân Tích Khoảng Trống & Giả Định (Gap & Assumption Analysis)
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
| :-: | :--- | :--- | :--- | :--- | :--- |
|
|
27
|
-
| 1 | *Ví dụ: Nhập Password* | *Mật khẩu được che giấu* | *Có nút show/hide mật khẩu hay không? Đăng nhập sai bao nhiêu lần thì khóa?* | *Mặc định không hiển thị nút show/hide. Cho phép nhập sai tối đa 5 lần.* | *Xem Q&A_01* |
|
|
28
|
-
| 2 | | | | | |
|
|
25
|
+
*Chỉ liệt kê các Gap còn **Open** (chưa Confirmed) — Gap đã Confirmed được tích hợp thẳng vào mục 1-4 phía trên, không giữ lại ở bảng này. Cột Mức độ ảnh hưởng: 🔴 Blocking (chặn gate tiếp theo) / 🟡 Non-blocking (được phép defer, có marker `[PENDING - QA-ID]`).*
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
| # | Tính năng/Luồng nghiệp vụ | Hiện trạng mô tả thô | Khoảng trống (Gap) / Sự mơ hồ phát hiện | Giả định của BA (Assumption) | Mức độ ảnh hưởng | Đề xuất giải pháp / Q&A ID tương ứng |
|
|
28
|
+
| :-: | :--- | :--- | :--- | :--- | :-: | :--- |
|
|
29
|
+
| 1 | *Ví dụ: Nhập Password* | *Mật khẩu được che giấu* | *Có nút show/hide mật khẩu hay không? Đăng nhập sai bao nhiêu lần thì khóa?* | *Chưa có giả định — cần khách hàng xác nhận số lần khóa vì ảnh hưởng luồng chính* | 🔴 Blocking | *Xem [PENDING - QA-01]* |
|
|
30
|
+
| 2 | *Ví dụ: Thông báo lỗi* | *Không nêu rõ text lỗi* | *Text thông báo lỗi cụ thể là gì?* | *Tạm dùng text mặc định, có thể đổi sau* | 🟡 Non-blocking | *Xem [PENDING - QA-02]* |
|
|
31
|
+
|
|
32
|
+
*Lưu ý: Bảng này là cơ sở quan trọng nhất để tạo ra danh sách câu hỏi Q&A chuẩn xác cho khách hàng. Số dòng phải phản ánh đúng số Gap thực tế tìm được — không rút gọn cho "gọn tài liệu" nếu vẫn còn Gap chưa được hỏi.*
|
|
@@ -32,14 +32,19 @@ Ngôn ngữ output: auto-detect theo ngôn ngữ của ticket/task input — xem
|
|
|
32
32
|
- Nếu để trống thì hệ thống xử lý thế nào? Có thông báo lỗi gì không?
|
|
33
33
|
- Có quy tắc nghiệp vụ (Business rules) ngầm định nào không?
|
|
34
34
|
- Luồng thay thế (Alternative flows) hoặc luồng lỗi (Exception flows) là gì?
|
|
35
|
+
|
|
36
|
+
Số lượng Gap tìm được phải tăng theo độ phức tạp thực tế của yêu cầu — KHÔNG dừng lại khi "cảm thấy đủ" hoặc đã đạt một số lượng quen thuộc (ví dụ 5-6 điểm) nếu còn trường/luồng/actor chưa được đối chiếu hết qua 4 câu hỏi trên. Với yêu cầu nhiều màn hình/nhiều actor/tích hợp hệ thống khác, quét từng màn hình/actor riêng biệt rồi tổng hợp, không gộp tắt.
|
|
37
|
+
Với mỗi Gap, gắn nhãn mức độ ảnh hưởng ngay: 🔴 **Blocking** (ảnh hưởng cấu trúc dữ liệu, luồng chính, phân quyền/bảo mật, hoặc quyết định khó đảo ngược) hoặc 🟡 **Non-blocking** (chi tiết UI/text, giá trị mặc định có thể đổi sau, luồng hiếm gặp).
|
|
35
38
|
- **Bước 4: Soạn dự thảo Kết quả phân tích ban đầu:**
|
|
36
|
-
Áp dụng template phân tích ban đầu (`skill-ba-initial-analysis-template-v1.md`) để điền thông tin và lập bảng Gap/Assumption.
|
|
39
|
+
Áp dụng template phân tích ban đầu (`skill-ba-initial-analysis-template-v1.md`) để điền thông tin và lập bảng Gap/Assumption, kèm cột Mức độ ảnh hưởng cho mỗi Gap.
|
|
37
40
|
|
|
38
41
|
## 4. Checklist kiểm tra (Checklist for Verification)
|
|
39
42
|
- [ ] Đã xác định rõ Mục tiêu hệ thống/chức năng chưa? (Hệ thống giải quyết bài toán gì?)
|
|
40
43
|
- [ ] Đã làm rõ tất cả các Tác nhân (Actors) tham gia chưa?
|
|
41
44
|
- [ ] Đã bóc tách hết các trường thông tin (Inputs) được liệt kê trong tài liệu thô chưa?
|
|
42
45
|
- [ ] Đã ghi nhận rõ ràng danh sách các điểm mơ hồ hoặc thiếu thông tin dưới dạng **Gap/Assumption** chưa?
|
|
46
|
+
- [ ] Số lượng Gap tìm được có phản ánh đúng độ phức tạp thực tế (nhiều màn hình/actor/luồng → nhiều Gap hơn), không bị gò về một số cố định không?
|
|
47
|
+
- [ ] Mỗi Gap đã có nhãn Mức độ ảnh hưởng (🔴 Blocking / 🟡 Non-blocking) chưa?
|
|
43
48
|
- [ ] Không tự tiện bổ sung các tính năng ngoài phạm vi yêu cầu của khách hàng khi chưa có thảo luận/Q&A.
|
|
44
49
|
|
|
45
50
|
## 5. Output mong đợi (Expected Output)
|
|
@@ -6,16 +6,17 @@ Mẫu tài liệu dùng để trình bày danh sách câu hỏi Q&A và theo dõ
|
|
|
6
6
|
|
|
7
7
|
# Tài liệu Q&A: [Tên Chức Năng]
|
|
8
8
|
|
|
9
|
-
*Tài liệu này dùng để theo dõi các vấn đề nghiệp vụ cần làm rõ giữa đội ngũ dự án và khách hàng. Trạng thái bao gồm: **Open** (Đang chờ phản hồi), **Confirmed** (Đã thống nhất).*
|
|
9
|
+
*Tài liệu này dùng để theo dõi các vấn đề nghiệp vụ cần làm rõ giữa đội ngũ dự án và khách hàng. Trạng thái bao gồm: **Open** (Đang chờ phản hồi), **Confirmed** (Đã thống nhất). Mức độ ảnh hưởng: 🔴 **Blocking** (chưa trả lời thì không thể tiến gate tiếp theo), 🟡 **Non-blocking** (có thể defer, output sẽ giữ marker `[PENDING - QA-ID]` tại vị trí liên quan).*
|
|
10
10
|
|
|
11
11
|
## Danh sách câu hỏi Q&A
|
|
12
12
|
|
|
13
|
-
| ID | Chức năng / Màn hình | Nội dung yêu cầu hiện tại | Câu hỏi / Điểm chưa rõ | Đề xuất giải pháp (Options) | Câu trả lời của Khách hàng | Trạng thái |
|
|
14
|
-
| :-: | :--- | :--- | :--- | :--- | :--- | :-: |
|
|
15
|
-
| **QA-01** | *Đăng nhập* | *Có text link đổi mật khẩu* | *Text link này sẽ dẫn sang URL cụ thể nào? Hệ thống tự sinh OTP gửi mail hay chuyển sang màn nhập email?* | *- Option A: Chuyển sang URL `/forgot-password` để nhập Email nhận link reset.<br>- Option B: Hiển thị popup nhập SĐT nhận OTP.* | *Khách hàng phản hồi: Chọn Option A, link URL là `/forgot-password`* | **Confirmed** |
|
|
16
|
-
| **QA-02** | | | | | | **Open** |
|
|
13
|
+
| ID | Chức năng / Màn hình | Nội dung yêu cầu hiện tại | Câu hỏi / Điểm chưa rõ | Đề xuất giải pháp (Options) | Mức độ ảnh hưởng | Câu trả lời của Khách hàng | Trạng thái |
|
|
14
|
+
| :-: | :--- | :--- | :--- | :--- | :-: | :--- | :-: |
|
|
15
|
+
| **QA-01** | *Đăng nhập* | *Có text link đổi mật khẩu* | *Text link này sẽ dẫn sang URL cụ thể nào? Hệ thống tự sinh OTP gửi mail hay chuyển sang màn nhập email?* | *- Option A: Chuyển sang URL `/forgot-password` để nhập Email nhận link reset.<br>- Option B: Hiển thị popup nhập SĐT nhận OTP.* | 🔴 Blocking | *Khách hàng phản hồi: Chọn Option A, link URL là `/forgot-password`* | **Confirmed** |
|
|
16
|
+
| **QA-02** | *Đăng nhập* | *Thông báo lỗi khi sai mật khẩu* | *Câu chữ thông báo lỗi cụ thể là gì?* | *- Option A: "Email hoặc mật khẩu không đúng."<br>- Option B: Ý kiến khác...* | 🟡 Non-blocking | *Chưa trả lời — khách hàng cần hỏi lại team Marketing* | **Open** |
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
## Lịch sử cập nhật tài liệu
|
|
20
20
|
*Sau mỗi lần nhận phản hồi, BA cập nhật bảng trên và ghi nhận lịch sử tại đây:*
|
|
21
21
|
- **Ngày [dd/mm/yyyy]:** Nhận phản hồi lần 1 từ khách hàng cho câu hỏi QA-01. Cập nhật trạng thái sang **Confirmed** và chỉnh sửa tài liệu Phân tích bản đầu tương ứng.
|
|
22
|
+
- **Ngày [dd/mm/yyyy]:** QA-02 (🟡 Non-blocking) vẫn **Open** — BA đã xác nhận tiếp tục sang gate kế tiếp, đánh dấu `[PENDING - QA-02]` trong Analysis tại mục thông báo lỗi đăng nhập.
|
|
@@ -14,15 +14,24 @@ Ngôn ngữ output: auto-detect theo ngôn ngữ của ticket/task input — xem
|
|
|
14
14
|
|
|
15
15
|
## 3. Quy trình thực hiện (Step-by-step Process)
|
|
16
16
|
- **Bước 1: Chuyển đổi Gap thành câu hỏi Q&A:**
|
|
17
|
-
Từ danh sách khoảng trống phát hiện ở bước Phân tích ban đầu, chuyển mỗi dòng thành một câu hỏi Q&A cụ thể.
|
|
18
|
-
- **Bước 2:
|
|
17
|
+
Từ danh sách khoảng trống phát hiện ở bước Phân tích ban đầu, chuyển mỗi dòng thành một câu hỏi Q&A cụ thể. Số lượng câu hỏi phải phản ánh đúng số Gap thực tế — không tự giới hạn theo một số cố định (ví dụ luôn dừng ở 5-6 câu) bất kể yêu cầu đơn giản hay phức tạp. Nếu phát sinh Gap mới trong lúc soạn câu hỏi (đọc kỹ hơn thấy còn điểm mơ hồ), bổ sung ngay câu hỏi mới, không bỏ qua để "gọn danh sách".
|
|
18
|
+
- **Bước 2: Gắn nhãn mức độ ảnh hưởng (Blocking/Non-blocking):**
|
|
19
|
+
Trước khi chuẩn hóa câu hỏi, gắn nhãn:
|
|
20
|
+
- 🔴 **Blocking** — ảnh hưởng cấu trúc dữ liệu, luồng chính (happy path), phân quyền/bảo mật, hoặc quyết định kiến trúc khó đảo ngược sau khi code.
|
|
21
|
+
- 🟡 **Non-blocking** — chi tiết UI/text, giá trị mặc định có thể đổi sau, alternative/exception flow hiếm gặp.
|
|
22
|
+
Nhãn này quyết định câu hỏi có bắt buộc phải Confirmed trước khi qua gate tiếp theo hay được phép defer.
|
|
23
|
+
- **Bước 3: Chuẩn hóa câu hỏi theo mẫu `@skill-ba-qna-template-v1.md`:**
|
|
19
24
|
- Xác định phân vùng nghiệp vụ (Module/Screen).
|
|
20
25
|
- Trích dẫn yêu cầu hiện tại (Current Status/Requirement).
|
|
21
26
|
- Nêu rõ vấn đề mơ hồ.
|
|
22
27
|
- Đưa ra các giải pháp đề xuất (Options) cùng giả định của BA.
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
-
|
|
28
|
+
- Điền cột Mức độ ảnh hưởng (🔴 Blocking / 🟡 Non-blocking) đã gắn ở Bước 2.
|
|
29
|
+
- **Bước 4: Nhận phản hồi và Cập nhật (Process Responses):**
|
|
30
|
+
- Khi nhận được câu trả lời: Đọc kỹ để đảm bảo câu trả lời đã giải quyết triệt để câu hỏi.
|
|
31
|
+
- Đã rõ ràng → đánh dấu **Confirmed**, cập nhật thông tin đó trực tiếp vào tài liệu phân tích hiện tại, xóa marker `[PENDING - QA-ID]` liên quan nếu có.
|
|
32
|
+
- Chưa rõ ràng / khách hàng chưa trả lời được ngay:
|
|
33
|
+
- 🟡 Non-blocking → giữ **Open** (deferred), tiếp tục các câu khác/gate tiếp theo bình thường, ghi marker `[PENDING - QA-ID]` tại vị trí nội dung liên quan trong tài liệu.
|
|
34
|
+
- 🔴 Blocking → giữ **Open** nhưng cảnh báo rõ cho BA lý do đây là blocking và hệ quả nếu bỏ qua trước khi cho phép gate tiếp theo tiến hành; không tự hạ nhãn xuống Non-blocking để né cảnh báo.
|
|
26
35
|
- Ghi nhận lịch sử thay đổi để Dev/Test nắm được lý do thay đổi logic.
|
|
27
36
|
|
|
28
37
|
## 4. Checklist kiểm tra (Checklist for Verification)
|
|
@@ -30,7 +39,10 @@ Ngôn ngữ output: auto-detect theo ngôn ngữ của ticket/task input — xem
|
|
|
30
39
|
- [ ] Câu hỏi có sử dụng từ ngữ trung lập, không mang tính áp đặt ý kiến chủ quan của BA không?
|
|
31
40
|
- [ ] Có đưa ra các phương án gợi ý (Option A, Option B...) cho các vấn đề phức tạp để khách hàng dễ lựa chọn không?
|
|
32
41
|
- [ ] Các thuật ngữ viết tắt trong câu hỏi có được giải thích rõ không?
|
|
42
|
+
- [ ] Mỗi câu hỏi đã có nhãn Mức độ ảnh hưởng (🔴 Blocking / 🟡 Non-blocking) chưa?
|
|
43
|
+
- [ ] Số lượng câu hỏi có phản ánh đúng độ phức tạp thực tế của yêu cầu, không bị gò về một số cố định không?
|
|
33
44
|
- [ ] Đã cập nhật đúng và đầy đủ tất cả câu trả lời của khách hàng vào tài liệu phân tích chưa? (Không bỏ sót bất kỳ điểm chốt nào).
|
|
45
|
+
- [ ] Mọi nội dung phụ thuộc câu hỏi còn Open đã có marker `[PENDING - QA-ID]` tại đúng vị trí, chưa bị tự suy diễn để lấp đầy?
|
|
34
46
|
|
|
35
47
|
## 5. Output mong đợi (Expected Output)
|
|
36
48
|
- File danh sách câu hỏi Q&A định dạng markdown, cấu trúc thống nhất dựa theo `@skill-ba-qna-template-v1.md`, đặt tên theo chuẩn: `QnA-Log_v(m).md` trong thư mục `02.BA-Specs/02.QnA/[functionId]/`.
|
|
@@ -59,7 +59,8 @@ Same methodology as `read-study-requirement` Step 1 (steps 4–5), reused here:
|
|
|
59
59
|
- Find modules/files that implement or would implement this UC's Main Flow (existing feature being extended, or nearest analogous feature for a new one).
|
|
60
60
|
- **If GitNexus MCP available:** `gitnexus: query()` / `gitnexus: context()` for the relevant area — same token-saving shortcut as `read-study-requirement`.
|
|
61
61
|
- Identify **existing error-handling conventions** (error code format, message structure, exception class hierarchy) — the Exception & Error Handling section (Step 4 below) must reuse these, not invent a new convention.
|
|
62
|
-
- Identify **existing data model / API surface** touched by this UC (tables, DTOs, endpoints) — feeds Section 6 of the output.
|
|
62
|
+
- Identify **existing data model / API surface** touched by this UC (tables, DTOs, endpoints) — feeds Section 6.1 of the output.
|
|
63
|
+
- Identify whether this UC integrates with any system **outside** the app's own UI/DB (third-party API, webhook, message queue, etc.) — the UC Spec won't describe this since it's UI/flow-focused; if found, feeds Section 6.3. If there's none, skip Section 6.3 entirely rather than leaving it as empty boilerplate.
|
|
63
64
|
|
|
64
65
|
This step exists so System Requirement reflects what the system *can actually do today*, not just what the UC Spec says in the abstract.
|
|
65
66
|
|
|
@@ -73,18 +74,32 @@ For every row in the UC Spec's Main Flow, Alternative/Exception Flows, and Busin
|
|
|
73
74
|
- **Non-Functional Requirements** — from BR3-type rules (security, authz) or explicit constraints in the UC Spec / ticket context; do not invent performance/scale numbers that aren't stated anywhere — mark as Gap and ask instead.
|
|
74
75
|
- **Business Rules → Validation Rules** — translate each BR into a concrete system-level rule, cross-referenced with the existing pattern found in Step 2 (or flagged if no existing pattern applies).
|
|
75
76
|
- **Exception & Error Handling** — one per Exception Flow, using the error-handling convention found in Step 2.
|
|
76
|
-
- **Acceptance Test Scenarios** — Given/When/Then, at least one per Main Flow outcome + one per Alternative/Exception Flow. This is the concrete deliverable requested by proposal #1 (acceptance tests generated from the spec, not copied from the ticket).
|
|
77
|
+
- **Acceptance Test Scenarios** — Given/When/Then, at least one per Main Flow outcome + one per Alternative/Exception Flow. This is the concrete deliverable requested by proposal #1 (acceptance tests generated from the spec, not copied from the ticket). Tag each scenario with the Requirement IDs it exercises (**Requirement Coverage**) so QA can trace AT → FR/VR/ER without re-reading the whole document.
|
|
77
78
|
|
|
78
79
|
**`RESYNC` mode:** diff the new UC Spec version against the previous one section by section; carry forward unchanged items, mark changed/removed items, draft new items only for the delta. Never silently drop an item without noting why in the Change Log.
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
#### Writing style & layering (applies to every item in Sections 1–4)
|
|
82
|
+
|
|
83
|
+
Every item is a stack of layers, each aimed at a different reader — write each layer, don't blend them:
|
|
84
|
+
|
|
85
|
+
1. **Requirement** — the system behavior in plain business language. No framework names, class names, method names, or library calls (`Rule::unique`, `FormRequest`, `Middleware`, `permission_handle()`, enum class names, etc.). PM/BA must be able to read this layer alone and understand what the system does.
|
|
86
|
+
- ❌ `Rule::unique(...)` → ✅ "The system validates that the Tag name is unique among active Tags."
|
|
87
|
+
- ❌ `permission_handle()` → ✅ "Only users with CREATE permission can create Tags."
|
|
88
|
+
- When a technical concept (e.g. an enum) has a business meaning, state the business impact first (e.g. "Newly created Tags are assigned the default status PENDING") and put the raw technical value in Implementation Reference as a `Tech Reference:` line — **never invent or assume what an enum/status value means in business terms unless the BA has confirmed it**; if unconfirmed, ask in Step 4 or leave it as the raw value with a Gap/Assumption tag. Every `Tech Reference:` line also gets a row in Section 6.2 (Glossary / Term Mapping) — write it once there, don't leave it scattered only inside individual items.
|
|
89
|
+
2. **System Behavior** — how the system processes it, still in plain language (conditions, order of checks, what triggers what). This is what BA/Tester use to write test cases.
|
|
90
|
+
3. **Error Response** (Validation Rules and Exception & Error Handling only) — the expected result for Tester: keep the HTTP status code (never drop it — Tester needs it), paired with a friendly label and the user-facing message, e.g. `HTTP 422 (Validation Error) — "..."`.
|
|
91
|
+
4. **Implementation Reference** — file/class/method/framework rule, for Developer cross-check only. This is where all the technical detail from Step 2 belongs — it never appears in layers 1–2.
|
|
92
|
+
|
|
93
|
+
Keep each layer short — one requirement, one behavior, one result. If a sentence needs 2–3 clauses to say, split it into separate `Requirement` / `System Behavior` / `Result` lines instead of one long sentence.
|
|
94
|
+
|
|
95
|
+
Classify every item as **Gap** (missing entirely) / **Assumption** (inferred, unconfirmed) / **Decision** (a choice made and confirmed during Q&A) / **Deviation** (implementation differs from what the UC Spec states) — only when one of these applies. A plain fact (explicit in UC Spec or confirmed in code) needs no tag; do not mark every item "Fact" by default, since a Requirement is a fact unless flagged otherwise. This replaces the old Fact/Assumption/Gap convention from `read-study-requirement` Step 1.75 for this skill's output — `read-study-requirement` itself is unaffected.
|
|
81
96
|
|
|
82
97
|
---
|
|
83
98
|
|
|
84
99
|
### Step 4: Clarify via Q&A (ask until Confirmed) [Gate 1]
|
|
85
100
|
|
|
86
101
|
- Ask **one question at a time**, prioritizing unresolved Assumptions/Gaps from Step 3.
|
|
87
|
-
- **Do not run `aiflow task next` into Gate 2 while any Gap remains unresolved.** This is the hard rule from proposal #7 — no fabrication, no "reasonable default" for missing UC content. If DEV genuinely cannot answer (needs BA), stop and record it as an
|
|
102
|
+
- **Do not run `aiflow task next` into Gate 2 while any Gap remains unresolved.** This is the hard rule from proposal #7 — no fabrication, no "reasonable default" for missing UC content. If DEV genuinely cannot answer (needs BA), stop and record it as an unresolved Gap in Section 7 rather than guessing.
|
|
88
103
|
- Do NOT invoke `superpowers:brainstorming` (same reason as `read-study-requirement`: its terminal state bypasses this gate's approval).
|
|
89
104
|
- All Gaps Confirmed → present a short Gate 1 summary, wait for DEV to run `aiflow task next` before continuing to Step 5.
|
|
90
105
|
|
|
@@ -122,6 +137,16 @@ Save to `AK-Docs/02.BA-Specs/00.Requirements/[functionId]/System-Requirement_v{N
|
|
|
122
137
|
|
|
123
138
|
---
|
|
124
139
|
|
|
140
|
+
## Executive Summary
|
|
141
|
+
- **Purpose:** [1 sentence — what this document covers and why it exists]
|
|
142
|
+
- **Implementation status:** [e.g. Not started / In progress / Matches UC Spec v{N}]
|
|
143
|
+
- **Key deviations from UC Spec:** [bullet list of Deviation-tagged items, or "None identified"]
|
|
144
|
+
- **Action needed from BA:** [bullet list of unresolved Gaps/Assumptions needing BA input, or "None — ready for Dev handoff"]
|
|
145
|
+
|
|
146
|
+
> This section alone should give PM/BA the full picture in about 30 seconds — everything below is supporting detail for BA/Tester/Dev.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
125
150
|
## 0. Traceability Matrix
|
|
126
151
|
| UC Reference (Flow / BR) | System Requirement Item(s) |
|
|
127
152
|
|---|---|
|
|
@@ -130,49 +155,95 @@ Save to `AK-Docs/02.BA-Specs/00.Requirements/[functionId]/System-Requirement_v{N
|
|
|
130
155
|
| BR1.1 | VR-01 |
|
|
131
156
|
|
|
132
157
|
## 1. Functional Requirements
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
158
|
+
|
|
159
|
+
Each item below is layered: **Requirement** (business language, for PM/BA) → **System Behavior** (for BA/Tester) → **Implementation Reference** (for Dev, technical detail only — never appears in the layers above it).
|
|
160
|
+
|
|
161
|
+
### FR-01: [short business-behavior title]
|
|
162
|
+
- **Requirement:** [system behavior in business language, no framework/class/method names]
|
|
163
|
+
- **System Behavior:** [how the system processes it — conditions, order of checks]
|
|
164
|
+
- **Traced UC Ref:** Main Flow #3
|
|
165
|
+
- **Classification:** [Gap | Assumption | Decision | Deviation — omit this line if it's a plain fact]
|
|
166
|
+
- **Implementation Reference:** [file:line / class / method]
|
|
167
|
+
|
|
168
|
+
<!-- repeat FR-02, FR-03, ... in the same block format -->
|
|
136
169
|
|
|
137
170
|
## 2. Non-Functional Requirements
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
171
|
+
|
|
172
|
+
### NFR-01: [short title]
|
|
173
|
+
- **Requirement:** [business language — e.g. performance/security expectation]
|
|
174
|
+
- **System Behavior:** [how it's enforced, in plain language]
|
|
175
|
+
- **Traced UC Ref:** BR3.1
|
|
176
|
+
- **Classification:** [Gap | Assumption | Decision | Deviation — omit if plain fact]
|
|
177
|
+
- **Implementation Reference:** [file:line / class / method]
|
|
141
178
|
|
|
142
179
|
## 3. Business Rules → Validation Rules
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
180
|
+
|
|
181
|
+
### VR-01: [short title]
|
|
182
|
+
- **Requirement:** [e.g. "Tag name must be unique among active Tags."]
|
|
183
|
+
- **System Behavior:** [e.g. "The system checks the Tag name against all active Tags before saving."]
|
|
184
|
+
- **Error Response:** HTTP 422 (Validation Error) — "[user-facing message]"
|
|
185
|
+
- **Traced UC BR:** BR1.1
|
|
186
|
+
- **Classification:** [Gap | Assumption | Decision | Deviation — omit if plain fact]
|
|
187
|
+
- **Implementation Reference:** [e.g. `Rule::unique(...)` in `StoreTagRequest`]
|
|
146
188
|
|
|
147
189
|
## 4. Exception & Error Handling
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
190
|
+
|
|
191
|
+
### ER-01: [trigger condition, in business language]
|
|
192
|
+
- **Requirement:** [e.g. "Only users with CREATE permission can create Tags."]
|
|
193
|
+
- **System Behavior:** [e.g. "The request is rejected because the caller lacks the required permission."]
|
|
194
|
+
- **Error Response:** HTTP 403 (Forbidden) — "[user-facing message]"
|
|
195
|
+
- **Traced Exception Flow:** Exception Flow B
|
|
196
|
+
- **Classification:** [Gap | Assumption | Decision | Deviation — omit if plain fact]
|
|
197
|
+
- **Implementation Reference:** [existing error code/class/middleware]
|
|
151
198
|
|
|
152
199
|
## 5. Acceptance Test Scenarios
|
|
153
200
|
### AT-01: [Scenario] (Main Flow)
|
|
154
201
|
- **Given** ...
|
|
155
202
|
- **When** ...
|
|
156
203
|
- **Then** ...
|
|
204
|
+
- **Requirement Coverage:** FR-01, FR-03
|
|
157
205
|
|
|
158
206
|
### AT-02: [Scenario] (Exception Flow B)
|
|
159
|
-
...
|
|
207
|
+
- **Given** ...
|
|
208
|
+
- **When** ...
|
|
209
|
+
- **Then** ...
|
|
210
|
+
- **Requirement Coverage:** VR-01, ER-01
|
|
160
211
|
|
|
161
212
|
## 6. Existing System Context
|
|
162
|
-
### Related Modules / Files
|
|
163
|
-
| File | Role | Current Behavior |
|
|
164
|
-
|---|---|---|
|
|
165
213
|
|
|
166
|
-
###
|
|
167
|
-
|
|
214
|
+
### 6.1 System Areas Summary
|
|
215
|
+
Summary only — deeper implementation detail belongs in each item's **Implementation Reference** above, not here.
|
|
216
|
+
|
|
217
|
+
| Area | Summary |
|
|
218
|
+
|---|---|
|
|
219
|
+
| API | ... |
|
|
220
|
+
| Model | ... |
|
|
221
|
+
| Validation | ... |
|
|
222
|
+
| Migration | ... |
|
|
223
|
+
| Test | ... |
|
|
224
|
+
|
|
225
|
+
### 6.2 Glossary / Term Mapping
|
|
226
|
+
Every `Tech Reference:` used in Sections 1–4 gets one row here — a single place to look up what a business term maps to in code, instead of hunting through every item. Only include terms with a BA-confirmed business meaning (Decision) or the BA-unconfirmed raw value tagged accordingly — never a guessed meaning.
|
|
227
|
+
|
|
228
|
+
| Business Term | Technical Reference | Classification |
|
|
168
229
|
|---|---|---|
|
|
230
|
+
| [e.g. "default status PENDING"] | `TagStatusEnum::PENDING` | Decision (BA-confirmed [date]) / Assumption (unconfirmed) |
|
|
231
|
+
|
|
232
|
+
### 6.3 External System Interfaces *(optional — include only if this UC integrates with a system outside the app's own UI/DB, e.g. third-party API, webhook, message queue)*
|
|
233
|
+
The UC Spec describes UI/business flow, not external integration contracts — capture those here when they exist. Omit this subsection entirely if the UC has no external interface.
|
|
234
|
+
|
|
235
|
+
| Interface | Direction | Protocol/Format | Note |
|
|
236
|
+
|---|---|---|---|
|
|
237
|
+
| [e.g. Payment Gateway API] | Outbound | REST/JSON | ... |
|
|
238
|
+
|
|
239
|
+
## 7. Assumptions / Gaps / Decisions / Deviations
|
|
240
|
+
Only items tagged Gap / Assumption / Decision / Deviation land here — a plain fact is the default, unmarked state of every item above and is not repeated in this table.
|
|
169
241
|
|
|
170
|
-
## 7. Facts / Assumptions / Gaps
|
|
171
242
|
| Type | Item | Resolution |
|
|
172
243
|
|---|---|---|
|
|
173
244
|
|
|
174
|
-
## 8.
|
|
175
|
-
[Question asked → answer received → date. Unresolved Gaps stay listed here, never silently dropped.]
|
|
245
|
+
## 8. Decision Log
|
|
246
|
+
[Question asked → decision/answer received → date. Unresolved Gaps stay listed here, never silently dropped. (Renamed from "Open Questions Log" — every entry here already has an answer; unresolved items are Gaps, tracked in Section 7.)]
|
|
176
247
|
|
|
177
248
|
## 9. Change Log
|
|
178
249
|
| Date | Ticket | Change | Note |
|
|
@@ -229,7 +300,7 @@ This does not bump `System-Requirement-Version` — the version stays tied to th
|
|
|
229
300
|
| Concern | Handled by |
|
|
230
301
|
|---|---|
|
|
231
302
|
| Source code investigation methodology | `read-study-requirement` Step 1 pattern (reused inline) / GitNexus MCP |
|
|
232
|
-
|
|
|
303
|
+
| Gap/Assumption/Decision/Deviation classification | This skill (inline, Step 3 — output-only convention, distinct from `read-study-requirement` Step 1.75's Fact/Assumption/Gap) |
|
|
233
304
|
| Q&A loop (one question at a time, no fabrication) | This skill (inline) |
|
|
234
305
|
| UC Spec structure/content | `skill-ba-uc-template-v1.md` (read-only reference, never edited by this skill) |
|
|
235
306
|
| Split decision | This skill (Step 5) |
|
|
@@ -250,3 +321,10 @@ This does not bump `System-Requirement-Version` — the version stays tied to th
|
|
|
250
321
|
- ✅ **MUST** investigate source code (Step 2) before drafting Exception/Error Handling or Existing System Context.
|
|
251
322
|
- ✅ **MUST** carry the mandatory `UC-Spec-Version` header on the master file.
|
|
252
323
|
- ✅ **MUST** surface a ⚠️ non-blocking warning (never a cancel) from the Gate 1 Pre-flight check until this skill reaches APPROVED.
|
|
324
|
+
- ✅ **MUST** write the `Requirement` and `System Behavior` layer of every FR/NFR/VR/ER item in business language — no framework, class, or method names (those belong only in `Implementation Reference`).
|
|
325
|
+
- ✅ **MUST** keep the HTTP status code in every `Error Response` line, paired with a friendly label and the user-facing message (e.g. `HTTP 422 (Validation Error) — "..."`) — never drop the code for readability.
|
|
326
|
+
- ✅ **MUST** tag each Acceptance Test with its `Requirement Coverage` (the FR/VR/ER IDs it exercises).
|
|
327
|
+
- ❌ **DO NOT** tag every item "Fact" — a plain fact is the unmarked default; only tag `Gap`, `Assumption`, `Decision`, or `Deviation` when one applies.
|
|
328
|
+
- ❌ **DO NOT** state or assume the business meaning of an enum/status value (e.g. what `PENDING` "means" for the business) unless the BA has confirmed it — reference the raw technical value in `Implementation Reference` and tag it `Assumption` or `Gap` until confirmed.
|
|
329
|
+
- ✅ **MUST** mirror every `Tech Reference:` used in Sections 1–4 as a row in Section 6.2 (Glossary / Term Mapping) — don't leave the mapping only inside individual items.
|
|
330
|
+
- ❌ **DO NOT** include Section 6.3 (External System Interfaces) when the UC has no integration outside the app's own UI/DB — omit the subsection entirely rather than leaving an empty table.
|
|
@@ -16,7 +16,7 @@ keywords: ingest data, comtor, brse, pm workflow, meeting minutes, qna log, conf
|
|
|
16
16
|
| Input | Cách xử lý |
|
|
17
17
|
|---|---|
|
|
18
18
|
| Backlog ticket link (`/view/PROJ-N`) hoặc comment (`#comment-N`) | `ak fetch-links "<url>"` → JSON `{ sourceType: "ticket" \| "comment", ... }` |
|
|
19
|
-
| Backlog Document link (`/document/{id}
|
|
19
|
+
| Backlog Document link (`/document/{id}`, `/alias/document/{id}`, hoặc share link mới `/document/{PROJECT_KEY}/e/{id}`) | `ak fetch-links "<url>"` → JSON `{ sourceType: "document" \| "document-comment", ... }`. Đã xác nhận hoạt động live (2026-08-06) cho document body (`title`/`content`). ⚠️ Fetch comment trên Document (`document-comment`) vẫn chưa xác minh trên space thật — nếu lệnh trả lỗi HTTP 404 hoặc `content` rỗng, báo lại cho người dùng, đây là dấu hiệu endpoint/field cần điều chỉnh, không phải lỗi ở phía bạn. |
|
|
20
20
|
| Backlog Wiki link (`/alias/wiki/{id}`) | `ak fetch-links "<url>"` → JSON `{ sourceType: "wiki", ... }` |
|
|
21
21
|
| Jira ticket/comment link | `ak fetch-links "<url>"` → JSON `{ sourceType: "ticket" \| "comment", ... }` |
|
|
22
22
|
| SharePoint link (`*.sharepoint.com`) | `ak fetch-links "<url>"` → `{ sourceType: "unsupported", reason: "sharepoint-not-configured" }`. **Không có connector** (cần Microsoft Graph API + OAuth, xem PM Workflow doc "Vấn đề 4" — chưa làm POC). Hiển thị `message` trong JSON cho người dùng, và đề nghị: "Paste trực tiếp nội dung comment/tài liệu vào chat, mình sẽ dùng luôn." |
|
|
@@ -130,7 +130,7 @@ Nếu người dùng yêu cầu sửa (thêm/bớt ý, đổi log đích, sửa
|
|
|
130
130
|
|
|
131
131
|
**Không phải mọi entry đều sinh ra task.** Trước khi đề xuất bất kỳ task nào, tự hỏi: nội dung này có yêu cầu một hành động cụ thể (thay đổi spec, code, test, tài liệu...) hay chỉ là thông tin tham khảo/FYI (cập nhật tiến độ, thông tin không đổi hành vi hệ thống, trả lời một câu hỏi đã đóng)?
|
|
132
132
|
|
|
133
|
-
- **Chỉ là tham khảo** → hiển thị: `ℹ️ Nội dung này không phát sinh task — chỉ lưu làm tài liệu tham khảo. Gate 3 kết thúc.` rồi dừng, không hỏi thêm
|
|
133
|
+
- **Chỉ là tham khảo** → hiển thị: `ℹ️ Nội dung này không phát sinh task — chỉ lưu làm tài liệu tham khảo. Gate 3 kết thúc.` rồi chạy `ak gate 3 skip --ticket [ticket-id] --reason "<1 câu lý do>"` (không cần `ak gate 3 start` trước) và dừng, không hỏi thêm. Việc này đóng gate đúng cách — dashboard (ai-flow-ex) hiển thị "⏭ Gate 3 skipped — \<lý do\>" thay vì để task treo mãi ở trạng thái "sẵn sàng chạy Gate 3".
|
|
134
134
|
- **Có hành động cụ thể** → tiếp tục Bước 3. Khi không chắc (ví dụ nội dung vừa có FYI vừa có 1 ý cần sửa code) — nghiêng về đề xuất task cho phần cần hành động, bỏ qua phần FYI, không tự bịa task cho phần không rõ.
|
|
135
135
|
|
|
136
136
|
### 5.3 Bước 3 — Đề xuất danh sách task
|
|
@@ -223,4 +223,4 @@ Check LOCAL trước, chỉ hỏi khi thật sự chưa biết (Vấn đề 5.1)
|
|
|
223
223
|
```
|
|
224
224
|
3. Run: `ak gate 3 approved --ticket [ticket-id]`.
|
|
225
225
|
|
|
226
|
-
> **Telemetry:** Run `ak gate 3 start --ticket [ticket-id]` khi bắt đầu Bước 1 (bỏ qua nếu Bước 2 kết luận không cần task — không start gate cho trường hợp "chỉ tham khảo"). Run `ak gate 3 approved --ticket [ticket-id]` khi Bước 8 xong.
|
|
226
|
+
> **Telemetry:** Run `ak gate 3 start --ticket [ticket-id]` khi bắt đầu Bước 1 (bỏ qua nếu Bước 2 kết luận không cần task — không start gate cho trường hợp "chỉ tham khảo"). Run `ak gate 3 approved --ticket [ticket-id]` khi Bước 8 xong, HOẶC `ak gate 3 skip --ticket [ticket-id] --reason "..."` khi Bước 2 kết luận không cần task (thay cho việc không đóng gate — xem Bước 2).
|
|
@@ -3,7 +3,29 @@
|
|
|
3
3
|
> **For:** `create-spec`
|
|
4
4
|
> **Persona:** Business Analyst (BA)
|
|
5
5
|
> **Goal:** Chuyển đổi yêu cầu thô (Jira / Backlog / file) thành tài liệu Đặc tả Use Case (UC Spec) hoàn chỉnh để bàn giao Dev/Test, tuân theo quy trình UCflow.
|
|
6
|
-
> **Interaction Rules:** Hỏi ONE câu hỏi tại một thời điểm — đợi BA trả lời trước khi tiếp tục. KHÔNG hỏi nhiều câu cùng lúc.
|
|
6
|
+
> **Interaction Rules:** Hỏi ONE câu hỏi tại một thời điểm — đợi BA trả lời trước khi tiếp tục. KHÔNG hỏi nhiều câu cùng lúc. Số lượng câu hỏi KHÔNG cố định — phải phản ánh đúng độ phức tạp thực tế của yêu cầu (xem chi tiết ở Gate 1 Bước 2).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
### Quy ước Blocking / Non-blocking & đánh dấu PENDING
|
|
11
|
+
|
|
12
|
+
> Áp dụng cho **cả 4 Gate** — dùng để quyết định câu hỏi nào bắt buộc phải Confirmed trước khi tiến gate tiếp theo, và câu nào được phép defer mà vẫn cho qua.
|
|
13
|
+
|
|
14
|
+
Mỗi Gap/Assumption/câu hỏi Q&A phải được gắn nhãn mức độ ảnh hưởng ngay khi phát hiện:
|
|
15
|
+
|
|
16
|
+
- **🔴 Blocking** — chưa trả lời thì KHÔNG thể tiến gate tiếp theo một cách đáng tin cậy. Gồm: ảnh hưởng cấu trúc dữ liệu (thêm/sửa field, quan hệ), luồng chính (happy path) của use case, phân quyền/bảo mật, hoặc quyết định kiến trúc khó đảo ngược sau khi đã code.
|
|
17
|
+
- **🟡 Non-blocking** — có thể tạm ghi Open (deferred) và vẫn đi tiếp. Gồm: chi tiết UI/text hiển thị, giá trị mặc định có thể chỉnh sau, alternative/exception flow hiếm gặp, câu hỏi cần chờ khách hàng xác nhận nhưng không chặn thiết kế các phần khác.
|
|
18
|
+
|
|
19
|
+
**Khi BA/khách hàng defer (chưa trả lời ngay) một câu hỏi:**
|
|
20
|
+
|
|
21
|
+
- 🟡 Non-blocking → đánh dấu **Open**, tiếp tục ngay sang câu hỏi kế tiếp hoặc gate kế tiếp — KHÔNG chặn.
|
|
22
|
+
- 🔴 Blocking → AI phải hiển thị cảnh báo rõ lý do đây là blocking + hệ quả nếu bỏ qua, rồi hỏi xác nhận BA có chắc muốn tiếp tục không. Nếu BA xác nhận đồng ý tiếp tục dù chưa trả lời → vẫn đánh dấu Open nhưng giữ nhãn 🔴 Blocking (không được hạ xuống Non-blocking) — mục "Điều kiện dừng chặn APPROVED" ở mỗi Gate dựa vào nhãn này.
|
|
23
|
+
|
|
24
|
+
**Đánh dấu PENDING trong tài liệu output:** bất kỳ nội dung nào phụ thuộc vào một câu hỏi còn Open (Blocking hoặc Non-blocking) phải ghi rõ marker tại đúng vị trí liên quan trong `Analysis_v(n).md` / `UI-Prototype` / `UC-Spec_v1.md`, thay vì tự suy diễn nội dung để lấp đầy:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
⚠️ [PENDING - QA-0N] <mô tả ngắn nội dung còn thiếu>
|
|
28
|
+
```
|
|
7
29
|
|
|
8
30
|
---
|
|
9
31
|
|
|
@@ -189,40 +211,48 @@ Nếu workspace mở dạng parent folder chứa cả `ak docs` lẫn source cod
|
|
|
189
211
|
- Xem xét các khía cạnh: validate dữ liệu, định dạng nhập liệu, phân quyền, xử lý ngoại lệ, thông báo lỗi
|
|
190
212
|
- Liệt kê **toàn bộ** Gap/Assumption tìm được — không chỉ những điểm "cốt yếu"
|
|
191
213
|
|
|
214
|
+
> ❌ **KHÔNG** tự giới hạn số câu hỏi theo một số cố định (ví dụ luôn dừng ở 5-6 câu) bất kể độ phức tạp của input. Số câu hỏi phải phản ánh đúng số Gap/Assumption thực sự tồn tại: yêu cầu đơn giản (1 field, 1 luồng) có thể chỉ cần 2-3 câu; yêu cầu phức tạp (nhiều actor, nhiều luồng, tích hợp hệ thống khác) có thể cần 15-20+ câu. Nếu trong lúc hỏi/nghe trả lời phát hiện thêm Gap mới, bổ sung ngay câu hỏi mới vào cuối vòng lặp — không đóng vòng lặp sớm chỉ vì đã hỏi "đủ nhiều".
|
|
215
|
+
|
|
216
|
+
**Phân loại mức ảnh hưởng:** trước khi hỏi, gắn nhãn mỗi Gap là 🔴 Blocking hoặc 🟡 Non-blocking theo [Quy ước Blocking / Non-blocking](#quy-ước-blocking--non-blocking--đánh-dấu-pending) ở đầu file.
|
|
217
|
+
|
|
192
218
|
**Vòng lặp hỏi-đáp:** Với từng Gap/Assumption trong danh sách, hỏi **ONE câu một lúc**, đợi BA trả lời trước khi hỏi câu tiếp theo:
|
|
193
219
|
|
|
194
220
|
- BA trả lời đủ rõ → đánh dấu **Confirmed**, tích hợp ngay vào bản phân tích đang xây dựng, chuyển sang câu hỏi tiếp theo
|
|
195
|
-
- BA trả lời "chưa biết" / "để hỏi lại [stakeholder]" / "chưa chốt được ngay"
|
|
196
|
-
-
|
|
221
|
+
- BA trả lời "chưa biết" / "để hỏi lại [stakeholder]" / "chưa chốt được ngay":
|
|
222
|
+
- 🟡 Non-blocking → đánh dấu **Open** (deferred), ghi chú lý do, chuyển ngay sang câu hỏi tiếp theo — KHÔNG chặn
|
|
223
|
+
- 🔴 Blocking → hiển thị cảnh báo lý do đây là blocking + hệ quả nếu bỏ qua, hỏi BA xác nhận có chắc muốn tiếp tục không; BA xác nhận → đánh dấu **Open** nhưng giữ nhãn 🔴 Blocking, vẫn chuyển sang câu tiếp theo
|
|
224
|
+
- Lặp lại cho tới khi **mọi** Gap/Assumption trong danh sách đã được hỏi (mỗi câu ở trạng thái Confirmed hoặc Open tường minh, kèm nhãn Blocking/Non-blocking)
|
|
197
225
|
|
|
198
|
-
Chỉ sau khi vòng lặp này hoàn tất (không còn Gap nào **chưa được hỏi**) mới chuyển sang Bước 3. Số lượng câu hỏi Open còn lại
|
|
226
|
+
Chỉ sau khi vòng lặp này hoàn tất (không còn Gap nào **chưa được hỏi**) mới chuyển sang Bước 3. Số lượng câu hỏi Open còn lại (và nhãn Blocking/Non-blocking của chúng) chính là input cho Gate 2.
|
|
199
227
|
|
|
200
228
|
#### Bước 3: Soạn thảo Kết quả phân tích sơ bộ
|
|
201
229
|
- **READ template:** `.claude/skills/ba-skills/skill-ba-initial-analysis-template-v1.md`
|
|
202
230
|
- Điền đầy đủ các mục theo template: Actors, Facts, Assumptions, Gap Analysis table — dùng câu trả lời **Confirmed** từ vòng lặp Bước 2 làm nội dung chính, không phải giả định của AI
|
|
203
|
-
- Gap Analysis table chỉ còn liệt kê các Gap **Open** (deferred) từ vòng lặp Bước 2
|
|
231
|
+
- Gap Analysis table chỉ còn liệt kê các Gap **Open** (deferred) từ vòng lặp Bước 2, kèm nhãn 🔴 Blocking / 🟡 Non-blocking
|
|
232
|
+
- Với mỗi Gap Open, chèn marker `⚠️ [PENDING - QA-0N]` tại đúng vị trí nội dung liên quan (mục 3/4 của template) thay vì bỏ trống hoặc tự suy diễn
|
|
233
|
+
- Nếu tài liệu còn ít nhất 1 Gap Open → thêm banner đầu tài liệu: `⚠️ TÀI LIỆU CHƯA ĐẦY ĐỦ — còn [N] câu hỏi Open ([X] Blocking, [Y] Non-blocking), xem QnA-Log_v1.md`
|
|
204
234
|
- Lưu: `02.BA-Specs/01.Analysis/[functionId]/Analysis_v1.md`
|
|
205
235
|
|
|
206
236
|
#### Bước 4: Soạn thảo danh sách Q&A
|
|
207
237
|
|
|
208
238
|
- **READ skill:** `.claude/skills/ba-skills/skill-ba-qna-v1.md`
|
|
209
239
|
- **READ template:** `.claude/skills/ba-skills/skill-ba-qna-template-v1.md`
|
|
210
|
-
- Ghi lại **toàn bộ** câu hỏi đã hỏi ở vòng lặp Bước 2 dưới dạng log: mỗi câu kèm câu trả lời và trạng thái cuối cùng
|
|
240
|
+
- Ghi lại **toàn bộ** câu hỏi đã hỏi ở vòng lặp Bước 2 dưới dạng log: mỗi câu kèm câu trả lời, nhãn Blocking/Non-blocking, và trạng thái cuối cùng
|
|
211
241
|
- **Confirmed** — BA đã trả lời trong Bước 2, ghi kèm câu trả lời
|
|
212
|
-
- **Open** — BA đã xác nhận chưa trả lời được ngay (cần hỏi lại stakeholder khác), ghi kèm lý do deferred
|
|
242
|
+
- **Open** — BA đã xác nhận chưa trả lời được ngay (cần hỏi lại stakeholder khác), ghi kèm lý do deferred + nhãn 🔴 Blocking hoặc 🟡 Non-blocking
|
|
213
243
|
- Không tạo câu hỏi mới ở bước này — đây là bản ghi (log) của vòng lặp đã chạy ở Bước 2, không phải một vòng hỏi mới
|
|
214
244
|
- Lưu: `02.BA-Specs/02.QnA/[functionId]/QnA-Log_v1.md`
|
|
215
245
|
|
|
216
246
|
#### Bước 5: Gate Review & Pause
|
|
217
247
|
- **INVOKE** `gate-review` skill (generate mode) — ghi `.aiflow/review/gate-1-[functionId].md`
|
|
218
|
-
- **Kiểm tra Q&A bắt buộc:** Đọc `QnA-Log_v1.md` — đếm số câu
|
|
248
|
+
- **Kiểm tra Q&A bắt buộc:** Đọc `QnA-Log_v1.md` — đếm số câu **Open**, tách riêng theo nhãn 🔴 Blocking và 🟡 Non-blocking
|
|
219
249
|
- Hiển thị gate pause message — chờ phản hồi từ BA
|
|
220
250
|
|
|
221
|
-
**Nếu
|
|
251
|
+
**Nếu còn câu Open 🔴 Blocking → từ chối APPROVED ngay, hiển thị:**
|
|
222
252
|
|
|
223
|
-
⛔ GATE 1 BLOCKED — Còn [N] câu hỏi chưa được trả lời trong QnA-Log_v1.md.
|
|
253
|
+
⛔ GATE 1 BLOCKED — Còn [N] câu hỏi Blocking chưa được trả lời trong QnA-Log_v1.md.
|
|
224
254
|
|
|
225
|
-
| ID | Câu hỏi còn Open |
|
|
255
|
+
| ID | Câu hỏi còn Open (Blocking) |
|
|
226
256
|
|----|-----------------|
|
|
227
257
|
| [Q_ID] | [nội dung câu hỏi] |
|
|
228
258
|
|
|
@@ -231,17 +261,26 @@ Vui lòng cung cấp câu trả lời theo một trong 3 cách:
|
|
|
231
261
|
→ Option B: paste nội dung bảng Q&A đã điền vào chat
|
|
232
262
|
→ Option C: đặt file `QnA-Log_v1_response.md` vào thư mục `02.QnA/[functionId]/` rồi gõ NEXT
|
|
233
263
|
|
|
234
|
-
❌ APPROVED không được chấp nhận cho đến khi
|
|
264
|
+
❌ APPROVED không được chấp nhận cho đến khi mọi câu hỏi **Blocking** đã Confirmed.
|
|
235
265
|
|
|
236
|
-
**
|
|
266
|
+
**Nếu chỉ còn câu Open 🟡 Non-blocking (không còn Blocking) → cho phép APPROVED, nhưng hiển thị cảnh báo ngay trong gate pause message trước khi BA gõ APPROVED:**
|
|
267
|
+
|
|
268
|
+
⚠️ Còn [N] câu hỏi Non-blocking chưa Confirmed — có thể APPROVED để tiếp tục, tài liệu sẽ giữ marker `[PENDING - QA-0N]` tại các phần liên quan cho tới khi được bổ sung ở Gate 2.
|
|
269
|
+
|
|
270
|
+
| ID | Câu hỏi còn Open (Non-blocking) |
|
|
271
|
+
|----|-----------------|
|
|
272
|
+
| [Q_ID] | [nội dung câu hỏi] |
|
|
273
|
+
|
|
274
|
+
**Khi APPROVED (không còn câu Blocking Open — câu Non-blocking Open được phép tồn tại):**
|
|
237
275
|
→ **INVOKE** `gate-review` skill (verify mode) — chạy `ak review check --gate 1 --ticket [functionId]`
|
|
238
276
|
→ Nếu passed: `ak gate 1 approved --ticket [functionId]` → chuyển Gate 2
|
|
239
277
|
→ Nếu blocked: làm theo gate-review skill response protocol
|
|
240
278
|
|
|
241
279
|
**Definition of Done:**
|
|
242
280
|
- [ ] `functionId` đã được xác định và thư mục đầu ra đã sẵn sàng
|
|
243
|
-
- [ ] File `Analysis_v1.md` tạo đúng vị trí, cấu trúc đúng template, có bảng Gap Analysis
|
|
244
|
-
- [ ] File `QnA-Log_v1.md` có ít nhất 1 câu hỏi cho mỗi Gap,
|
|
281
|
+
- [ ] File `Analysis_v1.md` tạo đúng vị trí, cấu trúc đúng template, có bảng Gap Analysis, số Gap phản ánh đúng độ phức tạp thực tế (không bị gò về một số cố định)
|
|
282
|
+
- [ ] File `QnA-Log_v1.md` có ít nhất 1 câu hỏi cho mỗi Gap, mỗi câu có nhãn Blocking/Non-blocking rõ ràng
|
|
283
|
+
- [ ] Không còn câu hỏi 🔴 Blocking ở trạng thái Open
|
|
245
284
|
- [ ] Không có giả định nào được tự ý chốt thành Spec mà không đưa vào Q&A
|
|
246
285
|
|
|
247
286
|
> **Telemetry:** Run `ak gate 1 start --ticket [functionId]` khi bắt đầu gate này.
|
|
@@ -270,8 +309,8 @@ Vui lòng cung cấp câu trả lời theo một trong 3 cách:
|
|
|
270
309
|
#### Bước 1: Tiếp nhận và đánh giá câu trả lời
|
|
271
310
|
- Đối chiếu từng câu trả lời với câu hỏi trong `QnA-Log_v(m).md`
|
|
272
311
|
- Phân loại:
|
|
273
|
-
- Đủ thông tin → cập nhật trạng thái: **Confirmed
|
|
274
|
-
- Chưa rõ hoặc phát sinh nghiệp vụ mới → giữ trạng thái **Open**, bổ sung ghi
|
|
312
|
+
- Đủ thông tin → cập nhật trạng thái: **Confirmed**, xóa marker `[PENDING - QA-ID]` liên quan
|
|
313
|
+
- Chưa rõ hoặc phát sinh nghiệp vụ mới → giữ trạng thái **Open**, bổ sung ghi chú, giữ nguyên nhãn 🔴 Blocking / 🟡 Non-blocking đã gắn từ Gate 1 (hoặc gắn mới nếu là Gap phát sinh)
|
|
275
314
|
|
|
276
315
|
#### Bước 2: Tích hợp thông tin vào tài liệu phân tích
|
|
277
316
|
- Lấy thông tin từ các câu Confirmed → cập nhật vào `Analysis_v(n).md`
|
|
@@ -280,7 +319,7 @@ Vui lòng cung cấp câu trả lời theo một trong 3 cách:
|
|
|
280
319
|
|
|
281
320
|
#### Bước 3: Rẽ nhánh theo trạng thái Q&A
|
|
282
321
|
|
|
283
|
-
**Kịch bản A —
|
|
322
|
+
**Kịch bản A — Còn câu hỏi Open 🔴 Blocking:**
|
|
284
323
|
1. Kiểm tra `Analysis_v(n+1).md` có phát sinh Gap mới không
|
|
285
324
|
2. Tạo: `02.BA-Specs/02.QnA/[functionId]/QnA-Log_v(m+1).md` — chỉ giữ câu Open và câu mới phát sinh
|
|
286
325
|
3. **INVOKE** `gate-review` skill (generate mode) — ghi `.aiflow/review/gate-2-[functionId]-round-[m+1].md`
|
|
@@ -289,7 +328,8 @@ Vui lòng cung cấp câu trả lời theo một trong 3 cách:
|
|
|
289
328
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
290
329
|
⏸️ GATE 2 — VÒNG Q&A [m+1]
|
|
291
330
|
|
|
292
|
-
Câu hỏi còn Open: [N]
|
|
331
|
+
Câu hỏi còn Open (🔴 Blocking): [N]
|
|
332
|
+
Câu hỏi còn Open (🟡 Non-blocking): [M]
|
|
293
333
|
File Q&A mới: [02.BA-Specs/02.QnA/[functionId]/QnA-Log_v(m+1).md](02.BA-Specs/02.QnA/[functionId]/QnA-Log_v(m+1).md)
|
|
294
334
|
File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md)
|
|
295
335
|
|
|
@@ -299,23 +339,40 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
299
339
|
|
|
300
340
|
5. Lặp lại Bước 1 khi nhận phản hồi mới
|
|
301
341
|
|
|
302
|
-
**Nếu BA gõ APPROVED khi đang ở Kịch bản A (còn câu hỏi Open) → từ chối ngay:**
|
|
342
|
+
**Nếu BA gõ APPROVED khi đang ở Kịch bản A (còn câu hỏi Open 🔴 Blocking) → từ chối ngay:**
|
|
303
343
|
|
|
304
|
-
⛔ GATE 2 BLOCKED — Còn [N] câu hỏi chưa Confirmed.
|
|
344
|
+
⛔ GATE 2 BLOCKED — Còn [N] câu hỏi Blocking chưa Confirmed.
|
|
305
345
|
|
|
306
|
-
| ID | Câu hỏi còn Open |
|
|
346
|
+
| ID | Câu hỏi còn Open (Blocking) |
|
|
307
347
|
|----|-----------------|
|
|
308
348
|
| [Q_ID] | [nội dung câu hỏi] |
|
|
309
349
|
|
|
310
350
|
→ Cung cấp câu trả lời (Option A/B/C) rồi gõ NEXT để AI xử lý tiếp.
|
|
311
|
-
❌ APPROVED chỉ được chấp nhận khi
|
|
351
|
+
❌ APPROVED chỉ được chấp nhận khi mọi câu hỏi **Blocking** đã Confirmed.
|
|
352
|
+
|
|
353
|
+
**Kịch bản B — Chỉ còn câu hỏi Open 🟡 Non-blocking (không còn Blocking):**
|
|
354
|
+
|
|
355
|
+
1. Tạo `QnA-Log_v(m+1).md` như Kịch bản A (giữ câu Non-blocking Open + câu mới phát sinh)
|
|
356
|
+
2. Hiển thị cho BA 2 lựa chọn, không tự chọn thay:
|
|
357
|
+
|
|
358
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
359
|
+
⏸️ GATE 2 — CÒN [M] CÂU HỎI NON-BLOCKING CHƯA CONFIRMED
|
|
360
|
+
|
|
361
|
+
Các câu hỏi này không chặn thiết kế Gate 3/4, nhưng output sẽ giữ marker `[PENDING - QA-ID]` tại các phần liên quan cho tới khi được bổ sung.
|
|
362
|
+
|
|
363
|
+
→ Cách 1: cung cấp câu trả lời (Option A/B/C) rồi gõ NEXT để xử lý tiếp
|
|
364
|
+
→ Cách 2: gõ APPROVED để chấp nhận tiếp tục dù output chưa đầy đủ ở các mục này
|
|
365
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
366
|
+
|
|
367
|
+
1. BA gõ NEXT với phản hồi mới → lặp lại Bước 1
|
|
368
|
+
2. BA gõ APPROVED → coi là đã xác nhận chấp nhận output chưa đầy đủ, chuyển sang xử lý APPROVED bên dưới
|
|
312
369
|
|
|
313
|
-
**Kịch bản
|
|
370
|
+
**Kịch bản C — Tất cả đã Confirmed:**
|
|
314
371
|
1. Chốt tài liệu phân tích (phiên bản cuối cùng là đầu vào Gate 3)
|
|
315
372
|
2. **INVOKE** `gate-review` skill (generate mode) — ghi `.aiflow/review/gate-2-[functionId].md`
|
|
316
373
|
3. Hiển thị gate pause message — đợi **APPROVED**
|
|
317
374
|
|
|
318
|
-
**Khi APPROVED (
|
|
375
|
+
**Khi APPROVED (Kịch bản B hoặc C — không còn câu Blocking Open):**
|
|
319
376
|
→ **INVOKE** `gate-review` skill (verify mode) — chạy `ak review check --gate 2 --ticket [functionId]`
|
|
320
377
|
→ Nếu passed: `ak gate 2 approved --ticket [functionId]` → chuyển Gate 3
|
|
321
378
|
→ Nếu blocked: làm theo gate-review skill response protocol
|
|
@@ -323,7 +380,8 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
323
380
|
**Definition of Done:**
|
|
324
381
|
- [ ] Mọi câu trả lời đều được phân tích và phân loại trạng thái
|
|
325
382
|
- [ ] Tài liệu phân tích phiên bản mới tích hợp đầy đủ thông tin nghiệp vụ mới nhất
|
|
326
|
-
- [ ] Không còn câu hỏi
|
|
383
|
+
- [ ] Không còn câu hỏi 🔴 Blocking ở trạng thái Open trước khi tiến Gate 3
|
|
384
|
+
- [ ] Nếu còn câu 🟡 Non-blocking Open, BA đã xác nhận rõ ràng (gõ APPROVED sau khi thấy cảnh báo) và các mục liên quan trong Analysis đã có marker `[PENDING - QA-ID]`
|
|
327
385
|
|
|
328
386
|
> **Telemetry:** Run `ak gate 2 start --ticket [functionId]` khi bắt đầu gate này.
|
|
329
387
|
> Run `ak gate 2 approved --ticket [functionId]` sau khi gate-review verify passed. Run as-is — không thêm shell redirects.
|
|
@@ -334,7 +392,7 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
334
392
|
|
|
335
393
|
**Mục tiêu:** Dựa trên tài liệu phân tích đã chốt, thiết kế bản mẫu giao diện (Prototype) độc lập bằng HTML/CSS để trực quan hóa các thành phần và luồng tương tác.
|
|
336
394
|
|
|
337
|
-
**Điều kiện vào Gate 3:**
|
|
395
|
+
**Điều kiện vào Gate 3:** Không còn câu hỏi 🔴 Blocking Open và Gate 2 đã **APPROVED** (câu 🟡 Non-blocking Open, nếu còn, mang marker `[PENDING - QA-ID]` sang cùng Analysis).
|
|
338
396
|
|
|
339
397
|
**Đầu vào (Inputs):**
|
|
340
398
|
- `02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n).md` — phiên bản cuối
|
|
@@ -349,6 +407,7 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
349
407
|
#### Bước 1: Liệt kê thành phần giao diện
|
|
350
408
|
- Đọc tài liệu phân tích đã chốt
|
|
351
409
|
- Xác định: ô nhập liệu, nút bấm, liên kết, vùng hiển thị lỗi, vùng hiển thị dữ liệu
|
|
410
|
+
- Nếu Analysis còn marker `[PENDING - QA-ID]` liên quan đến thành phần giao diện nào → giữ nguyên placeholder trực quan cho thành phần đó (không tự bịa nội dung/behavior để lấp đầy) và ghi chú `<!-- PENDING - QA-ID -->` cạnh phần tử HTML tương ứng
|
|
352
411
|
|
|
353
412
|
#### Bước 2: Thiết kế và viết code HTML/CSS
|
|
354
413
|
- **READ skill:** `.claude/skills/ba-skills/skill-ba-prototype-v1.md` và làm theo
|
|
@@ -406,6 +465,7 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
406
465
|
- **READ skill:** `.claude/skills/ba-skills/skill-ba-write-uc-spec-v1.md`
|
|
407
466
|
- Tạo: `02.BA-Specs/04.UC-Specs/[functionId]/UC-Spec_v1.md`
|
|
408
467
|
- Điền General Information: Use Case ID, Title, Version, Actors, Preconditions, Postconditions
|
|
468
|
+
- Nếu Analysis/Prototype đầu vào còn marker `[PENDING - QA-ID]` (câu Non-blocking chưa Confirmed) → giữ nguyên marker tại đúng vị trí liên quan (Business Rule, UI Component, Flow step) trong UC Spec, không tự bịa nội dung để lấp đầy; thêm banner đầu tài liệu: `⚠️ UC SPEC CHƯA ĐẦY ĐỦ — còn [N] mục PENDING, xem QnA-Log_v(m).md`
|
|
409
469
|
|
|
410
470
|
#### Bước 2: Mô tả luồng sự kiện (Flow of Events)
|
|
411
471
|
- **Main Flow** — happy path
|
|
@@ -450,7 +510,7 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
450
510
|
- [ ] 100% element HTML được mô tả trong bảng UI Components (id, loại, ràng buộc)
|
|
451
511
|
- [ ] Mã Mermaid hợp lệ, thể hiện đủ Main/Alternative/Exception Flow
|
|
452
512
|
- [ ] Business Rules đầy đủ với mã `[BR-NNN]` và thông báo lỗi chính xác
|
|
453
|
-
- [ ]
|
|
513
|
+
- [ ] Không còn giả định ngầm chưa Confirm bị viết như thể đã chốt; mọi nội dung Non-blocking Open còn lại đã có marker `[PENDING - QA-ID]` rõ ràng tại đúng vị trí (không phải ghi chú mơ hồ chung)
|
|
454
514
|
|
|
455
515
|
> **Telemetry:** Run `ak gate 4 start --ticket [functionId]` khi bắt đầu gate này.
|
|
456
516
|
> Run `ak gate 4 approved --ticket [functionId]` sau khi gate-review verify passed. Run as-is — không thêm shell redirects.
|
|
@@ -497,9 +557,11 @@ Sau khi Gate 4 đã APPROVED (UC Spec hoàn thành):
|
|
|
497
557
|
- ❌ **KHÔNG** bỏ qua thứ tự Gate — luôn đi từ Gate 1 → 2 → 3 → 4
|
|
498
558
|
- ❌ **KHÔNG** tự chốt giả định nghiệp vụ mà không đưa vào Q&A
|
|
499
559
|
- ❌ **KHÔNG** dùng `superpowers:brainstorming` ở Gate 1 — terminal state của skill đó invoke `writing-plans`, bypass cấu trúc BA workflow
|
|
500
|
-
- ✅ **BẮT BUỘC** ở Gate 1 Bước 2: hỏi hết **toàn bộ** Gap/Assumption xác định được, từng câu một, ngay trong hội thoại — không giới hạn ở "điểm mơ hồ cốt yếu". Chỉ được ghi Open (deferred sang QnA-Log) khi BA xác nhận rõ ràng là chưa trả lời được ngay
|
|
501
|
-
-
|
|
502
|
-
- ❌ **KHÔNG
|
|
560
|
+
- ✅ **BẮT BUỘC** ở Gate 1 Bước 2: hỏi hết **toàn bộ** Gap/Assumption xác định được, từng câu một, ngay trong hội thoại — không giới hạn ở "điểm mơ hồ cốt yếu" và **không giới hạn theo một số câu hỏi cố định** bất kể độ phức tạp input. Chỉ được ghi Open (deferred sang QnA-Log) khi BA xác nhận rõ ràng là chưa trả lời được ngay
|
|
561
|
+
- ✅ **BẮT BUỘC** gắn nhãn 🔴 Blocking / 🟡 Non-blocking cho mỗi Gap/câu hỏi ngay khi phát hiện (xem [Quy ước Blocking / Non-blocking](#quy-ước-blocking--non-blocking--đánh-dấu-pending))
|
|
562
|
+
- ❌ **KHÔNG** tiến Gate 3 khi vẫn còn câu hỏi 🔴 Blocking ở trạng thái Open
|
|
563
|
+
- ❌ **KHÔNG chấp nhận APPROVED** ở Gate 1 hoặc Gate 2 khi còn bất kỳ câu hỏi 🔴 **Blocking** nào ở trạng thái **Open** — từ chối và hiển thị danh sách câu hỏi cần trả lời
|
|
564
|
+
- ✅ **ĐƯỢC PHÉP chấp nhận APPROVED** ở Gate 1/2/4 khi chỉ còn câu hỏi 🟡 **Non-blocking** Open, với điều kiện: đã hiển thị cảnh báo rõ ràng cho BA trước khi nhận APPROVED, và mọi nội dung phụ thuộc câu hỏi đó được đánh dấu `[PENDING - QA-ID]` tại đúng vị trí trong output — không được tự suy diễn nội dung để lấp đầy
|
|
503
565
|
- ✅ **BẮT BUỘC** chạy Bước 0 ở Gate 1 — xác nhận `functionId` và thư mục đầu ra trước khi làm bất cứ điều gì
|
|
504
566
|
- ✅ **BẮT BUỘC** chạy Bước 0.5 ở Gate 1 — đảm bảo AK-Docs đang ở branch `feature/[functionId]/[taskId]` trước khi ghi file đầu tiên
|
|
505
567
|
- ✅ **BẮT BUỘC** đọc skill từ `.claude/skills/ba-skills/` — không suy luận từ bộ nhớ
|
|
@@ -725,7 +725,7 @@ Bugs logged: [N] | Skipped: [N]
|
|
|
725
725
|
> Implements "Vấn đề 5" trong `docs/internal/PM Workflow_v1.0.md`. **Không chờ APPROVED để bắt đầu** — chạy tự động ngay sau Gate 2 Bước 7, không cần lệnh riêng và không cần chờ PM merge MR (merge là việc độc lập của PM). `INVOKE`: `ingest-data` skill § 5 cho toàn bộ logic phân tích/đề xuất — mục này chỉ nêu gate mechanics.
|
|
726
726
|
|
|
727
727
|
1. Đọc lại entry vừa ghi + điều tra source/docs liên quan (skill § 5.1).
|
|
728
|
-
2. Quyết định content này có cần task không (skill § 5.2). Nếu KHÔNG cần task → hiển thị thông báo tương ứng
|
|
728
|
+
2. Quyết định content này có cần task không (skill § 5.2). Nếu KHÔNG cần task → hiển thị thông báo tương ứng, chạy `ak gate 3 skip --ticket [ticket-id] --reason "<1 câu lý do>"` (không chạy `ak gate 3 start`), và **kết thúc luôn, không có Gate 3 Display**. `skip` vẫn đóng gate đúng cách (advance `currentGate` giống `approved`) — task hiện đúng "done" trên dashboard, không treo ở trạng thái "sẵn sàng chạy Gate 3" mãi.
|
|
729
729
|
3. Nếu CẦN task → chạy `ak gate 3 start --ticket [ticket-id]`, rồi đề xuất danh sách task (skill § 5.3), cho PM sửa/thêm/xoá (skill § 5.4), lặp tới khi PM hài lòng.
|
|
730
730
|
4. Điểm dừng xác nhận trước khi tạo ticket (skill § 5.5) — ❌ không tự thêm `--yes`, phải có xác nhận rõ ràng trong hội thoại.
|
|
731
731
|
5. Xác định project đích trên Backlog/Jira (skill § 5.6, dùng `ak backlog-projects`/`ak jira-projects` + `ak backlog-set-default-project`/`ak jira-set-default-project`).
|
|
@@ -733,4 +733,4 @@ Bugs logged: [N] | Skipped: [N]
|
|
|
733
733
|
7. Ghi ngược link ticket vào entry gốc + hiển thị tổng kết (skill § 5.8).
|
|
734
734
|
8. Run: `ak gate 3 approved --ticket [ticket-id]` để đóng task.
|
|
735
735
|
|
|
736
|
-
> **Telemetry:** Run `ak gate 3 start --ticket [ticket-id]` chỉ khi Bước 2 kết luận CẦN task. Run `ak gate 3 approved --ticket [ticket-id]` khi Gate 3 hoàn tất.
|
|
736
|
+
> **Telemetry:** Run `ak gate 3 start --ticket [ticket-id]` chỉ khi Bước 2 kết luận CẦN task. Run `ak gate 3 approved --ticket [ticket-id]` khi Gate 3 hoàn tất, hoặc `ak gate 3 skip --ticket [ticket-id] --reason "..."` khi Bước 2 kết luận KHÔNG cần task.
|
package/docs/common/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.2.2] - 2026-08-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`ak gate <n> skip --ticket <id> [--reason <text>]`** — a gate can now close as "skipped" (legitimately produced no deliverable) instead of only `start`/`approved`. First consumer: `ingest-data` Gate 3, when the AI decides the ingested content is reference-only and no task list is needed — it now runs `ak gate 3 skip` instead of leaving the gate untouched. `scripts/task.js`'s `updateTaskGateState()` gained a `skip` branch that records `skippedGates[gate] = {at, reason}` in `task-state.json` and advances `currentGate` exactly like `approved` does, so every existing "is this task done" check (which only ever inspects `currentGate`) keeps working with zero changes. Prompted by an impact assessment for the `ai-flow-ex` VS Code extension's dashboard, which was showing skipped-Gate-3 ingest-data tasks stuck as "ready to run Gate 3" forever — see `docs/superpowers/specs/2026-08-06-ingest-data-gate3-skipped-state-design.md` in `ai-flow-ex` for the paired UI-side change (reads `skippedGates` to render a distinct "⏭ Skipped" badge instead of the generic "✓ Approved").
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **`ak task next` treated `ingest-data` as a 2-gate flow** — a stale assumption left over from before Gate 3 (task creation & ticket generation) was added to `ingest-data` earlier in the same release cycle. `scripts/task.js` grouped it with `gen-doc`/`create-system-requirement` (`maxGate = 2`), so pausing via `ak task next` on Gate 2 would prematurely mark the task `status: 'done'` and `gateLabel(3, 'ingest-data')` returned `'Done'` instead of `'Sinh Task & Tạo Ticket'`. Split into its own 3-gate branch (`maxGate = 3`); `gen-doc`/`create-system-requirement` are unaffected.
|
|
19
|
+
|
|
10
20
|
## [0.2.1] - 2026-08-05
|
|
11
21
|
|
|
12
22
|
### Added
|
package/package.json
CHANGED
package/scripts/link-resolver.js
CHANGED
|
@@ -3,9 +3,13 @@ const https = require('https');
|
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
|
|
5
5
|
const BACKLOG_RE = /https?:\/\/([\w.-]+\.backlog(?:tool)?\.com)\/view\/([A-Z][A-Z0-9_]+-\d+)(?:#comment-(\d+))?/i;
|
|
6
|
-
// Backlog Document permalink — "Copy link" on a Document page gives /alias/document/{id}
|
|
7
|
-
//
|
|
8
|
-
|
|
6
|
+
// Backlog Document permalink — "Copy link" on a Document page gives /alias/document/{id},
|
|
7
|
+
// where {id} is Nulab's hex document ID (e.g. 0193b335c62173de9547bab5dd0b5324), not numeric.
|
|
8
|
+
// Newer "Share link" format adds a project-key + /e/ prefix: /document/{PROJECT_KEY}/e/{id}.
|
|
9
|
+
// Confirmed live against a real space (2026-08-06): GET /api/v2/documents/{id} returns the
|
|
10
|
+
// body as `plain` (not `plainText`/`content`) — see fetchBacklogDocument below.
|
|
11
|
+
// Comment fetch (fetchBacklogDocumentComment) is still unverified — adjust its field names if it 404s or returns empty content.
|
|
12
|
+
const BACKLOG_DOCUMENT_RE = /https?:\/\/([\w.-]+\.backlog(?:tool)?\.com)\/(?:alias\/)?document\/(?:[A-Z][A-Z0-9_]*\/e\/)?([0-9a-f]+)(?:#comment-(\d+))?/i;
|
|
9
13
|
// Backlog Wiki permalink — "Copy link" on a Wiki page gives /alias/wiki/{id}.
|
|
10
14
|
const BACKLOG_WIKI_RE = /https?:\/\/([\w.-]+\.backlog(?:tool)?\.com)\/alias\/wiki\/(\d+)/i;
|
|
11
15
|
const JIRA_RE = /https?:\/\/([\w.-]+\.atlassian\.net)\/browse\/([A-Z][A-Z0-9_]+-\d+)/i;
|
|
@@ -150,7 +154,7 @@ async function fetchBacklogDocument(domain, apiKey, documentId) {
|
|
|
150
154
|
documentId: String(documentId),
|
|
151
155
|
title: doc.title || doc.name || '',
|
|
152
156
|
tag: (doc.tags || []).map(t => t.name).join(', '),
|
|
153
|
-
content: (doc.plainText || doc.content || '').substring(0, 4000),
|
|
157
|
+
content: (doc.plain || doc.plainText || doc.content || '').substring(0, 4000),
|
|
154
158
|
};
|
|
155
159
|
}
|
|
156
160
|
|
package/scripts/task.js
CHANGED
|
@@ -345,8 +345,9 @@ async function nextGate(taskId) {
|
|
|
345
345
|
const isGenDoc = taskType === 'gen-doc';
|
|
346
346
|
const isSystemRequirement = taskType === 'create-system-requirement';
|
|
347
347
|
const isIngestData = taskType === 'ingest-data';
|
|
348
|
-
const isTwoGateDoc = isGenDoc || isSystemRequirement
|
|
349
|
-
const
|
|
348
|
+
const isTwoGateDoc = isGenDoc || isSystemRequirement;
|
|
349
|
+
const isDocFlow = isTwoGateDoc || isIngestData;
|
|
350
|
+
const maxGate = isTwoGateDoc ? 2 : isIngestData ? 3 : 5;
|
|
350
351
|
|
|
351
352
|
const taskState = {
|
|
352
353
|
...existing,
|
|
@@ -371,7 +372,7 @@ async function nextGate(taskId) {
|
|
|
371
372
|
console.log(chalk.green(`✓ Gate ${currentGate} approved for ${resolvedId}.`));
|
|
372
373
|
console.log(chalk.gray(` Summary saved to: .aiflow/tasks/${resolvedId}/task-summary.md`));
|
|
373
374
|
|
|
374
|
-
if (
|
|
375
|
+
if (isDocFlow && currentGate >= maxGate) {
|
|
375
376
|
console.log(chalk.green('\n ✅ Document workflow complete. Task is done.'));
|
|
376
377
|
} else {
|
|
377
378
|
const nextLabel = gateLabel(nextGateNum, taskType);
|
|
@@ -380,7 +381,7 @@ async function nextGate(taskId) {
|
|
|
380
381
|
console.log(chalk.gray(` 1. Open a NEW chatbox or terminal session.`));
|
|
381
382
|
console.log(chalk.gray(` 2. Run: aiflow task resume ${resolvedId} (to load context).`));
|
|
382
383
|
console.log(chalk.gray(` 3. Type "start" or "continue from the current plan".`));
|
|
383
|
-
if (!
|
|
384
|
+
if (!isDocFlow) {
|
|
384
385
|
console.log(chalk.yellow(` (Note: Gate 3 progress is saved via [x] checkboxes in the Gate 2 plan doc (AK-Docs/04.Coding/02.Plans/).`));
|
|
385
386
|
console.log(chalk.yellow(` The AI will automatically resume the exact task you left off.)`));
|
|
386
387
|
}
|
|
@@ -485,7 +486,10 @@ async function detectCurrentGate(taskId) {
|
|
|
485
486
|
|
|
486
487
|
async function generateMarkdownSummary(taskState, taskType = null) {
|
|
487
488
|
taskType = taskType || taskState.taskType || 'feature';
|
|
488
|
-
const maxGate = taskType === 'testing' ? 4
|
|
489
|
+
const maxGate = taskType === 'testing' ? 4
|
|
490
|
+
: taskType === 'ingest-data' ? 3
|
|
491
|
+
: (taskType === 'gen-doc' || taskType === 'create-system-requirement') ? 2
|
|
492
|
+
: 5;
|
|
489
493
|
const lines = [];
|
|
490
494
|
lines.push(`# Task Summary: ${taskState.taskId}`);
|
|
491
495
|
lines.push(`**Title:** ${taskState.title}`);
|
|
@@ -531,7 +535,8 @@ function gateLabel(n, taskType = null) {
|
|
|
531
535
|
if (taskType === 'ingest-data') {
|
|
532
536
|
if (n === 1) return 'Fetch, Classify, Draft';
|
|
533
537
|
if (n === 2) return 'Branch + Merge Request';
|
|
534
|
-
if (n
|
|
538
|
+
if (n === 3) return 'Sinh Task & Tạo Ticket';
|
|
539
|
+
if (n >= 4) return 'Done';
|
|
535
540
|
}
|
|
536
541
|
const labels = {
|
|
537
542
|
1: 'AI Analyze Requirement',
|
|
@@ -599,15 +604,19 @@ module.exports.createOrActivateTaskState = async function createOrActivateTaskSt
|
|
|
599
604
|
};
|
|
600
605
|
|
|
601
606
|
/**
|
|
602
|
-
* Called by `aiflow gate <N> <start|approved>` to keep task-state.json in sync
|
|
607
|
+
* Called by `aiflow gate <N> <start|approved|skip>` to keep task-state.json in sync
|
|
603
608
|
* with the actual gate progress — without requiring the user to run `task next`.
|
|
604
609
|
*
|
|
605
610
|
* - 'start' : advances currentGate to N (if N is higher than stored value)
|
|
606
611
|
* - 'approved': records approval timestamp + advances currentGate to N+1
|
|
612
|
+
* - 'skip' : records a skip (gate legitimately produced no deliverable, e.g.
|
|
613
|
+
* ingest-data Gate 3 deciding no task is needed) + advances currentGate
|
|
614
|
+
* to N+1, same as 'approved' — every "is this task done" check only ever
|
|
615
|
+
* inspects `currentGate`, so a skipped gate still lets the task complete.
|
|
607
616
|
*
|
|
608
617
|
* Silently no-ops when task-state.json does not exist yet (task not saved).
|
|
609
618
|
*/
|
|
610
|
-
module.exports.updateTaskGateState = async function updateTaskGateState(ticketId, gateNum, action) {
|
|
619
|
+
module.exports.updateTaskGateState = async function updateTaskGateState(ticketId, gateNum, action, options = {}) {
|
|
611
620
|
if (!ticketId) return;
|
|
612
621
|
const taskDir = path.join(TASKS_DIR, ticketId);
|
|
613
622
|
const statePath = path.join(taskDir, 'task-state.json');
|
|
@@ -633,6 +642,14 @@ module.exports.updateTaskGateState = async function updateTaskGateState(ticketId
|
|
|
633
642
|
if (gateNum >= (existing.currentGate || 1)) {
|
|
634
643
|
updated.currentGate = gateNum + 1;
|
|
635
644
|
}
|
|
645
|
+
} else if (action === 'skip') {
|
|
646
|
+
const skippedGates = { ...(existing.skippedGates || {}) };
|
|
647
|
+
skippedGates[String(gateNum)] = { at: now, reason: options.reason || '' };
|
|
648
|
+
updated.skippedGates = skippedGates;
|
|
649
|
+
// Advance currentGate to next gate (only if not already ahead) — same as 'approved'
|
|
650
|
+
if (gateNum >= (existing.currentGate || 1)) {
|
|
651
|
+
updated.currentGate = gateNum + 1;
|
|
652
|
+
}
|
|
636
653
|
}
|
|
637
654
|
|
|
638
655
|
await fs.writeJson(statePath, updated, { spaces: 2 });
|