@rigstate/mcp 0.4.2 → 0.4.3

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.
Files changed (57) hide show
  1. package/.agent/skills/client-side-notification-logger/SKILL.md +139 -0
  2. package/.agent/skills/react-state-counter/SKILL.md +73 -0
  3. package/.agent/skills/rigstate-evolutionary-refactor/SKILL.md +40 -0
  4. package/.agent/skills/rigstate-integrity-gate/SKILL.md +55 -0
  5. package/.agent/skills/rigstate-legacy-renovator/SKILL.md +12 -0
  6. package/.agent/skills/sec-auth-04/SKILL.md +22 -0
  7. package/.agent/skills/sec-key-01/SKILL.md +21 -0
  8. package/.agent/skills/sec-rls-01/SKILL.md +22 -0
  9. package/.agent/skills/sec-sql-01/SKILL.md +23 -0
  10. package/.agent/skills/sec-ui-01/SKILL.md +21 -0
  11. package/.cursor/rules/rigstate-database.mdc +89 -0
  12. package/.cursor/rules/rigstate-guardian.mdc +43 -0
  13. package/.cursor/rules/rigstate-identity.mdc +45 -0
  14. package/.cursor/rules/rigstate-roadmap.mdc +9 -0
  15. package/.cursor/rules/rigstate-workflow.mdc +323 -0
  16. package/.cursorrules +402 -0
  17. package/AGENTS.md +34 -0
  18. package/dist/index.js +2604 -3067
  19. package/dist/index.js.map +1 -1
  20. package/package.json +2 -2
  21. package/roadmap.json +815 -21
  22. package/src/index.ts +16 -1765
  23. package/src/lib/context-engine.ts +85 -0
  24. package/src/lib/curator/actions/fortress.ts +77 -0
  25. package/src/lib/curator/actions/query.ts +73 -0
  26. package/src/lib/curator/actions/stats.ts +70 -0
  27. package/src/lib/curator/actions/submit.ts +190 -0
  28. package/src/lib/curator/index.ts +10 -0
  29. package/src/lib/curator/schemas.ts +37 -0
  30. package/src/lib/schemas.ts +191 -0
  31. package/src/lib/types.ts +102 -261
  32. package/src/server/core.ts +40 -0
  33. package/src/server/factory.ts +78 -0
  34. package/src/server/telemetry.ts +122 -0
  35. package/src/server/types.ts +21 -0
  36. package/src/tools/analyze-database-performance.ts +157 -0
  37. package/src/tools/arch-tools.ts +16 -0
  38. package/src/tools/audit-integrity-gate.ts +166 -0
  39. package/src/tools/check-rules-sync.ts +20 -0
  40. package/src/tools/complete-roadmap-task.ts +88 -31
  41. package/src/tools/curator-tools.ts +74 -0
  42. package/src/tools/get-latest-decisions.ts +22 -0
  43. package/src/tools/get-next-roadmap-step.ts +21 -0
  44. package/src/tools/get-project-context.ts +35 -1
  45. package/src/tools/index.ts +7 -0
  46. package/src/tools/list-features.ts +4 -1
  47. package/src/tools/list-roadmap-tasks.ts +21 -0
  48. package/src/tools/planning-tools.ts +40 -0
  49. package/src/tools/query-brain.ts +25 -1
  50. package/src/tools/run-architecture-audit.ts +23 -0
  51. package/src/tools/save-decision.ts +26 -0
  52. package/src/tools/security-checks.ts +241 -0
  53. package/src/tools/security-tools.ts +88 -18
  54. package/src/tools/submit-idea.ts +25 -0
  55. package/src/tools/sync-ide-rules.ts +35 -3
  56. package/src/tools/teacher-mode.ts +92 -13
  57. package/src/tools/update-roadmap.ts +24 -0
@@ -1,4 +1,29 @@
1
+
1
2
  import { SupabaseClient } from '@supabase/supabase-js';
