@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigstate/mcp",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "Rigstate MCP Server - Model Context Protocol for AI Editors",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -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 ownership
15
- const { data: project, error: projectError } = await supabase
16
- .from('projects')
17
- .select('id')
18
- .eq('id', input.projectId)
19
- .eq('owner_id', userId)
20
- .single();
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.array(z.string()).optional().describe('Filter by framework tags (e.g., ["nextjs", "react", "supabase"])'),
11
- min_trust_score: z.number().optional().describe('Minimum trust score (0-100)'),
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.array(z.string()).optional().describe('Relevant framework tags'),
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
+ }
@@ -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 interface RoadmapChunk {
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
+ }
@@ -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.0'; // Evolutionary Update
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