@relipa/ai-flow-kit 0.1.9 → 0.2.0-beta.1

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.
Files changed (55) hide show
  1. package/README.md +65 -0
  2. package/bin/aiflow.js +74 -4
  3. package/custom/rules/output-language.md +36 -0
  4. package/custom/rules/project-conventions.md +16 -0
  5. package/custom/skills/automation-testing/SKILL.md +1 -1
  6. package/custom/skills/ba-skills/skill-ba-build-business-rules-v1.md +2 -0
  7. package/custom/skills/ba-skills/skill-ba-initial-analysis-v1.md +2 -0
  8. package/custom/skills/ba-skills/skill-ba-mermaid-flowchart-v1.md +2 -0
  9. package/custom/skills/ba-skills/skill-ba-qna-v1.md +2 -0
  10. package/custom/skills/ba-skills/skill-ba-ui-prototype-v1.md +2 -0
  11. package/custom/skills/ba-skills/skill-ba-write-uc-spec-v1.md +2 -0
  12. package/custom/skills/coverage-check/SKILL.md +2 -0
  13. package/custom/skills/create-system-requirement/SKILL.md +252 -0
  14. package/custom/skills/deploy-model/SKILL.md +2 -0
  15. package/custom/skills/design-experiment/SKILL.md +2 -0
  16. package/custom/skills/evaluate-model/SKILL.md +2 -0
  17. package/custom/skills/evidence-aggregation/SKILL.md +2 -0
  18. package/custom/skills/execute-flow/SKILL.md +2 -0
  19. package/custom/skills/explore-data/SKILL.md +2 -0
  20. package/custom/skills/frame-ml-problem/SKILL.md +2 -0
  21. package/custom/skills/gate-review/SKILL.md +2 -0
  22. package/custom/skills/generate-spec/SKILL.md +2 -0
  23. package/custom/skills/generate-test-report/SKILL.md +2 -0
  24. package/custom/skills/generate-testcase/SKILL.md +2 -0
  25. package/custom/skills/impact-analysis/SKILL.md +2 -0
  26. package/custom/skills/improve-algorithm/SKILL.md +2 -0
  27. package/custom/skills/ingest-data/SKILL.md +226 -0
  28. package/custom/skills/log-bug/SKILL.md +2 -0
  29. package/custom/skills/pr-impact-analysis/SKILL.md +2 -0
  30. package/custom/skills/read-study-requirement/SKILL.md +41 -2
  31. package/custom/skills/report-customer/SKILL.md +6 -2
  32. package/custom/skills/retest-orchestration/SKILL.md +2 -0
  33. package/custom/skills/review-plan/SKILL.md +2 -0
  34. package/custom/skills/script-sync/SKILL.md +1 -1
  35. package/custom/skills/test-analysis/SKILL.md +2 -0
  36. package/custom/skills/test-skills/rules/qa-writing-standards.md +2 -2
  37. package/custom/skills/train-model/SKILL.md +2 -0
  38. package/custom/templates/shared/create-testcase-workflow.md +32 -1
  39. package/custom/templates/shared/gate-workflow.md +64 -0
  40. package/docs/common/BA-Specs-Structure.md +3 -0
  41. package/docs/common/CHANGELOG.md +39 -0
  42. package/docs/common/Docs-Management-Flow.md +1 -1
  43. package/docs/common/INDEX.md +1 -0
  44. package/docs/common/Memory-Architecture-v1.0.md +1 -0
  45. package/docs/common/Project-Structure.md +5 -2
  46. package/package.json +1 -1
  47. package/scripts/create-score-excel.js +4 -111
  48. package/scripts/detect.js +22 -0
  49. package/scripts/hooks/session-start.js +1 -0
  50. package/scripts/init.js +24 -1
  51. package/scripts/link-resolver.js +194 -7
  52. package/scripts/prompt.js +144 -0
  53. package/scripts/task.js +22 -6
  54. package/scripts/ticket-writer.js +247 -0
  55. package/scripts/use.js +402 -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,65 @@ 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.
