@su-record/vibe 0.1.2 → 0.1.4
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 +13 -6
- package/bin/vibe +20 -2
- package/package.json +5 -6
- package/scripts/install-mcp.js +31 -5
- package/mcp/dist/__tests__/complexity.test.js +0 -126
- package/mcp/dist/__tests__/memory.test.js +0 -120
- package/mcp/dist/__tests__/python-dart-complexity.test.js +0 -146
- package/mcp/dist/index.js +0 -230
- package/mcp/dist/lib/ContextCompressor.js +0 -305
- package/mcp/dist/lib/MemoryManager.js +0 -334
- package/mcp/dist/lib/ProjectCache.js +0 -126
- package/mcp/dist/lib/PythonParser.js +0 -241
- package/mcp/dist/tools/browser/browserPool.js +0 -76
- package/mcp/dist/tools/browser/browserUtils.js +0 -135
- package/mcp/dist/tools/browser/inspectNetworkRequests.js +0 -140
- package/mcp/dist/tools/browser/monitorConsoleLogs.js +0 -97
- package/mcp/dist/tools/convention/analyzeComplexity.js +0 -248
- package/mcp/dist/tools/convention/applyQualityRules.js +0 -102
- package/mcp/dist/tools/convention/checkCouplingCohesion.js +0 -233
- package/mcp/dist/tools/convention/complexityMetrics.js +0 -133
- package/mcp/dist/tools/convention/dartComplexity.js +0 -117
- package/mcp/dist/tools/convention/getCodingGuide.js +0 -64
- package/mcp/dist/tools/convention/languageDetector.js +0 -50
- package/mcp/dist/tools/convention/pythonComplexity.js +0 -109
- package/mcp/dist/tools/convention/suggestImprovements.js +0 -257
- package/mcp/dist/tools/convention/validateCodeQuality.js +0 -177
- package/mcp/dist/tools/memory/autoSaveContext.js +0 -79
- package/mcp/dist/tools/memory/database.js +0 -123
- package/mcp/dist/tools/memory/deleteMemory.js +0 -39
- package/mcp/dist/tools/memory/listMemories.js +0 -38
- package/mcp/dist/tools/memory/memoryConfig.js +0 -27
- package/mcp/dist/tools/memory/memorySQLite.js +0 -138
- package/mcp/dist/tools/memory/memoryUtils.js +0 -34
- package/mcp/dist/tools/memory/migrate.js +0 -113
- package/mcp/dist/tools/memory/prioritizeMemory.js +0 -109
- package/mcp/dist/tools/memory/recallMemory.js +0 -40
- package/mcp/dist/tools/memory/restoreSessionContext.js +0 -69
- package/mcp/dist/tools/memory/saveMemory.js +0 -34
- package/mcp/dist/tools/memory/searchMemories.js +0 -37
- package/mcp/dist/tools/memory/startSession.js +0 -100
- package/mcp/dist/tools/memory/updateMemory.js +0 -46
- package/mcp/dist/tools/planning/analyzeRequirements.js +0 -166
- package/mcp/dist/tools/planning/createUserStories.js +0 -119
- package/mcp/dist/tools/planning/featureRoadmap.js +0 -202
- package/mcp/dist/tools/planning/generatePrd.js +0 -156
- package/mcp/dist/tools/prompt/analyzePrompt.js +0 -145
- package/mcp/dist/tools/prompt/enhancePrompt.js +0 -105
- package/mcp/dist/tools/semantic/findReferences.js +0 -195
- package/mcp/dist/tools/semantic/findSymbol.js +0 -200
- package/mcp/dist/tools/thinking/analyzeProblem.js +0 -50
- package/mcp/dist/tools/thinking/breakDownProblem.js +0 -140
- package/mcp/dist/tools/thinking/createThinkingChain.js +0 -39
- package/mcp/dist/tools/thinking/formatAsPlan.js +0 -73
- package/mcp/dist/tools/thinking/stepByStepAnalysis.js +0 -58
- package/mcp/dist/tools/thinking/thinkAloudProcess.js +0 -75
- package/mcp/dist/tools/time/getCurrentTime.js +0 -61
- package/mcp/dist/tools/ui/previewUiAscii.js +0 -232
- package/mcp/dist/types/tool.js +0 -2
- package/mcp/package.json +0 -53
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
// Memory management tool - SQLite based (v1.3)
|
|
2
|
-
import { MemoryManager } from '../../lib/MemoryManager.js';
|
|
3
|
-
import { promises as fs } from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
const GUIDES_DIR = path.join(process.cwd(), 'guides');
|
|
6
|
-
const GUIDES_FILE = path.join(GUIDES_DIR, 'coding_guides.json');
|
|
7
|
-
async function ensureGuidesDir() {
|
|
8
|
-
try {
|
|
9
|
-
await fs.access(GUIDES_DIR);
|
|
10
|
-
}
|
|
11
|
-
catch {
|
|
12
|
-
await fs.mkdir(GUIDES_DIR, { recursive: true });
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
async function loadGuides() {
|
|
16
|
-
try {
|
|
17
|
-
await ensureGuidesDir();
|
|
18
|
-
const data = await fs.readFile(GUIDES_FILE, 'utf-8');
|
|
19
|
-
return JSON.parse(data);
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
export const startSessionDefinition = {
|
|
26
|
-
name: 'start_session',
|
|
27
|
-
description: 'hi-ai|hello|안녕|하이아이 - Start session with context',
|
|
28
|
-
inputSchema: {
|
|
29
|
-
type: 'object',
|
|
30
|
-
properties: {
|
|
31
|
-
greeting: { type: 'string', description: 'Greeting message that triggered this action (e.g., "하이아이", "hi-ai")' },
|
|
32
|
-
loadMemory: { type: 'boolean', description: 'Load relevant project memories (default: true)' },
|
|
33
|
-
loadGuides: { type: 'boolean', description: 'Load applicable coding guides (default: true)' },
|
|
34
|
-
restoreContext: { type: 'boolean', description: 'Restore previous session context (default: true)' }
|
|
35
|
-
},
|
|
36
|
-
required: []
|
|
37
|
-
},
|
|
38
|
-
annotations: {
|
|
39
|
-
title: 'Start Session',
|
|
40
|
-
audience: ['user', 'assistant']
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
export async function startSession(args) {
|
|
44
|
-
const { greeting = '', loadMemory = true, loadGuides: shouldLoadGuides = true, restoreContext = true } = args;
|
|
45
|
-
try {
|
|
46
|
-
const memoryManager = MemoryManager.getInstance();
|
|
47
|
-
let summary = `${greeting ? greeting + '! ' : ''}Session started.\n`;
|
|
48
|
-
// Load relevant project memories
|
|
49
|
-
if (loadMemory) {
|
|
50
|
-
const projectMemories = memoryManager.list('project');
|
|
51
|
-
const codeMemories = memoryManager.list('code');
|
|
52
|
-
const memories = [...projectMemories, ...codeMemories].slice(0, 5);
|
|
53
|
-
if (memories.length > 0) {
|
|
54
|
-
summary += `\nRecent Project Info:\n`;
|
|
55
|
-
memories.forEach(mem => {
|
|
56
|
-
const preview = mem.value.substring(0, 80);
|
|
57
|
-
summary += ` • ${mem.key}: ${preview}${mem.value.length > 80 ? '...' : ''}\n`;
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// Load coding guides
|
|
62
|
-
if (shouldLoadGuides) {
|
|
63
|
-
const allGuides = await loadGuides();
|
|
64
|
-
const guides = allGuides
|
|
65
|
-
.sort((a, b) => new Date(b.lastUpdated).getTime() - new Date(a.lastUpdated).getTime())
|
|
66
|
-
.slice(0, 3);
|
|
67
|
-
if (guides.length > 0) {
|
|
68
|
-
summary += `\nActive Coding Guides:\n`;
|
|
69
|
-
guides.forEach(guide => {
|
|
70
|
-
summary += ` • ${guide.name} (${guide.category}): ${guide.description}\n`;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// Restore context
|
|
75
|
-
if (restoreContext) {
|
|
76
|
-
const contextMemories = memoryManager.list('context').slice(0, 3);
|
|
77
|
-
if (contextMemories.length > 0) {
|
|
78
|
-
summary += `\nPrevious Context:\n`;
|
|
79
|
-
contextMemories.forEach(ctx => {
|
|
80
|
-
try {
|
|
81
|
-
const data = JSON.parse(ctx.value);
|
|
82
|
-
summary += ` • ${data.urgency?.toUpperCase() || 'MEDIUM'} priority from ${new Date(ctx.timestamp).toLocaleString()}\n`;
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
summary += ` • Context from ${new Date(ctx.timestamp).toLocaleString()}\n`;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
summary += '\nReady to continue development! What would you like to work on?';
|
|
91
|
-
return {
|
|
92
|
-
content: [{ type: 'text', text: summary }]
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
return {
|
|
97
|
-
content: [{ type: 'text', text: `${greeting ? greeting + '! ' : ''}Session started.\n\nReady to begin! What can I help you with?` }]
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// Memory management tool - completely independent
|
|
2
|
-
import { MemoryManager } from '../../lib/MemoryManager.js';
|
|
3
|
-
export const updateMemoryDefinition = {
|
|
4
|
-
name: 'update_memory',
|
|
5
|
-
description: '수정해|업데이트|바꿔|update|change|modify|edit - Update existing memory',
|
|
6
|
-
inputSchema: {
|
|
7
|
-
type: 'object',
|
|
8
|
-
properties: {
|
|
9
|
-
key: { type: 'string', description: 'Memory key to update' },
|
|
10
|
-
value: { type: 'string', description: 'New value' },
|
|
11
|
-
append: { type: 'boolean', description: 'Append to existing value' }
|
|
12
|
-
},
|
|
13
|
-
required: ['key', 'value']
|
|
14
|
-
},
|
|
15
|
-
annotations: {
|
|
16
|
-
title: 'Update Memory',
|
|
17
|
-
audience: ['user', 'assistant']
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
export async function updateMemory(args) {
|
|
21
|
-
const { key: updateKey, value: updateValue, append = false } = args;
|
|
22
|
-
try {
|
|
23
|
-
const mm = MemoryManager.getInstance();
|
|
24
|
-
const existingMemory = mm.recall(updateKey);
|
|
25
|
-
if (existingMemory) {
|
|
26
|
-
const newValue = append ? existingMemory.value + ' ' + updateValue : updateValue;
|
|
27
|
-
mm.update(updateKey, newValue);
|
|
28
|
-
return {
|
|
29
|
-
content: [{
|
|
30
|
-
type: 'text',
|
|
31
|
-
text: `✓ ${append ? 'Appended to' : 'Updated'} memory: "${updateKey}"`
|
|
32
|
-
}]
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
return {
|
|
37
|
-
content: [{ type: 'text', text: `✗ Memory not found: "${updateKey}". Use save_memory to create new memory.` }]
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
return {
|
|
43
|
-
content: [{ type: 'text', text: `✗ Error: ${error instanceof Error ? error.message : 'Unknown error'}` }]
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
// Planning tool - completely independent
|
|
2
|
-
export const analyzeRequirementsDefinition = {
|
|
3
|
-
name: 'analyze_requirements',
|
|
4
|
-
description: '요구사항 분석|필요한 것들|requirements analysis|what we need|analyze requirements|필수 기능 - Analyze project requirements',
|
|
5
|
-
inputSchema: {
|
|
6
|
-
type: 'object',
|
|
7
|
-
properties: {
|
|
8
|
-
requirements: { type: 'string', description: 'List of requirements to analyze' },
|
|
9
|
-
stakeholders: { type: 'string', description: 'Project stakeholders (e.g., users, admins, developers)' },
|
|
10
|
-
constraints: { type: 'string', description: 'Project constraints (timeline, budget, technical)' },
|
|
11
|
-
analysisMethod: { type: 'string', description: 'Analysis method', enum: ['moscow', 'kano', 'value-effort'], default: 'moscow' }
|
|
12
|
-
},
|
|
13
|
-
required: ['requirements']
|
|
14
|
-
},
|
|
15
|
-
annotations: {
|
|
16
|
-
title: 'Analyze Requirements',
|
|
17
|
-
audience: ['user', 'assistant']
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
export async function analyzeRequirements(args) {
|
|
21
|
-
const { requirements, stakeholders = 'end users, product owner, development team', constraints = 'standard timeline and budget constraints', analysisMethod = 'moscow' } = args;
|
|
22
|
-
// Parse requirements
|
|
23
|
-
const requirementList = requirements.split(/[,\n]/).map(r => r.trim()).filter(r => r.length > 0);
|
|
24
|
-
const stakeholderList = stakeholders.split(',').map(s => s.trim());
|
|
25
|
-
const analyzedRequirements = requirementList.map((req, index) => {
|
|
26
|
-
const reqId = `REQ-${String(index + 1).padStart(3, '0')}`;
|
|
27
|
-
// Determine requirement type
|
|
28
|
-
let type = 'functional';
|
|
29
|
-
if (req.toLowerCase().includes('performance') || req.toLowerCase().includes('security') || req.toLowerCase().includes('scalability')) {
|
|
30
|
-
type = 'non-functional';
|
|
31
|
-
}
|
|
32
|
-
else if (req.toLowerCase().includes('business') || req.toLowerCase().includes('revenue') || req.toLowerCase().includes('cost')) {
|
|
33
|
-
type = 'business';
|
|
34
|
-
}
|
|
35
|
-
else if (req.toLowerCase().includes('infrastructure') || req.toLowerCase().includes('architecture') || req.toLowerCase().includes('database')) {
|
|
36
|
-
type = 'technical';
|
|
37
|
-
}
|
|
38
|
-
// Determine priority using MoSCoW
|
|
39
|
-
let priority = 'should-have';
|
|
40
|
-
if (req.toLowerCase().includes('critical') || req.toLowerCase().includes('essential') || req.toLowerCase().includes('required')) {
|
|
41
|
-
priority = 'must-have';
|
|
42
|
-
}
|
|
43
|
-
else if (req.toLowerCase().includes('important') || req.toLowerCase().includes('needed')) {
|
|
44
|
-
priority = 'should-have';
|
|
45
|
-
}
|
|
46
|
-
else if (req.toLowerCase().includes('nice') || req.toLowerCase().includes('optional') || req.toLowerCase().includes('enhancement')) {
|
|
47
|
-
priority = 'could-have';
|
|
48
|
-
}
|
|
49
|
-
else if (req.toLowerCase().includes('future') || req.toLowerCase().includes('later') || req.toLowerCase().includes('v2')) {
|
|
50
|
-
priority = 'wont-have';
|
|
51
|
-
}
|
|
52
|
-
// Assess complexity
|
|
53
|
-
let complexity = 'medium';
|
|
54
|
-
if (req.length > 100 || req.toLowerCase().includes('complex') || req.toLowerCase().includes('integration') || req.toLowerCase().includes('advanced')) {
|
|
55
|
-
complexity = 'high';
|
|
56
|
-
}
|
|
57
|
-
else if (req.length < 50 || req.toLowerCase().includes('simple') || req.toLowerCase().includes('basic')) {
|
|
58
|
-
complexity = 'low';
|
|
59
|
-
}
|
|
60
|
-
// Assess risk
|
|
61
|
-
let risk = 'low';
|
|
62
|
-
if (req.toLowerCase().includes('external') || req.toLowerCase().includes('third-party') || req.toLowerCase().includes('new technology')) {
|
|
63
|
-
risk = 'high';
|
|
64
|
-
}
|
|
65
|
-
else if (req.toLowerCase().includes('integration') || req.toLowerCase().includes('performance') || complexity === 'high') {
|
|
66
|
-
risk = 'medium';
|
|
67
|
-
}
|
|
68
|
-
// Estimate effort
|
|
69
|
-
let estimatedEffort = '3-5 days';
|
|
70
|
-
if (complexity === 'high') {
|
|
71
|
-
estimatedEffort = '1-3 weeks';
|
|
72
|
-
}
|
|
73
|
-
else if (complexity === 'low') {
|
|
74
|
-
estimatedEffort = '1-2 days';
|
|
75
|
-
}
|
|
76
|
-
// Determine relevant stakeholders
|
|
77
|
-
const relevantStakeholders = stakeholderList.filter(stakeholder => {
|
|
78
|
-
if (type === 'business' && stakeholder.toLowerCase().includes('owner'))
|
|
79
|
-
return true;
|
|
80
|
-
if (type === 'technical' && stakeholder.toLowerCase().includes('developer'))
|
|
81
|
-
return true;
|
|
82
|
-
if (type === 'functional' && stakeholder.toLowerCase().includes('user'))
|
|
83
|
-
return true;
|
|
84
|
-
return true; // Include all by default
|
|
85
|
-
});
|
|
86
|
-
return {
|
|
87
|
-
id: reqId,
|
|
88
|
-
title: req.length > 50 ? req.substring(0, 47) + '...' : req,
|
|
89
|
-
description: req,
|
|
90
|
-
type,
|
|
91
|
-
priority,
|
|
92
|
-
complexity,
|
|
93
|
-
risk,
|
|
94
|
-
dependencies: [],
|
|
95
|
-
estimatedEffort,
|
|
96
|
-
stakeholders: relevantStakeholders
|
|
97
|
-
};
|
|
98
|
-
});
|
|
99
|
-
const analysis = {
|
|
100
|
-
action: 'analyze_requirements',
|
|
101
|
-
method: analysisMethod,
|
|
102
|
-
totalRequirements: analyzedRequirements.length,
|
|
103
|
-
requirements: analyzedRequirements,
|
|
104
|
-
priorityBreakdown: {
|
|
105
|
-
mustHave: analyzedRequirements.filter(r => r.priority === 'must-have').length,
|
|
106
|
-
shouldHave: analyzedRequirements.filter(r => r.priority === 'should-have').length,
|
|
107
|
-
couldHave: analyzedRequirements.filter(r => r.priority === 'could-have').length,
|
|
108
|
-
wontHave: analyzedRequirements.filter(r => r.priority === 'wont-have').length
|
|
109
|
-
},
|
|
110
|
-
typeBreakdown: {
|
|
111
|
-
functional: analyzedRequirements.filter(r => r.type === 'functional').length,
|
|
112
|
-
nonFunctional: analyzedRequirements.filter(r => r.type === 'non-functional').length,
|
|
113
|
-
business: analyzedRequirements.filter(r => r.type === 'business').length,
|
|
114
|
-
technical: analyzedRequirements.filter(r => r.type === 'technical').length
|
|
115
|
-
},
|
|
116
|
-
riskAssessment: {
|
|
117
|
-
high: analyzedRequirements.filter(r => r.risk === 'high').length,
|
|
118
|
-
medium: analyzedRequirements.filter(r => r.risk === 'medium').length,
|
|
119
|
-
low: analyzedRequirements.filter(r => r.risk === 'low').length
|
|
120
|
-
},
|
|
121
|
-
recommendations: [
|
|
122
|
-
'Focus on Must-Have requirements for MVP',
|
|
123
|
-
'Validate high-risk requirements early',
|
|
124
|
-
'Consider Should-Have items for post-MVP releases',
|
|
125
|
-
'Review Could-Have items based on resource availability',
|
|
126
|
-
'Plan technical requirements to support functional ones'
|
|
127
|
-
],
|
|
128
|
-
constraints: constraints,
|
|
129
|
-
status: 'success'
|
|
130
|
-
};
|
|
131
|
-
// Format output
|
|
132
|
-
let formattedOutput = `# Requirements Analysis\n\n`;
|
|
133
|
-
formattedOutput += `**Analysis Method:** ${analysisMethod.toUpperCase()} \n`;
|
|
134
|
-
formattedOutput += `**Total Requirements:** ${analysis.totalRequirements} \n`;
|
|
135
|
-
formattedOutput += `**Constraints:** ${constraints}\n\n`;
|
|
136
|
-
formattedOutput += `## Priority Breakdown (MoSCoW)\n`;
|
|
137
|
-
formattedOutput += `- **Must Have:** ${analysis.priorityBreakdown.mustHave}\n`;
|
|
138
|
-
formattedOutput += `- **Should Have:** ${analysis.priorityBreakdown.shouldHave}\n`;
|
|
139
|
-
formattedOutput += `- **Could Have:** ${analysis.priorityBreakdown.couldHave}\n`;
|
|
140
|
-
formattedOutput += `- **Won't Have:** ${analysis.priorityBreakdown.wontHave}\n\n`;
|
|
141
|
-
formattedOutput += `## Risk Assessment\n`;
|
|
142
|
-
formattedOutput += `- **High Risk:** ${analysis.riskAssessment.high} requirements\n`;
|
|
143
|
-
formattedOutput += `- **Medium Risk:** ${analysis.riskAssessment.medium} requirements\n`;
|
|
144
|
-
formattedOutput += `- **Low Risk:** ${analysis.riskAssessment.low} requirements\n\n`;
|
|
145
|
-
formattedOutput += `## Detailed Requirements\n\n`;
|
|
146
|
-
// Group by priority
|
|
147
|
-
const priorities = ['must-have', 'should-have', 'could-have', 'wont-have'];
|
|
148
|
-
priorities.forEach(priority => {
|
|
149
|
-
const reqsForPriority = analyzedRequirements.filter(r => r.priority === priority);
|
|
150
|
-
if (reqsForPriority.length > 0) {
|
|
151
|
-
formattedOutput += `### ${priority.toUpperCase().replace('-', ' ')} (${reqsForPriority.length})\n\n`;
|
|
152
|
-
reqsForPriority.forEach(req => {
|
|
153
|
-
formattedOutput += `**${req.id}:** ${req.title} \n`;
|
|
154
|
-
formattedOutput += `*Type:* ${req.type} | *Complexity:* ${req.complexity} | *Risk:* ${req.risk} | *Effort:* ${req.estimatedEffort} \n`;
|
|
155
|
-
formattedOutput += `*Stakeholders:* ${req.stakeholders.join(', ')}\n\n`;
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
formattedOutput += `## Recommendations\n`;
|
|
160
|
-
analysis.recommendations.forEach(rec => {
|
|
161
|
-
formattedOutput += `- ${rec}\n`;
|
|
162
|
-
});
|
|
163
|
-
return {
|
|
164
|
-
content: [{ type: 'text', text: formattedOutput }]
|
|
165
|
-
};
|
|
166
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// Planning tool - completely independent
|
|
2
|
-
export const createUserStoriesDefinition = {
|
|
3
|
-
name: 'create_user_stories',
|
|
4
|
-
description: '스토리|사용자 스토리|user story|user stories|as a user - Generate user stories from requirements',
|
|
5
|
-
inputSchema: {
|
|
6
|
-
type: 'object',
|
|
7
|
-
properties: {
|
|
8
|
-
features: { type: 'string', description: 'List of features or requirements to convert to user stories' },
|
|
9
|
-
userTypes: { type: 'string', description: 'Types of users (e.g., admin, customer, guest)' },
|
|
10
|
-
priority: { type: 'string', description: 'Default priority level', enum: ['high', 'medium', 'low'] },
|
|
11
|
-
includeAcceptanceCriteria: { type: 'boolean', description: 'Include acceptance criteria for each story' }
|
|
12
|
-
},
|
|
13
|
-
required: ['features']
|
|
14
|
-
},
|
|
15
|
-
annotations: {
|
|
16
|
-
title: 'Create User Stories',
|
|
17
|
-
audience: ['user', 'assistant']
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
export async function createUserStories(args) {
|
|
21
|
-
const { features, userTypes = 'user, admin, guest', priority = 'medium', includeAcceptanceCriteria = true } = args;
|
|
22
|
-
// Parse features into individual items
|
|
23
|
-
const featureList = features.split(/[,\n]/).map(f => f.trim()).filter(f => f.length > 0);
|
|
24
|
-
const userTypeList = userTypes.split(',').map(u => u.trim());
|
|
25
|
-
const userStories = featureList.map((feature, index) => {
|
|
26
|
-
const storyId = `US-${String(index + 1).padStart(3, '0')}`;
|
|
27
|
-
// Determine user type based on feature content
|
|
28
|
-
let selectedUserType = userTypeList[0];
|
|
29
|
-
if (feature.toLowerCase().includes('admin') || feature.toLowerCase().includes('manage')) {
|
|
30
|
-
selectedUserType = userTypeList.find(u => u.toLowerCase().includes('admin')) || selectedUserType;
|
|
31
|
-
}
|
|
32
|
-
else if (feature.toLowerCase().includes('guest') || feature.toLowerCase().includes('browse')) {
|
|
33
|
-
selectedUserType = userTypeList.find(u => u.toLowerCase().includes('guest')) || selectedUserType;
|
|
34
|
-
}
|
|
35
|
-
// Extract functionality and benefit
|
|
36
|
-
const functionality = feature;
|
|
37
|
-
let benefit = 'to achieve my goals efficiently';
|
|
38
|
-
// Try to infer benefit from common patterns
|
|
39
|
-
if (feature.toLowerCase().includes('search'))
|
|
40
|
-
benefit = 'to find relevant information quickly';
|
|
41
|
-
else if (feature.toLowerCase().includes('save') || feature.toLowerCase().includes('store'))
|
|
42
|
-
benefit = 'to preserve my data for future use';
|
|
43
|
-
else if (feature.toLowerCase().includes('share'))
|
|
44
|
-
benefit = 'to collaborate with others effectively';
|
|
45
|
-
else if (feature.toLowerCase().includes('track') || feature.toLowerCase().includes('monitor'))
|
|
46
|
-
benefit = 'to stay informed about important changes';
|
|
47
|
-
else if (feature.toLowerCase().includes('customize') || feature.toLowerCase().includes('configure'))
|
|
48
|
-
benefit = 'to tailor the experience to my needs';
|
|
49
|
-
// Generate acceptance criteria
|
|
50
|
-
const acceptanceCriteria = includeAcceptanceCriteria ? [
|
|
51
|
-
`Given I am a ${selectedUserType}, when I access the ${functionality.toLowerCase()} feature, then it should be available and functional`,
|
|
52
|
-
`When I use the ${functionality.toLowerCase()} feature, then it should provide clear feedback about the action`,
|
|
53
|
-
`The ${functionality.toLowerCase()} feature should handle errors gracefully and provide helpful messages`,
|
|
54
|
-
`The feature should be accessible and usable across different devices and browsers`
|
|
55
|
-
] : [];
|
|
56
|
-
// Determine priority based on feature content
|
|
57
|
-
let storyPriority = priority;
|
|
58
|
-
if (feature.toLowerCase().includes('critical') || feature.toLowerCase().includes('security') || feature.toLowerCase().includes('login')) {
|
|
59
|
-
storyPriority = 'high';
|
|
60
|
-
}
|
|
61
|
-
else if (feature.toLowerCase().includes('nice to have') || feature.toLowerCase().includes('optional')) {
|
|
62
|
-
storyPriority = 'low';
|
|
63
|
-
}
|
|
64
|
-
// Estimate effort based on complexity
|
|
65
|
-
let estimatedEffort = '3-5 days';
|
|
66
|
-
if (feature.length > 100 || feature.toLowerCase().includes('complex') || feature.toLowerCase().includes('integration')) {
|
|
67
|
-
estimatedEffort = '1-2 weeks';
|
|
68
|
-
}
|
|
69
|
-
else if (feature.length < 30 || feature.toLowerCase().includes('simple') || feature.toLowerCase().includes('basic')) {
|
|
70
|
-
estimatedEffort = '1-2 days';
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
id: storyId,
|
|
74
|
-
title: `${selectedUserType} - ${functionality}`,
|
|
75
|
-
story: `As a ${selectedUserType}, I want to ${functionality.toLowerCase()}, so that ${benefit}.`,
|
|
76
|
-
userType: selectedUserType,
|
|
77
|
-
functionality,
|
|
78
|
-
benefit,
|
|
79
|
-
acceptanceCriteria,
|
|
80
|
-
priority: storyPriority,
|
|
81
|
-
estimatedEffort,
|
|
82
|
-
dependencies: []
|
|
83
|
-
};
|
|
84
|
-
});
|
|
85
|
-
const result = {
|
|
86
|
-
action: 'create_user_stories',
|
|
87
|
-
totalStories: userStories.length,
|
|
88
|
-
userTypes: userTypeList,
|
|
89
|
-
stories: userStories,
|
|
90
|
-
summary: {
|
|
91
|
-
high: userStories.filter(s => s.priority === 'high').length,
|
|
92
|
-
medium: userStories.filter(s => s.priority === 'medium').length,
|
|
93
|
-
low: userStories.filter(s => s.priority === 'low').length,
|
|
94
|
-
estimatedTotalEffort: `${userStories.length * 3}-${userStories.length * 7} days`
|
|
95
|
-
},
|
|
96
|
-
status: 'success'
|
|
97
|
-
};
|
|
98
|
-
// Format output
|
|
99
|
-
let formattedOutput = `# User Stories\n\n**Total Stories:** ${result.totalStories} \n**Priority Breakdown:** ${result.summary.high} High, ${result.summary.medium} Medium, ${result.summary.low} Low \n**Estimated Effort:** ${result.summary.estimatedTotalEffort}\n\n`;
|
|
100
|
-
userStories.forEach((story, index) => {
|
|
101
|
-
formattedOutput += `## ${story.id}: ${story.title}\n\n`;
|
|
102
|
-
formattedOutput += `**Story:** ${story.story}\n\n`;
|
|
103
|
-
formattedOutput += `**Priority:** ${story.priority.toUpperCase()} \n`;
|
|
104
|
-
formattedOutput += `**Estimated Effort:** ${story.estimatedEffort}\n\n`;
|
|
105
|
-
if (story.acceptanceCriteria.length > 0) {
|
|
106
|
-
formattedOutput += `**Acceptance Criteria:**\n`;
|
|
107
|
-
story.acceptanceCriteria.forEach((criteria, i) => {
|
|
108
|
-
formattedOutput += `${i + 1}. ${criteria}\n`;
|
|
109
|
-
});
|
|
110
|
-
formattedOutput += '\n';
|
|
111
|
-
}
|
|
112
|
-
if (index < userStories.length - 1) {
|
|
113
|
-
formattedOutput += '---\n\n';
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
return {
|
|
117
|
-
content: [{ type: 'text', text: formattedOutput }]
|
|
118
|
-
};
|
|
119
|
-
}
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
// Planning tool - completely independent
|
|
2
|
-
export const featureRoadmapDefinition = {
|
|
3
|
-
name: 'feature_roadmap',
|
|
4
|
-
description: '로드맵|일정|계획표|roadmap|timeline|project plan|development schedule - Generate development roadmap',
|
|
5
|
-
inputSchema: {
|
|
6
|
-
type: 'object',
|
|
7
|
-
properties: {
|
|
8
|
-
projectName: { type: 'string', description: 'Name of the project' },
|
|
9
|
-
features: { type: 'string', description: 'List of features to include in roadmap' },
|
|
10
|
-
timeframe: { type: 'string', description: 'Project timeframe', enum: ['3-months', '6-months', '12-months', 'custom'] },
|
|
11
|
-
approach: { type: 'string', description: 'Development approach', enum: ['mvp-first', 'phased-rollout', 'big-bang'], default: 'mvp-first' },
|
|
12
|
-
teamSize: { type: 'number', description: 'Development team size' }
|
|
13
|
-
},
|
|
14
|
-
required: ['projectName', 'features']
|
|
15
|
-
},
|
|
16
|
-
annotations: {
|
|
17
|
-
title: 'Feature Roadmap',
|
|
18
|
-
audience: ['user', 'assistant']
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
export async function featureRoadmap(args) {
|
|
22
|
-
const { projectName, features, timeframe = '6-months', approach = 'mvp-first', teamSize = 3 } = args;
|
|
23
|
-
// Parse features
|
|
24
|
-
const featureList = features.split(/[,\n]/).map(f => f.trim()).filter(f => f.length > 0);
|
|
25
|
-
// Define phases based on approach
|
|
26
|
-
let phaseNames = [];
|
|
27
|
-
if (approach === 'mvp-first') {
|
|
28
|
-
phaseNames = ['MVP Foundation', 'Core Features', 'Advanced Features', 'Optimization & Scaling'];
|
|
29
|
-
}
|
|
30
|
-
else if (approach === 'phased-rollout') {
|
|
31
|
-
phaseNames = ['Phase 1: Core', 'Phase 2: Enhancement', 'Phase 3: Expansion', 'Phase 4: Innovation'];
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
phaseNames = ['Planning & Setup', 'Development Sprint', 'Integration & Testing', 'Launch & Monitoring'];
|
|
35
|
-
}
|
|
36
|
-
// Calculate phase durations
|
|
37
|
-
const totalMonths = timeframe === '3-months' ? 3 : timeframe === '6-months' ? 6 : timeframe === '12-months' ? 12 : 6;
|
|
38
|
-
const monthsPerPhase = Math.ceil(totalMonths / phaseNames.length);
|
|
39
|
-
// Categorize features by priority and complexity
|
|
40
|
-
const roadmapItems = featureList.map((feature, index) => {
|
|
41
|
-
const itemId = `F-${String(index + 1).padStart(3, '0')}`;
|
|
42
|
-
// Determine priority
|
|
43
|
-
let priority = 'medium';
|
|
44
|
-
if (feature.toLowerCase().includes('critical') || feature.toLowerCase().includes('core') || feature.toLowerCase().includes('essential')) {
|
|
45
|
-
priority = 'high';
|
|
46
|
-
}
|
|
47
|
-
else if (feature.toLowerCase().includes('enhancement') || feature.toLowerCase().includes('nice') || feature.toLowerCase().includes('optional')) {
|
|
48
|
-
priority = 'low';
|
|
49
|
-
}
|
|
50
|
-
// Determine phase based on priority and approach
|
|
51
|
-
let phase = phaseNames[1]; // Default to second phase
|
|
52
|
-
if (priority === 'high' || feature.toLowerCase().includes('mvp') || feature.toLowerCase().includes('basic')) {
|
|
53
|
-
phase = phaseNames[0];
|
|
54
|
-
}
|
|
55
|
-
else if (priority === 'low' || feature.toLowerCase().includes('advanced') || feature.toLowerCase().includes('future')) {
|
|
56
|
-
phase = phaseNames[Math.min(2, phaseNames.length - 1)];
|
|
57
|
-
}
|
|
58
|
-
// Estimate duration
|
|
59
|
-
let estimatedDuration = '2-3 weeks';
|
|
60
|
-
if (feature.length > 100 || feature.toLowerCase().includes('complex') || feature.toLowerCase().includes('integration')) {
|
|
61
|
-
estimatedDuration = '4-6 weeks';
|
|
62
|
-
}
|
|
63
|
-
else if (feature.length < 50 || feature.toLowerCase().includes('simple')) {
|
|
64
|
-
estimatedDuration = '1-2 weeks';
|
|
65
|
-
}
|
|
66
|
-
// Generate deliverables
|
|
67
|
-
const deliverables = [
|
|
68
|
-
`${feature} implementation`,
|
|
69
|
-
`Unit and integration tests`,
|
|
70
|
-
`Documentation and user guides`,
|
|
71
|
-
`Code review and quality assurance`
|
|
72
|
-
];
|
|
73
|
-
// Generate success criteria
|
|
74
|
-
const successCriteria = [
|
|
75
|
-
`Feature functions as specified`,
|
|
76
|
-
`Meets performance requirements`,
|
|
77
|
-
`Passes all test cases`,
|
|
78
|
-
`User acceptance criteria met`
|
|
79
|
-
];
|
|
80
|
-
// Identify potential risks
|
|
81
|
-
const risks = [];
|
|
82
|
-
if (feature.toLowerCase().includes('external') || feature.toLowerCase().includes('third-party')) {
|
|
83
|
-
risks.push('External dependency risk');
|
|
84
|
-
}
|
|
85
|
-
if (feature.toLowerCase().includes('performance') || feature.toLowerCase().includes('scalability')) {
|
|
86
|
-
risks.push('Performance optimization complexity');
|
|
87
|
-
}
|
|
88
|
-
if (feature.toLowerCase().includes('security') || feature.toLowerCase().includes('authentication')) {
|
|
89
|
-
risks.push('Security implementation complexity');
|
|
90
|
-
}
|
|
91
|
-
if (risks.length === 0) {
|
|
92
|
-
risks.push('Standard development risks');
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
id: itemId,
|
|
96
|
-
title: feature.length > 50 ? feature.substring(0, 47) + '...' : feature,
|
|
97
|
-
description: feature,
|
|
98
|
-
phase,
|
|
99
|
-
priority,
|
|
100
|
-
estimatedDuration,
|
|
101
|
-
dependencies: [],
|
|
102
|
-
deliverables,
|
|
103
|
-
successCriteria,
|
|
104
|
-
risks
|
|
105
|
-
};
|
|
106
|
-
});
|
|
107
|
-
// Group features by phase
|
|
108
|
-
const phases = phaseNames.map((phaseName, index) => {
|
|
109
|
-
const phaseFeatures = roadmapItems.filter(item => item.phase === phaseName);
|
|
110
|
-
const phaseGoals = [];
|
|
111
|
-
if (index === 0) {
|
|
112
|
-
phaseGoals.push('Establish core functionality', 'Validate core assumptions', 'Build foundation for future features');
|
|
113
|
-
}
|
|
114
|
-
else if (index === 1) {
|
|
115
|
-
phaseGoals.push('Enhance user experience', 'Add key differentiating features', 'Improve system reliability');
|
|
116
|
-
}
|
|
117
|
-
else if (index === 2) {
|
|
118
|
-
phaseGoals.push('Scale system capabilities', 'Add advanced features', 'Optimize performance');
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
phaseGoals.push('Continuous improvement', 'Innovation and experimentation', 'Long-term sustainability');
|
|
122
|
-
}
|
|
123
|
-
const milestones = [
|
|
124
|
-
`${phaseName} features delivered`,
|
|
125
|
-
`Quality assurance completed`,
|
|
126
|
-
`User feedback incorporated`,
|
|
127
|
-
`Metrics and KPIs reviewed`
|
|
128
|
-
];
|
|
129
|
-
return {
|
|
130
|
-
name: phaseName,
|
|
131
|
-
duration: `${monthsPerPhase} month${monthsPerPhase > 1 ? 's' : ''}`,
|
|
132
|
-
goals: phaseGoals,
|
|
133
|
-
features: phaseFeatures,
|
|
134
|
-
milestones
|
|
135
|
-
};
|
|
136
|
-
});
|
|
137
|
-
const roadmap = {
|
|
138
|
-
action: 'feature_roadmap',
|
|
139
|
-
project: projectName,
|
|
140
|
-
timeframe,
|
|
141
|
-
approach,
|
|
142
|
-
teamSize,
|
|
143
|
-
phases,
|
|
144
|
-
summary: {
|
|
145
|
-
totalFeatures: roadmapItems.length,
|
|
146
|
-
totalDuration: `${totalMonths} months`,
|
|
147
|
-
highPriorityFeatures: roadmapItems.filter(f => f.priority === 'high').length,
|
|
148
|
-
mediumPriorityFeatures: roadmapItems.filter(f => f.priority === 'medium').length,
|
|
149
|
-
lowPriorityFeatures: roadmapItems.filter(f => f.priority === 'low').length
|
|
150
|
-
},
|
|
151
|
-
recommendations: [
|
|
152
|
-
'Review and validate priorities with stakeholders',
|
|
153
|
-
'Set up regular milestone reviews and adjustments',
|
|
154
|
-
'Plan for buffer time between phases for testing',
|
|
155
|
-
'Consider team capacity and external dependencies',
|
|
156
|
-
'Establish clear success metrics for each phase'
|
|
157
|
-
],
|
|
158
|
-
status: 'success'
|
|
159
|
-
};
|
|
160
|
-
// Format output
|
|
161
|
-
let formattedOutput = `# ${projectName} - Feature Roadmap\n\n`;
|
|
162
|
-
formattedOutput += `**Timeframe:** ${timeframe} \n`;
|
|
163
|
-
formattedOutput += `**Approach:** ${approach} \n`;
|
|
164
|
-
formattedOutput += `**Team Size:** ${teamSize} developers \n`;
|
|
165
|
-
formattedOutput += `**Total Features:** ${roadmap.summary.totalFeatures}\n\n`;
|
|
166
|
-
formattedOutput += `## Overview\n`;
|
|
167
|
-
formattedOutput += `- **High Priority:** ${roadmap.summary.highPriorityFeatures} features\n`;
|
|
168
|
-
formattedOutput += `- **Medium Priority:** ${roadmap.summary.mediumPriorityFeatures} features\n`;
|
|
169
|
-
formattedOutput += `- **Low Priority:** ${roadmap.summary.lowPriorityFeatures} features\n\n`;
|
|
170
|
-
phases.forEach((phase, index) => {
|
|
171
|
-
formattedOutput += `## ${phase.name}\n`;
|
|
172
|
-
formattedOutput += `**Duration:** ${phase.duration} \n`;
|
|
173
|
-
formattedOutput += `**Features:** ${phase.features.length}\n\n`;
|
|
174
|
-
formattedOutput += `### Goals\n`;
|
|
175
|
-
phase.goals.forEach(goal => {
|
|
176
|
-
formattedOutput += `- ${goal}\n`;
|
|
177
|
-
});
|
|
178
|
-
formattedOutput += '\n';
|
|
179
|
-
if (phase.features.length > 0) {
|
|
180
|
-
formattedOutput += `### Features\n`;
|
|
181
|
-
phase.features.forEach(feature => {
|
|
182
|
-
formattedOutput += `**${feature.id}:** ${feature.title} (${feature.priority.toUpperCase()}) \n`;
|
|
183
|
-
formattedOutput += `*Duration:* ${feature.estimatedDuration} \n`;
|
|
184
|
-
formattedOutput += `*Key Risks:* ${feature.risks.join(', ')}\n\n`;
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
formattedOutput += `### Milestones\n`;
|
|
188
|
-
phase.milestones.forEach(milestone => {
|
|
189
|
-
formattedOutput += `- ${milestone}\n`;
|
|
190
|
-
});
|
|
191
|
-
if (index < phases.length - 1) {
|
|
192
|
-
formattedOutput += '\n---\n\n';
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
formattedOutput += `\n## Recommendations\n`;
|
|
196
|
-
roadmap.recommendations.forEach(rec => {
|
|
197
|
-
formattedOutput += `- ${rec}\n`;
|
|
198
|
-
});
|
|
199
|
-
return {
|
|
200
|
-
content: [{ type: 'text', text: formattedOutput }]
|
|
201
|
-
};
|
|
202
|
-
}
|