@timmeck/brain 1.8.1 → 1.8.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 (164) hide show
  1. package/BRAIN_PLAN.md +3324 -3324
  2. package/LICENSE +21 -21
  3. package/dist/cli/commands/dashboard.js +595 -595
  4. package/dist/cli/commands/doctor.js +6 -1
  5. package/dist/cli/commands/doctor.js.map +1 -1
  6. package/dist/dashboard/server.js +25 -25
  7. package/dist/db/migrations/001_core_schema.js +115 -115
  8. package/dist/db/migrations/002_learning_schema.js +33 -33
  9. package/dist/db/migrations/003_code_schema.js +48 -48
  10. package/dist/db/migrations/004_synapses_schema.js +52 -52
  11. package/dist/db/migrations/005_fts_indexes.js +73 -73
  12. package/dist/db/migrations/007_feedback.js +8 -8
  13. package/dist/db/migrations/008_git_integration.js +33 -33
  14. package/dist/db/migrations/009_embeddings.js +3 -3
  15. package/dist/db/repositories/antipattern.repository.js +3 -3
  16. package/dist/db/repositories/code-module.repository.js +32 -32
  17. package/dist/db/repositories/notification.repository.js +3 -3
  18. package/dist/db/repositories/project.repository.js +21 -21
  19. package/dist/db/repositories/rule.repository.js +24 -24
  20. package/dist/db/repositories/solution.repository.js +50 -50
  21. package/dist/db/repositories/synapse.repository.js +18 -18
  22. package/dist/db/repositories/terminal.repository.js +24 -24
  23. package/dist/ipc/server.d.ts +8 -0
  24. package/dist/ipc/server.js +67 -1
  25. package/dist/ipc/server.js.map +1 -1
  26. package/dist/matching/error-matcher.js +5 -5
  27. package/dist/matching/fingerprint.js +6 -1
  28. package/dist/matching/fingerprint.js.map +1 -1
  29. package/dist/services/error.service.js +4 -3
  30. package/dist/services/error.service.js.map +1 -1
  31. package/dist/services/git.service.js +14 -14
  32. package/package.json +49 -49
  33. package/src/api/server.ts +395 -395
  34. package/src/brain.ts +266 -266
  35. package/src/cli/colors.ts +116 -116
  36. package/src/cli/commands/config.ts +169 -169
  37. package/src/cli/commands/dashboard.ts +755 -755
  38. package/src/cli/commands/doctor.ts +124 -118
  39. package/src/cli/commands/explain.ts +83 -83
  40. package/src/cli/commands/export.ts +31 -31
  41. package/src/cli/commands/import.ts +199 -199
  42. package/src/cli/commands/insights.ts +65 -65
  43. package/src/cli/commands/learn.ts +24 -24
  44. package/src/cli/commands/modules.ts +53 -53
  45. package/src/cli/commands/network.ts +67 -67
  46. package/src/cli/commands/projects.ts +42 -42
  47. package/src/cli/commands/query.ts +120 -120
  48. package/src/cli/commands/start.ts +62 -62
  49. package/src/cli/commands/status.ts +75 -75
  50. package/src/cli/commands/stop.ts +34 -34
  51. package/src/cli/ipc-helper.ts +22 -22
  52. package/src/cli/update-check.ts +63 -63
  53. package/src/code/fingerprint.ts +87 -87
  54. package/src/code/parsers/generic.ts +29 -29
  55. package/src/code/parsers/python.ts +54 -54
  56. package/src/code/parsers/typescript.ts +65 -65
  57. package/src/code/registry.ts +60 -60
  58. package/src/dashboard/server.ts +142 -142
  59. package/src/db/connection.ts +22 -22
  60. package/src/db/migrations/001_core_schema.ts +120 -120
  61. package/src/db/migrations/002_learning_schema.ts +38 -38
  62. package/src/db/migrations/003_code_schema.ts +53 -53
  63. package/src/db/migrations/004_synapses_schema.ts +57 -57
  64. package/src/db/migrations/005_fts_indexes.ts +78 -78
  65. package/src/db/migrations/006_synapses_phase3.ts +17 -17
  66. package/src/db/migrations/007_feedback.ts +13 -13
  67. package/src/db/migrations/008_git_integration.ts +38 -38
  68. package/src/db/migrations/009_embeddings.ts +8 -8
  69. package/src/db/repositories/antipattern.repository.ts +66 -66
  70. package/src/db/repositories/code-module.repository.ts +142 -142
  71. package/src/db/repositories/notification.repository.ts +66 -66
  72. package/src/db/repositories/project.repository.ts +93 -93
  73. package/src/db/repositories/rule.repository.ts +108 -108
  74. package/src/db/repositories/solution.repository.ts +154 -154
  75. package/src/db/repositories/synapse.repository.ts +153 -153
  76. package/src/db/repositories/terminal.repository.ts +101 -101
  77. package/src/embeddings/engine.ts +238 -238
  78. package/src/index.ts +63 -63
  79. package/src/ipc/client.ts +118 -118
  80. package/src/ipc/protocol.ts +35 -35
  81. package/src/ipc/router.ts +133 -133
  82. package/src/ipc/server.ts +176 -110
  83. package/src/learning/decay.ts +46 -46
  84. package/src/learning/pattern-extractor.ts +90 -90
  85. package/src/learning/rule-generator.ts +74 -74
  86. package/src/matching/error-matcher.ts +5 -5
  87. package/src/matching/fingerprint.ts +34 -29
  88. package/src/matching/similarity.ts +61 -61
  89. package/src/matching/tfidf.ts +74 -74
  90. package/src/matching/tokenizer.ts +41 -41
  91. package/src/mcp/auto-detect.ts +93 -93
  92. package/src/mcp/http-server.ts +140 -140
  93. package/src/mcp/server.ts +73 -73
  94. package/src/parsing/error-parser.ts +28 -28
  95. package/src/parsing/parsers/compiler.ts +93 -93
  96. package/src/parsing/parsers/generic.ts +28 -28
  97. package/src/parsing/parsers/go.ts +97 -97
  98. package/src/parsing/parsers/node.ts +69 -69
  99. package/src/parsing/parsers/python.ts +62 -62
  100. package/src/parsing/parsers/rust.ts +50 -50
  101. package/src/parsing/parsers/shell.ts +42 -42
  102. package/src/parsing/types.ts +47 -47
  103. package/src/research/gap-analyzer.ts +135 -135
  104. package/src/research/insight-generator.ts +123 -123
  105. package/src/research/research-engine.ts +116 -116
  106. package/src/research/synergy-detector.ts +126 -126
  107. package/src/research/template-extractor.ts +130 -130
  108. package/src/research/trend-analyzer.ts +127 -127
  109. package/src/services/code.service.ts +271 -271
  110. package/src/services/error.service.ts +4 -3
  111. package/src/services/git.service.ts +132 -132
  112. package/src/services/notification.service.ts +41 -41
  113. package/src/services/synapse.service.ts +59 -59
  114. package/src/services/terminal.service.ts +81 -81
  115. package/src/synapses/activation.ts +80 -80
  116. package/src/synapses/decay.ts +38 -38
  117. package/src/synapses/hebbian.ts +69 -69
  118. package/src/synapses/pathfinder.ts +81 -81
  119. package/src/synapses/synapse-manager.ts +109 -109
  120. package/src/types/code.types.ts +52 -52
  121. package/src/types/error.types.ts +67 -67
  122. package/src/types/ipc.types.ts +8 -8
  123. package/src/types/mcp.types.ts +53 -53
  124. package/src/types/research.types.ts +28 -28
  125. package/src/types/solution.types.ts +30 -30
  126. package/src/utils/events.ts +45 -45
  127. package/src/utils/hash.ts +5 -5
  128. package/src/utils/logger.ts +48 -48
  129. package/src/utils/paths.ts +19 -19
  130. package/tests/e2e/test_code_intelligence.py +1015 -0
  131. package/tests/e2e/test_error_memory.py +451 -0
  132. package/tests/e2e/test_full_integration.py +534 -0
  133. package/tests/fixtures/code-modules/modules.ts +83 -83
  134. package/tests/fixtures/errors/go.ts +9 -9
  135. package/tests/fixtures/errors/node.ts +24 -24
  136. package/tests/fixtures/errors/python.ts +21 -21
  137. package/tests/fixtures/errors/rust.ts +25 -25
  138. package/tests/fixtures/errors/shell.ts +15 -15
  139. package/tests/fixtures/solutions/solutions.ts +27 -27
  140. package/tests/helpers/setup-db.ts +52 -52
  141. package/tests/integration/code-flow.test.ts +86 -86
  142. package/tests/integration/error-flow.test.ts +83 -83
  143. package/tests/integration/ipc-flow.test.ts +166 -166
  144. package/tests/integration/learning-cycle.test.ts +82 -82
  145. package/tests/integration/synapse-flow.test.ts +117 -117
  146. package/tests/unit/code/analyzer.test.ts +58 -58
  147. package/tests/unit/code/fingerprint.test.ts +51 -51
  148. package/tests/unit/code/scorer.test.ts +55 -55
  149. package/tests/unit/learning/confidence-scorer.test.ts +60 -60
  150. package/tests/unit/learning/decay.test.ts +45 -45
  151. package/tests/unit/learning/pattern-extractor.test.ts +50 -50
  152. package/tests/unit/matching/error-matcher.test.ts +69 -69
  153. package/tests/unit/matching/fingerprint.test.ts +47 -47
  154. package/tests/unit/matching/similarity.test.ts +65 -65
  155. package/tests/unit/matching/tfidf.test.ts +71 -71
  156. package/tests/unit/matching/tokenizer.test.ts +83 -83
  157. package/tests/unit/parsing/parsers.test.ts +113 -113
  158. package/tests/unit/research/gap-analyzer.test.ts +45 -45
  159. package/tests/unit/research/trend-analyzer.test.ts +45 -45
  160. package/tests/unit/synapses/activation.test.ts +80 -80
  161. package/tests/unit/synapses/decay.test.ts +27 -27
  162. package/tests/unit/synapses/hebbian.test.ts +96 -96
  163. package/tests/unit/synapses/pathfinder.test.ts +72 -72
  164. package/tsconfig.json +18 -18