722
+
723
+ ### GATE 3 — Sinh Task & Tạo Ticket (auto, chạy ngay sau Gate 2 xong)
724
+
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
+
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 và **kết thúc luôn, không chạy `ak gate 3 start`, không có Gate 3 Display**.
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
+ 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
+ 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`).
732
+ 6. Tạo ticket bằng `ak tasks create-tickets <file>.json --json` (skill § 5.7). Nếu thiếu WRITE credentials, hỏi PM nhập ngay trong chat rồi `ak credentials set <field> "<value>"` và thử lại đúng 1 lần.
733
+ 7. Ghi ngược link ticket vào entry gốc + hiển thị tổng kết (skill § 5.8).
734
+ 8. Run: `ak gate 3 approved --ticket [ticket-id]` để đóng task.
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.
@@ -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
@@ -7,6 +7,45 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.2.1] - 2026-08-05
11
+
12
+ ### Added
13
+
14
+ - **`ingest-data` gained Gate 3 — auto-triggered task proposal & real ticket creation on Backlog/Jira, closing the gap after Gate 2 where the flow used to just stop once an entry landed in `AK-Docs/01.QnA/`.** Implements "Vấn đề 5" in `docs/internal/PM Workflow_v1.0.md`, decided to run **automatically** right after Gate 2 (not on-demand as the doc's earlier tentative proposal had it):
15
+ - AI re-reads the entry just ingested plus related source code/docs to judge impact, then decides whether it needs a task at all — pure-reference content (FYI, status update) ends the gate with no task proposed, no ticket created.
16
+ - When action is needed, proposes a task list (`type`: spec/coding/test/other, `title`, `track`, `description` built from the PM Workflow §6.1 template — spec-type tasks additionally require a PM-supplied "Nguồn tham chiếu" link, never inferred). The user can add/edit/remove tasks directly during review — not just approve/reject the whole list — before the single explicit confirmation point ("Danh sách task như trên — đồng ý tạo trên Backlog/Jira?", never auto-`--yes`'d).
17
+ - New `scripts/ticket-writer.js` — `ak tasks create-tickets <file>.json [--json]` posts the approved list as real Backlog/Jira issues. `scripts/link-resolver.js` gained the write-side API calls it needed (`createBacklogIssue`, `createJiraIssue`, `fetchBacklogIssueTypes`, `fetchBacklogPriorities`) plus a generic `httpsPost` helper (form-encoded for Backlog, JSON for Jira) — the existing `httpsGet`-only file had no POST capability before this.
18
+ - **Deliberately separate WRITE credentials** (`BACKLOG_API_KEY_WRITE` / `JIRA_API_TOKEN_WRITE`) from the read-only keys `ak fetch-links`/`ak use` already rely on, per the PM Workflow doc's policy of never letting the read key create tickets. When missing, `ak tasks create-tickets` returns a structured `{"error":"missing-write-credentials", field, message}` instead of failing silently — the AI surfaces this in chat, asks the user to paste the key, saves it via the new `ak credentials set <key> <value>` (allowlisted to the keys this feature introduced — dedicated adapter credentials still go through `ak init --adapter`), and retries once.
19
+ - Project-id resolution reuses the existing `BACKLOG_DEFAULT_PROJECT_ID`/`ak backlog-projects`/`ak backlog-set-default-project` pattern; added the Jira equivalents (`ak jira-projects`, `ak jira-set-default-project`, `fetchJiraProjects` in `scripts/use.js`) so both adapters check local config before ever prompting.
20
+ - Approved tickets get their link written back into the originating `Meetings-Log`/`QnA-Log`/`Confirmations-Log` entry (`→ Tasks created: TICKET-101 (coding), ...`), keeping the traceability chain from PM Workflow §6 intact end-to-end.
21
+ - **Still open, tracked in the PM Workflow doc's Vấn đề 5 implementation note:** no fixed feedback→task-type rule table (AI still judges per-context); new tickets don't auto-attach `functionId`/labels (Dev/BA/QA still assign on `ak use TICKET-XXX`); Backlog issueType/priority default to the project's first issueType and a "Normal"-named priority unless overridden explicitly in the task JSON.
22
+
23
+ ## [0.2.0] - 2026-08-04
24
+
25
+ ### Added
26
+
27
+ - **`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):
28
+ - **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.
29
+ - **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`.
30
+ - 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).
31
+ - **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.
32
+ - 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.
33
+ - **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.
34
+ - **`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`:
35
+ - **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`.
36
+ - **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.
37
+ - 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.
38
+ - 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.
39
+ - **`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").
40
+ - 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.
41
+ - **`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).
42
+
43
+ ### Fixed
44
+
45
+ - **`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`.
46
+
47
+ ---
48
+
10
49
  ## [0.1.9] - 2026-08-04
