@relipa/ai-flow-kit 0.1.6 → 0.1.7
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 +30 -4
- package/bin/aiflow.js +38 -34
- package/custom/skills/review-plan/SKILL.md +19 -0
- package/custom/templates/memory/CODEOWNERS +8 -0
- package/custom/templates/memory/ci/memory-finalize.yml +9 -0
- package/custom/templates/memory/ci/memory-lint.yml +10 -0
- package/custom/templates/memory/gitlab/merge_request_templates/memory.md +18 -0
- package/custom/templates/memory/memory-item.md +25 -0
- package/custom/templates/memory/skeleton/00.Shared/architecture/_global/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/00.Shared/decisions/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/00.Shared/domain/_global/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/00.Shared/glossary/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/01.Lessons/ba/_global/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/01.Lessons/dev/_global/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/01.Lessons/pm/_global/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/01.Lessons/qa/_global/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/02.Instincts/approved/_global/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/03.Retro/.gitkeep +0 -0
- package/custom/templates/memory/skeleton/MEMORY.md +7 -0
- package/custom/templates/memory/skeleton/_deprecated/.gitkeep +0 -0
- package/custom/templates/shared/create-spec-workflow.md +13 -1
- package/custom/templates/shared/create-testcase-workflow.md +12 -0
- package/custom/templates/shared/gate-workflow.md +7 -0
- package/docs/common/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/scripts/create-score-excel.js +1 -1
- package/scripts/hooks/session-start.js +105 -2
- package/scripts/init.js +24 -0
- package/scripts/memory-store.js +391 -0
- package/scripts/memory.js +176 -247
- package/scripts/update.js +12 -0
- package/scripts/use.js +2 -1
package/README.md
CHANGED
|
@@ -459,12 +459,17 @@ ak validate src/Payment.java --ruleset strict
|
|
|
459
459
|
|
|
460
460
|
### `ak memory`
|
|
461
461
|
|
|
462
|
-
|
|
462
|
+
Draft, submit, and remove entries in the `99.Memory/` Project Brain (`AK-Docs/99.Memory/`) — see [Memory-Architecture-v1.0.md](docs/internal/Memory-Architecture-v1.0.md). Drafts are local-only until submitted; PM reviews and merges the Merge Request before a memory becomes team-visible.
|
|
463
463
|
|
|
464
464
|
```bash
|
|
465
|
-
ak memory
|
|
466
|
-
|
|
467
|
-
|
|
465
|
+
ak memory draft --category 01.Lessons/dev --function-id F-003_Payment \
|
|
466
|
+
--slug prevent-429-error --content "..." --tags payment,http-429 --workflows coding
|
|
467
|
+
|
|
468
|
+
ak memory list # local pending drafts (this machine only)
|
|
469
|
+
ak memory list --approved # team-approved memories
|
|
470
|
+
|
|
471
|
+
ak memory submit <pendingPath> --title "..." # move draft to destination, open MR
|
|
472
|
+
ak memory remove <path> --title "..." --reason "..." # propose removal (soft by default)
|
|
468
473
|
```
|
|
469
474
|
|
|
470
475
|
---
|
|
@@ -584,6 +589,27 @@ Then run `ak update` or `ak sync-skills` to apply.
|
|
|
584
589
|
|
|
585
590
|
> Summary of major changes per version. See full details in [CHANGELOG.md](docs/common/CHANGELOG.md).
|
|
586
591
|
|
|
592
|
+
### v0.1.7 — 2026-07-20
|
|
593
|
+
- **`99.Memory/` Project Brain (Phase 1):** New git-based, human-approved team knowledge base in `AK-Docs/99.Memory/` — replaces the dead `.aiflow/memory/` JSON store. AI drafts lessons/facts/decisions locally; a human submits them via Merge Request, PM approves.
|
|
594
|
+
- **`ak memory draft|list|submit|remove`:** New CLI (`scripts/memory-store.js` + rewritten `scripts/memory.js`), reusing the same branch-then-MR pattern as `ak docs branch`/`ak docs submit`.
|
|
595
|
+
- **Session-start auto-recall:** `session-start.js` now loads the memory index plus the top-N memories relevant to the active ticket's functionId/workflow/tags into every session automatically.
|
|
596
|
+
- **Retrospect step added to every Gate workflow** (DEV, BA, QA): drafts a memory at the end of each gate — and immediately when a human gives `BUG:`/`REVISION:` feedback, not deferred to hindsight.
|
|
597
|
+
- **`ak init`/`ak update`** auto-bootstrap the `99.Memory/` skeleton, committed locally but never auto-pushed (`main` is a protected branch).
|
|
598
|
+
- Docs: new `docs/internal/Memory-Architecture-v1.0.md` describing the 4 operating flows (Init/Store/Load/Remove) and the scoring model.
|
|
599
|
+
|
|
600
|
+
### v0.1.6 — 2026-07-13
|
|
601
|
+
- **Mandatory Source & Docs sync at the start of every Gate** across DEV/TESTER/EXECUTE/BA/QA workflows — a shared pre-flight procedure pulls the source repo plus `AK-Docs`/`Shared-Docs` before each gate; failures warn but never block.
|
|
602
|
+
- **New `gen-doc` task type (2-Gate):** lightweight flow for ad-hoc documentation tasks — plan → generate + self-review, no TDD/coding gates.
|
|
603
|
+
- **Figma wired into the DEV workflow end-to-end (Gate 1→4):** design fetched once and cached, then reused through spec/implementation/review; new anti-429 rate-limit guard for Figma MCP calls.
|
|
604
|
+
- **`ak docs branch` / `ak docs submit`:** new CLI for the AI to create a docs branch and open a Merge Request — the same "never commits/pushes unasked" guarantee as elsewhere, extended to `AK-Docs`/`Shared-Docs`.
|
|
605
|
+
- Fixed: `ak prompt <type>` and `ak init`'s `.gitignore` still referencing the deprecated `plan/` convention.
|
|
606
|
+
|
|
607
|
+
### v0.1.5 — 2026-07-01
|
|
608
|
+
- **DEV workflow output migrated `plan/[ticket-id]/` → `AK-Docs/04.Coding/`** — same folder-per-feature/file-per-ticket convention BA/QA already used; new Gate 3 (`03.TDD-Notes/`) and Gate 5 (`05.Pull-Requests/`) artifacts.
|
|
609
|
+
- **Mandatory `functionId` pre-flight** extended to the DEV workflow (BA/QA already had it) — resolved from context, inferred from input, or asked directly; no gate output is written without it.
|
|
610
|
+
- **New `/coding` slash command** — manual fallback to start/resume the DEV workflow when the SessionStart auto-start message doesn't re-fire (e.g. ticket switched via `ak use` in another terminal while a session is already open).
|
|
611
|
+
- Testing skills consolidated into `custom/skills/test-skills/`; skill filenames standardized to English kebab-case.
|
|
612
|
+
|
|
587
613
|
### v0.1.4 — 2026-06-29
|
|
588
614
|
- **Create Spec Flow (4-Gate BA Workflow):** New `taskType: "spec"` — Q&A Analysis → Prototype Design → UC Spec. AI follows UCflow process guided by `ba-skills/` sub-skills.
|
|
589
615
|
- **Create Testcase Flow (4-Gate QA Workflow):** New `taskType: "testcase"` — Requirement Analysis → Scenario Building → Detailed TC Design → Review & Optimize. AI applies BVA, Equivalence Partitioning, Decision Table techniques.
|
package/bin/aiflow.js
CHANGED
|
@@ -85,12 +85,10 @@ program
|
|
|
85
85
|
let sub = sec;
|
|
86
86
|
if (sec && !sec.startsWith('-')) {
|
|
87
87
|
const memAliases = {
|
|
88
|
-
'
|
|
89
|
-
'g': 'get',
|
|
88
|
+
'd': 'draft',
|
|
90
89
|
'ls': 'list',
|
|
91
|
-
'
|
|
92
|
-
'
|
|
93
|
-
'cl': 'clear'
|
|
90
|
+
'sb': 'submit',
|
|
91
|
+
'rm': 'remove',
|
|
94
92
|
};
|
|
95
93
|
if (memAliases[sec]) sub = memAliases[sec];
|
|
96
94
|
cmd = `memory.${sub}`;
|
|
@@ -351,45 +349,51 @@ program
|
|
|
351
349
|
});
|
|
352
350
|
});
|
|
353
351
|
|
|
354
|
-
// ── memory
|
|
355
|
-
//
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
memCmd
|
|
359
|
-
.command('save <key> <value>')
|
|
360
|
-
.alias('s')
|
|
361
|
-
.description('Save a memory entry')
|
|
362
|
-
.action((key, value) => { memoryCommand('save', { key, value }); });
|
|
352
|
+
// ── memory (99.Memory/ Project Brain — see docs/internal/Memory-Architecture-v1.0.md) ──
|
|
353
|
+
// Same "AI drafts — human approves via MR" pattern as `docs` below: drafts are local-only
|
|
354
|
+
// (_pending/, gitignored) until `submit` opens a Merge Request for PM review.
|
|
355
|
+
const memCmd = program.command('memory').alias('mem').description('Manage 99.Memory/ project knowledge (draft, list, submit, remove)');
|
|
363
356
|
|
|
364
357
|
memCmd
|
|
365
|
-
.command('
|
|
366
|
-
.alias('
|
|
367
|
-
.description('
|
|
368
|
-
.
|
|
358
|
+
.command('draft')
|
|
359
|
+
.alias('d')
|
|
360
|
+
.description('Create a local memory draft in _pending/ (not yet shared with the team)')
|
|
361
|
+
.requiredOption('-c, --category <category>', 'e.g. 00.Shared/architecture, 01.Lessons/dev, 02.Instincts/approved')
|
|
362
|
+
.requiredOption('-s, --slug <slug>', 'short kebab-case name, e.g. prevent-429-error')
|
|
363
|
+
.requiredOption('--content <text>', 'memory body (≤150 words, 1 fact)')
|
|
364
|
+
.option('-f, --function-id <id>', 'functionId this memory is scoped to (omit/= global for cross-project facts)')
|
|
365
|
+
.option('--scope <scope>', 'alternative to --function-id for flat categories (glossary/decisions)')
|
|
366
|
+
.option('-t, --tags <list>', 'comma-separated tags, scorer matches on these')
|
|
367
|
+
.option('-w, --workflows <list>', 'comma-separated workflows (coding, create-spec, create-testcase, gen-doc, all)')
|
|
368
|
+
.option('--source <text>', 'trace: ticket / Gate this was learned from')
|
|
369
|
+
.option('--confidence <n>', 'AI self-rated 0.3–0.7', '0.5')
|
|
370
|
+
.action((options) => { memoryCommand('draft', options); });
|
|
369
371
|
|
|
370
372
|
memCmd
|
|
371
373
|
.command('list')
|
|
372
374
|
.alias('ls')
|
|
373
|
-
.
|
|
374
|
-
.action(() => { memoryCommand('list'); });
|
|
375
|
-
|
|
376
|
-
memCmd
|
|
377
|
-
.command('search <query>')
|
|
378
|
-
.alias('sr')
|
|
379
|
-
.description('Search memories by keyword')
|
|
380
|
-
.action((query) => { memoryCommand('search', { query }); });
|
|
375
|
+
.option('-a, --approved', 'list approved memories instead of local pending drafts')
|
|
376
|
+
.action((options) => { memoryCommand('list', options); });
|
|
381
377
|
|
|
382
378
|
memCmd
|
|
383
|
-
.command('
|
|
384
|
-
.alias('
|
|
385
|
-
.description('
|
|
386
|
-
.
|
|
379
|
+
.command('submit <path>')
|
|
380
|
+
.alias('sb')
|
|
381
|
+
.description('Move a pending draft (path from `ak memory list`) to its destination and open a Merge Request')
|
|
382
|
+
.requiredOption('-t, --title <title>', 'commit message / MR title')
|
|
383
|
+
.option('-d, --description <text>', 'MR description', '')
|
|
384
|
+
.option('-y, --yes', 'skip the interactive confirm — only pass this after the user has approved in chat')
|
|
385
|
+
.action((path, options) => { memoryCommand('submit', { ...options, _positional: [path] }); });
|
|
387
386
|
|
|
388
387
|
memCmd
|
|
389
|
-
.command('
|
|
390
|
-
.alias('
|
|
391
|
-
.description('
|
|
392
|
-
.
|
|
388
|
+
.command('remove <path>')
|
|
389
|
+
.alias('rm')
|
|
390
|
+
.description('Propose removing an approved memory (path from `ak memory list --approved`)')
|
|
391
|
+
.requiredOption('-t, --title <title>', 'commit message / MR title')
|
|
392
|
+
.option('-d, --description <text>', 'MR description', '')
|
|
393
|
+
.option('--reason <text>', 'why this memory is being removed')
|
|
394
|
+
.option('--hard', 'delete outright instead of moving to _deprecated/ (rarely — see doc §Luồng 4)')
|
|
395
|
+
.option('-y, --yes', 'skip the interactive confirm — only pass this after the user has approved in chat')
|
|
396
|
+
.action((path, options) => { memoryCommand('remove', { ...options, _positional: [path] }); });
|
|
393
397
|
|
|
394
398
|
// ── docs (branch + Merge Request workflow for AK-Docs/Shared-Docs) ─────
|
|
395
399
|
// See docs/internal/Docs-Management-Flow.md — PM reviews & merges `main`;
|
|
@@ -164,6 +164,22 @@ Create file `AK-Docs/04.Coding/04.Reviews/[functionId]/[ticketId].md`:
|
|
|
164
164
|
- [ ] UI matches `design-context.md` (layout, color, typography, spacing) — UI tickets only
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
### Step 2.5: Retrospect + propose memory drafts
|
|
168
|
+
|
|
169
|
+
Synthesize what was learned this task. **Priority order — human corrections first:** if this is a repeat pass through Gate 4 (the developer already sent "BUG: ..." at least once this task), the developer's own correction is the single highest-value lesson — scan back through this session for it and draft it even if you already drafted something for the earlier BUG at Step 4 (dedup will catch an exact repeat; don't skip capturing it out of caution). Only after that, add anything else genuinely new: architecture facts discovered, decisions made and why. For each candidate, create a **local draft** (no approval needed yet — `_pending/` is local-only, doc `docs/internal/Memory-Architecture-v1.0.md`):
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
ak memory draft --category 01.Lessons/dev --function-id [functionId] \
|
|
173
|
+
--slug <short-kebab-slug> --content "<≤150 từ, 1 fact>" \
|
|
174
|
+
--tags <tag1,tag2> --workflows coding --source "[ticket-id] / Gate 4"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Other useful categories here: `00.Shared/architecture` (facts about the system discovered while coding), `00.Shared/decisions` (a technical choice made and why). Skip this step if nothing genuinely new was learned — don't manufacture a memory just to have one.
|
|
178
|
+
|
|
179
|
+
If `ak memory draft` reports a conflict (a similar memory already exists), don't create a duplicate — mention it to the developer instead so they can decide whether to edit the existing one.
|
|
180
|
+
|
|
181
|
+
List the created draft(s) in the Step 3 message below so the developer knows what's sitting in `_pending/` — they (or anyone on the team) can inspect and `ak memory submit` it later when ready to share with the team.
|
|
182
|
+
|
|
167
183
|
### Step 3: GATE 4 — Present to Developer
|
|
168
184
|
|
|
169
185
|
```markdown
|
|
@@ -177,6 +193,7 @@ Summary: AK-Docs/04.Coding/04.Reviews/[functionId]/[ticketId].md
|
|
|
177
193
|
- Tests: ✅ [N] passed / ❌ [N] failed
|
|
178
194
|
- Impact: [Low/Medium/High]
|
|
179
195
|
- Checklist: [N/N] items ✅
|
|
196
|
+
- Memory drafts created: [N] (local, `_pending/` — `ak memory submit` when ready to share)
|
|
180
197
|
|
|
181
198
|
**You need to:**
|
|
182
199
|
1. Review the summary above
|
|
@@ -199,10 +216,12 @@ Summary: AK-Docs/04.Coding/04.Reviews/[functionId]/[ticketId].md
|
|
|
199
216
|
→ Guide on creating a Pull Request
|
|
200
217
|
|
|
201
218
|
**If the developer types "BUG: [description]" — coding bug:**
|
|
219
|
+
→ **Immediately draft a memory** capturing exactly what the developer flagged and why it was wrong (`ak memory draft --category 01.Lessons/dev --function-id [functionId] --slug <slug> --content "<the bug + the fix>" --workflows coding --source "[ticket-id] / Gate 4 dev feedback"`) — do this before fixing, while the correction is fresh; don't wait for Step 2.5 on the next pass to catch it in hindsight.
|
|
202
220
|
→ Analyze bug, fix, rerun verification
|
|
203
221
|
→ Repeat from Step 1 of Gate 4
|
|
204
222
|
|
|
205
223
|
**If the developer types "BUG: [description]" — requirement bug:**
|
|
224
|
+
→ **Immediately draft a memory** (same category/command as above) capturing what was misunderstood about the requirement and what it actually should have been — this is a requirement-comprehension lesson, valuable even though Gate 1 itself has no retrospect step of its own.
|
|
206
225
|
→ Notify: "This is a requirement bug, requirement document needs update"
|
|
207
226
|
→ Return to Gate 1, update requirement.md, wait for APPROVED again
|
|
208
227
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Áp dụng thủ công vào file CODEOWNERS của repo AK-Docs (mục 5.1.2 Memory-Architecture-v1.0.md).
|
|
2
|
+
# GitLab tự gợi ý các reviewer này làm Consult khi diff đụng đúng thư mục — không phải approver
|
|
3
|
+
# (approver luôn là PM, cấu hình riêng ở MR approval rule, không qua CODEOWNERS).
|
|
4
|
+
|
|
5
|
+
99.Memory/00.Shared/architecture/ @TL
|
|
6
|
+
99.Memory/00.Shared/domain/ @BA
|
|
7
|
+
99.Memory/00.Shared/glossary/ @BA
|
|
8
|
+
99.Memory/02.Instincts/ @TL
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Áp dụng thủ công vào .gitlab-ci.yml của repo AK-Docs (mục 5.1.2 Memory-Architecture-v1.0.md).
|
|
2
|
+
# Chạy khi MR label `memory` đã đủ approval từ PM — flip status, rebuild MEMORY.md, commit lên branch.
|
|
3
|
+
memory-finalize:
|
|
4
|
+
stage: finalize
|
|
5
|
+
rules:
|
|
6
|
+
- if: '$CI_MERGE_REQUEST_LABELS =~ /memory/ && $CI_MERGE_REQUEST_APPROVED == "true"'
|
|
7
|
+
script:
|
|
8
|
+
- node scripts/ci/memory-finalize.js # flip status: approved, điền reviewed_by, rebuild MEMORY.md
|
|
9
|
+
# (script CI thực tế nằm trong repo AK-Docs, không phải kit)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Áp dụng thủ công vào .gitlab-ci.yml của repo AK-Docs (mục 5.1.2 Memory-Architecture-v1.0.md).
|
|
2
|
+
# Chạy trên mọi MR có label `memory`, TRƯỚC khi PM approve.
|
|
3
|
+
memory-lint:
|
|
4
|
+
stage: lint
|
|
5
|
+
rules:
|
|
6
|
+
- if: '$CI_MERGE_REQUEST_LABELS =~ /memory/'
|
|
7
|
+
script:
|
|
8
|
+
- node scripts/ci/memory-lint.js # validate frontmatter đủ trường, ≤150 từ, 1 fact/file,
|
|
9
|
+
# id không trùng, id khớp đường dẫn file, quét secret/PII
|
|
10
|
+
# (script CI thực tế nằm trong repo AK-Docs, không phải kit)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Memory MR — Ticket: <!-- TICKET-123 -->
|
|
2
|
+
|
|
3
|
+
**Loại:** Thêm mới / Gỡ bỏ (soft-remove / hard-remove)
|
|
4
|
+
**Mem-id(s):** <!-- mem-F003-refund-flow, mem-F003-prevent-429-error -->
|
|
5
|
+
|
|
6
|
+
### Checklist PM (bắt buộc trước khi approve)
|
|
7
|
+
|
|
8
|
+
- [ ] Đúng sự thật và còn hiệu lực?
|
|
9
|
+
- [ ] Trace được nguồn gốc (`source:` trỏ đúng ticket/Gate)?
|
|
10
|
+
- [ ] Nội dung ngắn gọn (≤150 từ), đúng khuôn mẫu 1 file = 1 fact?
|
|
11
|
+
- [ ] Có hành động cụ thể áp dụng được (mục "Áp dụng")?
|
|
12
|
+
- [ ] Phạm vi (`scope:`) hẹp nhất có thể — không lạm dụng `global`?
|
|
13
|
+
- [ ] Không mâu thuẫn với `.rules/`?
|
|
14
|
+
- [ ] Đã tham vấn đúng người cho nội dung nhạy cảm (TL cho kỹ thuật, BA/Comtor cho glossary/domain)?
|
|
15
|
+
|
|
16
|
+
### Consult (tự động theo CODEOWNERS)
|
|
17
|
+
|
|
18
|
+
TL/BA được tag tự động theo thư mục bị đụng — đây là góp ý, quyền quyết vẫn ở PM.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: mem-<functionId>-<slug> # CLI tự sinh từ vị trí file: mem-<functionId>-<slug>
|
|
3
|
+
# slug do AI đặt — ngắn, đọc là hiểu memory lưu gì
|
|
4
|
+
# (vd: basic-payment-flow, refund-flow, prevent-429-error).
|
|
5
|
+
# KHÔNG có timestamp: trùng slug trong cùng folder chính là
|
|
6
|
+
# tín hiệu chống trùng lặp — CLI hỏi "memory tương tự đã có,
|
|
7
|
+
# cập nhật bản cũ thay vì tạo mới?"
|
|
8
|
+
type: lesson | fact | decision | glossary | instinct
|
|
9
|
+
workflows: [coding, create-testcase] # workflow nào cần recall; [all] nếu mọi workflow
|
|
10
|
+
tags: [payment, refund, http-429] # ascii-lowercase, AI tự sinh khi tạo draft —
|
|
11
|
+
# scorer CHỈ so khớp trên trường này (không so body — JP/VN)
|
|
12
|
+
scope: F-003_Payment | global # trùng với folder chứa file; global → file đặt trong _global/
|
|
13
|
+
confidence: 0.6 # AI tự chấm 0.3–0.7; reviewer chỉnh khi duyệt
|
|
14
|
+
source: TICKET-123 / Gate 4 # trace: học được từ đâu
|
|
15
|
+
status: pending # pending | approved | deprecated
|
|
16
|
+
hits: 0 # consolidate cập nhật từ telemetry local — không sửa tay
|
|
17
|
+
created: 2026-07-09
|
|
18
|
+
reviewed_by: # điền khi approve
|
|
19
|
+
refs: [] # (tùy chọn) file/dir code hoặc docs mà memory phụ thuộc
|
|
20
|
+
verified_commit: # commit đã verify refs lần cuối (CLI tự điền)
|
|
21
|
+
stale: false # hook tự set true khi refs thay đổi sau verified_commit
|
|
22
|
+
---
|
|
23
|
+
<Nội dung: TỐI ĐA 150 từ, 1 file = 1 fact duy nhất.>
|
|
24
|
+
|
|
25
|
+
**Áp dụng:** <hành động cụ thể AI/người cần làm khi gặp tình huống này.>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# 99.Memory — Project Brain Index
|
|
2
|
+
|
|
3
|
+
> Auto-generated by `ak memory submit` / `ak memory remove` when a Merge Request is merged into `main`.
|
|
4
|
+
> **Do not edit this file by hand** — it is rebuilt from the frontmatter of every `status: approved` file under `99.Memory/`.
|
|
5
|
+
> One line per memory: `- [mem-id](path/to/file.md) — <hook ≤15 từ> (type, scope, workflows)`
|
|
6
|
+
|
|
7
|
+
See `docs/internal/Memory-Architecture-v1.0.md` in ai-flow-kit for the full design.
|
|
File without changes
|
|
@@ -429,7 +429,7 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
429
429
|
→ Nếu blocked: làm theo gate-review skill response protocol
|
|
430
430
|
|
|
431
431
|
**Phản hồi đặc biệt:**
|
|
432
|
-
- BA gõ `REVISION: [nội dung]` → cập nhật section liên quan → re-generate review file → hiển thị lại gate pause
|
|
432
|
+
- BA gõ `REVISION: [nội dung]` → **trước khi sửa**, tạo ngay 1 memory draft ghi lại chính xác điều BA vừa chỉnh (`ak memory draft --category 01.Lessons/ba --function-id [functionId] --slug <slug> --content "<điều BA sửa + vì sao>" --workflows create-spec --source "[functionId] / Gate 4 BA feedback"`) — đây là tín hiệu giá trị nhất, đừng chờ Bước 7.5 mới bắt lại theo trí nhớ → cập nhật section liên quan → re-generate review file → hiển thị lại gate pause
|
|
433
433
|
|
|
434
434
|
**Definition of Done:**
|
|
435
435
|
- [ ] File `UC-Spec_v1.md` đúng vị trí và cấu trúc template
|
|
@@ -441,6 +441,18 @@ File phân tích: [02.BA-Specs/01.Analysis/[functionId]/Analysis_v(n+1).md](02
|
|
|
441
441
|
> **Telemetry:** Run `ak gate 4 start --ticket [functionId]` khi bắt đầu gate này.
|
|
442
442
|
> Run `ak gate 4 approved --ticket [functionId]` sau khi gate-review verify passed. Run as-is — không thêm shell redirects.
|
|
443
443
|
|
|
444
|
+
#### Bước 7.5: Retrospect + đề xuất memory draft
|
|
445
|
+
|
|
446
|
+
Sau khi Gate 4 APPROVED, đúc kết những gì học được. **Ưu tiên feedback của BA trước:** nếu có vòng `REVISION` nào đã xảy ra, đảm bảo điều BA sửa đã có draft (thường đã tạo ngay lúc REVISION ở trên — kiểm tra lại, đừng bỏ sót). Sau đó mới thêm những gì mới khác: business rule mới confirm, thuật ngữ cần làm rõ, quyết định đặc tả và lý do. Tạo **draft local** cho từng candidate (chưa cần duyệt — `_pending/` chỉ ở local, xem `docs/internal/Memory-Architecture-v1.0.md`):
|
|
447
|
+
|
|
448
|
+
```
|
|
449
|
+
ak memory draft --category 00.Shared/domain --function-id [functionId] \
|
|
450
|
+
--slug <slug-ngắn> --content "<≤150 từ, 1 fact>" \
|
|
451
|
+
--tags <tag1,tag2> --workflows create-spec --source "[functionId] / Gate 4"
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Category khác hữu ích ở đây: `00.Shared/glossary` (thuật ngữ JP↔VN↔EN mới xác nhận — flat, không cần `--function-id`), `01.Lessons/ba` (bài học khi làm spec), `00.Shared/decisions` (quyết định đặc tả). Bỏ qua bước này nếu không có gì thực sự mới. Nếu `ak memory draft` báo trùng, đừng tạo bản mới — báo cho BA để họ quyết định sửa bản cũ.
|
|
455
|
+
|
|
444
456
|
#### Bước 8: Submit AK-Docs lên remote qua Merge Request
|
|
445
457
|
|
|
446
458
|
Sau khi Gate 4 đã APPROVED (UC Spec hoàn thành):
|
|
@@ -485,6 +485,18 @@ Trước khi ghi bất kỳ file nào vào `03.Testing/`, đảm bảo AK-Docs
|
|
|
485
485
|
> **Telemetry:** Run `ak gate 4 start --ticket [functionId]` khi bắt đầu gate này.
|
|
486
486
|
> Run `ak gate 4 approved --ticket [functionId]` sau khi gate-review verify passed. Run as-is — không thêm shell redirects.
|
|
487
487
|
|
|
488
|
+
#### Bước 7.5: Retrospect + đề xuất memory draft
|
|
489
|
+
|
|
490
|
+
Sau khi Gate 4 APPROVED, đúc kết những gì học được. **Ưu tiên trước:** nếu review ở Bước 7 từng phát hiện Major/Critical issue phải sửa lại, đó là bài học giá trị nhất — đảm bảo có draft cho đúng issue đó. Sau đó mới thêm lỗi/bẫy môi trường gặp khi test, business rule cần làm rõ thêm. Tạo **draft local** cho từng candidate (chưa cần duyệt — `_pending/` chỉ ở local, xem `docs/internal/Memory-Architecture-v1.0.md`):
|
|
491
|
+
|
|
492
|
+
```
|
|
493
|
+
ak memory draft --category 01.Lessons/qa --function-id [functionId] \
|
|
494
|
+
--slug <slug-ngắn> --content "<≤150 từ, 1 fact>" \
|
|
495
|
+
--tags <tag1,tag2> --workflows create-testcase --source "[functionId] / Gate 4"
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
Category khác hữu ích ở đây: `00.Shared/domain` (business rule phát hiện khi thiết kế test), `00.Shared/glossary` (thuật ngữ — flat, không cần `--function-id`). Bỏ qua bước này nếu không có gì thực sự mới. Nếu `ak memory draft` báo trùng, đừng tạo bản mới — báo cho QA để họ quyết định sửa bản cũ.
|
|
499
|
+
|
|
488
500
|
#### Bước 8: Submit AK-Docs lên remote qua Merge Request
|
|
489
501
|
|
|
490
502
|
Sau khi Gate 4 đã APPROVED (bộ Test Case hoàn thành):
|
|
@@ -655,6 +655,13 @@ Bugs logged: [N] | Skipped: [N]
|
|
|
655
655
|
- **Markdown:** Save to `AK-Docs/04.Coding/02.Plans/[functionId]/[ticketId].md` (or the custom path/format noted in the requirement doc — e.g. Excel; still write a short pointer + summary into this file so the AK-Docs history stays complete)
|
|
656
656
|
4. Self-review: verify content completeness against the approved requirement outline
|
|
657
657
|
5. Create `AK-Docs/04.Coding/02.Plans/[functionId]/[ticketId]-summary.md` with a brief summary of what was generated
|
|
658
|
+
5.5. **Retrospect + propose memory drafts:** synthesize anything genuinely new learned while producing this document (architecture fact, business rule, decision) and create a **local draft** for each (no approval needed yet — `_pending/` is local-only, see `docs/internal/Memory-Architecture-v1.0.md`):
|
|
659
|
+
```
|
|
660
|
+
ak memory draft --category 00.Shared/architecture --function-id [functionId] \
|
|
661
|
+
--slug <short-kebab-slug> --content "<≤150 words, 1 fact>" \
|
|
662
|
+
--tags <tag1,tag2> --workflows gen-doc --source "[ticket-id] / Gate 2"
|
|
663
|
+
```
|
|
664
|
+
Skip if nothing new was learned. If `ak memory draft` reports a conflict, don't duplicate — mention the existing one instead.
|
|
658
665
|
6. **Submit AK-Docs lên remote qua Merge Request:**
|
|
659
666
|
- Soạn title + description cho MR (tóm tắt tài liệu vừa tạo, link ticket gốc), hiển thị cho người dùng xem trước.
|
|
660
667
|
- 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/tạo MR khi sẵn sàng.
|
package/docs/common/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,22 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.1.7] - 2026-07-20
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`99.Memory/` Project Brain — Phase 1** (`docs/internal/Memory-Architecture-v1.0.md`, v1.1). A git-based, human-approved team knowledge base living inside `AK-Docs/99.Memory/`, replacing the legacy `.aiflow/memory/` JSON store whose only "auto-load" function was dead code no hook ever called. AI now accumulates lessons/facts/decisions across tasks, scored and recalled automatically at session start.
|
|
17
|
+
- **`scripts/memory-store.js`** — new engine: `99.Memory/` skeleton bootstrap; `mem-<functionId>-<slug>` id scheme with folder-per-functionId layout (`_global/` for cross-project facts, flat for `glossary`/`decisions`); hand-rolled frontmatter parse/serialize (no new YAML dependency); dedup-aware draft creation (a repeated slug in the same folder surfaces as a conflict instead of silently duplicating); the §5.2 scoring formula (folder/workflow/tag match, confidence, staleness decay, pending penalty); the Layer-2 relevant-set loader (top-N within a token budget); a local hit-count ledger. Deliberately **dependency-free** (no `fs-extra`/`chalk`) — this file is copied standalone into `.claude/lib/memory-store.js` in every project so the session-start hook can `require()` it without the kit's own `node_modules`.
|
|
18
|
+
- **`scripts/memory.js`** — full rewrite: `ak memory draft|list|submit|remove`, replacing the old `save/get/list/search/delete/clear`. `submit`/`remove` reuse `scripts/docs-branch.js`'s existing branch-then-MR mechanism — same "AI drafts, human approves via Merge Request" model already used by `ak docs branch`/`ak docs submit`.
|
|
19
|
+
- **`scripts/hooks/session-start.js`** — new step: injects Layer 1 (`MEMORY.md` index, always) + Layer 2 (top-N scored memories relevant to the active ticket's functionId/workflow/tags, budget-capped) into session context. Pulls `AK-Docs` with a short timeout first; a failed/offline pull only logs a warning and falls back to the local copy, never blocks the session.
|
|
20
|
+
- **`scripts/init.js` / `scripts/update.js`** — auto-bootstrap the `99.Memory/` skeleton and gitignore its `_pending/` folder (local-only drafts) the first time `AK-Docs` is present. Both are committed locally on whatever branch is checked out but **never auto-pushed**, since `main` is a protected branch and pushing is left to a human.
|
|
21
|
+
- **`custom/templates/memory/`** — `99.Memory/` skeleton tree, the memory-item frontmatter template, a GitLab MR template, a `CODEOWNERS` snippet, and reference `memory-lint`/`memory-finalize` CI job YAML (copyable snippets for a project admin to wire into a live pipeline — not auto-applied, no live GitLab project to attach them to from the kit itself).
|
|
22
|
+
- **New "Retrospect + propose memory draft" step** added to all 4 Gate workflows — `review-plan` (Gate 4), `create-spec-workflow` (Gate 4), `create-testcase-workflow` (Gate 4), and `gate-workflow`'s gen-doc flow (Gate 2). Human review feedback (`BUG: ...`, `REVISION: ...`) is captured as a memory draft **immediately when given**, before the fix/update — not deferred to a generic end-of-gate retrospective where it could get lost or diluted.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- `.aiflow/memory/` (JSON key/value store) and its `save/get/search/delete/clear` commands are retired outright — superseded by `99.Memory/`, no backward-compat shim (nothing else in the kit read that store).
|
|
27
|
+
|
|
12
28
|
## [0.1.6] - 2026-07-13
|
|
13
29
|
|
|
14
30
|
### Added
|
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ function norm(cmd) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// ── Version helpers ─────────────────────────────────────────────────────────
|
|
28
|
-
const CURRENT_VERSION = '0.1.
|
|
28
|
+
const CURRENT_VERSION = '0.1.5';
|
|
29
29
|
|
|
30
30
|
function parseVersion(v) {
|
|
31
31
|
if (!v || v === '-' || v === '' || v.toLowerCase() === 'unknown') return null;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
const fs = require('fs');
|
|
10
10
|
const path = require('path');
|
|
11
11
|
const os = require('os');
|
|
12
|
+
const { execSync } = require('child_process');
|
|
12
13
|
|
|
13
14
|
function loadTelemetry() {
|
|
14
15
|
try { return require('../telemetry/record'); } catch (_) { }
|
|
@@ -29,7 +30,7 @@ let tasksDir = '';
|
|
|
29
30
|
let raw = '';
|
|
30
31
|
process.stdin.setEncoding('utf-8');
|
|
31
32
|
process.stdin.on('data', chunk => { raw += chunk; });
|
|
32
|
-
process.stdin.on('end', () => {
|
|
33
|
+
process.stdin.on('end', async () => {
|
|
33
34
|
let hookData = {};
|
|
34
35
|
try { hookData = JSON.parse(raw || '{}'); } catch (_) { }
|
|
35
36
|
|
|
@@ -59,9 +60,10 @@ process.stdin.on('end', () => {
|
|
|
59
60
|
|
|
60
61
|
// ── 2. Load active ticket context ──────────────────────────────
|
|
61
62
|
let contextBlock = '';
|
|
63
|
+
let ctx = null;
|
|
62
64
|
try {
|
|
63
65
|
if (fs.existsSync(contextPath)) {
|
|
64
|
-
|
|
66
|
+
ctx = JSON.parse(fs.readFileSync(contextPath, 'utf-8'));
|
|
65
67
|
if (ctx.taskId && ctx.title) {
|
|
66
68
|
const taskState = loadTaskState(ctx.taskId);
|
|
67
69
|
contextBlock = buildContextPrompt(ctx, taskState);
|
|
@@ -97,6 +99,34 @@ process.stdin.on('end', () => {
|
|
|
97
99
|
}
|
|
98
100
|
} catch (_) { }
|
|
99
101
|
|
|
102
|
+
// ── 3.5 Load relevant memory (99.Memory/ Project Brain) ────────
|
|
103
|
+
// See docs/internal/Memory-Architecture-v1.0.md — Luồng 3 (Nạp/Sử dụng).
|
|
104
|
+
let memoryBlock = '';
|
|
105
|
+
try {
|
|
106
|
+
const workspaceRoot = resolveWorkspaceRoot(projectRoot);
|
|
107
|
+
const akDocsPath = path.join(workspaceRoot, 'AK-Docs');
|
|
108
|
+
if (fs.existsSync(akDocsPath)) {
|
|
109
|
+
if (fs.existsSync(path.join(akDocsPath, '.git'))) {
|
|
110
|
+
pullAkDocsWithTimeout(akDocsPath);
|
|
111
|
+
}
|
|
112
|
+
const memoryStore = require('../lib/memory-store');
|
|
113
|
+
const functionId = ctx ? (ctx.functionId || ctx.screenId) : null;
|
|
114
|
+
const workflow = inferWorkflow(ctx);
|
|
115
|
+
const tags = ctx ? extractQueryTags(ctx) : [];
|
|
116
|
+
|
|
117
|
+
const [indexContent, relevant] = await Promise.all([
|
|
118
|
+
memoryStore.readIndex(workspaceRoot),
|
|
119
|
+
memoryStore.loadRelevant(workspaceRoot, { functionId, workflow, tags }),
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
memoryBlock = buildMemoryBlock(indexContent, relevant);
|
|
123
|
+
// recordHits' ledger lives under THIS project's own .aiflow/ (projectRoot),
|
|
124
|
+
// not the workspace root — matches where context/tasks/ already live. Batched
|
|
125
|
+
// into one read-modify-write (see memory-store.js) instead of one call per id.
|
|
126
|
+
await memoryStore.recordHits(projectRoot, relevant.map(m => m.id));
|
|
127
|
+
}
|
|
128
|
+
} catch (_) { }
|
|
129
|
+
|
|
100
130
|
// ── 4. Combine and output ──────────────────────────────────────
|
|
101
131
|
const parts = [];
|
|
102
132
|
if (skillContent) {
|
|
@@ -105,6 +135,9 @@ process.stdin.on('end', () => {
|
|
|
105
135
|
if (contextBlock) {
|
|
106
136
|
parts.push(contextBlock);
|
|
107
137
|
}
|
|
138
|
+
if (memoryBlock) {
|
|
139
|
+
parts.push(memoryBlock);
|
|
140
|
+
}
|
|
108
141
|
|
|
109
142
|
const combined = parts.join('\n\n');
|
|
110
143
|
const escaped = combined
|
|
@@ -126,6 +159,76 @@ process.stdin.on('end', () => {
|
|
|
126
159
|
|
|
127
160
|
// ── Helpers ────────────────────────────────────────────────────
|
|
128
161
|
|
|
162
|
+
// AK-Docs lives as a sibling of the project repo at the workspace root (see
|
|
163
|
+
// scripts/docs-repo.js), but this hook can't rely on process.cwd() — Claude Code's
|
|
164
|
+
// hook invocation cwd isn't guaranteed to be the workspace root. Try the project
|
|
165
|
+
// root itself first (project opened standalone with AK-Docs cloned alongside it
|
|
166
|
+
// at that same level), then its parent (the documented sibling-of-the-repo layout).
|
|
167
|
+
function resolveWorkspaceRoot(projectRoot) {
|
|
168
|
+
if (fs.existsSync(path.join(projectRoot, 'AK-Docs'))) return projectRoot;
|
|
169
|
+
const parent = path.resolve(projectRoot, '..');
|
|
170
|
+
if (fs.existsSync(path.join(parent, 'AK-Docs'))) return parent;
|
|
171
|
+
return projectRoot;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function pullAkDocsWithTimeout(akDocsPath, timeoutMs = 5000) {
|
|
175
|
+
try {
|
|
176
|
+
execSync('git pull', { cwd: akDocsPath, stdio: 'ignore', timeout: timeoutMs });
|
|
177
|
+
} catch (err) {
|
|
178
|
+
process.stderr.write(`[aiflow] ⚠ Không pull được AK-Docs (${String(err.message || err).split('\n')[0]}) — dùng bản memory hiện có trên máy.\n`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Map the active task's taskType to the workflow profile used by the memory scorer
|
|
183
|
+
// (doc §5.2 profile table). Unresolvable → null, which falls back to the doc's
|
|
184
|
+
// "gen-doc / không xác định" default profile inside memory-store's scoring.
|
|
185
|
+
function inferWorkflow(ctx) {
|
|
186
|
+
if (!ctx) return null;
|
|
187
|
+
const t = ctx.taskType;
|
|
188
|
+
if (t === 'gen-doc') return 'gen-doc';
|
|
189
|
+
if (t === 'testing') return 'create-testcase';
|
|
190
|
+
if (t === 'spec') return 'create-spec';
|
|
191
|
+
if (!t || ['feature', 'bug-fix', 'refactor', 'documentation', 'investigation'].includes(t)) return 'coding';
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Rough query-side tag extraction from the ticket title — the scorer only needs a
|
|
196
|
+
// handful of significant words to overlap against memory `tags:` (doc §5.2 formula).
|
|
197
|
+
function extractQueryTags(ctx) {
|
|
198
|
+
const text = `${ctx.title || ''} ${ctx.description || ''}`;
|
|
199
|
+
return [...new Set(
|
|
200
|
+
text.toLowerCase()
|
|
201
|
+
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
202
|
+
.split(/\s+/)
|
|
203
|
+
.filter(w => w.length > 3)
|
|
204
|
+
)].slice(0, 8);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function buildMemoryBlock(indexContent, relevant) {
|
|
208
|
+
if (!indexContent && (!relevant || relevant.length === 0)) return '';
|
|
209
|
+
const lines = ['<PROJECT_MEMORY>'];
|
|
210
|
+
lines.push('**99.Memory/ index (Lớp 1 — luôn có; xem MEMORY.md để biết toàn bộ danh mục):**');
|
|
211
|
+
lines.push('```markdown');
|
|
212
|
+
lines.push((indexContent || '(chưa có memory nào được approve)').trim());
|
|
213
|
+
lines.push('```');
|
|
214
|
+
if (relevant && relevant.length > 0) {
|
|
215
|
+
lines.push('');
|
|
216
|
+
lines.push(`**Memory liên quan nhất tới task này (Lớp 2, ${relevant.length} mục):**`);
|
|
217
|
+
for (const m of relevant) {
|
|
218
|
+
const pendingTag = m.status === 'pending'
|
|
219
|
+
? ' ⚠ CHƯA DUYỆT — chỉ máy này thấy, kiểm tra lại trước khi tin'
|
|
220
|
+
: '';
|
|
221
|
+
const firstLine = (m.content || '').trim().split('\n')[0];
|
|
222
|
+
lines.push(`- **${m.id}** (${m.type}, scope=${m.scope})${pendingTag}`);
|
|
223
|
+
lines.push(` ${firstLine}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
lines.push('');
|
|
227
|
+
lines.push('Nếu memory mâu thuẫn với `.rules/`, `.rules/` thắng — báo cho developer biết.');
|
|
228
|
+
lines.push('</PROJECT_MEMORY>');
|
|
229
|
+
return lines.join('\n');
|
|
230
|
+
}
|
|
231
|
+
|
|
129
232
|
function loadTaskState(taskId) {
|
|
130
233
|
try {
|
|
131
234
|
const statePath = path.join(tasksDir, taskId, 'task-state.json');
|
package/scripts/init.js
CHANGED
|
@@ -4,6 +4,7 @@ const os = require('os');
|
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const { input, checkbox, confirm } = require('@inquirer/prompts');
|
|
6
6
|
const { syncDocsRepos } = require('./docs-repo');
|
|
7
|
+
const memoryStore = require('./memory-store');
|
|
7
8
|
|
|
8
9
|
const PKG_DIR = path.join(__dirname, '..');
|
|
9
10
|
const GLOBAL_AIFLOW_DIR = path.join(os.homedir(), '.aiflow');
|
|
@@ -229,6 +230,16 @@ async function setupSuperpowersHook(_projectDir, claudeDir) {
|
|
|
229
230
|
await fs.copy(telemetrySrc, telemetryDest, { overwrite: true });
|
|
230
231
|
await fs.writeJson(path.join(telemetryDest, 'package.json'), { type: 'commonjs' }, { spaces: 2 });
|
|
231
232
|
|
|
233
|
+
// Copy memory-store.js so session-start.js can require('../lib/memory-store') for the
|
|
234
|
+
// 99.Memory/ Layer 1+2 load — same reason as telemetry above: only the hook file itself
|
|
235
|
+
// is deployed, not the rest of scripts/. memory-store.js is dependency-free by design
|
|
236
|
+
// (no fs-extra/chalk — see its own header comment) specifically so it can be copied alone.
|
|
237
|
+
// Own subdir + nested package.json for the same CJS-pinning reason as hooks/telemetry above.
|
|
238
|
+
const libDest = path.join(claudeDir, 'lib');
|
|
239
|
+
await fs.ensureDir(libDest);
|
|
240
|
+
await fs.copy(path.join(PKG_DIR, 'scripts', 'memory-store.js'), path.join(libDest, 'memory-store.js'), { overwrite: true });
|
|
241
|
+
await fs.writeJson(path.join(libDest, 'package.json'), { type: 'commonjs' }, { spaces: 2 });
|
|
242
|
+
|
|
232
243
|
const settingsFile = path.join(claudeDir, 'settings.json');
|
|
233
244
|
let settings = {};
|
|
234
245
|
if (await fs.pathExists(settingsFile)) {
|
|
@@ -1079,6 +1090,19 @@ async function init(options) {
|
|
|
1079
1090
|
// ── Sync AK-Docs / Shared-Docs sibling repos ──────────────────
|
|
1080
1091
|
await syncDocsRepos(projectDir);
|
|
1081
1092
|
|
|
1093
|
+
// ── Bootstrap 99.Memory/ skeleton (Luồng 1 — Khởi tạo) ────────
|
|
1094
|
+
// Free: no reads, no token cost — just an empty folder skeleton if AK-Docs
|
|
1095
|
+
// exists and doesn't have one yet (docs/internal/Memory-Architecture-v1.0.md §4).
|
|
1096
|
+
const memorySkeleton = await memoryStore.ensureSkeleton(projectDir);
|
|
1097
|
+
if (memorySkeleton.created) {
|
|
1098
|
+
console.log(chalk.green('✓ Đã tạo khung 99.Memory/ trong AK-Docs (chưa có ghi nhớ nào).'));
|
|
1099
|
+
const gitignoreResult = await memoryStore.ensureMemoryGitignored(projectDir);
|
|
1100
|
+
if (memorySkeleton.committed || gitignoreResult.committed) {
|
|
1101
|
+
console.log(chalk.yellow(' ⚠ Đã commit local trên nhánh hiện tại của AK-Docs — `main` là protected branch,'));
|
|
1102
|
+
console.log(chalk.yellow(' hãy tự `git push` khi sẵn sàng (không tự động push).'));
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1082
1106
|
// ── Auto-detect or prompt for framework if not supplied ──────
|
|
1083
1107
|
if (frameworks.length === 0) {
|
|
1084
1108
|
const stateFilePath = path.join(aiflowDir, 'state.json');
|