@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/scripts/memory.js
CHANGED
|
@@ -1,247 +1,176 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
.replace(/-+/g, '-')
|
|
178
|
-
.substring(0, 50);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
module.exports = async function memory(command, args = {}) {
|
|
182
|
-
try {
|
|
183
|
-
if (command === 'save' && args.key && args.value) {
|
|
184
|
-
return await saveMemory(args.key, args.value, args.metadata);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (command === 'get' && args.key) {
|
|
188
|
-
const m = await getMemory(args.key);
|
|
189
|
-
if (m) {
|
|
190
|
-
await displayMemory(m);
|
|
191
|
-
return m;
|
|
192
|
-
} else {
|
|
193
|
-
console.log(chalk.yellow(`! Memory not found: ${args.key}`));
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (command === 'list') {
|
|
198
|
-
const memories = await listMemories();
|
|
199
|
-
if (memories.length === 0) {
|
|
200
|
-
console.log(chalk.gray('No memories saved yet'));
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
console.log(chalk.cyan('\n📚 Saved Memories:\n'));
|
|
204
|
-
memories.forEach((m, i) => {
|
|
205
|
-
console.log(`${i + 1}. ${chalk.white(m.key)}`);
|
|
206
|
-
console.log(` ${chalk.gray(m.value)}`);
|
|
207
|
-
console.log(` ${chalk.gray('Created: ' + new Date(m.created).toLocaleDateString())}\n`);
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (command === 'search' && args.query) {
|
|
212
|
-
const results = await searchMemories(args.query);
|
|
213
|
-
if (results.length === 0) {
|
|
214
|
-
console.log(chalk.gray(`No memories matching "${args.query}"`));
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
console.log(chalk.cyan(`\n🔍 Found ${results.length} memories matching "${args.query}":\n`));
|
|
218
|
-
results.forEach((m, i) => {
|
|
219
|
-
console.log(`${i + 1}. ${chalk.white(m.key)}`);
|
|
220
|
-
console.log(` ${chalk.gray(m.value)}\n`);
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (command === 'delete' && args.key) {
|
|
225
|
-
return await deleteMemory(args.key);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (command === 'clear') {
|
|
229
|
-
return await clearAllMemories();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (command === 'auto-load' && args.context) {
|
|
233
|
-
return await loadRelevantMemories(args.context);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
} catch (err) {
|
|
237
|
-
console.error(chalk.red(`Error: ${err.message}`));
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
module.exports.saveMemory = saveMemory;
|
|
242
|
-
module.exports.getMemory = getMemory;
|
|
243
|
-
module.exports.listMemories = listMemories;
|
|
244
|
-
module.exports.searchMemories = searchMemories;
|
|
245
|
-
module.exports.deleteMemory = deleteMemory;
|
|
246
|
-
module.exports.clearAllMemories = clearAllMemories;
|
|
247
|
-
module.exports.loadRelevantMemories = loadRelevantMemories;
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const store = require('./memory-store');
|
|
5
|
+
const docsBranchCommand = require('./docs-branch');
|
|
6
|
+
|
|
7
|
+
// CLI for the "99.Memory/" Project Brain (docs/internal/Memory-Architecture-v1.0.md).
|
|
8
|
+
// Thin dispatch layer: business logic lives in memory-store.js, git/MR logic is reused
|
|
9
|
+
// from docs-branch.js (same "AI drafts — human approves via MR" pattern as `ak docs`).
|
|
10
|
+
//
|
|
11
|
+
// Replaces the legacy JSON key/value store this file used to implement
|
|
12
|
+
// (`.aiflow/memory/*.json`, save/get/search/delete/clear) — unrelated to 99.Memory/,
|
|
13
|
+
// retired outright (no backward-compat shim; nothing in the kit still reads that store).
|
|
14
|
+
|
|
15
|
+
const PROJECT_DIR = process.cwd();
|
|
16
|
+
|
|
17
|
+
module.exports = async function memory(action, options = {}) {
|
|
18
|
+
try {
|
|
19
|
+
if (action === 'draft') return await draftCmd(options);
|
|
20
|
+
if (action === 'list') return await listCmd(options);
|
|
21
|
+
if (action === 'submit') return await submitCmd(options);
|
|
22
|
+
if (action === 'remove') return await removeCmd(options);
|
|
23
|
+
|
|
24
|
+
console.log(chalk.yellow('Usage:'));
|
|
25
|
+
console.log(chalk.gray(' ak memory draft --category <cat> --slug <slug> --content <text> [options]'));
|
|
26
|
+
console.log(chalk.gray(' ak memory list [--approved]'));
|
|
27
|
+
console.log(chalk.gray(' ak memory submit <pendingPath> --title "..." [--yes]'));
|
|
28
|
+
console.log(chalk.gray(' ak memory remove <path> [--hard] [--reason "..."] --title "..." [--yes]'));
|
|
29
|
+
console.log(chalk.gray(`\n Categories: ${Object.keys(store.CATEGORIES).join(', ')}`));
|
|
30
|
+
} catch (err) {
|
|
31
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
async function draftCmd(options) {
|
|
37
|
+
if (!options.category || !options.slug || !options.content) {
|
|
38
|
+
console.log(chalk.red('✗ Cần --category, --slug, và --content.'));
|
|
39
|
+
process.exitCode = 1;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const tags = splitList(options.tags);
|
|
43
|
+
const workflows = splitList(options.workflows, ['all']);
|
|
44
|
+
|
|
45
|
+
const result = await store.createDraft(PROJECT_DIR, {
|
|
46
|
+
category: options.category,
|
|
47
|
+
functionId: options.functionId,
|
|
48
|
+
scope: options.scope,
|
|
49
|
+
slug: options.slug,
|
|
50
|
+
content: options.content,
|
|
51
|
+
source: options.source || '',
|
|
52
|
+
tags, workflows,
|
|
53
|
+
confidence: options.confidence !== undefined ? Number(options.confidence) : 0.5,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (result.conflict) {
|
|
57
|
+
console.log(chalk.yellow(`⚠ Memory tương tự đã có tại: ${result.existingPath}`));
|
|
58
|
+
console.log(chalk.gray(' Sửa file đó trực tiếp nếu muốn cập nhật, thay vì tạo bản mới.'));
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log(chalk.green(`✓ Draft đã tạo: ${result.path}`));
|
|
63
|
+
console.log(chalk.gray(` id: ${result.id} (local — chỉ máy này recall được cho tới khi submit)`));
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function listCmd(options) {
|
|
68
|
+
const memories = options.approved
|
|
69
|
+
? await store.listApproved(PROJECT_DIR)
|
|
70
|
+
: await store.listDrafts(PROJECT_DIR);
|
|
71
|
+
|
|
72
|
+
if (memories.length === 0) {
|
|
73
|
+
console.log(chalk.gray(options.approved ? 'Chưa có memory nào được approve.' : 'Chưa có draft nào trong _pending/.'));
|
|
74
|
+
return memories;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(chalk.cyan(`\n${options.approved ? 'Approved memories' : 'Pending drafts (local)'}:\n`));
|
|
78
|
+
for (const m of memories) {
|
|
79
|
+
console.log(` ${chalk.white(m.id || '(no id)')} ${chalk.gray(m.relPath)}`);
|
|
80
|
+
console.log(` ${chalk.gray(`type=${m.type} scope=${m.scope} workflows=${m.workflows}`)}`);
|
|
81
|
+
}
|
|
82
|
+
console.log();
|
|
83
|
+
return memories;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Submit a pending draft: create a branch in AK-Docs, move the file from _pending/
|
|
88
|
+
* to its destination path, commit, push, open an MR — same two-step CLI already
|
|
89
|
+
* used by `ak docs branch` + `ak docs submit --yes` (custom/templates/shared/*.md).
|
|
90
|
+
*/
|
|
91
|
+
async function submitCmd(options) {
|
|
92
|
+
const pendingRelPath = options._positional && options._positional[0];
|
|
93
|
+
if (!pendingRelPath || !options.title) {
|
|
94
|
+
console.log(chalk.red('✗ Cần <pendingPath> (từ `ak memory list`) và --title.'));
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const base = store.memoryDir(PROJECT_DIR);
|
|
100
|
+
const pendingAbs = path.join(base, pendingRelPath);
|
|
101
|
+
if (!(await fs.pathExists(pendingAbs))) {
|
|
102
|
+
console.log(chalk.red(`✗ Không tìm thấy draft: ${pendingRelPath}`));
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const { data } = store.parseFrontmatter(await fs.readFile(pendingAbs, 'utf-8'));
|
|
108
|
+
const destRelPath = pendingRelPath.replace(/^_pending[\\/]/, '');
|
|
109
|
+
const destAbs = path.join(base, destRelPath);
|
|
110
|
+
|
|
111
|
+
const slug = path.basename(destRelPath, '.md');
|
|
112
|
+
const branchResult = await docsBranchCommand.createBranch({
|
|
113
|
+
functionId: 'memory', taskId: slug, repo: 'AK-Docs', yes: options.yes,
|
|
114
|
+
});
|
|
115
|
+
if (!branchResult) return; // createBranch already printed the reason / plan
|
|
116
|
+
|
|
117
|
+
await fs.ensureDir(path.dirname(destAbs));
|
|
118
|
+
await fs.move(pendingAbs, destAbs, { overwrite: false });
|
|
119
|
+
|
|
120
|
+
return docsBranchCommand.submitDocs({
|
|
121
|
+
title: options.title,
|
|
122
|
+
description: options.description || `Memory: ${data.id || slug}`,
|
|
123
|
+
repo: 'AK-Docs', yes: options.yes,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Propose removal (Luồng 4): same branch+MR mechanism as submit, but moves the
|
|
129
|
+
* target file into _deprecated/ (soft, default) or deletes it outright (--hard).
|
|
130
|
+
*/
|
|
131
|
+
async function removeCmd(options) {
|
|
132
|
+
const targetRelPath = options._positional && options._positional[0];
|
|
133
|
+
if (!targetRelPath || !options.title) {
|
|
134
|
+
console.log(chalk.red('✗ Cần <path đã approve> (từ `ak memory list --approved`) và --title.'));
|
|
135
|
+
process.exitCode = 1;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const base = store.memoryDir(PROJECT_DIR);
|
|
140
|
+
const targetAbs = path.join(base, targetRelPath);
|
|
141
|
+
if (!(await fs.pathExists(targetAbs))) {
|
|
142
|
+
console.log(chalk.red(`✗ Không tìm thấy memory: ${targetRelPath}`));
|
|
143
|
+
process.exitCode = 1;
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const slug = path.basename(targetRelPath, '.md');
|
|
148
|
+
const branchResult = await docsBranchCommand.createBranch({
|
|
149
|
+
functionId: 'memory', taskId: `remove-${slug}`, repo: 'AK-Docs', yes: options.yes,
|
|
150
|
+
});
|
|
151
|
+
if (!branchResult) return;
|
|
152
|
+
|
|
153
|
+
if (options.hard) {
|
|
154
|
+
await fs.remove(targetAbs);
|
|
155
|
+
console.log(chalk.yellow(`⚠ Hard-remove: đã xóa file khỏi working tree. Lý do: ${options.reason || '(không ghi lý do)'}`));
|
|
156
|
+
} else {
|
|
157
|
+
const deprecatedAbs = path.join(base, '_deprecated', path.basename(targetRelPath));
|
|
158
|
+
await fs.ensureDir(path.dirname(deprecatedAbs));
|
|
159
|
+
await fs.move(targetAbs, deprecatedAbs, { overwrite: false });
|
|
160
|
+
console.log(chalk.gray(` Soft-remove: chuyển vào _deprecated/${path.basename(targetRelPath)}`));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return docsBranchCommand.submitDocs({
|
|
164
|
+
title: options.title,
|
|
165
|
+
description: options.description || `Remove memory: ${slug}. Lý do: ${options.reason || '(không ghi lý do)'}`,
|
|
166
|
+
repo: 'AK-Docs', yes: options.yes,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function splitList(value, fallback = []) {
|
|
171
|
+
if (!value) return fallback;
|
|
172
|
+
if (Array.isArray(value)) return value;
|
|
173
|
+
return String(value).split(',').map(s => s.trim()).filter(Boolean);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
module.exports.store = store;
|
package/scripts/update.js
CHANGED
|
@@ -3,6 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const { confirm, select } = require('@inquirer/prompts');
|
|
5
5
|
const { syncDocsRepos } = require('./docs-repo');
|
|
6
|
+
const memoryStore = require('./memory-store');
|
|
6
7
|
|
|
7
8
|
const PKG_DIR = path.join(__dirname, '..');
|
|
8
9
|
const PKG_VERSION = require('../package.json').version;
|
|
@@ -29,6 +30,17 @@ module.exports = async function update(options = {}) {
|
|
|
29
30
|
// ── Sync AK-Docs / Shared-Docs sibling repos ──────────────────
|
|
30
31
|
await syncDocsRepos(projectDir);
|
|
31
32
|
|
|
33
|
+
// ── Bootstrap 99.Memory/ skeleton if AK-Docs was cloned after init ────
|
|
34
|
+
const memorySkeleton = await memoryStore.ensureSkeleton(projectDir);
|
|
35
|
+
if (memorySkeleton.created) {
|
|
36
|
+
console.log(chalk.green('✓ Đã tạo khung 99.Memory/ trong AK-Docs (chưa có ghi nhớ nào).'));
|
|
37
|
+
const gitignoreResult = await memoryStore.ensureMemoryGitignored(projectDir);
|
|
38
|
+
if (memorySkeleton.committed || gitignoreResult.committed) {
|
|
39
|
+
console.log(chalk.yellow(' ⚠ Đã commit local trên nhánh hiện tại của AK-Docs — `main` là protected branch,'));
|
|
40
|
+
console.log(chalk.yellow(' hãy tự `git push` khi sẵn sàng (không tự động push).'));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
32
44
|
const state = await fs.readJson(stateFile);
|
|
33
45
|
const currentVersion = state.current_version;
|
|
34
46
|
|
package/scripts/use.js
CHANGED
|
@@ -636,6 +636,7 @@ async function promptForTaskType(detectedDefault) {
|
|
|
636
636
|
{ name: td("🔍 Investigation", "Analysis", "Investigate, analyze root cause"), value: "investigation" },
|
|
637
637
|
{ name: td("📊 Impact Analysis", "Analysis", "Assess scope and risk of changes"), value: "impact-analysis" },
|
|
638
638
|
{ name: td("📖 Documentation", "Document", "Write docs, README, API reference"), value: "documentation" },
|
|
639
|
+
{ name: td("📝 Generate Doc/Spec", "Document", "Generate new documentation/Spec (2-gate)"), value: "gen-doc" },
|
|
639
640
|
],
|
|
640
641
|
default: detectedDefault || "feature",
|
|
641
642
|
});
|
|
@@ -709,7 +710,7 @@ async function manualContext(prefillId = "") {
|
|
|
709
710
|
{ name: td("🔍 Investigation", "Analysis", "Investigate, analyze root cause"), value: "investigation" },
|
|
710
711
|
{ name: td("📊 Impact Analysis", "Analysis", "Assess scope and risk of changes"), value: "impact-analysis" },
|
|
711
712
|
{ name: td("📖 Documentation", "Document", "Write docs, README, API reference"), value: "documentation" },
|
|
712
|
-
{ name: td("📝 Generate Doc
|
|
713
|
+
{ name: td("📝 Generate Doc/Spec", "Document", "Generate new documentation/Spec (2-gate)"), value: "gen-doc" },
|
|
713
714
|
],
|
|
714
715
|
default: existing.taskType || undefined,
|
|
715
716
|
});
|