11
50
 
12
51
  ### 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**.
@@ -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
- └── QnA-Log.md # 1 file duy nhất cho toàn dự án
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relipa/ai-flow-kit",
3
- "version": "0.1.9",
3
+ "version": "0.2.0-beta.1",
4
4
  "description": "All-in-one AI Flow Kit for team development with Claude AI - skills, templates, and MCP adapters",
5
5
  "author": "Example Team",
6
6
  "publishConfig": {
@@ -24,25 +24,6 @@ function norm(cmd) {
24
24
  return ALIAS_MAP[c] || c;
25
25
  }
26
26
 
27
- // ── Version helpers ─────────────────────────────────────────────────────────
28
- const CURRENT_VERSION = '0.1.6';
29
-
30
- function parseVersion(v) {
31
- if (!v || v === '-' || v === '' || v.toLowerCase() === 'unknown') return null;
32
- const core = v.split('-')[0]; // strip prerelease suffix, e.g. 0.1.5-beta.1 -> 0.1.5
33
- const parts = core.split('.').map(n => parseInt(n, 10));
34
- if (parts.some(n => Number.isNaN(n))) return null;
35
- return parts;
36
- }
37
-
38
- function compareVersion(a, b) {
39
- for (let i = 0; i < Math.max(a.length, b.length); i++) {
40
- const diff = (a[i] || 0) - (b[i] || 0);
41
- if (diff !== 0) return diff;
42
- }
43
- return 0;
44
- }
45
-
46
27
  // ── Parse log file ─────────────────────────────────────────────────────────
47
28
  function parseLog(filePath) {
48
29
  const lines = fs.readFileSync(filePath, 'utf-8').split(/\r?\n/);
@@ -58,19 +39,17 @@ function parseLog(filePath) {
58
39
  if (!user || user === '-' || user === '') continue;
59
40
 
60
41
  const timestamp = cols[0] || '';
61
- const version = cols[5] || '';
62
42
  const command = cols[6] || '';
63
43
  const ticket = cols[9] || '';
64
44
 
65
45
  const date = timestamp.split(' ')[0]; // dd/MM/yyyy
66
46
 
67
47
  if (!users[user]) {
68
- users[user] = { email: user, days: new Set(), events: 0, rawCmds: new Set(), gateCmds: [], versions: new Set() };
48
+ users[user] = { email: user, days: new Set(), events: 0, rawCmds: new Set(), gateCmds: [] };
69
49
  }
70
50
  const u = users[user];
71
51
  u.events++;
72
52
  if (date) u.days.add(date);
73
- if (version.trim()) u.versions.add(version.trim());
74
53
 
75
54
  const cmd = norm(command);
76
55
  if (cmd) u.rawCmds.add(cmd);
@@ -151,19 +130,6 @@ const SCORE_LABELS = [
151
130
  'Sử dụng thường xuyên workflow',
152
131
  ];
153
132
 
154
- // ── Version status for a user ──────────────────────────────────────────────
155
- function getVersionStatus(u) {
156
- const all = [...u.versions];
157
- const parsed = all.map(v => ({ raw: v, parts: parseVersion(v) })).filter(v => v.parts);
158
- if (parsed.length === 0) {
159
- return { status: all.length ? 'unknown' : 'none', latest: null, all };
160
- }
161
- parsed.sort((a, b) => compareVersion(a.parts, b.parts));
162
- const latest = parsed[parsed.length - 1];
163
- const isOutdated = compareVersion(latest.parts, parseVersion(CURRENT_VERSION)) < 0;
164
- return { status: isOutdated ? 'outdated' : 'ok', latest: latest.raw, all };
165
- }
166
-
167
133
  // ── Build summary row for each user ───────────────────────────────────────
168
134
  function buildRow(email, u) {
169
135
  const { events, days, rawCmds, gateCmds } = u;
@@ -232,7 +198,6 @@ function buildRow(email, u) {
232
198
  impactLabel: '',
233
199
  totalScore: score,
234
200
  notes,
235
- versionStatus: getVersionStatus(u),
236
201
  };
237
202
  }
238
203
 
@@ -331,78 +296,11 @@ function writeExcel(rows, workbook, sheetLabel, fromLabel, toLabel) {
331
296
  return sheet;
332
297
  }
333
298
 
334
- // ── Version warning sheet ───────────────────────────────────────────────────
335
- function writeVersionSheet(workbook, rows) {
336
- const sheet = workbook.addWorksheet('Version Warning');
337
- sheet.columns = [
338
- { key: 'no', width: 5 },
339
- { key: 'email', width: 30 },
340
- { key: 'status', width: 16 },
341
- { key: 'latest', width: 16 },
342
- { key: 'allVersions', width: 30 },
343
- { key: 'note', width: 50 },
344
- ];
345
-
346
- const border = {
347
- top: { style: 'thin' }, left: { style: 'thin' },
348
- bottom: { style: 'thin' }, right: { style: 'thin' },
349
- };
350
-
351
- sheet.addRow([`Cảnh báo phiên bản — Yêu cầu phiên bản hiện tại: ${CURRENT_VERSION}`]);
352
- sheet.mergeCells('A1:F1');
353
- const title = sheet.getCell('A1');
354
- title.font = { bold: true, size: 13, color: { argb: 'FF1F3864' } };
355
- title.alignment = { vertical: 'middle', horizontal: 'center' };
356
- title.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFD6DCE4' } };
357
- sheet.getRow(1).height = 28;
358
-
359
- const HEADERS = ['#', 'Email', 'Trạng thái', 'Phiên bản mới nhất', 'Các phiên bản dùng trong tuần', 'Ghi chú'];
360
- const hRow = sheet.addRow(HEADERS);
361
- hRow.height = 20;
362
- hRow.eachCell(cell => {
363
- cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF4F81BD' } };
364
- cell.font = { bold: true, color: { argb: 'FFFFFFFF' }, size: 11 };
365
- cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true };
366
- cell.border = border;
367
- });
368
-
369
- const warnings = rows.filter(row => row.versionStatus.status === 'outdated' || row.versionStatus.status === 'unknown');
370
-
371
- const STATUS_LABEL = { outdated: 'CŨ HƠN', unknown: 'KHÔNG XÁC ĐỊNH', ok: 'OK', none: 'Không có dữ liệu' };
372
- const STATUS_COLOR = { outdated: 'FFFFC7CE', unknown: 'FFFFEB9C' };
373
-
374
- warnings.forEach((row, idx) => {
375
- const vs = row.versionStatus;
376
- const note = vs.status === 'outdated'
377
- ? `Đang dùng ${vs.latest}, chưa cập nhật lên ${CURRENT_VERSION}`
378
- : 'Không đọc được phiên bản (giá trị "-" hoặc "unknown") — cần kiểm tra lại';
379
- const r = sheet.addRow([
380
- idx + 1, row.email, STATUS_LABEL[vs.status], vs.latest || '-', vs.all.join(', ') || '-', note,
381
- ]);
382
- r.height = 20;
383
- const fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: STATUS_COLOR[vs.status] || 'FFFFFFFF' } };
384
- r.eachCell({ includeEmpty: true }, (cell, col) => {
385
- cell.border = border;
386
- cell.fill = fill;
387
- cell.alignment = (col <= 4)
388
- ? { vertical: 'middle', horizontal: 'center' }
389
- : { vertical: 'middle', horizontal: 'left', wrapText: false };
390
- });
391
- });
392
-
393
- sheet.views = [{ state: 'frozen', ySplit: 2 }];
394
- sheet.autoFilter = { from: 'A2', to: 'F2' };
395
-
396
- return warnings;
397
- }
398
-
399
299
  async function writeExcelFile(rows, outputPath, sheetLabel, fromLabel, toLabel) {
400
300
  const workbook = new ExcelJS.Workbook();
401
301
  writeExcel(rows, workbook, sheetLabel, fromLabel, toLabel);
402
- const warnings = writeVersionSheet(workbook, rows);
403
302
  await workbook.xlsx.writeFile(outputPath);
404
- console.log(`Written: ${outputPath} (${rows.length} users, ${warnings.length} version warning(s))`);
405
- return warnings;
303
+ console.log(`Written: ${outputPath} (${rows.length} users)`);
406
304
  }
