@timmeck/brain 1.0.0

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 (437) hide show
  1. package/BRAIN_PLAN.md +3324 -0
  2. package/LICENSE +21 -0
  3. package/README.md +188 -0
  4. package/dist/brain.d.ts +11 -0
  5. package/dist/brain.js +166 -0
  6. package/dist/brain.js.map +1 -0
  7. package/dist/cli/commands/dashboard.d.ts +2 -0
  8. package/dist/cli/commands/dashboard.js +457 -0
  9. package/dist/cli/commands/dashboard.js.map +1 -0
  10. package/dist/cli/commands/export.d.ts +2 -0
  11. package/dist/cli/commands/export.js +25 -0
  12. package/dist/cli/commands/export.js.map +1 -0
  13. package/dist/cli/commands/import.d.ts +2 -0
  14. package/dist/cli/commands/import.js +173 -0
  15. package/dist/cli/commands/import.js.map +1 -0
  16. package/dist/cli/commands/insights.d.ts +2 -0
  17. package/dist/cli/commands/insights.js +32 -0
  18. package/dist/cli/commands/insights.js.map +1 -0
  19. package/dist/cli/commands/modules.d.ts +2 -0
  20. package/dist/cli/commands/modules.js +29 -0
  21. package/dist/cli/commands/modules.js.map +1 -0
  22. package/dist/cli/commands/network.d.ts +2 -0
  23. package/dist/cli/commands/network.js +56 -0
  24. package/dist/cli/commands/network.js.map +1 -0
  25. package/dist/cli/commands/query.d.ts +2 -0
  26. package/dist/cli/commands/query.js +40 -0
  27. package/dist/cli/commands/query.js.map +1 -0
  28. package/dist/cli/commands/start.d.ts +2 -0
  29. package/dist/cli/commands/start.js +56 -0
  30. package/dist/cli/commands/start.js.map +1 -0
  31. package/dist/cli/commands/status.d.ts +2 -0
  32. package/dist/cli/commands/status.js +60 -0
  33. package/dist/cli/commands/status.js.map +1 -0
  34. package/dist/cli/commands/stop.d.ts +2 -0
  35. package/dist/cli/commands/stop.js +34 -0
  36. package/dist/cli/commands/stop.js.map +1 -0
  37. package/dist/cli/ipc-helper.d.ts +2 -0
  38. package/dist/cli/ipc-helper.js +25 -0
  39. package/dist/cli/ipc-helper.js.map +1 -0
  40. package/dist/code/analyzer.d.ts +12 -0
  41. package/dist/code/analyzer.js +58 -0
  42. package/dist/code/analyzer.js.map +1 -0
  43. package/dist/code/fingerprint.d.ts +2 -0
  44. package/dist/code/fingerprint.js +84 -0
  45. package/dist/code/fingerprint.js.map +1 -0
  46. package/dist/code/matcher.d.ts +9 -0
  47. package/dist/code/matcher.js +37 -0
  48. package/dist/code/matcher.js.map +1 -0
  49. package/dist/code/parsers/generic.d.ts +7 -0
  50. package/dist/code/parsers/generic.js +22 -0
  51. package/dist/code/parsers/generic.js.map +1 -0
  52. package/dist/code/parsers/python.d.ts +7 -0
  53. package/dist/code/parsers/python.js +45 -0
  54. package/dist/code/parsers/python.js.map +1 -0
  55. package/dist/code/parsers/typescript.d.ts +7 -0
  56. package/dist/code/parsers/typescript.js +58 -0
  57. package/dist/code/parsers/typescript.js.map +1 -0
  58. package/dist/code/registry.d.ts +22 -0
  59. package/dist/code/registry.js +31 -0
  60. package/dist/code/registry.js.map +1 -0
  61. package/dist/code/scorer.d.ts +15 -0
  62. package/dist/code/scorer.js +103 -0
  63. package/dist/code/scorer.js.map +1 -0
  64. package/dist/config.d.ts +2 -0
  65. package/dist/config.js +110 -0
  66. package/dist/config.js.map +1 -0
  67. package/dist/db/connection.d.ts +2 -0
  68. package/dist/db/connection.js +19 -0
  69. package/dist/db/connection.js.map +1 -0
  70. package/dist/db/migrations/001_core_schema.d.ts +2 -0
  71. package/dist/db/migrations/001_core_schema.js +119 -0
  72. package/dist/db/migrations/001_core_schema.js.map +1 -0
  73. package/dist/db/migrations/002_learning_schema.d.ts +2 -0
  74. package/dist/db/migrations/002_learning_schema.js +37 -0
  75. package/dist/db/migrations/002_learning_schema.js.map +1 -0
  76. package/dist/db/migrations/003_code_schema.d.ts +2 -0
  77. package/dist/db/migrations/003_code_schema.js +52 -0
  78. package/dist/db/migrations/003_code_schema.js.map +1 -0
  79. package/dist/db/migrations/004_synapses_schema.d.ts +2 -0
  80. package/dist/db/migrations/004_synapses_schema.js +56 -0
  81. package/dist/db/migrations/004_synapses_schema.js.map +1 -0
  82. package/dist/db/migrations/005_fts_indexes.d.ts +2 -0
  83. package/dist/db/migrations/005_fts_indexes.js +77 -0
  84. package/dist/db/migrations/005_fts_indexes.js.map +1 -0
  85. package/dist/db/migrations/006_synapses_phase3.d.ts +2 -0
  86. package/dist/db/migrations/006_synapses_phase3.js +14 -0
  87. package/dist/db/migrations/006_synapses_phase3.js.map +1 -0
  88. package/dist/db/migrations/index.d.ts +2 -0
  89. package/dist/db/migrations/index.js +49 -0
  90. package/dist/db/migrations/index.js.map +1 -0
  91. package/dist/db/repositories/antipattern.repository.d.ts +26 -0
  92. package/dist/db/repositories/antipattern.repository.js +44 -0
  93. package/dist/db/repositories/antipattern.repository.js.map +1 -0
  94. package/dist/db/repositories/code-module.repository.d.ts +19 -0
  95. package/dist/db/repositories/code-module.repository.js +64 -0
  96. package/dist/db/repositories/code-module.repository.js.map +1 -0
  97. package/dist/db/repositories/error.repository.d.ts +20 -0
  98. package/dist/db/repositories/error.repository.js +134 -0
  99. package/dist/db/repositories/error.repository.js.map +1 -0
  100. package/dist/db/repositories/insight.repository.d.ts +18 -0
  101. package/dist/db/repositories/insight.repository.js +57 -0
  102. package/dist/db/repositories/insight.repository.js.map +1 -0
  103. package/dist/db/repositories/notification.repository.d.ts +24 -0
  104. package/dist/db/repositories/notification.repository.js +40 -0
  105. package/dist/db/repositories/notification.repository.js.map +1 -0
  106. package/dist/db/repositories/project.repository.d.ts +25 -0
  107. package/dist/db/repositories/project.repository.js +72 -0
  108. package/dist/db/repositories/project.repository.js.map +1 -0
  109. package/dist/db/repositories/rule.repository.d.ts +31 -0
  110. package/dist/db/repositories/rule.repository.js +81 -0
  111. package/dist/db/repositories/rule.repository.js.map +1 -0
  112. package/dist/db/repositories/solution.repository.d.ts +27 -0
  113. package/dist/db/repositories/solution.repository.js +132 -0
  114. package/dist/db/repositories/solution.repository.js.map +1 -0
  115. package/dist/db/repositories/synapse.repository.d.ts +25 -0
  116. package/dist/db/repositories/synapse.repository.js +115 -0
  117. package/dist/db/repositories/synapse.repository.js.map +1 -0
  118. package/dist/db/repositories/terminal.repository.d.ts +27 -0
  119. package/dist/db/repositories/terminal.repository.js +78 -0
  120. package/dist/db/repositories/terminal.repository.js.map +1 -0
  121. package/dist/hooks/post-tool-use.d.ts +2 -0
  122. package/dist/hooks/post-tool-use.js +77 -0
  123. package/dist/hooks/post-tool-use.js.map +1 -0
  124. package/dist/hooks/post-write.d.ts +2 -0
  125. package/dist/hooks/post-write.js +102 -0
  126. package/dist/hooks/post-write.js.map +1 -0
  127. package/dist/index.d.ts +2 -0
  128. package/dist/index.js +47 -0
  129. package/dist/index.js.map +1 -0
  130. package/dist/ipc/client.d.ts +16 -0
  131. package/dist/ipc/client.js +101 -0
  132. package/dist/ipc/client.js.map +1 -0
  133. package/dist/ipc/protocol.d.ts +8 -0
  134. package/dist/ipc/protocol.js +29 -0
  135. package/dist/ipc/protocol.js.map +1 -0
  136. package/dist/ipc/router.d.ts +28 -0
  137. package/dist/ipc/router.js +70 -0
  138. package/dist/ipc/router.js.map +1 -0
  139. package/dist/ipc/server.d.ts +14 -0
  140. package/dist/ipc/server.js +98 -0
  141. package/dist/ipc/server.js.map +1 -0
  142. package/dist/learning/confidence-scorer.d.ts +13 -0
  143. package/dist/learning/confidence-scorer.js +35 -0
  144. package/dist/learning/confidence-scorer.js.map +1 -0
  145. package/dist/learning/decay.d.ts +13 -0
  146. package/dist/learning/decay.js +37 -0
  147. package/dist/learning/decay.js.map +1 -0
  148. package/dist/learning/learning-engine.d.ts +30 -0
  149. package/dist/learning/learning-engine.js +121 -0
  150. package/dist/learning/learning-engine.js.map +1 -0
  151. package/dist/learning/pattern-extractor.d.ts +16 -0
  152. package/dist/learning/pattern-extractor.js +61 -0
  153. package/dist/learning/pattern-extractor.js.map +1 -0
  154. package/dist/learning/rule-generator.d.ts +18 -0
  155. package/dist/learning/rule-generator.js +50 -0
  156. package/dist/learning/rule-generator.js.map +1 -0
  157. package/dist/matching/error-matcher.d.ts +13 -0
  158. package/dist/matching/error-matcher.js +84 -0
  159. package/dist/matching/error-matcher.js.map +1 -0
  160. package/dist/matching/fingerprint.d.ts +3 -0
  161. package/dist/matching/fingerprint.js +23 -0
  162. package/dist/matching/fingerprint.js.map +1 -0
  163. package/dist/matching/similarity.d.ts +3 -0
  164. package/dist/matching/similarity.js +53 -0
  165. package/dist/matching/similarity.js.map +1 -0
  166. package/dist/matching/tfidf.d.ts +15 -0
  167. package/dist/matching/tfidf.js +68 -0
  168. package/dist/matching/tfidf.js.map +1 -0
  169. package/dist/matching/tokenizer.d.ts +4 -0
  170. package/dist/matching/tokenizer.js +36 -0
  171. package/dist/matching/tokenizer.js.map +1 -0
  172. package/dist/mcp/auto-detect.d.ts +1 -0
  173. package/dist/mcp/auto-detect.js +81 -0
  174. package/dist/mcp/auto-detect.js.map +1 -0
  175. package/dist/mcp/server.d.ts +1 -0
  176. package/dist/mcp/server.js +68 -0
  177. package/dist/mcp/server.js.map +1 -0
  178. package/dist/mcp/tools.d.ts +3 -0
  179. package/dist/mcp/tools.js +201 -0
  180. package/dist/mcp/tools.js.map +1 -0
  181. package/dist/parsing/error-parser.d.ts +3 -0
  182. package/dist/parsing/error-parser.js +26 -0
  183. package/dist/parsing/error-parser.js.map +1 -0
  184. package/dist/parsing/parsers/compiler.d.ts +2 -0
  185. package/dist/parsing/parsers/compiler.js +83 -0
  186. package/dist/parsing/parsers/compiler.js.map +1 -0
  187. package/dist/parsing/parsers/generic.d.ts +2 -0
  188. package/dist/parsing/parsers/generic.js +23 -0
  189. package/dist/parsing/parsers/generic.js.map +1 -0
  190. package/dist/parsing/parsers/go.d.ts +2 -0
  191. package/dist/parsing/parsers/go.js +85 -0
  192. package/dist/parsing/parsers/go.js.map +1 -0
  193. package/dist/parsing/parsers/node.d.ts +2 -0
  194. package/dist/parsing/parsers/node.js +61 -0
  195. package/dist/parsing/parsers/node.js.map +1 -0
  196. package/dist/parsing/parsers/python.d.ts +2 -0
  197. package/dist/parsing/parsers/python.js +50 -0
  198. package/dist/parsing/parsers/python.js.map +1 -0
  199. package/dist/parsing/parsers/rust.d.ts +2 -0
  200. package/dist/parsing/parsers/rust.js +43 -0
  201. package/dist/parsing/parsers/rust.js.map +1 -0
  202. package/dist/parsing/parsers/shell.d.ts +2 -0
  203. package/dist/parsing/parsers/shell.js +36 -0
  204. package/dist/parsing/parsers/shell.js.map +1 -0
  205. package/dist/parsing/types.d.ts +28 -0
  206. package/dist/parsing/types.js +21 -0
  207. package/dist/parsing/types.js.map +1 -0
  208. package/dist/research/gap-analyzer.d.ts +23 -0
  209. package/dist/research/gap-analyzer.js +119 -0
  210. package/dist/research/gap-analyzer.js.map +1 -0
  211. package/dist/research/insight-generator.d.ts +23 -0
  212. package/dist/research/insight-generator.js +107 -0
  213. package/dist/research/insight-generator.js.map +1 -0
  214. package/dist/research/research-engine.d.ts +31 -0
  215. package/dist/research/research-engine.js +97 -0
  216. package/dist/research/research-engine.js.map +1 -0
  217. package/dist/research/synergy-detector.d.ts +24 -0
  218. package/dist/research/synergy-detector.js +109 -0
  219. package/dist/research/synergy-detector.js.map +1 -0
  220. package/dist/research/template-extractor.d.ts +18 -0
  221. package/dist/research/template-extractor.js +116 -0
  222. package/dist/research/template-extractor.js.map +1 -0
  223. package/dist/research/trend-analyzer.d.ts +20 -0
  224. package/dist/research/trend-analyzer.js +111 -0
  225. package/dist/research/trend-analyzer.js.map +1 -0
  226. package/dist/services/analytics.service.d.ts +52 -0
  227. package/dist/services/analytics.service.js +59 -0
  228. package/dist/services/analytics.service.js.map +1 -0
  229. package/dist/services/code.service.d.ts +39 -0
  230. package/dist/services/code.service.js +98 -0
  231. package/dist/services/code.service.js.map +1 -0
  232. package/dist/services/error.service.d.ts +35 -0
  233. package/dist/services/error.service.js +118 -0
  234. package/dist/services/error.service.js.map +1 -0
  235. package/dist/services/notification.service.d.ts +17 -0
  236. package/dist/services/notification.service.js +29 -0
  237. package/dist/services/notification.service.js.map +1 -0
  238. package/dist/services/prevention.service.d.ts +35 -0
  239. package/dist/services/prevention.service.js +82 -0
  240. package/dist/services/prevention.service.js.map +1 -0
  241. package/dist/services/research.service.d.ts +35 -0
  242. package/dist/services/research.service.js +60 -0
  243. package/dist/services/research.service.js.map +1 -0
  244. package/dist/services/solution.service.d.ts +30 -0
  245. package/dist/services/solution.service.js +73 -0
  246. package/dist/services/solution.service.js.map +1 -0
  247. package/dist/services/synapse.service.d.ts +30 -0
  248. package/dist/services/synapse.service.js +25 -0
  249. package/dist/services/synapse.service.js.map +1 -0
  250. package/dist/services/terminal.service.d.ts +20 -0
  251. package/dist/services/terminal.service.js +66 -0
  252. package/dist/services/terminal.service.js.map +1 -0
  253. package/dist/synapses/activation.d.ts +13 -0
  254. package/dist/synapses/activation.js +50 -0
  255. package/dist/synapses/activation.js.map +1 -0
  256. package/dist/synapses/decay.d.ts +11 -0
  257. package/dist/synapses/decay.js +27 -0
  258. package/dist/synapses/decay.js.map +1 -0
  259. package/dist/synapses/hebbian.d.ts +13 -0
  260. package/dist/synapses/hebbian.js +36 -0
  261. package/dist/synapses/hebbian.js.map +1 -0
  262. package/dist/synapses/pathfinder.d.ts +14 -0
  263. package/dist/synapses/pathfinder.js +50 -0
  264. package/dist/synapses/pathfinder.js.map +1 -0
  265. package/dist/synapses/synapse-manager.d.ts +30 -0
  266. package/dist/synapses/synapse-manager.js +72 -0
  267. package/dist/synapses/synapse-manager.js.map +1 -0
  268. package/dist/types/code.types.d.ts +47 -0
  269. package/dist/types/code.types.js +2 -0
  270. package/dist/types/code.types.js.map +1 -0
  271. package/dist/types/config.types.d.ts +70 -0
  272. package/dist/types/config.types.js +2 -0
  273. package/dist/types/config.types.js.map +1 -0
  274. package/dist/types/error.types.d.ts +60 -0
  275. package/dist/types/error.types.js +2 -0
  276. package/dist/types/error.types.js.map +1 -0
  277. package/dist/types/ipc.types.d.ts +11 -0
  278. package/dist/types/ipc.types.js +2 -0
  279. package/dist/types/ipc.types.js.map +1 -0
  280. package/dist/types/mcp.types.d.ts +46 -0
  281. package/dist/types/mcp.types.js +2 -0
  282. package/dist/types/mcp.types.js.map +1 -0
  283. package/dist/types/research.types.d.ts +25 -0
  284. package/dist/types/research.types.js +2 -0
  285. package/dist/types/research.types.js.map +1 -0
  286. package/dist/types/solution.types.d.ts +28 -0
  287. package/dist/types/solution.types.js +2 -0
  288. package/dist/types/solution.types.js.map +1 -0
  289. package/dist/types/synapse.types.d.ts +37 -0
  290. package/dist/types/synapse.types.js +2 -0
  291. package/dist/types/synapse.types.js.map +1 -0
  292. package/dist/utils/events.d.ts +59 -0
  293. package/dist/utils/events.js +23 -0
  294. package/dist/utils/events.js.map +1 -0
  295. package/dist/utils/hash.d.ts +1 -0
  296. package/dist/utils/hash.js +5 -0
  297. package/dist/utils/hash.js.map +1 -0
  298. package/dist/utils/logger.d.ts +8 -0
  299. package/dist/utils/logger.js +39 -0
  300. package/dist/utils/logger.js.map +1 -0
  301. package/dist/utils/paths.d.ts +3 -0
  302. package/dist/utils/paths.js +18 -0
  303. package/dist/utils/paths.js.map +1 -0
  304. package/package.json +43 -0
  305. package/src/brain.ts +220 -0
  306. package/src/cli/commands/dashboard.ts +495 -0
  307. package/src/cli/commands/export.ts +27 -0
  308. package/src/cli/commands/import.ts +190 -0
  309. package/src/cli/commands/insights.ts +33 -0
  310. package/src/cli/commands/modules.ts +30 -0
  311. package/src/cli/commands/network.ts +61 -0
  312. package/src/cli/commands/query.ts +43 -0
  313. package/src/cli/commands/start.ts +59 -0
  314. package/src/cli/commands/status.ts +69 -0
  315. package/src/cli/commands/stop.ts +33 -0
  316. package/src/cli/ipc-helper.ts +21 -0
  317. package/src/code/analyzer.ts +77 -0
  318. package/src/code/fingerprint.ts +87 -0
  319. package/src/code/matcher.ts +64 -0
  320. package/src/code/parsers/generic.ts +29 -0
  321. package/src/code/parsers/python.ts +54 -0
  322. package/src/code/parsers/typescript.ts +65 -0
  323. package/src/code/registry.ts +60 -0
  324. package/src/code/scorer.ts +108 -0
  325. package/src/config.ts +111 -0
  326. package/src/db/connection.ts +22 -0
  327. package/src/db/migrations/001_core_schema.ts +120 -0
  328. package/src/db/migrations/002_learning_schema.ts +38 -0
  329. package/src/db/migrations/003_code_schema.ts +53 -0
  330. package/src/db/migrations/004_synapses_schema.ts +57 -0
  331. package/src/db/migrations/005_fts_indexes.ts +78 -0
  332. package/src/db/migrations/006_synapses_phase3.ts +17 -0
  333. package/src/db/migrations/index.ts +64 -0
  334. package/src/db/repositories/antipattern.repository.ts +66 -0
  335. package/src/db/repositories/code-module.repository.ts +80 -0
  336. package/src/db/repositories/error.repository.ts +149 -0
  337. package/src/db/repositories/insight.repository.ts +78 -0
  338. package/src/db/repositories/notification.repository.ts +66 -0
  339. package/src/db/repositories/project.repository.ts +93 -0
  340. package/src/db/repositories/rule.repository.ts +108 -0
  341. package/src/db/repositories/solution.repository.ts +154 -0
  342. package/src/db/repositories/synapse.repository.ts +153 -0
  343. package/src/db/repositories/terminal.repository.ts +101 -0
  344. package/src/hooks/post-tool-use.ts +90 -0
  345. package/src/hooks/post-write.ts +117 -0
  346. package/src/index.ts +53 -0
  347. package/src/ipc/client.ts +118 -0
  348. package/src/ipc/protocol.ts +35 -0
  349. package/src/ipc/router.ts +106 -0
  350. package/src/ipc/server.ts +110 -0
  351. package/src/learning/confidence-scorer.ts +47 -0
  352. package/src/learning/decay.ts +46 -0
  353. package/src/learning/learning-engine.ts +162 -0
  354. package/src/learning/pattern-extractor.ts +90 -0
  355. package/src/learning/rule-generator.ts +74 -0
  356. package/src/main.rs:10:5 +0 -0
  357. package/src/matching/error-matcher.ts +115 -0
  358. package/src/matching/fingerprint.ts +29 -0
  359. package/src/matching/similarity.ts +61 -0
  360. package/src/matching/tfidf.ts +74 -0
  361. package/src/matching/tokenizer.ts +41 -0
  362. package/src/mcp/auto-detect.ts +93 -0
  363. package/src/mcp/server.ts +73 -0
  364. package/src/mcp/tools.ts +290 -0
  365. package/src/parsing/error-parser.ts +28 -0
  366. package/src/parsing/parsers/compiler.ts +93 -0
  367. package/src/parsing/parsers/generic.ts +28 -0
  368. package/src/parsing/parsers/go.ts +97 -0
  369. package/src/parsing/parsers/node.ts +69 -0
  370. package/src/parsing/parsers/python.ts +62 -0
  371. package/src/parsing/parsers/rust.ts +50 -0
  372. package/src/parsing/parsers/shell.ts +42 -0
  373. package/src/parsing/types.ts +47 -0
  374. package/src/research/gap-analyzer.ts +135 -0
  375. package/src/research/insight-generator.ts +123 -0
  376. package/src/research/research-engine.ts +116 -0
  377. package/src/research/synergy-detector.ts +126 -0
  378. package/src/research/template-extractor.ts +130 -0
  379. package/src/research/trend-analyzer.ts +127 -0
  380. package/src/services/analytics.service.ts +87 -0
  381. package/src/services/code.service.ts +140 -0
  382. package/src/services/error.service.ts +164 -0
  383. package/src/services/notification.service.ts +41 -0
  384. package/src/services/prevention.service.ts +119 -0
  385. package/src/services/research.service.ts +93 -0
  386. package/src/services/solution.service.ts +116 -0
  387. package/src/services/synapse.service.ts +59 -0
  388. package/src/services/terminal.service.ts +81 -0
  389. package/src/synapses/activation.ts +80 -0
  390. package/src/synapses/decay.ts +38 -0
  391. package/src/synapses/hebbian.ts +69 -0
  392. package/src/synapses/pathfinder.ts +81 -0
  393. package/src/synapses/synapse-manager.ts +109 -0
  394. package/src/types/code.types.ts +52 -0
  395. package/src/types/config.types.ts +79 -0
  396. package/src/types/error.types.ts +67 -0
  397. package/src/types/ipc.types.ts +8 -0
  398. package/src/types/mcp.types.ts +53 -0
  399. package/src/types/research.types.ts +28 -0
  400. package/src/types/solution.types.ts +30 -0
  401. package/src/types/synapse.types.ts +49 -0
  402. package/src/utils/events.ts +45 -0
  403. package/src/utils/hash.ts +5 -0
  404. package/src/utils/logger.ts +48 -0
  405. package/src/utils/paths.ts +19 -0
  406. package/tests/fixtures/code-modules/modules.ts +83 -0
  407. package/tests/fixtures/errors/go.ts +9 -0
  408. package/tests/fixtures/errors/node.ts +24 -0
  409. package/tests/fixtures/errors/python.ts +21 -0
  410. package/tests/fixtures/errors/rust.ts +25 -0
  411. package/tests/fixtures/errors/shell.ts +15 -0
  412. package/tests/fixtures/solutions/solutions.ts +27 -0
  413. package/tests/helpers/setup-db.ts +52 -0
  414. package/tests/integration/code-flow.test.ts +86 -0
  415. package/tests/integration/error-flow.test.ts +83 -0
  416. package/tests/integration/ipc-flow.test.ts +166 -0
  417. package/tests/integration/learning-cycle.test.ts +82 -0
  418. package/tests/integration/synapse-flow.test.ts +117 -0
  419. package/tests/unit/code/analyzer.test.ts +58 -0
  420. package/tests/unit/code/fingerprint.test.ts +51 -0
  421. package/tests/unit/code/scorer.test.ts +55 -0
  422. package/tests/unit/learning/confidence-scorer.test.ts +60 -0
  423. package/tests/unit/learning/decay.test.ts +45 -0
  424. package/tests/unit/learning/pattern-extractor.test.ts +50 -0
  425. package/tests/unit/matching/error-matcher.test.ts +69 -0
  426. package/tests/unit/matching/fingerprint.test.ts +47 -0
  427. package/tests/unit/matching/similarity.test.ts +65 -0
  428. package/tests/unit/matching/tfidf.test.ts +71 -0
  429. package/tests/unit/matching/tokenizer.test.ts +83 -0
  430. package/tests/unit/parsing/parsers.test.ts +113 -0
  431. package/tests/unit/research/gap-analyzer.test.ts +45 -0
  432. package/tests/unit/research/trend-analyzer.test.ts +45 -0
  433. package/tests/unit/synapses/activation.test.ts +80 -0
  434. package/tests/unit/synapses/decay.test.ts +27 -0
  435. package/tests/unit/synapses/hebbian.test.ts +96 -0
  436. package/tests/unit/synapses/pathfinder.test.ts +72 -0
  437. package/tsconfig.json +18 -0