package/src/brain.ts CHANGED
@@ -1,266 +1,266 @@
1
- import path from 'node:path';
2
- import fs from 'node:fs';
3
- import type Database from 'better-sqlite3';
4
- import { loadConfig } from './config.js';
5
- import type { BrainConfig } from './types/config.types.js';
6
- import { createLogger, getLogger } from './utils/logger.js';
7
- import { getEventBus } from './utils/events.js';
8
- import { createConnection } from './db/connection.js';
9
- import { runMigrations } from './db/migrations/index.js';
10
-
11
- // Repositories
12
- import { ProjectRepository } from './db/repositories/project.repository.js';
13
- import { ErrorRepository } from './db/repositories/error.repository.js';
14
- import { SolutionRepository } from './db/repositories/solution.repository.js';
15
- import { RuleRepository } from './db/repositories/rule.repository.js';
16
- import { AntipatternRepository } from './db/repositories/antipattern.repository.js';
17
- import { TerminalRepository } from './db/repositories/terminal.repository.js';
18
- import { CodeModuleRepository } from './db/repositories/code-module.repository.js';
19
- import { SynapseRepository } from './db/repositories/synapse.repository.js';
20
- import { NotificationRepository } from './db/repositories/notification.repository.js';
21
- import { InsightRepository } from './db/repositories/insight.repository.js';
22
-
23
- // Services
24
- import { ErrorService } from './services/error.service.js';
25
- import { SolutionService } from './services/solution.service.js';
26
- import { TerminalService } from './services/terminal.service.js';
27
- import { PreventionService } from './services/prevention.service.js';
28
- import { CodeService } from './services/code.service.js';
29
- import { SynapseService } from './services/synapse.service.js';
30
- import { ResearchService } from './services/research.service.js';
31
- import { NotificationService } from './services/notification.service.js';
32
- import { AnalyticsService } from './services/analytics.service.js';
33
- import { GitService } from './services/git.service.js';
34
-
35
- // Synapses
36
- import { SynapseManager } from './synapses/synapse-manager.js';
37
-
38
- // Engines
39
- import { LearningEngine } from './learning/learning-engine.js';
40
- import { ResearchEngine } from './research/research-engine.js';
41
-
42
- // IPC
43
- import { IpcRouter, type Services } from './ipc/router.js';
44
- import { IpcServer } from './ipc/server.js';
45
-
46
- // API & MCP HTTP
47
- import { ApiServer } from './api/server.js';
48
- import { McpHttpServer } from './mcp/http-server.js';
49
-
50
- // Embeddings
51
- import { EmbeddingEngine } from './embeddings/engine.js';
52
-
53
- export class BrainCore {
54
- private db: Database.Database | null = null;
55
- private ipcServer: IpcServer | null = null;
56
- private apiServer: ApiServer | null = null;
57
- private mcpHttpServer: McpHttpServer | null = null;
58
- private embeddingEngine: EmbeddingEngine | null = null;
59
- private learningEngine: LearningEngine | null = null;
60
- private researchEngine: ResearchEngine | null = null;
61
- private cleanupTimer: ReturnType<typeof setInterval> | null = null;
62
- private config: BrainConfig | null = null;
63
-
64
- start(configPath?: string): void {
65
- // 1. Config
66
- this.config = loadConfig(configPath);
67
- const config = this.config;
68
-
69
- // 2. Ensure data dir
70
- fs.mkdirSync(path.dirname(config.dbPath), { recursive: true });
71
-
72
- // 3. Logger
73
- createLogger({
74
- level: config.log.level,
75
- file: config.log.file,
76
- maxSize: config.log.maxSize,
77
- maxFiles: config.log.maxFiles,
78
- });
79
- const logger = getLogger();
80
-
81
- // 4. Database
82
- this.db = createConnection(config.dbPath);
83
- runMigrations(this.db);
84
- logger.info(`Database initialized: ${config.dbPath}`);
85
-
86
- // 5. Repositories
87
- const projectRepo = new ProjectRepository(this.db);
88
- const errorRepo = new ErrorRepository(this.db);
89
- const solutionRepo = new SolutionRepository(this.db);
90
- const ruleRepo = new RuleRepository(this.db);
91
- const antipatternRepo = new AntipatternRepository(this.db);
92
- const terminalRepo = new TerminalRepository(this.db);
93
- const codeModuleRepo = new CodeModuleRepository(this.db);
94
- const synapseRepo = new SynapseRepository(this.db);
95
- const notificationRepo = new NotificationRepository(this.db);
96
- const insightRepo = new InsightRepository(this.db);
97
-
98
- // 6. Synapse Manager
99
- const synapseManager = new SynapseManager(synapseRepo, config.synapses);
100
-
101
- // 7. Services
102
- const services: Services = {
103
- error: new ErrorService(errorRepo, projectRepo, synapseManager, config.matching),
104
- solution: new SolutionService(solutionRepo, synapseManager),
105
- terminal: new TerminalService(terminalRepo, config.terminal.staleTimeout),
106
- prevention: new PreventionService(ruleRepo, antipatternRepo, synapseManager),
107
- code: new CodeService(codeModuleRepo, projectRepo, synapseManager),
108
- synapse: new SynapseService(synapseManager),
109
- research: new ResearchService(insightRepo, errorRepo, synapseManager),
110
- notification: new NotificationService(notificationRepo),
111
- analytics: new AnalyticsService(
112
- errorRepo, solutionRepo, codeModuleRepo,
113
- ruleRepo, antipatternRepo, insightRepo,
114
- synapseManager,
115
- ),
116
- git: new GitService(this.db!, synapseManager),
117
- };
118
-
119
- // 8. Embedding Engine (local vector search)
120
- if (config.embeddings.enabled) {
121
- this.embeddingEngine = new EmbeddingEngine(config.embeddings, this.db!);
122
- this.embeddingEngine.start();
123
- // Wire embedding engine into services for hybrid search
124
- services.error.setEmbeddingEngine(this.embeddingEngine);
125
- services.code.setEmbeddingEngine(this.embeddingEngine);
126
- logger.info('Embedding engine started (model will load in background)');
127
- }
128
-
129
- // 9. Learning Engine
130
- this.learningEngine = new LearningEngine(
131
- config.learning, errorRepo, solutionRepo,
132
- ruleRepo, antipatternRepo, synapseManager,
133
- );
134
- this.learningEngine.start();
135
- logger.info(`Learning engine started (interval: ${config.learning.intervalMs}ms)`);
136
-
137
- // 10. Research Engine
138
- this.researchEngine = new ResearchEngine(
139
- config.research, errorRepo, solutionRepo, projectRepo,
140
- codeModuleRepo, synapseRepo, insightRepo, synapseManager,
141
- );
142
- this.researchEngine.start();
143
- logger.info(`Research engine started (interval: ${config.research.intervalMs}ms)`);
144
-
145
- // Expose learning engine to IPC
146
- services.learning = this.learningEngine;
147
-
148
- // 11. IPC Server
149
- const router = new IpcRouter(services);
150
- this.ipcServer = new IpcServer(router, config.ipc.pipeName);
151
- this.ipcServer.start();
152
-
153
- // 11a. REST API Server
154
- if (config.api.enabled) {
155
- this.apiServer = new ApiServer({
156
- port: config.api.port,
157
- router,
158
- apiKey: config.api.apiKey,
159
- });
160
- this.apiServer.start();
161
- logger.info(`REST API enabled on port ${config.api.port}`);
162
- }
163
-
164
- // 11b. MCP HTTP Server (SSE transport for Cursor, Windsurf, Cline, Continue)
165
- if (config.mcpHttp.enabled) {
166
- this.mcpHttpServer = new McpHttpServer(config.mcpHttp.port, router);
167
- this.mcpHttpServer.start();
168
- logger.info(`MCP HTTP (SSE) enabled on port ${config.mcpHttp.port}`);
169
- }
170
-
171
- // 12. Terminal cleanup timer
172
- this.cleanupTimer = setInterval(() => {
173
- services.terminal.cleanup();
174
- }, 60_000);
175
-
176
- // 13. Event listeners (synapse wiring)
177
- this.setupEventListeners(services, synapseManager);
178
-
179
- // 14. PID file
180
- const pidPath = path.join(path.dirname(config.dbPath), 'brain.pid');
181
- fs.writeFileSync(pidPath, String(process.pid));
182
-
183
- // 15. Graceful shutdown
184
- process.on('SIGINT', () => this.stop());
185
- process.on('SIGTERM', () => this.stop());
186
-
187
- logger.info(`Brain daemon started (PID: ${process.pid})`);
188
- }
189
-
190
- stop(): void {
191
- const logger = getLogger();
192
- logger.info('Shutting down...');
193
-
194
- if (this.cleanupTimer) {
195
- clearInterval(this.cleanupTimer);
196
- this.cleanupTimer = null;
197
- }
198
-
199
- this.researchEngine?.stop();
200
- this.embeddingEngine?.stop();
201
- this.learningEngine?.stop();
202
- this.mcpHttpServer?.stop();
203
- this.apiServer?.stop();
204
- this.ipcServer?.stop();
205
- this.db?.close();
206
-
207
- // Remove PID file
208
- if (this.config) {
209
- const pidPath = path.join(path.dirname(this.config.dbPath), 'brain.pid');
210
- try { fs.unlinkSync(pidPath); } catch { /* ignore */ }
211
- }
212
-
213
- logger.info('Brain daemon stopped');
214
- process.exit(0);
215
- }
216
-
217
- private setupEventListeners(services: Services, synapseManager: SynapseManager): void {
218
- const bus = getEventBus();
219
-
220
- // Error → Project synapse
221
- bus.on('error:reported', ({ errorId, projectId }) => {
222
- synapseManager.strengthen(
223
- { type: 'error', id: errorId },
224
- { type: 'project', id: projectId },
225
- 'co_occurs',
226
- );
227
- });
228
-
229
- // Solution applied → strengthen or weaken
230
- bus.on('solution:applied', ({ errorId, solutionId, success }) => {
231
- if (success) {
232
- synapseManager.strengthen(
233
- { type: 'solution', id: solutionId },
234
- { type: 'error', id: errorId },
235
- 'solves',
236
- );
237
- } else {
238
- const synapse = synapseManager.find(
239
- { type: 'solution', id: solutionId },
240
- { type: 'error', id: errorId },
241
- 'solves',
242
- );
243
- if (synapse) synapseManager.weaken(synapse.id, 0.7);
244
- }
245
- });
246
-
247
- // Module registered → link to project
248
- bus.on('module:registered', ({ moduleId, projectId }) => {
249
- synapseManager.strengthen(
250
- { type: 'code_module', id: moduleId },
251
- { type: 'project', id: projectId },
252
- 'co_occurs',
253
- );
254
- });
255
-
256
- // Rule learned → log
257
- bus.on('rule:learned', ({ ruleId, pattern }) => {
258
- getLogger().info(`New rule #${ruleId} learned: ${pattern}`);
259
- });
260
-
261
- // Insight created → log
262
- bus.on('insight:created', ({ insightId, type }) => {
263
- getLogger().info(`New insight #${insightId} (${type})`);
264
- });
265
- }
266
- }
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import type Database from 'better-sqlite3';
4
+ import { loadConfig } from './config.js';
5
+ import type { BrainConfig } from './types/config.types.js';
6
+ import { createLogger, getLogger } from './utils/logger.js';
7
+ import { getEventBus } from './utils/events.js';
8
+ import { createConnection } from './db/connection.js';
9
+ import { runMigrations } from './db/migrations/index.js';
10
+
11
+ // Repositories
12
+ import { ProjectRepository } from './db/repositories/project.repository.js';
13
+ import { ErrorRepository } from './db/repositories/error.repository.js';
14
+ import { SolutionRepository } from './db/repositories/solution.repository.js';
15
+ import { RuleRepository } from './db/repositories/rule.repository.js';
16
+ import { AntipatternRepository } from './db/repositories/antipattern.repository.js';
17
+ import { TerminalRepository } from './db/repositories/terminal.repository.js';
18
+ import { CodeModuleRepository } from './db/repositories/code-module.repository.js';
19
+ import { SynapseRepository } from './db/repositories/synapse.repository.js';
20
+ import { NotificationRepository } from './db/repositories/notification.repository.js';
21
+ import { InsightRepository } from './db/repositories/insight.repository.js';
22
+
23
+ // Services
24
+ import { ErrorService } from './services/error.service.js';
25
+ import { SolutionService } from './services/solution.service.js';
26
+ import { TerminalService } from './services/terminal.service.js';
27
+ import { PreventionService } from './services/prevention.service.js';
28
+ import { CodeService } from './services/code.service.js';
29
+ import { SynapseService } from './services/synapse.service.js';
30
+ import { ResearchService } from './services/research.service.js';
31
+ import { NotificationService } from './services/notification.service.js';
32
+ import { AnalyticsService } from './services/analytics.service.js';
33
+ import { GitService } from './services/git.service.js';
34
+
35
+ // Synapses
36
+ import { SynapseManager } from './synapses/synapse-manager.js';
37
+
38
+ // Engines
39
+ import { LearningEngine } from './learning/learning-engine.js';
40
+ import { ResearchEngine } from './research/research-engine.js';
41
+
42
+ // IPC
43
+ import { IpcRouter, type Services } from './ipc/router.js';
44
+ import { IpcServer } from './ipc/server.js';
45
+
46
+ // API & MCP HTTP
47
+ import { ApiServer } from './api/server.js';
48
+ import { McpHttpServer } from './mcp/http-server.js';
49
+
50
+ // Embeddings
51
+ import { EmbeddingEngine } from './embeddings/engine.js';
52
+
53
+ export class BrainCore {
54
+ private db: Database.Database | null = null;
55
+ private ipcServer: IpcServer | null = null;
56
+ private apiServer: ApiServer | null = null;
57
+ private mcpHttpServer: McpHttpServer | null = null;
58
+ private embeddingEngine: EmbeddingEngine | null = null;
59
+ private learningEngine: LearningEngine | null = null;
60
+ private researchEngine: ResearchEngine | null = null;
61
+ private cleanupTimer: ReturnType<typeof setInterval> | null = null;
62
+ private config: BrainConfig | null = null;
63
+
64
+ start(configPath?: string): void {
65
+ // 1. Config
66
+ this.config = loadConfig(configPath);
67
+ const config = this.config;
68
+
69
+ // 2. Ensure data dir
70
+ fs.mkdirSync(path.dirname(config.dbPath), { recursive: true });
71
+
72
+ // 3. Logger
73
+ createLogger({
74
+ level: config.log.level,
75
+ file: config.log.file,
76
+ maxSize: config.log.maxSize,
77
+ maxFiles: config.log.maxFiles,
78
+ });
79
+ const logger = getLogger();
80
+
81
+ // 4. Database
82
+ this.db = createConnection(config.dbPath);
83
+ runMigrations(this.db);
84
+ logger.info(`Database initialized: ${config.dbPath}`);
85
+
86
+ // 5. Repositories
87
+ const projectRepo = new ProjectRepository(this.db);
88
+ const errorRepo = new ErrorRepository(this.db);
89
+ const solutionRepo = new SolutionRepository(this.db);
90
+ const ruleRepo = new RuleRepository(this.db);
91
+ const antipatternRepo = new AntipatternRepository(this.db);
92
+ const terminalRepo = new TerminalRepository(this.db);
93
+ const codeModuleRepo = new CodeModuleRepository(this.db);
94
+ const synapseRepo = new SynapseRepository(this.db);
95
+ const notificationRepo = new NotificationRepository(this.db);
96
+ const insightRepo = new InsightRepository(this.db);
97
+
98
+ // 6. Synapse Manager
99
+ const synapseManager = new SynapseManager(synapseRepo, config.synapses);
100
+
101
+ // 7. Services
102
+ const services: Services = {
103
+ error: new ErrorService(errorRepo, projectRepo, synapseManager, config.matching),
104
+ solution: new SolutionService(solutionRepo, synapseManager),
105
+ terminal: new TerminalService(terminalRepo, config.terminal.staleTimeout),
106
+ prevention: new PreventionService(ruleRepo, antipatternRepo, synapseManager),
107
+ code: new CodeService(codeModuleRepo, projectRepo, synapseManager),
108
+ synapse: new SynapseService(synapseManager),
109
+ research: new ResearchService(insightRepo, errorRepo, synapseManager),
110
+ notification: new NotificationService(notificationRepo),
111
+ analytics: new AnalyticsService(
112
+ errorRepo, solutionRepo, codeModuleRepo,
113
+ ruleRepo, antipatternRepo, insightRepo,
114
+ synapseManager,
115
+ ),
116
+ git: new GitService(this.db!, synapseManager),
117
+ };
118
+
119
+ // 8. Embedding Engine (local vector search)
120
+ if (config.embeddings.enabled) {
121
+ this.embeddingEngine = new EmbeddingEngine(config.embeddings, this.db!);
122
+ this.embeddingEngine.start();
123
+ // Wire embedding engine into services for hybrid search
124
+ services.error.setEmbeddingEngine(this.embeddingEngine);
125
+ services.code.setEmbeddingEngine(this.embeddingEngine);
126
+ logger.info('Embedding engine started (model will load in background)');
127
+ }
128
+
129
+ // 9. Learning Engine
130
+ this.learningEngine = new LearningEngine(
131
+ config.learning, errorRepo, solutionRepo,
132
+ ruleRepo, antipatternRepo, synapseManager,
133
+ );
134
+ this.learningEngine.start();
135
+ logger.info(`Learning engine started (interval: ${config.learning.intervalMs}ms)`);
136
+
137
+ // 10. Research Engine
138
+ this.researchEngine = new ResearchEngine(
139
+ config.research, errorRepo, solutionRepo, projectRepo,
140
+ codeModuleRepo, synapseRepo, insightRepo, synapseManager,
141
+ );
142
+ this.researchEngine.start();
143
+ logger.info(`Research engine started (interval: ${config.research.intervalMs}ms)`);
144
+
145
+ // Expose learning engine to IPC
146
+ services.learning = this.learningEngine;
147
+
148
+ // 11. IPC Server
149
+ const router = new IpcRouter(services);
150
+ this.ipcServer = new IpcServer(router, config.ipc.pipeName);
151
+ this.ipcServer.start();
152
+
153
+ // 11a. REST API Server
154
+ if (config.api.enabled) {
155
+ this.apiServer = new ApiServer({
156
+ port: config.api.port,
157
+ router,
158
+ apiKey: config.api.apiKey,
159
+ });
160
+ this.apiServer.start();
161
+ logger.info(`REST API enabled on port ${config.api.port}`);
162
+ }
163
+
164
+ // 11b. MCP HTTP Server (SSE transport for Cursor, Windsurf, Cline, Continue)
165
+ if (config.mcpHttp.enabled) {
166
+ this.mcpHttpServer = new McpHttpServer(config.mcpHttp.port, router);
167
+ this.mcpHttpServer.start();
168
+ logger.info(`MCP HTTP (SSE) enabled on port ${config.mcpHttp.port}`);
169
+ }
170
+
171
+ // 12. Terminal cleanup timer
172
+ this.cleanupTimer = setInterval(() => {
173
+ services.terminal.cleanup();
174
+ }, 60_000);
175
+
176
+ // 13. Event listeners (synapse wiring)
177
+ this.setupEventListeners(services, synapseManager);
178
+
179
+ // 14. PID file
180
+ const pidPath = path.join(path.dirname(config.dbPath), 'brain.pid');
181
+ fs.writeFileSync(pidPath, String(process.pid));
182
+
183
+ // 15. Graceful shutdown
184
+ process.on('SIGINT', () => this.stop());
185
+ process.on('SIGTERM', () => this.stop());
186
+
187
+ logger.info(`Brain daemon started (PID: ${process.pid})`);
188
+ }
189
+
190
+ stop(): void {
191
+ const logger = getLogger();
192
+ logger.info('Shutting down...');
193
+
194
+ if (this.cleanupTimer) {
195
+ clearInterval(this.cleanupTimer);
196
+ this.cleanupTimer = null;
197
+ }
198
+
199
+ this.researchEngine?.stop();
200
+ this.embeddingEngine?.stop();
201
+ this.learningEngine?.stop();
202
+ this.mcpHttpServer?.stop();
203
+ this.apiServer?.stop();
204
+ this.ipcServer?.stop();
205
+ this.db?.close();
206
+
207
+ // Remove PID file
208
+ if (this.config) {
209
+ const pidPath = path.join(path.dirname(this.config.dbPath), 'brain.pid');
210
+ try { fs.unlinkSync(pidPath); } catch { /* ignore */ }
211
+ }
212
+
213
+ logger.info('Brain daemon stopped');
214
+ process.exit(0);
215
+ }
216
+
217
+ private setupEventListeners(services: Services, synapseManager: SynapseManager): void {
218
+ const bus = getEventBus();
219
+
220
+ // Error → Project synapse
221
+ bus.on('error:reported', ({ errorId, projectId }) => {
222
+ synapseManager.strengthen(
223
+ { type: 'error', id: errorId },
224
+ { type: 'project', id: projectId },
225
+ 'co_occurs',
226
+ );
227
+ });
228
+
229
+ // Solution applied → strengthen or weaken
230
+ bus.on('solution:applied', ({ errorId, solutionId, success }) => {
231
+ if (success) {
232
+ synapseManager.strengthen(
233
+ { type: 'solution', id: solutionId },
234
+ { type: 'error', id: errorId },
235
+ 'solves',
236
+ );
237
+ } else {
238
+ const synapse = synapseManager.find(
239
+ { type: 'solution', id: solutionId },
240
+ { type: 'error', id: errorId },
241
+ 'solves',
242
+ );
243
+ if (synapse) synapseManager.weaken(synapse.id, 0.7);
244
+ }
245
+ });
246
+
247
+ // Module registered → link to project
248
+ bus.on('module:registered', ({ moduleId, projectId }) => {
249
+ synapseManager.strengthen(
250
+ { type: 'code_module', id: moduleId },
251
+ { type: 'project', id: projectId },
252
+ 'co_occurs',
253
+ );
254
+ });
255
+
256
+ // Rule learned → log
257
+ bus.on('rule:learned', ({ ruleId, pattern }) => {
258
+ getLogger().info(`New rule #${ruleId} learned: ${pattern}`);
259
+ });
260
+
261
+ // Insight created → log
262
+ bus.on('insight:created', ({ insightId, type }) => {
263
+ getLogger().info(`New insight #${insightId} (${type})`);
264
+ });
265
+ }
266
+ }