407
305
 
408
306
  // ── Canonical user list (fixed order) ─────────────────────────────────────
@@ -437,7 +335,7 @@ const LOG_EMAIL_ALIAS = {
437
335
  };
438
336
 
439
337
  const EMPTY_USER = (email) => ({
440
- email, events: 0, days: new Set(), rawCmds: new Set(), gateCmds: [], versions: new Set(),
338
+ email, events: 0, days: new Set(), rawCmds: new Set(), gateCmds: [],
441
339
  });
442
340
 
443
341
  // ── Main ───────────────────────────────────────────────────────────────────
@@ -471,7 +369,6 @@ const EMPTY_USER = (email) => ({
471
369
  u.events += data.events;
472
370
  data.days.forEach(d => u.days.add(d));
473
371
  data.rawCmds.forEach(c => u.rawCmds.add(c));
474
- data.versions.forEach(v => u.versions.add(v));
475
372
  u.gateCmds.push(...data.gateCmds);
476
373
  }
477
374
  }
@@ -482,9 +379,5 @@ const EMPTY_USER = (email) => ({
482
379
  return buildRow(email, u);
483
380
  });
484
381
 
485
- const warnings = await writeExcelFile(rows, outputFile, sheetLabel, fromLabel, toLabel);
486
- if (warnings.length) {
487
- console.log(`\n⚠️ Version warnings (< ${CURRENT_VERSION} or unknown):`);
488
- warnings.forEach(w => console.log(` - ${w.email}: ${w.versionStatus.latest || 'unknown'} (${w.versionStatus.status})`));
489
- }
382
+ await writeExcelFile(rows, outputFile, sheetLabel, fromLabel, toLabel);
490
383
  })();
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/init.js CHANGED
@@ -2,7 +2,7 @@ const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const os = require('os');
4
4
  const chalk = require('chalk');