package/BRAIN_PLAN.md ADDED
@@ -0,0 +1,3324 @@
1
+ # Brain - Lernfähiges Wissens-System für Multi-Terminal Claude
2
+
3
+ ## Vision
4
+
5
+ Brain ist ein intelligentes Speicher-System das als Daemon-Prozess läuft und mehrere Claude-Terminal-Sessions verbindet. Es besteht aus vier Systemen:
6
+
7
+ 1. **Error Brain** - Erfasst automatisch Fehler, speichert Lösungen, lernt Muster und warnt Terminals bevor sie bekannte Fehler wiederholen.
8
+ 2. **Code Brain** - Modulare Code-Bibliothek die projektübergreifend wiederverwendbaren Code trackt, ähnlichen Code erkennt und bei neuen Projekten passende Module vorschlägt.
9
+ 3. **Synapsen-Netzwerk** - Verbindet ALLES miteinander: Errors, Solutions, Code-Module, Patterns, Projekte. Jede Synapse hat ein Gewicht das stärker wird je öfter die Verbindung bestätigt wird - wie echte Neuronen. Oft benutzte Pfade werden stärker, unbenutzte verblassen.
10
+ 4. **Research Brain** - Meta-Learning Layer der über allen Daten und Synapsen sitzt. Analysiert das Gesamtnetzwerk, erkennt höhere Muster, schlägt Verbesserungen und neue Projekt-Ideen vor. Forscht autonom in den gesammelten Daten.
11
+
12
+ Das Synapsen-Netzwerk ist das Bindegewebe: Error Brain und Code Brain speichern Wissen, Synapsen verbinden es, und das Research Brain zieht Schlüsse daraus.
13
+
14
+ ## Architektur-Übersicht
15
+
16
+ ```
17
+ ┌─────────────────────────────────────────────────────────────────┐
18
+ │ Claude Sessions │
19
+ │ │
20
+ │ Terminal 1 Terminal 2 Terminal 3 Terminal 4│
21
+ │ (Projekt A) (Projekt B) (Projekt C) (Proj D) │
22
+ │ │ │ │ │ │
23
+ │ │ ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐ │ │
24
+ │ ├──┤MCP Server├ ├──┤MCP Server├ ├──┤MCP Server├ │ │
25
+ │ │ │ (stdio) │ │ │ (stdio) │ │ │ (stdio) │ │ │
26
+ │ │ └────┬─────┘ │ └────┬─────┘ │ └────┬─────┘ │ │
27
+ │ │ │ │ │ │ │ │ │
28
+ │ ┌───┴──┐ │ ┌───┴──┐ │ ┌───┴──┐ │ ┌───┴──┐ │
29
+ │ │Hooks │ │ │Hooks │ │ │Hooks │ │ │Hooks │ │
30
+ │ │(auto)│ │ │(auto)│ │ │(auto)│ │ │(auto)│ │
31
+ │ └───┬──┘ │ └───┬──┘ │ └───┬──┘ │ └───┬──┘ │
32
+ └──────┼───────┼─────────┼───────┼─────────┼───────┼─────────┼────┘
33
+ │ │ │ │ │ │ │
34
+ └───────┴─────────┴───────┴─────────┴───────┴─────────┘
35
+
36
+ ┌─────────┴─────────┐
37
+ │ Named Pipe IPC │
38
+ │ \\.\pipe\brain-ipc │
39
+ └─────────┬─────────┘
40
+
41
+ ┌──────────────┴──────────────┐
42
+ │ Brain Daemon │
43
+ │ │
44
+ │ ┌────────────────────────┐ │
45
+ │ │ BrainCore │ │
46
+ │ │ (Orchestrierung) │ │
47
+ │ └──────────┬─────────────┘ │
48
+ │ │ │
49
+ │ ┌──────────┴─────────────┐ │
50
+ │ │ Services │ │
51
+ │ │ error, solution, │ │
52
+ │ │ code, prevention, │ │
53
+ │ │ synapse, terminal │ │
54
+ │ └──────────┬─────────────┘ │
55
+ │ │ │
56
+ │ ┌──────────┼─────────────┐ │
57
+ │ │ │ │ │
58
+ │ │ ┌───────┴────────┐ │ │
59
+ │ │ │Learning Engine │ │ │
60
+ │ │ │(15 min cycles) │ │ │
61
+ │ │ └───────┬────────┘ │ │
62
+ │ │ │ │ │
63
+ │ │ ┌───────┴────────┐ │ │
64
+ │ │ │Research Engine │ │ │
65
+ │ │ │ (60 min cycles)│ │ │
66
+ │ │ └───────┬────────┘ │ │
67
+ │ │ │ │ │
68
+ │ └──────────┼─────────────┘ │
69
+ │ │ │
70
+ │ ┌──────────┴─────────────┐ │
71
+ │ │ ┌──────────────────┐ │ │
72
+ │ │ │ Synapse Network │ │ │
73
+ │ │ │ (gewichteter │ │ │
74
+ │ │ │ Knowledge Graph)│ │ │
75
+ │ │ └────────┬─────────┘ │ │
76
+ │ │ │ │ │
77
+ │ │ ┌────────┴─────────┐ │ │
78
+ │ │ │ SQLite+WAL+FTS5 │ │ │
79
+ │ │ │ brain.db │ │ │
80
+ │ │ └─────────────────┘ │ │
81
+ │ └────────────────────────┘ │
82
+ └──────────────────────────────┘
83
+ ```
84
+
85
+ ### Integrations-Strategie
86
+
87
+ **MCP Server** (pro Claude-Session, stdio): Claude kann Brain-Tools direkt aufrufen - Fehler melden, Lösungen suchen, Code-Module finden. Der MCP Server ist ein Thin Client der via Named Pipe mit dem Daemon kommuniziert.
88
+
89
+ **Claude Code Hooks** (automatisch, unsichtbar): PostToolUse-Hook auf Bash erkennt Fehler automatisch aus der Tool-Ausgabe (Exit-Code != 0, Stack-Traces, Error-Patterns) und sendet sie an den Daemon. Der User muss nichts manuell melden.
90
+
91
+ **CLAUDE.md Integration**: Jedes Projekt bekommt Instruktionen die Claude anweisen, bei Fehlern Brain zu konsultieren und bei erfolgreich gelösten Fehlern die Lösung zu melden.
92
+
93
+ ## Technologie-Stack
94
+
95
+ - **TypeScript** mit Node.js v20+
96
+ - **better-sqlite3** (synchron, 2-10x schneller als async sqlite3, WAL-Modus für concurrent reads)
97
+ - **Named Pipes** (Windows `\\.\pipe\brain-ipc`) / Unix Sockets (`/tmp/brain.sock`) für IPC
98
+ - **FTS5** für Volltext-Suche in Fehlern, Lösungen und Code-Modulen
99
+ - **@modelcontextprotocol/sdk** für MCP Server
100
+ - **commander** für CLI
101
+ - **vitest** für Tests
102
+ - **winston** für File-Logging
103
+
104
+ ## Projektstruktur
105
+
106
+ ```
107
+ brain/
108
+ ├── package.json
109
+ ├── tsconfig.json
110
+ ├── .gitignore
111
+ ├── src/
112
+ │ ├── index.ts # CLI Einstiegspunkt (commander)
113
+ │ ├── brain.ts # BrainCore - zentrale Orchestrierung
114
+ │ ├── config.ts # Konfiguration mit Defaults
115
+ │ │
116
+ │ ├── db/
117
+ │ │ ├── connection.ts # SQLite Verbindung (WAL, Pragmas)
118
+ │ │ ├── migrations/
119
+ │ │ │ ├── 001_core_schema.ts # projects, terminals, errors, solutions
120
+ │ │ │ ├── 002_learning_schema.ts # rules, error_chains, antipatterns
121
+ │ │ │ ├── 003_code_schema.ts # code_modules, module_usages, module_similarities
122
+ │ │ │ ├── 004_synapses_schema.ts # synapses, insights
123
+ │ │ │ ├── 005_fts_indexes.ts # FTS5 Tabellen + Sync-Trigger
124
+ │ │ │ └── index.ts # Migration-Runner
125
+ │ │ └── repositories/
126
+ │ │ ├── error.repository.ts # Jedes Repo compiled eigene Prepared Statements
127
+ │ │ ├── solution.repository.ts
128
+ │ │ ├── rule.repository.ts
129
+ │ │ ├── terminal.repository.ts
130
+ │ │ ├── project.repository.ts
131
+ │ │ ├── notification.repository.ts
132
+ │ │ ├── code-module.repository.ts
133
+ │ │ ├── antipattern.repository.ts
134
+ │ │ ├── synapse.repository.ts
135
+ │ │ └── insight.repository.ts
136
+ │ │
137
+ │ ├── matching/
138
+ │ │ ├── similarity.ts # Levenshtein, Cosine, Jaccard
139
+ │ │ ├── error-matcher.ts # Multi-Signal Error Matching Engine
140
+ │ │ ├── fingerprint.ts # Strukturelles Error-Hashing
141
+ │ │ ├── tokenizer.ts # Text-Tokenisierung
142
+ │ │ └── tfidf.ts # TF-IDF Index (inkrementell)
143
+ │ │
144
+ │ ├── parsing/
145
+ │ │ ├── types.ts # Parser-Interfaces
146
+ │ │ ├── error-parser.ts # Registry-basierter Dispatcher
147
+ │ │ └── parsers/
148
+ │ │ ├── node.ts # Node.js/TypeScript Errors
149
+ │ │ ├── python.ts # Python Tracebacks
150
+ │ │ ├── rust.ts # Rust Compiler Errors
151
+ │ │ ├── go.ts # Go Errors
152
+ │ │ ├── shell.ts # Shell/Bash Errors (exit codes, command not found)
153
+ │ │ ├── compiler.ts # Generische Compiler Errors (gcc, javac, etc.)
154
+ │ │ └── generic.ts # Regex-basierter Fallback
155
+ │ │
156
+ │ ├── code/
157
+ │ │ ├── analyzer.ts # Code-Analyse (Exports, Purity, Cohesion)
158
+ │ │ ├── fingerprint.ts # Strukturelles Code-Hashing
159
+ │ │ ├── matcher.ts # Ähnlichen Code finden
160
+ │ │ ├── registry.ts # Module registrieren/verwalten
161
+ │ │ ├── scorer.ts # Reusability-Scoring
162
+ │ │ └── parsers/
163
+ │ │ ├── typescript.ts # TS/JS Export/Import Extraction
164
+ │ │ ├── python.ts # Python def/class/import Extraction
165
+ │ │ └── generic.ts # Regex-basierter Fallback
166
+ │ │
167
+ │ ├── learning/
168
+ │ │ ├── learning-engine.ts # Lern-Zyklus Orchestrierung
169
+ │ │ ├── pattern-extractor.ts # Centroid-basiertes Clustering
170
+ │ │ ├── rule-generator.ts # Regeln aus Mustern generieren
171
+ │ │ ├── confidence-scorer.ts # Wilson Score Intervall
172
+ │ │ └── decay.ts # Zeitbasierte Relevanz
173
+ │ │
174
+ │ ├── synapses/
175
+ │ │ ├── synapse-manager.ts # Synapsen erstellen, stärken, schwächen
176
+ │ │ ├── hebbian.ts # Hebbsches Lernen (fire together → wire together)
177
+ │ │ ├── pathfinder.ts # Multi-Hop-Pfade durch das Netzwerk finden
178
+ │ │ ├── activation.ts # Spreading Activation Algorithmus
179
+ │ │ └── decay.ts # Synaptische Abschwächung bei Nicht-Nutzung
180
+ │ │
181
+ │ ├── research/
182
+ │ │ ├── research-engine.ts # Forschungs-Zyklus Orchestrierung
183
+ │ │ ├── trend-analyzer.ts # Trends erkennen (was wird besser/schlechter)
184
+ │ │ ├── gap-analyzer.ts # Lücken finden (wiederkehrende ungelöste Probleme)
185
+ │ │ ├── synergy-detector.ts # Synergien zwischen Projekten erkennen
186
+ │ │ ├── template-extractor.ts # Wiederholte Patterns zu Templates generalisieren
187
+ │ │ └── insight-generator.ts # Insights generieren und priorisieren
188
+ │ │
189
+ │ ├── ipc/
190
+ │ │ ├── server.ts # Named Pipe IPC Server
191
+ │ │ ├── client.ts # Client für MCP Server → Daemon
192
+ │ │ ├── protocol.ts # Length-prefixed JSON Framing
193
+ │ │ └── router.ts # Methoden-Routing
194
+ │ │
195
+ │ ├── mcp/
196
+ │ │ ├── server.ts # MCP Server Entry (stdio Transport)
197
+ │ │ ├── tools.ts # Tool-Definitionen für Claude
198
+ │ │ └── auto-detect.ts # Error-Pattern-Erkennung aus Output
199
+ │ │
200
+ │ ├── services/
201
+ │ │ ├── error.service.ts
202
+ │ │ ├── solution.service.ts
203
+ │ │ ├── terminal.service.ts
204
+ │ │ ├── prevention.service.ts
205
+ │ │ ├── code.service.ts
206
+ │ │ ├── synapse.service.ts
207
+ │ │ ├── research.service.ts
208
+ │ │ ├── notification.service.ts
209
+ │ │ └── analytics.service.ts
210
+ │ │
211
+ │ ├── cli/
212
+ │ │ └── commands/
213
+ │ │ ├── start.ts # brain start - Daemon starten
214
+ │ │ ├── stop.ts # brain stop - Daemon stoppen
215
+ │ │ ├── status.ts # brain status - Textbasierter Status
216
+ │ │ ├── query.ts # brain query "error" - Fehler suchen
217
+ │ │ ├── modules.ts # brain modules - Code-Module auflisten
218
+ │ │ └── export.ts # brain export - Daten exportieren
219
+ │ │
220
+ │ ├── hooks/
221
+ │ │ ├── post-tool-use.ts # Hook-Script für automatische Error-Erkennung
222
+ │ │ └── post-write.ts # Hook-Script für automatische Code-Analyse
223
+ │ │
224
+ │ ├── types/
225
+ │ │ ├── error.types.ts
226
+ │ │ ├── solution.types.ts
227
+ │ │ ├── code.types.ts
228
+ │ │ ├── ipc.types.ts
229
+ │ │ ├── mcp.types.ts
230
+ │ │ └── config.types.ts
231
+ │ │
232
+ │ └── utils/
233
+ │ ├── logger.ts # Winston File-Logger
234
+ │ ├── hash.ts # SHA-256 Hashing
235
+ │ ├── paths.ts # Pfad-Normalisierung
236
+ │ └── events.ts # Typisierter EventBus
237
+
238
+ ├── tests/
239
+ │ ├── unit/
240
+ │ │ ├── matching/
241
+ │ │ ├── parsing/
242
+ │ │ ├── code/
243
+ │ │ └── learning/
244
+ │ ├── integration/
245
+ │ │ ├── error-flow.test.ts # Error → Match → Solution → Learn
246
+ │ │ ├── code-flow.test.ts # Code → Analyze → Register → Match
247
+ │ │ └── ipc-flow.test.ts # MCP → IPC → Daemon → Response
248
+ │ └── fixtures/
249
+ │ ├── errors/ # Beispiel-Errors pro Sprache
250
+ │ ├── solutions/
251
+ │ └── code-modules/ # Beispiel-Code für Matching-Tests
252
+
253
+ └── data/ # Runtime (gitignored)
254
+ ├── brain.db
255
+ └── brain.log
256
+ ```
257
+
258
+ ## Datenbank-Schema
259
+
260
+ ### projects
261
+ ```sql
262
+ CREATE TABLE projects (
263
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
264
+ name TEXT NOT NULL UNIQUE,
265
+ root_path TEXT NOT NULL,
266
+ languages TEXT, -- JSON Array: ["typescript", "python"]
267
+ frameworks TEXT, -- JSON Array: ["express", "react"]
268
+ description TEXT, -- Kurzbeschreibung des Projekts
269
+ error_count INTEGER NOT NULL DEFAULT 0,
270
+ solution_count INTEGER NOT NULL DEFAULT 0,
271
+ module_count INTEGER NOT NULL DEFAULT 0,
272
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
273
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
274
+ );
275
+ ```
276
+
277
+ ### terminals
278
+ ```sql
279
+ CREATE TABLE terminals (
280
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
281
+ uuid TEXT NOT NULL UNIQUE,
282
+ pid INTEGER,
283
+ project_id INTEGER REFERENCES projects(id),
284
+ status TEXT NOT NULL DEFAULT 'connected'
285
+ CHECK(status IN ('connected', 'disconnected', 'stale')),
286
+ connected_at TEXT NOT NULL DEFAULT (datetime('now')),
287
+ last_heartbeat TEXT NOT NULL DEFAULT (datetime('now')),
288
+ metadata TEXT -- JSON: Shell, OS, etc.
289
+ );
290
+ CREATE INDEX idx_terminals_status ON terminals(status);
291
+ ```
292
+
293
+ ### errors
294
+ ```sql
295
+ CREATE TABLE errors (
296
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
297
+ fingerprint TEXT NOT NULL,
298
+ error_type TEXT NOT NULL, -- "TypeError", "ENOENT", "SyntaxError", etc.
299
+ message TEXT NOT NULL,
300
+ message_template TEXT, -- Templatisierte Version
301
+ stack_trace TEXT,
302
+ source_file TEXT,
303
+ source_line INTEGER,
304
+
305
+ -- Was wir wirklich haben (statt generischem "context" JSON)
306
+ raw_output TEXT, -- Tatsächlicher Terminal-Output
307
+ command TEXT, -- Befehl der den Error auslöste
308
+ working_directory TEXT,
309
+ task_context TEXT, -- Was der User versuchte zu tun
310
+
311
+ -- Auto-Labels statt separater Tag-Tabellen
312
+ labels TEXT, -- JSON Array: ["typescript", "import", "node_modules"]
313
+
314
+ project_id INTEGER REFERENCES projects(id),
315
+ terminal_id INTEGER REFERENCES terminals(id),
316
+ occurrence_count INTEGER NOT NULL DEFAULT 1,
317
+ first_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
318
+ last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
319
+ resolved INTEGER NOT NULL DEFAULT 0
320
+ );
321
+ CREATE INDEX idx_errors_fingerprint ON errors(fingerprint);
322
+ CREATE INDEX idx_errors_type ON errors(error_type);
323
+ CREATE INDEX idx_errors_project ON errors(project_id);
324
+ CREATE INDEX idx_errors_resolved ON errors(resolved);
325
+ ```
326
+
327
+ ### stack_frames
328
+ ```sql
329
+ CREATE TABLE stack_frames (
330
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
331
+ error_id INTEGER NOT NULL REFERENCES errors(id) ON DELETE CASCADE,
332
+ position INTEGER NOT NULL,
333
+ function_name TEXT,
334
+ file_path TEXT,
335
+ line_number INTEGER,
336
+ column_number INTEGER,
337
+ normalized TEXT -- Pfad/Zeile normalisiert für Matching
338
+ );
339
+ CREATE INDEX idx_stack_frames_error ON stack_frames(error_id);
340
+ ```
341
+
342
+ ### solutions
343
+ ```sql
344
+ CREATE TABLE solutions (
345
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
346
+ title TEXT NOT NULL,
347
+ description TEXT,
348
+ labels TEXT, -- JSON Array: ["config", "tsconfig", "path-mapping"]
349
+ steps TEXT, -- JSON Array von Schritten
350
+ code_before TEXT,
351
+ code_after TEXT,
352
+ diff TEXT,
353
+ confidence_score REAL NOT NULL DEFAULT 0.0,
354
+ success_count INTEGER NOT NULL DEFAULT 0,
355
+ failure_count INTEGER NOT NULL DEFAULT 0,
356
+ project_id INTEGER REFERENCES projects(id),
357
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
358
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
359
+ );
360
+ ```
361
+
362
+ ### error_solutions
363
+ ```sql
364
+ CREATE TABLE error_solutions (
365
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
366
+ error_id INTEGER NOT NULL REFERENCES errors(id) ON DELETE CASCADE,
367
+ solution_id INTEGER NOT NULL REFERENCES solutions(id) ON DELETE CASCADE,
368
+ outcome TEXT CHECK(outcome IN ('success', 'failure', 'partial', 'pending')),
369
+ applied_at TEXT NOT NULL DEFAULT (datetime('now')),
370
+ applied_by_terminal INTEGER REFERENCES terminals(id),
371
+ notes TEXT,
372
+ UNIQUE(error_id, solution_id, applied_at)
373
+ );
374
+ ```
375
+
376
+ ### solution_attempts (was NICHT funktioniert hat)
377
+ ```sql
378
+ CREATE TABLE solution_attempts (
379
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
380
+ error_id INTEGER NOT NULL REFERENCES errors(id) ON DELETE CASCADE,
381
+ description TEXT NOT NULL,
382
+ outcome TEXT NOT NULL CHECK(outcome IN ('failure', 'partial')),
383
+ reason TEXT, -- Warum hat es nicht funktioniert
384
+ attempted_at TEXT NOT NULL DEFAULT (datetime('now')),
385
+ terminal_id INTEGER REFERENCES terminals(id)
386
+ );
387
+ ```
388
+
389
+ ### error_chains (Fehler A verursacht Fehler B)
390
+ ```sql
391
+ CREATE TABLE error_chains (
392
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
393
+ session_id TEXT NOT NULL, -- Gruppiert Fehler einer Session
394
+ error_id INTEGER NOT NULL REFERENCES errors(id) ON DELETE CASCADE,
395
+ position INTEGER NOT NULL, -- Reihenfolge in der Chain
396
+ time_delta_ms INTEGER, -- Zeit seit vorigem Fehler in der Chain
397
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
398
+ );
399
+ CREATE INDEX idx_error_chains_session ON error_chains(session_id);
400
+ CREATE INDEX idx_error_chains_error ON error_chains(error_id);
401
+ ```
402
+
403
+ ### synapses (das neuronale Netzwerk)
404
+ Verbindet ALLES miteinander. Jede Synapse hat ein Gewicht das durch Hebbsches Lernen stärker oder schwächer wird.
405
+
406
+ ```sql
407
+ CREATE TABLE synapses (
408
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
409
+
410
+ -- Source-Knoten
411
+ source_type TEXT NOT NULL CHECK(source_type IN (
412
+ 'error', 'solution', 'code_module', 'rule', 'antipattern', 'project', 'insight'
413
+ )),
414
+ source_id INTEGER NOT NULL,
415
+
416
+ -- Target-Knoten
417
+ target_type TEXT NOT NULL CHECK(target_type IN (
418
+ 'error', 'solution', 'code_module', 'rule', 'antipattern', 'project', 'insight'
419
+ )),
420
+ target_id INTEGER NOT NULL,
421
+
422
+ -- Verbindungs-Typ
423
+ synapse_type TEXT NOT NULL CHECK(synapse_type IN (
424
+ 'solves', -- Solution löst Error
425
+ 'causes', -- Error verursacht Error
426
+ 'similar_to', -- Ähnlichkeit (Error↔Error, Code↔Code)
427
+ 'uses_module', -- Solution/Project nutzt Code-Module
428
+ 'derived_from', -- Abgeleitet von (Rule aus Error, Insight aus Pattern)
429
+ 'co_occurs', -- Tritt gemeinsam auf (zeitliche Korrelation)
430
+ 'prevents', -- Rule/Antipattern verhindert Error
431
+ 'improves', -- Insight verbessert Projekt/Code
432
+ 'generalizes', -- Pattern ist Generalisierung von Einzelfällen
433
+ 'cross_project' -- Verbindung zwischen Projekten (gleicher Fehler, gleicher Code)
434
+ )),
435
+
436
+ -- Synaptisches Gewicht (Hebbsches Lernen)
437
+ weight REAL NOT NULL DEFAULT 0.1, -- Startet schwach, wird stärker
438
+ activation_count INTEGER NOT NULL DEFAULT 1, -- Wie oft wurde dieser Pfad benutzt
439
+ last_activated_at TEXT NOT NULL DEFAULT (datetime('now')),
440
+
441
+ -- Kontext
442
+ context TEXT, -- JSON: Warum diese Verbindung existiert
443
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
444
+
445
+ UNIQUE(source_type, source_id, target_type, target_id, synapse_type)
446
+ );
447
+
448
+ CREATE INDEX idx_synapses_source ON synapses(source_type, source_id);
449
+ CREATE INDEX idx_synapses_target ON synapses(target_type, target_id);
450
+ CREATE INDEX idx_synapses_type ON synapses(synapse_type);
451
+ CREATE INDEX idx_synapses_weight ON synapses(weight DESC);
452
+ ```
453
+
454
+ ### insights (Erkenntnisse des Research Brain)
455
+ ```sql
456
+ CREATE TABLE insights (
457
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
458
+
459
+ -- Klassifikation
460
+ insight_type TEXT NOT NULL CHECK(insight_type IN (
461
+ 'trend', -- "Error-Rate in Projekt A sinkt seit 2 Wochen"
462
+ 'pattern', -- "Du baust in jedem Projekt einen API-Client"
463
+ 'gap', -- "Kein Projekt hat ordentliches Error-Handling für X"
464
+ 'synergy', -- "Module A + Module B = vollständiges Auth-System"
465
+ 'optimization', -- "retry.ts aus Projekt A ist 30% effizienter als Projekt B's Version"
466
+ 'template_candidate', -- "Dieser Code-Pattern wiederholt sich - Template erstellen?"
467
+ 'project_suggestion', -- "Basierend auf deinen Modulen könntest du X bauen"
468
+ 'warning' -- "Dependency X verursacht Fehler in 3 von 4 Projekten"
469
+ )),
470
+
471
+ title TEXT NOT NULL,
472
+ description TEXT NOT NULL,
473
+ evidence TEXT NOT NULL, -- JSON: Welche Daten stützen diesen Insight
474
+ confidence REAL NOT NULL DEFAULT 0.5,
475
+
476
+ -- Aktionierbarkeit
477
+ actionable INTEGER NOT NULL DEFAULT 0, -- Hat dieser Insight eine konkrete Aktion?
478
+ suggested_action TEXT, -- JSON: Was sollte man tun
479
+ action_taken INTEGER NOT NULL DEFAULT 0, -- Wurde darauf reagiert?
480
+ action_outcome TEXT, -- Ergebnis der Aktion
481
+
482
+ -- Relevanz
483
+ affected_project_ids TEXT, -- JSON Array
484
+ priority TEXT NOT NULL DEFAULT 'medium'
485
+ CHECK(priority IN ('low', 'medium', 'high', 'critical')),
486
+
487
+ -- Lifecycle
488
+ status TEXT NOT NULL DEFAULT 'active'
489
+ CHECK(status IN ('active', 'acknowledged', 'acted_upon', 'dismissed', 'expired')),
490
+ expires_at TEXT, -- Manche Insights sind zeitgebunden
491
+
492
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
493
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
494
+ );
495
+ CREATE INDEX idx_insights_type ON insights(insight_type);
496
+ CREATE INDEX idx_insights_status ON insights(status);
497
+ CREATE INDEX idx_insights_priority ON insights(priority);
498
+ ```
499
+
500
+ ### rules
501
+ ```sql
502
+ CREATE TABLE rules (
503
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
504
+ name TEXT NOT NULL,
505
+ description TEXT,
506
+ pattern TEXT NOT NULL, -- JSON: Matching-Kriterien
507
+ action TEXT NOT NULL, -- JSON: Was tun wenn Pattern matcht
508
+ rule_type TEXT NOT NULL CHECK(rule_type IN ('prevention', 'suggestion', 'warning', 'auto_fix')),
509
+ confidence REAL NOT NULL DEFAULT 0.0,
510
+ trigger_count INTEGER NOT NULL DEFAULT 0,
511
+ success_count INTEGER NOT NULL DEFAULT 0,
512
+ rejection_count INTEGER NOT NULL DEFAULT 0,
513
+ active INTEGER NOT NULL DEFAULT 1,
514
+ source_error_ids TEXT, -- JSON Array
515
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
516
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
517
+ );
518
+ ```
519
+
520
+ ### antipatterns (explizites "Tu das NICHT")
521
+ ```sql
522
+ CREATE TABLE antipatterns (
523
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
524
+ description TEXT NOT NULL, -- "Nie X mit Y Config kombinieren"
525
+ trigger_pattern TEXT NOT NULL, -- JSON: Wann warnen
526
+ severity TEXT NOT NULL DEFAULT 'warning'
527
+ CHECK(severity IN ('info', 'warning', 'critical')),
528
+ learned_from_error_ids TEXT, -- JSON Array
529
+ project_id INTEGER REFERENCES projects(id), -- NULL = global
530
+ confidence REAL NOT NULL DEFAULT 0.5,
531
+ trigger_count INTEGER NOT NULL DEFAULT 0,
532
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
533
+ );
534
+ ```
535
+
536
+ ### notifications (statt Inter-Terminal-Chat)
537
+ ```sql
538
+ CREATE TABLE notifications (
539
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
540
+ target_terminal_id INTEGER REFERENCES terminals(id), -- NULL = alle Terminals
541
+ notification_type TEXT NOT NULL CHECK(notification_type IN (
542
+ 'solution_available', -- "Diesen Fehler hatten wir schon, Lösung existiert"
543
+ 'error_recurring', -- "Dieser Fehler tritt gerade in Projekt B auch auf"
544
+ 'rule_triggered', -- "Prevention-Rule hat angeschlagen"
545
+ 'learning_insight', -- "Neues Muster erkannt"
546
+ 'module_suggested', -- "Wiederverwendbarer Code verfügbar"
547
+ 'antipattern_warning' -- "Bekanntes Anti-Pattern erkannt"
548
+ )),
549
+ reference_type TEXT, -- 'error', 'solution', 'rule', 'code_module', 'antipattern'
550
+ reference_id INTEGER,
551
+ summary TEXT NOT NULL,
552
+ acknowledged INTEGER NOT NULL DEFAULT 0,
553
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
554
+ );
555
+ CREATE INDEX idx_notifications_terminal ON notifications(target_terminal_id);
556
+ CREATE INDEX idx_notifications_ack ON notifications(acknowledged);
557
+ ```
558
+
559
+ ### code_modules
560
+ ```sql
561
+ CREATE TABLE code_modules (
562
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
563
+
564
+ -- Identität
565
+ name TEXT NOT NULL, -- "retry", "logger", "AuthMiddleware"
566
+ module_type TEXT NOT NULL CHECK(module_type IN (
567
+ 'file', -- Ganze Datei als Modul
568
+ 'function', -- Einzelne Funktion
569
+ 'class', -- Klasse
570
+ 'pattern' -- Architektur-Pattern
571
+ )),
572
+
573
+ -- Herkunft
574
+ project_id INTEGER NOT NULL REFERENCES projects(id),
575
+ file_path TEXT NOT NULL, -- Relativ zu project root
576
+ start_line INTEGER, -- NULL bei file-level Modulen
577
+ end_line INTEGER,
578
+
579
+ -- Code
580
+ source_code TEXT NOT NULL,
581
+ fingerprint TEXT NOT NULL, -- Struktureller Hash
582
+ language TEXT NOT NULL,
583
+
584
+ -- Klassifikation
585
+ category TEXT, -- "utility", "middleware", "config", "hook", "component", "service"
586
+ purpose TEXT NOT NULL, -- "Retry wrapper with exponential backoff and jitter"
587
+ interface_signature TEXT, -- "retry<T>(fn: () => Promise<T>, opts?: RetryOpts): Promise<T>"
588
+ dependencies TEXT, -- JSON: Externe Packages ["axios", "lodash"]
589
+ internal_imports TEXT, -- JSON: Interne Abhängigkeiten ["./logger", "./types"]
590
+ labels TEXT, -- JSON: Auto-Labels ["async", "error-handling", "http"]
591
+
592
+ -- Qualitätssignale
593
+ reuse_count INTEGER NOT NULL DEFAULT 0,
594
+ adaptation_count INTEGER NOT NULL DEFAULT 0,
595
+ confidence REAL NOT NULL DEFAULT 0.5, -- Wie wiederverwendbar ist das
596
+ is_pure INTEGER NOT NULL DEFAULT 0, -- Keine Side-Effects?
597
+ complexity_score REAL, -- Niedrig = besser wiederverwendbar
598
+
599
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
600
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
601
+ );
602
+ CREATE INDEX idx_modules_fingerprint ON code_modules(fingerprint);
603
+ CREATE INDEX idx_modules_language ON code_modules(language);
604
+ CREATE INDEX idx_modules_category ON code_modules(category);
605
+ CREATE INDEX idx_modules_project ON code_modules(project_id);
606
+ ```
607
+
608
+ ### module_usages
609
+ ```sql
610
+ CREATE TABLE module_usages (
611
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
612
+ module_id INTEGER NOT NULL REFERENCES code_modules(id) ON DELETE CASCADE,
613
+ project_id INTEGER NOT NULL REFERENCES projects(id),
614
+ file_path TEXT NOT NULL, -- Wo wurde es eingesetzt
615
+ usage_type TEXT NOT NULL CHECK(usage_type IN (
616
+ 'exact', -- 1:1 kopiert
617
+ 'adapted', -- Angepasst
618
+ 'pattern_based' -- Gleiches Pattern, andere Implementierung
619
+ )),
620
+ adaptations TEXT, -- JSON: Was wurde geändert
621
+ outcome TEXT NOT NULL DEFAULT 'unknown'
622
+ CHECK(outcome IN ('success', 'failure', 'unknown')),
623
+ used_at TEXT NOT NULL DEFAULT (datetime('now'))
624
+ );
625
+ CREATE INDEX idx_module_usages_module ON module_usages(module_id);
626
+ CREATE INDEX idx_module_usages_project ON module_usages(project_id);
627
+ ```
628
+
629
+ ### module_similarities
630
+ ```sql
631
+ CREATE TABLE module_similarities (
632
+ module_id_1 INTEGER NOT NULL REFERENCES code_modules(id) ON DELETE CASCADE,
633
+ module_id_2 INTEGER NOT NULL REFERENCES code_modules(id) ON DELETE CASCADE,
634
+ similarity_score REAL NOT NULL,
635
+ similarity_type TEXT NOT NULL CHECK(similarity_type IN (
636
+ 'exact', -- Identischer Code (anderes Projekt)
637
+ 'structural', -- Gleiche Struktur, andere Namen
638
+ 'semantic' -- Gleicher Zweck, andere Implementierung
639
+ )),
640
+ detected_at TEXT NOT NULL DEFAULT (datetime('now')),
641
+ PRIMARY KEY (module_id_1, module_id_2)
642
+ );
643
+ ```
644
+
645
+ ### FTS5 Volltext-Suche
646
+ ```sql
647
+ -- Error-Suche
648
+ CREATE VIRTUAL TABLE errors_fts USING fts5(
649
+ message, message_template, stack_trace, raw_output, task_context,
650
+ content=errors, content_rowid=id
651
+ );
652
+
653
+ -- Solution-Suche
654
+ CREATE VIRTUAL TABLE solutions_fts USING fts5(
655
+ title, description, steps, code_before, code_after,
656
+ content=solutions, content_rowid=id
657
+ );
658
+
659
+ -- Code-Modul-Suche
660
+ CREATE VIRTUAL TABLE code_modules_fts USING fts5(
661
+ name, purpose, source_code, interface_signature,
662
+ content=code_modules, content_rowid=id
663
+ );
664
+
665
+ -- Sync-Trigger für errors_fts
666
+ CREATE TRIGGER errors_ai AFTER INSERT ON errors BEGIN
667
+ INSERT INTO errors_fts(rowid, message, message_template, stack_trace, raw_output, task_context)
668
+ VALUES (new.id, new.message, new.message_template, new.stack_trace, new.raw_output, new.task_context);
669
+ END;
670
+
671
+ CREATE TRIGGER errors_ad AFTER DELETE ON errors BEGIN
672
+ INSERT INTO errors_fts(errors_fts, rowid, message, message_template, stack_trace, raw_output, task_context)
673
+ VALUES ('delete', old.id, old.message, old.message_template, old.stack_trace, old.raw_output, old.task_context);
674
+ END;
675
+
676
+ CREATE TRIGGER errors_au AFTER UPDATE ON errors BEGIN
677
+ INSERT INTO errors_fts(errors_fts, rowid, message, message_template, stack_trace, raw_output, task_context)
678
+ VALUES ('delete', old.id, old.message, old.message_template, old.stack_trace, old.raw_output, old.task_context);
679
+ INSERT INTO errors_fts(rowid, message, message_template, stack_trace, raw_output, task_context)
680
+ VALUES (new.id, new.message, new.message_template, new.stack_trace, new.raw_output, new.task_context);
681
+ END;
682
+
683
+ -- Sync-Trigger für solutions_fts
684
+ CREATE TRIGGER solutions_ai AFTER INSERT ON solutions BEGIN
685
+ INSERT INTO solutions_fts(rowid, title, description, steps, code_before, code_after)
686
+ VALUES (new.id, new.title, new.description, new.steps, new.code_before, new.code_after);
687
+ END;
688
+
689
+ CREATE TRIGGER solutions_ad AFTER DELETE ON solutions BEGIN
690
+ INSERT INTO solutions_fts(solutions_fts, rowid, title, description, steps, code_before, code_after)
691
+ VALUES ('delete', old.id, old.title, old.description, old.steps, old.code_before, old.code_after);
692
+ END;
693
+
694
+ CREATE TRIGGER solutions_au AFTER UPDATE ON solutions BEGIN
695
+ INSERT INTO solutions_fts(solutions_fts, rowid, title, description, steps, code_before, code_after)
696
+ VALUES ('delete', old.id, old.title, old.description, old.steps, old.code_before, old.code_after);
697
+ INSERT INTO solutions_fts(rowid, title, description, steps, code_before, code_after)
698
+ VALUES (new.id, new.title, new.description, new.steps, new.code_before, new.code_after);
699
+ END;
700
+
701
+ -- Sync-Trigger für code_modules_fts
702
+ CREATE TRIGGER code_modules_ai AFTER INSERT ON code_modules BEGIN
703
+ INSERT INTO code_modules_fts(rowid, name, purpose, source_code, interface_signature)
704
+ VALUES (new.id, new.name, new.purpose, new.source_code, new.interface_signature);
705
+ END;
706
+
707
+ CREATE TRIGGER code_modules_ad AFTER DELETE ON code_modules BEGIN
708
+ INSERT INTO code_modules_fts(code_modules_fts, rowid, name, purpose, source_code, interface_signature)
709
+ VALUES ('delete', old.id, old.name, old.purpose, old.source_code, old.interface_signature);
710
+ END;
711
+
712
+ CREATE TRIGGER code_modules_au AFTER UPDATE ON code_modules BEGIN
713
+ INSERT INTO code_modules_fts(code_modules_fts, rowid, name, purpose, source_code, interface_signature)
714
+ VALUES ('delete', old.id, old.name, old.purpose, old.source_code, old.interface_signature);
715
+ INSERT INTO code_modules_fts(rowid, name, purpose, source_code, interface_signature)
716
+ VALUES (new.id, new.name, new.purpose, new.source_code, new.interface_signature);
717
+ END;
718
+ ```
719
+
720
+ ## Kern-Algorithmen
721
+
722
+ ### Error-Fingerprinting
723
+
724
+ Struktureller Hash: error_type + templatisierte Message + Top-3 Stack-Frames → SHA-256.
725
+
726
+ **Templatisierung:** Variable Teile werden durch Platzhalter ersetzt:
727
+ - Dateipfade → `<PATH>`
728
+ - Zeilennummern → `<LINE>`
729
+ - Variablennamen in Fehlermessages → bleiben (oft key info)
730
+ - Zahlen in generischen Kontexten → `<NUM>`
731
+ - Hex-Adressen → `<ADDR>`
732
+ - UUIDs → `<UUID>`
733
+ - URLs → `<URL>`
734
+ - Timestamps → `<TIMESTAMP>`
735
+
736
+ ```typescript
737
+ function templateMessage(msg: string): string {
738
+ return msg
739
+ .replace(/[A-Z]:\\[\w\-\.\\]+\.\w+/g, '<PATH>') // Windows-Pfade
740
+ .replace(/\/[\w\-\.\/]+\.\w+/g, '<PATH>') // Unix-Pfade
741
+ .replace(/:\d+:\d+/g, ':<LINE>:<COL>') // Zeile:Spalte
742
+ .replace(/line \d+/gi, 'line <LINE>') // "line 42"
743
+ .replace(/0x[0-9a-fA-F]+/g, '<ADDR>') // Hex
744
+ .replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '<UUID>')
745
+ .replace(/https?:\/\/[^\s]+/g, '<URL>') // URLs
746
+ .replace(/\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}/g, '<TIMESTAMP>');
747
+ }
748
+
749
+ function generateFingerprint(errorType: string, message: string, frames: StackFrame[]): string {
750
+ const template = templateMessage(message);
751
+ const topFrames = frames.slice(0, 3).map(f =>
752
+ `${f.function_name || '<anon>'}@${basename(f.file_path || '<unknown>')}`
753
+ ).join('|');
754
+ const input = `${errorType}::${template}::${topFrames}`;
755
+ return createHash('sha256').update(input).digest('hex');
756
+ }
757
+ ```
758
+
759
+ ### Multi-Signal Error-Matching
760
+
761
+ ```typescript
762
+ interface MatchSignal {
763
+ name: string;
764
+ weight: number;
765
+ compute: (a: ErrorRecord, b: ErrorRecord) => number; // 0.0 - 1.0
766
+ }
767
+
768
+ const SIGNALS: MatchSignal[] = [
769
+ { name: 'fingerprint', weight: 0.30, compute: fingerprintMatch },
770
+ { name: 'message_similarity', weight: 0.20, compute: messageSimilarity },
771
+ { name: 'type_match', weight: 0.15, compute: typeMatch },
772
+ { name: 'stack_similarity', weight: 0.15, compute: stackSimilarity },
773
+ { name: 'file_similarity', weight: 0.10, compute: fileSimilarity },
774
+ { name: 'fts_score', weight: 0.10, compute: ftsScore },
775
+ ];
776
+
777
+ const MATCH_THRESHOLD = 0.70;
778
+ const STRONG_MATCH_THRESHOLD = 0.90;
779
+
780
+ function matchError(incoming: ErrorRecord, candidates: ErrorRecord[]): MatchResult[] {
781
+ return candidates
782
+ .map(candidate => {
783
+ const scores = SIGNALS.map(signal => {
784
+ const score = signal.compute(incoming, candidate);
785
+ return {
786
+ signal: signal.name,
787
+ score,
788
+ weighted: score * signal.weight,
789
+ };
790
+ });
791
+ const totalScore = scores.reduce((sum, s) => sum + s.weighted, 0);
792
+ return { candidate, scores, totalScore, isMatch: totalScore >= MATCH_THRESHOLD };
793
+ })
794
+ .filter(r => r.isMatch)
795
+ .sort((a, b) => b.totalScore - a.totalScore);
796
+ }
797
+ ```
798
+
799
+ ### Similarity-Funktionen
800
+
801
+ ```typescript
802
+ // Levenshtein Distanz (normalisiert auf 0-1 Similarity)
803
+ function levenshteinSimilarity(a: string, b: string): number {
804
+ if (a === b) return 1.0;
805
+ const maxLen = Math.max(a.length, b.length);
806
+ if (maxLen === 0) return 1.0;
807
+ return 1 - levenshteinDistance(a, b) / maxLen;
808
+ }
809
+
810
+ // Cosine Similarity auf Token-Vektoren
811
+ function cosineSimilarity(tokensA: string[], tokensB: string[]): number {
812
+ const vocab = new Set([...tokensA, ...tokensB]);
813
+ const vecA = new Map<string, number>();
814
+ const vecB = new Map<string, number>();
815
+ tokensA.forEach(t => vecA.set(t, (vecA.get(t) || 0) + 1));
816
+ tokensB.forEach(t => vecB.set(t, (vecB.get(t) || 0) + 1));
817
+
818
+ let dot = 0, magA = 0, magB = 0;
819
+ for (const word of vocab) {
820
+ const a = vecA.get(word) || 0;
821
+ const b = vecB.get(word) || 0;
822
+ dot += a * b;
823
+ magA += a * a;
824
+ magB += b * b;
825
+ }
826
+ const denom = Math.sqrt(magA) * Math.sqrt(magB);
827
+ return denom === 0 ? 0 : dot / denom;
828
+ }
829
+
830
+ // Jaccard Similarity auf Token-Sets
831
+ function jaccardSimilarity(tokensA: string[], tokensB: string[]): number {
832
+ const setA = new Set(tokensA);
833
+ const setB = new Set(tokensB);
834
+ const intersection = new Set([...setA].filter(x => setB.has(x)));
835
+ const union = new Set([...setA, ...setB]);
836
+ return union.size === 0 ? 0 : intersection.size / union.size;
837
+ }
838
+ ```
839
+
840
+ ### TF-IDF (Inkrementell)
841
+
842
+ ```typescript
843
+ class TfIdfIndex {
844
+ private documents: Map<number, string[]> = new Map();
845
+ private df: Map<string, number> = new Map(); // Document Frequency Cache
846
+ private idf: Map<string, number> = new Map();
847
+ private documentCount = 0;
848
+
849
+ addDocument(id: number, tokens: string[]): void {
850
+ // Inkrementelles DF-Update statt Full-Recompute
851
+ const unique = new Set(tokens);
852
+ for (const token of unique) {
853
+ this.df.set(token, (this.df.get(token) || 0) + 1);
854
+ }
855
+ this.documents.set(id, tokens);
856
+ this.documentCount++;
857
+ this.recomputeIdfForTerms(unique);
858
+ }
859
+
860
+ removeDocument(id: number): void {
861
+ const tokens = this.documents.get(id);
862
+ if (!tokens) return;
863
+
864
+ const unique = new Set(tokens);
865
+ for (const token of unique) {
866
+ const count = (this.df.get(token) || 1) - 1;
867
+ if (count <= 0) {
868
+ this.df.delete(token);
869
+ this.idf.delete(token);
870
+ } else {
871
+ this.df.set(token, count);
872
+ }
873
+ }
874
+ this.documents.delete(id);
875
+ this.documentCount--;
876
+ this.recomputeIdfForTerms(unique);
877
+ }
878
+
879
+ private recomputeIdfForTerms(terms: Set<string>): void {
880
+ const N = this.documentCount;
881
+ for (const term of terms) {
882
+ const count = this.df.get(term);
883
+ if (count) {
884
+ this.idf.set(term, Math.log((N + 1) / (count + 1)) + 1);
885
+ }
886
+ }
887
+ }
888
+
889
+ search(queryTokens: string[], topK = 10): Array<{ id: number; score: number }> {
890
+ const results: Array<{ id: number; score: number }> = [];
891
+
892
+ for (const [id, docTokens] of this.documents) {
893
+ let score = 0;
894
+ const tf = new Map<string, number>();
895
+ docTokens.forEach(t => tf.set(t, (tf.get(t) || 0) + 1));
896
+
897
+ for (const qt of queryTokens) {
898
+ const termFreq = (tf.get(qt) || 0) / docTokens.length;
899
+ const inverseDocFreq = this.idf.get(qt) || 0;
900
+ score += termFreq * inverseDocFreq;
901
+ }
902
+ if (score > 0) results.push({ id, score });
903
+ }
904
+
905
+ return results.sort((a, b) => b.score - a.score).slice(0, topK);
906
+ }
907
+
908
+ // Persistenz: Zustand in SQLite speichern/laden für schnelle Daemon-Neustarts
909
+ serialize(): { documents: [number, string[]][]; df: [string, number][] } {
910
+ return {
911
+ documents: [...this.documents.entries()],
912
+ df: [...this.df.entries()],
913
+ };
914
+ }
915
+
916
+ static deserialize(data: ReturnType<TfIdfIndex['serialize']>): TfIdfIndex {
917
+ const index = new TfIdfIndex();
918
+ index.documents = new Map(data.documents);
919
+ index.df = new Map(data.df);
920
+ index.documentCount = index.documents.size;
921
+ // IDF aus DF recomputen
922
+ const N = index.documentCount;
923
+ for (const [term, count] of index.df) {
924
+ index.idf.set(term, Math.log((N + 1) / (count + 1)) + 1);
925
+ }
926
+ return index;
927
+ }
928
+ }
929
+ ```
930
+
931
+ ### Confidence-Scoring (Wilson Score Intervall)
932
+
933
+ ```typescript
934
+ // Wilson Score Interval - Lower Bound
935
+ // Besser als Durchschnitt: berücksichtigt Stichprobengröße
936
+ function wilsonScore(successes: number, total: number, z = 1.96): number {
937
+ if (total === 0) return 0;
938
+
939
+ const p = successes / total;
940
+ const denominator = 1 + z * z / total;
941
+ const centre = p + z * z / (2 * total);
942
+ const adjustment = z * Math.sqrt((p * (1 - p) + z * z / (4 * total)) / total);
943
+
944
+ return (centre - adjustment) / denominator;
945
+ }
946
+
947
+ // Zeitbasierter Decay
948
+ function timeDecay(timestamp: Date, halfLifeDays = 30): number {
949
+ const now = new Date();
950
+ const ageMs = now.getTime() - timestamp.getTime();
951
+ const ageDays = ageMs / (1000 * 60 * 60 * 24);
952
+ return Math.pow(0.5, ageDays / halfLifeDays);
953
+ }
954
+
955
+ // Kombinierter Score
956
+ function computeConfidence(
957
+ successes: number,
958
+ failures: number,
959
+ lastUsed: Date,
960
+ halfLifeDays = 30
961
+ ): number {
962
+ const total = successes + failures;
963
+ const wilson = wilsonScore(successes, total);
964
+ const decay = timeDecay(lastUsed, halfLifeDays);
965
+ return wilson * decay;
966
+ }
967
+ ```
968
+
969
+ ### Code-Fingerprinting (Strukturell)
970
+
971
+ ```typescript
972
+ function fingerprintCode(source: string, language: string): string {
973
+ // 1. Comments entfernen
974
+ let normalized = stripComments(source, language);
975
+
976
+ // 2. Whitespace normalisieren
977
+ normalized = normalized.replace(/\s+/g, ' ').trim();
978
+
979
+ // 3. Identifier normalisieren (aber Import-Names und API-Calls behalten)
980
+ normalized = normalizeIdentifiers(normalized, language);
981
+
982
+ // 4. String-Literale normalisieren
983
+ normalized = normalized.replace(/'[^']*'/g, "'<STR>'");
984
+ normalized = normalized.replace(/"[^"]*"/g, '"<STR>"');
985
+ normalized = normalized.replace(/`[^`]*`/g, '`<STR>`');
986
+
987
+ // 5. Zahlen normalisieren
988
+ normalized = normalized.replace(/\b\d+\b/g, '<NUM>');
989
+
990
+ return createHash('sha256').update(normalized).digest('hex');
991
+ }
992
+
993
+ function stripComments(source: string, language: string): string {
994
+ switch (language) {
995
+ case 'typescript':
996
+ case 'javascript':
997
+ case 'java':
998
+ case 'go':
999
+ case 'rust':
1000
+ return source
1001
+ .replace(/\/\/.*$/gm, '') // Single-line
1002
+ .replace(/\/\*[\s\S]*?\*\//g, ''); // Multi-line
1003
+ case 'python':
1004
+ return source
1005
+ .replace(/#.*$/gm, '') // Single-line
1006
+ .replace(/"""[\s\S]*?"""/g, '') // Docstrings
1007
+ .replace(/'''[\s\S]*?'''/g, '');
1008
+ default:
1009
+ return source.replace(/\/\/.*$/gm, '').replace(/#.*$/gm, '');
1010
+ }
1011
+ }
1012
+
1013
+ function normalizeIdentifiers(source: string, language: string): string {
1014
+ // Lokale Variablen normalisieren, aber importierte Namen behalten
1015
+ // Einfache Heuristik: camelCase/snake_case Wörter die nicht in Import-Statements stehen
1016
+ const imports = extractImportNames(source, language);
1017
+ const keywords = getLanguageKeywords(language);
1018
+ const preserve = new Set([...imports, ...keywords]);
1019
+
1020
+ return source.replace(/\b[a-zA-Z_]\w*\b/g, (match) => {
1021
+ if (preserve.has(match)) return match;
1022
+ // Behalte den ersten Buchstaben als Typ-Hint (großbuchstabe = Klasse)
1023
+ if (match[0] === match[0].toUpperCase()) return '<CLASS>';
1024
+ return '<VAR>';
1025
+ });
1026
+ }
1027
+ ```
1028
+
1029
+ ### Code-Reusability-Scoring
1030
+
1031
+ ```typescript
1032
+ interface ReusabilitySignal {
1033
+ name: string;
1034
+ weight: number;
1035
+ check: (code: CodeUnit) => number; // 0.0 - 1.0
1036
+ }
1037
+
1038
+ const REUSABILITY_SIGNALS: ReusabilitySignal[] = [
1039
+ {
1040
+ name: 'single_responsibility',
1041
+ weight: 0.25,
1042
+ // Datei hat EINEN klaren Zweck (1-3 Exports, kohärente Naming)
1043
+ check: (code) => {
1044
+ const exports = code.exports.length;
1045
+ if (exports === 0) return 0;
1046
+ if (exports <= 3) return 1.0;
1047
+ if (exports <= 6) return 0.6;
1048
+ return 0.3;
1049
+ }
1050
+ },
1051
+ {
1052
+ name: 'pure_function',
1053
+ weight: 0.20,
1054
+ // Keine Side-Effects: kein fs, kein process, kein console, kein fetch
1055
+ check: (code) => {
1056
+ const sideEffects = ['fs.', 'process.', 'console.', 'fetch(', 'XMLHttpRequest',
1057
+ 'document.', 'window.', 'global.', 'require('];
1058
+ const found = sideEffects.filter(se => code.source.includes(se));
1059
+ return found.length === 0 ? 1.0 : Math.max(0, 1 - found.length * 0.3);
1060
+ }
1061
+ },
1062
+ {
1063
+ name: 'clear_interface',
1064
+ weight: 0.20,
1065
+ // Typisierte Parameter, klarer Return-Type, keine any
1066
+ check: (code) => {
1067
+ let score = 0.5; // Baseline
1068
+ if (code.hasTypeAnnotations) score += 0.3;
1069
+ if (!code.source.includes(': any')) score += 0.2;
1070
+ return Math.min(1.0, score);
1071
+ }
1072
+ },
1073
+ {
1074
+ name: 'low_coupling',
1075
+ weight: 0.15,
1076
+ // Wenig interne Imports, wenig externe Dependencies
1077
+ check: (code) => {
1078
+ const internalImports = code.internalImports.length;
1079
+ const externalImports = code.externalImports.length;
1080
+ const total = internalImports + externalImports;
1081
+ if (total === 0) return 1.0;
1082
+ if (total <= 3) return 0.8;
1083
+ if (total <= 6) return 0.5;
1084
+ return 0.2;
1085
+ }
1086
+ },
1087
+ {
1088
+ name: 'generic_utility',
1089
+ weight: 0.10,
1090
+ // Pfad enthält utils/, helpers/, lib/, shared/
1091
+ // Oder: Funktion nutzt Generics
1092
+ check: (code) => {
1093
+ const utilPaths = ['utils/', 'helpers/', 'lib/', 'shared/', 'common/'];
1094
+ const isUtilPath = utilPaths.some(p => code.filePath.includes(p));
1095
+ const hasGenerics = /\<[A-Z]\w*\>/.test(code.source);
1096
+ let score = 0;
1097
+ if (isUtilPath) score += 0.6;
1098
+ if (hasGenerics) score += 0.4;
1099
+ return Math.min(1.0, score || 0.2);
1100
+ }
1101
+ },
1102
+ {
1103
+ name: 'documentation',
1104
+ weight: 0.10,
1105
+ // JSDoc/TSDoc/Docstring vorhanden
1106
+ check: (code) => {
1107
+ const hasJsdoc = /\/\*\*[\s\S]*?\*\//.test(code.source);
1108
+ const hasDocstring = /"""[\s\S]*?"""/.test(code.source) || /'''[\s\S]*?'''/.test(code.source);
1109
+ const hasInlineComments = (code.source.match(/\/\/ /g) || []).length >= 2;
1110
+ if (hasJsdoc || hasDocstring) return 1.0;
1111
+ if (hasInlineComments) return 0.5;
1112
+ return 0.1;
1113
+ }
1114
+ },
1115
+ ];
1116
+
1117
+ const MODULE_THRESHOLD = 0.60;
1118
+ ```
1119
+
1120
+ ### Smart Granularity Detection
1121
+
1122
+ ```typescript
1123
+ function detectGranularity(filePath: string, source: string, language: string): ModuleType {
1124
+ const exports = extractExports(source, language);
1125
+
1126
+ // Datei mit 1 Default-Export → Ganzes File ist das Modul
1127
+ if (exports.default && exports.named.length <= 2) {
1128
+ return 'file';
1129
+ }
1130
+
1131
+ // Datei mit einer Klasse → Klasse ist das Modul
1132
+ if (exports.classes.length === 1 && exports.named.length <= 3) {
1133
+ return 'class';
1134
+ }
1135
+
1136
+ // Datei mit vielen unzusammenhängenden Exports → Einzeln tracken
1137
+ if (exports.named.length > 3) {
1138
+ const cohesion = measureExportCohesion(exports, source);
1139
+ if (cohesion < 0.5) {
1140
+ return 'function'; // Jeder Export wird einzeln als Modul registriert
1141
+ }
1142
+ }
1143
+
1144
+ // Default: Ganze Datei
1145
+ return 'file';
1146
+ }
1147
+
1148
+ function measureExportCohesion(exports: ExportInfo, source: string): number {
1149
+ // Messe ob die Exports thematisch zusammengehören
1150
+ // Heuristik: Teilen sie gemeinsame Tokens in ihren Namen?
1151
+ const names = exports.named.map(e => tokenizeCamelCase(e.name));
1152
+ if (names.length <= 1) return 1.0;
1153
+
1154
+ let sharedTokens = 0;
1155
+ let totalPairs = 0;
1156
+ for (let i = 0; i < names.length; i++) {
1157
+ for (let j = i + 1; j < names.length; j++) {
1158
+ const shared = names[i].filter(t => names[j].includes(t)).length;
1159
+ const total = new Set([...names[i], ...names[j]]).size;
1160
+ sharedTokens += total > 0 ? shared / total : 0;
1161
+ totalPairs++;
1162
+ }
1163
+ }
1164
+ return totalPairs > 0 ? sharedTokens / totalPairs : 0;
1165
+ }
1166
+ ```
1167
+
1168
+ ### Pattern-Extraktion (Centroid-basiert)
1169
+
1170
+ ```typescript
1171
+ class PatternExtractor {
1172
+ extractPatterns(pairs: ErrorSolutionPair[]): Pattern[] {
1173
+ const clusters: { pairs: ErrorSolutionPair[]; centroid: number[] }[] = [];
1174
+
1175
+ for (const pair of pairs) {
1176
+ const tokens = tokenize(pair.error.message_template || pair.error.message);
1177
+ const vector = this.tokensToVector(tokens);
1178
+
1179
+ let bestCluster: typeof clusters[number] | null = null;
1180
+ let bestSim = 0;
1181
+
1182
+ for (const cluster of clusters) {
1183
+ const sim = this.vectorCosineSimilarity(vector, cluster.centroid);
1184
+ if (sim >= 0.75 && sim > bestSim) {
1185
+ bestSim = sim;
1186
+ bestCluster = cluster;
1187
+ }
1188
+ }
1189
+
1190
+ if (bestCluster) {
1191
+ bestCluster.pairs.push(pair);
1192
+ // Centroid aktualisieren (Running Average)
1193
+ bestCluster.centroid = this.updateCentroid(bestCluster.centroid, vector, bestCluster.pairs.length);
1194
+ } else {
1195
+ clusters.push({ pairs: [pair], centroid: vector });
1196
+ }
1197
+ }
1198
+
1199
+ return clusters
1200
+ .filter(c => c.pairs.length >= 2)
1201
+ .map(cluster => ({
1202
+ errorTemplate: this.findCommonTemplate(cluster.pairs),
1203
+ solutionSummary: this.findCommonSolution(cluster.pairs),
1204
+ occurrences: cluster.pairs.length,
1205
+ confidence: this.computeClusterConfidence(cluster.pairs),
1206
+ successRate: this.computeSuccessRate(cluster.pairs),
1207
+ errorIds: cluster.pairs.map(p => p.error.id),
1208
+ solutionIds: [...new Set(cluster.pairs.map(p => p.solution.id))],
1209
+ }));
1210
+ }
1211
+
1212
+ private updateCentroid(current: number[], newVec: number[], count: number): number[] {
1213
+ // Inkrementeller Centroid: new_centroid = old + (new_vec - old) / count
1214
+ return current.map((v, i) => v + ((newVec[i] || 0) - v) / count);
1215
+ }
1216
+ }
1217
+ ```
1218
+
1219
+ ### Rule-Generation
1220
+
1221
+ ```typescript
1222
+ class RuleGenerator {
1223
+ generateRules(patterns: Pattern[], config: LearningConfig): Rule[] {
1224
+ return patterns
1225
+ .filter(p =>
1226
+ p.occurrences >= config.minOccurrences &&
1227
+ p.confidence >= config.minConfidence &&
1228
+ p.successRate >= config.minSuccessRate
1229
+ )
1230
+ .map(pattern => ({
1231
+ name: `Auto: ${pattern.errorTemplate.substring(0, 50)}`,
1232
+ description: `Automatisch generiert aus ${pattern.occurrences} Vorkommen`,
1233
+ pattern: {
1234
+ error_type: pattern.errorType,
1235
+ message_pattern: pattern.messageRegex,
1236
+ file_pattern: pattern.filePattern,
1237
+ },
1238
+ action: {
1239
+ type: pattern.confidence >= 0.90 ? 'auto_fix' : 'suggestion',
1240
+ solution_ids: pattern.solutionIds,
1241
+ message: pattern.solutionSummary,
1242
+ },
1243
+ rule_type: pattern.confidence >= 0.90 ? 'auto_fix' : 'suggestion',
1244
+ confidence: pattern.confidence,
1245
+ source_error_ids: pattern.errorIds,
1246
+ }));
1247
+ }
1248
+ }
1249
+ ```
1250
+
1251
+ ### Lern-Zyklus
1252
+
1253
+ ```typescript
1254
+ class LearningEngine {
1255
+ private timer: NodeJS.Timeout | null = null;
1256
+
1257
+ startSchedule(intervalMs: number): void {
1258
+ this.timer = setInterval(() => this.runCycle(), intervalMs);
1259
+ }
1260
+
1261
+ stop(): void {
1262
+ if (this.timer) clearInterval(this.timer);
1263
+ }
1264
+
1265
+ async runCycle(): Promise<LearningCycleResult> {
1266
+ const result: LearningCycleResult = {
1267
+ newPatterns: 0,
1268
+ updatedRules: 0,
1269
+ prunedRules: 0,
1270
+ crossProjectInsights: 0,
1271
+ newAntipatterns: 0,
1272
+ };
1273
+
1274
+ // Phase 1: Neue Error-Solution-Paare sammeln (seit letztem Cycle)
1275
+ const newPairs = this.collectNewErrorSolutionPairs();
1276
+
1277
+ // Phase 2: Confidence-Scores aller Solutions aktualisieren
1278
+ this.updateConfidenceScores();
1279
+
1280
+ // Phase 3: Muster extrahieren (Centroid-basiertes Clustering)
1281
+ const patterns = this.patternExtractor.extractPatterns(newPairs);
1282
+ result.newPatterns = patterns.length;
1283
+
1284
+ // Phase 4: Regeln generieren aus Mustern
1285
+ const newRules = this.ruleGenerator.generateRules(patterns, this.config);
1286
+ result.updatedRules = newRules.length;
1287
+
1288
+ // Phase 5: Schwache Regeln beschneiden
1289
+ // Entferne: Confidence < 0.20 ODER Ablehnungsrate > 50%
1290
+ result.prunedRules = this.pruneRules();
1291
+
1292
+ // Phase 6: Anti-Patterns erkennen
1293
+ // Wiederholte Fehler OHNE erfolgreiche Lösung → Anti-Pattern Kandidat
1294
+ result.newAntipatterns = this.detectAntipatterns();
1295
+
1296
+ // Phase 7: Cross-Projekt Analyse
1297
+ // Gleiche Fehler in verschiedenen Projekten → Lösung übertragbar?
1298
+ result.crossProjectInsights = this.analyzeCrossProject();
1299
+
1300
+ // Phase 8: Code-Module Confidence aktualisieren
1301
+ // Reuse-Count, Adaptation-Outcomes → Confidence-Score
1302
+ this.updateModuleConfidence();
1303
+
1304
+ // Phase 9: Notifications senden
1305
+ this.emitNotifications(result);
1306
+
1307
+ return result;
1308
+ }
1309
+
1310
+ private detectAntipatterns(): number {
1311
+ // Finde Fehler die >= 3x aufgetreten sind, aber keine erfolgreiche Lösung haben
1312
+ // → Kandidat für "Tu das nicht"-Regel
1313
+ const candidates = this.services.error.findUnresolvedRecurring(3);
1314
+ let count = 0;
1315
+
1316
+ for (const error of candidates) {
1317
+ const failedAttempts = this.services.solution.getFailedAttempts(error.id);
1318
+ if (failedAttempts.length >= 2) {
1319
+ this.services.antipattern.create({
1320
+ description: `Wiederkehrender Fehler ohne Lösung: ${error.message_template || error.message}`,
1321
+ trigger_pattern: JSON.stringify({
1322
+ error_type: error.error_type,
1323
+ message_pattern: error.message_template,
1324
+ }),
1325
+ severity: failedAttempts.length >= 4 ? 'critical' : 'warning',
1326
+ learned_from_error_ids: JSON.stringify([error.id]),
1327
+ project_id: error.project_id,
1328
+ confidence: Math.min(0.9, 0.3 + failedAttempts.length * 0.15),
1329
+ });
1330
+ count++;
1331
+ }
1332
+ }
1333
+ return count;
1334
+ }
1335
+ }
1336
+ ```
1337
+
1338
+ ## Synapsen-Netzwerk
1339
+
1340
+ ### Hebbsches Lernen: "Neurons that fire together, wire together"
1341
+
1342
+ Jede Aktion im System stärkt oder schwächt Synapsen:
1343
+
1344
+ ```typescript
1345
+ class SynapseManager {
1346
+ // Synapse erstellen oder stärken
1347
+ strengthen(
1348
+ source: { type: NodeType; id: number },
1349
+ target: { type: NodeType; id: number },
1350
+ synapseType: SynapseType,
1351
+ context?: Record<string, unknown>
1352
+ ): void {
1353
+ const existing = this.repo.find(source, target, synapseType);
1354
+
1355
+ if (existing) {
1356
+ // Hebbsche Verstärkung: Gewicht wächst logarithmisch (nie über 1.0)
1357
+ const newWeight = Math.min(1.0,
1358
+ existing.weight + (1.0 - existing.weight) * this.config.learningRate
1359
+ );
1360
+ this.repo.update(existing.id, {
1361
+ weight: newWeight,
1362
+ activation_count: existing.activation_count + 1,
1363
+ last_activated_at: new Date().toISOString(),
1364
+ });
1365
+ } else {
1366
+ this.repo.create({
1367
+ source_type: source.type,
1368
+ source_id: source.id,
1369
+ target_type: target.type,
1370
+ target_id: target.id,
1371
+ synapse_type: synapseType,
1372
+ weight: this.config.initialWeight, // Default: 0.1
1373
+ context: context ? JSON.stringify(context) : null,
1374
+ });
1375
+ }
1376
+ }
1377
+
1378
+ // Synapse schwächen (bei Fehlschlag oder Ablehnung)
1379
+ weaken(synapseId: number, factor = 0.5): void {
1380
+ const synapse = this.repo.getById(synapseId);
1381
+ if (!synapse) return;
1382
+
1383
+ const newWeight = synapse.weight * factor;
1384
+ if (newWeight < this.config.pruneThreshold) {
1385
+ // Zu schwach → Synapse entfernen
1386
+ this.repo.delete(synapseId);
1387
+ } else {
1388
+ this.repo.update(synapseId, { weight: newWeight });
1389
+ }
1390
+ }
1391
+
1392
+ // Zeitbasierter Verfall aller Synapsen (im Learning Cycle)
1393
+ decayAll(): number {
1394
+ // Gewicht *= decay_factor für alle Synapsen die seit X Tagen nicht aktiviert wurden
1395
+ const cutoff = new Date();
1396
+ cutoff.setDate(cutoff.getDate() - this.config.decayAfterDays);
1397
+
1398
+ const stale = this.repo.findInactiveSince(cutoff.toISOString());
1399
+ let pruned = 0;
1400
+
1401
+ for (const synapse of stale) {
1402
+ const decay = timeDecay(
1403
+ new Date(synapse.last_activated_at),
1404
+ this.config.decayHalfLifeDays
1405
+ );
1406
+ const newWeight = synapse.weight * decay;
1407
+
1408
+ if (newWeight < this.config.pruneThreshold) {
1409
+ this.repo.delete(synapse.id);
1410
+ pruned++;
1411
+ } else {
1412
+ this.repo.update(synapse.id, { weight: newWeight });
1413
+ }
1414
+ }
1415
+ return pruned;
1416
+ }
1417
+ }
1418
+ ```
1419
+
1420
+ ### Wann werden Synapsen erstellt?
1421
+
1422
+ ```typescript
1423
+ // In den Event-Listeners des BrainCore:
1424
+
1425
+ // Error gemeldet → Synapse zu Projekt
1426
+ eventBus.on('error:reported', ({ errorId, projectId }) => {
1427
+ synapseManager.strengthen(
1428
+ { type: 'error', id: errorId },
1429
+ { type: 'project', id: projectId },
1430
+ 'co_occurs'
1431
+ );
1432
+ });
1433
+
1434
+ // Solution löst Error → starke Synapse
1435
+ eventBus.on('solution:applied', ({ solutionId, errorId, outcome }) => {
1436
+ if (outcome === 'success') {
1437
+ synapseManager.strengthen(
1438
+ { type: 'solution', id: solutionId },
1439
+ { type: 'error', id: errorId },
1440
+ 'solves',
1441
+ { outcome: 'success' }
1442
+ );
1443
+ } else if (outcome === 'failure') {
1444
+ // Schwäche die Synapse bei Fehlschlag
1445
+ const synapse = synapseManager.find(
1446
+ { type: 'solution', id: solutionId },
1447
+ { type: 'error', id: errorId },
1448
+ 'solves'
1449
+ );
1450
+ if (synapse) synapseManager.weaken(synapse.id, 0.7);
1451
+ }
1452
+ });
1453
+
1454
+ // Gleicher Error in zwei Projekten → cross_project Synapse
1455
+ eventBus.on('error:cross_project_match', ({ errorId1, errorId2, projectId1, projectId2 }) => {
1456
+ synapseManager.strengthen(
1457
+ { type: 'error', id: errorId1 },
1458
+ { type: 'error', id: errorId2 },
1459
+ 'similar_to'
1460
+ );
1461
+ synapseManager.strengthen(
1462
+ { type: 'project', id: projectId1 },
1463
+ { type: 'project', id: projectId2 },
1464
+ 'cross_project'
1465
+ );
1466
+ });
1467
+
1468
+ // Code-Modul wiederverwendet → starke Synapse
1469
+ eventBus.on('module:reused', ({ moduleId, projectId, outcome }) => {
1470
+ synapseManager.strengthen(
1471
+ { type: 'code_module', id: moduleId },
1472
+ { type: 'project', id: projectId },
1473
+ 'uses_module',
1474
+ { outcome }
1475
+ );
1476
+ });
1477
+
1478
+ // Solution nutzt Code-Modul → Synapse
1479
+ eventBus.on('solution:uses_code', ({ solutionId, moduleId }) => {
1480
+ synapseManager.strengthen(
1481
+ { type: 'solution', id: solutionId },
1482
+ { type: 'code_module', id: moduleId },
1483
+ 'uses_module'
1484
+ );
1485
+ });
1486
+
1487
+ // Rule verhindert Error → Synapse stärken
1488
+ eventBus.on('rule:prevented', ({ ruleId, errorId }) => {
1489
+ synapseManager.strengthen(
1490
+ { type: 'rule', id: ruleId },
1491
+ { type: 'error', id: errorId },
1492
+ 'prevents'
1493
+ );
1494
+ });
1495
+
1496
+ // Error tritt kurz nach anderem Error auf → causal Synapse
1497
+ eventBus.on('error:chain_detected', ({ causeErrorId, effectErrorId }) => {
1498
+ synapseManager.strengthen(
1499
+ { type: 'error', id: causeErrorId },
1500
+ { type: 'error', id: effectErrorId },
1501
+ 'causes'
1502
+ );
1503
+ });
1504
+ ```
1505
+
1506
+ ### Spreading Activation (Pfade durch das Netzwerk finden)
1507
+
1508
+ ```typescript
1509
+ class SpreadingActivation {
1510
+ // Finde alles was mit einem Knoten zusammenhängt, gewichtet nach Stärke
1511
+ activate(
1512
+ startNode: { type: NodeType; id: number },
1513
+ maxDepth = 3,
1514
+ minWeight = 0.2
1515
+ ): ActivationResult[] {
1516
+ const visited = new Set<string>();
1517
+ const results: ActivationResult[] = [];
1518
+ const queue: Array<{
1519
+ node: { type: NodeType; id: number };
1520
+ depth: number;
1521
+ pathWeight: number;
1522
+ path: string[];
1523
+ }> = [{ node: startNode, depth: 0, pathWeight: 1.0, path: [] }];
1524
+
1525
+ while (queue.length > 0) {
1526
+ const current = queue.shift()!;
1527
+ const key = `${current.node.type}:${current.node.id}`;
1528
+
1529
+ if (visited.has(key)) continue;
1530
+ if (current.depth > maxDepth) continue;
1531
+ if (current.pathWeight < minWeight) continue;
1532
+
1533
+ visited.add(key);
1534
+
1535
+ if (current.depth > 0) {
1536
+ results.push({
1537
+ node: current.node,
1538
+ activation: current.pathWeight,
1539
+ depth: current.depth,
1540
+ path: current.path,
1541
+ });
1542
+ }
1543
+
1544
+ // Alle Synapsen von diesem Knoten holen
1545
+ const synapses = this.repo.getOutgoing(current.node.type, current.node.id);
1546
+
1547
+ for (const synapse of synapses) {
1548
+ const nextWeight = current.pathWeight * synapse.weight;
1549
+ if (nextWeight >= minWeight) {
1550
+ queue.push({
1551
+ node: { type: synapse.target_type, id: synapse.target_id },
1552
+ depth: current.depth + 1,
1553
+ pathWeight: nextWeight,
1554
+ path: [...current.path, `--${synapse.synapse_type}-->`],
1555
+ });
1556
+ }
1557
+ }
1558
+ }
1559
+
1560
+ // Sortiere nach Aktivierungsstärke
1561
+ return results.sort((a, b) => b.activation - a.activation);
1562
+ }
1563
+
1564
+ // Finde den stärksten Pfad zwischen zwei Knoten
1565
+ findPath(
1566
+ from: { type: NodeType; id: number },
1567
+ to: { type: NodeType; id: number },
1568
+ maxDepth = 5
1569
+ ): SynapsePath | null {
1570
+ // BFS mit Gewichts-Tracking
1571
+ const visited = new Set<string>();
1572
+ const queue: Array<{
1573
+ node: { type: NodeType; id: number };
1574
+ path: SynapseRecord[];
1575
+ totalWeight: number;
1576
+ }> = [{ node: from, path: [], totalWeight: 1.0 }];
1577
+
1578
+ let bestPath: SynapsePath | null = null;
1579
+
1580
+ while (queue.length > 0) {
1581
+ const current = queue.shift()!;
1582
+ const key = `${current.node.type}:${current.node.id}`;
1583
+
1584
+ if (visited.has(key)) continue;
1585
+ visited.add(key);
1586
+
1587
+ if (current.node.type === to.type && current.node.id === to.id) {
1588
+ if (!bestPath || current.totalWeight > bestPath.totalWeight) {
1589
+ bestPath = {
1590
+ from, to,
1591
+ synapses: current.path,
1592
+ totalWeight: current.totalWeight,
1593
+ hops: current.path.length,
1594
+ };
1595
+ }
1596
+ continue;
1597
+ }
1598
+
1599
+ if (current.path.length >= maxDepth) continue;
1600
+
1601
+ const synapses = this.repo.getOutgoing(current.node.type, current.node.id);
1602
+ for (const synapse of synapses) {
1603
+ queue.push({
1604
+ node: { type: synapse.target_type, id: synapse.target_id },
1605
+ path: [...current.path, synapse],
1606
+ totalWeight: current.totalWeight * synapse.weight,
1607
+ });
1608
+ }
1609
+ }
1610
+
1611
+ return bestPath;
1612
+ }
1613
+ }
1614
+ ```
1615
+
1616
+ ### Synapse-Queries (häufige Abfragen)
1617
+
1618
+ ```typescript
1619
+ class SynapseService {
1620
+ // "Was weiß Brain alles über diesen Error?"
1621
+ getErrorContext(errorId: number): ErrorContext {
1622
+ const activation = this.spreading.activate(
1623
+ { type: 'error', id: errorId },
1624
+ maxDepth: 3
1625
+ );
1626
+
1627
+ return {
1628
+ solutions: activation.filter(a => a.node.type === 'solution'),
1629
+ relatedErrors: activation.filter(a => a.node.type === 'error'),
1630
+ relevantModules: activation.filter(a => a.node.type === 'code_module'),
1631
+ preventionRules: activation.filter(a => a.node.type === 'rule'),
1632
+ insights: activation.filter(a => a.node.type === 'insight'),
1633
+ antipatterns: activation.filter(a => a.node.type === 'antipattern'),
1634
+ };
1635
+ }
1636
+
1637
+ // "Wie hängen Projekt A und Projekt B zusammen?"
1638
+ getProjectRelation(projectIdA: number, projectIdB: number): ProjectRelation {
1639
+ const path = this.spreading.findPath(
1640
+ { type: 'project', id: projectIdA },
1641
+ { type: 'project', id: projectIdB }
1642
+ );
1643
+
1644
+ const sharedErrors = this.repo.findConnected('project', projectIdA, 'project', projectIdB, 'error');
1645
+ const sharedModules = this.repo.findConnected('project', projectIdA, 'project', projectIdB, 'code_module');
1646
+
1647
+ return { path, sharedErrors, sharedModules };
1648
+ }
1649
+
1650
+ // "Was sind die stärksten Verbindungen im ganzen Netzwerk?"
1651
+ getStrongestSynapses(limit = 20): SynapseRecord[] {
1652
+ return this.repo.findByWeight(limit);
1653
+ }
1654
+
1655
+ // Netzwerk-Statistiken
1656
+ getNetworkStats(): NetworkStats {
1657
+ return {
1658
+ totalNodes: this.repo.countNodes(),
1659
+ totalSynapses: this.repo.countSynapses(),
1660
+ avgWeight: this.repo.avgWeight(),
1661
+ strongSynapses: this.repo.countByWeightThreshold(0.7),
1662
+ weakSynapses: this.repo.countByWeightThreshold(0.2, 'below'),
1663
+ synapsesByType: this.repo.countByType(),
1664
+ };
1665
+ }
1666
+ }
1667
+ ```
1668
+
1669
+ ## Research Brain (Forscher-Hirn)
1670
+
1671
+ Das Research Brain läuft als eigener Scheduled Cycle (langsamer als Learning Engine, z.B. alle 60 Minuten) und analysiert das Gesamtnetzwerk aus Errors, Solutions, Code-Modulen und Synapsen.
1672
+
1673
+ ### Forschungs-Zyklus
1674
+
1675
+ ```typescript
1676
+ class ResearchEngine {
1677
+ private timer: NodeJS.Timeout | null = null;
1678
+
1679
+ startSchedule(intervalMs: number): void {
1680
+ // Erster Cycle nach 5 Minuten (Brain soll erstmal Daten sammeln)
1681
+ setTimeout(() => {
1682
+ this.runCycle();
1683
+ this.timer = setInterval(() => this.runCycle(), intervalMs);
1684
+ }, 5 * 60_000);
1685
+ }
1686
+
1687
+ stop(): void {
1688
+ if (this.timer) clearInterval(this.timer);
1689
+ }
1690
+
1691
+ async runCycle(): Promise<ResearchCycleResult> {
1692
+ const result: ResearchCycleResult = {
1693
+ trendsFound: 0,
1694
+ patternsFound: 0,
1695
+ gapsFound: 0,
1696
+ synergiesFound: 0,
1697
+ templatesFound: 0,
1698
+ suggestionsGenerated: 0,
1699
+ };
1700
+
1701
+ // Phase 1: Trend-Analyse
1702
+ // Was wird besser? Was wird schlechter? Zeitreihen über Error-Frequenz, Solution-Erfolgsrate
1703
+ result.trendsFound = await this.analyzeTrends();
1704
+
1705
+ // Phase 2: Gap-Analyse
1706
+ // Wiederkehrende ungelöste Probleme, fehlende Module, schwache Synapsen
1707
+ result.gapsFound = await this.analyzeGaps();
1708
+
1709
+ // Phase 3: Synergie-Detektion
1710
+ // Module die zusammen stark sind, Projekte die voneinander lernen können
1711
+ result.synergiesFound = await this.detectSynergies();
1712
+
1713
+ // Phase 4: Template-Extraktion
1714
+ // Wiederholte Code-Patterns die zu Templates generalisiert werden können
1715
+ result.templatesFound = await this.extractTemplates();
1716
+
1717
+ // Phase 5: Projekt-Vorschläge
1718
+ // Basierend auf vorhandenen Modulen und Patterns: was könnte man noch bauen?
1719
+ result.suggestionsGenerated = await this.generateSuggestions();
1720
+
1721
+ // Phase 6: Insight-Prioritisierung
1722
+ // Bestehende Insights neu bewerten, abgelaufene entfernen
1723
+ await this.prioritizeInsights();
1724
+
1725
+ // Phase 7: Synapsen-Pflege
1726
+ // Schwache Synapsen prunen, starke Cluster identifizieren
1727
+ await this.synapseManager.decayAll();
1728
+
1729
+ return result;
1730
+ }
1731
+ }
1732
+ ```
1733
+
1734
+ ### Trend-Analyse
1735
+
1736
+ ```typescript
1737
+ class TrendAnalyzer {
1738
+ analyze(): Insight[] {
1739
+ const insights: Insight[] = [];
1740
+ const projects = this.projectRepo.getAll();
1741
+
1742
+ for (const project of projects) {
1743
+ // Error-Frequenz über Zeit (letzte 7 Tage vs. 7 Tage davor)
1744
+ const recentErrors = this.errorRepo.countSince(project.id, 7);
1745
+ const previousErrors = this.errorRepo.countBetween(project.id, 14, 7);
1746
+
1747
+ if (previousErrors > 0) {
1748
+ const changeRate = (recentErrors - previousErrors) / previousErrors;
1749
+
1750
+ if (changeRate < -0.3) {
1751
+ insights.push({
1752
+ insight_type: 'trend',
1753
+ title: `Error-Rate in ${project.name} sinkt`,
1754
+ description: `${Math.round(-changeRate * 100)}% weniger Fehler in den letzten 7 Tagen vs. Vorwoche. Was auch immer du machst - es funktioniert.`,
1755
+ evidence: JSON.stringify({ recentErrors, previousErrors, changeRate }),
1756
+ confidence: Math.min(0.9, 0.5 + Math.abs(changeRate) * 0.5),
1757
+ priority: 'low',
1758
+ });
1759
+ } else if (changeRate > 0.5) {
1760
+ insights.push({
1761
+ insight_type: 'trend',
1762
+ title: `Error-Rate in ${project.name} steigt stark`,
1763
+ description: `${Math.round(changeRate * 100)}% mehr Fehler. Mögliche Ursachen prüfen: neue Dependencies, Refactoring, API-Änderungen.`,
1764
+ evidence: JSON.stringify({ recentErrors, previousErrors, changeRate }),
1765
+ confidence: Math.min(0.9, 0.5 + changeRate * 0.3),
1766
+ priority: 'high',
1767
+ });
1768
+ }
1769
+ }
1770
+
1771
+ // Solution-Erfolgsrate-Trend
1772
+ const recentSuccessRate = this.solutionRepo.successRate(project.id, 14);
1773
+ const overallSuccessRate = this.solutionRepo.successRate(project.id);
1774
+
1775
+ if (recentSuccessRate < overallSuccessRate - 0.15) {
1776
+ insights.push({
1777
+ insight_type: 'trend',
1778
+ title: `Lösungsqualität in ${project.name} sinkt`,
1779
+ description: `Aktuelle Erfolgsrate ${Math.round(recentSuccessRate * 100)}% vs. Durchschnitt ${Math.round(overallSuccessRate * 100)}%. Lösungen werden weniger effektiv.`,
1780
+ evidence: JSON.stringify({ recentSuccessRate, overallSuccessRate }),
1781
+ confidence: 0.7,
1782
+ priority: 'medium',
1783
+ actionable: true,
1784
+ suggested_action: JSON.stringify({
1785
+ action: 'review_recent_solutions',
1786
+ message: 'Letzte Lösungen prüfen - stimmen die Ansätze noch?',
1787
+ }),
1788
+ });
1789
+ }
1790
+ }
1791
+
1792
+ return insights;
1793
+ }
1794
+ }
1795
+ ```
1796
+
1797
+ ### Gap-Analyse
1798
+
1799
+ ```typescript
1800
+ class GapAnalyzer {
1801
+ analyze(): Insight[] {
1802
+ const insights: Insight[] = [];
1803
+
1804
+ // 1. Wiederkehrende ungelöste Errors
1805
+ const unresolvedRecurring = this.errorRepo.findUnresolvedRecurring(5);
1806
+ for (const error of unresolvedRecurring) {
1807
+ insights.push({
1808
+ insight_type: 'gap',
1809
+ title: `Ungelöster wiederkehrender Fehler: ${error.error_type}`,
1810
+ description: `"${error.message.substring(0, 80)}..." ist ${error.occurrence_count}x aufgetreten und hat keine erfolgreiche Lösung. Das kostet Zeit.`,
1811
+ evidence: JSON.stringify({ errorId: error.id, occurrences: error.occurrence_count }),
1812
+ confidence: Math.min(0.95, 0.5 + error.occurrence_count * 0.1),
1813
+ priority: error.occurrence_count >= 10 ? 'critical' : 'high',
1814
+ actionable: true,
1815
+ suggested_action: JSON.stringify({
1816
+ action: 'investigate_error',
1817
+ error_id: error.id,
1818
+ message: 'Grundursache untersuchen und nachhaltige Lösung finden',
1819
+ }),
1820
+ });
1821
+ }
1822
+
1823
+ // 2. Fehlende Code-Module (Funktionalität die in mehreren Projekten gebraucht wird)
1824
+ const commonErrors = this.findCommonErrorPatternsAcrossProjects();
1825
+ for (const pattern of commonErrors) {
1826
+ if (pattern.projectCount >= 2 && !pattern.hasSolution) {
1827
+ insights.push({
1828
+ insight_type: 'gap',
1829
+ title: `Gemeinsames Problem ohne gemeinsame Lösung`,
1830
+ description: `${pattern.projectCount} Projekte haben "${pattern.errorTemplate}" - aber kein geteiltes Modul löst das.`,
1831
+ confidence: 0.7,
1832
+ priority: 'medium',
1833
+ actionable: true,
1834
+ suggested_action: JSON.stringify({
1835
+ action: 'create_shared_module',
1836
+ message: `Shared utility erstellen das ${pattern.errorTemplate} in allen Projekten verhindert`,
1837
+ }),
1838
+ });
1839
+ }
1840
+ }
1841
+
1842
+ // 3. Schwache Synapsen-Cluster (isolierte Knoten ohne Verbindungen)
1843
+ const isolated = this.synapseRepo.findIsolatedNodes();
1844
+ if (isolated.errors.length > 5) {
1845
+ insights.push({
1846
+ insight_type: 'gap',
1847
+ title: `${isolated.errors.length} Fehler ohne Vernetzung`,
1848
+ description: `Diese Fehler haben keine Synapsen zu Lösungen, Modulen oder anderen Fehlern. Brain kann sie nicht einordnen.`,
1849
+ confidence: 0.6,
1850
+ priority: 'low',
1851
+ });
1852
+ }
1853
+
1854
+ return insights;
1855
+ }
1856
+ }
1857
+ ```
1858
+
1859
+ ### Synergie-Detektion
1860
+
1861
+ ```typescript
1862
+ class SynergyDetector {
1863
+ detect(): Insight[] {
1864
+ const insights: Insight[] = [];
1865
+
1866
+ // 1. Module die zusammen genutzt werden (starke co_occurs Synapsen)
1867
+ const modulePairs = this.synapseRepo.findStrongPairs('code_module', 'code_module', 'co_occurs', 0.5);
1868
+ for (const pair of modulePairs) {
1869
+ insights.push({
1870
+ insight_type: 'synergy',
1871
+ title: `Module "${pair.sourceName}" + "${pair.targetName}" sind ein starkes Team`,
1872
+ description: `Diese Module werden in ${pair.coUsageCount} Projekten zusammen genutzt. Zusammen als Package veröffentlichen?`,
1873
+ evidence: JSON.stringify(pair),
1874
+ confidence: Math.min(0.9, pair.weight),
1875
+ priority: 'medium',
1876
+ actionable: true,
1877
+ suggested_action: JSON.stringify({
1878
+ action: 'combine_modules',
1879
+ module_ids: [pair.sourceId, pair.targetId],
1880
+ message: 'Zu einem kombinierten Package zusammenfassen',
1881
+ }),
1882
+ });
1883
+ }
1884
+
1885
+ // 2. Projekte die voneinander lernen können
1886
+ const projectPairs = this.findProjectSynergies();
1887
+ for (const pair of projectPairs) {
1888
+ if (pair.transferableSolutions.length >= 2) {
1889
+ insights.push({
1890
+ insight_type: 'synergy',
1891
+ title: `${pair.projectA.name} hat Lösungen die ${pair.projectB.name} braucht`,
1892
+ description: `${pair.transferableSolutions.length} Lösungen aus ${pair.projectA.name} könnten in ${pair.projectB.name} helfen.`,
1893
+ evidence: JSON.stringify(pair.transferableSolutions.map(s => s.id)),
1894
+ confidence: 0.7,
1895
+ priority: 'medium',
1896
+ actionable: true,
1897
+ });
1898
+ }
1899
+ }
1900
+
1901
+ // 3. Error-Solution-Chains die sich zu einem Workflow zusammensetzen lassen
1902
+ const workflows = this.findWorkflowPatterns();
1903
+ for (const wf of workflows) {
1904
+ insights.push({
1905
+ insight_type: 'synergy',
1906
+ title: `Wiederkehrender Workflow erkannt: ${wf.name}`,
1907
+ description: `Die Sequenz ${wf.steps.join(' → ')} wiederholt sich. Automatisierung möglich?`,
1908
+ evidence: JSON.stringify(wf),
1909
+ confidence: wf.occurrences >= 3 ? 0.8 : 0.5,
1910
+ priority: wf.occurrences >= 5 ? 'high' : 'medium',
1911
+ actionable: true,
1912
+ suggested_action: JSON.stringify({
1913
+ action: 'automate_workflow',
1914
+ steps: wf.steps,
1915
+ message: 'Script oder Template erstellen das diese Sequenz automatisiert',
1916
+ }),
1917
+ });
1918
+ }
1919
+
1920
+ return insights;
1921
+ }
1922
+ }
1923
+ ```
1924
+
1925
+ ### Template-Extraktion
1926
+
1927
+ ```typescript
1928
+ class TemplateExtractor {
1929
+ extract(): Insight[] {
1930
+ const insights: Insight[] = [];
1931
+
1932
+ // Finde Code-Module die in >= 3 Projekten in adaptierter Form existieren
1933
+ const adaptedModules = this.codeModuleRepo.findWithMultipleAdaptations(3);
1934
+
1935
+ for (const group of adaptedModules) {
1936
+ // Extrahiere das Gemeinsame aus allen Adaptationen
1937
+ const commonStructure = this.findCommonStructure(group.modules);
1938
+
1939
+ if (commonStructure.similarity >= 0.6) {
1940
+ insights.push({
1941
+ insight_type: 'template_candidate',
1942
+ title: `Template-Kandidat: "${group.baseName}"`,
1943
+ description: `${group.modules.length} Varianten in ${group.projectCount} Projekten. Gemeinsame Struktur: ${Math.round(commonStructure.similarity * 100)}%. Ein parametrisiertes Template würde Duplikation eliminieren.`,
1944
+ evidence: JSON.stringify({
1945
+ moduleIds: group.modules.map(m => m.id),
1946
+ commonParts: commonStructure.commonParts,
1947
+ variableParts: commonStructure.variableParts,
1948
+ }),
1949
+ confidence: commonStructure.similarity,
1950
+ priority: group.projectCount >= 3 ? 'high' : 'medium',
1951
+ actionable: true,
1952
+ suggested_action: JSON.stringify({
1953
+ action: 'create_template',
1954
+ base_module_id: group.bestModule.id,
1955
+ parameters: commonStructure.variableParts,
1956
+ message: `Template erstellen mit Parametern: ${commonStructure.variableParts.join(', ')}`,
1957
+ }),
1958
+ });
1959
+
1960
+ // Synapse: Template-Insight → alle beteiligten Module
1961
+ for (const mod of group.modules) {
1962
+ this.synapseManager.strengthen(
1963
+ { type: 'insight', id: insights[insights.length - 1].id! },
1964
+ { type: 'code_module', id: mod.id },
1965
+ 'generalizes'
1966
+ );
1967
+ }
1968
+ }
1969
+ }
1970
+
1971
+ return insights;
1972
+ }
1973
+ }
1974
+ ```
1975
+
1976
+ ### Projekt-Vorschläge
1977
+
1978
+ ```typescript
1979
+ class ProjectSuggestionGenerator {
1980
+ generate(): Insight[] {
1981
+ const insights: Insight[] = [];
1982
+ const modules = this.codeModuleRepo.getAll();
1983
+ const projects = this.projectRepo.getAll();
1984
+
1985
+ // 1. Analyse: Welche Funktionalität existiert bereits verteilt?
1986
+ const capabilities = this.categorizeModules(modules);
1987
+
1988
+ // Beispiel: Wenn du auth, database, api-client, validation hast → "Du könntest ein Backend-Template bauen"
1989
+ const templateSuggestions = this.checkForProjectTemplates(capabilities);
1990
+ for (const suggestion of templateSuggestions) {
1991
+ insights.push({
1992
+ insight_type: 'project_suggestion',
1993
+ title: suggestion.title,
1994
+ description: suggestion.description,
1995
+ evidence: JSON.stringify(suggestion.modules),
1996
+ confidence: suggestion.coverage,
1997
+ priority: suggestion.coverage >= 0.7 ? 'medium' : 'low',
1998
+ actionable: true,
1999
+ suggested_action: JSON.stringify({
2000
+ action: 'create_project_template',
2001
+ modules: suggestion.modules,
2002
+ message: suggestion.description,
2003
+ }),
2004
+ });
2005
+ }
2006
+
2007
+ // 2. Schwachstellen die ein eigenes Tool verdienen
2008
+ const recurringPain = this.findRecurringPainPoints();
2009
+ for (const pain of recurringPain) {
2010
+ insights.push({
2011
+ insight_type: 'project_suggestion',
2012
+ title: `Tool-Idee: ${pain.suggestedToolName}`,
2013
+ description: `Du verbringst wiederholt Zeit mit "${pain.description}". Ein dediziertes Tool könnte das automatisieren.`,
2014
+ evidence: JSON.stringify(pain.evidence),
2015
+ confidence: pain.confidence,
2016
+ priority: pain.timeWasted >= 10 ? 'high' : 'medium',
2017
+ actionable: true,
2018
+ });
2019
+ }
2020
+
2021
+ return insights;
2022
+ }
2023
+
2024
+ private checkForProjectTemplates(
2025
+ capabilities: Map<string, CodeModule[]>
2026
+ ): ProjectTemplateSuggestion[] {
2027
+ const suggestions: ProjectTemplateSuggestion[] = [];
2028
+
2029
+ // Bekannte Kombinationen die ein Projekt ergeben
2030
+ const templates: Array<{ name: string; required: string[]; optional: string[] }> = [
2031
+ {
2032
+ name: 'REST API Template',
2033
+ required: ['http-server', 'routing', 'database', 'validation'],
2034
+ optional: ['auth', 'logging', 'rate-limiting', 'caching'],
2035
+ },
2036
+ {
2037
+ name: 'CLI Tool Template',
2038
+ required: ['argument-parsing', 'config', 'logging'],
2039
+ optional: ['interactive-prompts', 'progress-bar', 'file-operations'],
2040
+ },
2041
+ {
2042
+ name: 'Data Pipeline Template',
2043
+ required: ['file-reading', 'data-transformation', 'output-writing'],
2044
+ optional: ['validation', 'error-handling', 'progress-tracking'],
2045
+ },
2046
+ ];
2047
+
2048
+ for (const template of templates) {
2049
+ const foundRequired = template.required.filter(r => capabilities.has(r));
2050
+ const foundOptional = template.optional.filter(o => capabilities.has(o));
2051
+ const coverage = foundRequired.length / template.required.length;
2052
+
2053
+ if (coverage >= 0.5) {
2054
+ suggestions.push({
2055
+ title: template.name,
2056
+ description: `Du hast ${foundRequired.length}/${template.required.length} Kern-Module und ${foundOptional.length} Extras. ${coverage >= 0.75 ? 'Fast komplett!' : 'Guter Anfang.'}`,
2057
+ modules: [...foundRequired, ...foundOptional].flatMap(c => capabilities.get(c) || []),
2058
+ coverage,
2059
+ });
2060
+ }
2061
+ }
2062
+
2063
+ return suggestions;
2064
+ }
2065
+ }
2066
+ ```
2067
+
2068
+ ## Error-Parser Registry
2069
+
2070
+ ```typescript
2071
+ interface ErrorParser {
2072
+ name: string;
2073
+ priority: number; // Höher = wird zuerst versucht
2074
+ canParse: (input: string) => boolean; // Kann dieser Parser den Input verarbeiten?
2075
+ parse: (input: string) => ParsedError | null;
2076
+ }
2077
+
2078
+ interface ParsedError {
2079
+ errorType: string;
2080
+ message: string;
2081
+ stackTrace?: string;
2082
+ frames: StackFrame[];
2083
+ sourceFile?: string;
2084
+ sourceLine?: number;
2085
+ language?: string;
2086
+ }
2087
+
2088
+ class ErrorParserRegistry {
2089
+ private parsers: ErrorParser[] = [];
2090
+
2091
+ register(parser: ErrorParser): void {
2092
+ this.parsers.push(parser);
2093
+ this.parsers.sort((a, b) => b.priority - a.priority);
2094
+ }
2095
+
2096
+ parse(input: string): ParsedError | null {
2097
+ for (const parser of this.parsers) {
2098
+ if (parser.canParse(input)) {
2099
+ const result = parser.parse(input);
2100
+ if (result) return result;
2101
+ }
2102
+ }
2103
+ return null;
2104
+ }
2105
+ }
2106
+
2107
+ // Beispiel: Node.js Parser
2108
+ const nodeParser: ErrorParser = {
2109
+ name: 'node',
2110
+ priority: 10,
2111
+ canParse: (input) =>
2112
+ /at .+ \(.+:\d+:\d+\)/.test(input) || // V8 Stack-Trace
2113
+ /^\w*Error:/.test(input) || // Error: ...
2114
+ /^\w*TypeError:/.test(input), // TypeError: ...
2115
+ parse: (input) => {
2116
+ const messageMatch = input.match(/^(\w+(?:Error|Exception)?): (.+)$/m);
2117
+ if (!messageMatch) return null;
2118
+
2119
+ const frames: StackFrame[] = [];
2120
+ const frameRegex = /at (?:(.+?) )?\((.+?):(\d+):(\d+)\)/g;
2121
+ let match;
2122
+ while ((match = frameRegex.exec(input)) !== null) {
2123
+ frames.push({
2124
+ function_name: match[1] || '<anonymous>',
2125
+ file_path: match[2],
2126
+ line_number: parseInt(match[3]),
2127
+ column_number: parseInt(match[4]),
2128
+ });
2129
+ }
2130
+
2131
+ return {
2132
+ errorType: messageMatch[1],
2133
+ message: messageMatch[2],
2134
+ stackTrace: input,
2135
+ frames,
2136
+ sourceFile: frames[0]?.file_path,
2137
+ sourceLine: frames[0]?.line_number,
2138
+ language: 'javascript',
2139
+ };
2140
+ }
2141
+ };
2142
+
2143
+ // Beispiel: Python Parser
2144
+ const pythonParser: ErrorParser = {
2145
+ name: 'python',
2146
+ priority: 10,
2147
+ canParse: (input) =>
2148
+ /Traceback \(most recent call last\)/.test(input) ||
2149
+ /File ".+", line \d+/.test(input),
2150
+ parse: (input) => {
2151
+ const frames: StackFrame[] = [];
2152
+ const frameRegex = /File "(.+?)", line (\d+), in (.+)/g;
2153
+ let match;
2154
+ while ((match = frameRegex.exec(input)) !== null) {
2155
+ frames.push({
2156
+ function_name: match[3],
2157
+ file_path: match[1],
2158
+ line_number: parseInt(match[2]),
2159
+ });
2160
+ }
2161
+
2162
+ const errorMatch = input.match(/^(\w+(?:Error|Exception)?): (.+)$/m);
2163
+ return {
2164
+ errorType: errorMatch?.[1] || 'Error',
2165
+ message: errorMatch?.[2] || input.split('\n').pop() || input,
2166
+ stackTrace: input,
2167
+ frames,
2168
+ sourceFile: frames[frames.length - 1]?.file_path,
2169
+ sourceLine: frames[frames.length - 1]?.line_number,
2170
+ language: 'python',
2171
+ };
2172
+ }
2173
+ };
2174
+
2175
+ // Beispiel: Shell Parser
2176
+ const shellParser: ErrorParser = {
2177
+ name: 'shell',
2178
+ priority: 5,
2179
+ canParse: (input) =>
2180
+ /command not found/.test(input) ||
2181
+ /Permission denied/.test(input) ||
2182
+ /No such file or directory/.test(input) ||
2183
+ /ENOENT|EACCES|ECONNREFUSED/.test(input),
2184
+ parse: (input) => {
2185
+ const message = input.split('\n')[0].trim();
2186
+ let errorType = 'ShellError';
2187
+ if (/command not found/.test(input)) errorType = 'CommandNotFound';
2188
+ if (/Permission denied|EACCES/.test(input)) errorType = 'PermissionError';
2189
+ if (/No such file|ENOENT/.test(input)) errorType = 'FileNotFound';
2190
+ if (/ECONNREFUSED/.test(input)) errorType = 'ConnectionRefused';
2191
+
2192
+ return {
2193
+ errorType,
2194
+ message,
2195
+ frames: [],
2196
+ language: 'shell',
2197
+ };
2198
+ }
2199
+ };
2200
+
2201
+ // Generischer Fallback
2202
+ const genericParser: ErrorParser = {
2203
+ name: 'generic',
2204
+ priority: 0,
2205
+ canParse: () => true, // Fängt alles auf
2206
+ parse: (input) => {
2207
+ const firstLine = input.split('\n')[0].trim();
2208
+ const errorMatch = firstLine.match(/^(?:error|Error|ERROR)[\s:]+(.+)/i);
2209
+ return {
2210
+ errorType: 'GenericError',
2211
+ message: errorMatch?.[1] || firstLine,
2212
+ stackTrace: input.includes('\n') ? input : undefined,
2213
+ frames: [],
2214
+ };
2215
+ }
2216
+ };
2217
+ ```
2218
+
2219
+ ## IPC-Architektur
2220
+
2221
+ ### Protocol (Length-prefixed JSON Framing)
2222
+ ```typescript
2223
+ // Framing: [4 Byte Length (Big Endian)][JSON Payload]
2224
+ // Kein Delimiter-Problem, keine partielle Message Issues
2225
+
2226
+ interface IpcMessage {
2227
+ id: string; // Request-ID für Response-Zuordnung
2228
+ type: 'request' | 'response' | 'notification';
2229
+ method?: string; // z.B. 'error.report', 'code.find'
2230
+ params?: unknown;
2231
+ result?: unknown;
2232
+ error?: { code: number; message: string };
2233
+ }
2234
+
2235
+ function encodeMessage(msg: IpcMessage): Buffer {
2236
+ const json = JSON.stringify(msg);
2237
+ const payload = Buffer.from(json, 'utf8');
2238
+ const frame = Buffer.alloc(4 + payload.length);
2239
+ frame.writeUInt32BE(payload.length, 0);
2240
+ payload.copy(frame, 4);
2241
+ return frame;
2242
+ }
2243
+
2244
+ class MessageDecoder {
2245
+ private buffer = Buffer.alloc(0);
2246
+
2247
+ feed(chunk: Buffer): IpcMessage[] {
2248
+ this.buffer = Buffer.concat([this.buffer, chunk]);
2249
+ const messages: IpcMessage[] = [];
2250
+
2251
+ while (this.buffer.length >= 4) {
2252
+ const length = this.buffer.readUInt32BE(0);
2253
+ if (this.buffer.length < 4 + length) break;
2254
+
2255
+ const json = this.buffer.subarray(4, 4 + length).toString('utf8');
2256
+ this.buffer = this.buffer.subarray(4 + length);
2257
+ messages.push(JSON.parse(json));
2258
+ }
2259
+ return messages;
2260
+ }
2261
+ }
2262
+ ```
2263
+
2264
+ ### IPC Router
2265
+ ```typescript
2266
+ const methods = {
2267
+ // Terminal Lifecycle
2268
+ 'terminal.register': (p) => terminalService.register(p),
2269
+ 'terminal.heartbeat': (p) => terminalService.heartbeat(p),
2270
+ 'terminal.disconnect': (p) => terminalService.disconnect(p),
2271
+
2272
+ // Error Brain
2273
+ 'error.report': (p) => errorService.report(p),
2274
+ 'error.query': (p) => errorService.query(p),
2275
+ 'error.match': (p) => errorService.matchSimilar(p),
2276
+ 'solution.report': (p) => solutionService.report(p),
2277
+ 'solution.query': (p) => solutionService.query(p),
2278
+ 'solution.rate': (p) => solutionService.rateOutcome(p),
2279
+ 'solution.attempt': (p) => solutionService.reportAttempt(p),
2280
+
2281
+ // Code Brain
2282
+ 'code.analyze': (p) => codeService.analyzeAndRegister(p),
2283
+ 'code.find': (p) => codeService.findReusable(p),
2284
+ 'code.similarity': (p) => codeService.checkSimilarity(p),
2285
+ 'code.modules': (p) => codeService.listModules(p),
2286
+ 'code.usage': (p) => codeService.reportUsage(p),
2287
+
2288
+ // Prevention
2289
+ 'prevention.check': (p) => preventionService.checkRules(p),
2290
+ 'prevention.antipatterns': (p) => preventionService.checkAntipatterns(p),
2291
+
2292
+ // Synapsen
2293
+ 'synapse.context': (p) => synapseService.getErrorContext(p),
2294
+ 'synapse.path': (p) => synapseService.findPath(p),
2295
+ 'synapse.related': (p) => synapseService.getRelated(p),
2296
+ 'synapse.stats': (p) => synapseService.getNetworkStats(),
2297
+
2298
+ // Research / Insights
2299
+ 'research.insights': (p) => researchService.getInsights(p),
2300
+ 'research.suggest': (p) => researchService.getSuggestions(p),
2301
+ 'research.trends': (p) => researchService.getTrends(p),
2302
+
2303
+ // Notifications
2304
+ 'notification.list': (p) => notificationService.list(p),
2305
+ 'notification.ack': (p) => notificationService.acknowledge(p),
2306
+
2307
+ // Analytics
2308
+ 'analytics.summary': (p) => analyticsService.getSummary(p),
2309
+ 'analytics.network': (p) => analyticsService.getNetworkOverview(p),
2310
+ };
2311
+ ```
2312
+
2313
+ ### Named Pipe Server
2314
+ ```typescript
2315
+ import net from 'net';
2316
+
2317
+ class IpcServer {
2318
+ private server: net.Server;
2319
+ private clients = new Map<string, net.Socket>();
2320
+
2321
+ constructor(
2322
+ private router: IpcRouter,
2323
+ private config: IpcConfig
2324
+ ) {}
2325
+
2326
+ start(): void {
2327
+ this.server = net.createServer((socket) => {
2328
+ const clientId = randomUUID();
2329
+ this.clients.set(clientId, socket);
2330
+ const decoder = new MessageDecoder();
2331
+
2332
+ socket.on('data', (chunk) => {
2333
+ const messages = decoder.feed(chunk);
2334
+ for (const msg of messages) {
2335
+ this.handleMessage(clientId, msg, socket);
2336
+ }
2337
+ });
2338
+
2339
+ socket.on('close', () => {
2340
+ this.clients.delete(clientId);
2341
+ });
2342
+
2343
+ socket.on('error', (err) => {
2344
+ logger.error(`Client ${clientId} error:`, err);
2345
+ this.clients.delete(clientId);
2346
+ });
2347
+ });
2348
+
2349
+ this.server.listen(this.config.pipeName);
2350
+ logger.info(`IPC server listening on ${this.config.pipeName}`);
2351
+ }
2352
+
2353
+ private async handleMessage(clientId: string, msg: IpcMessage, socket: net.Socket): Promise<void> {
2354
+ if (msg.type !== 'request' || !msg.method) return;
2355
+
2356
+ try {
2357
+ const result = await this.router.handle(msg.method, msg.params);
2358
+ socket.write(encodeMessage({
2359
+ id: msg.id,
2360
+ type: 'response',
2361
+ result,
2362
+ }));
2363
+ } catch (err) {
2364
+ socket.write(encodeMessage({
2365
+ id: msg.id,
2366
+ type: 'response',
2367
+ error: { code: -1, message: String(err) },
2368
+ }));
2369
+ }
2370
+ }
2371
+
2372
+ notify(terminalId: string | null, notification: IpcMessage): void {
2373
+ if (terminalId) {
2374
+ const socket = this.clients.get(terminalId);
2375
+ if (socket && !socket.destroyed) socket.write(encodeMessage(notification));
2376
+ } else {
2377
+ for (const socket of this.clients.values()) {
2378
+ if (!socket.destroyed) socket.write(encodeMessage(notification));
2379
+ }
2380
+ }
2381
+ }
2382
+
2383
+ stop(): void {
2384
+ for (const socket of this.clients.values()) {
2385
+ socket.destroy();
2386
+ }
2387
+ this.server.close();
2388
+ }
2389
+ }
2390
+ ```
2391
+
2392
+ ## MCP Server
2393
+
2394
+ Der MCP Server läuft als eigener Prozess pro Claude-Session (stdio Transport). Er ist ein Thin Client der alle Anfragen via Named Pipe an den Brain Daemon weiterleitet.
2395
+
2396
+ ### MCP Tool-Definitionen
2397
+
2398
+ ```typescript
2399
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2400
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2401
+
2402
+ const server = new McpServer({
2403
+ name: 'brain',
2404
+ version: '1.0.0',
2405
+ });
2406
+
2407
+ // === Error Brain Tools ===
2408
+
2409
+ server.tool(
2410
+ 'brain_report_error',
2411
+ 'Report an error that occurred. Brain will store it, match it against known errors, and return solutions if available.',
2412
+ {
2413
+ error_output: { type: 'string', description: 'The raw error output from the terminal' },
2414
+ command: { type: 'string', description: 'The command that caused the error' },
2415
+ task_context: { type: 'string', description: 'What was the user trying to accomplish' },
2416
+ working_directory: { type: 'string', description: 'Working directory when error occurred' },
2417
+ },
2418
+ async (params) => {
2419
+ const result = await ipcClient.request('error.report', params);
2420
+ // Sofort nach ähnlichen Fehlern suchen
2421
+ const matches = await ipcClient.request('error.match', { error_id: result.error_id });
2422
+ return formatErrorReportResponse(result, matches);
2423
+ }
2424
+ );
2425
+
2426
+ server.tool(
2427
+ 'brain_query_error',
2428
+ 'Search for similar errors and their solutions in the Brain database.',
2429
+ {
2430
+ query: { type: 'string', description: 'Error message or description to search for' },
2431
+ project_only: { type: 'boolean', description: 'Only search in current project (default: false)' },
2432
+ },
2433
+ async (params) => {
2434
+ const results = await ipcClient.request('error.query', params);
2435
+ return formatErrorQueryResponse(results);
2436
+ }
2437
+ );
2438
+
2439
+ server.tool(
2440
+ 'brain_report_solution',
2441
+ 'Report a successful solution for an error. Brain will learn from this.',
2442
+ {
2443
+ error_id: { type: 'number', description: 'The error ID this solution fixes' },
2444
+ title: { type: 'string', description: 'Short title of the solution' },
2445
+ description: { type: 'string', description: 'What was done to fix the error' },
2446
+ code_before: { type: 'string', description: 'Code before the fix (optional)' },
2447
+ code_after: { type: 'string', description: 'Code after the fix (optional)' },
2448
+ diff: { type: 'string', description: 'Diff of the changes (optional)' },
2449
+ },
2450
+ async (params) => {
2451
+ const result = await ipcClient.request('solution.report', params);
2452
+ return formatSolutionReportResponse(result);
2453
+ }
2454
+ );
2455
+
2456
+ server.tool(
2457
+ 'brain_report_attempt',
2458
+ 'Report a failed solution attempt. Brain learns what does NOT work.',
2459
+ {
2460
+ error_id: { type: 'number', description: 'The error ID' },
2461
+ description: { type: 'string', description: 'What was tried' },
2462
+ reason: { type: 'string', description: 'Why it did not work' },
2463
+ },
2464
+ async (params) => {
2465
+ const result = await ipcClient.request('solution.attempt', params);
2466
+ return formatAttemptResponse(result);
2467
+ }
2468
+ );
2469
+
2470
+ // === Code Brain Tools ===
2471
+
2472
+ server.tool(
2473
+ 'brain_find_reusable_code',
2474
+ 'Search for reusable code modules from other projects. Use when starting new functionality.',
2475
+ {
2476
+ purpose: { type: 'string', description: 'What the code should do (e.g., "retry with backoff", "JWT authentication")' },
2477
+ language: { type: 'string', description: 'Programming language' },
2478
+ category: { type: 'string', description: 'Category: utility, middleware, config, hook, component, service (optional)' },
2479
+ },
2480
+ async (params) => {
2481
+ const results = await ipcClient.request('code.find', params);
2482
+ return formatCodeSearchResponse(results);
2483
+ }
2484
+ );
2485
+
2486
+ server.tool(
2487
+ 'brain_register_code',
2488
+ 'Register a code module as reusable. Brain will analyze it and make it available to other projects.',
2489
+ {
2490
+ source_code: { type: 'string', description: 'The source code' },
2491
+ file_path: { type: 'string', description: 'File path relative to project root' },
2492
+ name: { type: 'string', description: 'Module name (optional - Brain will auto-detect)' },
2493
+ purpose: { type: 'string', description: 'What this code does (optional - Brain will analyze)' },
2494
+ },
2495
+ async (params) => {
2496
+ const result = await ipcClient.request('code.analyze', params);
2497
+ return formatCodeRegisterResponse(result);
2498
+ }
2499
+ );
2500
+
2501
+ server.tool(
2502
+ 'brain_check_code_similarity',
2503
+ 'Check if similar code already exists in other projects before writing new code.',
2504
+ {
2505
+ source_code: { type: 'string', description: 'The code to check' },
2506
+ file_path: { type: 'string', description: 'File path for context' },
2507
+ },
2508
+ async (params) => {
2509
+ const results = await ipcClient.request('code.similarity', params);
2510
+ return formatSimilarityResponse(results);
2511
+ }
2512
+ );
2513
+
2514
+ // === Synapsen-Netzwerk Tools ===
2515
+
2516
+ server.tool(
2517
+ 'brain_explore',
2518
+ 'Explore what Brain knows about a topic. Uses spreading activation through the synapse network to find connected errors, solutions, modules, and insights.',
2519
+ {
2520
+ node_type: { type: 'string', description: 'Type: error, solution, code_module, project' },
2521
+ node_id: { type: 'number', description: 'ID of the node to explore from' },
2522
+ max_depth: { type: 'number', description: 'How many hops to follow (default: 3)' },
2523
+ },
2524
+ async (params) => {
2525
+ const context = await ipcClient.request('synapse.context', params);
2526
+ return formatExploreResponse(context);
2527
+ }
2528
+ );
2529
+
2530
+ server.tool(
2531
+ 'brain_connections',
2532
+ 'Find how two things are connected in Brain (e.g., how an error relates to a code module).',
2533
+ {
2534
+ from_type: { type: 'string', description: 'Source type: error, solution, code_module, project' },
2535
+ from_id: { type: 'number', description: 'Source ID' },
2536
+ to_type: { type: 'string', description: 'Target type' },
2537
+ to_id: { type: 'number', description: 'Target ID' },
2538
+ },
2539
+ async (params) => {
2540
+ const path = await ipcClient.request('synapse.path', params);
2541
+ return formatPathResponse(path);
2542
+ }
2543
+ );
2544
+
2545
+ // === Research Brain Tools ===
2546
+
2547
+ server.tool(
2548
+ 'brain_insights',
2549
+ 'Get research insights: trends, gaps, synergies, template candidates, and project suggestions.',
2550
+ {
2551
+ type: { type: 'string', description: 'Filter by type: trend, pattern, gap, synergy, optimization, template_candidate, project_suggestion, warning (optional)' },
2552
+ priority: { type: 'string', description: 'Minimum priority: low, medium, high, critical (optional)' },
2553
+ },
2554
+ async (params) => {
2555
+ const insights = await ipcClient.request('research.insights', params);
2556
+ return formatInsightsResponse(insights);
2557
+ }
2558
+ );
2559
+
2560
+ server.tool(
2561
+ 'brain_suggest',
2562
+ 'Ask Brain for suggestions: what to build next, what to improve, what patterns to extract.',
2563
+ {
2564
+ context: { type: 'string', description: 'Current context or question (e.g., "starting new project", "looking for optimizations")' },
2565
+ },
2566
+ async (params) => {
2567
+ const suggestions = await ipcClient.request('research.suggest', params);
2568
+ return formatSuggestionsResponse(suggestions);
2569
+ }
2570
+ );
2571
+
2572
+ // === Status & Notifications ===
2573
+
2574
+ server.tool(
2575
+ 'brain_status',
2576
+ 'Get current Brain status: connected terminals, error count, solutions, code modules, synapse network, and research insights.',
2577
+ {},
2578
+ async () => {
2579
+ const summary = await ipcClient.request('analytics.summary', {});
2580
+ const network = await ipcClient.request('synapse.stats', {});
2581
+ const notifications = await ipcClient.request('notification.list', { unacknowledged: true });
2582
+ return formatStatusResponse(summary, network, notifications);
2583
+ }
2584
+ );
2585
+
2586
+ server.tool(
2587
+ 'brain_notifications',
2588
+ 'Get pending notifications (new solutions, recurring errors, research insights, synergy suggestions).',
2589
+ {},
2590
+ async () => {
2591
+ const notifications = await ipcClient.request('notification.list', { unacknowledged: true });
2592
+ return formatNotificationsResponse(notifications);
2593
+ }
2594
+ );
2595
+
2596
+ // Server starten
2597
+ const transport = new StdioServerTransport();
2598
+ await server.connect(transport);
2599
+ ```
2600
+
2601
+ ## Claude Code Hooks
2602
+
2603
+ ### Hook-Konfiguration
2604
+
2605
+ In jeder Projekt-`.claude/settings.json`:
2606
+ ```json
2607
+ {
2608
+ "hooks": {
2609
+ "PostToolUse": [
2610
+ {
2611
+ "matcher": { "tool_name": "Bash" },
2612
+ "command": "node /path/to/brain/dist/hooks/post-tool-use.js"
2613
+ }
2614
+ ]
2615
+ }
2616
+ }
2617
+ ```
2618
+
2619
+ Oder global in `~/.claude/settings.json`:
2620
+ ```json
2621
+ {
2622
+ "hooks": {
2623
+ "PostToolUse": [
2624
+ {
2625
+ "matcher": { "tool_name": "Bash" },
2626
+ "command": "node /path/to/brain/dist/hooks/post-tool-use.js"
2627
+ }
2628
+ ]
2629
+ }
2630
+ }
2631
+ ```
2632
+
2633
+ ### Hook-Script (auto-detect.ts)
2634
+
2635
+ ```typescript
2636
+ // hooks/post-tool-use.ts
2637
+ // Wird nach jedem Bash-Tool-Aufruf ausgeführt
2638
+ // Erhält Tool-Input und Output via stdin als JSON
2639
+
2640
+ import { IpcClient } from '../ipc/client.js';
2641
+
2642
+ interface HookInput {
2643
+ tool_name: string;
2644
+ tool_input: { command: string };
2645
+ tool_output: string;
2646
+ exit_code?: number;
2647
+ }
2648
+
2649
+ async function main() {
2650
+ // Hook-Input von stdin lesen
2651
+ const input: HookInput = JSON.parse(await readStdin());
2652
+
2653
+ // Nur bei Fehlern reagieren
2654
+ if (!isError(input)) return;
2655
+
2656
+ const client = new IpcClient();
2657
+ try {
2658
+ await client.connect();
2659
+
2660
+ // Error an Brain melden
2661
+ const result = await client.request('error.report', {
2662
+ raw_output: input.tool_output,
2663
+ command: input.tool_input.command,
2664
+ auto_detected: true,
2665
+ });
2666
+
2667
+ // Wenn Brain eine Lösung kennt, als Feedback ausgeben
2668
+ if (result.matches?.length > 0) {
2669
+ const best = result.matches[0];
2670
+ console.log(`Brain: Similar error found (#${best.error_id}, ${Math.round(best.score * 100)}% match)`);
2671
+ if (best.solutions?.length > 0) {
2672
+ console.log(`Brain: Solution available - use brain_query_error to see details`);
2673
+ }
2674
+ }
2675
+
2676
+ // Anti-Pattern Check
2677
+ const antipatterns = await client.request('prevention.antipatterns', {
2678
+ error_output: input.tool_output,
2679
+ });
2680
+ if (antipatterns?.length > 0) {
2681
+ console.log(`Brain WARNING: Known anti-pattern detected: ${antipatterns[0].description}`);
2682
+ }
2683
+
2684
+ } catch {
2685
+ // Hook darf nie den Workflow blockieren - stille Fehler
2686
+ } finally {
2687
+ client.disconnect();
2688
+ }
2689
+ }
2690
+
2691
+ function isError(input: HookInput): boolean {
2692
+ // Exit-Code Check
2693
+ if (input.exit_code !== undefined && input.exit_code !== 0) return true;
2694
+
2695
+ // Pattern-Check im Output
2696
+ const errorPatterns = [
2697
+ /Error:/i,
2698
+ /error\[E\d+\]/, // Rust errors
2699
+ /Traceback \(most recent call last\)/,
2700
+ /FATAL|PANIC/i,
2701
+ /npm ERR!/,
2702
+ /SyntaxError|TypeError|ReferenceError|RangeError/,
2703
+ /ENOENT|EACCES|ECONNREFUSED|ETIMEDOUT/,
2704
+ /ModuleNotFoundError|ImportError/,
2705
+ /failed to compile/i,
2706
+ /BUILD FAILED/i,
2707
+ /Cannot find module/,
2708
+ /command not found/,
2709
+ /Permission denied/,
2710
+ ];
2711
+
2712
+ return errorPatterns.some(p => p.test(input.tool_output));
2713
+ }
2714
+
2715
+ function readStdin(): Promise<string> {
2716
+ return new Promise((resolve) => {
2717
+ let data = '';
2718
+ process.stdin.on('data', (chunk) => data += chunk);
2719
+ process.stdin.on('end', () => resolve(data));
2720
+ });
2721
+ }
2722
+
2723
+ main();
2724
+ ```
2725
+
2726
+ ### Auto-Detection für Code Brain (PostToolUse auf Write/Edit)
2727
+
2728
+ ```json
2729
+ {
2730
+ "hooks": {
2731
+ "PostToolUse": [
2732
+ {
2733
+ "matcher": { "tool_name": "Bash" },
2734
+ "command": "node /path/to/brain/dist/hooks/post-tool-use.js"
2735
+ },
2736
+ {
2737
+ "matcher": { "tool_name": "Write" },
2738
+ "command": "node /path/to/brain/dist/hooks/post-write.js"
2739
+ },
2740
+ {
2741
+ "matcher": { "tool_name": "Edit" },
2742
+ "command": "node /path/to/brain/dist/hooks/post-edit.js"
2743
+ }
2744
+ ]
2745
+ }
2746
+ }
2747
+ ```
2748
+
2749
+ ```typescript
2750
+ // hooks/post-write.ts
2751
+ // Analysiert geschriebene Dateien auf Wiederverwendbarkeit
2752
+
2753
+ async function main() {
2754
+ const input = JSON.parse(await readStdin());
2755
+ const filePath = input.tool_input?.file_path;
2756
+ if (!filePath) return;
2757
+
2758
+ // Nur Source-Code-Dateien analysieren
2759
+ if (!isSourceFile(filePath)) return;
2760
+
2761
+ const client = new IpcClient();
2762
+ try {
2763
+ await client.connect();
2764
+
2765
+ // Code auf Ähnlichkeit prüfen
2766
+ const similarities = await client.request('code.similarity', {
2767
+ file_path: filePath,
2768
+ source_code: input.tool_input.content,
2769
+ });
2770
+
2771
+ if (similarities?.length > 0) {
2772
+ const best = similarities[0];
2773
+ console.log(`Brain: Similar code exists in ${best.project_name}/${best.file_path} (${Math.round(best.score * 100)}% match)`);
2774
+ }
2775
+
2776
+ // Reusability-Check
2777
+ const analysis = await client.request('code.analyze', {
2778
+ file_path: filePath,
2779
+ source_code: input.tool_input.content,
2780
+ dry_run: true, // Nur analysieren, nicht registrieren
2781
+ });
2782
+
2783
+ if (analysis?.reusability_score >= 0.60) {
2784
+ console.log(`Brain: This code looks reusable (score: ${Math.round(analysis.reusability_score * 100)}%). Consider registering it.`);
2785
+ }
2786
+ } catch {
2787
+ // Stille Fehler
2788
+ } finally {
2789
+ client.disconnect();
2790
+ }
2791
+ }
2792
+ ```
2793
+
2794
+ ## Terminal-Lifecycle
2795
+
2796
+ ```
2797
+ ┌─────────────┐ register ┌──────────────┐
2798
+ │ Connecting │ ─────────────► │ Connected │
2799
+ └─────────────┘ └──────┬───────┘
2800
+
2801
+ heartbeat (30s) │
2802
+
2803
+ ┌──────▼───────┐
2804
+ │ Active │◄── error.report
2805
+ │ │◄── solution.report
2806
+ │ │◄── code.analyze
2807
+ │ │◄── prevention.check
2808
+ └──────┬───────┘
2809
+
2810
+ disconnect/timeout │
2811
+
2812
+ ┌──────▼───────┐
2813
+ │ Disconnected │
2814
+ └──────────────┘
2815
+
2816
+ 300s no heartbeat │ (5 min statt 90s)
2817
+
2818
+ ┌──────▼───────┐
2819
+ │ Stale │ → Cleanup
2820
+ └──────────────┘
2821
+ ```
2822
+
2823
+ ## BrainCore Orchestrierung
2824
+
2825
+ ```typescript
2826
+ class BrainCore {
2827
+ private db: Database;
2828
+ private ipcServer: IpcServer;
2829
+ private learningEngine: LearningEngine;
2830
+ private researchEngine: ResearchEngine;
2831
+ private synapseManager: SynapseManager;
2832
+ private services: Services;
2833
+ private config: BrainConfig;
2834
+ private eventBus: TypedEventBus;
2835
+
2836
+ async start(): Promise<void> {
2837
+ // 1. Config laden (Datei + Env-Overrides)
2838
+ this.config = loadConfig();
2839
+
2840
+ // 2. Logger initialisieren
2841
+ initLogger(this.config.log);
2842
+
2843
+ // 3. DB initialisieren + Migrationen
2844
+ this.db = createConnection(this.config.dbPath);
2845
+ runMigrations(this.db);
2846
+
2847
+ // 4. EventBus
2848
+ this.eventBus = new TypedEventBus();
2849
+
2850
+ // 5. Synapse Manager (muss vor Services stehen, die ihn nutzen)
2851
+ this.synapseManager = new SynapseManager(
2852
+ new SynapseRepository(this.db),
2853
+ this.config.synapses
2854
+ );
2855
+
2856
+ // 6. Services initialisieren (inkl. SynapseService und ResearchService)
2857
+ this.services = createServices(this.db, this.eventBus, this.synapseManager);
2858
+
2859
+ // 7. Learning Engine starten (alle 15 Minuten)
2860
+ this.learningEngine = new LearningEngine(this.services, this.synapseManager, this.config.learning);
2861
+ this.learningEngine.startSchedule(this.config.learning.intervalMs);
2862
+
2863
+ // 8. Research Engine starten (alle 60 Minuten, erster Cycle nach 5 min)
2864
+ this.researchEngine = new ResearchEngine(this.services, this.synapseManager, this.config.research);
2865
+ this.researchEngine.startSchedule(this.config.research.intervalMs);
2866
+
2867
+ // 9. IPC Server starten
2868
+ const router = new IpcRouter(this.services);
2869
+ this.ipcServer = new IpcServer(router, this.config.ipc);
2870
+ this.ipcServer.start();
2871
+
2872
+ // 10. Terminal-Cleanup-Timer (stale nach 5 Minuten)
2873
+ setInterval(
2874
+ () => this.services.terminal.cleanupStale(this.config.terminal.staleTimeoutMs),
2875
+ this.config.terminal.cleanupIntervalMs
2876
+ );
2877
+
2878
+ // 11. PID-File schreiben
2879
+ writePidFile(process.pid);
2880
+
2881
+ // 12. Event-Listeners (Synapsen werden hier verdrahtet)
2882
+ this.setupEventListeners();
2883
+
2884
+ // 13. Graceful Shutdown
2885
+ process.on('SIGINT', () => this.stop());
2886
+ process.on('SIGTERM', () => this.stop());
2887
+
2888
+ logger.info(`Brain daemon started (PID: ${process.pid})`);
2889
+ }
2890
+
2891
+ async stop(): Promise<void> {
2892
+ logger.info('Shutting down...');
2893
+ this.researchEngine.stop();
2894
+ this.learningEngine.stop();
2895
+ this.ipcServer.stop();
2896
+ this.db.close();
2897
+ removePidFile();
2898
+ logger.info('Brain daemon stopped');
2899
+ process.exit(0);
2900
+ }
2901
+
2902
+ private setupEventListeners(): void {
2903
+ // === Error Events + Synapsen ===
2904
+
2905
+ this.eventBus.on('error:reported', async ({ errorId, terminalId, projectId }) => {
2906
+ // Synapse: Error → Projekt
2907
+ this.synapseManager.strengthen(
2908
+ { type: 'error', id: errorId },
2909
+ { type: 'project', id: projectId },
2910
+ 'co_occurs'
2911
+ );
2912
+
2913
+ // Sofort nach Matches suchen
2914
+ const matches = await this.services.error.matchSimilar(errorId);
2915
+ if (matches.length > 0) {
2916
+ const bestMatch = matches[0];
2917
+
2918
+ // Synapse: Error → ähnlicher Error
2919
+ this.synapseManager.strengthen(
2920
+ { type: 'error', id: errorId },
2921
+ { type: 'error', id: bestMatch.candidate.id },
2922
+ 'similar_to'
2923
+ );
2924
+
2925
+ const solutions = await this.services.solution.getForError(bestMatch.candidate.id);
2926
+ if (solutions.length > 0) {
2927
+ this.services.notification.create({
2928
+ target_terminal_id: terminalId,
2929
+ notification_type: 'solution_available',
2930
+ reference_type: 'solution',
2931
+ reference_id: solutions[0].id,
2932
+ summary: `Known error: "${bestMatch.candidate.message.substring(0, 60)}..." - ${solutions.length} solution(s) available`,
2933
+ });
2934
+ }
2935
+ }
2936
+ });
2937
+
2938
+ // === Solution Events + Synapsen ===
2939
+
2940
+ this.eventBus.on('solution:applied', async ({ solutionId, errorId, outcome }) => {
2941
+ if (outcome === 'success') {
2942
+ // Starke Synapse: Solution löst Error
2943
+ this.synapseManager.strengthen(
2944
+ { type: 'solution', id: solutionId },
2945
+ { type: 'error', id: errorId },
2946
+ 'solves',
2947
+ { outcome: 'success' }
2948
+ );
2949
+ } else if (outcome === 'failure') {
2950
+ // Synapse schwächen
2951
+ const synapse = this.synapseManager.find(
2952
+ { type: 'solution', id: solutionId },
2953
+ { type: 'error', id: errorId },
2954
+ 'solves'
2955
+ );
2956
+ if (synapse) this.synapseManager.weaken(synapse.id, 0.7);
2957
+ }
2958
+ });
2959
+
2960
+ // Cross-Projekt: Fehler gelöst → prüfe ob andere Projekte profitieren
2961
+ this.eventBus.on('solution:reported', async ({ solutionId, errorId }) => {
2962
+ const error = await this.services.error.getById(errorId);
2963
+ if (!error) return;
2964
+
2965
+ const crossProjectErrors = await this.services.error.findCrossProject(
2966
+ error.fingerprint,
2967
+ error.project_id
2968
+ );
2969
+
2970
+ for (const otherError of crossProjectErrors) {
2971
+ // Cross-Project Synapsen
2972
+ this.synapseManager.strengthen(
2973
+ { type: 'error', id: error.id },
2974
+ { type: 'error', id: otherError.id },
2975
+ 'cross_project'
2976
+ );
2977
+ this.synapseManager.strengthen(
2978
+ { type: 'project', id: error.project_id! },
2979
+ { type: 'project', id: otherError.project_id! },
2980
+ 'cross_project'
2981
+ );
2982
+
2983
+ this.services.notification.create({
2984
+ notification_type: 'solution_available',
2985
+ reference_type: 'solution',
2986
+ reference_id: solutionId,
2987
+ summary: `Solution from project ${error.project_id} may fix error #${otherError.id}`,
2988
+ });
2989
+ }
2990
+ });
2991
+
2992
+ // === Code Events + Synapsen ===
2993
+
2994
+ this.eventBus.on('module:registered', async ({ moduleId, projectId }) => {
2995
+ this.synapseManager.strengthen(
2996
+ { type: 'code_module', id: moduleId },
2997
+ { type: 'project', id: projectId },
2998
+ 'co_occurs'
2999
+ );
3000
+ });
3001
+
3002
+ this.eventBus.on('module:reused', async ({ moduleId, projectId, outcome }) => {
3003
+ this.synapseManager.strengthen(
3004
+ { type: 'code_module', id: moduleId },
3005
+ { type: 'project', id: projectId },
3006
+ 'uses_module',
3007
+ { outcome }
3008
+ );
3009
+ });
3010
+
3011
+ // === Rule Events + Synapsen ===
3012
+
3013
+ this.eventBus.on('rule:triggered', async ({ ruleId, errorId, outcome }) => {
3014
+ if (outcome === 'prevented') {
3015
+ this.synapseManager.strengthen(
3016
+ { type: 'rule', id: ruleId },
3017
+ { type: 'error', id: errorId },
3018
+ 'prevents'
3019
+ );
3020
+ }
3021
+ });
3022
+
3023
+ // === Error Chain Detection ===
3024
+
3025
+ this.eventBus.on('error:chain_detected', async ({ causeErrorId, effectErrorId }) => {
3026
+ this.synapseManager.strengthen(
3027
+ { type: 'error', id: causeErrorId },
3028
+ { type: 'error', id: effectErrorId },
3029
+ 'causes'
3030
+ );
3031
+ });
3032
+
3033
+ // === Research Insights + Synapsen ===
3034
+
3035
+ this.eventBus.on('insight:created', async ({ insightId, relatedNodeIds }) => {
3036
+ // Insight mit allen beteiligten Knoten verbinden
3037
+ for (const node of relatedNodeIds) {
3038
+ this.synapseManager.strengthen(
3039
+ { type: 'insight', id: insightId },
3040
+ { type: node.type, id: node.id },
3041
+ 'derived_from'
3042
+ );
3043
+ }
3044
+ });
3045
+ }
3046
+ }
3047
+ ```
3048
+
3049
+ ## CLI Commands
3050
+
3051
+ ```bash
3052
+ brain start # Daemon starten (Hintergrund via detached child_process)
3053
+ brain stop # Daemon stoppen (PID-File lesen, SIGTERM senden)
3054
+ brain status # Status: Terminals, Errors, Code, Synapsen, Research
3055
+ brain query "error message" # Ähnliche Fehler + Lösungen suchen
3056
+ brain modules [--language ts] # Code-Module auflisten
3057
+ brain insights [--type trend] # Research Insights anzeigen
3058
+ brain network [--node error:42] # Synapsen-Netzwerk um einen Knoten erkunden
3059
+ brain export [--format json] # Daten exportieren
3060
+ brain reset [--confirm] # Datenbank zurücksetzen
3061
+ brain logs [--tail 50] # Log-Datei anzeigen
3062
+ ```
3063
+
3064
+ ### Beispiel: `brain status` Output
3065
+ ```
3066
+ Brain Daemon: RUNNING (PID 12345, uptime 2h 34m)
3067
+ Database: brain.db (2.4 MB)
3068
+
3069
+ Terminals (3 connected):
3070
+ T1: my-api (PID 1234) Active 5s ago
3071
+ T2: frontend (PID 5678) Active 12s ago
3072
+ T3: data-tools (PID 9012) Idle 45s ago
3073
+
3074
+ Error Brain:
3075
+ Errors: 42 total, 8 unresolved
3076
+ Solutions: 31 (avg confidence: 0.74)
3077
+ Rules: 8 active, 2 pending
3078
+ Anti-Patterns: 3
3079
+
3080
+ Code Brain:
3081
+ Modules: 23 registered
3082
+ Reuses: 14 total (9 exact, 3 adapted, 2 pattern-based)
3083
+ Top module: retry.ts (4 reuses, confidence 0.92)
3084
+
3085
+ Synapse Network:
3086
+ Nodes: 98 Synapses: 247
3087
+ Avg weight: 0.43 Strong (>0.7): 31
3088
+ Top connection: Solution#7 --solves--> Error#42 (weight: 0.96)
3089
+
3090
+ Research Brain:
3091
+ Insights: 12 active (3 high priority)
3092
+ Last cycle: 18m ago Next: in 42m
3093
+ Latest: "Template-Kandidat: API-Client Pattern (3 Projekte)"
3094
+
3095
+ Learning:
3096
+ Last cycle: 5m ago (3 patterns, 1 new rule)
3097
+ Next cycle: in 10m
3098
+ ```
3099
+
3100
+ ## Konfiguration
3101
+
3102
+ ```typescript
3103
+ interface BrainConfig {
3104
+ dbPath: string; // Default: ~/.brain/brain.db
3105
+ ipc: {
3106
+ pipeName: string; // Default: \\.\pipe\brain-ipc (Win) / /tmp/brain.sock (Unix)
3107
+ maxConnections: number; // Default: 50
3108
+ };
3109
+ learning: {
3110
+ intervalMs: number; // Default: 900_000 (15 min)
3111
+ minOccurrences: number; // Default: 3
3112
+ minSuccessRate: number; // Default: 0.70
3113
+ minConfidence: number; // Default: 0.60
3114
+ pruneThreshold: number; // Default: 0.20
3115
+ maxRejectionRate: number; // Default: 0.50
3116
+ decayHalfLifeDays: number; // Default: 30
3117
+ };
3118
+ terminal: {
3119
+ heartbeatIntervalMs: number; // Default: 30_000
3120
+ staleTimeoutMs: number; // Default: 300_000 (5 min)
3121
+ cleanupIntervalMs: number; // Default: 60_000
3122
+ };
3123
+ matching: {
3124
+ threshold: number; // Default: 0.70
3125
+ strongThreshold: number; // Default: 0.90
3126
+ maxCandidates: number; // Default: 100
3127
+ };
3128
+ code: {
3129
+ moduleThreshold: number; // Default: 0.60 (Reusability Score minimum)
3130
+ similarityThreshold: number; // Default: 0.70
3131
+ autoAnalyze: boolean; // Default: true
3132
+ ignorePaths: string[]; // Default: ["node_modules", "dist", ".git", "__pycache__"]
3133
+ };
3134
+ synapses: {
3135
+ initialWeight: number; // Default: 0.1
3136
+ learningRate: number; // Default: 0.15 (wie schnell Synapsen stärker werden)
3137
+ decayHalfLifeDays: number; // Default: 45 (Synapsen verblassen langsamer als Solutions)
3138
+ pruneThreshold: number; // Default: 0.05 (unter diesem Gewicht → löschen)
3139
+ decayAfterDays: number; // Default: 14 (Decay erst nach 14 Tagen Inaktivität)
3140
+ maxDepth: number; // Default: 3 (Spreading Activation Tiefe)
3141
+ minActivationWeight: number; // Default: 0.2 (Minimum für Pfad-Traversierung)
3142
+ };
3143
+ research: {
3144
+ intervalMs: number; // Default: 3_600_000 (60 min)
3145
+ initialDelayMs: number; // Default: 300_000 (5 min, Brain soll erstmal Daten sammeln)
3146
+ minDataPoints: number; // Default: 10 (Minimum Errors/Solutions bevor geforscht wird)
3147
+ trendWindowDays: number; // Default: 7
3148
+ gapMinOccurrences: number; // Default: 5 (Fehler muss 5x auftreten für Gap-Erkennung)
3149
+ synergyMinWeight: number; // Default: 0.5 (Minimum Synapse-Gewicht für Synergie)
3150
+ templateMinAdaptations: number; // Default: 3 (Minimum Adaptationen für Template-Vorschlag)
3151
+ insightExpiryDays: number; // Default: 30 (Insights verfallen nach 30 Tagen)
3152
+ };
3153
+ log: {
3154
+ level: 'debug' | 'info' | 'warn' | 'error';
3155
+ file: string; // Default: ~/.brain/brain.log
3156
+ maxSizeMb: number; // Default: 10
3157
+ maxFiles: number; // Default: 3 (Rotation)
3158
+ };
3159
+ retention: {
3160
+ maxErrorAgeDays: number; // Default: 90
3161
+ maxResolvedErrorAgeDays: number; // Default: 180
3162
+ maxLogAgeDays: number; // Default: 30
3163
+ cleanupIntervalMs: number; // Default: 86_400_000 (24h)
3164
+ };
3165
+ }
3166
+ ```
3167
+
3168
+ ## Implementierungsreihenfolge (8 Phasen)
3169
+
3170
+ ### Phase 1: Foundation
3171
+ **Ziel:** Projekt-Skeleton, DB, Config - alles was andere Phasen brauchen.
3172
+
3173
+ - `package.json` mit allen Dependencies
3174
+ - `tsconfig.json` (strict, ES2022, NodeNext module resolution)
3175
+ - `.gitignore` (node_modules, data/, dist/, *.db, *.log)
3176
+ - `src/config.ts` - Konfiguration mit Defaults + Env-Overrides
3177
+ - `src/types/` - Alle TypeScript Interfaces (inkl. synapse.types.ts, research.types.ts)
3178
+ - `src/utils/logger.ts` - Winston File-Logger mit Rotation
3179
+ - `src/utils/hash.ts` - SHA-256 Wrapper
3180
+ - `src/utils/paths.ts` - Pfad-Normalisierung (Windows/Unix)
3181
+ - `src/utils/events.ts` - Typisierter EventBus
3182
+ - `src/db/connection.ts` - SQLite Connection (WAL, journal_mode, synchronous, cache_size Pragmas)
3183
+ - `src/db/migrations/` - Alle 5 Migrations + Runner
3184
+ - `src/db/repositories/` - Alle 10 Repository-Klassen (jede mit eigenen Prepared Statements)
3185
+
3186
+ ### Phase 2: Parsing, Matching & Code Analysis
3187
+ **Ziel:** Die "Intelligenz" - Error-Erkennung, Matching, Code-Analyse.
3188
+
3189
+ - `src/parsing/types.ts` - Parser Interfaces
3190
+ - `src/parsing/error-parser.ts` - Registry-basierter Dispatcher
3191
+ - `src/parsing/parsers/` - Node, Python, Rust, Go, Shell, Compiler, Generic
3192
+ - `src/matching/tokenizer.ts` - Text-Tokenisierung (splitCamelCase, splitSnakeCase, stopwords)
3193
+ - `src/matching/similarity.ts` - Levenshtein, Cosine, Jaccard
3194
+ - `src/matching/tfidf.ts` - Inkrementeller TF-IDF Index mit Persistenz
3195
+ - `src/matching/fingerprint.ts` - Error-Fingerprinting mit Templatisierung
3196
+ - `src/matching/error-matcher.ts` - Multi-Signal Matching Engine
3197
+ - `src/code/analyzer.ts` - Export-Extraction, Purity-Check, Cohesion-Messung
3198
+ - `src/code/fingerprint.ts` - Strukturelles Code-Hashing
3199
+ - `src/code/matcher.ts` - Code-Similarity-Matching
3200
+ - `src/code/registry.ts` - Module-Registration + Granularity-Detection
3201
+ - `src/code/scorer.ts` - Reusability-Scoring (6 Signals)
3202
+ - `src/code/parsers/` - TypeScript, Python, Generic Code-Parser
3203
+
3204
+ ### Phase 3: Synapsen-Netzwerk
3205
+ **Ziel:** Das neuronale Netzwerk das alles verbindet.
3206
+
3207
+ - `src/synapses/synapse-manager.ts` - Erstellen, Stärken, Schwächen von Synapsen
3208
+ - `src/synapses/hebbian.ts` - Hebbsches Lerngesetz (logarithmische Verstärkung, Sättigung)
3209
+ - `src/synapses/pathfinder.ts` - BFS-Pfadsuche mit Gewichts-Tracking
3210
+ - `src/synapses/activation.ts` - Spreading Activation (Multi-Hop Netzwerk-Traversierung)
3211
+ - `src/synapses/decay.ts` - Synaptische Abschwächung + Pruning inaktiver Verbindungen
3212
+
3213
+ ### Phase 4: Services
3214
+ **Ziel:** Business-Logik über den Repositories.
3215
+
3216
+ - `src/services/error.service.ts` - Report, Query, Match, Auto-Label
3217
+ - `src/services/solution.service.ts` - Report, Rate, Track Attempts
3218
+ - `src/services/terminal.service.ts` - Register, Heartbeat, Cleanup
3219
+ - `src/services/prevention.service.ts` - Rule-Check, Antipattern-Check
3220
+ - `src/services/code.service.ts` - Analyze, Find, Similarity, Register
3221
+ - `src/services/synapse.service.ts` - Context-Queries, Pfadsuche, Netzwerk-Stats
3222
+ - `src/services/research.service.ts` - Insights abfragen, Suggestions generieren
3223
+ - `src/services/notification.service.ts` - Create, List, Acknowledge
3224
+ - `src/services/analytics.service.ts` - Summary, Trends, Network Overview
3225
+
3226
+ ### Phase 5: Learning Engine + Research Brain
3227
+ **Ziel:** Das System wird über Zeit besser UND forscht eigenständig.
3228
+
3229
+ - `src/learning/confidence-scorer.ts` - Wilson Score + Time Decay
3230
+ - `src/learning/decay.ts` - Zeitbasierte Relevanz-Berechnung
3231
+ - `src/learning/pattern-extractor.ts` - Centroid-basiertes Error-Clustering
3232
+ - `src/learning/rule-generator.ts` - Regeln aus Mustern generieren
3233
+ - `src/learning/learning-engine.ts` - Lern-Zyklus + Scheduling
3234
+ - `src/research/research-engine.ts` - Forschungs-Zyklus Orchestrierung (7 Phasen)
3235
+ - `src/research/trend-analyzer.ts` - Error-Frequenz, Solution-Erfolgsrate über Zeit
3236
+ - `src/research/gap-analyzer.ts` - Ungelöste recurring Errors, isolierte Knoten
3237
+ - `src/research/synergy-detector.ts` - Module-Paare, transferierbare Solutions, Workflow-Patterns
3238
+ - `src/research/template-extractor.ts` - Adaptierte Module → parametrisierte Templates
3239
+ - `src/research/insight-generator.ts` - Projekt-Vorschläge, Tool-Ideen, Optimierungen
3240
+
3241
+ ### Phase 6: IPC + MCP
3242
+ **Ziel:** Kommunikation - Daemon erreichbar für Terminals und Claude.
3243
+
3244
+ - `src/ipc/protocol.ts` - Length-prefixed JSON Framing (Encode/Decode)
3245
+ - `src/ipc/router.ts` - Method-Routing mit Error-Handling
3246
+ - `src/ipc/server.ts` - Named Pipe Server
3247
+ - `src/ipc/client.ts` - IPC Client (für MCP Server → Daemon)
3248
+ - `src/mcp/server.ts` - MCP Server (stdio Transport, Tool Registration)
3249
+ - `src/mcp/tools.ts` - Alle 13 MCP Tool-Definitionen
3250
+ - `src/mcp/auto-detect.ts` - Error-Pattern-Erkennung für Hooks
3251
+
3252
+ ### Phase 7: BrainCore + CLI + Hooks
3253
+ **Ziel:** Alles zusammenbinden, benutzbar machen.
3254
+
3255
+ - `src/brain.ts` - BrainCore (Start, Stop, Service-Wiring, Synapse-Events, Engine-Scheduling)
3256
+ - `src/index.ts` - Commander CLI Setup
3257
+ - `src/cli/commands/start.ts` - Daemon als detached child_process starten
3258
+ - `src/cli/commands/stop.ts` - PID lesen, SIGTERM senden
3259
+ - `src/cli/commands/status.ts` - Text-basierter Status (inkl. Synapse-Stats + Research-Insights)
3260
+ - `src/cli/commands/query.ts` - Error-Suche via CLI
3261
+ - `src/cli/commands/modules.ts` - Code-Module auflisten
3262
+ - `src/cli/commands/insights.ts` - Research Insights anzeigen
3263
+ - `src/cli/commands/network.ts` - Synapsen-Netzwerk erkunden
3264
+ - `src/cli/commands/export.ts` - JSON/CSV Export
3265
+ - `src/hooks/post-tool-use.ts` - Auto Error Detection Hook
3266
+ - `src/hooks/post-write.ts` - Auto Code Analysis Hook
3267
+
3268
+ ### Phase 8: Tests
3269
+ **Ziel:** Alles getestet, produktionsreif.
3270
+
3271
+ - Unit-Tests:
3272
+ - `tests/unit/matching/` - Fingerprinting, Similarity, TF-IDF, Error-Matcher
3273
+ - `tests/unit/parsing/` - Jeder Parser einzeln mit Fixtures
3274
+ - `tests/unit/code/` - Analyzer, Fingerprint, Scorer, Granularity
3275
+ - `tests/unit/learning/` - Wilson Score, Decay, Pattern-Extraktion, Rule-Gen
3276
+ - `tests/unit/synapses/` - Hebbian Learning, Spreading Activation, Decay, Pathfinding
3277
+ - `tests/unit/research/` - Trend-Analyse, Gap-Analyse, Synergie-Detektion, Template-Extraktion
3278
+ - Integration-Tests:
3279
+ - `tests/integration/error-flow.test.ts` - Error → Parse → Store → Match → Solution → Synapse
3280
+ - `tests/integration/code-flow.test.ts` - Write → Analyze → Register → Find → Reuse → Synapse
3281
+ - `tests/integration/synapse-flow.test.ts` - Events → Synapsen bilden → Spreading Activation → Kontext
3282
+ - `tests/integration/research-cycle.test.ts` - Daten sammeln → Forschen → Insights → Notifications
3283
+ - `tests/integration/learning-cycle.test.ts` - Voller Lern-Zyklus inkl. Synapse-Decay
3284
+ - `tests/integration/ipc-flow.test.ts` - MCP → IPC → Daemon → Response
3285
+ - Fixtures:
3286
+ - `tests/fixtures/errors/` - Beispiel-Errors pro Sprache (node, python, rust, go, shell)
3287
+ - `tests/fixtures/solutions/` - Beispiel-Lösungen
3288
+ - `tests/fixtures/code-modules/` - Beispiel-Code für Matching-Tests
3289
+ - `tests/fixtures/synapses/` - Vorkonfigurierte Netzwerke für Pfadsuche-Tests
3290
+
3291
+ ## Verifikation
3292
+
3293
+ 1. `npm run build` - TypeScript kompiliert ohne Fehler
3294
+ 2. `npm test` - Alle Tests grün
3295
+ 3. `brain start` - Daemon startet, PID-File wird geschrieben
3296
+ 4. `brain status` - Zeigt laufenden Brain mit 0 Terminals, leeres Netzwerk
3297
+ 5. **Error-Flow:** Error melden → Brain matcht → Lösung vorschlagen → Feedback → Confidence steigt → Synapse stärkt sich
3298
+ 6. **Code-Flow:** Code schreiben → Brain analysiert → Modul registriert → In anderem Projekt vorgeschlagen → Synapse zu Projekt
3299
+ 7. **Hook-Flow:** Bash-Fehler → Hook erkennt → Brain speichert → Nächstes Mal: Warnung
3300
+ 8. **Cross-Projekt:** Fehler in Projekt A lösen → Synapse cross_project → Brain schlägt Lösung für Projekt B vor
3301
+ 9. **Synapse-Flow:** Mehrere Aktionen → Synapsen bilden sich → Spreading Activation findet Zusammenhänge → Context-Query zeigt vernetztes Wissen
3302
+ 10. **Research-Flow:** Nach genug Daten → Research Engine läuft → Trends, Gaps, Synergien erkannt → Insights mit konkreten Vorschlägen
3303
+ 11. **Learning + Decay:** Synapsen die nicht bestätigt werden verblassen → Schwache Regeln werden gepruned → Netzwerk bleibt relevant
3304
+
3305
+ ## Wichtige Entscheidungen
3306
+
3307
+ - **better-sqlite3 statt async**: Synchron ist für diesen Use-Case besser (kein Web-Server, lokaler Daemon). WAL-Modus erlaubt concurrent reads von mehreren MCP Server Prozessen.
3308
+ - **Named Pipes + MCP Dual-Layer**: Named Pipes für performante Daemon-Kommunikation, MCP für saubere Claude-Integration. MCP Server sind Thin Clients, keine eigene Logik.
3309
+ - **Hooks für automatische Erkennung**: PostToolUse-Hooks sind der unsichtbare Kanal. Der User muss nichts manuell melden, Brain läuft im Hintergrund. Hooks dürfen NIE den Workflow blockieren (silent catch).
3310
+ - **Wilson Score statt Durchschnitt**: Bei wenigen Datenpunkten (1/0 = 100%) unrealistisch. Wilson Score berücksichtigt Stichprobengröße.
3311
+ - **Centroid-basiertes Clustering statt Single-Pass**: Ordnungsunabhängig, findet Cluster besser, Running Average für effiziente Updates.
3312
+ - **Parser-Registry statt Hardcoded Dispatch**: Neue Sprachen = neue Datei registrieren. Open/Closed Principle.
3313
+ - **Labels statt Tag-Tabellen**: Auto-generierte JSON-Labels direkt am Record. Kein 3-Tabellen-Overhead für Tags die niemand manuell pflegt.
3314
+ - **Notifications statt Inter-Terminal-Chat**: Ein User, ein Bildschirm. Brain informiert, es chattet nicht.
3315
+ - **Synapsen-Netzwerk statt isolierter Relationen**: Statt `related_errors`, `cross_project_solutions` als separate Tabellen ein einheitliches Synapse-System das ALLES verbindet. Typed + weighted + decaying. Ermöglicht Spreading Activation und Multi-Hop-Entdeckungen die mit isolierten Tabellen unmöglich wären.
3316
+ - **Hebbsches Lernen für Synapsen**: "Neurons that fire together, wire together". Wenn Solution X Error Y löst, wird die Synapse stärker. Bei Fehlschlag schwächer. Logarithmische Sättigung verhindert Übergewichtung. Natürlicher als binäre Relationen.
3317
+ - **Research Brain als eigener Engine**: Getrennt von der Learning Engine (die taktisch lernt) forscht das Research Brain strategisch. Längere Intervalle (60 min vs 15 min), höhere Abstraktion (Trends, Synergien, Templates statt Error-Patterns). Generiert Insights die über einzelne Fehler/Lösungen hinausgehen.
3318
+ - **Synapse-Decay statt Deletion**: Unbenutzte Verbindungen verblassen langsam (halfLife 45 Tage) statt hart gelöscht zu werden. Ermöglicht "Wiederentdeckung" wenn ein Pfad nach langer Zeit wieder relevant wird. Erst unter pruneThreshold (0.05) wird tatsächlich gelöscht.
3319
+ - **Insights als first-class Citizens**: Nicht nur Notifications, sondern persistente, priorisierte, aktionierbare Erkenntnisse mit Lifecycle (active → acknowledged → acted_upon → expired). Das Research Brain wird über Zeit klüger weil es auf Insight-Outcomes lernen kann.
3320
+ - **Kein ink Dashboard**: Claude IST das Dashboard. MCP-Tools liefern reichhaltige, formatierte Informationen. CLI gibt simplen Text-Status. Die UI-Komplexität von ink lohnt nicht für einen Daemon der primär durch Claude bedient wird.
3321
+ - **Prepared Statements pro Repository**: Jedes Repository compiled seine eigenen Statements bei Init. Kein God-File mit 50+ Statements.
3322
+ - **File-Logging statt DB-Event-Log**: Audit/Debug-Daten gehören in Log-Dateien mit Rotation, nicht in die Datenbank. Die DB bleibt für strukturierte, abfragbare Daten.
3323
+ - **300s statt 90s stale Timeout**: Claude denkt manchmal minutenlang. 90s ist zu aggressiv.
3324
+ - **Code-Fingerprinting normalisiert Identifier**: Lokale Variablennamen werden ersetzt, aber Import-Names und API-Calls bleiben. So matcht `const result = await fetch(url)` mit `const response = await fetch(endpoint)`.