@relipa/ai-flow-kit 0.0.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.
- package/AIFLOW.md +432 -0
- package/CHANGELOG.md +78 -0
- package/CONTRIBUTING.md +351 -0
- package/IMPLEMENTATION_SUMMARY.md +348 -0
- package/QUICK_START.md +392 -0
- package/README.md +323 -0
- package/bin/aiflow.js +178 -0
- package/custom/mcp-presets/README.md +138 -0
- package/custom/mcp-presets/backlog.json +15 -0
- package/custom/mcp-presets/figma.json +15 -0
- package/custom/mcp-presets/google-sheets.json +14 -0
- package/custom/mcp-presets/jira.json +16 -0
- package/custom/prompts/bug-fix.md +149 -0
- package/custom/prompts/feature.md +190 -0
- package/custom/prompts/investigation.md +164 -0
- package/custom/rules/code-style.md +7 -0
- package/custom/rules/java/code-style.md +11 -0
- package/custom/rules/java/naming.md +17 -0
- package/custom/rules/java/review-checklist.md +36 -0
- package/custom/rules/javascript/code-style.md +12 -0
- package/custom/rules/javascript/naming.md +14 -0
- package/custom/rules/naming.md +9 -0
- package/custom/rules/php/code-style.md +10 -0
- package/custom/rules/php/naming.md +15 -0
- package/custom/rules/review-checklist.md +9 -0
- package/custom/skills/figma-to-component/SKILL.md +207 -0
- package/custom/skills/generate-spec/SKILL.md +97 -0
- package/custom/skills/impact-analysis/SKILL.md +94 -0
- package/custom/skills/investigate-bug/SKILL.md +93 -0
- package/custom/skills/report-customer/SKILL.md +95 -0
- package/custom/skills/review-plan/SKILL.md +158 -0
- package/custom/skills/validate-ticket/SKILL.md +240 -0
- package/custom/templates/laravel.md +90 -0
- package/custom/templates/nextjs.md +89 -0
- package/custom/templates/reactjs.md +567 -0
- package/custom/templates/spring-boot.md +598 -0
- package/custom/templates/vue-nuxt.md +89 -0
- package/docs/architecture.md +395 -0
- package/docs/cli-reference.md +438 -0
- package/docs/configuration.md +412 -0
- package/docs/getting-started.md +248 -0
- package/docs/troubleshooting.md +587 -0
- package/docs/workflows/bug-fix.md +126 -0
- package/docs/workflows/feature.md +123 -0
- package/docs/workflows/impact-analysis.md +13 -0
- package/docs/workflows/investigation.md +13 -0
- package/docs/workflows/refactor.md +13 -0
- package/index.js +27 -0
- package/package.json +70 -0
- package/scripts/config.js +317 -0
- package/scripts/context.js +117 -0
- package/scripts/detect.js +239 -0
- package/scripts/doctor.js +48 -0
- package/scripts/guide.js +282 -0
- package/scripts/hooks/session-start.js +140 -0
- package/scripts/init.js +453 -0
- package/scripts/memory.js +247 -0
- package/scripts/prompt.js +392 -0
- package/scripts/remove.js +170 -0
- package/scripts/update.js +111 -0
- package/scripts/use.js +570 -0
- package/scripts/validate.js +303 -0
- package/upstream/.claude-plugin/marketplace.json +20 -0
- package/upstream/.claude-plugin/plugin.json +20 -0
- package/upstream/.codex/INSTALL.md +67 -0
- package/upstream/.cursor-plugin/plugin.json +25 -0
- package/upstream/.gitattributes +18 -0
- package/upstream/.github/FUNDING.yml +3 -0
- package/upstream/.github/ISSUE_TEMPLATE/bug_report.md +52 -0
- package/upstream/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/upstream/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
- package/upstream/.github/ISSUE_TEMPLATE/platform_support.md +23 -0
- package/upstream/.github/PULL_REQUEST_TEMPLATE.md +87 -0
- package/upstream/.opencode/INSTALL.md +83 -0
- package/upstream/.opencode/plugins/superpowers.js +112 -0
- package/upstream/.version-bump.json +19 -0
- package/upstream/AGENTS.md +1 -0
- package/upstream/CHANGELOG.md +13 -0
- package/upstream/CLAUDE.md +85 -0
- package/upstream/CODE_OF_CONDUCT.md +128 -0
- package/upstream/GEMINI.md +2 -0
- package/upstream/LICENSE +21 -0
- package/upstream/README.md +190 -0
- package/upstream/RELEASE-NOTES.md +1096 -0
- package/upstream/agents/code-reviewer.md +48 -0
- package/upstream/commands/brainstorm.md +5 -0
- package/upstream/commands/execute-plan.md +5 -0
- package/upstream/commands/write-plan.md +5 -0
- package/upstream/docs/README.codex.md +126 -0
- package/upstream/docs/README.opencode.md +130 -0
- package/upstream/docs/plans/2025-11-22-opencode-support-design.md +294 -0
- package/upstream/docs/plans/2025-11-22-opencode-support-implementation.md +1095 -0
- package/upstream/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md +711 -0
- package/upstream/docs/plans/2026-01-17-visual-brainstorming.md +571 -0
- package/upstream/docs/superpowers/plans/2026-01-22-document-review-system.md +301 -0
- package/upstream/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md +523 -0
- package/upstream/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md +479 -0
- package/upstream/docs/superpowers/plans/2026-03-23-codex-app-compatibility.md +564 -0
- package/upstream/docs/superpowers/specs/2026-01-22-document-review-system-design.md +136 -0
- package/upstream/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md +162 -0
- package/upstream/docs/superpowers/specs/2026-03-11-zero-dep-brainstorm-server-design.md +118 -0
- package/upstream/docs/superpowers/specs/2026-03-23-codex-app-compatibility-design.md +244 -0
- package/upstream/docs/testing.md +303 -0
- package/upstream/docs/windows/polyglot-hooks.md +212 -0
- package/upstream/gemini-extension.json +6 -0
- package/upstream/hooks/hooks-cursor.json +10 -0
- package/upstream/hooks/hooks.json +16 -0
- package/upstream/hooks/run-hook.cmd +46 -0
- package/upstream/hooks/session-start +57 -0
- package/upstream/package.json +6 -0
- package/upstream/scripts/bump-version.sh +220 -0
- package/upstream/skills/brainstorming/SKILL.md +164 -0
- package/upstream/skills/brainstorming/scripts/frame-template.html +214 -0
- package/upstream/skills/brainstorming/scripts/helper.js +88 -0
- package/upstream/skills/brainstorming/scripts/server.cjs +354 -0
- package/upstream/skills/brainstorming/scripts/start-server.sh +148 -0
- package/upstream/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/upstream/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/upstream/skills/brainstorming/visual-companion.md +287 -0
- package/upstream/skills/dispatching-parallel-agents/SKILL.md +182 -0
- package/upstream/skills/executing-plans/SKILL.md +70 -0
- package/upstream/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/upstream/skills/receiving-code-review/SKILL.md +213 -0
- package/upstream/skills/requesting-code-review/SKILL.md +105 -0
- package/upstream/skills/requesting-code-review/code-reviewer.md +146 -0
- package/upstream/skills/subagent-driven-development/SKILL.md +277 -0
- package/upstream/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/upstream/skills/subagent-driven-development/implementer-prompt.md +113 -0
- package/upstream/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/upstream/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/upstream/skills/systematic-debugging/SKILL.md +296 -0
- package/upstream/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/upstream/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/upstream/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/upstream/skills/systematic-debugging/find-polluter.sh +63 -0
- package/upstream/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/upstream/skills/systematic-debugging/test-academic.md +14 -0
- package/upstream/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/upstream/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/upstream/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/upstream/skills/test-driven-development/SKILL.md +371 -0
- package/upstream/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/upstream/skills/using-git-worktrees/SKILL.md +218 -0
- package/upstream/skills/using-superpowers/SKILL.md +117 -0
- package/upstream/skills/using-superpowers/references/codex-tools.md +100 -0
- package/upstream/skills/using-superpowers/references/copilot-tools.md +52 -0
- package/upstream/skills/using-superpowers/references/gemini-tools.md +33 -0
- package/upstream/skills/verification-before-completion/SKILL.md +139 -0
- package/upstream/skills/writing-plans/SKILL.md +152 -0
- package/upstream/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/upstream/skills/writing-skills/SKILL.md +655 -0
- package/upstream/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/upstream/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/upstream/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/upstream/skills/writing-skills/persuasion-principles.md +187 -0
- package/upstream/skills/writing-skills/render-graphs.js +168 -0
- package/upstream/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/upstream/tests/brainstorm-server/package-lock.json +36 -0
- package/upstream/tests/brainstorm-server/package.json +10 -0
- package/upstream/tests/brainstorm-server/server.test.js +427 -0
- package/upstream/tests/brainstorm-server/windows-lifecycle.test.sh +351 -0
- package/upstream/tests/brainstorm-server/ws-protocol.test.js +392 -0
- package/upstream/tests/claude-code/README.md +158 -0
- package/upstream/tests/claude-code/analyze-token-usage.py +168 -0
- package/upstream/tests/claude-code/run-skill-tests.sh +187 -0
- package/upstream/tests/claude-code/test-document-review-system.sh +177 -0
- package/upstream/tests/claude-code/test-helpers.sh +202 -0
- package/upstream/tests/claude-code/test-subagent-driven-development-integration.sh +314 -0
- package/upstream/tests/claude-code/test-subagent-driven-development.sh +165 -0
- package/upstream/tests/explicit-skill-requests/prompts/action-oriented.txt +3 -0
- package/upstream/tests/explicit-skill-requests/prompts/after-planning-flow.txt +17 -0
- package/upstream/tests/explicit-skill-requests/prompts/claude-suggested-it.txt +11 -0
- package/upstream/tests/explicit-skill-requests/prompts/i-know-what-sdd-means.txt +8 -0
- package/upstream/tests/explicit-skill-requests/prompts/mid-conversation-execute-plan.txt +3 -0
- package/upstream/tests/explicit-skill-requests/prompts/please-use-brainstorming.txt +1 -0
- package/upstream/tests/explicit-skill-requests/prompts/skip-formalities.txt +3 -0
- package/upstream/tests/explicit-skill-requests/prompts/subagent-driven-development-please.txt +1 -0
- package/upstream/tests/explicit-skill-requests/prompts/use-systematic-debugging.txt +1 -0
- package/upstream/tests/explicit-skill-requests/run-all.sh +70 -0
- package/upstream/tests/explicit-skill-requests/run-claude-describes-sdd.sh +100 -0
- package/upstream/tests/explicit-skill-requests/run-extended-multiturn-test.sh +113 -0
- package/upstream/tests/explicit-skill-requests/run-haiku-test.sh +144 -0
- package/upstream/tests/explicit-skill-requests/run-multiturn-test.sh +143 -0
- package/upstream/tests/explicit-skill-requests/run-test.sh +136 -0
- package/upstream/tests/opencode/run-tests.sh +163 -0
- package/upstream/tests/opencode/setup.sh +88 -0
- package/upstream/tests/opencode/test-plugin-loading.sh +82 -0
- package/upstream/tests/opencode/test-priority.sh +198 -0
- package/upstream/tests/opencode/test-tools.sh +104 -0
- package/upstream/tests/skill-triggering/prompts/dispatching-parallel-agents.txt +8 -0
- package/upstream/tests/skill-triggering/prompts/executing-plans.txt +1 -0
- package/upstream/tests/skill-triggering/prompts/requesting-code-review.txt +3 -0
- package/upstream/tests/skill-triggering/prompts/systematic-debugging.txt +11 -0
- package/upstream/tests/skill-triggering/prompts/test-driven-development.txt +7 -0
- package/upstream/tests/skill-triggering/prompts/writing-plans.txt +10 -0
- package/upstream/tests/skill-triggering/run-all.sh +60 -0
- package/upstream/tests/skill-triggering/run-test.sh +88 -0
- package/upstream/tests/subagent-driven-dev/go-fractals/design.md +81 -0
- package/upstream/tests/subagent-driven-dev/go-fractals/plan.md +172 -0
- package/upstream/tests/subagent-driven-dev/go-fractals/scaffold.sh +45 -0
- package/upstream/tests/subagent-driven-dev/run-test.sh +106 -0
- package/upstream/tests/subagent-driven-dev/svelte-todo/design.md +70 -0
- package/upstream/tests/subagent-driven-dev/svelte-todo/plan.md +222 -0
- package/upstream/tests/subagent-driven-dev/svelte-todo/scaffold.sh +46 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
const MEMORY_DIR = path.join(process.cwd(), '.aiflow', 'memory');
|
|
6
|
+
|
|
7
|
+
async function ensureMemoryDir() {
|
|
8
|
+
await fs.ensureDir(MEMORY_DIR);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Save knowledge to memory
|
|
13
|
+
*/
|
|
14
|
+
async function saveMemory(key, value, metadata = {}) {
|
|
15
|
+
await ensureMemoryDir();
|
|
16
|
+
|
|
17
|
+
const fileName = `${sanitizeFileName(key)}.json`;
|
|
18
|
+
const filePath = path.join(MEMORY_DIR, fileName);
|
|
19
|
+
|
|
20
|
+
const memory = {
|
|
21
|
+
key,
|
|
22
|
+
value,
|
|
23
|
+
metadata: {
|
|
24
|
+
created: new Date().toISOString(),
|
|
25
|
+
updated: new Date().toISOString(),
|
|
26
|
+
...metadata
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
await fs.writeJson(filePath, memory, { spaces: 2 });
|
|
31
|
+
console.log(chalk.green(`✓ Saved: ${key}`));
|
|
32
|
+
|
|
33
|
+
return memory;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get memory by key
|
|
38
|
+
*/
|
|
39
|
+
async function getMemory(key) {
|
|
40
|
+
await ensureMemoryDir();
|
|
41
|
+
|
|
42
|
+
const fileName = `${sanitizeFileName(key)}.json`;
|
|
43
|
+
const filePath = path.join(MEMORY_DIR, fileName);
|
|
44
|
+
|
|
45
|
+
if (!(await fs.pathExists(filePath))) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return await fs.readJson(filePath);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* List all memories
|
|
54
|
+
*/
|
|
55
|
+
async function listMemories() {
|
|
56
|
+
await ensureMemoryDir();
|
|
57
|
+
|
|
58
|
+
const files = await fs.readdir(MEMORY_DIR);
|
|
59
|
+
const memories = [];
|
|
60
|
+
|
|
61
|
+
for (const file of files) {
|
|
62
|
+
if (file.endsWith('.json')) {
|
|
63
|
+
const memory = await fs.readJson(path.join(MEMORY_DIR, file));
|
|
64
|
+
memories.push({
|
|
65
|
+
key: memory.key,
|
|
66
|
+
value: memory.value.substring(0, 100) + (memory.value.length > 100 ? '...' : ''),
|
|
67
|
+
created: memory.metadata.created,
|
|
68
|
+
updated: memory.metadata.updated
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return memories.sort((a, b) => new Date(b.created) - new Date(a.created));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Search memories by keyword
|
|
78
|
+
*/
|
|
79
|
+
async function searchMemories(query) {
|
|
80
|
+
await ensureMemoryDir();
|
|
81
|
+
|
|
82
|
+
const files = await fs.readdir(MEMORY_DIR);
|
|
83
|
+
const results = [];
|
|
84
|
+
|
|
85
|
+
for (const file of files) {
|
|
86
|
+
if (file.endsWith('.json')) {
|
|
87
|
+
const memory = await fs.readJson(path.join(MEMORY_DIR, file));
|
|
88
|
+
const matchesKey = memory.key.toLowerCase().includes(query.toLowerCase());
|
|
89
|
+
const matchesValue = memory.value.toLowerCase().includes(query.toLowerCase());
|
|
90
|
+
|
|
91
|
+
if (matchesKey || matchesValue) {
|
|
92
|
+
results.push({
|
|
93
|
+
key: memory.key,
|
|
94
|
+
value: memory.value.substring(0, 150) + (memory.value.length > 150 ? '...' : ''),
|
|
95
|
+
matches: matchesKey ? ['key'] : [],
|
|
96
|
+
created: memory.metadata.created
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return results;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Delete memory
|
|
107
|
+
*/
|
|
108
|
+
async function deleteMemory(key) {
|
|
109
|
+
await ensureMemoryDir();
|
|
110
|
+
|
|
111
|
+
const fileName = `${sanitizeFileName(key)}.json`;
|
|
112
|
+
const filePath = path.join(MEMORY_DIR, fileName);
|
|
113
|
+
|
|
114
|
+
if (!(await fs.pathExists(filePath))) {
|
|
115
|
+
console.log(chalk.yellow(`! Memory not found: ${key}`));
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
await fs.remove(filePath);
|
|
120
|
+
console.log(chalk.green(`✓ Deleted: ${key}`));
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Clear all memories
|
|
126
|
+
*/
|
|
127
|
+
async function clearAllMemories() {
|
|
128
|
+
await fs.emptyDir(MEMORY_DIR);
|
|
129
|
+
console.log(chalk.green(`✓ Cleared all memories`));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Auto-load relevant memories for current context
|
|
134
|
+
*/
|
|
135
|
+
async function loadRelevantMemories(contextDescription) {
|
|
136
|
+
const keywords = contextDescription.split(/\s+/).filter(w => w.length > 3);
|
|
137
|
+
const allMemories = await listMemories();
|
|
138
|
+
const relevant = [];
|
|
139
|
+
|
|
140
|
+
for (const memory of allMemories) {
|
|
141
|
+
const score = keywords.filter(k =>
|
|
142
|
+
memory.key.toLowerCase().includes(k.toLowerCase()) ||
|
|
143
|
+
memory.value.toLowerCase().includes(k.toLowerCase())
|
|
144
|
+
).length;
|
|
145
|
+
|
|
146
|
+
if (score > 0) {
|
|
147
|
+
const fullMemory = await getMemory(memory.key);
|
|
148
|
+
relevant.push({
|
|
149
|
+
...memory,
|
|
150
|
+
score,
|
|
151
|
+
content: fullMemory.value
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return relevant.sort((a, b) => b.score - a.score);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Display memory in CLI
|
|
161
|
+
*/
|
|
162
|
+
async function displayMemory(memory) {
|
|
163
|
+
console.log(chalk.cyan(`\n📝 ${memory.key}`));
|
|
164
|
+
console.log(chalk.gray(`Created: ${new Date(memory.metadata.created).toLocaleDateString()}`));
|
|
165
|
+
console.log(chalk.gray(`Updated: ${new Date(memory.metadata.updated).toLocaleDateString()}`));
|
|
166
|
+
console.log(chalk.white(`\n${memory.value}\n`));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Sanitize file name from key
|
|
171
|
+
*/
|
|
172
|
+
function sanitizeFileName(key) {
|
|
173
|
+
return key
|
|
174
|
+
.toLowerCase()
|
|
175
|
+
.replace(/[^\w\s-]/g, '')
|
|
176
|
+
.replace(/\s+/g, '-')
|
|
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;
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
|
|
5
|
+
const PROJECT_DIR = process.cwd();
|
|
6
|
+
const CURRENT_FILE = path.join(PROJECT_DIR, '.claude', 'context', 'current.json');
|
|
7
|
+
const RULES_DIR = path.join(PROJECT_DIR, '.rules');
|
|
8
|
+
|
|
9
|
+
// Prompt templates per task type
|
|
10
|
+
// Each template includes mandatory superpowers skill invocation steps.
|
|
11
|
+
const PROMPT_TEMPLATES = {
|
|
12
|
+
'bug-fix': {
|
|
13
|
+
header: 'Fix Bug',
|
|
14
|
+
instruction: 'Investigate and fix the bug described below.',
|
|
15
|
+
skillWorkflow: `
|
|
16
|
+
## STRICT GATE WORKFLOW — Bug Fix
|
|
17
|
+
|
|
18
|
+
Follow gates IN ORDER. Do NOT skip or merge gates.
|
|
19
|
+
|
|
20
|
+
### GATE 1 — AI Analyze Requirement
|
|
21
|
+
**INVOKE:** \`validate-ticket\` skill
|
|
22
|
+
AI must:
|
|
23
|
+
1. Load ticket context + read source code related to the bug
|
|
24
|
+
2. Trace data flow to form root cause hypothesis (\`superpowers:systematic-debugging\`)
|
|
25
|
+
3. If unclear → ask ONE question at a time, wait for reply
|
|
26
|
+
4. Output \`plan/[ticket-id]/requirement.md\` with:
|
|
27
|
+
- Bug analysis (current vs expected behavior)
|
|
28
|
+
- Root cause hypothesis with evidence from source code
|
|
29
|
+
- Proposed fix approach (options if multiple)
|
|
30
|
+
- Impact analysis — will the fix break anything else?
|
|
31
|
+
- Effort estimate (S/M/L/XL)
|
|
32
|
+
- Testing plan (reproduce bug + verify fix)
|
|
33
|
+
5. Display "GATE 1: Requirement doc ready" → wait for **APPROVED**
|
|
34
|
+
|
|
35
|
+
### GATE 2 — Implementation Plan (wait for APPROVED)
|
|
36
|
+
**INVOKE:** \`generate-spec\` skill → \`superpowers:writing-plans\`
|
|
37
|
+
- Create TDD task breakdown: test to reproduce bug → fix → verify
|
|
38
|
+
- Display: "GATE 2: Plan ready, type APPROVED to start coding"
|
|
39
|
+
- **DO NOT WRITE CODE until APPROVED received**
|
|
40
|
+
|
|
41
|
+
### GATE 3 — Code (TDD)
|
|
42
|
+
Only runs after Gate 2 APPROVED.
|
|
43
|
+
1. **INVOKE:** \`superpowers:systematic-debugging\` — confirm root cause
|
|
44
|
+
2. **INVOKE:** \`investigate-bug\` skill — trace Controller→Service→Repository
|
|
45
|
+
3. **INVOKE:** \`superpowers:test-driven-development\` — write failing test to reproduce bug
|
|
46
|
+
4. Implement minimal fix to make test pass
|
|
47
|
+
|
|
48
|
+
### GATE 4 — AI Self-Review (wait for APPROVED)
|
|
49
|
+
**INVOKE:** \`review-plan\` skill
|
|
50
|
+
1. \`superpowers:verification-before-completion\` — all tests PASS (including old tests)
|
|
51
|
+
2. \`impact-analysis\` skill — fix doesn't cause new bugs elsewhere
|
|
52
|
+
3. Tick \`custom/rules/review-checklist.md\`
|
|
53
|
+
4. Create \`plan/[ticket-id]/summary.md\`
|
|
54
|
+
- Display: "GATE 4: type APPROVED or BUG: [description]"
|
|
55
|
+
- Coding bug → fix → repeat Gate 4
|
|
56
|
+
- Requirement bug → back to Gate 1
|
|
57
|
+
|
|
58
|
+
### GATE 5 — Peer Review & Done
|
|
59
|
+
Only runs after Gate 4 APPROVED.
|
|
60
|
+
**INVOKE:** \`superpowers:requesting-code-review\` → guide PR creation
|
|
61
|
+
`,
|
|
62
|
+
},
|
|
63
|
+
'feature': {
|
|
64
|
+
header: 'Implement Feature',
|
|
65
|
+
instruction: 'Implement the feature described below following team rules.',
|
|
66
|
+
skillWorkflow: `
|
|
67
|
+
## STRICT GATE WORKFLOW — Feature
|
|
68
|
+
|
|
69
|
+
Follow gates IN ORDER. Do NOT skip or merge gates.
|
|
70
|
+
|
|
71
|
+
### GATE 1 — AI Analyze Requirement
|
|
72
|
+
**INVOKE:** \`validate-ticket\` skill
|
|
73
|
+
AI must:
|
|
74
|
+
1. Load ticket context + read source code to understand architecture
|
|
75
|
+
2. Investigate related files, data flow, existing patterns
|
|
76
|
+
3. Use \`superpowers:brainstorming\` if solution approach is complex
|
|
77
|
+
4. If unclear → ask ONE question at a time, wait for reply
|
|
78
|
+
5. Output \`plan/[ticket-id]/requirement.md\` with:
|
|
79
|
+
- Requirements summary (AI's understanding in technical language)
|
|
80
|
+
- Source code analysis (related files, data flow, patterns)
|
|
81
|
+
- Proposed solution with options (recommended + alternatives)
|
|
82
|
+
- Impact analysis — what areas are affected?
|
|
83
|
+
- Effort estimate (S/M/L/XL) with task breakdown
|
|
84
|
+
- Testing plan (unit + integration + manual)
|
|
85
|
+
6. Display "GATE 1: Requirement doc ready" → wait for **APPROVED**
|
|
86
|
+
|
|
87
|
+
### GATE 2 — Implementation Plan (wait for APPROVED)
|
|
88
|
+
**INVOKE:** \`generate-spec\` skill → \`superpowers:writing-plans\`
|
|
89
|
+
- Create TDD task breakdown: test first → implement → verify
|
|
90
|
+
- Define commit strategy (small, focused)
|
|
91
|
+
- Display: "GATE 2: Plan ready, type APPROVED to start coding"
|
|
92
|
+
- **DO NOT WRITE CODE until APPROVED received**
|
|
93
|
+
|
|
94
|
+
### GATE 3 — Code (TDD)
|
|
95
|
+
Only runs after Gate 2 APPROVED.
|
|
96
|
+
1. Complex feature (3+ files): **INVOKE:** \`superpowers:subagent-driven-development\`
|
|
97
|
+
2. **INVOKE:** \`superpowers:test-driven-development\` — write failing test first
|
|
98
|
+
3. Implement to make tests pass — commit each small step
|
|
99
|
+
|
|
100
|
+
### GATE 4 — AI Self-Review (wait for APPROVED)
|
|
101
|
+
**INVOKE:** \`review-plan\` skill
|
|
102
|
+
1. \`superpowers:verification-before-completion\` — all tests PASS
|
|
103
|
+
2. \`impact-analysis\` skill — no regressions
|
|
104
|
+
3. Tick \`custom/rules/review-checklist.md\`
|
|
105
|
+
4. Create \`plan/[ticket-id]/summary.md\`
|
|
106
|
+
- Display: "GATE 4: type APPROVED or BUG: [description]"
|
|
107
|
+
- Coding bug → fix → repeat Gate 4
|
|
108
|
+
- Requirement bug → back to Gate 1
|
|
109
|
+
|
|
110
|
+
### GATE 5 — Peer Review & Done
|
|
111
|
+
Only runs after Gate 4 APPROVED.
|
|
112
|
+
**INVOKE:** \`superpowers:requesting-code-review\` → guide PR creation
|
|
113
|
+
`,
|
|
114
|
+
},
|
|
115
|
+
'investigation': {
|
|
116
|
+
header: 'Investigate',
|
|
117
|
+
instruction: 'Investigate the topic described below. Document findings before proposing solutions.',
|
|
118
|
+
skillWorkflow: `
|
|
119
|
+
## STRICT GATE WORKFLOW — Investigation
|
|
120
|
+
|
|
121
|
+
Investigation stops at Gate 1 — produce requirement doc with findings only, no coding.
|
|
122
|
+
|
|
123
|
+
### GATE 1 — AI Analyze & Investigate
|
|
124
|
+
**INVOKE:** \`validate-ticket\` skill
|
|
125
|
+
AI must:
|
|
126
|
+
1. Load ticket context + read source code thoroughly
|
|
127
|
+
2. **INVOKE:** \`superpowers:systematic-debugging\` — trace through all layers
|
|
128
|
+
3. **INVOKE:** \`investigate-bug\` skill — trace data flow through all layers
|
|
129
|
+
4. If unclear → ask ONE question at a time
|
|
130
|
+
5. Output \`plan/[ticket-id]/requirement.md\` with:
|
|
131
|
+
- Investigation scope and approach
|
|
132
|
+
- Source code analysis (all related files traced)
|
|
133
|
+
- Findings with evidence (log output, code references)
|
|
134
|
+
- Root cause (if applicable)
|
|
135
|
+
- Impact analysis — what areas are affected?
|
|
136
|
+
- Recommendations and next steps
|
|
137
|
+
- Effort estimate for proposed fix (if applicable)
|
|
138
|
+
6. Display "GATE 1: Investigation complete" → wait for **APPROVED**
|
|
139
|
+
|
|
140
|
+
**Do NOT implement any fix.** If fix needed → create new ticket → new workflow.
|
|
141
|
+
`,
|
|
142
|
+
},
|
|
143
|
+
'refactor': {
|
|
144
|
+
header: 'Refactor',
|
|
145
|
+
instruction: 'Refactor the code described below. Behaviour must be preserved.',
|
|
146
|
+
skillWorkflow: `
|
|
147
|
+
## STRICT GATE WORKFLOW — Refactor
|
|
148
|
+
|
|
149
|
+
Follow gates IN ORDER. Do NOT skip or merge gates.
|
|
150
|
+
|
|
151
|
+
### GATE 1 — AI Analyze Requirement
|
|
152
|
+
**INVOKE:** \`validate-ticket\` skill
|
|
153
|
+
AI must:
|
|
154
|
+
1. Load ticket context + read source code to understand current state
|
|
155
|
+
2. **INVOKE:** \`impact-analysis\` skill — map ALL callers and dependants
|
|
156
|
+
3. If unclear → ask ONE question at a time
|
|
157
|
+
4. Output \`plan/[ticket-id]/requirement.md\` with:
|
|
158
|
+
- Current state analysis (what exists, what's wrong)
|
|
159
|
+
- Target state (what it should look like after refactor)
|
|
160
|
+
- Proposed approach (step-by-step refactor strategy)
|
|
161
|
+
- Impact analysis — all callers, dependencies, test coverage
|
|
162
|
+
- Risk assessment — what could break?
|
|
163
|
+
- Effort estimate (S/M/L/XL)
|
|
164
|
+
5. Display "GATE 1: Requirement doc ready" → wait for **APPROVED**
|
|
165
|
+
|
|
166
|
+
### GATE 2 — Implementation Plan (wait for APPROVED)
|
|
167
|
+
**INVOKE:** \`generate-spec\` skill → \`superpowers:writing-plans\`
|
|
168
|
+
- Plan: ensure tests cover CURRENT behavior → refactor in steps → verify at each step
|
|
169
|
+
- Display: "GATE 2: Plan ready, type APPROVED to start refactoring"
|
|
170
|
+
- **DO NOT TOUCH CODE until APPROVED received**
|
|
171
|
+
|
|
172
|
+
### GATE 3 — Refactor (TDD)
|
|
173
|
+
Only runs after Gate 2 APPROVED.
|
|
174
|
+
1. **INVOKE:** \`superpowers:test-driven-development\` — ensure tests cover CURRENT behavior
|
|
175
|
+
2. Refactor incrementally — keep tests green at each step
|
|
176
|
+
3. Commit each step
|
|
177
|
+
|
|
178
|
+
### GATE 4 — AI Self-Review (wait for APPROVED)
|
|
179
|
+
**INVOKE:** \`review-plan\` skill
|
|
180
|
+
1. \`superpowers:verification-before-completion\` — all tests PASS
|
|
181
|
+
2. \`impact-analysis\` skill — verify no regressions
|
|
182
|
+
3. Tick \`custom/rules/review-checklist.md\`
|
|
183
|
+
4. Create \`plan/[ticket-id]/summary.md\`
|
|
184
|
+
- Display: "GATE 4: type APPROVED or BUG: [description]"
|
|
185
|
+
|
|
186
|
+
### GATE 5 — Peer Review & Done
|
|
187
|
+
**INVOKE:** \`superpowers:requesting-code-review\` → guide PR creation
|
|
188
|
+
`,
|
|
189
|
+
},
|
|
190
|
+
'impact-analysis': {
|
|
191
|
+
header: 'Impact Analysis',
|
|
192
|
+
instruction: 'Analyse the scope and impact of the change described below.',
|
|
193
|
+
skillWorkflow: `
|
|
194
|
+
## STRICT GATE WORKFLOW — Impact Analysis
|
|
195
|
+
|
|
196
|
+
Impact analysis stops at Gate 1 — produce report only, no coding.
|
|
197
|
+
|
|
198
|
+
### GATE 1 — AI Analyze & Report
|
|
199
|
+
**INVOKE:** \`validate-ticket\` skill
|
|
200
|
+
AI must:
|
|
201
|
+
1. Load ticket context + read source code thoroughly
|
|
202
|
+
2. Map all dependencies, callers, services, jobs, tests
|
|
203
|
+
3. If unclear → ask ONE question at a time
|
|
204
|
+
4. Output \`plan/[ticket-id]/requirement.md\` with:
|
|
205
|
+
- Change description and scope
|
|
206
|
+
- Dependency map (all callers, services, jobs, tests)
|
|
207
|
+
- Impact level: 🟢 Low / 🟡 Medium / 🔴 High / 🔥 Critical
|
|
208
|
+
- Breaking changes list
|
|
209
|
+
- Affected test coverage
|
|
210
|
+
- Risk assessment with mitigations
|
|
211
|
+
- Recommendations
|
|
212
|
+
- Effort estimate for implementation (if applicable)
|
|
213
|
+
5. Display "GATE 1: Impact report complete" → wait for **APPROVED**
|
|
214
|
+
|
|
215
|
+
**Do NOT make any code changes.** Implementation needs a separate ticket.
|
|
216
|
+
`,
|
|
217
|
+
},
|
|
218
|
+
'documentation': {
|
|
219
|
+
header: 'Write Documentation',
|
|
220
|
+
instruction: 'Write documentation for the topic described below.',
|
|
221
|
+
skillWorkflow: `
|
|
222
|
+
## STRICT GATE WORKFLOW — Documentation
|
|
223
|
+
|
|
224
|
+
### GATE 1 — AI Analyze Requirement
|
|
225
|
+
**INVOKE:** \`validate-ticket\` skill
|
|
226
|
+
AI must:
|
|
227
|
+
1. Load ticket context + read source code
|
|
228
|
+
2. Understand what needs to be documented and for whom
|
|
229
|
+
3. If unclear → ask ONE question at a time
|
|
230
|
+
4. Output \`plan/[ticket-id]/requirement.md\` with:
|
|
231
|
+
- Documentation scope and target audience
|
|
232
|
+
- Content outline (sections to cover)
|
|
233
|
+
- Source code references
|
|
234
|
+
- Effort estimate
|
|
235
|
+
5. Display "GATE 1: Documentation plan ready" → wait for **APPROVED**
|
|
236
|
+
|
|
237
|
+
### GATE 2 — Write Documentation
|
|
238
|
+
Only runs after Gate 1 APPROVED.
|
|
239
|
+
Read actual code/tests first — docs must reflect real implementation.
|
|
240
|
+
Write documentation based on approved outline.
|
|
241
|
+
|
|
242
|
+
### GATE 3 — Review (wait for APPROVED)
|
|
243
|
+
**INVOKE:** \`superpowers:verification-before-completion\`
|
|
244
|
+
Verify docs match code. No outdated examples.
|
|
245
|
+
Display: "GATE 3: Documentation complete. Type APPROVED."
|
|
246
|
+
`,
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// ──────────────────────────────────────────────────────────────
|
|
251
|
+
// Entry point
|
|
252
|
+
// ──────────────────────────────────────────────────────────────
|
|
253
|
+
|
|
254
|
+
module.exports = async function generatePrompt(type, options = {}) {
|
|
255
|
+
if (options.list) {
|
|
256
|
+
console.log(chalk.cyan('\nAvailable prompt types:\n'));
|
|
257
|
+
for (const [key, tpl] of Object.entries(PROMPT_TEMPLATES)) {
|
|
258
|
+
console.log(` ${chalk.white(key.padEnd(18))} ${chalk.gray(tpl.instruction.substring(0, 60))}...`);
|
|
259
|
+
}
|
|
260
|
+
console.log();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Load context
|
|
265
|
+
let ctx = null;
|
|
266
|
+
if (await fs.pathExists(CURRENT_FILE)) {
|
|
267
|
+
ctx = await fs.readJson(CURRENT_FILE).catch(() => null);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Resolve task type: CLI arg > context > ask user to specify
|
|
271
|
+
const resolvedType = type || ctx?.taskType;
|
|
272
|
+
if (!resolvedType || !PROMPT_TEMPLATES[resolvedType]) {
|
|
273
|
+
console.log(chalk.red(`Unknown or missing prompt type: ${resolvedType || '(none)'}`));
|
|
274
|
+
console.log(chalk.gray('Run: aiflow prompt --list'));
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const template = PROMPT_TEMPLATES[resolvedType];
|
|
279
|
+
const rules = await loadRules();
|
|
280
|
+
|
|
281
|
+
const prompt = buildPrompt(template, ctx, rules, options);
|
|
282
|
+
|
|
283
|
+
if (options.output) {
|
|
284
|
+
await fs.writeFile(options.output, prompt, 'utf-8');
|
|
285
|
+
console.log(chalk.green(`✓ Prompt saved to: ${options.output}`));
|
|
286
|
+
} else {
|
|
287
|
+
console.log(chalk.cyan('\n' + '─'.repeat(60)));
|
|
288
|
+
console.log(prompt);
|
|
289
|
+
console.log('─'.repeat(60) + '\n');
|
|
290
|
+
console.log(chalk.gray('Tip: paste this into your Claude session, or use --output <file>'));
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// ──────────────────────────────────────────────────────────────
|
|
295
|
+
// Helpers
|
|
296
|
+
// ──────────────────────────────────────────────────────────────
|
|
297
|
+
|
|
298
|
+
async function loadRules() {
|
|
299
|
+
if (!(await fs.pathExists(RULES_DIR))) return '';
|
|
300
|
+
|
|
301
|
+
const files = (await fs.readdir(RULES_DIR)).filter(f => f.endsWith('.md'));
|
|
302
|
+
if (!files.length) return '';
|
|
303
|
+
|
|
304
|
+
const parts = [];
|
|
305
|
+
for (const file of files) {
|
|
306
|
+
const content = await fs.readFile(path.join(RULES_DIR, file), 'utf-8');
|
|
307
|
+
parts.push(`### ${file}\n${content.trim()}`);
|
|
308
|
+
}
|
|
309
|
+
return parts.join('\n\n');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function buildPrompt(template, ctx, rules, options) {
|
|
313
|
+
const lang = options.lang || 'english';
|
|
314
|
+
const detail = options.detail || 'standard';
|
|
315
|
+
|
|
316
|
+
const lines = [];
|
|
317
|
+
|
|
318
|
+
lines.push(`# ${template.header}`);
|
|
319
|
+
lines.push('');
|
|
320
|
+
lines.push(`**Task:** ${template.instruction}`);
|
|
321
|
+
lines.push('');
|
|
322
|
+
|
|
323
|
+
// ── Mandatory skill workflow ───────────────────────────────
|
|
324
|
+
if (template.skillWorkflow) {
|
|
325
|
+
lines.push(template.skillWorkflow.trim());
|
|
326
|
+
lines.push('');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ── Context section ────────────────────────────────────────
|
|
330
|
+
if (ctx) {
|
|
331
|
+
lines.push('## Context');
|
|
332
|
+
lines.push('');
|
|
333
|
+
lines.push(`- **Ticket:** ${ctx.taskId || 'N/A'}`);
|
|
334
|
+
lines.push(`- **Title:** ${ctx.title || 'N/A'}`);
|
|
335
|
+
lines.push(`- **Status:** ${ctx.status || 'N/A'}`);
|
|
336
|
+
lines.push(`- **Assignee:** ${ctx.assignee || 'N/A'}`);
|
|
337
|
+
lines.push('');
|
|
338
|
+
|
|
339
|
+
if (ctx.description) {
|
|
340
|
+
lines.push('### Description');
|
|
341
|
+
lines.push('');
|
|
342
|
+
lines.push(ctx.description.trim());
|
|
343
|
+
lines.push('');
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (ctx.acceptanceCriteria?.length) {
|
|
347
|
+
lines.push('### Acceptance Criteria');
|
|
348
|
+
lines.push('');
|
|
349
|
+
for (const c of ctx.acceptanceCriteria) {
|
|
350
|
+
lines.push(`- ${c}`);
|
|
351
|
+
}
|
|
352
|
+
lines.push('');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (detail === 'comprehensive' && ctx.comments?.length) {
|
|
356
|
+
lines.push('### Comments');
|
|
357
|
+
lines.push('');
|
|
358
|
+
for (const c of ctx.comments) {
|
|
359
|
+
lines.push(c);
|
|
360
|
+
lines.push('');
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (ctx.context?.files?.length) {
|
|
365
|
+
lines.push('### Related Files Mentioned');
|
|
366
|
+
lines.push('');
|
|
367
|
+
for (const f of ctx.context.files) {
|
|
368
|
+
lines.push(`- \`${f}\``);
|
|
369
|
+
}
|
|
370
|
+
lines.push('');
|
|
371
|
+
}
|
|
372
|
+
} else {
|
|
373
|
+
lines.push('> No context loaded. Run `aiflow use <ticket>` to load ticket context.');
|
|
374
|
+
lines.push('');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// ── Rules section ──────────────────────────────────────────
|
|
378
|
+
if (rules) {
|
|
379
|
+
lines.push('## Team Rules');
|
|
380
|
+
lines.push('');
|
|
381
|
+
lines.push(rules);
|
|
382
|
+
lines.push('');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// ── Language instruction ───────────────────────────────────
|
|
386
|
+
if (lang === 'vietnamese') {
|
|
387
|
+
lines.push('> **Reply in English.**');
|
|
388
|
+
lines.push('');
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return lines.join('\n');
|
|
392
|
+
}
|