vibe-coder-kit 6.0.0 → 6.1.0
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/.cursorrules +77 -0
- package/.github/copilot-instructions.md +108 -0
- package/.vibe/mcp/mcp-config.json +11 -0
- package/.vibe/mcp/server.js +686 -0
- package/.vibe/state/events.jsonl +3 -0
- package/package.json +6 -4
package/.cursorrules
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Vibe Coder Kit - Cursor Rules
|
|
2
|
+
|
|
3
|
+
## Rules
|
|
4
|
+
|
|
5
|
+
When working in this project, you MUST:
|
|
6
|
+
|
|
7
|
+
1. **Read `.vibe/config.json` first** to understand project configuration
|
|
8
|
+
2. **Check current phase** with `vibe status` before making changes
|
|
9
|
+
3. **Log all events** using `vibe_append_event` tool
|
|
10
|
+
4. **Follow the DAG workflow** - don't skip phases
|
|
11
|
+
5. **Block on blockers** - use `vibe_log_blocker` and wait for resolution
|
|
12
|
+
|
|
13
|
+
## Phase Rules
|
|
14
|
+
|
|
15
|
+
### init
|
|
16
|
+
- Set up project structure
|
|
17
|
+
- Initialize all configuration files
|
|
18
|
+
|
|
19
|
+
### plan
|
|
20
|
+
- Create detailed implementation plan
|
|
21
|
+
- Get approval before proceeding to code
|
|
22
|
+
|
|
23
|
+
### code
|
|
24
|
+
- Write code according to plan
|
|
25
|
+
- Log each significant change
|
|
26
|
+
- Run tests before marking complete
|
|
27
|
+
|
|
28
|
+
### review
|
|
29
|
+
- Review all changes
|
|
30
|
+
- Log any issues found
|
|
31
|
+
- Fix issues before proceeding
|
|
32
|
+
|
|
33
|
+
### test
|
|
34
|
+
- Run all tests
|
|
35
|
+
- Log test results
|
|
36
|
+
- Fix failures before proceeding
|
|
37
|
+
|
|
38
|
+
## Available Tools
|
|
39
|
+
|
|
40
|
+
Use these MCP tools to interact with VCK:
|
|
41
|
+
|
|
42
|
+
- `vibe_status` - Check current phase and status
|
|
43
|
+
- `vibe_append_event` - Log events
|
|
44
|
+
- `vibe_transition` - Move to next phase
|
|
45
|
+
- `vibe_check_health` - Run health checks
|
|
46
|
+
- `vibe_add_knowledge` - Add to knowledge base
|
|
47
|
+
- `vibe_search_knowledge` - Search knowledge base
|
|
48
|
+
- `vibe_log_blocker` - Log blockers
|
|
49
|
+
- `vibe_resolve_blocker` - Resolve blockers
|
|
50
|
+
- `vibe_get_blockers` - Check open blockers
|
|
51
|
+
|
|
52
|
+
## Anti-Patterns
|
|
53
|
+
|
|
54
|
+
DO NOT:
|
|
55
|
+
- Skip phases without explicit user approval
|
|
56
|
+
- Ignore blockers
|
|
57
|
+
- Make assumptions - research or ask
|
|
58
|
+
- Commit secrets or keys
|
|
59
|
+
- Break the DAG workflow
|
|
60
|
+
|
|
61
|
+
## Examples
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
User: Add user authentication
|
|
65
|
+
|
|
66
|
+
Agent actions:
|
|
67
|
+
1. vibe_status -> Check current phase
|
|
68
|
+
2. vibe_transition(phase: "plan", reason: "Planning auth feature")
|
|
69
|
+
3. [Create implementation plan]
|
|
70
|
+
4. vibe_append_event(type: "plan_created", data: {plan: "..."})
|
|
71
|
+
5. vibe_transition(phase: "code", reason: "Implementing auth")
|
|
72
|
+
6. [Write code]
|
|
73
|
+
7. vibe_append_event(type: "code_written", data: {files: [...]})
|
|
74
|
+
8. vibe_transition(phase: "review", reason: "Reviewing auth")
|
|
75
|
+
9. [Review code]
|
|
76
|
+
10. vibe_resolve_blocker(blockerId: "auth_security", resolution: "Fixed")
|
|
77
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Vibe Coder Kit - Copilot Instructions
|
|
2
|
+
|
|
3
|
+
## Project Context
|
|
4
|
+
|
|
5
|
+
This project uses Vibe Coder Kit (VCK) for AI agent workflow management.
|
|
6
|
+
|
|
7
|
+
## Key Rules
|
|
8
|
+
|
|
9
|
+
1. **Always check status first** - Run `vibe status` to know current phase
|
|
10
|
+
2. **Log everything** - Use MCP tools to log events and decisions
|
|
11
|
+
3. **Follow the workflow** - Respect phase transitions
|
|
12
|
+
4. **No assumptions** - Research or ask user when uncertain
|
|
13
|
+
5. **Block on blockers** - Don't proceed until blockers are resolved
|
|
14
|
+
|
|
15
|
+
## MCP Tools Available
|
|
16
|
+
|
|
17
|
+
When you see these tools, use them:
|
|
18
|
+
|
|
19
|
+
| Tool | Purpose |
|
|
20
|
+
|------|---------|
|
|
21
|
+
| `vibe_status` | Check project status |
|
|
22
|
+
| `vibe_append_event` | Log an event |
|
|
23
|
+
| `vibe_transition` | Change phase |
|
|
24
|
+
| `vibe_check_health` | Health check |
|
|
25
|
+
| `vibe_add_knowledge` | Add to knowledge base |
|
|
26
|
+
| `vibe_search_knowledge` | Search knowledge |
|
|
27
|
+
| `vibe_log_blocker` | Log a blocker |
|
|
28
|
+
| `vibe_resolve_blocker` | Resolve a blocker |
|
|
29
|
+
| `vibe_get_blockers` | List blockers |
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
User Request
|
|
35
|
+
↓
|
|
36
|
+
Check Status (vibe_status)
|
|
37
|
+
↓
|
|
38
|
+
Plan (vibe_transition to plan)
|
|
39
|
+
↓
|
|
40
|
+
Implement (vibe_transition to code)
|
|
41
|
+
↓
|
|
42
|
+
Review (vibe_transition to review)
|
|
43
|
+
↓
|
|
44
|
+
Test (vibe_transition to test)
|
|
45
|
+
↓
|
|
46
|
+
Done
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Code Style
|
|
50
|
+
|
|
51
|
+
- TypeScript for all new code
|
|
52
|
+
- Turkish for comments and docs
|
|
53
|
+
- English for code identifiers
|
|
54
|
+
- No secrets in code
|
|
55
|
+
- Log significant decisions
|
|
56
|
+
|
|
57
|
+
## Common Patterns
|
|
58
|
+
|
|
59
|
+
### Starting Work
|
|
60
|
+
```javascript
|
|
61
|
+
// Check current phase
|
|
62
|
+
vibe_status()
|
|
63
|
+
|
|
64
|
+
// Transition to planning
|
|
65
|
+
vibe_transition({
|
|
66
|
+
phase: "plan",
|
|
67
|
+
reason: "Starting new feature"
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### During Work
|
|
72
|
+
```javascript
|
|
73
|
+
// Log progress
|
|
74
|
+
vibe_append_event({
|
|
75
|
+
type: "progress",
|
|
76
|
+
data: {
|
|
77
|
+
description: "Implemented auth module",
|
|
78
|
+
files: ["auth.ts", "auth.test.ts"]
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Finishing Work
|
|
84
|
+
```javascript
|
|
85
|
+
// Log completion
|
|
86
|
+
vibe_append_event({
|
|
87
|
+
type: "task_complete",
|
|
88
|
+
data: {
|
|
89
|
+
task: "Add user authentication",
|
|
90
|
+
result: "success"
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Error Handling
|
|
96
|
+
|
|
97
|
+
If you encounter blockers:
|
|
98
|
+
1. Log the blocker: `vibe_log_blocker({description: "...", severity: "high"})`
|
|
99
|
+
2. Ask user for guidance
|
|
100
|
+
3. Wait for resolution
|
|
101
|
+
4. Resolve blocker: `vibe_resolve_blocker({blockerId: "...", resolution: "..."})`
|
|
102
|
+
|
|
103
|
+
## Security
|
|
104
|
+
|
|
105
|
+
- Never commit secrets
|
|
106
|
+
- Use environment variables
|
|
107
|
+
- Validate all inputs
|
|
108
|
+
- Log security events
|
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vibe Coder Kit - MCP Server
|
|
5
|
+
*
|
|
6
|
+
* Exposes VCK modules as MCP tools for AI agents.
|
|
7
|
+
* Usage: node .vibe/mcp/server.js
|
|
8
|
+
*
|
|
9
|
+
* Transport: stdio
|
|
10
|
+
* Protocol: MCP (Model Context Protocol)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { readFileSync, writeFileSync, existsSync, mkdirSync } = require('fs');
|
|
14
|
+
const { join, resolve } = require('path');
|
|
15
|
+
const { createHash } = require('crypto');
|
|
16
|
+
|
|
17
|
+
// ============================================================
|
|
18
|
+
// Configuration
|
|
19
|
+
// ============================================================
|
|
20
|
+
|
|
21
|
+
const PROJECT_ROOT = process.env.VIBE_PROJECT_ROOT || process.cwd();
|
|
22
|
+
const VIBE_DIR = join(PROJECT_ROOT, '.vibe');
|
|
23
|
+
const STATE_DIR = join(VIBE_DIR, 'state');
|
|
24
|
+
const STATE_FILE = join(STATE_DIR, 'events.jsonl');
|
|
25
|
+
const CONFIG_FILE = join(VIBE_DIR, 'config.json');
|
|
26
|
+
const KNOWLEDGE_DIR = join(VIBE_DIR, 'memory');
|
|
27
|
+
|
|
28
|
+
// ============================================================
|
|
29
|
+
// Utility Functions
|
|
30
|
+
// ============================================================
|
|
31
|
+
|
|
32
|
+
function ensureDirectories() {
|
|
33
|
+
[VIBE_DIR, STATE_DIR, KNOWLEDGE_DIR].forEach(dir => {
|
|
34
|
+
if (!existsSync(dir)) {
|
|
35
|
+
mkdirSync(dir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readJSON(filePath) {
|
|
41
|
+
try {
|
|
42
|
+
if (!existsSync(filePath)) return null;
|
|
43
|
+
return JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
44
|
+
} catch (e) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function writeJSON(filePath, data) {
|
|
50
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function appendLine(filePath, line) {
|
|
54
|
+
writeFileSync(filePath, line + '\n', { flag: 'a' });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function generateId() {
|
|
58
|
+
return `evt_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function computeChecksum(event) {
|
|
62
|
+
return createHash('sha256')
|
|
63
|
+
.update(JSON.stringify(event))
|
|
64
|
+
.digest('hex')
|
|
65
|
+
.substring(0, 16);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getTimestamp() {
|
|
69
|
+
return new Date().toISOString();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ============================================================
|
|
73
|
+
// Event Store Functions
|
|
74
|
+
// ============================================================
|
|
75
|
+
|
|
76
|
+
function readEvents() {
|
|
77
|
+
if (!existsSync(STATE_FILE)) return [];
|
|
78
|
+
const content = readFileSync(STATE_FILE, 'utf-8');
|
|
79
|
+
return content
|
|
80
|
+
.split('\n')
|
|
81
|
+
.filter(line => line.trim())
|
|
82
|
+
.map(line => {
|
|
83
|
+
try {
|
|
84
|
+
return JSON.parse(line);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
.filter(e => e !== null);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function appendEvent(eventData) {
|
|
93
|
+
ensureDirectories();
|
|
94
|
+
|
|
95
|
+
const event = {
|
|
96
|
+
id: generateId(),
|
|
97
|
+
timestamp: getTimestamp(),
|
|
98
|
+
...eventData
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
event.checksum = computeChecksum(event);
|
|
102
|
+
|
|
103
|
+
appendLine(STATE_FILE, JSON.stringify(event));
|
|
104
|
+
|
|
105
|
+
return event;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getLatestPhase() {
|
|
109
|
+
const events = readEvents();
|
|
110
|
+
const phaseEvents = events.filter(e => e.type === 'phase_transition');
|
|
111
|
+
if (phaseEvents.length === 0) return 'init';
|
|
112
|
+
return phaseEvents[phaseEvents.length - 1].data?.phase || 'init';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ============================================================
|
|
116
|
+
// MCP Protocol Implementation
|
|
117
|
+
// ============================================================
|
|
118
|
+
|
|
119
|
+
const TOOLS = [
|
|
120
|
+
{
|
|
121
|
+
name: 'vibe_status',
|
|
122
|
+
description: 'Show current VCK status including phase, events, and blockers',
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: 'object',
|
|
125
|
+
properties: {},
|
|
126
|
+
required: []
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'vibe_append_event',
|
|
131
|
+
description: 'Append a new event to the event store',
|
|
132
|
+
inputSchema: {
|
|
133
|
+
type: 'object',
|
|
134
|
+
properties: {
|
|
135
|
+
type: {
|
|
136
|
+
type: 'string',
|
|
137
|
+
description: 'Event type (e.g., phase_transition, code_written, review_done)'
|
|
138
|
+
},
|
|
139
|
+
data: {
|
|
140
|
+
type: 'object',
|
|
141
|
+
description: 'Event data payload'
|
|
142
|
+
},
|
|
143
|
+
phase: {
|
|
144
|
+
type: 'string',
|
|
145
|
+
description: 'Current phase (e.g., plan, code, review)'
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
required: ['type', 'data']
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: 'vibe_get_events',
|
|
153
|
+
description: 'Get all events from the event store',
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: 'object',
|
|
156
|
+
properties: {
|
|
157
|
+
type: {
|
|
158
|
+
type: 'string',
|
|
159
|
+
description: 'Filter by event type (optional)'
|
|
160
|
+
},
|
|
161
|
+
limit: {
|
|
162
|
+
type: 'number',
|
|
163
|
+
description: 'Maximum number of events to return (default: 50)'
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
required: []
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: 'vibe_transition',
|
|
171
|
+
description: 'Transition to a new workflow phase',
|
|
172
|
+
inputSchema: {
|
|
173
|
+
type: 'object',
|
|
174
|
+
properties: {
|
|
175
|
+
phase: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
description: 'Target phase (e.g., plan, code, review, test)'
|
|
178
|
+
},
|
|
179
|
+
reason: {
|
|
180
|
+
type: 'string',
|
|
181
|
+
description: 'Reason for transition'
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
required: ['phase', 'reason']
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: 'vibe_check_health',
|
|
189
|
+
description: 'Run health checks on the VCK installation',
|
|
190
|
+
inputSchema: {
|
|
191
|
+
type: 'object',
|
|
192
|
+
properties: {},
|
|
193
|
+
required: []
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'vibe_add_knowledge',
|
|
198
|
+
description: 'Add an entry to the knowledge base',
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: 'object',
|
|
201
|
+
properties: {
|
|
202
|
+
title: {
|
|
203
|
+
type: 'string',
|
|
204
|
+
description: 'Knowledge entry title'
|
|
205
|
+
},
|
|
206
|
+
content: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'Knowledge entry content'
|
|
209
|
+
},
|
|
210
|
+
tags: {
|
|
211
|
+
type: 'array',
|
|
212
|
+
items: { type: 'string' },
|
|
213
|
+
description: 'Tags for categorization'
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
required: ['title', 'content']
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: 'vibe_search_knowledge',
|
|
221
|
+
description: 'Search the knowledge base',
|
|
222
|
+
inputSchema: {
|
|
223
|
+
type: 'object',
|
|
224
|
+
properties: {
|
|
225
|
+
query: {
|
|
226
|
+
type: 'string',
|
|
227
|
+
description: 'Search query'
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
required: ['query']
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: 'vibe_get_config',
|
|
235
|
+
description: 'Get the current project configuration',
|
|
236
|
+
inputSchema: {
|
|
237
|
+
type: 'object',
|
|
238
|
+
properties: {},
|
|
239
|
+
required: []
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: 'vibe_update_config',
|
|
244
|
+
description: 'Update project configuration',
|
|
245
|
+
inputSchema: {
|
|
246
|
+
type: 'object',
|
|
247
|
+
properties: {
|
|
248
|
+
updates: {
|
|
249
|
+
type: 'object',
|
|
250
|
+
description: 'Configuration updates to apply'
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
required: ['updates']
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: 'vibe_log_blocker',
|
|
258
|
+
description: 'Log a blocker that prevents progress',
|
|
259
|
+
inputSchema: {
|
|
260
|
+
type: 'object',
|
|
261
|
+
properties: {
|
|
262
|
+
description: {
|
|
263
|
+
type: 'string',
|
|
264
|
+
description: 'Description of the blocker'
|
|
265
|
+
},
|
|
266
|
+
severity: {
|
|
267
|
+
type: 'string',
|
|
268
|
+
enum: ['low', 'medium', 'high', 'critical'],
|
|
269
|
+
description: 'Blocker severity'
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
required: ['description']
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: 'vibe_resolve_blocker',
|
|
277
|
+
description: 'Mark a blocker as resolved',
|
|
278
|
+
inputSchema: {
|
|
279
|
+
type: 'object',
|
|
280
|
+
properties: {
|
|
281
|
+
blockerId: {
|
|
282
|
+
type: 'string',
|
|
283
|
+
description: 'ID of the blocker to resolve'
|
|
284
|
+
},
|
|
285
|
+
resolution: {
|
|
286
|
+
type: 'string',
|
|
287
|
+
description: 'How the blocker was resolved'
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
required: ['blockerId', 'resolution']
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
name: 'vibe_get_blockers',
|
|
295
|
+
description: 'Get all open blockers',
|
|
296
|
+
inputSchema: {
|
|
297
|
+
type: 'object',
|
|
298
|
+
properties: {},
|
|
299
|
+
required: []
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
];
|
|
303
|
+
|
|
304
|
+
// ============================================================
|
|
305
|
+
// Tool Handlers
|
|
306
|
+
// ============================================================
|
|
307
|
+
|
|
308
|
+
const handlers = {
|
|
309
|
+
vibe_status: () => {
|
|
310
|
+
const events = readEvents();
|
|
311
|
+
const phase = getLatestPhase();
|
|
312
|
+
const blockers = events.filter(e =>
|
|
313
|
+
e.type === 'blocker' && !e.data?.resolved
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
phase,
|
|
318
|
+
lastUpdated: events.length > 0 ? events[events.length - 1].timestamp : null,
|
|
319
|
+
totalEvents: events.length,
|
|
320
|
+
openBlockers: blockers.length,
|
|
321
|
+
recentEvents: events.slice(-5)
|
|
322
|
+
};
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
vibe_append_event: (args) => {
|
|
326
|
+
const event = appendEvent({
|
|
327
|
+
type: args.type,
|
|
328
|
+
phase: args.phase || getLatestPhase(),
|
|
329
|
+
data: args.data
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
success: true,
|
|
334
|
+
event
|
|
335
|
+
};
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
vibe_get_events: (args) => {
|
|
339
|
+
let events = readEvents();
|
|
340
|
+
|
|
341
|
+
if (args.type) {
|
|
342
|
+
events = events.filter(e => e.type === args.type);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const limit = args.limit || 50;
|
|
346
|
+
return events.slice(-limit);
|
|
347
|
+
},
|
|
348
|
+
|
|
349
|
+
vibe_transition: (args) => {
|
|
350
|
+
const fromPhase = getLatestPhase();
|
|
351
|
+
|
|
352
|
+
const event = appendEvent({
|
|
353
|
+
type: 'phase_transition',
|
|
354
|
+
data: {
|
|
355
|
+
from: fromPhase,
|
|
356
|
+
to: args.phase,
|
|
357
|
+
reason: args.reason
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
success: true,
|
|
363
|
+
from: fromPhase,
|
|
364
|
+
to: args.phase,
|
|
365
|
+
event
|
|
366
|
+
};
|
|
367
|
+
},
|
|
368
|
+
|
|
369
|
+
vibe_check_health: () => {
|
|
370
|
+
const checks = [];
|
|
371
|
+
|
|
372
|
+
// Check .vibe directory
|
|
373
|
+
checks.push({
|
|
374
|
+
name: '.vibe directory',
|
|
375
|
+
status: existsSync(VIBE_DIR) ? 'pass' : 'fail'
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Check config.json
|
|
379
|
+
checks.push({
|
|
380
|
+
name: 'config.json',
|
|
381
|
+
status: existsSync(CONFIG_FILE) ? 'pass' : 'fail'
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
// Check state directory
|
|
385
|
+
checks.push({
|
|
386
|
+
name: 'State directory',
|
|
387
|
+
status: existsSync(STATE_DIR) ? 'pass' : 'fail'
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// Check knowledge directory
|
|
391
|
+
checks.push({
|
|
392
|
+
name: 'Knowledge directory',
|
|
393
|
+
status: existsSync(KNOWLEDGE_DIR) ? 'pass' : 'fail'
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// Check events file
|
|
397
|
+
checks.push({
|
|
398
|
+
name: 'Events file',
|
|
399
|
+
status: existsSync(STATE_FILE) ? 'pass' : 'warn',
|
|
400
|
+
message: existsSync(STATE_FILE) ? undefined : 'No events yet'
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const allPassed = checks.every(c => c.status === 'pass');
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
healthy: allPassed,
|
|
407
|
+
checks,
|
|
408
|
+
timestamp: getTimestamp()
|
|
409
|
+
};
|
|
410
|
+
},
|
|
411
|
+
|
|
412
|
+
vibe_add_knowledge: (args) => {
|
|
413
|
+
ensureDirectories();
|
|
414
|
+
|
|
415
|
+
const id = `kb_${Date.now()}`;
|
|
416
|
+
const entry = {
|
|
417
|
+
id,
|
|
418
|
+
title: args.title,
|
|
419
|
+
content: args.content,
|
|
420
|
+
tags: args.tags || [],
|
|
421
|
+
createdAt: getTimestamp()
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
const filePath = join(KNOWLEDGE_DIR, `${id}.json`);
|
|
425
|
+
writeJSON(filePath, entry);
|
|
426
|
+
|
|
427
|
+
// Update INDEX.md
|
|
428
|
+
const indexPath = join(KNOWLEDGE_DIR, 'INDEX.md');
|
|
429
|
+
const indexEntry = `- [${args.title}](${id}.json) - ${args.tags?.join(', ') || 'untagged'}\n`;
|
|
430
|
+
writeFileSync(indexPath, indexEntry, { flag: 'a' });
|
|
431
|
+
|
|
432
|
+
return {
|
|
433
|
+
success: true,
|
|
434
|
+
entry
|
|
435
|
+
};
|
|
436
|
+
},
|
|
437
|
+
|
|
438
|
+
vibe_search_knowledge: (args) => {
|
|
439
|
+
if (!existsSync(KNOWLEDGE_DIR)) {
|
|
440
|
+
return { results: [], total: 0 };
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const { readdirSync } = require('fs');
|
|
444
|
+
const files = readdirSync(KNOWLEDGE_DIR).filter(f => f.endsWith('.json'));
|
|
445
|
+
const query = args.query.toLowerCase();
|
|
446
|
+
|
|
447
|
+
const results = [];
|
|
448
|
+
|
|
449
|
+
for (const file of files) {
|
|
450
|
+
const entry = readJSON(join(KNOWLEDGE_DIR, file));
|
|
451
|
+
if (!entry) continue;
|
|
452
|
+
|
|
453
|
+
const matches =
|
|
454
|
+
entry.title?.toLowerCase().includes(query) ||
|
|
455
|
+
entry.content?.toLowerCase().includes(query) ||
|
|
456
|
+
entry.tags?.some(t => t.toLowerCase().includes(query));
|
|
457
|
+
|
|
458
|
+
if (matches) {
|
|
459
|
+
results.push(entry);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return {
|
|
464
|
+
results,
|
|
465
|
+
total: results.length,
|
|
466
|
+
query: args.query
|
|
467
|
+
};
|
|
468
|
+
},
|
|
469
|
+
|
|
470
|
+
vibe_get_config: () => {
|
|
471
|
+
return readJSON(CONFIG_FILE) || {};
|
|
472
|
+
},
|
|
473
|
+
|
|
474
|
+
vibe_update_config: (args) => {
|
|
475
|
+
const current = readJSON(CONFIG_FILE) || {};
|
|
476
|
+
const updated = { ...current, ...args.updates };
|
|
477
|
+
writeJSON(CONFIG_FILE, updated);
|
|
478
|
+
|
|
479
|
+
return {
|
|
480
|
+
success: true,
|
|
481
|
+
config: updated
|
|
482
|
+
};
|
|
483
|
+
},
|
|
484
|
+
|
|
485
|
+
vibe_log_blocker: (args) => {
|
|
486
|
+
const blockerId = `blocker_${Date.now()}`;
|
|
487
|
+
|
|
488
|
+
const event = appendEvent({
|
|
489
|
+
type: 'blocker',
|
|
490
|
+
data: {
|
|
491
|
+
id: blockerId,
|
|
492
|
+
description: args.description,
|
|
493
|
+
severity: args.severity || 'medium',
|
|
494
|
+
resolved: false,
|
|
495
|
+
createdAt: getTimestamp()
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
return {
|
|
500
|
+
success: true,
|
|
501
|
+
blockerId,
|
|
502
|
+
event
|
|
503
|
+
};
|
|
504
|
+
},
|
|
505
|
+
|
|
506
|
+
vibe_resolve_blocker: (args) => {
|
|
507
|
+
const events = readEvents();
|
|
508
|
+
const blockerEvent = events.find(e =>
|
|
509
|
+
e.type === 'blocker' && e.data?.id === args.blockerId
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
if (!blockerEvent) {
|
|
513
|
+
return {
|
|
514
|
+
success: false,
|
|
515
|
+
error: `Blocker ${args.blockerId} not found`
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const event = appendEvent({
|
|
520
|
+
type: 'blocker_resolved',
|
|
521
|
+
data: {
|
|
522
|
+
id: args.blockerId,
|
|
523
|
+
resolution: args.resolution,
|
|
524
|
+
resolvedAt: getTimestamp()
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
return {
|
|
529
|
+
success: true,
|
|
530
|
+
blockerId: args.blockerId,
|
|
531
|
+
event
|
|
532
|
+
};
|
|
533
|
+
},
|
|
534
|
+
|
|
535
|
+
vibe_get_blockers: () => {
|
|
536
|
+
const events = readEvents();
|
|
537
|
+
const blockers = events.filter(e => e.type === 'blocker');
|
|
538
|
+
|
|
539
|
+
// Mark resolved ones
|
|
540
|
+
const resolved = events
|
|
541
|
+
.filter(e => e.type === 'blocker_resolved')
|
|
542
|
+
.map(e => e.data?.id);
|
|
543
|
+
|
|
544
|
+
const open = blockers.filter(b =>
|
|
545
|
+
!resolved.includes(b.data?.id)
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
return {
|
|
549
|
+
open: open.map(b => b.data),
|
|
550
|
+
resolved: blockers.filter(b => resolved.includes(b.data?.id)).map(b => b.data),
|
|
551
|
+
totalOpen: open.length
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
// ============================================================
|
|
557
|
+
// MCP Message Handling
|
|
558
|
+
// ============================================================
|
|
559
|
+
|
|
560
|
+
function handleMessage(message) {
|
|
561
|
+
const { id, method, params } = message;
|
|
562
|
+
|
|
563
|
+
// Initialize
|
|
564
|
+
if (method === 'initialize') {
|
|
565
|
+
return {
|
|
566
|
+
jsonrpc: '2.0',
|
|
567
|
+
id,
|
|
568
|
+
result: {
|
|
569
|
+
protocolVersion: '2024-11-05',
|
|
570
|
+
capabilities: {
|
|
571
|
+
tools: {}
|
|
572
|
+
},
|
|
573
|
+
serverInfo: {
|
|
574
|
+
name: 'vibe-coder-kit',
|
|
575
|
+
version: '6.0.0'
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// List tools
|
|
582
|
+
if (method === 'tools/list') {
|
|
583
|
+
return {
|
|
584
|
+
jsonrpc: '2.0',
|
|
585
|
+
id,
|
|
586
|
+
result: {
|
|
587
|
+
tools: TOOLS
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Call tool
|
|
593
|
+
if (method === 'tools/call') {
|
|
594
|
+
const { name, arguments: args } = params;
|
|
595
|
+
|
|
596
|
+
if (!handlers[name]) {
|
|
597
|
+
return {
|
|
598
|
+
jsonrpc: '2.0',
|
|
599
|
+
id,
|
|
600
|
+
result: {
|
|
601
|
+
content: [{
|
|
602
|
+
type: 'text',
|
|
603
|
+
text: JSON.stringify({ error: `Unknown tool: ${name}` })
|
|
604
|
+
}],
|
|
605
|
+
isError: true
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
try {
|
|
611
|
+
const result = handlers[name](args || {});
|
|
612
|
+
return {
|
|
613
|
+
jsonrpc: '2.0',
|
|
614
|
+
id,
|
|
615
|
+
result: {
|
|
616
|
+
content: [{
|
|
617
|
+
type: 'text',
|
|
618
|
+
text: JSON.stringify(result, null, 2)
|
|
619
|
+
}]
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
} catch (error) {
|
|
623
|
+
return {
|
|
624
|
+
jsonrpc: '2.0',
|
|
625
|
+
id,
|
|
626
|
+
result: {
|
|
627
|
+
content: [{
|
|
628
|
+
type: 'text',
|
|
629
|
+
text: JSON.stringify({ error: error.message })
|
|
630
|
+
}],
|
|
631
|
+
isError: true
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Ping
|
|
638
|
+
if (method === 'ping') {
|
|
639
|
+
return {
|
|
640
|
+
jsonrpc: '2.0',
|
|
641
|
+
id,
|
|
642
|
+
result: {}
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return {
|
|
647
|
+
jsonrpc: '2.0',
|
|
648
|
+
id,
|
|
649
|
+
error: {
|
|
650
|
+
code: -32601,
|
|
651
|
+
message: `Method not found: ${method}`
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// ============================================================
|
|
657
|
+
// Main - stdio transport
|
|
658
|
+
// ============================================================
|
|
659
|
+
|
|
660
|
+
let buffer = '';
|
|
661
|
+
|
|
662
|
+
process.stdin.setEncoding('utf-8');
|
|
663
|
+
process.stdin.on('data', (chunk) => {
|
|
664
|
+
buffer += chunk;
|
|
665
|
+
|
|
666
|
+
// Process complete messages
|
|
667
|
+
while (true) {
|
|
668
|
+
const newlineIndex = buffer.indexOf('\n');
|
|
669
|
+
if (newlineIndex === -1) break;
|
|
670
|
+
|
|
671
|
+
const line = buffer.substring(0, newlineIndex).trim();
|
|
672
|
+
buffer = buffer.substring(newlineIndex + 1);
|
|
673
|
+
|
|
674
|
+
if (!line) continue;
|
|
675
|
+
|
|
676
|
+
try {
|
|
677
|
+
const message = JSON.parse(line);
|
|
678
|
+
const response = handleMessage(message);
|
|
679
|
+
process.stdout.write(JSON.stringify(response) + '\n');
|
|
680
|
+
} catch (e) {
|
|
681
|
+
// Ignore parse errors
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
process.stderr.write('VCK MCP Server started on stdio\n');
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
{"id":"evt_1782678823750_hviim082n","timestamp":"2026-06-28T20:33:43.750Z","type":"phase_transition","data":{"from":"init","to":"plan","reason":"Starting feature planning"},"checksum":"3776bbcddf185329"}
|
|
2
|
+
{"id":"evt_1782678823755_dzqwd4kek","timestamp":"2026-06-28T20:33:43.755Z","type":"task_started","phase":"init","data":{"task":"Add user authentication"},"checksum":"34ba543afd423c7c"}
|
|
3
|
+
{"id":"evt_1782678823758_l74v7crfy","timestamp":"2026-06-28T20:33:43.758Z","type":"blocker","data":{"id":"blocker_1782678823757","description":"Need API key from user","severity":"high","resolved":false,"createdAt":"2026-06-28T20:33:43.757Z"},"checksum":"867c4d9c17a6aea8"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibe-coder-kit",
|
|
3
|
-
"version": "6.
|
|
4
|
-
"description": "Production-ready AI agent workflow template with TypeScript enforcement",
|
|
3
|
+
"version": "6.1.0",
|
|
4
|
+
"description": "Production-ready AI agent workflow template with TypeScript enforcement and MCP server",
|
|
5
5
|
"main": "dist/.vibe/core/index.js",
|
|
6
6
|
"types": "dist/.vibe/core/index.d.ts",
|
|
7
7
|
"bin": {
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"bin/",
|
|
13
13
|
".vibe/",
|
|
14
|
+
".cursorrules",
|
|
15
|
+
".github/copilot-instructions.md",
|
|
14
16
|
"AGENTS.md",
|
|
15
17
|
"README.md"
|
|
16
18
|
],
|
|
@@ -18,11 +20,11 @@
|
|
|
18
20
|
"build": "tsc",
|
|
19
21
|
"dev": "ts-node .vibe/core/cli.ts",
|
|
20
22
|
"start": "node dist/.vibe/core/cli.js",
|
|
23
|
+
"mcp": "node .vibe/mcp/server.js",
|
|
21
24
|
"test": "vitest run",
|
|
22
25
|
"test:watch": "vitest",
|
|
23
26
|
"lint": "eslint .vibe/core/**/*.ts",
|
|
24
|
-
"typecheck": "tsc --noEmit"
|
|
25
|
-
"postinstall": "node bin/vibe.js postinstall"
|
|
27
|
+
"typecheck": "tsc --noEmit"
|
|
26
28
|
},
|
|
27
29
|
"dependencies": {
|
|
28
30
|
"yaml": "^2.4.0"
|