3
+ import { IntegrityGateResponse, ReleaseManifest } from '../lib/types.js';
4
+ import { registry } from '../lib/tool-registry.js';
5
+ import { CompleteRoadmapTaskInputSchema } from '../lib/schemas.js';
6
+
7
+ // ============================================
8
+ // Tool Registration
9
+ // ============================================
10
+
11
+ registry.register({
12
+ name: 'complete_roadmap_task',
13
+ description: `Finalizes a roadmap task. Generates a Release Manifest and triggers the Sovereign Harvesting protocol.`,
14
+ schema: CompleteRoadmapTaskInputSchema,
15
+ handler: async (args, context) => {
16
+ const result = await completeRoadmapTask(
17
+ context.supabase,
18
+ args.projectId,
19
+ args.summary,
20
+ args.taskId,
21
+ args.gitDiff,
22
+ args.integrityGate
23
+ );
24
+ return { content: [{ type: 'text', text: result.message }] };
25
+ }
26
+ });
2
27
 
3
28
  export interface CompleteRoadmapTaskResponse {
4
29
  success: boolean;
@@ -11,7 +36,8 @@ export async function completeRoadmapTask(
11
36
  projectId: string,
12
37
  summary: string,
13
38
  taskId?: string,
14
- gitDiff?: string
39
+ gitDiff?: string,
40
+ integrityGate?: IntegrityGateResponse
15
41
  ): Promise<CompleteRoadmapTaskResponse> {
16
42
 
17
43
  // 1. Identify the task
@@ -35,16 +61,36 @@ export async function completeRoadmapTask(
35
61
  }
36
62
  }
37
63
 
38
- // 2. Update the Task Status
64
+ // 2. Generate Release Manifest if Integrity Gate info is present
65
+ let metadata: any = {};
66
+ if (integrityGate) {
67
+ const securityCheck = integrityGate.checks.find(c => (c as any).check === 'SECURITY');
68
+ const performanceCheck = integrityGate.checks.find(c => (c as any).check === 'PERFORMANCE');
69
+
70
+ const manifest: ReleaseManifest = {
71
+ executive_summary: summary,
72
+ security_certificate: {
73
+ status: securityCheck?.status === 'PASS' ? 'PASSED' : (securityCheck?.status === 'FAIL' ? 'FAILED' : 'WARNING'),
74
+ message: securityCheck?.message || 'No security audit performed.',
75
+ unsecured_tables: securityCheck?.details || []
76
+ },
77
+ performance_report: {
78
+ status: performanceCheck?.status === 'PASS' ? 'PASSED' : (performanceCheck?.status === 'FAIL' ? 'FAILED' : 'WARNING'),
79
+ message: performanceCheck?.message || 'No performance audit performed.',
80
+ issues_found: performanceCheck?.details ? (Array.isArray(performanceCheck.details) ? performanceCheck.details.length : 0) : 0
81
+ },
82
+ timestamp: new Date().toISOString()
83
+ };
84
+
85
+ metadata.release_manifest = manifest;
86
+ }
87
+
88
+ // 3. Update the Task Status
39
89
  const { error: updateError } = await supabase
40
90
  .from('roadmap_chunks')
41
91
  .update({
42
92
  status: 'COMPLETED',
43
- completed_at: new Date().toISOString(),
44
- // We could store the summary directly on the chunk if there's a column,
45
- // but mission_reports is the proper place for detailed logs.
46
- // Let's check if we can update metadata or similar.
47
- // For now, let's assume mission_reports is the way.
93
+ completed_at: new Date().toISOString()
48
94
  })
49
95
  .eq('id', targetTaskId);
50
96
 
@@ -52,26 +98,7 @@ export async function completeRoadmapTask(
52
98
  throw new Error(`Failed to update task status: ${updateError.message}`);
53
99
  }
54
100
 
55
- // 3. Create a Mission Report entry
56
- // Check if 'mission_reports' table exists and has the schema we expect.
57
- // Based on previous code in index.ts (Frank Watcher):
58
- /*
59
- await supabase.from('mission_reports').insert({
60
- bridge_id: task.id, // We might not have a bridge_id if this is direct from IDE
61
- project_id: task.project_id,
62
- task_id: task.task_id,
63
- human_summary: humanSummary,
64
- technical_summary: technicalSummary,
65
- ...
66
- });
67
- */
68
-
69
- // We'll insert a report. Since we don't have a bridge_id (this didn't come from the agent bridge queue),
70
- // we'll leave it null if allowed, or we might need to create a dummy bridge entry?
71
- // Let's assume bridge_id is nullable or we just skip it.
72
- // If bridge_id is required, we might need to fake one or just log to a 'notes' field on roadmap_chunk if available.
73
- // Let's try to insert into mission_reports first.
74
-
101
+ // 4. Create a Mission Report entry with the Manifest
75
102
  const { error: reportError } = await supabase
76
103
  .from('mission_reports')
77
104
  .insert({
@@ -79,18 +106,48 @@ export async function completeRoadmapTask(
79
106
  task_id: targetTaskId,
80
107
  human_summary: summary,
81
108
  technical_summary: gitDiff || 'Completed via IDE Direct Connection.',
82
- // bridge_id: null // Assuming nullable
109
+ metadata: metadata
83
110
  });
84
111
 
85
112
  if (reportError) {
86
113
  console.warn('Failed to save mission report:', reportError.message);
87
- // Fallback: Add a comment/note to the chunk?
88
- // We'll just return a warning in the message.
114
+ }
115
+
116
+ // 5. SOVEREIGN HARVESTING: Trigger Reflection & Skill Extraction (Brynjar)
117
+ // Fire and forget - don't block completion on harvesting
118
+ try {
119
+ const apiKey = process.env.RIGSTATE_API_KEY;
120
+ // Default to localhost for development if not set
121
+ const apiUrl = process.env.RIGSTATE_API_URL || 'http://localhost:3000';
122
+
123
+ // In local dev, we might not have an API key set, so we allow it if it's localhost
124
+ const isLocal = apiUrl.includes('localhost') || apiUrl.includes('127.0.0.1');
125
+
126
+ if (apiKey || isLocal) {
127
+ fetch(`${apiUrl}/api/v1/skills/harvest`, {
128
+ method: 'POST',
129
+ headers: {
130
+ 'Content-Type': 'application/json',
131
+ ...(apiKey ? { 'Authorization': `Bearer ${apiKey}` } : {})
132
+ },
133
+ body: JSON.stringify({
134
+ projectId,
135
+ taskId: targetTaskId,
136
+ summary,
137
+ technicalSummary: gitDiff || 'Completed via IDE Direct Connection.',
138
+ metadata: metadata
139
+ })
140
+ }).catch(e => console.error('Harvesting failed (silent):', e));
141
+ }
142
+ } catch (e) {
143
+ // Harvesting is non-critical, fail silently
89
144
  }
90
145
 
91
146
  return {
92
147
  success: true,
93
148
  taskId: targetTaskId!,
94
- message: `Task completed successfully! Summary saved.`
149
+ message: integrityGate
150
+ ? `Task completed! 🎖️ Release Manifest generated and attached.`
151
+ : `Task completed successfully! Summary saved.`
95
152
  };
96
153
  }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Phase 8.5: The Curator Protocol
3
+ * MCP Tools for Curator Operations
4
+ *
5
+ * Sigrid's Tools for Global Knowledge Curation.
6
+ * These tools enable AI agents to contribute to and query the global antidote registry.
7
+ */
8
+
9
+ import { registry } from '../lib/tool-registry.js';
10
+ import {
11
+ queryGlobalAntidotes,
12
+ submitSignal,
13
+ getCuratorStats,
14
+ checkFortress,
15
+ QueryGlobalAntidotesSchema,
16
+ SubmitSignalSchema,
17
+ GetCuratorStatsSchema,
18
+ CheckFortressSchema
19
+ } from '../lib/curator/index.js';
20
+
21
+ // ============================================
22
+ // Tool Registration
23
+ // ============================================
24
+
25
+ registry.register({
26
+ name: 'query_global_antidotes',
27
+ description: `Sigrid's Tool: Query the Global Antidotes Registry.
28
+ Search for cross-platform intelligence signals (antidotes) that encode best practices.
29
+ Use this to find relevant security, architecture, UX, and performance guidelines.`,
30
+ schema: QueryGlobalAntidotesSchema,
31
+ handler: async (args, context) => {
32
+ const result = await queryGlobalAntidotes(context.supabase, context.userId, args);
33
+ return { content: [{ type: 'text', text: result.formatted }] };
34
+ }
35
+ });
36
+
37
+ registry.register({
38
+ name: 'submit_curator_signal',
39
+ description: `Sigrid's Tool: Submit a new signal to the Curator Protocol.
40
+ When you discover a best practice or anti-pattern during development, submit it as a signal.
41
+ Signals are processed through a trust-scoring pipeline and may be promoted to global antidotes.
42
+ Note: All submissions go through quarantine for human review.`,
43
+ schema: SubmitSignalSchema,
44
+ handler: async (args, context) => {
45
+ const result = await submitSignal(context.supabase, context.userId, args);
46
+ return { content: [{ type: 'text', text: result.message }] };
47
+ }
48
+ });
49
+
50
+ registry.register({
51
+ name: 'get_curator_stats',
52
+ description: `Get statistics about the Curator Registry.
53
+ Shows total antidotes, fortress rules, pending quarantine, and today's curation activity.`,
54
+ schema: GetCuratorStatsSchema,
55
+ handler: async (args, context) => {
56
+ const result = await getCuratorStats(context.supabase, context.userId, args);
57
+ return { content: [{ type: 'text', text: result.formatted }] };
58
+ }
59
+ });
60
+
61
+ registry.register({
62
+ name: 'check_fortress_rules',
63
+ description: `Sigrid's Tool: Check an instruction against Fortress Rules.
64
+ Before submitting a signal, use this to verify it doesn't conflict with immutable security rules.
65
+ Fortress rules can NEVER be overridden by any signal.`,
66
+ schema: CheckFortressSchema,
67
+ handler: async (args, context) => {
68
+ const result = await checkFortress(context.supabase, context.userId, args);
69
+ return { content: [{ type: 'text', text: result.message }] };
70
+ }
71
+ });
72
+
73
+ // Export functions for historical compatibility if any tests use them directly
74
+ export { queryGlobalAntidotes, submitSignal, getCuratorStats, checkFortress };
@@ -7,6 +7,28 @@
7
7
 
8
8
  import { SupabaseClient } from '@supabase/supabase-js';
9
9
  import type { DecisionsResponse, CouncilSession, RoadmapStep } from '../lib/types.js';
10
+ import { registry } from '../lib/tool-registry.js';
11
+ import { GetLatestDecisionsInputSchema } from '../lib/schemas.js';
12
+
13
+ // ============================================
14
+ // Tool Registration
15
+ // ============================================
16
+
17
+ registry.register({
18
+ name: 'get_latest_decisions',
19
+ description: `Fetches the most recent ADRs and decisions from The Council,
20
+ including active roadmap steps and council session feedback.`,
21
+ schema: GetLatestDecisionsInputSchema,
22
+ handler: async (args, context) => {
23
+ const result = await getLatestDecisions(
24
+ context.supabase,
25
+ context.userId,
26
+ args.projectId,
27
+ args.limit
28
+ );
29
+ return { content: [{ type: 'text', text: result.summary }] };
30
+ }
31
+ });
10
32
 
11
33
  export async function getLatestDecisions(
12
34
  supabase: SupabaseClient,
@@ -1,6 +1,27 @@
1
1
 
2
2
  import { SupabaseClient } from '@supabase/supabase-js';
3
3
  import type { RoadmapChunk } from '../lib/types.js';
4
+ import { registry } from '../lib/tool-registry.js';
5
+ import { GetNextRoadmapStepInputSchema } from '../lib/schemas.js';
6
+
7
+ // ============================================
8
+ // Tool Registration
9
+ // ============================================
10
+
11
+ registry.register({
12
+ name: 'get_next_roadmap_step',
13
+ description: `Fetches the next logical step from the roadmap for a project.
14
+ Useful for transitioning between tasks.`,
15
+ schema: GetNextRoadmapStepInputSchema,
16
+ handler: async (args, context) => {
17
+ const result = await getNextRoadmapStep(
18
+ context.supabase,
19
+ args.projectId,
20
+ args.currentStepId
21
+ );
22
+ return { content: [{ type: 'text', text: result.message }] };
23
+ }
24
+ });
4
25
 
5
26
  export interface GetNextRoadmapStepResponse {
6
27
  nextStep: RoadmapChunk | null;
@@ -7,6 +7,23 @@
7
7
 
8
8
  import { SupabaseClient } from '@supabase/supabase-js';
9
9
  import type { ProjectContextResponse, TechStackInfo } from '../lib/types.js';
10
+ import { injectGlobalContext } from '../lib/context-engine.js';
11
+ import { registry } from '../lib/tool-registry.js';
12
+ import { GetProjectContextInputSchema } from '../lib/schemas.js';
13
+
14
+ // ============================================
15
+ // Tool Registration
16
+ // ============================================
17
+
18
+ registry.register({
19
+ name: 'get_project_context',
20
+ description: `Returns the project type, tech stack, and high-level description for a Rigstate project.`,
21
+ schema: GetProjectContextInputSchema,
22
+ handler: async (args, context) => {
23
+ const result = await getProjectContext(context.supabase, context.userId, args.projectId);
24
+ return { content: [{ type: 'text', text: result.summary }] };
25
+ }
26
+ });
10
27
 
11
28
  // Key libraries we care about for display
12
29
  const KEY_LIBS: Record<string, string> = {
@@ -148,7 +165,7 @@ export async function getProjectContext(
148
165
  });
149
166
  }
150
167
 
151
- return {
168
+ const response: ProjectContextResponse = {
152
169
  project: {
153
170
  id: project.id,
154
171
  name: project.name,
@@ -160,4 +177,21 @@ export async function getProjectContext(
160
177
  techStack,
161
178
  summary: summaryParts.join('\n') || 'No project context available.'
162
179
  };
180
+
181
+ // Phase 8.5.5: Inject Global Context (Curator)
182
+ try {
183
+ const curatorContext = await injectGlobalContext(supabase, userId, {
184
+ frameworks: techStack.framework ? [techStack.framework] : [],
185
+ libraries: techStack.keyLibraries
186
+ });
187
+
188
+ if (curatorContext) {
189
+ response.summary += `\n\n=== CURATOR INTELLIGENCE ===${curatorContext}`;
190
+ }
191
+ } catch (e: any) {
192
+ console.error('Failed to inject global context:', e);
193
+ response.summary += `\n\n(Curator Context Unavailable: ${e.message})`;
194
+ }
195
+
196
+ return response;
163
197
  }
@@ -15,3 +15,10 @@ export { submitIdea } from './submit-idea.js';
15
15
  export { updateRoadmap } from './update-roadmap.js';
16
16
  export { runArchitectureAudit } from './run-architecture-audit.js';
17
17
 
18
+ // Curator Protocol (Phase 8.5 - Sigrid's Tools)
19
+ export {
20
+ queryGlobalAntidotes,
21
+ submitSignal,
22
+ getCuratorStats,
23
+ checkFortress
24
+ } from './curator-tools.js';
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { ToolDefinition } from '../lib/tool-registry.js';
2
+ import { ToolDefinition, registry } from '../lib/tool-registry.js';
3
3
 
4
4
  /**
5
5
  * Input Schema for List Features
@@ -65,3 +65,6 @@ Useful for understanding the strategic context and major milestones.`,
65
65
  }
66
66
  };
67
67
 
68
+ registry.register(listFeaturesTool);
69
+
70
+
@@ -6,6 +6,27 @@
6
6
 
7
7
  import { SupabaseClient } from '@supabase/supabase-js';
8
8
  import type { ListRoadmapTasksResponse } from '../lib/types.js';
9
+ import { registry } from '../lib/tool-registry.js';
10
+ import { ListRoadmapTasksInputSchema } from '../lib/schemas.js';
11
+
12
+ // ============================================
13
+ // Tool Registration
14
+ // ============================================
15
+
16
+ registry.register({
17
+ name: 'list_roadmap_tasks',
18
+ description: `Lists all actionable tasks for a project that are not yet COMPLETED.
19
+ Shows active and locked steps with their step numbers.`,
20
+ schema: ListRoadmapTasksInputSchema,
21
+ handler: async (args, context) => {
22
+ const result = await listRoadmapTasks(
23
+ context.supabase,
24
+ context.userId,
25
+ args.projectId
26
+ );
27
+ return { content: [{ type: 'text', text: result.formatted }] };
28
+ }
29
+ });
9
30
 
10
31
  export async function listRoadmapTasks(
11
32
  supabase: SupabaseClient,
@@ -1,5 +1,45 @@
1
1
  import { SupabaseClient } from '@supabase/supabase-js';
2
2
  import { SaveToProjectBrainInput, UpdateRoadmapStatusInput, AddRoadmapChunkInput } from '../lib/types.js';
3
+ import { registry } from '../lib/tool-registry.js';
4
+ import {
5
+ SaveToProjectBrainInputSchema,
6
+ UpdateRoadmapStatusInputSchema,
7
+ AddRoadmapChunkInputSchema
8
+ } from '../lib/schemas.js';
9
+
10
+ // ============================================
11
+ // Tool Registration
12
+ // ============================================
13
+
14
+ registry.register({
15
+ name: 'save_to_project_brain',
16
+ description: `Maja's Tool: Persists knowledge, decisions, and lessons learned to the Project Brain.`,
17
+ schema: SaveToProjectBrainInputSchema,
18
+ handler: async (args, context) => {
19
+ const result = await saveToProjectBrain(context.supabase, context.userId, args);
20
+ return { content: [{ type: 'text', text: result.message }] };
21
+ }
22
+ });
23
+
24
+ registry.register({
25
+ name: 'update_roadmap_status',
26
+ description: `Kine's Tool: Updates the status of a roadmap task and notifies Scribe system.`,
27
+ schema: UpdateRoadmapStatusInputSchema,
28
+ handler: async (args, context) => {
29
+ const result = await updateRoadmapStatus(context.supabase, context.userId, args);
30
+ return { content: [{ type: 'text', text: result.message }] };
31
+ }
32
+ });
33
+
34
+ registry.register({
35
+ name: 'add_roadmap_chunk',
36
+ description: `Kine's Tool: Adds a new task/chunk to the roadmap for feature decomposition.`,
37
+ schema: AddRoadmapChunkInputSchema,
38
+ handler: async (args, context) => {
39
+ const result = await addRoadmapChunk(context.supabase, context.userId, args);
40
+ return { content: [{ type: 'text', text: result.message }] };
41
+ }
42
+ });
3
43
 
4
44
  /**
5
45
  * Maja's Tool: Save to Project Brain
@@ -8,9 +8,33 @@
8
8
 
9
9
  import { SupabaseClient } from '@supabase/supabase-js';
10
10
  import type { BrainQueryResponse, MemoryRecord } from '../lib/types.js';
11
+ import { registry } from '../lib/tool-registry.js';
12
+ import { QueryBrainInputSchema } from '../lib/schemas.js';
13
+
14
+ // ============================================
15
+ // Tool Registration
16
+ // ============================================
17
+
18
+ registry.register({
19
+ name: 'query_brain',
20
+ description: `Takes a natural language query and performs semantic search
21
+ against the project's memories (RAG), returning relevant
22
+ architecture rules, decisions, and constraints.`,
23
+ schema: QueryBrainInputSchema,
24
+ handler: async (args, context) => {
25
+ const result = await queryBrain(
26
+ context.supabase,
27
+ context.userId,
28
+ args.projectId,
29
+ args.query,
30
+ args.limit,
31
+ args.threshold
32
+ );
33
+ return { content: [{ type: 'text', text: result.formatted }] };
34
+ }
35
+ });
11
36
 
12
37
  // Simple embedding generation using text normalization
13
- // In production, this would call an embedding API like OpenAI
14
38
  async function generateQueryEmbedding(query: string): Promise<number[]> {
15
39
  // For MCP server, we'll use the match_memories_text RPC if available,
16
40
  // or fall back to keyword-based search.
@@ -7,6 +7,8 @@
7
7
 
8
8
  import { SupabaseClient } from '@supabase/supabase-js';
9
9
  import type { ArchitectureAuditResponse, AuditViolation } from '../lib/types.js';
10
+ import { registry } from '../lib/tool-registry.js';
11
+ import { RunArchitectureAuditInputSchema } from '../lib/schemas.js';
10
12
 
11
13
  // Vulnerability patterns for static analysis
12
14
  const VULNERABILITY_PATTERNS: {
@@ -80,6 +82,27 @@ function extractLineNumber(content: string, match: RegExpMatchArray): number {
80
82
  return (upToMatch.match(/\n/g) || []).length + 1;
81
83
  }
82
84
 
85
+ // ============================================
86
+ // Tool Registration
87
+ // ============================================
88
+
89
+ registry.register({
90
+ name: 'run_architecture_audit',
91
+ description: `Audits code against project memories and architecture rules.
92
+ Returns violations or "Pass" status.`,
93
+ schema: RunArchitectureAuditInputSchema,
94
+ handler: async (args, context) => {
95
+ const result = await runArchitectureAudit(
96
+ context.supabase,
97
+ context.userId,
98
+ args.projectId,
99
+ args.filePath,
100
+ args.content
101
+ );
102
+ return { content: [{ type: 'text', text: result.summary }] };
103
+ }
104
+ });
105
+
83
106
  export async function runArchitectureAudit(
84
107
  supabase: SupabaseClient,
85
108
  userId: string,
@@ -7,6 +7,32 @@
7
7
 
8
8
  import { SupabaseClient } from '@supabase/supabase-js';
9
9
  import type { SaveDecisionResponse } from '../lib/types.js';
10
+ import { registry } from '../lib/tool-registry.js';
11
+ import { SaveDecisionInputSchema } from '../lib/schemas.js';
12
+
13
+ // ============================================
14
+ // Tool Registration
15
+ // ============================================
16
+
17
+ registry.register({
18
+ name: 'save_decision',
19
+ description: `Saves a new decision/ADR to the project's brain (project_memories).
20
+ High-importance memory for architectural decisions.`,
21
+ schema: SaveDecisionInputSchema,
22
+ handler: async (args, context) => {
23
+ const result = await saveDecision(
24
+ context.supabase,
25
+ context.userId,
26
+ args.projectId,
27
+ args.title,
28
+ args.decision,
29
+ args.rationale,
30
+ args.category,
31
+ args.tags
32
+ );
33
+ return { content: [{ type: 'text', text: result.message }] };
34
+ }
35
+ });
10
36
 
11
37
  export async function saveDecision(
12
38
  supabase: SupabaseClient,