@relipa/ai-flow-kit 0.1.9 → 0.2.0-beta.0
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/README.md +65 -0
- package/bin/aiflow.js +18 -4
- package/custom/rules/project-conventions.md +16 -0
- package/custom/skills/create-system-requirement/SKILL.md +248 -0
- package/custom/skills/ingest-data/SKILL.md +112 -0
- package/custom/skills/read-study-requirement/SKILL.md +35 -2
- package/custom/templates/shared/gate-workflow.md +49 -0
- package/docs/common/BA-Specs-Structure.md +3 -0
- package/docs/common/CHANGELOG.md +26 -0
- package/docs/common/Docs-Management-Flow.md +1 -1
- package/docs/common/INDEX.md +1 -0
- package/docs/common/Memory-Architecture-v1.0.md +1 -0
- package/docs/common/Project-Structure.md +5 -2
- package/package.json +1 -1
- package/scripts/detect.js +22 -0
- package/scripts/hooks/session-start.js +1 -0
- package/scripts/link-resolver.js +101 -7
- package/scripts/prompt.js +144 -0
- package/scripts/task.js +22 -6
- package/scripts/use.js +261 -135
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
> **Do not skip, shorten, or merge Gates.**
|
|
5
5
|
|
|
6
6
|
> **Task type `gen-doc`** uses a **2-gate flow** (Gate 1 + Gate 2 only). See the gen-doc section below — do NOT run Gates 3/4/5 for gen-doc tasks.
|
|
7
|
+
> **Task type `ingest-data`** also uses a **2-gate flow** — see the ingest-data section below. For PM/BrSE/Comtor ingesting customer communication (Backlog ticket/comment/Document/Wiki link, SharePoint link, or pasted text) into `AK-Docs/01.QnA/`.
|
|
7
8
|
|
|
8
9
|
You have superpowers. When a ticket context exists in `.aiflow/context/current.json`:
|
|
9
10
|
- **Consult the "AI Skill Registry"** below to find instructions for each skill (`SKILL.md`).
|
|
@@ -40,6 +41,7 @@ Read `.aiflow/context/current.json` → check the `taskType` field:
|
|
|
40
41
|
| `feature`, `bug-fix`, `refactor`, `investigation`, `documentation` | **[DEV] 5-Gate Development Workflow** (below) |
|
|
41
42
|
| `create-spec` | **[BA] 4-Gate Spec Creation Workflow** (below) |
|
|
42
43
|
| `create-testcase` | **[QA] 4-Gate TestCase Creation Workflow** (below) |
|
|
44
|
+
| `ingest-data` | **[COMTOR] Ingest Data — 2-Gate Flow** (below) |
|
|
43
45
|
|
|
44
46
|
If `taskType` is missing or unrecognized, default to the DEV workflow and ask ONE clarifying question.
|
|
45
47
|
|
|
@@ -670,3 +672,50 @@ Bugs logged: [N] | Skipped: [N]
|
|
|
670
672
|
8. Display: `GATE 2 DONE: Document generated at [path]`
|
|
671
673
|
|
|
672
674
|
**Do NOT wait for extra approval before generating the document or opening the MR — only the explicit branch/MR confirmations above gate this; run the gate 2 approved command immediately after.**
|
|
675
|
+
|
|
676
|
+
---
|
|
677
|
+
|
|
678
|
+
## ingest-data Task Type — 2-Gate Flow
|
|
679
|
+
|
|
680
|
+
> This section applies **only** when `taskType === "ingest-data"`. All other task types use the flows above.
|
|
681
|
+
> **For:** PM · BrSE · Comtor ingesting customer communication into `AK-Docs/01.QnA/` — see `docs/internal/PM Workflow_v1.0.md` Flow B for the full design background.
|
|
682
|
+
> **Input formats accepted:** Backlog ticket/comment link, Backlog Document link, Backlog Wiki link, Jira ticket/comment link, SharePoint link (not yet connected — see Gate 1 Step 2), or plain pasted text.
|
|
683
|
+
|
|
684
|
+
**INVOKE:** `ingest-data` skill (from `.claude/skills/ingest-data/SKILL.md`) for both gates — it has the full classification rules, draft templates, and per-file format. This section only covers the gate mechanics.
|
|
685
|
+
|
|
686
|
+
### GATE 1 — Fetch, Classify, Draft (auto-start)
|
|
687
|
+
|
|
688
|
+
0. **Pre-flight (bắt buộc):** chạy [Pre-flight — Đồng bộ Source & Docs](#pre-flight-bắt-buộc--đồng-bộ-source--docs-đầu-mỗi-gate) ở đầu file. Lỗi → hiển thị ⚠️ cảnh báo, không dừng gate.
|
|
689
|
+
1. Read `.aiflow/context/current.json` — if the primary input is a URL (Backlog/Jira/SharePoint), it's already there as `taskId`/description; if the input was plain pasted text via `ak use --manual`, it's in `description`.
|
|
690
|
+
2. **Resolve the source** (see `ingest-data` skill for full detail):
|
|
691
|
+
- Backlog/Jira ticket, comment, Document, or Wiki URL → run `ak fetch-links "<url>"`, parse the JSON.
|
|
692
|
+
- SharePoint URL → `ak fetch-links` returns `{ sourceType: "unsupported" }` (no connector yet — Microsoft Graph API/OAuth not built). Tell the user to paste the comment/document text directly instead of the link.
|
|
693
|
+
- Plain text → use as-is, no fetch needed.
|
|
694
|
+
3. **Classify** into `QnA-Log.md` / `Meetings-Log.md` / `Confirmations-Log.md` per the `ingest-data` skill's rules. If ambiguous (especially Confirmations — the rule for "official confirm" vs "regular feedback" is not yet finalized, see PM Workflow doc Vấn đề còn mở #1) — **ask the user**, do not guess silently.
|
|
695
|
+
4. Draft the entry using the exact template for the target log file (skill has all 3 templates) — include the trace fields (`Nguồn`, `functionId`, `Người tổng hợp`, `Người approve tại nguồn`).
|
|
696
|
+
5. Display the draft in full (not summarized) plus this footer:
|
|
697
|
+
```
|
|
698
|
+
⏸️ INGEST DRAFT READY — cần bạn review trước khi mở MR
|
|
699
|
+
|
|
700
|
+
Nguồn: [mô tả ngắn](url hoặc "pasted text")
|
|
701
|
+
Ghi vào: AK-Docs/01.QnA/[QnA-Log.md | Meetings-Log.md | Confirmations-Log.md]
|
|
702
|
+
|
|
703
|
+
→ Xem draft đầy đủ ở trên
|
|
704
|
+
→ Gõ APPROVED để tạo branch + MR (Gate 2)
|
|
705
|
+
→ Hoặc yêu cầu sửa trực tiếp draft, AI sẽ cập nhật lại rồi hiển thị lại
|
|
706
|
+
```
|
|
707
|
+
6. Loop on edits until the user types **APPROVED** — do not proceed to Gate 2 before that.
|
|
708
|
+
|
|
709
|
+
> **Telemetry:** Run `ak gate 1 start --ticket [ticket-id]` when starting. Run `ak gate 1 approved --ticket [ticket-id]` when APPROVED is received.
|
|
710
|
+
|
|
711
|
+
### GATE 2 — Branch + Merge Request (runs immediately after APPROVED)
|
|
712
|
+
|
|
713
|
+
1. Xác định `functionId`: tag đọc được từ Backlog Document (nếu có) → suy từ input → không suy được thì dùng `general` (theo đúng quy ước `custom/rules/project-conventions.md`, tương tự gen-doc dùng `AD-HOC`).
|
|
714
|
+
2. Kiểm tra `AK-Docs` hiện đang ở branch nào (`git -C AK-Docs branch --show-current`). Nếu chưa ở `feature/[functionId]/[ticketId]` → hỏi: "Chưa có branch riêng cho task này. Tạo branch `feature/[functionId]/[ticketId]` từ `main` — đồng ý không?" → đồng ý thì chạy `ak docs branch [functionId] [ticketId] --yes`; từ chối thì tiếp tục trên nhánh hiện tại. ❌ Không tự thêm `--yes` khi chưa thấy xác nhận rõ ràng.
|
|
715
|
+
3. Ghi/append entry đã approve vào đúng file log (tạo file + header template nếu chưa tồn tại).
|
|
716
|
+
4. Soạn title + description cho MR (tóm tắt entry vừa ghi, link nguồn gốc), hiển thị cho người dùng xem trước. Hỏi: "Nội dung commit/MR như trên — đồng ý submit AK-Docs không?" → đồng ý thì chạy `ak docs submit --title "..." --description "..." --yes`; từ chối thì dừng, để người dùng tự commit khi sẵn sàng. ❌ Không tự thêm `--yes` khi chưa thấy xác nhận rõ ràng.
|
|
717
|
+
5. Thông báo: MR đã mở, chờ **PM review & merge vào `main`** — đây là bước duyệt cuối cùng, không phải tự merge.
|
|
718
|
+
6. Run: `ak gate 2 approved --ticket [ticket-id]` to close the task.
|
|
719
|
+
7. Display: `GATE 2 DONE: Entry ghi vào AK-Docs/01.QnA/[file] — MR: [url hoặc "tạo thủ công"]`
|
|
720
|
+
|
|
721
|
+
> **Telemetry:** Run `ak gate 2 start --ticket [ticket-id]` when starting. Run `ak gate 2 approved --ticket [ticket-id]` when Gate 2 completes.
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
├── 00.Requirements/ # Requirements Gathering
|
|
16
16
|
│ └── F-001_User-Login/
|
|
17
17
|
│ ├── Raw-Requirements_v1.md # Raw input: ticket, meeting note, email
|
|
18
|
+
│ ├── System-Requirement_v2.md # Dev-facing bridge doc (create-system-requirement task type)
|
|
18
19
|
│ └── assets/ # Images, attachments, recordings
|
|
19
20
|
│
|
|
20
21
|
├── 01.Analysis/ # Gate 1: Business Analysis
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
| Section folder | `{N}.{Pascal-Case}/` | `00.Requirements/`, `03.UI-Prototypes/` |
|
|
47
48
|
| Feature folder | `F-{3-digit}_{Pascal-Case}/` | `F-001_User-Login/` |
|
|
48
49
|
| Requirements file | `Raw-Requirements_v{N}.md` | `Raw-Requirements_v1.md` |
|
|
50
|
+
| System Requirement file | `System-Requirement_v{N}.md` | `System-Requirement_v2.md` |
|
|
49
51
|
| Analysis file | `Analysis_v{N}.md` | `Analysis_v2.md` |
|
|
50
52
|
| QnA file | `QnA-Log_v{N}.md` | `QnA-Log_v1.md` |
|
|
51
53
|
| Prototype file | `UI-Prototype_v{N}.html` | `UI-Prototype_v1.html` |
|
|
@@ -84,3 +86,4 @@
|
|
|
84
86
|
- Thông báo cho Dev + Tester sau khi UC Spec sẵn sàng
|
|
85
87
|
- Không xóa file cũ — move vào `_archive/` khi có version mới
|
|
86
88
|
- `02.QnA/` là Q&A nội bộ với stakeholder — khác với `01.QnA/` ngoài dự án (dành cho khách hàng)
|
|
89
|
+
- `System-Requirement_v{N}.md` trong `00.Requirements/` do Dev viết (task type `create-system-requirement`, chạy 1 lần/functionId/UC Spec version), không phải do BA — `N` khớp đúng version của `UC-Spec_v{N}.md` mà nó trace tới, không phải bộ đếm riêng
|
package/docs/common/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2026-08-04
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`create-system-requirement` — new task type, bridging UC Spec (BA) into a Dev-facing System Requirement.** Until now, "System Requirement" only existed as whatever a coding ticket's Gate 1 (`read-study-requirement`) happened to write into its own per-ticket `requirement.md` — no single document traced 1-1 to a UC Spec version, so N tickets under one `functionId` (including bug fixes) left no coherent, BA-reviewable picture of what the system as a whole is required to do. New skill `custom/skills/create-system-requirement/SKILL.md` runs as its own 2-gate task type, scoped to a `functionId` (not a ticket):
|
|
15
|
+
- **Gate 1 — Investigate UC & Draft:** resolve the current UC Spec version, investigate existing source code/error-handling conventions (same methodology as `read-study-requirement`, including the GitNexus MCP shortcut), translate every Main/Alternative/Exception Flow step and Business Rule into Functional/Non-Functional Requirements, Validation Rules, Exception & Error Handling, and Acceptance Test scenarios (Given/When/Then) — every item carries a traced UC reference, nothing is invented. Q&A loops one question at a time until every Fact/Assumption/Gap is Confirmed; a genuinely unanswerable Gap blocks progress to Gate 2 rather than being guessed.
|
|
16
|
+
- **Gate 2 — Finalize & Approve:** decide single-file vs. split (default is one file, mirroring the UC Spec 1-1; splits only on measurable signals — business-rule domain fan-out, module/service fan-out, flow-count overload, or a ~400-line size ceiling, always along a semantic seam, never by raw line count; a UC Spec that reads like 2+ bundled independent use cases is escalated back to BA instead of silently split), write `AK-Docs/04.Coding/01.Requirements/[functionId]/System-Requirement_v{N}.md` (`N` pinned to the UC Spec version it was traced against, carried in a mandatory `UC-Spec-Version` header), and wait for `APPROVED`.
|
|
17
|
+
- Selectable via `ak use`'s "Task type:" prompt ("📐 Create System Requirement") or auto-detected by `aiflow prompt` — added to `scripts/detect.js` (keywords), `scripts/use.js` (both task-type selectors), and `scripts/task.js` (`maxGate = 2`, custom gate labels, alongside `gen-doc`'s existing 2-gate handling).
|
|
18
|
+
- **Coding Gate 1 (`read-study-requirement`) now requires System Requirement to exist and match the current UC Spec version before it can run.** New blocking Step 0: resolves the ticket's `functionId`, locates its current UC Spec, and checks for a `System-Requirement_v*.md` whose `UC-Spec-Version` header matches. Missing or stale → Gate 1 cancels outright and tells DEV to run the new `create-system-requirement` task type first (`⏸️ Gate 1 cancelled — run "ak use" and pick "📐 Create System Requirement" for [functionId] first...`); this check runs even in Fast Track mode (it's a 2-file header check, not a heavy investigation). Root `CLAUDE.md`'s Gate 1 section gained a matching "0. Pre-check (blocking)" line.
|
|
19
|
+
- Once unblocked, Step 1 now reads the System Requirement as mandatory input (`FR-*`/`NFR-*`/`VR-*`/`ER-*` item IDs are referenced, not restated), and a new **Step 3.5 — Reconcile with System Requirement** requires every ticket's scope to trace to an existing item, a UC-Spec-backed case System Requirement missed (proposed as a diff for DEV to confirm, appended with a Change Log row — never written directly, never bumping `System-Requirement-Version`), or a stop-and-ask when a ticket's scope traces to neither document at all.
|
|
20
|
+
- **Memory recall now has a profile for `create-system-requirement`.** `scripts/hooks/session-start.js`'s `inferWorkflow()` previously had no mapping for this task type (it would fall through to `null` → the generic `gen-doc` default), so memory entries tagged for it would never score the `workflows`-match bonus in `memory-store.js`'s `scoreMemory()`. Added the mapping, plus a guidance row in `docs/common/Memory-Architecture-v1.0.md`'s workflow-profile table (§5.2) — `domain` + `glossary` + `architecture`/`lessons-dev` + related `decisions` — since this task type bridges BA business language and Dev technical convention rather than sitting fully in either camp.
|
|
21
|
+
- **`ingest-data` — new task type for PM/BrSE/Comtor, ingesting customer communication into `AK-Docs/01.QnA/`.** Until now the only way link/text content from Backlog or SharePoint reached `AK-Docs` was a developer manually editing `QnA-Log.md` — no fetch, no classification, no drafted trace fields. New skill `custom/skills/ingest-data/SKILL.md`, wired as a 2-gate task type in `custom/templates/shared/gate-workflow.md`:
|
|
22
|
+
- **Gate 1 — Fetch, Classify, Draft:** resolves the source (Backlog ticket/comment/Document/Wiki link, Jira ticket/comment link, SharePoint link, or plain pasted text — via `ak fetch-links`, see below), classifies it into `QnA-Log.md` / `Meetings-Log.md` / `Confirmations-Log.md`, and drafts the entry with trace fields (`Nguồn`, `functionId`, `Người tổng hợp`, `Người approve tại nguồn`). When the target log is ambiguous — most notably Confirmations vs. regular feedback, a rule PM has not yet finalized (see `docs/internal/PM Workflow_v1.0.md` "Vấn đề còn mở" #1) — it asks instead of guessing. Displays the full draft (never summarized) and loops on edits until `APPROVED`.
|
|
23
|
+
- **Gate 2 — Branch + Merge Request:** writes the approved entry to `AK-Docs/01.QnA/{QnA-Log,Meetings-Log,Confirmations-Log}.md` (creating the file with its header template if it doesn't exist yet), then reuses the existing `ak docs branch`/`ak docs submit` (no new Git-writing code) behind the same explicit-confirmation gate every other docs-writing flow uses.
|
|
24
|
+
- Selectable via `ak use`'s "Task type:" prompt ("📥 Ingest Data" — new `PM` category). Output paths documented in `custom/rules/project-conventions.md` as a new, flat (non-`[functionId]/[ticketId]`) section, since these are project-wide logs, not per-ticket documents.
|
|
25
|
+
- Deliberately keeps `AK-Docs/01.QnA/` as the folder name rather than renaming to `01.Communications/` per the still-undecided proposal in `docs/internal/PM Workflow_v1.0.md` §1 — avoids a breaking rename on projects already using `01.QnA/QnA-Log.md` (e.g. the `ast-ai-agent` pilot). `docs/common/Docs-Management-Flow.md` §3's scope table now explicitly lists `01.QnA/` alongside `02.BA-Specs/`/`03.Testing/`/`04.Coding/`/`99.Memory/` as requiring the branch+MR flow.
|
|
26
|
+
- **`link-resolver.js` / `ak fetch-links` now fetch Backlog Document and Wiki links, not just ticket/comment — built for `ingest-data`, reusable anywhere.** `classifyLink()` gained a `kind` field (`ticket` | `document` | `wiki` | `unsupported`) and two new URL patterns: Backlog Document permalinks (`/document/{id}`, `/alias/document/{id}#comment-{id}`) and Wiki permalinks (`/alias/wiki/{id}`). New fetchers `fetchBacklogDocument`, `fetchBacklogDocumentComment`, `fetchBacklogWiki` call the same read-scoped `BACKLOG_API_KEY` already used for tickets — no new credentials needed. ⚠️ The Document API (`/api/v2/documents/:id`) is a genuinely new Nulab endpoint (added 2026) and its exact path has **not been verified against a live Backlog space** — expect to adjust it if it 404s. Also added `SHAREPOINT_RE` so a `*.sharepoint.com` URL is recognized and returns a clear `{ sourceType: "unsupported", reason: "sharepoint-not-configured" }` stub (with guidance to paste text instead) rather than the generic "not a recognized URL" error — SharePoint still has no real connector (Microsoft Graph API/OAuth is unbuilt, see `docs/internal/PM Workflow_v1.0.md` "Vấn đề 4").
|
|
27
|
+
- Auto-resolution of links found inside a ticket description (`ak use`'s `resolveLinks`, capped at 5) is **unchanged in scope** — `scanLinks()` now explicitly filters to `kind === 'ticket'` only, so Document/Wiki/SharePoint links are never auto-fetched en masse, only via an explicit single `ak fetch-links <url>` call.
|
|
28
|
+
- **`ak use` now captures `projectId`/`projectKey` from the loaded Backlog/Jira ticket.** `buildContextFromBacklog`/`buildContextFromJira` in `scripts/use.js` read `issue.projectId` (Backlog) and `fields.project.id`/`fields.project.key` (Jira), falling back to parsing the key out of the ticket ID (`PROJ-33` → `PROJ`) via a new `projectKeyFromIssueKey()` helper. Persisted into `.aiflow/context/current.json` and `.aiflow/state.json` (`current_context_project_id`/`current_context_project_key`), and shown in the `ak use` summary output. This is a read-only, informational addition — no code yet uses it to pick a Backlog/Jira project when creating a new ticket (that remains future work, tracked as "Vấn đề 5.1" in the PM Workflow doc).
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`ak use`'s "Task type:" selector crashed on every invocation once "📐 Create System Requirement" was added to the list.** `td()` (`scripts/use.js`) looks up `CATEGORY_COLOR[cat]` and calls it as a chalk styling function; the `"Dev"` category used by the Create System Requirement entry had no entry in `CATEGORY_COLOR`, so building the choices array threw `TypeError: CATEGORY_COLOR[cat] is not a function` before the prompt could even render — meaning `ak use <ticket>` and `ak use --manual` were both broken outright. Added `Dev` (and `PM`, for the new `ingest-data` entry) to `CATEGORY_COLOR`.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
10
36
|
## [0.1.9] - 2026-08-04
|
|
11
37
|
|
|
12
38
|
### Added
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
| Repo | Nội dung | Áp dụng flow này? |
|
|
40
40
|
|---|---|---|
|
|
41
|
-
| `AK-Docs` | `02.BA-Specs/`, `03.Testing/`, `04.Coding/`, `99.Memory/` — tài liệu riêng của từng dự án | ✅ Bắt buộc |
|
|
41
|
+
| `AK-Docs` | `01.QnA/`, `02.BA-Specs/`, `03.Testing/`, `04.Coding/`, `99.Memory/` — tài liệu riêng của từng dự án | ✅ Bắt buộc |
|
|
42
42
|
| `Shared-Docs` | Template dùng chung mọi dự án | ✅ Áp dụng, nhưng approver cuối có thể là AI Testing Team thay vì PM dự án (giống Flow B của Memory-Architecture) — mỗi dự án tự quyết định khi setup |
|
|
43
43
|
|
|
44
44
|
Flow này **không áp dụng** cho source code repo (Dev vẫn tạo PR code theo quy trình hiện có ở Gate 5 — `superpowers:requesting-code-review`). Đây là flow riêng cho kho **tài liệu**.
|
package/docs/common/INDEX.md
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
| `AK-Docs/03.Testing/` folder structure (Tester) | [Testing-Structure.md](./Testing-Structure.md) | Strategies → Testcases → evidence, by Function-ID |
|
|
29
29
|
| `99.Memory/` Project Brain — full design, scoring model, mem-id scheme, role/PM permissions | [Memory-Architecture-v1.0.md](./Memory-Architecture-v1.0.md) | v1.1 — Phase 1 (`draft/list/submit/remove`) is what's implemented today; later phases in this doc are roadmap, not shipped yet |
|
|
30
30
|
| How updates to `AK-Docs`/`Shared-Docs` get reviewed — branch/Merge Request flow, who can merge to `main` | [Docs-Management-Flow.md](./Docs-Management-Flow.md) | Doc's own header says `Trạng thái: Draft — chờ PM review` — flag that when answering, don't present it as final policy |
|
|
31
|
+
| PM/BrSE/Comtor — ingest a Backlog/Jira/SharePoint link or pasted text into `AK-Docs/01.QnA/` | [Project-Structure.md](./Project-Structure.md) (§ `01.QnA/`), `.claude/skills/ingest-data/SKILL.md` | `ak use` → taskType `ingest-data`, 2-gate flow (fetch/classify/draft → branch+MR). SharePoint link fetch is **not connected yet** — falls back to pasted text |
|
|
31
32
|
|
|
32
33
|
## Unanswered topics (do not invent — say so and stop here)
|
|
33
34
|
|
|
@@ -449,6 +449,7 @@ score = 3 × match(memory nằm trong folder functionId của ticket)
|
|
|
449
449
|
| coding — Gate 1–5 | `architecture` functionId liên quan + `lessons/dev` + `instincts` + `decisions` technical |
|
|
450
450
|
| create-spec | `domain` + `glossary` + `lessons/ba` + `decisions` business liên quan |
|
|
451
451
|
| create-testcase / execute-test | `lessons/qa` + `domain` + `glossary` |
|
|
452
|
+
| create-system-requirement | `domain` + `glossary` (hiểu đúng thuật ngữ nghiệp vụ từ UC Spec) + `architecture` functionId liên quan + `lessons/dev` (convention lỗi/exception hiện có) + `decisions` liên quan — bridge cả 2 phía BA/Dev, không rơi hẳn về 1 bên |
|
|
452
453
|
| gen-doc / không xác định (mặc định) | `decisions` + `03.Retro` gần nhất + `architecture` functionId liên quan |
|
|
453
454
|
|
|
454
455
|
**Điều chỉnh lượng theo độ phức tạp task:** ticket chạm nhiều module/mô tả dài → tăng N (10→15); hotfix nhỏ → giảm N (10→5) nhưng ưu tiên tuyệt đối lessons của đúng module; bug fix → bơm thêm toàn bộ lessons trong folder functionId liên quan (`01.Lessons/*/<functionId>/`) kể cả vượt N.
|
|
@@ -38,8 +38,10 @@ AK-Docs/
|
|
|
38
38
|
│ ├── Function-List.md # F-ID | Feature | BA | Dev | Tester | Status
|
|
39
39
|
│ └── Team.md # Member, role, contact
|
|
40
40
|
│
|
|
41
|
-
├── 01.QnA/ ← Trao đổi với khách hàng (có comtor)
|
|
42
|
-
│
|
|
41
|
+
├── 01.QnA/ ← Trao đổi với khách hàng (có comtor/BrSE)
|
|
42
|
+
│ ├── QnA-Log.md # Hỏi-đáp thông thường — 1 file duy nhất cho toàn dự án
|
|
43
|
+
│ ├── Meetings-Log.md # Tổng hợp meeting minutes (taskType `ingest-data`) — tạo khi cần
|
|
44
|
+
│ └── Confirmations-Log.md # Mốc khách CHỐT chính thức (taskType `ingest-data`) — tạo khi cần
|
|
43
45
|
│
|
|
44
46
|
├── 02.BA-Specs/ ← BA quản lý
|
|
45
47
|
│ ├── 00.Requirements/ # Requirements Gathering
|
|
@@ -102,6 +104,7 @@ Mỗi dự án khi cần tạo tài liệu mới (UC Spec, Test Case, Test Repor
|
|
|
102
104
|
|---|---|---|
|
|
103
105
|
| PM / BrSE | `00.Project-Overview/` | Đầu dự án + mỗi sprint |
|
|
104
106
|
| BA / PM / Comtor | `01.QnA/QnA-Log.md` | Khi có câu hỏi từ khách hàng |
|
|
107
|
+
| PM / BrSE / Comtor | `01.QnA/Meetings-Log.md`, `Confirmations-Log.md` | Ingest link/text đã approve, qua taskType `ingest-data` (`ak use` → "📥 Ingest Data") |
|
|
105
108
|
| BA | `02.BA-Specs/` | Sau khi Gate 4 APPROVED |
|
|
106
109
|
| Tester | `03.Testing/` | Sau khi Gate 4 APPROVED |
|
|
107
110
|
| Dev | `04.Coding/` | Trước khi tạo Pull Request |
|
package/package.json
CHANGED
package/scripts/detect.js
CHANGED
|
@@ -85,6 +85,28 @@ class TaskDetector {
|
|
|
85
85
|
antiKeywords: ['code', 'fix', 'bug'],
|
|
86
86
|
icon: '📝',
|
|
87
87
|
description: 'Generate document from source code / feature analysis'
|
|
88
|
+
},
|
|
89
|
+
'create-system-requirement': {
|
|
90
|
+
keywords: [
|
|
91
|
+
'system requirement', 'system requirements', 'srs',
|
|
92
|
+
'bridge uc', 'translate uc', 'uc to system requirement',
|
|
93
|
+
'uc spec to system', 'tạo system requirement',
|
|
94
|
+
'system requirement từ uc', 'dịch uc spec'
|
|
95
|
+
],
|
|
96
|
+
antiKeywords: ['bug', 'fix'],
|
|
97
|
+
icon: '📐',
|
|
98
|
+
description: 'Bridge UC Spec into a Dev-facing System Requirement'
|
|
99
|
+
},
|
|
100
|
+
'ingest-data': {
|
|
101
|
+
keywords: [
|
|
102
|
+
'ingest', 'meeting minutes', 'meetings log', 'qna log',
|
|
103
|
+
'confirmations log', 'tổng hợp buổi họp', 'biên bản họp',
|
|
104
|
+
'tổng hợp feedback khách hàng', 'ingest data', 'ingest link',
|
|
105
|
+
'ingest text', 'qna-log', 'meetings-log', 'confirmations-log'
|
|
106
|
+
],
|
|
107
|
+
antiKeywords: ['code', 'bug', 'fix'],
|
|
108
|
+
icon: '📥',
|
|
109
|
+
description: 'Ingest a Backlog/Jira/SharePoint link or pasted text into AK-Docs/01.QnA/ logs'
|
|
88
110
|
}
|
|
89
111
|
};
|
|
90
112
|
}
|
|
@@ -188,6 +188,7 @@ function inferWorkflow(ctx) {
|
|
|
188
188
|
if (t === 'gen-doc') return 'gen-doc';
|
|
189
189
|
if (t === 'testing') return 'create-testcase';
|
|
190
190
|
if (t === 'spec') return 'create-spec';
|
|
191
|
+
if (t === 'create-system-requirement') return 'create-system-requirement';
|
|
191
192
|
if (!t || ['feature', 'bug-fix', 'refactor', 'documentation', 'investigation'].includes(t)) return 'coding';
|
|
192
193
|
return null;
|
|
193
194
|
}
|
package/scripts/link-resolver.js
CHANGED
|
@@ -3,8 +3,14 @@ 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
|
+
// NOTE: Nulab's Document REST API is new (2026) — path unverified against a live space, adjust if it 404s.
|
|
8
|
+
const BACKLOG_DOCUMENT_RE = /https?:\/\/([\w.-]+\.backlog(?:tool)?\.com)\/(?:alias\/)?document\/(\d+)(?:#comment-(\d+))?/i;
|
|
9
|
+
// Backlog Wiki permalink — "Copy link" on a Wiki page gives /alias/wiki/{id}.
|
|
10
|
+
const BACKLOG_WIKI_RE = /https?:\/\/([\w.-]+\.backlog(?:tool)?\.com)\/alias\/wiki\/(\d+)/i;
|
|
6
11
|
const JIRA_RE = /https?:\/\/([\w.-]+\.atlassian\.net)\/browse\/([A-Z][A-Z0-9_]+-\d+)/i;
|
|
7
12
|
const JIRA_COMMENT_RE = /[?&]focusedCommentId=(\d+)/;
|
|
13
|
+
const SHAREPOINT_RE = /https?:\/\/([\w.-]+\.sharepoint\.com)\/\S*/i;
|
|
8
14
|
const URL_RE = /https?:\/\/[^\s\)\]"<>]+/g;
|
|
9
15
|
|
|
10
16
|
const MAX_AUTO_LINKS = 5;
|
|
@@ -13,25 +19,43 @@ function classifyLink(url) {
|
|
|
13
19
|
const bm = url.match(BACKLOG_RE);
|
|
14
20
|
if (bm) {
|
|
15
21
|
const [, domain, ticketId, commentId] = bm;
|
|
16
|
-
return { adapter: 'backlog', domain, ticketId, commentId: commentId || null, isComment: !!commentId };
|
|
22
|
+
return { adapter: 'backlog', kind: 'ticket', domain, ticketId, commentId: commentId || null, isComment: !!commentId };
|
|
23
|
+
}
|
|
24
|
+
const dm = url.match(BACKLOG_DOCUMENT_RE);
|
|
25
|
+
if (dm) {
|
|
26
|
+
const [, domain, documentId, commentId] = dm;
|
|
27
|
+
return { adapter: 'backlog', kind: 'document', domain, documentId, commentId: commentId || null, isComment: !!commentId };
|
|
28
|
+
}
|
|
29
|
+
const wm = url.match(BACKLOG_WIKI_RE);
|
|
30
|
+
if (wm) {
|
|
31
|
+
const [, domain, wikiId] = wm;
|
|
32
|
+
return { adapter: 'backlog', kind: 'wiki', domain, wikiId };
|
|
17
33
|
}
|
|
18
34
|
const jm = url.match(JIRA_RE);
|
|
19
35
|
if (jm) {
|
|
20
36
|
const [, domain, ticketId] = jm;
|
|
21
37
|
const cm = url.match(JIRA_COMMENT_RE);
|
|
22
38
|
const commentId = cm ? cm[1] : null;
|
|
23
|
-
return { adapter: 'jira', domain, ticketId, commentId, isComment: !!commentId };
|
|
39
|
+
return { adapter: 'jira', kind: 'ticket', domain, ticketId, commentId, isComment: !!commentId };
|
|
40
|
+
}
|
|
41
|
+
const sm = url.match(SHAREPOINT_RE);
|
|
42
|
+
if (sm) {
|
|
43
|
+
const [, domain] = sm;
|
|
44
|
+
return { adapter: 'sharepoint', kind: 'unsupported', domain };
|
|
24
45
|
}
|
|
25
46
|
return null;
|
|
26
47
|
}
|
|
27
48
|
|
|
49
|
+
// Auto-resolve (from a ticket description, capped at MAX_AUTO_LINKS) only ever
|
|
50
|
+
// followed ticket/comment links. Document/Wiki/SharePoint are explicit, single-URL
|
|
51
|
+
// lookups only (`ak fetch-links <url>`) — never auto-fetched en masse.
|
|
28
52
|
function scanLinks(text) {
|
|
29
53
|
const found = [];
|
|
30
54
|
let m;
|
|
31
55
|
URL_RE.lastIndex = 0;
|
|
32
56
|
while ((m = URL_RE.exec(text)) !== null) {
|
|
33
57
|
const classified = classifyLink(m[0]);
|
|
34
|
-
if (classified) found.push({ url: m[0], ...classified });
|
|
58
|
+
if (classified && classified.kind === 'ticket') found.push({ url: m[0], ...classified });
|
|
35
59
|
}
|
|
36
60
|
return found;
|
|
37
61
|
}
|
|
@@ -83,6 +107,47 @@ async function fetchBacklogComment(domain, apiKey, ticketId, commentId) {
|
|
|
83
107
|
};
|
|
84
108
|
}
|
|
85
109
|
|
|
110
|
+
async function fetchBacklogDocument(domain, apiKey, documentId) {
|
|
111
|
+
const doc = await httpsGet(`https://${domain}/api/v2/documents/${documentId}?apiKey=${apiKey}`);
|
|
112
|
+
return {
|
|
113
|
+
sourceType: 'document',
|
|
114
|
+
sourceUrl: `https://${domain}/document/${documentId}`,
|
|
115
|
+
documentId: String(documentId),
|
|
116
|
+
title: doc.title || doc.name || '',
|
|
117
|
+
tag: (doc.tags || []).map(t => t.name).join(', '),
|
|
118
|
+
content: (doc.plainText || doc.content || '').substring(0, 4000),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function fetchBacklogDocumentComment(domain, apiKey, documentId, commentId) {
|
|
123
|
+
const comments = await httpsGet(
|
|
124
|
+
`https://${domain}/api/v2/documents/${documentId}/comments?apiKey=${apiKey}&count=100&order=asc`
|
|
125
|
+
);
|
|
126
|
+
const comment = (comments || []).find(c => String(c.id) === String(commentId));
|
|
127
|
+
if (!comment) throw new Error(`Comment ${commentId} not found in document ${documentId}`);
|
|
128
|
+
const date = comment.created ? new Date(comment.created).toLocaleDateString('vi-VN') : '';
|
|
129
|
+
return {
|
|
130
|
+
sourceType: 'document-comment',
|
|
131
|
+
sourceUrl: `https://${domain}/document/${documentId}#comment-${commentId}`,
|
|
132
|
+
documentId: String(documentId),
|
|
133
|
+
commentId: String(commentId),
|
|
134
|
+
author: comment.createdUser?.name || 'Unknown',
|
|
135
|
+
date,
|
|
136
|
+
content: (comment.content || '').substring(0, 2000),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function fetchBacklogWiki(domain, apiKey, wikiId) {
|
|
141
|
+
const wiki = await httpsGet(`https://${domain}/api/v2/wikis/${wikiId}?apiKey=${apiKey}`);
|
|
142
|
+
return {
|
|
143
|
+
sourceType: 'wiki',
|
|
144
|
+
sourceUrl: `https://${domain}/alias/wiki/${wikiId}`,
|
|
145
|
+
wikiId: String(wikiId),
|
|
146
|
+
title: wiki.name || '',
|
|
147
|
+
content: (wiki.content || '').substring(0, 4000),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
86
151
|
function jiraAuth(email, token) {
|
|
87
152
|
return `Basic ${Buffer.from(`${email}:${token}`).toString('base64')}`;
|
|
88
153
|
}
|
|
@@ -126,17 +191,41 @@ async function fetchJiraComment(domain, email, token, ticketId, commentId) {
|
|
|
126
191
|
};
|
|
127
192
|
}
|
|
128
193
|
|
|
194
|
+
function linkDedupeKey(classified) {
|
|
195
|
+
if (classified.kind === 'document') return 'doc:' + classified.documentId + (classified.commentId ? '#' + classified.commentId : '');
|
|
196
|
+
if (classified.kind === 'wiki') return 'wiki:' + classified.wikiId;
|
|
197
|
+
if (classified.ticketId) return classified.ticketId + (classified.commentId ? '#' + classified.commentId : '');
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
129
201
|
async function fetchLink(url, credentials = {}, alreadyLoadedIds = []) {
|
|
130
202
|
const classified = classifyLink(url);
|
|
131
203
|
if (!classified) return null;
|
|
132
204
|
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
205
|
+
const dedupeKey = linkDedupeKey(classified);
|
|
206
|
+
if (dedupeKey && (alreadyLoadedIds.includes(dedupeKey) || alreadyLoadedIds.includes(classified.ticketId))) return null;
|
|
207
|
+
|
|
208
|
+
const { adapter, kind, domain, ticketId, commentId, documentId, wikiId, isComment } = classified;
|
|
209
|
+
|
|
210
|
+
if (adapter === 'sharepoint') {
|
|
211
|
+
return {
|
|
212
|
+
sourceType: 'unsupported',
|
|
213
|
+
reason: 'sharepoint-not-configured',
|
|
214
|
+
sourceUrl: url,
|
|
215
|
+
message:
|
|
216
|
+
'SharePoint chưa có connector (cần Microsoft Graph API + OAuth — xem "Vấn đề 4" trong PM Workflow_v1.0.md). ' +
|
|
217
|
+
'Copy/paste nội dung comment/tài liệu trực tiếp vào chat thay vì dán link.',
|
|
218
|
+
};
|
|
219
|
+
}
|
|
136
220
|
|
|
137
221
|
if (adapter === 'backlog') {
|
|
138
222
|
const apiKey = credentials.BACKLOG_API_KEY;
|
|
139
223
|
if (!apiKey) throw new Error('BACKLOG_API_KEY not set');
|
|
224
|
+
if (kind === 'document') {
|
|
225
|
+
if (isComment) return await fetchBacklogDocumentComment(domain, apiKey, documentId, commentId);
|
|
226
|
+
return await fetchBacklogDocument(domain, apiKey, documentId);
|
|
227
|
+
}
|
|
228
|
+
if (kind === 'wiki') return await fetchBacklogWiki(domain, apiKey, wikiId);
|
|
140
229
|
if (isComment) return await fetchBacklogComment(domain, apiKey, ticketId, commentId);
|
|
141
230
|
return await fetchBacklogTicket(domain, apiKey, ticketId);
|
|
142
231
|
}
|
|
@@ -176,4 +265,9 @@ async function resolveLinks(description, credentials = {}, alreadyLoadedIds = []
|
|
|
176
265
|
return results;
|
|
177
266
|
}
|
|
178
267
|
|
|
179
|
-
module.exports = {
|
|
268
|
+
module.exports = {
|
|
269
|
+
classifyLink, scanLinks, fetchLink, resolveLinks,
|
|
270
|
+
fetchBacklogTicket, fetchBacklogComment,
|
|
271
|
+
fetchBacklogDocument, fetchBacklogDocumentComment, fetchBacklogWiki,
|
|
272
|
+
fetchJiraTicket, fetchJiraComment,
|
|
273
|
+
};
|
package/scripts/prompt.js
CHANGED
|
@@ -278,6 +278,150 @@ Write documentation based on approved outline.
|
|
|
278
278
|
**INVOKE:** \`superpowers:verification-before-completion\`
|
|
279
279
|
Verify docs match code. No outdated examples.
|
|
280
280
|
Display: "GATE 3: Documentation complete. Type APPROVED."
|
|
281
|
+
`,
|
|
282
|
+
},
|
|
283
|
+
'create-spec': {
|
|
284
|
+
header: 'Create UC Spec',
|
|
285
|
+
instruction: 'Create a complete UC Spec from the raw requirement described below, following the BA 4-Gate workflow.',
|
|
286
|
+
skillWorkflow: `
|
|
287
|
+
## STRICT GATE WORKFLOW — [BA] 4-Gate Spec Creation
|
|
288
|
+
|
|
289
|
+
Follow gates IN ORDER. Do NOT skip or merge gates.
|
|
290
|
+
|
|
291
|
+
### GATE 1 — Analyze Requirement & Draft Q&A (auto-start)
|
|
292
|
+
**INVOKE:** \`read-study-requirement\` skill, then the \`ba-skills\` sub-skills for analysis
|
|
293
|
+
1. Confirm \`functionId\` and ensure AK-Docs is on branch \`feature/[functionId]/[ticketId]\`
|
|
294
|
+
2. Read the raw requirement (ticket/backlog/file) + related source code
|
|
295
|
+
3. Identify Gaps/Assumptions, draft a Q&A list — classify every item as Fact / Assumption / Gap
|
|
296
|
+
4. Output \`AK-Docs/02.BA-Specs/01.QnA/[functionId]/[ticketId].md\`
|
|
297
|
+
5. Display "GATE 1: Q&A draft ready" → wait for **APPROVED**
|
|
298
|
+
|
|
299
|
+
### GATE 2 — Update Q&A (loop until all Confirmed)
|
|
300
|
+
Integrate BA/stakeholder answers into the analysis doc. Loop: unresolved items remain → keep asking ONE question at a time. All Confirmed → display "GATE 2: All items Confirmed" → wait for **APPROVED**.
|
|
301
|
+
|
|
302
|
+
### GATE 3 — UI Prototype (HTML/CSS)
|
|
303
|
+
Only runs after Gate 2 APPROVED.
|
|
304
|
+
1. List UI components from the confirmed requirement
|
|
305
|
+
2. Design and write static HTML/CSS prototype (incl. error-state placeholders)
|
|
306
|
+
3. Save under \`AK-Docs/02.BA-Specs/03.Prototypes/[functionId]/\`
|
|
307
|
+
4. Display "GATE 3: Prototype ready" → wait for **APPROVED**
|
|
308
|
+
|
|
309
|
+
### GATE 4 — Full UC Spec (wait for APPROVED)
|
|
310
|
+
Only runs after Gate 3 APPROVED.
|
|
311
|
+
1. Fill the UC Spec template: Flow of Events (Main/Alternative/Exception), UI Components, Mermaid activity diagram, Business Rules
|
|
312
|
+
2. Save \`AK-Docs/02.BA-Specs/04.UC-Specs/[functionId]/UC-Spec_v[N].md\`
|
|
313
|
+
3. Retrospect — propose a memory draft for any new business rule/decision learned
|
|
314
|
+
4. Submit AK-Docs via Merge Request (title/description shown, explicit user confirmation) — PM reviews & merges into \`main\`
|
|
315
|
+
5. Display "GATE 4: UC Spec ready" → wait for **APPROVED**
|
|
316
|
+
`,
|
|
317
|
+
},
|
|
318
|
+
'create-testcase': {
|
|
319
|
+
header: 'Create Test Cases',
|
|
320
|
+
instruction: 'Create a complete, execution-ready Test Case set from the requirement described below, following the QA 4-Gate workflow.',
|
|
321
|
+
skillWorkflow: `
|
|
322
|
+
## STRICT GATE WORKFLOW — [QA] 4-Gate TestCase Creation
|
|
323
|
+
|
|
324
|
+
Follow gates IN ORDER. Do NOT skip or merge gates.
|
|
325
|
+
|
|
326
|
+
### GATE 1 — Requirement & Risk Analysis (auto-start)
|
|
327
|
+
**INVOKE:** \`read-study-requirement\` skill, then the \`test-skills\` sub-skills
|
|
328
|
+
1. Confirm \`functionId\` and ensure AK-Docs is on branch \`feature/[functionId]/[ticketId]\`
|
|
329
|
+
2. Read the requirement (SRS/Backlog/Jira/UC Spec) and assess risk areas
|
|
330
|
+
3. Clarify with QA/stakeholder if anything is ambiguous — ask ONE question at a time
|
|
331
|
+
4. Output requirement + risk analysis under \`AK-Docs/03.QA-Specs/01.Requirements/[functionId]/[ticketId].md\`
|
|
332
|
+
5. Display "GATE 1: Requirement & risk analysis ready" → wait for **APPROVED**
|
|
333
|
+
|
|
334
|
+
### GATE 2 — Scenario Building
|
|
335
|
+
Only runs after Gate 1 APPROVED.
|
|
336
|
+
Apply scenario-building skills to derive test scenarios (happy path, edge case, negative). Output scenario list. Display "GATE 2: Scenarios ready" → wait for **APPROVED**.
|
|
337
|
+
|
|
338
|
+
### GATE 3 — Detailed Test Case Design
|
|
339
|
+
Only runs after Gate 2 APPROVED.
|
|
340
|
+
1. Apply TC design techniques (equivalence partitioning, boundary values, etc.)
|
|
341
|
+
2. Design UI, business, and data test cases
|
|
342
|
+
3. Output draft Test Cases under \`AK-Docs/03.QA-Specs/03.TestCases/[functionId]/\`
|
|
343
|
+
4. Display "GATE 3: Draft Test Cases ready" → wait for **APPROVED**
|
|
344
|
+
|
|
345
|
+
### GATE 4 — Review & Optimize (wait for APPROVED)
|
|
346
|
+
Only runs after Gate 3 APPROVED.
|
|
347
|
+
1. Review coverage against requirements, optimize/dedupe test cases
|
|
348
|
+
2. Confirm sign-off status, generate the final TestCase artifact
|
|
349
|
+
3. Retrospect — propose a memory draft for any lesson learned
|
|
350
|
+
4. Submit AK-Docs via Merge Request (title/description shown, explicit user confirmation) — PM reviews & merges into \`main\`
|
|
351
|
+
5. Display "GATE 4: Final Test Cases ready" → wait for **APPROVED**
|
|
352
|
+
`,
|
|
353
|
+
},
|
|
354
|
+
'create-system-requirement': {
|
|
355
|
+
header: 'Create System Requirement',
|
|
356
|
+
instruction: 'Bridge the UC Spec into a Dev-facing System Requirement, following the 2-Gate workflow.',
|
|
357
|
+
skillWorkflow: `
|
|
358
|
+
## STRICT GATE WORKFLOW — Create System Requirement (2-Gate Bridge)
|
|
359
|
+
|
|
360
|
+
> Runs once per \`functionId\` per UC Spec version — NOT per ticket. Blocks coding Gate 1 until APPROVED.
|
|
361
|
+
|
|
362
|
+
### GATE 1 — Investigate & Draft (auto-start)
|
|
363
|
+
**INVOKE:** \`create-system-requirement\` skill
|
|
364
|
+
1. Resolve \`functionId\`; locate the current UC Spec (\`AK-Docs/02.BA-Specs/04.UC-Specs/[functionId]/UC-Spec_v[N].md\`) — not found → STOP, tell DEV the UC Spec must exist and be BA-signed-off first
|
|
365
|
+
2. Read the full UC Spec, then investigate source code (existing error-handling conventions, data model/API surface)
|
|
366
|
+
3. Translate UC → Functional/Non-Functional Requirements, Business Rules → Validation Rules, Exception & Error Handling, Acceptance Test Scenarios — every item traced to a UC reference, no invented content
|
|
367
|
+
4. Classify every item as Fact / Assumption / Gap; ask ONE question at a time until every Gap is Confirmed
|
|
368
|
+
5. Display "GATE 1: All Gaps Confirmed" → wait for **APPROVED**
|
|
369
|
+
|
|
370
|
+
### GATE 2 — Finalize & Approve (wait for APPROVED)
|
|
371
|
+
Only runs after Gate 1 APPROVED.
|
|
372
|
+
1. Decide single-file vs split (default: single file mirroring the UC Spec 1-1)
|
|
373
|
+
2. Write \`AK-Docs/02.BA-Specs/00.Requirements/[functionId]/System-Requirement_v[N].md\` with the Traceability Matrix + all sections
|
|
374
|
+
3. Display "GATE 2: System Requirement ready" with coverage counts (Open Gaps must be 0) → wait for **APPROVED**
|
|
375
|
+
|
|
376
|
+
**On APPROVED:** coding Gate 1 (\`read-study-requirement\`) unlocks for this functionId.
|
|
377
|
+
`,
|
|
378
|
+
},
|
|
379
|
+
'execute': {
|
|
380
|
+
header: 'Execute Test Cases',
|
|
381
|
+
instruction: 'Execute the Test Case file described below against the running app, following the EXECUTE 4-Gate workflow.',
|
|
382
|
+
skillWorkflow: `
|
|
383
|
+
## STRICT GATE WORKFLOW — [EXECUTE] Executing Flow
|
|
384
|
+
|
|
385
|
+
Follow gates IN ORDER. Do NOT skip or merge gates.
|
|
386
|
+
|
|
387
|
+
### GATE 1 — Pre-flight & Work Plan (auto-start)
|
|
388
|
+
**INVOKE:** \`execute-flow\` skill
|
|
389
|
+
Check: MCP Playwright configured, TC file is parseable, \`ak-test/{repo}/\` scaffold exists, \`BASE_URL\` set, Playwright config exists. Display the work plan (TC file, repo, screen, BASE_URL) → wait for **APPROVED**.
|
|
390
|
+
|
|
391
|
+
### GATE 2 — Script Sync
|
|
392
|
+
Only runs after Gate 1 APPROVED.
|
|
393
|
+
**INVOKE:** \`script-sync\` skill
|
|
394
|
+
Hash-based TC↔script sync: new TC → generate Playwright test via MCP snapshot/locator (never fabricate selectors); changed TC → update; unchanged → skip; manual/blocked → mark Untest/Pending. Display new/updated/skipped/manual counts → wait for **APPROVED**.
|
|
395
|
+
|
|
396
|
+
### GATE 3 — Execute & Evidence
|
|
397
|
+
Only runs after Gate 2 APPROVED.
|
|
398
|
+
Run \`BASE_URL=<url> npx playwright test scripts/{screenId}/{ScreenID}.spec.ts\`, organize evidence (screenshots/trace/result.md) into \`ak-test/{repo}/results/{screenId}/run-{N}/\`, auto-draft bug reports for failures, update R1/R2 columns in the TC file. Supports \`RETEST: [TC_ID]\` and \`PR: [url]\`. Display pass/fail/untest/pending counts → wait for **APPROVED** (all Critical/High bugs resolved).
|
|
399
|
+
|
|
400
|
+
### GATE 4 — Report & Bug Logging (wait for APPROVED)
|
|
401
|
+
Only runs after Gate 3 APPROVED.
|
|
402
|
+
Generate \`testreport.md\` (Go/No-Go: 0 unresolved Critical = Go), log each failed TC as a bug one at a time (ask Y/N/edit before logging). Display decision + bug counts → wait for **APPROVED** to sign off.
|
|
403
|
+
`,
|
|
404
|
+
},
|
|
405
|
+
'ingest-data': {
|
|
406
|
+
header: 'Ingest Data',
|
|
407
|
+
instruction: 'Ingest the customer communication (Backlog/Jira/SharePoint link or pasted text) described below into AK-Docs logs, following the 2-Gate workflow.',
|
|
408
|
+
skillWorkflow: `
|
|
409
|
+
## STRICT GATE WORKFLOW — Ingest Data (2-Gate)
|
|
410
|
+
|
|
411
|
+
**INVOKE:** \`ingest-data\` skill for both gates — it owns the classification rules, draft templates, and per-file format.
|
|
412
|
+
|
|
413
|
+
### GATE 1 — Fetch, Classify, Draft (auto-start)
|
|
414
|
+
1. Resolve the source: Backlog/Jira ticket/comment/Document/Wiki URL → \`ak fetch-links "<url>"\`; SharePoint → not yet connected, ask for pasted text instead; plain text → use as-is
|
|
415
|
+
2. Classify into \`QnA-Log.md\` / \`Meetings-Log.md\` / \`Confirmations-Log.md\` — ask the user if ambiguous, never guess silently
|
|
416
|
+
3. Draft the entry using the exact template for the target log file, including trace fields (Nguồn, functionId, Người tổng hợp, Người approve tại nguồn)
|
|
417
|
+
4. Display the full draft → wait for **APPROVED** (or edit requests, looped until approved)
|
|
418
|
+
|
|
419
|
+
### GATE 2 — Branch + Merge Request (runs immediately after APPROVED)
|
|
420
|
+
1. Resolve \`functionId\` (tag from source → inferred from input → fallback \`general\`)
|
|
421
|
+
2. Ensure AK-Docs is on branch \`feature/[functionId]/[ticketId]\` (create only after explicit confirmation)
|
|
422
|
+
3. Append the approved entry to the target log file (create with header template if missing)
|
|
423
|
+
4. Submit AK-Docs via Merge Request (title/description shown, explicit user confirmation) — PM reviews & merges into \`main\`
|
|
424
|
+
5. Display "GATE 2 DONE: Entry written to AK-Docs/01.QnA/[file]"
|
|
281
425
|
`,
|
|
282
426
|
},
|
|
283
427
|
'gen-doc': {
|
package/scripts/task.js
CHANGED
|
@@ -331,21 +331,27 @@ async function nextGate(taskId) {
|
|
|
331
331
|
const nextGateNum = currentGate + 1;
|
|
332
332
|
|
|
333
333
|
// Save context snapshot if current task is active
|
|
334
|
-
|
|
334
|
+
// taskType falls back to task-state.json's own stored value — current.json is removed
|
|
335
|
+
// at the end of this function, so on Gate 2+ of a multi-step task it's already gone.
|
|
336
|
+
let taskType = existing.taskType || null;
|
|
335
337
|
if (await fs.pathExists(CURRENT_FILE)) {
|
|
336
338
|
const ctx = await fs.readJson(CURRENT_FILE).catch(() => null);
|
|
337
339
|
if (ctx && ctx.taskId === resolvedId) {
|
|
338
|
-
taskType = ctx.taskType ||
|
|
340
|
+
taskType = ctx.taskType || taskType;
|
|
339
341
|
await fs.writeJson(path.join(taskDir, 'context.json'), ctx, { spaces: 2 });
|
|
340
342
|
}
|
|
341
343
|
}
|
|
342
344
|
|
|
343
345
|
const isGenDoc = taskType === 'gen-doc';
|
|
344
|
-
const
|
|
346
|
+
const isSystemRequirement = taskType === 'create-system-requirement';
|
|
347
|
+
const isIngestData = taskType === 'ingest-data';
|
|
348
|
+
const isTwoGateDoc = isGenDoc || isSystemRequirement || isIngestData;
|
|
349
|
+
const maxGate = isTwoGateDoc ? 2 : 5;
|
|
345
350
|
|
|
346
351
|
const taskState = {
|
|
347
352
|
...existing,
|
|
348
353
|
taskId: resolvedId,
|
|
354
|
+
taskType: taskType || existing.taskType || null,
|
|
349
355
|
status: nextGateNum > maxGate ? 'done' : 'pending',
|
|
350
356
|
updatedAt: now,
|
|
351
357
|
pausedAt: now,
|
|
@@ -365,7 +371,7 @@ async function nextGate(taskId) {
|
|
|
365
371
|
console.log(chalk.green(`✓ Gate ${currentGate} approved for ${resolvedId}.`));
|
|
366
372
|
console.log(chalk.gray(` Summary saved to: .aiflow/tasks/${resolvedId}/task-summary.md`));
|
|
367
373
|
|
|
368
|
-
if (
|
|
374
|
+
if (isTwoGateDoc && currentGate >= maxGate) {
|
|
369
375
|
console.log(chalk.green('\n ✅ Document workflow complete. Task is done.'));
|
|
370
376
|
} else {
|
|
371
377
|
const nextLabel = gateLabel(nextGateNum, taskType);
|
|
@@ -374,7 +380,7 @@ async function nextGate(taskId) {
|
|
|
374
380
|
console.log(chalk.gray(` 1. Open a NEW chatbox or terminal session.`));
|
|
375
381
|
console.log(chalk.gray(` 2. Run: aiflow task resume ${resolvedId} (to load context).`));
|
|
376
382
|
console.log(chalk.gray(` 3. Type "start" or "continue from the current plan".`));
|
|
377
|
-
if (!
|
|
383
|
+
if (!isTwoGateDoc) {
|
|
378
384
|
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/).`));
|
|
379
385
|
console.log(chalk.yellow(` The AI will automatically resume the exact task you left off.)`));
|
|
380
386
|
}
|
|
@@ -479,7 +485,7 @@ async function detectCurrentGate(taskId) {
|
|
|
479
485
|
|
|
480
486
|
async function generateMarkdownSummary(taskState, taskType = null) {
|
|
481
487
|
taskType = taskType || taskState.taskType || 'feature';
|
|
482
|
-
const maxGate = taskType === 'testing' ? 4 : (taskType === 'gen-doc' ? 2 : 5);
|
|
488
|
+
const maxGate = taskType === 'testing' ? 4 : ((taskType === 'gen-doc' || taskType === 'create-system-requirement' || taskType === 'ingest-data') ? 2 : 5);
|
|
483
489
|
const lines = [];
|
|
484
490
|
lines.push(`# Task Summary: ${taskState.taskId}`);
|
|
485
491
|
lines.push(`**Title:** ${taskState.title}`);
|
|
@@ -517,6 +523,16 @@ function gateLabel(n, taskType = null) {
|
|
|
517
523
|
if (n === 2) return 'Generate Document';
|
|
518
524
|
if (n >= 3) return 'Done';
|
|
519
525
|
}
|
|
526
|
+
if (taskType === 'create-system-requirement') {
|
|
527
|
+
if (n === 1) return 'Investigate UC & Draft';
|
|
528
|
+
if (n === 2) return 'Finalize & Approve';
|
|
529
|
+
if (n >= 3) return 'Done';
|
|
530
|
+
}
|
|
531
|
+
if (taskType === 'ingest-data') {
|
|
532
|
+
if (n === 1) return 'Fetch, Classify, Draft';
|
|
533
|
+
if (n === 2) return 'Branch + Merge Request';
|
|
534
|
+
if (n >= 3) return 'Done';
|
|
535
|
+
}
|
|
520
536
|
const labels = {
|
|
521
537
|
1: 'AI Analyze Requirement',
|
|
522
538
|
2: 'Implementation Plan',
|