@rigstate/mcp 0.7.4 → 0.7.6
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/dist/index.js +285 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/arch-analysis.ts +171 -0
- package/src/lib/curator/actions/submit.ts +8 -9
- package/src/lib/curator/schemas.ts +10 -4
- package/src/lib/project-context-utils.ts +139 -0
- package/src/lib/schemas.ts +10 -10
- package/src/lib/types-roadmap.ts +43 -0
- package/src/lib/types.ts +41 -25
- package/src/server/types.ts +1 -1
- package/src/tools/analyze-database-performance.ts +12 -0
- package/src/tools/archaeological-scan.ts +37 -214
- package/src/tools/audit-integrity-gate.ts +16 -4
- package/src/tools/check-agent-bridge.ts +11 -0
- package/src/tools/check-rules-sync.ts +13 -0
- package/src/tools/complete-roadmap-task.ts +12 -0
- package/src/tools/generate-professional-pdf.ts +17 -2
- package/src/tools/get-next-roadmap-step.ts +5 -1
- package/src/tools/get-project-context.ts +17 -79
- package/src/tools/list-features.ts +13 -3
- package/src/tools/list-roadmap-tasks.ts +6 -1
- package/src/tools/pending-tasks.ts +22 -0
- package/src/tools/query-brain.ts +8 -9
- package/src/tools/research-tools.ts +9 -8
- package/src/tools/run-architecture-audit.ts +8 -9
- package/src/tools/save-decision.ts +15 -9
- package/src/tools/security-tools.ts +26 -2
- package/src/tools/submit-idea.ts +15 -9
- package/src/tools/sync-ide-rules.ts +16 -3
- package/src/tools/teacher-mode.ts +6 -7
- package/src/tools/update-roadmap.ts +14 -8
package/package.json
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { GitCommit, DiscoveredFeature } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse git log output into structured commits
|
|
5
|
+
*/
|
|
6
|
+
export function parseGitLog(logOutput: string): GitCommit[] {
|
|
7
|
+
const commits: GitCommit[] = [];
|
|
8
|
+
const entries = logOutput.split('\n---COMMIT---\n').filter(Boolean);
|
|
9
|
+
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
const lines = entry.trim().split('\n');
|
|
12
|
+
if (lines.length >= 3) {
|
|
13
|
+
commits.push({
|
|
14
|
+
hash: lines[0]?.replace('hash:', '').trim() || '',
|
|
15
|
+
date: lines[1]?.replace('date:', '').trim() || '',
|
|
16
|
+
author: lines[2]?.replace('author:', '').trim() || '',
|
|
17
|
+
message: lines.slice(3).join('\n').trim()
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return commits;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Analyze commits to identify major milestones
|
|
27
|
+
*/
|
|
28
|
+
export function identifyMilestones(commits: GitCommit[]): { date: string; summary: string; commits: string[] }[] {
|
|
29
|
+
const milestones: { date: string; summary: string; commits: string[] }[] = [];
|
|
30
|
+
|
|
31
|
+
// Keywords that indicate significant features
|
|
32
|
+
const featurePatterns = [
|
|
33
|
+
{ pattern: /\b(auth|authentication|login|signup|oauth)\b/i, category: 'Authentication System' },
|
|
34
|
+
{ pattern: /\b(database|schema|migration|supabase|postgres)\b/i, category: 'Database Setup' },
|
|
35
|
+
{ pattern: /\b(api|endpoint|route)\b/i, category: 'API Development' },
|
|
36
|
+
{ pattern: /\b(ui|component|layout|design|tailwind)\b/i, category: 'UI/Component Development' },
|
|
37
|
+
{ pattern: /\b(test|spec|jest|vitest)\b/i, category: 'Testing Infrastructure' },
|
|
38
|
+
{ pattern: /\b(deploy|ci|cd|github|vercel|docker)\b/i, category: 'DevOps & Deployment' },
|
|
39
|
+
{ pattern: /\b(feature|implement|add|create|build)\b/i, category: 'Feature Implementation' },
|
|
40
|
+
{ pattern: /\b(fix|bug|patch|resolve)\b/i, category: 'Bug Fixes & Patches' },
|
|
41
|
+
{ pattern: /\b(refactor|clean|optimize|improve)\b/i, category: 'Code Quality Improvements' },
|
|
42
|
+
{ pattern: /\b(docs|readme|documentation)\b/i, category: 'Documentation' },
|
|
43
|
+
{ pattern: /\b(config|setup|init|scaffold)\b/i, category: 'Project Configuration' },
|
|
44
|
+
{ pattern: /\b(agent|mcp|ai|llm|openai)\b/i, category: 'AI/Agent Integration' },
|
|
45
|
+
{ pattern: /\b(roadmap|milestone|chunk)\b/i, category: 'Roadmap System' },
|
|
46
|
+
{ pattern: /\b(report|pdf|manifest|governance)\b/i, category: 'Reporting & Governance' },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// Group commits by category
|
|
50
|
+
const categoryMap = new Map<string, { commits: GitCommit[]; latestDate: string }>();
|
|
51
|
+
|
|
52
|
+
for (const commit of commits) {
|
|
53
|
+
for (const { pattern, category } of featurePatterns) {
|
|
54
|
+
if (pattern.test(commit.message)) {
|
|
55
|
+
if (!categoryMap.has(category)) {
|
|
56
|
+
categoryMap.set(category, { commits: [], latestDate: commit.date });
|
|
57
|
+
}
|
|
58
|
+
const entry = categoryMap.get(category)!;
|
|
59
|
+
entry.commits.push(commit);
|
|
60
|
+
if (new Date(commit.date) > new Date(entry.latestDate)) {
|
|
61
|
+
entry.latestDate = commit.date;
|
|
62
|
+
}
|
|
63
|
+
break; // Only categorize each commit once
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Convert to milestones (only include categories with 2+ commits)
|
|
69
|
+
for (const [category, data] of categoryMap.entries()) {
|
|
70
|
+
if (data.commits.length >= 2) {
|
|
71
|
+
milestones.push({
|
|
72
|
+
date: data.latestDate,
|
|
73
|
+
summary: `${category} (${data.commits.length} commits)`,
|
|
74
|
+
commits: data.commits.slice(0, 5).map(c => c.message.split('\n')[0].substring(0, 80))
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Sort by date descending
|
|
80
|
+
milestones.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
81
|
+
|
|
82
|
+
return milestones;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Map directory structure to potential features
|
|
87
|
+
*/
|
|
88
|
+
export function analyzeFilesystem(tree: string[]): { featureDirectories: string[]; configFiles: string[] } {
|
|
89
|
+
const featurePatterns = [
|
|
90
|
+
/^(apps|packages)\/[^/]+\/src\/(components|features|modules)\/[^/]+$/,
|
|
91
|
+
/^(apps|packages)\/[^/]+\/src\/app\/[^/]+$/,
|
|
92
|
+
/^src\/(components|features|modules|pages)\/[^/]+$/,
|
|
93
|
+
/^(apps|packages)\/[^/]+$/,
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
const configPatterns = [
|
|
97
|
+
/package\.json$/,
|
|
98
|
+
/tsconfig.*\.json$/,
|
|
99
|
+
/\.env.*$/,
|
|
100
|
+
/next\.config\./,
|
|
101
|
+
/tailwind\.config\./,
|
|
102
|
+
/supabase.*\.toml$/,
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
const featureDirectories = tree.filter(path =>
|
|
106
|
+
featurePatterns.some(pattern => pattern.test(path))
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const configFiles = tree.filter(path =>
|
|
110
|
+
configPatterns.some(pattern => pattern.test(path))
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
featureDirectories: [...new Set(featureDirectories)].slice(0, 20),
|
|
115
|
+
configFiles: [...new Set(configFiles)].slice(0, 10)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generate discovered features from milestones and filesystem
|
|
121
|
+
*/
|
|
122
|
+
export function generateDiscoveredFeatures(
|
|
123
|
+
milestones: { date: string; summary: string; commits: string[] }[],
|
|
124
|
+
filesystemAnalysis: { featureDirectories: string[]; configFiles: string[] }
|
|
125
|
+
): DiscoveredFeature[] {
|
|
126
|
+
const features: DiscoveredFeature[] = [];
|
|
127
|
+
let priority = 1;
|
|
128
|
+
|
|
129
|
+
// From Git milestones
|
|
130
|
+
for (const milestone of milestones.slice(0, 10)) {
|
|
131
|
+
const id = `ghost-${Date.now()}-${priority}`;
|
|
132
|
+
features.push({
|
|
133
|
+
id,
|
|
134
|
+
title: milestone.summary.split('(')[0].trim(),
|
|
135
|
+
description: `Reconstructed from ${milestone.commits.length} commits. Last activity: ${new Date(milestone.date).toLocaleDateString()}`,
|
|
136
|
+
status: 'COMPLETED',
|
|
137
|
+
source: 'git',
|
|
138
|
+
evidence: milestone.commits,
|
|
139
|
+
estimatedCompletionDate: milestone.date,
|
|
140
|
+
priority: priority++
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// From filesystem (major directories as features)
|
|
145
|
+
const directoryFeatures = filesystemAnalysis.featureDirectories
|
|
146
|
+
.filter(dir => dir.includes('src/') || dir.startsWith('apps/') || dir.startsWith('packages/'))
|
|
147
|
+
.slice(0, 5);
|
|
148
|
+
|
|
149
|
+
for (const dir of directoryFeatures) {
|
|
150
|
+
const name = dir.split('/').pop() || dir;
|
|
151
|
+
const id = `ghost-fs-${Date.now()}-${priority}`;
|
|
152
|
+
|
|
153
|
+
// Skip if we already have a similar feature from git
|
|
154
|
+
if (features.some(f => f.title.toLowerCase().includes(name.toLowerCase()))) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
features.push({
|
|
159
|
+
id,
|
|
160
|
+
title: `${name.charAt(0).toUpperCase() + name.slice(1)} Module`,
|
|
161
|
+
description: `Detected from directory structure: ${dir}`,
|
|
162
|
+
status: 'COMPLETED',
|
|
163
|
+
source: 'filesystem',
|
|
164
|
+
evidence: [dir],
|
|
165
|
+
estimatedCompletionDate: new Date().toISOString(),
|
|
166
|
+
priority: priority++
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return features;
|
|
171
|
+
}
|
|
@@ -11,15 +11,14 @@ export async function submitSignal(
|
|
|
11
11
|
userId: string,
|
|
12
12
|
input: z.infer<typeof SubmitSignalSchema>
|
|
13
13
|
) {
|
|
14
|
-
// 1. Verify project
|
|
15
|
-
const { data:
|
|
16
|
-
.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (projectError || !project) {
|
|
14
|
+
// 1. Verify project access
|
|
15
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
16
|
+
.rpc('check_project_access_secure', {
|
|
17
|
+
p_project_id: input.projectId,
|
|
18
|
+
p_user_id: userId
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (accessError || !hasAccess) {
|
|
23
22
|
throw new Error('Project not found or access denied');
|
|
24
23
|
}
|
|
25
24
|
|
|
@@ -7,10 +7,13 @@ import { z } from 'zod';
|
|
|
7
7
|
export const QueryGlobalAntidotesSchema = z.object({
|
|
8
8
|
categories: z.array(z.string()).optional().describe('Filter by categories (SECURITY, ARCHITECTURE, UX, PERFORMANCE, ACCESSIBILITY, MAINTAINABILITY)'),
|
|
9
9
|
severities: z.array(z.string()).optional().describe('Filter by severity (CRITICAL, HIGH, MEDIUM, LOW)'),
|
|
10
|
-
framework_tags: z.
|
|
11
|
-
|
|
10
|
+
framework_tags: z.preprocess(
|
|
11
|
+
(val) => (typeof val === 'string' ? JSON.parse(val) : val),
|
|
12
|
+
z.array(z.string())
|
|
13
|
+
).optional().describe('Filter by framework tags (e.g., ["nextjs", "react", "supabase"])'),
|
|
14
|
+
min_trust_score: z.coerce.number().optional().describe('Minimum trust score (0-100)'),
|
|
12
15
|
search_text: z.string().optional().describe('Search in title and instruction'),
|
|
13
|
-
limit: z.number().optional().describe('Max results (default: 20)')
|
|
16
|
+
limit: z.coerce.number().optional().describe('Max results (default: 20)')
|
|
14
17
|
});
|
|
15
18
|
|
|
16
19
|
export const SubmitSignalSchema = z.object({
|
|
@@ -21,7 +24,10 @@ export const SubmitSignalSchema = z.object({
|
|
|
21
24
|
severity: z.enum(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']).describe('Severity level'),
|
|
22
25
|
example: z.string().optional().describe('Good example demonstrating the instruction'),
|
|
23
26
|
anti_example: z.string().optional().describe('Bad example showing what NOT to do'),
|
|
24
|
-
framework_tags: z.
|
|
27
|
+
framework_tags: z.preprocess(
|
|
28
|
+
(val) => (typeof val === 'string' ? [val] : val),
|
|
29
|
+
z.array(z.string())
|
|
30
|
+
).optional().describe('Relevant framework tags'),
|
|
25
31
|
reasoning: z.string().optional().describe('Why this signal should be added'),
|
|
26
32
|
source_type: z.string().optional().describe('Internal source type override (e.g. TEACHER_MODE)')
|
|
27
33
|
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { ProjectContextResponse, TechStackInfo } from '../lib/types.js';
|
|
2
|
+
|
|
3
|
+
export async function buildProjectSummary(
|
|
4
|
+
project: any,
|
|
5
|
+
techStack: TechStackInfo,
|
|
6
|
+
activeTask: any,
|
|
7
|
+
nextTask: any,
|
|
8
|
+
agentTasks: any[],
|
|
9
|
+
roadmapItems: any[],
|
|
10
|
+
stackDef: any,
|
|
11
|
+
supabase: any
|
|
12
|
+
): Promise<string> {
|
|
13
|
+
const summaryParts: string[] = [];
|
|
14
|
+
|
|
15
|
+
summaryParts.push(`Project Type: ${project.project_type?.toUpperCase() || 'UNKNOWN'}`);
|
|
16
|
+
|
|
17
|
+
// Active Mission Parameters
|
|
18
|
+
if (stackDef) {
|
|
19
|
+
summaryParts.push('\n=== ACTIVE MISSION PARAMETERS ===');
|
|
20
|
+
if (activeTask) {
|
|
21
|
+
summaryParts.push(`⚠️ CURRENT OBJECTIVE: T-${activeTask.step_number}: ${activeTask.title}`);
|
|
22
|
+
summaryParts.push(` Role: ${activeTask.role || 'Developer'}`);
|
|
23
|
+
|
|
24
|
+
const detailedInstructions = activeTask.prompt_content || activeTask.instruction_set;
|
|
25
|
+
if (detailedInstructions) {
|
|
26
|
+
summaryParts.push(` Instructions: ${detailedInstructions.substring(0, 1000)}...`);
|
|
27
|
+
}
|
|
28
|
+
if (activeTask.architectural_brief) {
|
|
29
|
+
summaryParts.push(`\n Architectural Brief: ${activeTask.architectural_brief}`);
|
|
30
|
+
}
|
|
31
|
+
if (activeTask.context_summary) {
|
|
32
|
+
summaryParts.push(`\n Context: ${activeTask.context_summary}`);
|
|
33
|
+
}
|
|
34
|
+
if (activeTask.checklist && activeTask.checklist.length > 0) {
|
|
35
|
+
summaryParts.push('\n Checklist (DoD):');
|
|
36
|
+
activeTask.checklist.forEach((item: any) => {
|
|
37
|
+
summaryParts.push(` [ ] ${typeof item === 'string' ? item : item.task}`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (activeTask.metadata && Object.keys(activeTask.metadata).length > 0) {
|
|
41
|
+
summaryParts.push(`\n Technical Metadata: ${JSON.stringify(activeTask.metadata)}`);
|
|
42
|
+
}
|
|
43
|
+
if (activeTask.tags && activeTask.tags.length > 0) {
|
|
44
|
+
summaryParts.push(` Tags: ${activeTask.tags.join(', ')}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Enhanced Feature Context
|
|
48
|
+
if (activeTask.feature_id) {
|
|
49
|
+
const { data: feature } = await supabase
|
|
50
|
+
.from('project_features')
|
|
51
|
+
.select('name, description')
|
|
52
|
+
.eq('id', activeTask.feature_id)
|
|
53
|
+
.single();
|
|
54
|
+
|
|
55
|
+
if (feature) {
|
|
56
|
+
summaryParts.push(`\n Parent Feature: ${feature.name}`);
|
|
57
|
+
summaryParts.push(` Feature Vision: ${feature.description}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
summaryParts.push('\n ACTION: Focus ALL coding efforts on completing this task.');
|
|
62
|
+
} else if (nextTask) {
|
|
63
|
+
summaryParts.push(`⏸ SYSTEM IDLE (Waiting for command)`);
|
|
64
|
+
summaryParts.push(` Suggested Next Mission: T-${nextTask.step_number}: ${nextTask.title}`);
|
|
65
|
+
if (nextTask.tags && nextTask.tags.length > 0) {
|
|
66
|
+
summaryParts.push(` Scope: ${nextTask.tags.join(', ')}`);
|
|
67
|
+
}
|
|
68
|
+
summaryParts.push(` ACTION: Ask the user "Shall we start T-${nextTask.step_number}?"`);
|
|
69
|
+
} else {
|
|
70
|
+
summaryParts.push('✅ ALL MISSIONS COMPLETE. Awaiting new roadmap items.');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
summaryParts.push('\n=== AI BEHAVIORAL INSTRUCTIONS ===');
|
|
74
|
+
if (activeTask) {
|
|
75
|
+
summaryParts.push(`1. FOCUS: The user is working on T-${activeTask.step_number}. Help them complete it.`);
|
|
76
|
+
summaryParts.push(`2. COMPLIANCE: Ensure all code follows project standards.`);
|
|
77
|
+
} else if (nextTask) {
|
|
78
|
+
summaryParts.push(`1. NUDGE: No active task found. Suggest starting T-${nextTask.step_number} (${nextTask.title}).`);
|
|
79
|
+
summaryParts.push(`2. PROACTIVE: Instead of asking "How can I help?", ask "Shall we start on T-${nextTask.step_number}?"`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
summaryParts.push('\n=== CURRENT STACK ===');
|
|
83
|
+
if (stackDef.frontend) summaryParts.push(`Frontend: ${stackDef.frontend.framework} (${stackDef.frontend.language})`);
|
|
84
|
+
if (stackDef.backend) summaryParts.push(`Backend: ${stackDef.backend.service} (${stackDef.backend.database})`);
|
|
85
|
+
if (stackDef.styling) summaryParts.push(`Styling: ${stackDef.styling.framework} ${stackDef.styling.library || ''}`);
|
|
86
|
+
if (stackDef.hosting) summaryParts.push(`Infrastructure: ${stackDef.hosting.provider}`);
|
|
87
|
+
} else {
|
|
88
|
+
if (techStack.framework) summaryParts.push(`Framework: ${techStack.framework}`);
|
|
89
|
+
if (techStack.orm) summaryParts.push(`ORM: ${techStack.orm}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (project.description) {
|
|
93
|
+
summaryParts.push(`\nDescription: ${project.description}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (project.functional_spec) {
|
|
97
|
+
summaryParts.push('\n=== STRATEGIC PROJECT SPECIFICATION (NUANCES) ===');
|
|
98
|
+
const spec = typeof project.functional_spec === 'string' ? JSON.parse(project.functional_spec) : project.functional_spec;
|
|
99
|
+
|
|
100
|
+
if (spec.projectDescription) summaryParts.push(`Vision: ${spec.projectDescription}`);
|
|
101
|
+
if (spec.targetAudience) summaryParts.push(`Audience: ${spec.targetAudience}`);
|
|
102
|
+
if (spec.coreProblem) summaryParts.push(`Core Problem: ${spec.coreProblem}`);
|
|
103
|
+
|
|
104
|
+
if (spec.featureList && Array.isArray(spec.featureList)) {
|
|
105
|
+
summaryParts.push('\nKey Features & Nuances:');
|
|
106
|
+
spec.featureList.filter((f: any) => f.priority === 'MVP').forEach((f: any) => {
|
|
107
|
+
summaryParts.push(`- ${f.name}: ${f.description}`);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
summaryParts.push('\n=== RIGSTATE TOOLING GUIDELINES ===');
|
|
113
|
+
summaryParts.push('You have access to specialized MCP tools. USE THEM TO SUCCEED:');
|
|
114
|
+
summaryParts.push('1. NEVER guess about architecture. Use `query_brain` to search project documentation.');
|
|
115
|
+
summaryParts.push('2. BEFORE coding, check `get_learned_instructions` to see if you have been corrected before.');
|
|
116
|
+
summaryParts.push('3. When finishing a task, ALWAYS update the roadmap using `update_roadmap`.');
|
|
117
|
+
summaryParts.push('4. If you discover a reusable pattern, submit it with `submit_curator_signal`.');
|
|
118
|
+
summaryParts.push('5. For large refactors, use `run_architecture_audit` to check against rules.');
|
|
119
|
+
summaryParts.push('6. Store major decisions using `save_decision` (ADR).');
|
|
120
|
+
|
|
121
|
+
summaryParts.push('\n=== RECENT ACTIVITY DIGEST ===');
|
|
122
|
+
|
|
123
|
+
if (agentTasks && agentTasks.length > 0) {
|
|
124
|
+
summaryParts.push('\nLatest AI Executions:');
|
|
125
|
+
agentTasks.forEach((t: any) => {
|
|
126
|
+
const time = t.completed_at ? new Date(t.completed_at).toLocaleString() : 'Recently';
|
|
127
|
+
summaryParts.push(`- [${time}] ${t.roadmap_title || 'Task'}: ${t.execution_summary || 'Completed'}`);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (roadmapItems && roadmapItems.length > 0) {
|
|
132
|
+
summaryParts.push('\nRoadmap Updates:');
|
|
133
|
+
roadmapItems.forEach((i: any) => {
|
|
134
|
+
summaryParts.push(`- ${i.title} is now ${i.status}`);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return summaryParts.join('\n') || 'No project context available.';
|
|
139
|
+
}
|
package/src/lib/schemas.ts
CHANGED
|
@@ -7,8 +7,8 @@ import { z } from 'zod';
|
|
|
7
7
|
export const QueryBrainInputSchema = z.object({
|
|
8
8
|
projectId: z.string().uuid('Invalid project ID'),
|
|
9
9
|
query: z.string().min(1, 'Query is required'),
|
|
10
|
-
limit: z.number().min(1).max(20).optional().default(8),
|
|
11
|
-
threshold: z.number().min(0).max(1).optional().default(0.1)
|
|
10
|
+
limit: z.coerce.number().min(1).max(20).optional().default(8),
|
|
11
|
+
threshold: z.coerce.number().min(0).max(1).optional().default(0.1)
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
export const GetProjectContextInputSchema = z.object({
|
|
@@ -17,7 +17,7 @@ export const GetProjectContextInputSchema = z.object({
|
|
|
17
17
|
|
|
18
18
|
export const GetLatestDecisionsInputSchema = z.object({
|
|
19
19
|
projectId: z.string().uuid('Invalid project ID'),
|
|
20
|
-
limit: z.number().min(1).max(10).optional().default(5)
|
|
20
|
+
limit: z.coerce.number().min(1).max(10).optional().default(5)
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
export const SaveDecisionInputSchema = z.object({
|
|
@@ -26,7 +26,7 @@ export const SaveDecisionInputSchema = z.object({
|
|
|
26
26
|
decision: z.string().min(1, 'Decision content is required'),
|
|
27
27
|
rationale: z.string().optional(),
|
|
28
28
|
category: z.enum(['decision', 'architecture', 'constraint', 'tech_stack', 'design_rule']).optional().default('decision'),
|
|
29
|
-
tags: z.array(z.string()).optional().default([])
|
|
29
|
+
tags: z.preprocess((val) => (typeof val === 'string' ? [val] : val), z.array(z.string())).optional().default([])
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
export const SubmitIdeaInputSchema = z.object({
|
|
@@ -34,7 +34,7 @@ export const SubmitIdeaInputSchema = z.object({
|
|
|
34
34
|
title: z.string().min(1, 'Title is required').max(200, 'Title too long'),
|
|
35
35
|
description: z.string().min(1, 'Description is required'),
|
|
36
36
|
category: z.enum(['feature', 'improvement', 'experiment', 'pivot']).optional().default('feature'),
|
|
37
|
-
tags: z.array(z.string()).optional().default([])
|
|
37
|
+
tags: z.preprocess((val) => (typeof val === 'string' ? [val] : val), z.array(z.string())).optional().default([])
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
export const UpdateRoadmapInputSchema = z.object({
|
|
@@ -104,7 +104,7 @@ export const GenerateProfessionalPDFInputSchema = z.object({
|
|
|
104
104
|
export const ArchaeologicalScanInputSchema = z.object({
|
|
105
105
|
projectId: z.string().uuid('Invalid project ID'),
|
|
106
106
|
gitLog: z.string().describe('Git log output'),
|
|
107
|
-
fileTree: z.array(z.string()).describe('File paths')
|
|
107
|
+
fileTree: z.preprocess((val) => (typeof val === 'string' ? [val] : val), z.array(z.string())).describe('File paths')
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
export const ImportGhostFeaturesInputSchema = z.object({
|
|
@@ -124,7 +124,7 @@ export const AuditSecurityIntegrityInputSchema = z.object({
|
|
|
124
124
|
projectId: z.string().uuid(),
|
|
125
125
|
filePath: z.string().min(1),
|
|
126
126
|
content: z.string().min(1),
|
|
127
|
-
rules: z.array(z.string()).optional()
|
|
127
|
+
rules: z.preprocess((val) => (typeof val === 'string' ? [val] : val), z.array(z.string())).optional()
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
export const QueryProjectBrainInputSchema = QueryBrainInputSchema;
|
|
@@ -138,7 +138,7 @@ export const SaveToProjectBrainInputSchema = z.object({
|
|
|
138
138
|
title: z.string().min(1),
|
|
139
139
|
content: z.string().min(1),
|
|
140
140
|
category: z.enum(['DECISION', 'ARCHITECTURE', 'NOTE', 'LESSON_LEARNED']).default('NOTE'),
|
|
141
|
-
tags: z.array(z.string()).optional().default([])
|
|
141
|
+
tags: z.preprocess((val) => (typeof val === 'string' ? [val] : val), z.array(z.string())).optional().default([])
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
export const UpdateRoadmapStatusInputSchema = z.object({
|
|
@@ -174,12 +174,12 @@ export const GenerateCursorRulesInputSchema = z.object({
|
|
|
174
174
|
|
|
175
175
|
export const AnalyzeDatabasePerformanceInputSchema = z.object({
|
|
176
176
|
projectId: z.string().uuid(),
|
|
177
|
-
filePaths: z.array(z.string())
|
|
177
|
+
filePaths: z.preprocess((val) => (typeof val === 'string' ? [val] : val), z.array(z.string()))
|
|
178
178
|
});
|
|
179
179
|
|
|
180
180
|
export const AuditIntegrityGateInputSchema = z.object({
|
|
181
181
|
projectId: z.string().uuid(),
|
|
182
|
-
filePaths: z.array(z.string()).optional().default([])
|
|
182
|
+
filePaths: z.preprocess((val) => (typeof val === 'string' ? [val] : val), z.array(z.string())).optional().default([])
|
|
183
183
|
});
|
|
184
184
|
|
|
185
185
|
export const CompleteRoadmapTaskInputSchema = z.object({
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface RoadmapChunk {
|
|
2
|
+
id: string;
|
|
3
|
+
project_id: string;
|
|
4
|
+
feature_id: string | null;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string | null;
|
|
7
|
+
status: string;
|
|
8
|
+
priority: string | null;
|
|
9
|
+
step_number: number;
|
|
10
|
+
prompt_content: string | null;
|
|
11
|
+
architectural_brief?: string | null;
|
|
12
|
+
context_summary?: string | null;
|
|
13
|
+
checklist?: any[] | null;
|
|
14
|
+
metadata?: any | null;
|
|
15
|
+
tags?: string[] | null;
|
|
16
|
+
created_at: string;
|
|
17
|
+
completed_at: string | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ListRoadmapTasksResponse {
|
|
21
|
+
tasks: Array<{
|
|
22
|
+
id: string;
|
|
23
|
+
title: string;
|
|
24
|
+
priority: string | null;
|
|
25
|
+
status: string;
|
|
26
|
+
step_number: number;
|
|
27
|
+
prompt_content: string | null;
|
|
28
|
+
architectural_brief?: string | null;
|
|
29
|
+
context_summary?: string | null;
|
|
30
|
+
metadata?: any | null;
|
|
31
|
+
checklist?: any[] | null;
|
|
32
|
+
tags?: string[] | null;
|
|
33
|
+
}>;
|
|
34
|
+
formatted: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface RoadmapStep {
|
|
38
|
+
id: string;
|
|
39
|
+
stepNumber: number;
|
|
40
|
+
title: string;
|
|
41
|
+
status: string;
|
|
42
|
+
sprintFocus: string | null;
|
|
43
|
+
}
|
package/src/lib/types.ts
CHANGED
|
@@ -176,31 +176,7 @@ export interface SecurityIntegrityResponse {
|
|
|
176
176
|
// ROADMAP & TASK TYPES
|
|
177
177
|
// =============================================================================
|
|
178
178
|
|
|
179
|
-
export
|
|
180
|
-
id: string;
|
|
181
|
-
project_id: string;
|
|
182
|
-
feature_id: string | null;
|
|
183
|
-
title: string;
|
|
184
|
-
description: string | null;
|
|
185
|
-
status: string;
|
|
186
|
-
priority: string | null;
|
|
187
|
-
step_number: number;
|
|
188
|
-
prompt_content: string | null;
|
|
189
|
-
created_at: string;
|
|
190
|
-
completed_at: string | null;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export interface ListRoadmapTasksResponse {
|
|
194
|
-
tasks: Array<{
|
|
195
|
-
id: string;
|
|
196
|
-
title: string;
|
|
197
|
-
priority: string | null;
|
|
198
|
-
status: string;
|
|
199
|
-
step_number: number;
|
|
200
|
-
prompt_content: string | null;
|
|
201
|
-
}>;
|
|
202
|
-
formatted: string;
|
|
203
|
-
}
|
|
179
|
+
export * from './types-roadmap.js';
|
|
204
180
|
|
|
205
181
|
// =============================================================================
|
|
206
182
|
// AGENT BRIDGE & RULES TYPES
|
|
@@ -254,3 +230,43 @@ export interface ReleaseManifest {
|
|
|
254
230
|
};
|
|
255
231
|
timestamp: string;
|
|
256
232
|
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
// =============================================================================
|
|
236
|
+
// ARCHAEOLOGICAL SCAN TYPES
|
|
237
|
+
// =============================================================================
|
|
238
|
+
|
|
239
|
+
export interface GitCommit {
|
|
240
|
+
hash: string;
|
|
241
|
+
message: string;
|
|
242
|
+
date: string;
|
|
243
|
+
author: string;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export interface DiscoveredFeature {
|
|
247
|
+
id: string;
|
|
248
|
+
title: string;
|
|
249
|
+
description: string;
|
|
250
|
+
status: 'COMPLETED';
|
|
251
|
+
source: 'git' | 'filesystem' | 'combined';
|
|
252
|
+
evidence: string[];
|
|
253
|
+
estimatedCompletionDate: string;
|
|
254
|
+
priority: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export interface ArchaeologicalReport {
|
|
258
|
+
projectId: string;
|
|
259
|
+
scanDate: string;
|
|
260
|
+
gitAnalysis: {
|
|
261
|
+
totalCommits: number;
|
|
262
|
+
analyzedCommits: number;
|
|
263
|
+
milestones: { date: string; summary: string; commits: string[] }[];
|
|
264
|
+
};
|
|
265
|
+
filesystemAnalysis: {
|
|
266
|
+
totalDirectories: number;
|
|
267
|
+
featureDirectories: string[];
|
|
268
|
+
configFiles: string[];
|
|
269
|
+
};
|
|
270
|
+
discoveredFeatures: DiscoveredFeature[];
|
|
271
|
+
recommendations: string[];
|
|
272
|
+
}
|
package/src/server/types.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface McpServerConfig {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export const SERVER_NAME = 'rigstate-mcp';
|
|
16
|
-
export const SERVER_VERSION = '0.5
|
|
16
|
+
export const SERVER_VERSION = '0.7.5';
|
|
17
17
|
|
|
18
18
|
export interface AuthContext {
|
|
19
19
|
supabase: SupabaseClient;
|
|
@@ -26,8 +26,20 @@ interface TableMetadata {
|
|
|
26
26
|
|
|
27
27
|
export async function analyzeDatabasePerformance(
|
|
28
28
|
supabase: SupabaseClient,
|
|
29
|
+
userId: string,
|
|
29
30
|
input: AnalyzeDatabasePerformanceInput
|
|
30
31
|
): Promise<{ issues: PerformanceIssue[], summary: string }> {
|
|
32
|
+
// 0. Verify project access
|
|
33
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
34
|
+
.rpc('check_project_access_secure', {
|
|
35
|
+
p_project_id: input.projectId,
|
|
36
|
+
p_user_id: userId
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (accessError || !hasAccess) {
|
|
40
|
+
throw new Error('Project not found or access denied');
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
const issues: PerformanceIssue[] = [];
|
|
32
44
|
|
|
33
45
|
// 1. Fetch Database Metadata
|