5
- const { input, checkbox, confirm } = require('@inquirer/prompts');
5
+ const { input, checkbox, confirm, select } = require('@inquirer/prompts');
6
6
  const { syncDocsRepos } = require('./docs-repo');
7
7
  const memoryStore = require('./memory-store');
8
8
 
@@ -937,6 +937,29 @@ async function setupAdapter(projectDir, adapter) {
937
937
  console.log(chalk.green(`✓ Credentials verified successfully`));
938
938
  }
939
939
 
940
+ // Backlog: let the user pick a default project for tasks created manually (no ticket to
941
+ // derive one from otherwise) — kept for later use, e.g. syncing a local task up to Backlog.
942
+ if (adapter === 'backlog' && verifyResult.ok) {
943
+ const spaceKey = credentials.BACKLOG_SPACE_KEY;
944
+ const domain = spaceKey.includes('.') ? spaceKey : `${spaceKey}.backlog.com`;
945
+ try {
946
+ const { fetchBacklogProjects } = require('./use');
947
+ const projects = await fetchBacklogProjects(domain, credentials.BACKLOG_API_KEY);
948
+ if (projects.length > 0) {
949
+ const projectId = await select({
950
+ message: 'Default Backlog project for tasks created manually (no ticket):',
951
+ choices: projects.map((p) => ({ name: `${p.projectKey} ${p.name}`, value: p.id })),
952
+ });
953
+ const picked = projects.find((p) => p.id === projectId);
954
+ credentials.BACKLOG_DEFAULT_PROJECT_ID = picked.id;
955
+ credentials.BACKLOG_DEFAULT_PROJECT_KEY = picked.projectKey;
956
+ console.log(chalk.green(`✓ Default project set to ${picked.projectKey}.`));
957
+ }
958
+ } catch (err) {
959
+ console.log(chalk.gray(` (Could not fetch Backlog projects to pick a default: ${err.message} — skipping.)`));
960
+ }
961
+ }
962
+
940
963
  const claudeConfigDir = path.join(
941
964
  process.env.APPDATA ||
942
965
  (process.platform === 'darwin'