@vibescope/mcp-server 0.0.1 → 0.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/README.md +113 -98
- package/dist/api-client.d.ts +1114 -0
- package/dist/api-client.js +698 -0
- package/dist/cli.d.ts +1 -6
- package/dist/cli.js +39 -240
- package/dist/config/tool-categories.d.ts +31 -0
- package/dist/config/tool-categories.js +253 -0
- package/dist/handlers/blockers.js +57 -58
- package/dist/handlers/bodies-of-work.d.ts +2 -0
- package/dist/handlers/bodies-of-work.js +106 -476
- package/dist/handlers/cost.d.ts +1 -0
- package/dist/handlers/cost.js +35 -113
- package/dist/handlers/decisions.d.ts +2 -0
- package/dist/handlers/decisions.js +28 -27
- package/dist/handlers/deployment.js +112 -828
- package/dist/handlers/discovery.js +31 -0
- package/dist/handlers/fallback.d.ts +2 -0
- package/dist/handlers/fallback.js +39 -134
- package/dist/handlers/findings.js +43 -67
- package/dist/handlers/git-issues.d.ts +9 -13
- package/dist/handlers/git-issues.js +80 -225
- package/dist/handlers/ideas.d.ts +3 -0
- package/dist/handlers/ideas.js +53 -134
- package/dist/handlers/index.d.ts +2 -0
- package/dist/handlers/index.js +6 -0
- package/dist/handlers/milestones.d.ts +2 -0
- package/dist/handlers/milestones.js +51 -98
- package/dist/handlers/organizations.js +79 -275
- package/dist/handlers/progress.d.ts +2 -0
- package/dist/handlers/progress.js +25 -123
- package/dist/handlers/project.js +42 -221
- package/dist/handlers/requests.d.ts +2 -0
- package/dist/handlers/requests.js +23 -83
- package/dist/handlers/session.js +99 -585
- package/dist/handlers/sprints.d.ts +32 -0
- package/dist/handlers/sprints.js +274 -0
- package/dist/handlers/tasks.d.ts +7 -10
- package/dist/handlers/tasks.js +230 -900
- package/dist/handlers/tool-docs.d.ts +8 -0
- package/dist/handlers/tool-docs.js +657 -0
- package/dist/handlers/types.d.ts +11 -3
- package/dist/handlers/validation.d.ts +1 -1
- package/dist/handlers/validation.js +26 -153
- package/dist/index.js +473 -160
- package/dist/knowledge.js +106 -9
- package/dist/tools.js +4 -0
- package/dist/validators.d.ts +21 -0
- package/dist/validators.js +91 -0
- package/package.json +2 -3
- package/src/api-client.ts +1752 -0
- package/src/cli.test.ts +128 -302
- package/src/cli.ts +41 -285
- package/src/handlers/__test-setup__.ts +210 -0
- package/src/handlers/__test-utils__.ts +4 -134
- package/src/handlers/blockers.test.ts +114 -124
- package/src/handlers/blockers.ts +68 -70
- package/src/handlers/bodies-of-work.test.ts +236 -831
- package/src/handlers/bodies-of-work.ts +194 -525
- package/src/handlers/cost.test.ts +149 -113
- package/src/handlers/cost.ts +44 -132
- package/src/handlers/decisions.test.ts +111 -209
- package/src/handlers/decisions.ts +35 -27
- package/src/handlers/deployment.test.ts +193 -239
- package/src/handlers/deployment.ts +140 -895
- package/src/handlers/discovery.test.ts +20 -67
- package/src/handlers/discovery.ts +32 -0
- package/src/handlers/fallback.test.ts +128 -361
- package/src/handlers/fallback.ts +62 -148
- package/src/handlers/findings.test.ts +127 -345
- package/src/handlers/findings.ts +49 -66
- package/src/handlers/git-issues.test.ts +623 -0
- package/src/handlers/git-issues.ts +174 -0
- package/src/handlers/ideas.test.ts +229 -343
- package/src/handlers/ideas.ts +69 -143
- package/src/handlers/index.ts +6 -0
- package/src/handlers/milestones.test.ts +167 -281
- package/src/handlers/milestones.ts +54 -93
- package/src/handlers/organizations.test.ts +275 -467
- package/src/handlers/organizations.ts +84 -294
- package/src/handlers/progress.test.ts +112 -218
- package/src/handlers/progress.ts +29 -142
- package/src/handlers/project.test.ts +203 -226
- package/src/handlers/project.ts +48 -238
- package/src/handlers/requests.test.ts +74 -342
- package/src/handlers/requests.ts +25 -83
- package/src/handlers/session.test.ts +241 -206
- package/src/handlers/session.ts +110 -657
- package/src/handlers/sprints.test.ts +711 -0
- package/src/handlers/sprints.ts +497 -0
- package/src/handlers/tasks.test.ts +608 -353
- package/src/handlers/tasks.ts +248 -1025
- package/src/handlers/types.ts +12 -4
- package/src/handlers/validation.test.ts +189 -572
- package/src/handlers/validation.ts +29 -166
- package/src/index.ts +473 -184
- package/src/knowledge.ts +107 -9
- package/src/tools.ts +2506 -0
- package/src/validators.test.ts +223 -223
- package/src/validators.ts +127 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +14 -13
- package/dist/cli.test.d.ts +0 -1
- package/dist/cli.test.js +0 -367
- package/dist/handlers/__test-utils__.d.ts +0 -72
- package/dist/handlers/__test-utils__.js +0 -176
- package/dist/handlers/checkouts.d.ts +0 -37
- package/dist/handlers/checkouts.js +0 -377
- package/dist/handlers/knowledge-query.d.ts +0 -22
- package/dist/handlers/knowledge-query.js +0 -253
- package/dist/handlers/knowledge.d.ts +0 -12
- package/dist/handlers/knowledge.js +0 -108
- package/dist/handlers/roles.d.ts +0 -30
- package/dist/handlers/roles.js +0 -281
- package/dist/handlers/tasks.test.d.ts +0 -1
- package/dist/handlers/tasks.test.js +0 -431
- package/dist/utils.test.d.ts +0 -1
- package/dist/utils.test.js +0 -532
- package/dist/validators.test.d.ts +0 -1
- package/dist/validators.test.js +0 -176
- package/src/tmpclaude-0078-cwd +0 -1
- package/src/tmpclaude-0ee1-cwd +0 -1
- package/src/tmpclaude-2dd5-cwd +0 -1
- package/src/tmpclaude-344c-cwd +0 -1
- package/src/tmpclaude-3860-cwd +0 -1
- package/src/tmpclaude-4b63-cwd +0 -1
- package/src/tmpclaude-5c73-cwd +0 -1
- package/src/tmpclaude-5ee3-cwd +0 -1
- package/src/tmpclaude-6795-cwd +0 -1
- package/src/tmpclaude-709e-cwd +0 -1
- package/src/tmpclaude-9839-cwd +0 -1
- package/src/tmpclaude-d829-cwd +0 -1
- package/src/tmpclaude-e072-cwd +0 -1
- package/src/tmpclaude-f6ee-cwd +0 -1
- package/tmpclaude-0439-cwd +0 -1
- package/tmpclaude-132f-cwd +0 -1
- package/tmpclaude-15bb-cwd +0 -1
- package/tmpclaude-165a-cwd +0 -1
- package/tmpclaude-1ba9-cwd +0 -1
- package/tmpclaude-21a3-cwd +0 -1
- package/tmpclaude-2a38-cwd +0 -1
- package/tmpclaude-2adf-cwd +0 -1
- package/tmpclaude-2f56-cwd +0 -1
- package/tmpclaude-3626-cwd +0 -1
- package/tmpclaude-3727-cwd +0 -1
- package/tmpclaude-40bc-cwd +0 -1
- package/tmpclaude-436f-cwd +0 -1
- package/tmpclaude-4783-cwd +0 -1
- package/tmpclaude-4b6d-cwd +0 -1
- package/tmpclaude-4ba4-cwd +0 -1
- package/tmpclaude-51e6-cwd +0 -1
- package/tmpclaude-5ecf-cwd +0 -1
- package/tmpclaude-6f97-cwd +0 -1
- package/tmpclaude-7fb2-cwd +0 -1
- package/tmpclaude-825c-cwd +0 -1
- package/tmpclaude-8baf-cwd +0 -1
- package/tmpclaude-8d9f-cwd +0 -1
- package/tmpclaude-975c-cwd +0 -1
- package/tmpclaude-9983-cwd +0 -1
- package/tmpclaude-a045-cwd +0 -1
- package/tmpclaude-ac4a-cwd +0 -1
- package/tmpclaude-b593-cwd +0 -1
- package/tmpclaude-b891-cwd +0 -1
- package/tmpclaude-c032-cwd +0 -1
- package/tmpclaude-cf43-cwd +0 -1
- package/tmpclaude-d040-cwd +0 -1
- package/tmpclaude-dcdd-cwd +0 -1
- package/tmpclaude-dcee-cwd +0 -1
- package/tmpclaude-e16b-cwd +0 -1
- package/tmpclaude-ecd2-cwd +0 -1
- package/tmpclaude-f48d-cwd +0 -1
package/dist/cli.d.ts
CHANGED
|
@@ -8,10 +8,6 @@
|
|
|
8
8
|
* 1 = Non-compliant (block exit, loop back)
|
|
9
9
|
* 2 = Error (allow exit with warning)
|
|
10
10
|
*/
|
|
11
|
-
export interface AuthContext {
|
|
12
|
-
userId: string;
|
|
13
|
-
apiKeyId: string;
|
|
14
|
-
}
|
|
15
11
|
export interface VerificationResult {
|
|
16
12
|
status: 'compliant' | 'non_compliant' | 'no_session' | 'error';
|
|
17
13
|
reason: string;
|
|
@@ -28,7 +24,6 @@ export interface VerificationResult {
|
|
|
28
24
|
session_duration_minutes: number | null;
|
|
29
25
|
};
|
|
30
26
|
}
|
|
27
|
+
export declare function normalizeGitUrl(url: string): string;
|
|
31
28
|
export declare function detectGitUrl(): string | null;
|
|
32
|
-
export declare function hashApiKey(key: string): string;
|
|
33
|
-
export declare function validateApiKey(supabase: any, apiKey: string): Promise<AuthContext | null>;
|
|
34
29
|
export declare function verify(gitUrl?: string, projectId?: string): Promise<VerificationResult>;
|
package/dist/cli.js
CHANGED
|
@@ -8,19 +8,30 @@
|
|
|
8
8
|
* 1 = Non-compliant (block exit, loop back)
|
|
9
9
|
* 2 = Error (allow exit with warning)
|
|
10
10
|
*/
|
|
11
|
-
import { createClient } from '@supabase/supabase-js';
|
|
12
|
-
import { createHash } from 'crypto';
|
|
13
11
|
import { execSync } from 'child_process';
|
|
14
|
-
import { normalizeGitUrl } from './utils.js';
|
|
15
12
|
// ============================================================================
|
|
16
|
-
// Configuration
|
|
13
|
+
// Configuration (read at runtime for testability)
|
|
17
14
|
// ============================================================================
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
function getApiKey() {
|
|
16
|
+
return process.env.VIBESCOPE_API_KEY;
|
|
17
|
+
}
|
|
18
|
+
function getApiUrl() {
|
|
19
|
+
return process.env.VIBESCOPE_API_URL || 'https://vibescope.dev';
|
|
20
|
+
}
|
|
21
21
|
// ============================================================================
|
|
22
22
|
// Git URL Detection
|
|
23
23
|
// ============================================================================
|
|
24
|
+
export function normalizeGitUrl(url) {
|
|
25
|
+
// Remove .git suffix
|
|
26
|
+
let normalized = url.replace(/\.git$/, '');
|
|
27
|
+
// Convert SSH to HTTPS format
|
|
28
|
+
if (normalized.startsWith('git@')) {
|
|
29
|
+
normalized = normalized
|
|
30
|
+
.replace(/^git@/, 'https://')
|
|
31
|
+
.replace(/:([^/])/, '/$1');
|
|
32
|
+
}
|
|
33
|
+
return normalized;
|
|
34
|
+
}
|
|
24
35
|
export function detectGitUrl() {
|
|
25
36
|
try {
|
|
26
37
|
const url = execSync('git config --get remote.origin.url', {
|
|
@@ -28,7 +39,6 @@ export function detectGitUrl() {
|
|
|
28
39
|
timeout: 5000,
|
|
29
40
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
30
41
|
}).trim();
|
|
31
|
-
// Normalize: remove .git suffix, convert SSH to HTTPS format
|
|
32
42
|
return normalizeGitUrl(url);
|
|
33
43
|
}
|
|
34
44
|
catch {
|
|
@@ -36,252 +46,42 @@ export function detectGitUrl() {
|
|
|
36
46
|
}
|
|
37
47
|
}
|
|
38
48
|
// ============================================================================
|
|
39
|
-
// Authentication (reused from index.ts)
|
|
40
|
-
// ============================================================================
|
|
41
|
-
export function hashApiKey(key) {
|
|
42
|
-
return createHash('sha256').update(key).digest('hex');
|
|
43
|
-
}
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
-
export async function validateApiKey(supabase, apiKey) {
|
|
46
|
-
const keyHash = hashApiKey(apiKey);
|
|
47
|
-
const { data, error } = await supabase
|
|
48
|
-
.from('api_keys')
|
|
49
|
-
.select('id, user_id')
|
|
50
|
-
.eq('key_hash', keyHash)
|
|
51
|
-
.single();
|
|
52
|
-
if (error || !data) {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
// Cast to expected shape since we're using untyped client
|
|
56
|
-
const row = data;
|
|
57
|
-
return {
|
|
58
|
-
userId: row.user_id,
|
|
59
|
-
apiKeyId: row.id,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
// ============================================================================
|
|
63
49
|
// Verification Logic
|
|
64
50
|
// ============================================================================
|
|
65
51
|
export async function verify(gitUrl, projectId) {
|
|
66
|
-
// Check environment
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
status: 'error',
|
|
70
|
-
reason: 'Missing SUPABASE_URL or SUPABASE_SERVICE_KEY environment variables',
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
if (!API_KEY) {
|
|
52
|
+
// Check environment (read at runtime for testability)
|
|
53
|
+
const apiKey = getApiKey();
|
|
54
|
+
if (!apiKey) {
|
|
74
55
|
return {
|
|
75
56
|
status: 'error',
|
|
76
57
|
reason: 'VIBESCOPE_API_KEY environment variable not set',
|
|
77
58
|
};
|
|
78
59
|
}
|
|
79
|
-
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY);
|
|
80
|
-
// Validate API key
|
|
81
|
-
const auth = await validateApiKey(supabase, API_KEY);
|
|
82
|
-
if (!auth) {
|
|
83
|
-
return {
|
|
84
|
-
status: 'error',
|
|
85
|
-
reason: 'Invalid VIBESCOPE_API_KEY',
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
60
|
// Auto-detect git URL if not provided
|
|
89
61
|
if (!gitUrl && !projectId) {
|
|
90
62
|
gitUrl = detectGitUrl() || undefined;
|
|
91
63
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (projectId) {
|
|
98
|
-
projectQuery = projectQuery.eq('id', projectId);
|
|
99
|
-
}
|
|
100
|
-
else if (gitUrl) {
|
|
101
|
-
projectQuery = projectQuery.eq('git_url', gitUrl);
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
return {
|
|
105
|
-
status: 'no_session',
|
|
106
|
-
reason: 'Could not detect git URL and no project_id provided',
|
|
107
|
-
continuation_prompt: 'Could not detect which project you are working on. Please call start_work_session(git_url: "...") with your repository URL.',
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
const { data: project, error: projectError } = await projectQuery.single();
|
|
111
|
-
if (projectError || !project) {
|
|
112
|
-
// Project not found - this is OK, might be an untracked repo
|
|
113
|
-
return {
|
|
114
|
-
status: 'compliant',
|
|
115
|
-
reason: `No Vibescope project found for ${gitUrl || projectId}. Untracked repository - exit allowed.`,
|
|
116
|
-
details: {
|
|
117
|
-
session_started: false,
|
|
118
|
-
project_id: null,
|
|
119
|
-
project_name: null,
|
|
120
|
-
git_url: gitUrl || null,
|
|
121
|
-
in_progress_tasks: 0,
|
|
122
|
-
tasks_completed_this_session: 0,
|
|
123
|
-
progress_logs_this_session: 0,
|
|
124
|
-
blockers_logged_this_session: 0,
|
|
125
|
-
session_duration_minutes: null,
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
// Check for agent session
|
|
130
|
-
const { data: session } = await supabase
|
|
131
|
-
.from('agent_sessions')
|
|
132
|
-
.select('id, last_synced_at, created_at')
|
|
133
|
-
.eq('api_key_id', auth.apiKeyId)
|
|
134
|
-
.eq('project_id', project.id)
|
|
135
|
-
.single();
|
|
136
|
-
if (!session) {
|
|
137
|
-
return {
|
|
138
|
-
status: 'non_compliant',
|
|
139
|
-
reason: 'No Vibescope session started for this project',
|
|
140
|
-
continuation_prompt: `[VIBESCOPE ENFORCEMENT] You have not started a Vibescope work session.
|
|
141
|
-
|
|
142
|
-
BEFORE you can exit, you MUST call:
|
|
143
|
-
start_work_session(git_url: "${project.git_url || project.id}")
|
|
144
|
-
|
|
145
|
-
This registers your session and gives you project context.`,
|
|
146
|
-
details: {
|
|
147
|
-
session_started: false,
|
|
148
|
-
project_id: project.id,
|
|
149
|
-
project_name: project.name,
|
|
150
|
-
git_url: project.git_url,
|
|
151
|
-
in_progress_tasks: 0,
|
|
152
|
-
tasks_completed_this_session: 0,
|
|
153
|
-
progress_logs_this_session: 0,
|
|
154
|
-
blockers_logged_this_session: 0,
|
|
155
|
-
session_duration_minutes: null,
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
const sessionStartTime = new Date(session.created_at);
|
|
160
|
-
const lastSyncTime = new Date(session.last_synced_at);
|
|
161
|
-
const now = new Date();
|
|
162
|
-
const sessionDurationMinutes = Math.round((now.getTime() - sessionStartTime.getTime()) / 60000);
|
|
163
|
-
// Grace period: if session is less than 1 minute, allow exit
|
|
164
|
-
if (sessionDurationMinutes < 1) {
|
|
165
|
-
return {
|
|
166
|
-
status: 'compliant',
|
|
167
|
-
reason: 'Very short session (< 1 minute) - exit allowed',
|
|
168
|
-
details: {
|
|
169
|
-
session_started: true,
|
|
170
|
-
project_id: project.id,
|
|
171
|
-
project_name: project.name,
|
|
172
|
-
git_url: project.git_url,
|
|
173
|
-
in_progress_tasks: 0,
|
|
174
|
-
tasks_completed_this_session: 0,
|
|
175
|
-
progress_logs_this_session: 0,
|
|
176
|
-
blockers_logged_this_session: 0,
|
|
177
|
-
session_duration_minutes: sessionDurationMinutes,
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
// Check for in-progress tasks
|
|
182
|
-
const { data: inProgressTasks } = await supabase
|
|
183
|
-
.from('tasks')
|
|
184
|
-
.select('id, title, progress_percentage')
|
|
185
|
-
.eq('project_id', project.id)
|
|
186
|
-
.eq('status', 'in_progress');
|
|
187
|
-
const inProgressCount = inProgressTasks?.length || 0;
|
|
188
|
-
if (inProgressCount > 0) {
|
|
189
|
-
const taskList = inProgressTasks
|
|
190
|
-
.map((t) => ` - ${t.title} (${t.progress_percentage}% complete)`)
|
|
191
|
-
.join('\n');
|
|
192
|
-
return {
|
|
193
|
-
status: 'non_compliant',
|
|
194
|
-
reason: `You have ${inProgressCount} task(s) still in_progress`,
|
|
195
|
-
continuation_prompt: `[VIBESCOPE ENFORCEMENT] You have ${inProgressCount} task(s) still marked as in_progress:
|
|
196
|
-
|
|
197
|
-
${taskList}
|
|
198
|
-
|
|
199
|
-
You MUST either:
|
|
200
|
-
1. Complete them: complete_task(task_id: "...", summary: "...")
|
|
201
|
-
2. Log why you're stopping: log_progress(project_id: "${project.id}", summary: "Stopping because...")`,
|
|
202
|
-
details: {
|
|
203
|
-
session_started: true,
|
|
204
|
-
project_id: project.id,
|
|
205
|
-
project_name: project.name,
|
|
206
|
-
git_url: project.git_url,
|
|
207
|
-
in_progress_tasks: inProgressCount,
|
|
208
|
-
tasks_completed_this_session: 0,
|
|
209
|
-
progress_logs_this_session: 0,
|
|
210
|
-
blockers_logged_this_session: 0,
|
|
211
|
-
session_duration_minutes: sessionDurationMinutes,
|
|
64
|
+
try {
|
|
65
|
+
const response = await fetch(`${getApiUrl()}/api/mcp/verify`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'Content-Type': 'application/json',
|
|
212
69
|
},
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
.eq('status', 'completed')
|
|
224
|
-
.gte('completed_at', sessionStartIso),
|
|
225
|
-
// Progress logs by agent after session start
|
|
226
|
-
supabase
|
|
227
|
-
.from('progress_logs')
|
|
228
|
-
.select('id', { count: 'exact' })
|
|
229
|
-
.eq('project_id', project.id)
|
|
230
|
-
.eq('created_by', 'agent')
|
|
231
|
-
.gte('created_at', sessionStartIso),
|
|
232
|
-
// Blockers logged by agent after session start
|
|
233
|
-
supabase
|
|
234
|
-
.from('blockers')
|
|
235
|
-
.select('id', { count: 'exact' })
|
|
236
|
-
.eq('project_id', project.id)
|
|
237
|
-
.eq('created_by', 'agent')
|
|
238
|
-
.gte('created_at', sessionStartIso),
|
|
239
|
-
]);
|
|
240
|
-
const tasksCompleted = completedResult.count || 0;
|
|
241
|
-
const progressLogsCount = progressResult.count || 0;
|
|
242
|
-
const blockersLogged = blockerResult.count || 0;
|
|
243
|
-
// Check if any tracked work was done
|
|
244
|
-
const anyWorkTracked = tasksCompleted > 0 || progressLogsCount > 0 || blockersLogged > 0;
|
|
245
|
-
if (!anyWorkTracked && sessionDurationMinutes >= 5) {
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
api_key: apiKey,
|
|
72
|
+
git_url: gitUrl,
|
|
73
|
+
project_id: projectId,
|
|
74
|
+
}),
|
|
75
|
+
});
|
|
76
|
+
const result = await response.json();
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
246
80
|
return {
|
|
247
|
-
status: '
|
|
248
|
-
reason:
|
|
249
|
-
continuation_prompt: `[VIBESCOPE ENFORCEMENT] Your session has been active for ${sessionDurationMinutes} minutes but no work was tracked.
|
|
250
|
-
|
|
251
|
-
The human is watching the dashboard and will see an empty session.
|
|
252
|
-
|
|
253
|
-
You MUST either:
|
|
254
|
-
1. Pick a task and work on it: get_next_task(project_id: "${project.id}")
|
|
255
|
-
2. Log why you did nothing: log_progress(project_id: "${project.id}", summary: "No work done because...")`,
|
|
256
|
-
details: {
|
|
257
|
-
session_started: true,
|
|
258
|
-
project_id: project.id,
|
|
259
|
-
project_name: project.name,
|
|
260
|
-
git_url: project.git_url,
|
|
261
|
-
in_progress_tasks: 0,
|
|
262
|
-
tasks_completed_this_session: tasksCompleted,
|
|
263
|
-
progress_logs_this_session: progressLogsCount,
|
|
264
|
-
blockers_logged_this_session: blockersLogged,
|
|
265
|
-
session_duration_minutes: sessionDurationMinutes,
|
|
266
|
-
},
|
|
81
|
+
status: 'error',
|
|
82
|
+
reason: err instanceof Error ? err.message : 'Network error',
|
|
267
83
|
};
|
|
268
84
|
}
|
|
269
|
-
// All checks passed - compliant!
|
|
270
|
-
return {
|
|
271
|
-
status: 'compliant',
|
|
272
|
-
reason: 'All tracked work completed properly',
|
|
273
|
-
details: {
|
|
274
|
-
session_started: true,
|
|
275
|
-
project_id: project.id,
|
|
276
|
-
project_name: project.name,
|
|
277
|
-
git_url: project.git_url,
|
|
278
|
-
in_progress_tasks: 0,
|
|
279
|
-
tasks_completed_this_session: tasksCompleted,
|
|
280
|
-
progress_logs_this_session: progressLogsCount,
|
|
281
|
-
blockers_logged_this_session: blockersLogged,
|
|
282
|
-
session_duration_minutes: sessionDurationMinutes,
|
|
283
|
-
},
|
|
284
|
-
};
|
|
285
85
|
}
|
|
286
86
|
// ============================================================================
|
|
287
87
|
// CLI Entry Point
|
|
@@ -332,8 +132,7 @@ Exit Codes:
|
|
|
332
132
|
|
|
333
133
|
Environment Variables:
|
|
334
134
|
VIBESCOPE_API_KEY Required - Your Vibescope API key
|
|
335
|
-
|
|
336
|
-
SUPABASE_SERVICE_KEY Required - Supabase service role key
|
|
135
|
+
VIBESCOPE_API_URL Optional - API URL (default: https://vibescope.dev)
|
|
337
136
|
`);
|
|
338
137
|
process.exit(0);
|
|
339
138
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Categories Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines the categorization of MCP tools for discovery.
|
|
5
|
+
* Moved to separate config for lazy-loading optimization.
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolEntry {
|
|
8
|
+
name: string;
|
|
9
|
+
brief: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CategoryEntry {
|
|
12
|
+
description: string;
|
|
13
|
+
tools: ToolEntry[];
|
|
14
|
+
}
|
|
15
|
+
export declare const TOOL_CATEGORIES: Record<string, CategoryEntry>;
|
|
16
|
+
/**
|
|
17
|
+
* Get list of category names
|
|
18
|
+
*/
|
|
19
|
+
export declare function getCategoryNames(): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Get category summary (without full tool list)
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCategorySummary(): Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
tool_count: number;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Get tools in a specific category
|
|
30
|
+
*/
|
|
31
|
+
export declare function getCategoryTools(category: string): CategoryEntry | undefined;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Categories Configuration
|
|
3
|
+
*
|
|
4
|
+
* Defines the categorization of MCP tools for discovery.
|
|
5
|
+
* Moved to separate config for lazy-loading optimization.
|
|
6
|
+
*/
|
|
7
|
+
export const TOOL_CATEGORIES = {
|
|
8
|
+
session: {
|
|
9
|
+
description: 'Session lifecycle and monitoring',
|
|
10
|
+
tools: [
|
|
11
|
+
{ name: 'start_work_session', brief: 'Initialize session, get next task' },
|
|
12
|
+
{ name: 'get_help', brief: 'Get workflow guidance' },
|
|
13
|
+
{ name: 'get_token_usage', brief: 'View token stats' },
|
|
14
|
+
{ name: 'heartbeat', brief: 'Maintain active status' },
|
|
15
|
+
{ name: 'end_work_session', brief: 'End session, release tasks' },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
project: {
|
|
19
|
+
description: 'Project CRUD and configuration',
|
|
20
|
+
tools: [
|
|
21
|
+
{ name: 'get_project_context', brief: 'Full project info' },
|
|
22
|
+
{ name: 'get_git_workflow', brief: 'Git branching config' },
|
|
23
|
+
{ name: 'create_project', brief: 'Create new project' },
|
|
24
|
+
{ name: 'update_project', brief: 'Modify project settings' },
|
|
25
|
+
{ name: 'update_project_readme', brief: 'Sync README to dashboard' },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
tasks: {
|
|
29
|
+
description: 'Task management and tracking',
|
|
30
|
+
tools: [
|
|
31
|
+
{ name: 'get_tasks', brief: 'List project tasks' },
|
|
32
|
+
{ name: 'get_next_task', brief: 'Get highest priority task' },
|
|
33
|
+
{ name: 'add_task', brief: 'Create new task' },
|
|
34
|
+
{ name: 'update_task', brief: 'Update task status/progress' },
|
|
35
|
+
{ name: 'complete_task', brief: 'Mark task done' },
|
|
36
|
+
{ name: 'delete_task', brief: 'Remove a task' },
|
|
37
|
+
{ name: 'batch_update_tasks', brief: 'Update multiple tasks' },
|
|
38
|
+
{ name: 'batch_complete_tasks', brief: 'Complete multiple tasks' },
|
|
39
|
+
{ name: 'add_task_reference', brief: 'Add URL to task' },
|
|
40
|
+
{ name: 'remove_task_reference', brief: 'Remove URL from task' },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
milestones: {
|
|
44
|
+
description: 'Task breakdown into steps',
|
|
45
|
+
tools: [
|
|
46
|
+
{ name: 'add_milestone', brief: 'Add step to task' },
|
|
47
|
+
{ name: 'update_milestone', brief: 'Update milestone' },
|
|
48
|
+
{ name: 'complete_milestone', brief: 'Mark step done' },
|
|
49
|
+
{ name: 'delete_milestone', brief: 'Remove milestone' },
|
|
50
|
+
{ name: 'get_milestones', brief: 'List task milestones' },
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
progress: {
|
|
54
|
+
description: 'Progress logging and activity',
|
|
55
|
+
tools: [
|
|
56
|
+
{ name: 'log_progress', brief: 'Record progress update' },
|
|
57
|
+
{ name: 'get_activity_feed', brief: 'Combined activity feed' },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
blockers: {
|
|
61
|
+
description: 'Blocker management',
|
|
62
|
+
tools: [
|
|
63
|
+
{ name: 'add_blocker', brief: 'Record a blocker' },
|
|
64
|
+
{ name: 'resolve_blocker', brief: 'Mark resolved' },
|
|
65
|
+
{ name: 'get_blockers', brief: 'List blockers' },
|
|
66
|
+
{ name: 'delete_blocker', brief: 'Remove blocker' },
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
decisions: {
|
|
70
|
+
description: 'Architectural decisions',
|
|
71
|
+
tools: [
|
|
72
|
+
{ name: 'log_decision', brief: 'Record decision' },
|
|
73
|
+
{ name: 'get_decisions', brief: 'List decisions' },
|
|
74
|
+
{ name: 'delete_decision', brief: 'Remove decision' },
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
ideas: {
|
|
78
|
+
description: 'Feature ideas tracking',
|
|
79
|
+
tools: [
|
|
80
|
+
{ name: 'add_idea', brief: 'Record an idea' },
|
|
81
|
+
{ name: 'update_idea', brief: 'Update idea status' },
|
|
82
|
+
{ name: 'get_ideas', brief: 'List ideas' },
|
|
83
|
+
{ name: 'delete_idea', brief: 'Remove idea' },
|
|
84
|
+
{ name: 'convert_idea_to_task', brief: 'Convert idea to task' },
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
findings: {
|
|
88
|
+
description: 'Audit findings/knowledge base',
|
|
89
|
+
tools: [
|
|
90
|
+
{ name: 'add_finding', brief: 'Record audit finding' },
|
|
91
|
+
{ name: 'get_findings', brief: 'List findings' },
|
|
92
|
+
{ name: 'update_finding', brief: 'Update finding status' },
|
|
93
|
+
{ name: 'delete_finding', brief: 'Remove finding' },
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
validation: {
|
|
97
|
+
description: 'Cross-agent task validation',
|
|
98
|
+
tools: [
|
|
99
|
+
{ name: 'get_tasks_awaiting_validation', brief: 'Unvalidated tasks' },
|
|
100
|
+
{ name: 'claim_validation', brief: 'Claim task for review' },
|
|
101
|
+
{ name: 'validate_task', brief: 'Approve/reject task' },
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
deployment: {
|
|
105
|
+
description: 'Deployment coordination',
|
|
106
|
+
tools: [
|
|
107
|
+
{ name: 'request_deployment', brief: 'Request deploy' },
|
|
108
|
+
{ name: 'claim_deployment_validation', brief: 'Claim for validation' },
|
|
109
|
+
{ name: 'report_validation', brief: 'Report build/test results' },
|
|
110
|
+
{ name: 'check_deployment_status', brief: 'Get deploy status' },
|
|
111
|
+
{ name: 'start_deployment', brief: 'Begin deployment' },
|
|
112
|
+
{ name: 'complete_deployment', brief: 'Mark deploy done' },
|
|
113
|
+
{ name: 'cancel_deployment', brief: 'Cancel deployment' },
|
|
114
|
+
{ name: 'add_deployment_requirement', brief: 'Add pre-deploy step' },
|
|
115
|
+
{ name: 'complete_deployment_requirement', brief: 'Mark step done' },
|
|
116
|
+
{ name: 'get_deployment_requirements', brief: 'List pre-deploy steps' },
|
|
117
|
+
{ name: 'schedule_deployment', brief: 'Schedule future deployment' },
|
|
118
|
+
{ name: 'get_scheduled_deployments', brief: 'List scheduled deployments' },
|
|
119
|
+
{ name: 'update_scheduled_deployment', brief: 'Update schedule config' },
|
|
120
|
+
{ name: 'delete_scheduled_deployment', brief: 'Delete schedule' },
|
|
121
|
+
{ name: 'trigger_scheduled_deployment', brief: 'Manual trigger' },
|
|
122
|
+
{ name: 'check_due_deployments', brief: 'Check due schedules' },
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
fallback: {
|
|
126
|
+
description: 'Background activities when idle',
|
|
127
|
+
tools: [
|
|
128
|
+
{ name: 'start_fallback_activity', brief: 'Start background work' },
|
|
129
|
+
{ name: 'stop_fallback_activity', brief: 'Stop background work' },
|
|
130
|
+
{ name: 'get_activity_history', brief: 'Activity history' },
|
|
131
|
+
{ name: 'get_activity_schedules', brief: 'Activity schedules' },
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
bodies_of_work: {
|
|
135
|
+
description: 'Group tasks into bodies of work',
|
|
136
|
+
tools: [
|
|
137
|
+
{ name: 'create_body_of_work', brief: 'Create task group' },
|
|
138
|
+
{ name: 'update_body_of_work', brief: 'Update settings' },
|
|
139
|
+
{ name: 'get_body_of_work', brief: 'Get with tasks' },
|
|
140
|
+
{ name: 'get_bodies_of_work', brief: 'List bodies of work' },
|
|
141
|
+
{ name: 'delete_body_of_work', brief: 'Remove body of work' },
|
|
142
|
+
{ name: 'add_task_to_body_of_work', brief: 'Add task to group' },
|
|
143
|
+
{ name: 'remove_task_from_body_of_work', brief: 'Remove from group' },
|
|
144
|
+
{ name: 'activate_body_of_work', brief: 'Activate for work' },
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
requests: {
|
|
148
|
+
description: 'User request handling',
|
|
149
|
+
tools: [
|
|
150
|
+
{ name: 'get_pending_requests', brief: 'Unhandled requests' },
|
|
151
|
+
{ name: 'acknowledge_request', brief: 'Mark handled' },
|
|
152
|
+
{ name: 'answer_question', brief: 'Answer user question' },
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
organizations: {
|
|
156
|
+
description: 'Organization and team management',
|
|
157
|
+
tools: [
|
|
158
|
+
{ name: 'list_organizations', brief: 'List user orgs' },
|
|
159
|
+
{ name: 'create_organization', brief: 'Create new org' },
|
|
160
|
+
{ name: 'update_organization', brief: 'Update org settings' },
|
|
161
|
+
{ name: 'delete_organization', brief: 'Delete org' },
|
|
162
|
+
{ name: 'list_org_members', brief: 'List org members' },
|
|
163
|
+
{ name: 'invite_member', brief: 'Invite by email' },
|
|
164
|
+
{ name: 'update_member_role', brief: 'Change member role' },
|
|
165
|
+
{ name: 'remove_member', brief: 'Remove from org' },
|
|
166
|
+
{ name: 'leave_organization', brief: 'Leave an org' },
|
|
167
|
+
{ name: 'share_project_with_org', brief: 'Share project' },
|
|
168
|
+
{ name: 'update_project_share', brief: 'Update share perms' },
|
|
169
|
+
{ name: 'unshare_project', brief: 'Remove share' },
|
|
170
|
+
{ name: 'list_project_shares', brief: 'List project shares' },
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
cost: {
|
|
174
|
+
description: 'Cost monitoring and alerts',
|
|
175
|
+
tools: [
|
|
176
|
+
{ name: 'get_cost_summary', brief: 'Cost by period' },
|
|
177
|
+
{ name: 'get_cost_alerts', brief: 'List cost alerts' },
|
|
178
|
+
{ name: 'add_cost_alert', brief: 'Add threshold alert' },
|
|
179
|
+
{ name: 'update_cost_alert', brief: 'Update alert config' },
|
|
180
|
+
{ name: 'delete_cost_alert', brief: 'Remove alert' },
|
|
181
|
+
{ name: 'get_task_costs', brief: 'Cost per task' },
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
knowledge: {
|
|
185
|
+
description: 'Queryable knowledge base from project data',
|
|
186
|
+
tools: [
|
|
187
|
+
{ name: 'query_knowledge_base', brief: 'Aggregated project knowledge in one call' },
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
subtasks: {
|
|
191
|
+
description: 'Subtask management',
|
|
192
|
+
tools: [
|
|
193
|
+
{ name: 'add_subtask', brief: 'Add subtask to parent' },
|
|
194
|
+
{ name: 'get_subtasks', brief: 'List subtasks' },
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
sprints: {
|
|
198
|
+
description: 'Sprint planning and tracking',
|
|
199
|
+
tools: [
|
|
200
|
+
{ name: 'create_sprint', brief: 'Create new sprint' },
|
|
201
|
+
{ name: 'update_sprint', brief: 'Update sprint' },
|
|
202
|
+
{ name: 'get_sprint', brief: 'Get sprint details' },
|
|
203
|
+
{ name: 'get_sprints', brief: 'List sprints' },
|
|
204
|
+
{ name: 'delete_sprint', brief: 'Remove sprint' },
|
|
205
|
+
{ name: 'start_sprint', brief: 'Start sprint' },
|
|
206
|
+
{ name: 'complete_sprint', brief: 'End sprint' },
|
|
207
|
+
{ name: 'add_task_to_sprint', brief: 'Add task' },
|
|
208
|
+
{ name: 'remove_task_from_sprint', brief: 'Remove task' },
|
|
209
|
+
{ name: 'get_sprint_backlog', brief: 'Available tasks' },
|
|
210
|
+
{ name: 'get_sprint_velocity', brief: 'Velocity metrics' },
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
git_issues: {
|
|
214
|
+
description: 'Git issue tracking',
|
|
215
|
+
tools: [
|
|
216
|
+
{ name: 'add_git_issue', brief: 'Record git issue' },
|
|
217
|
+
{ name: 'resolve_git_issue', brief: 'Mark resolved' },
|
|
218
|
+
{ name: 'get_git_issues', brief: 'List git issues' },
|
|
219
|
+
{ name: 'delete_git_issue', brief: 'Remove issue' },
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
dependencies: {
|
|
223
|
+
description: 'Task dependencies',
|
|
224
|
+
tools: [
|
|
225
|
+
{ name: 'add_task_dependency', brief: 'Add dependency' },
|
|
226
|
+
{ name: 'remove_task_dependency', brief: 'Remove dependency' },
|
|
227
|
+
{ name: 'get_task_dependencies', brief: 'List dependencies' },
|
|
228
|
+
{ name: 'get_next_body_of_work_task', brief: 'Next available task' },
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* Get list of category names
|
|
234
|
+
*/
|
|
235
|
+
export function getCategoryNames() {
|
|
236
|
+
return Object.keys(TOOL_CATEGORIES);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get category summary (without full tool list)
|
|
240
|
+
*/
|
|
241
|
+
export function getCategorySummary() {
|
|
242
|
+
return Object.entries(TOOL_CATEGORIES).map(([name, cat]) => ({
|
|
243
|
+
name,
|
|
244
|
+
description: cat.description,
|
|
245
|
+
tool_count: cat.tools.length,
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get tools in a specific category
|
|
250
|
+
*/
|
|
251
|
+
export function getCategoryTools(category) {
|
|
252
|
+
return TOOL_CATEGORIES[category];
|
|
253
|
+
}
|