@timmeck/brain 1.8.1 → 1.8.2

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 (162) 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/dashboard/server.js +25 -25
  5. package/dist/db/migrations/001_core_schema.js +115 -115
  6. package/dist/db/migrations/002_learning_schema.js +33 -33
  7. package/dist/db/migrations/003_code_schema.js +48 -48
  8. package/dist/db/migrations/004_synapses_schema.js +52 -52
  9. package/dist/db/migrations/005_fts_indexes.js +73 -73
  10. package/dist/db/migrations/007_feedback.js +8 -8
  11. package/dist/db/migrations/008_git_integration.js +33 -33
  12. package/dist/db/migrations/009_embeddings.js +3 -3
  13. package/dist/db/repositories/antipattern.repository.js +3 -3
  14. package/dist/db/repositories/code-module.repository.js +32 -32
  15. package/dist/db/repositories/notification.repository.js +3 -3
  16. package/dist/db/repositories/project.repository.js +21 -21
  17. package/dist/db/repositories/rule.repository.js +24 -24
  18. package/dist/db/repositories/solution.repository.js +50 -50
  19. package/dist/db/repositories/synapse.repository.js +18 -18
  20. package/dist/db/repositories/terminal.repository.js +24 -24
  21. package/dist/ipc/server.d.ts +8 -0
  22. package/dist/ipc/server.js +67 -1
  23. package/dist/ipc/server.js.map +1 -1
  24. package/dist/matching/error-matcher.js +5 -5
  25. package/dist/matching/fingerprint.js +6 -1
  26. package/dist/matching/fingerprint.js.map +1 -1
  27. package/dist/services/error.service.js +4 -3
  28. package/dist/services/error.service.js.map +1 -1
  29. package/dist/services/git.service.js +14 -14
  30. package/package.json +49 -49
  31. package/src/api/server.ts +395 -395
  32. package/src/brain.ts +266 -266
  33. package/src/cli/colors.ts +116 -116
  34. package/src/cli/commands/config.ts +169 -169
  35. package/src/cli/commands/dashboard.ts +755 -755
  36. package/src/cli/commands/doctor.ts +118 -118
  37. package/src/cli/commands/explain.ts +83 -83
  38. package/src/cli/commands/export.ts +31 -31
  39. package/src/cli/commands/import.ts +199 -199
  40. package/src/cli/commands/insights.ts +65 -65
  41. package/src/cli/commands/learn.ts +24 -24
  42. package/src/cli/commands/modules.ts +53 -53
  43. package/src/cli/commands/network.ts +67 -67
  44. package/src/cli/commands/projects.ts +42 -42
  45. package/src/cli/commands/query.ts +120 -120
  46. package/src/cli/commands/start.ts +62 -62
  47. package/src/cli/commands/status.ts +75 -75
  48. package/src/cli/commands/stop.ts +34 -34
  49. package/src/cli/ipc-helper.ts +22 -22
  50. package/src/cli/update-check.ts +63 -63
  51. package/src/code/fingerprint.ts +87 -87
  52. package/src/code/parsers/generic.ts +29 -29
  53. package/src/code/parsers/python.ts +54 -54
  54. package/src/code/parsers/typescript.ts +65 -65
  55. package/src/code/registry.ts +60 -60
  56. package/src/dashboard/server.ts +142 -142
  57. package/src/db/connection.ts +22 -22
  58. package/src/db/migrations/001_core_schema.ts +120 -120
  59. package/src/db/migrations/002_learning_schema.ts +38 -38
  60. package/src/db/migrations/003_code_schema.ts +53 -53
  61. package/src/db/migrations/004_synapses_schema.ts +57 -57
  62. package/src/db/migrations/005_fts_indexes.ts +78 -78
  63. package/src/db/migrations/006_synapses_phase3.ts +17 -17
  64. package/src/db/migrations/007_feedback.ts +13 -13
  65. package/src/db/migrations/008_git_integration.ts +38 -38
  66. package/src/db/migrations/009_embeddings.ts +8 -8
  67. package/src/db/repositories/antipattern.repository.ts +66 -66
  68. package/src/db/repositories/code-module.repository.ts +142 -142
  69. package/src/db/repositories/notification.repository.ts +66 -66
  70. package/src/db/repositories/project.repository.ts +93 -93
  71. package/src/db/repositories/rule.repository.ts +108 -108
  72. package/src/db/repositories/solution.repository.ts +154 -154
  73. package/src/db/repositories/synapse.repository.ts +153 -153
  74. package/src/db/repositories/terminal.repository.ts +101 -101
  75. package/src/embeddings/engine.ts +238 -238
  76. package/src/index.ts +63 -63
  77. package/src/ipc/client.ts +118 -118
  78. package/src/ipc/protocol.ts +35 -35
  79. package/src/ipc/router.ts +133 -133
  80. package/src/ipc/server.ts +176 -110
  81. package/src/learning/decay.ts +46 -46
  82. package/src/learning/pattern-extractor.ts +90 -90
  83. package/src/learning/rule-generator.ts +74 -74
  84. package/src/matching/error-matcher.ts +5 -5
  85. package/src/matching/fingerprint.ts +34 -29
  86. package/src/matching/similarity.ts +61 -61
  87. package/src/matching/tfidf.ts +74 -74
  88. package/src/matching/tokenizer.ts +41 -41
  89. package/src/mcp/auto-detect.ts +93 -93
  90. package/src/mcp/http-server.ts +140 -140
  91. package/src/mcp/server.ts +73 -73
  92. package/src/parsing/error-parser.ts +28 -28
  93. package/src/parsing/parsers/compiler.ts +93 -93
  94. package/src/parsing/parsers/generic.ts +28 -28
  95. package/src/parsing/parsers/go.ts +97 -97
  96. package/src/parsing/parsers/node.ts +69 -69
  97. package/src/parsing/parsers/python.ts +62 -62
  98. package/src/parsing/parsers/rust.ts +50 -50
  99. package/src/parsing/parsers/shell.ts +42 -42
  100. package/src/parsing/types.ts +47 -47
  101. package/src/research/gap-analyzer.ts +135 -135
  102. package/src/research/insight-generator.ts +123 -123
  103. package/src/research/research-engine.ts +116 -116
  104. package/src/research/synergy-detector.ts +126 -126
  105. package/src/research/template-extractor.ts +130 -130
  106. package/src/research/trend-analyzer.ts +127 -127
  107. package/src/services/code.service.ts +271 -271
  108. package/src/services/error.service.ts +4 -3
  109. package/src/services/git.service.ts +132 -132
  110. package/src/services/notification.service.ts +41 -41
  111. package/src/services/synapse.service.ts +59 -59
  112. package/src/services/terminal.service.ts +81 -81
  113. package/src/synapses/activation.ts +80 -80
  114. package/src/synapses/decay.ts +38 -38
  115. package/src/synapses/hebbian.ts +69 -69
  116. package/src/synapses/pathfinder.ts +81 -81
  117. package/src/synapses/synapse-manager.ts +109 -109
  118. package/src/types/code.types.ts +52 -52
  119. package/src/types/error.types.ts +67 -67
  120. package/src/types/ipc.types.ts +8 -8
  121. package/src/types/mcp.types.ts +53 -53
  122. package/src/types/research.types.ts +28 -28
  123. package/src/types/solution.types.ts +30 -30
  124. package/src/utils/events.ts +45 -45
  125. package/src/utils/hash.ts +5 -5
  126. package/src/utils/logger.ts +48 -48
  127. package/src/utils/paths.ts +19 -19
  128. package/tests/e2e/test_code_intelligence.py +1015 -0
  129. package/tests/e2e/test_error_memory.py +451 -0
  130. package/tests/e2e/test_full_integration.py +534 -0
  131. package/tests/fixtures/code-modules/modules.ts +83 -83
  132. package/tests/fixtures/errors/go.ts +9 -9
  133. package/tests/fixtures/errors/node.ts +24 -24
  134. package/tests/fixtures/errors/python.ts +21 -21
  135. package/tests/fixtures/errors/rust.ts +25 -25
  136. package/tests/fixtures/errors/shell.ts +15 -15
  137. package/tests/fixtures/solutions/solutions.ts +27 -27
  138. package/tests/helpers/setup-db.ts +52 -52
  139. package/tests/integration/code-flow.test.ts +86 -86
  140. package/tests/integration/error-flow.test.ts +83 -83
  141. package/tests/integration/ipc-flow.test.ts +166 -166
  142. package/tests/integration/learning-cycle.test.ts +82 -82
  143. package/tests/integration/synapse-flow.test.ts +117 -117
  144. package/tests/unit/code/analyzer.test.ts +58 -58
  145. package/tests/unit/code/fingerprint.test.ts +51 -51
  146. package/tests/unit/code/scorer.test.ts +55 -55
  147. package/tests/unit/learning/confidence-scorer.test.ts +60 -60
  148. package/tests/unit/learning/decay.test.ts +45 -45
  149. package/tests/unit/learning/pattern-extractor.test.ts +50 -50
  150. package/tests/unit/matching/error-matcher.test.ts +69 -69
  151. package/tests/unit/matching/fingerprint.test.ts +47 -47
  152. package/tests/unit/matching/similarity.test.ts +65 -65
  153. package/tests/unit/matching/tfidf.test.ts +71 -71
  154. package/tests/unit/matching/tokenizer.test.ts +83 -83
  155. package/tests/unit/parsing/parsers.test.ts +113 -113
  156. package/tests/unit/research/gap-analyzer.test.ts +45 -45
  157. package/tests/unit/research/trend-analyzer.test.ts +45 -45
  158. package/tests/unit/synapses/activation.test.ts +80 -80
  159. package/tests/unit/synapses/decay.test.ts +27 -27
  160. package/tests/unit/synapses/hebbian.test.ts +96 -96
  161. package/tests/unit/synapses/pathfinder.test.ts +72 -72
  162. 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
+ }