@timmeck/brain-core 2.36.62 → 2.36.63

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 (253) hide show
  1. package/dist/guardrails/guardrail-engine.d.ts +2 -0
  2. package/dist/guardrails/guardrail-engine.js +17 -9
  3. package/dist/guardrails/guardrail-engine.js.map +1 -1
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/utils/memory-watchdog.d.ts +33 -0
  8. package/dist/utils/memory-watchdog.js +88 -0
  9. package/dist/utils/memory-watchdog.js.map +1 -0
  10. package/package.json +1 -1
  11. package/dist/action/__tests__/action-bridge.test.d.ts +0 -1
  12. package/dist/action/__tests__/action-bridge.test.js +0 -175
  13. package/dist/action/__tests__/action-bridge.test.js.map +0 -1
  14. package/dist/action/__tests__/adjust-parameter-handler.test.d.ts +0 -1
  15. package/dist/action/__tests__/adjust-parameter-handler.test.js +0 -138
  16. package/dist/action/__tests__/adjust-parameter-handler.test.js.map +0 -1
  17. package/dist/action/__tests__/content-handler.test.d.ts +0 -1
  18. package/dist/action/__tests__/content-handler.test.js +0 -100
  19. package/dist/action/__tests__/content-handler.test.js.map +0 -1
  20. package/dist/action/__tests__/creative-seed-handler.test.d.ts +0 -1
  21. package/dist/action/__tests__/creative-seed-handler.test.js +0 -96
  22. package/dist/action/__tests__/creative-seed-handler.test.js.map +0 -1
  23. package/dist/action/__tests__/trade-handler.test.d.ts +0 -1
  24. package/dist/action/__tests__/trade-handler.test.js +0 -165
  25. package/dist/action/__tests__/trade-handler.test.js.map +0 -1
  26. package/dist/active-learning/__tests__/active-learning.test.d.ts +0 -1
  27. package/dist/active-learning/__tests__/active-learning.test.js +0 -132
  28. package/dist/active-learning/__tests__/active-learning.test.js.map +0 -1
  29. package/dist/agent-training/__tests__/agent-trainer.test.d.ts +0 -1
  30. package/dist/agent-training/__tests__/agent-trainer.test.js +0 -158
  31. package/dist/agent-training/__tests__/agent-trainer.test.js.map +0 -1
  32. package/dist/agent-training/__tests__/sub-agent-factory.test.d.ts +0 -1
  33. package/dist/agent-training/__tests__/sub-agent-factory.test.js +0 -100
  34. package/dist/agent-training/__tests__/sub-agent-factory.test.js.map +0 -1
  35. package/dist/agent-training/__tests__/sub-agent.test.d.ts +0 -1
  36. package/dist/agent-training/__tests__/sub-agent.test.js +0 -102
  37. package/dist/agent-training/__tests__/sub-agent.test.js.map +0 -1
  38. package/dist/chat/__tests__/chat-engine.test.d.ts +0 -1
  39. package/dist/chat/__tests__/chat-engine.test.js +0 -209
  40. package/dist/chat/__tests__/chat-engine.test.js.map +0 -1
  41. package/dist/checkpoint/__tests__/checkpoint-manager.test.d.ts +0 -1
  42. package/dist/checkpoint/__tests__/checkpoint-manager.test.js +0 -160
  43. package/dist/checkpoint/__tests__/checkpoint-manager.test.js.map +0 -1
  44. package/dist/code-health/__tests__/code-health.test.d.ts +0 -1
  45. package/dist/code-health/__tests__/code-health.test.js +0 -123
  46. package/dist/code-health/__tests__/code-health.test.js.map +0 -1
  47. package/dist/codegen/__tests__/code-forge.test.d.ts +0 -1
  48. package/dist/codegen/__tests__/code-forge.test.js +0 -105
  49. package/dist/codegen/__tests__/code-forge.test.js.map +0 -1
  50. package/dist/config/__tests__/loader.test.d.ts +0 -1
  51. package/dist/config/__tests__/loader.test.js +0 -86
  52. package/dist/config/__tests__/loader.test.js.map +0 -1
  53. package/dist/consciousness/__tests__/thought-stream.test.d.ts +0 -1
  54. package/dist/consciousness/__tests__/thought-stream.test.js +0 -62
  55. package/dist/consciousness/__tests__/thought-stream.test.js.map +0 -1
  56. package/dist/consensus/__tests__/consensus.test.d.ts +0 -1
  57. package/dist/consensus/__tests__/consensus.test.js +0 -159
  58. package/dist/consensus/__tests__/consensus.test.js.map +0 -1
  59. package/dist/content/__tests__/auto-publisher.test.d.ts +0 -1
  60. package/dist/content/__tests__/auto-publisher.test.js +0 -125
  61. package/dist/content/__tests__/auto-publisher.test.js.map +0 -1
  62. package/dist/content/__tests__/content-forge.test.d.ts +0 -1
  63. package/dist/content/__tests__/content-forge.test.js +0 -117
  64. package/dist/content/__tests__/content-forge.test.js.map +0 -1
  65. package/dist/creative/__tests__/creative-engine.test.d.ts +0 -1
  66. package/dist/creative/__tests__/creative-engine.test.js +0 -229
  67. package/dist/creative/__tests__/creative-engine.test.js.map +0 -1
  68. package/dist/cross-brain/__tests__/borg-sync-engine.test.d.ts +0 -1
  69. package/dist/cross-brain/__tests__/borg-sync-engine.test.js +0 -240
  70. package/dist/cross-brain/__tests__/borg-sync-engine.test.js.map +0 -1
  71. package/dist/cross-brain/__tests__/client.test.d.ts +0 -1
  72. package/dist/cross-brain/__tests__/client.test.js +0 -31
  73. package/dist/cross-brain/__tests__/client.test.js.map +0 -1
  74. package/dist/cross-brain/__tests__/notifications.test.d.ts +0 -1
  75. package/dist/cross-brain/__tests__/notifications.test.js +0 -52
  76. package/dist/cross-brain/__tests__/notifications.test.js.map +0 -1
  77. package/dist/cross-brain/__tests__/signal-router.test.d.ts +0 -1
  78. package/dist/cross-brain/__tests__/signal-router.test.js +0 -218
  79. package/dist/cross-brain/__tests__/signal-router.test.js.map +0 -1
  80. package/dist/cross-brain/__tests__/subscription.test.d.ts +0 -1
  81. package/dist/cross-brain/__tests__/subscription.test.js +0 -75
  82. package/dist/cross-brain/__tests__/subscription.test.js.map +0 -1
  83. package/dist/dashboard/__tests__/command-center-server.test.d.ts +0 -1
  84. package/dist/dashboard/__tests__/command-center-server.test.js +0 -522
  85. package/dist/dashboard/__tests__/command-center-server.test.js.map +0 -1
  86. package/dist/dashboard/__tests__/server.test.d.ts +0 -1
  87. package/dist/dashboard/__tests__/server.test.js +0 -105
  88. package/dist/dashboard/__tests__/server.test.js.map +0 -1
  89. package/dist/db/__tests__/connection.test.d.ts +0 -1
  90. package/dist/db/__tests__/connection.test.js +0 -135
  91. package/dist/db/__tests__/connection.test.js.map +0 -1
  92. package/dist/dream/__tests__/dream-engine.test.d.ts +0 -1
  93. package/dist/dream/__tests__/dream-engine.test.js +0 -184
  94. package/dist/dream/__tests__/dream-engine.test.js.map +0 -1
  95. package/dist/embeddings/__tests__/engine.test.d.ts +0 -1
  96. package/dist/embeddings/__tests__/engine.test.js +0 -82
  97. package/dist/embeddings/__tests__/engine.test.js.map +0 -1
  98. package/dist/feedback/__tests__/feedback-engine.test.d.ts +0 -1
  99. package/dist/feedback/__tests__/feedback-engine.test.js +0 -156
  100. package/dist/feedback/__tests__/feedback-engine.test.js.map +0 -1
  101. package/dist/feedback/__tests__/feedback-router.test.d.ts +0 -1
  102. package/dist/feedback/__tests__/feedback-router.test.js +0 -173
  103. package/dist/feedback/__tests__/feedback-router.test.js.map +0 -1
  104. package/dist/goals/__tests__/goal-engine.test.d.ts +0 -1
  105. package/dist/goals/__tests__/goal-engine.test.js +0 -203
  106. package/dist/goals/__tests__/goal-engine.test.js.map +0 -1
  107. package/dist/guardrails/__tests__/guardrail-engine.test.d.ts +0 -1
  108. package/dist/guardrails/__tests__/guardrail-engine.test.js +0 -343
  109. package/dist/guardrails/__tests__/guardrail-engine.test.js.map +0 -1
  110. package/dist/ipc/__tests__/integration.test.d.ts +0 -1
  111. package/dist/ipc/__tests__/integration.test.js +0 -352
  112. package/dist/ipc/__tests__/integration.test.js.map +0 -1
  113. package/dist/ipc/__tests__/protocol.test.d.ts +0 -1
  114. package/dist/ipc/__tests__/protocol.test.js +0 -69
  115. package/dist/ipc/__tests__/protocol.test.js.map +0 -1
  116. package/dist/knowledge-graph/__tests__/contradiction-resolver.test.d.ts +0 -1
  117. package/dist/knowledge-graph/__tests__/contradiction-resolver.test.js +0 -114
  118. package/dist/knowledge-graph/__tests__/contradiction-resolver.test.js.map +0 -1
  119. package/dist/knowledge-graph/__tests__/knowledge-graph.test.d.ts +0 -1
  120. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js +0 -215
  121. package/dist/knowledge-graph/__tests__/knowledge-graph.test.js.map +0 -1
  122. package/dist/learning/__tests__/base-engine.test.d.ts +0 -1
  123. package/dist/learning/__tests__/base-engine.test.js +0 -49
  124. package/dist/learning/__tests__/base-engine.test.js.map +0 -1
  125. package/dist/llm/__tests__/anthropic-provider.test.d.ts +0 -1
  126. package/dist/llm/__tests__/anthropic-provider.test.js +0 -121
  127. package/dist/llm/__tests__/anthropic-provider.test.js.map +0 -1
  128. package/dist/llm/__tests__/llm-service.test.d.ts +0 -1
  129. package/dist/llm/__tests__/llm-service.test.js +0 -507
  130. package/dist/llm/__tests__/llm-service.test.js.map +0 -1
  131. package/dist/llm/__tests__/ollama-embedding.test.d.ts +0 -1
  132. package/dist/llm/__tests__/ollama-embedding.test.js +0 -128
  133. package/dist/llm/__tests__/ollama-embedding.test.js.map +0 -1
  134. package/dist/llm/__tests__/ollama-provider.test.d.ts +0 -1
  135. package/dist/llm/__tests__/ollama-provider.test.js +0 -213
  136. package/dist/llm/__tests__/ollama-provider.test.js.map +0 -1
  137. package/dist/llm/__tests__/provider.test.d.ts +0 -1
  138. package/dist/llm/__tests__/provider.test.js +0 -126
  139. package/dist/llm/__tests__/provider.test.js.map +0 -1
  140. package/dist/math/__tests__/time-decay.test.d.ts +0 -1
  141. package/dist/math/__tests__/time-decay.test.js +0 -37
  142. package/dist/math/__tests__/time-decay.test.js.map +0 -1
  143. package/dist/math/__tests__/wilson-score.test.d.ts +0 -1
  144. package/dist/math/__tests__/wilson-score.test.js +0 -43
  145. package/dist/math/__tests__/wilson-score.test.js.map +0 -1
  146. package/dist/memory/__tests__/base-memory-engine.test.d.ts +0 -1
  147. package/dist/memory/__tests__/base-memory-engine.test.js +0 -233
  148. package/dist/memory/__tests__/base-memory-engine.test.js.map +0 -1
  149. package/dist/metacognition/__tests__/auto-experiment-engine.test.d.ts +0 -1
  150. package/dist/metacognition/__tests__/auto-experiment-engine.test.js +0 -218
  151. package/dist/metacognition/__tests__/auto-experiment-engine.test.js.map +0 -1
  152. package/dist/metacognition/__tests__/evolution-engine.test.d.ts +0 -1
  153. package/dist/metacognition/__tests__/evolution-engine.test.js +0 -473
  154. package/dist/metacognition/__tests__/evolution-engine.test.js.map +0 -1
  155. package/dist/metacognition/__tests__/parameter-registry.test.d.ts +0 -1
  156. package/dist/metacognition/__tests__/parameter-registry.test.js +0 -223
  157. package/dist/metacognition/__tests__/parameter-registry.test.js.map +0 -1
  158. package/dist/missions/__tests__/mission-engine.test.d.ts +0 -1
  159. package/dist/missions/__tests__/mission-engine.test.js +0 -67
  160. package/dist/missions/__tests__/mission-engine.test.js.map +0 -1
  161. package/dist/notifications/__tests__/notification-service.test.d.ts +0 -1
  162. package/dist/notifications/__tests__/notification-service.test.js +0 -176
  163. package/dist/notifications/__tests__/notification-service.test.js.map +0 -1
  164. package/dist/plugin/__tests__/plugin-registry.test.d.ts +0 -1
  165. package/dist/plugin/__tests__/plugin-registry.test.js +0 -166
  166. package/dist/plugin/__tests__/plugin-registry.test.js.map +0 -1
  167. package/dist/prediction/__tests__/prediction-engine.test.d.ts +0 -1
  168. package/dist/prediction/__tests__/prediction-engine.test.js +0 -252
  169. package/dist/prediction/__tests__/prediction-engine.test.js.map +0 -1
  170. package/dist/proactive/__tests__/proactive-engine.test.d.ts +0 -1
  171. package/dist/proactive/__tests__/proactive-engine.test.js +0 -183
  172. package/dist/proactive/__tests__/proactive-engine.test.js.map +0 -1
  173. package/dist/rag/__tests__/rag-engine.test.d.ts +0 -1
  174. package/dist/rag/__tests__/rag-engine.test.js +0 -235
  175. package/dist/rag/__tests__/rag-engine.test.js.map +0 -1
  176. package/dist/research/__tests__/autonomy-features.test.d.ts +0 -1
  177. package/dist/research/__tests__/autonomy-features.test.js +0 -155
  178. package/dist/research/__tests__/autonomy-features.test.js.map +0 -1
  179. package/dist/research/__tests__/base-engine.test.d.ts +0 -1
  180. package/dist/research/__tests__/base-engine.test.js +0 -56
  181. package/dist/research/__tests__/base-engine.test.js.map +0 -1
  182. package/dist/research/__tests__/semantic-compressor.test.d.ts +0 -1
  183. package/dist/research/__tests__/semantic-compressor.test.js +0 -153
  184. package/dist/research/__tests__/semantic-compressor.test.js.map +0 -1
  185. package/dist/research/adapters/__tests__/playwright-adapter.test.d.ts +0 -1
  186. package/dist/research/adapters/__tests__/playwright-adapter.test.js +0 -64
  187. package/dist/research/adapters/__tests__/playwright-adapter.test.js.map +0 -1
  188. package/dist/research/adapters/__tests__/web-adapters.test.d.ts +0 -1
  189. package/dist/research/adapters/__tests__/web-adapters.test.js +0 -106
  190. package/dist/research/adapters/__tests__/web-adapters.test.js.map +0 -1
  191. package/dist/sandbox/__tests__/code-sandbox.test.d.ts +0 -1
  192. package/dist/sandbox/__tests__/code-sandbox.test.js +0 -182
  193. package/dist/sandbox/__tests__/code-sandbox.test.js.map +0 -1
  194. package/dist/scanner/__tests__/signal-scanner.test.d.ts +0 -1
  195. package/dist/scanner/__tests__/signal-scanner.test.js +0 -142
  196. package/dist/scanner/__tests__/signal-scanner.test.js.map +0 -1
  197. package/dist/self-modification/__tests__/self-modification-engine.test.d.ts +0 -1
  198. package/dist/self-modification/__tests__/self-modification-engine.test.js +0 -313
  199. package/dist/self-modification/__tests__/self-modification-engine.test.js.map +0 -1
  200. package/dist/strategy/__tests__/strategy-forge.test.d.ts +0 -1
  201. package/dist/strategy/__tests__/strategy-forge.test.js +0 -190
  202. package/dist/strategy/__tests__/strategy-forge.test.js.map +0 -1
  203. package/dist/strategy/__tests__/strategy-mutator.test.d.ts +0 -1
  204. package/dist/strategy/__tests__/strategy-mutator.test.js +0 -141
  205. package/dist/strategy/__tests__/strategy-mutator.test.js.map +0 -1
  206. package/dist/synapses/__tests__/activation.test.d.ts +0 -1
  207. package/dist/synapses/__tests__/activation.test.js +0 -87
  208. package/dist/synapses/__tests__/activation.test.js.map +0 -1
  209. package/dist/synapses/__tests__/decay.test.d.ts +0 -1
  210. package/dist/synapses/__tests__/decay.test.js +0 -73
  211. package/dist/synapses/__tests__/decay.test.js.map +0 -1
  212. package/dist/synapses/__tests__/hebbian.test.d.ts +0 -1
  213. package/dist/synapses/__tests__/hebbian.test.js +0 -95
  214. package/dist/synapses/__tests__/hebbian.test.js.map +0 -1
  215. package/dist/synapses/__tests__/pathfinder.test.d.ts +0 -1
  216. package/dist/synapses/__tests__/pathfinder.test.js +0 -74
  217. package/dist/synapses/__tests__/pathfinder.test.js.map +0 -1
  218. package/dist/synapses/__tests__/synapse-manager.test.d.ts +0 -1
  219. package/dist/synapses/__tests__/synapse-manager.test.js +0 -94
  220. package/dist/synapses/__tests__/synapse-manager.test.js.map +0 -1
  221. package/dist/teaching/__tests__/teaching.test.d.ts +0 -1
  222. package/dist/teaching/__tests__/teaching.test.js +0 -252
  223. package/dist/teaching/__tests__/teaching.test.js.map +0 -1
  224. package/dist/techradar/__tests__/techradar-engine.test.d.ts +0 -1
  225. package/dist/techradar/__tests__/techradar-engine.test.js +0 -246
  226. package/dist/techradar/__tests__/techradar-engine.test.js.map +0 -1
  227. package/dist/tool-learning/__tests__/tool-learning.test.d.ts +0 -1
  228. package/dist/tool-learning/__tests__/tool-learning.test.js +0 -187
  229. package/dist/tool-learning/__tests__/tool-learning.test.js.map +0 -1
  230. package/dist/user-model/__tests__/user-model.test.d.ts +0 -1
  231. package/dist/user-model/__tests__/user-model.test.js +0 -142
  232. package/dist/user-model/__tests__/user-model.test.js.map +0 -1
  233. package/dist/utils/__tests__/batch-queue.test.d.ts +0 -1
  234. package/dist/utils/__tests__/batch-queue.test.js +0 -85
  235. package/dist/utils/__tests__/batch-queue.test.js.map +0 -1
  236. package/dist/utils/__tests__/events.test.d.ts +0 -1
  237. package/dist/utils/__tests__/events.test.js +0 -38
  238. package/dist/utils/__tests__/events.test.js.map +0 -1
  239. package/dist/utils/__tests__/hash.test.d.ts +0 -1
  240. package/dist/utils/__tests__/hash.test.js +0 -25
  241. package/dist/utils/__tests__/hash.test.js.map +0 -1
  242. package/dist/utils/__tests__/logger.test.d.ts +0 -1
  243. package/dist/utils/__tests__/logger.test.js +0 -55
  244. package/dist/utils/__tests__/logger.test.js.map +0 -1
  245. package/dist/utils/__tests__/paths.test.d.ts +0 -1
  246. package/dist/utils/__tests__/paths.test.js +0 -50
  247. package/dist/utils/__tests__/paths.test.js.map +0 -1
  248. package/dist/utils/__tests__/retry.test.d.ts +0 -1
  249. package/dist/utils/__tests__/retry.test.js +0 -91
  250. package/dist/utils/__tests__/retry.test.js.map +0 -1
  251. package/dist/watchdog/__tests__/watchdog-service.test.d.ts +0 -1
  252. package/dist/watchdog/__tests__/watchdog-service.test.js +0 -113
  253. package/dist/watchdog/__tests__/watchdog-service.test.js.map +0 -1
@@ -1,166 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import os from 'node:os';
5
- import { PluginRegistry } from '../plugin-registry.js';
6
- function createMockContext(name) {
7
- return {
8
- dataDir: path.join(os.tmpdir(), 'brain-test-plugins', name),
9
- log: {
10
- info: vi.fn(),
11
- warn: vi.fn(),
12
- error: vi.fn(),
13
- debug: vi.fn(),
14
- },
15
- callBrain: vi.fn().mockResolvedValue({}),
16
- notify: vi.fn().mockResolvedValue(undefined),
17
- };
18
- }
19
- describe('PluginRegistry', () => {
20
- let tmpDir;
21
- let registry;
22
- beforeEach(() => {
23
- tmpDir = path.join(os.tmpdir(), `brain-plugin-test-${Date.now()}`);
24
- fs.mkdirSync(tmpDir, { recursive: true });
25
- registry = new PluginRegistry(tmpDir);
26
- });
27
- afterEach(() => {
28
- fs.rmSync(tmpDir, { recursive: true, force: true });
29
- });
30
- it('creates plugin directory if it does not exist', () => {
31
- const newDir = path.join(tmpDir, 'subdir');
32
- const reg = new PluginRegistry(newDir);
33
- expect(fs.existsSync(newDir)).toBe(true);
34
- });
35
- it('starts with no plugins', () => {
36
- expect(registry.size).toBe(0);
37
- expect(registry.list()).toEqual([]);
38
- expect(registry.getRoutes()).toEqual([]);
39
- expect(registry.getTools()).toEqual([]);
40
- });
41
- it('has() returns false for unknown plugin', () => {
42
- expect(registry.has('nonexistent')).toBe(false);
43
- });
44
- it('get() returns null for unknown plugin', () => {
45
- expect(registry.get('nonexistent')).toBeNull();
46
- });
47
- it('loadAll with empty directory loads nothing', async () => {
48
- await registry.loadAll((name) => createMockContext(name));
49
- expect(registry.size).toBe(0);
50
- });
51
- it('loadAll skips directories without package.json', async () => {
52
- fs.mkdirSync(path.join(tmpDir, 'empty-dir'));
53
- await registry.loadAll((name) => createMockContext(name));
54
- expect(registry.size).toBe(0);
55
- });
56
- it('loadAll skips packages without brainPlugin flag', async () => {
57
- const pluginDir = path.join(tmpDir, 'normal-pkg');
58
- fs.mkdirSync(pluginDir);
59
- fs.writeFileSync(path.join(pluginDir, 'package.json'), JSON.stringify({
60
- name: 'normal-pkg',
61
- version: '1.0.0',
62
- }));
63
- fs.writeFileSync(path.join(pluginDir, 'index.js'), 'module.exports = {}');
64
- await registry.loadAll((name) => createMockContext(name));
65
- expect(registry.size).toBe(0);
66
- });
67
- it('unloadPlugin returns false for unknown plugin', async () => {
68
- expect(await registry.unloadPlugin('nonexistent')).toBe(false);
69
- });
70
- it('runCycle does nothing with no plugins', async () => {
71
- await expect(registry.runCycle(1)).resolves.toBeUndefined();
72
- });
73
- it('list returns empty array when no plugins loaded', () => {
74
- expect(registry.list()).toEqual([]);
75
- });
76
- it('getRoutes returns plugin-prefixed routes', () => {
77
- // Manually inject a plugin for testing
78
- const plugin = {
79
- name: 'test-plugin',
80
- version: '1.0.0',
81
- routes: [
82
- { method: 'test.hello', handler: () => ({ hello: 'world' }) },
83
- ],
84
- };
85
- // Access internal map (testing only)
86
- registry.plugins.set('test-plugin', {
87
- plugin,
88
- path: '/fake',
89
- loadedAt: new Date().toISOString(),
90
- error: null,
91
- });
92
- const routes = registry.getRoutes();
93
- expect(routes).toHaveLength(1);
94
- expect(routes[0].plugin).toBe('test-plugin');
95
- expect(routes[0].method).toBe('test.hello');
96
- });
97
- it('getTools returns plugin-prefixed tools', () => {
98
- const plugin = {
99
- name: 'test-plugin',
100
- version: '1.0.0',
101
- tools: [
102
- { name: 'test_tool', description: 'A test', schema: {}, handler: () => 'ok' },
103
- ],
104
- };
105
- registry.plugins.set('test-plugin', {
106
- plugin,
107
- path: '/fake',
108
- loadedAt: new Date().toISOString(),
109
- error: null,
110
- });
111
- const tools = registry.getTools();
112
- expect(tools).toHaveLength(1);
113
- expect(tools[0].plugin).toBe('test-plugin');
114
- expect(tools[0].name).toBe('test_tool');
115
- });
116
- it('runCycle calls onCycle for loaded plugins', async () => {
117
- const onCycle = vi.fn();
118
- const plugin = {
119
- name: 'cycle-plugin',
120
- version: '1.0.0',
121
- onCycle,
122
- };
123
- registry.plugins.set('cycle-plugin', {
124
- plugin,
125
- path: '/fake',
126
- loadedAt: new Date().toISOString(),
127
- error: null,
128
- });
129
- await registry.runCycle(42);
130
- expect(onCycle).toHaveBeenCalledWith(42);
131
- });
132
- it('runCycle catches errors from plugins', async () => {
133
- const plugin = {
134
- name: 'bad-plugin',
135
- version: '1.0.0',
136
- onCycle: () => { throw new Error('boom'); },
137
- };
138
- registry.plugins.set('bad-plugin', {
139
- plugin,
140
- path: '/fake',
141
- loadedAt: new Date().toISOString(),
142
- error: null,
143
- });
144
- // Should not throw
145
- await expect(registry.runCycle(1)).resolves.toBeUndefined();
146
- });
147
- it('unloadPlugin calls onUnload and removes', async () => {
148
- const onUnload = vi.fn();
149
- const plugin = {
150
- name: 'unload-test',
151
- version: '1.0.0',
152
- onUnload,
153
- };
154
- registry.plugins.set('unload-test', {
155
- plugin,
156
- path: '/fake',
157
- loadedAt: new Date().toISOString(),
158
- error: null,
159
- });
160
- expect(registry.has('unload-test')).toBe(true);
161
- await registry.unloadPlugin('unload-test');
162
- expect(registry.has('unload-test')).toBe(false);
163
- expect(onUnload).toHaveBeenCalled();
164
- });
165
- });
166
- //# sourceMappingURL=plugin-registry.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-registry.test.js","sourceRoot":"","sources":["../../../src/plugin/__tests__/plugin-registry.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,252 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import Database from 'better-sqlite3';
3
- vi.mock('../../utils/logger.js', () => ({
4
- getLogger: () => ({
5
- info: vi.fn(),
6
- warn: vi.fn(),
7
- error: vi.fn(),
8
- debug: vi.fn(),
9
- }),
10
- }));
11
- import { PredictionEngine, runPredictionMigration } from '../prediction-engine.js';
12
- // ── Helpers ───────────────────────────────────────────────
13
- /** Seed ascending metric data to produce a predictable upward trend. */
14
- function seedMetrics(db, metric, count, options) {
15
- const baseValue = options?.baseValue ?? 10;
16
- const step = options?.step ?? 1;
17
- const domain = options?.domain ?? 'metric';
18
- const baseTime = options?.baseTime ?? Date.now() - count * 60_000;
19
- for (let i = 0; i < count; i++) {
20
- db.prepare('INSERT INTO prediction_metrics (metric, value, domain, timestamp) VALUES (?, ?, ?, ?)').run(metric, baseValue + i * step, domain, baseTime + i * 60_000);
21
- }
22
- }
23
- // ── Tests ─────────────────────────────────────────────────
24
- describe('runPredictionMigration', () => {
25
- let db;
26
- beforeEach(() => { db = new Database(':memory:'); });
27
- afterEach(() => { db.close(); });
28
- it('creates predictions, prediction_metrics, and prediction_state tables', () => {
29
- runPredictionMigration(db);
30
- const tables = db
31
- .prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
32
- .all();
33
- const names = tables.map(t => t.name);
34
- expect(names).toContain('predictions');
35
- expect(names).toContain('prediction_metrics');
36
- expect(names).toContain('prediction_state');
37
- });
38
- it('initialises prediction_state with a single row', () => {
39
- runPredictionMigration(db);
40
- const row = db.prepare('SELECT * FROM prediction_state WHERE id = 1').get();
41
- expect(row).toBeDefined();
42
- expect(row.total_predictions).toBe(0);
43
- expect(row.total_resolved).toBe(0);
44
- expect(row.total_correct).toBe(0);
45
- expect(row.calibration_offset).toBe(0);
46
- });
47
- it('is idempotent (running twice does not throw)', () => {
48
- runPredictionMigration(db);
49
- expect(() => runPredictionMigration(db)).not.toThrow();
50
- });
51
- });
52
- describe('PredictionEngine', () => {
53
- let db;
54
- let engine;
55
- beforeEach(() => {
56
- db = new Database(':memory:');
57
- runPredictionMigration(db);
58
- engine = new PredictionEngine(db, { brainName: 'test-brain', minConfidence: 0.01, minDataPoints: 5 });
59
- });
60
- afterEach(() => {
61
- engine.stop();
62
- db.close();
63
- });
64
- // ── Creation & Config ───────────────────────────────────
65
- it('creates an engine with default config values', () => {
66
- const cfg = engine.getConfig();
67
- expect(cfg.brainName).toBe('test-brain');
68
- expect(cfg.defaultHorizonMs).toBe(600_000);
69
- expect(cfg.expirationMs).toBe(3_600_000);
70
- expect(cfg.ewmaAlpha).toBe(0.3);
71
- expect(cfg.trendBeta).toBe(0.1);
72
- expect(cfg.minDataPoints).toBe(5);
73
- expect(cfg.minConfidence).toBe(0.01);
74
- expect(cfg.maxPredictionsPerCycle).toBe(5);
75
- expect(cfg.resolveIntervalMs).toBe(60_000);
76
- });
77
- it('updateConfig merges partial updates', () => {
78
- engine.updateConfig({ ewmaAlpha: 0.5, trendBeta: 0.2 });
79
- const cfg = engine.getConfig();
80
- expect(cfg.ewmaAlpha).toBe(0.5);
81
- expect(cfg.trendBeta).toBe(0.2);
82
- // unchanged fields remain
83
- expect(cfg.minDataPoints).toBe(5);
84
- });
85
- // ── recordMetric ────────────────────────────────────────
86
- it('recordMetric inserts data points into prediction_metrics', () => {
87
- engine.recordMetric('cpu_load', 42.5, 'metric');
88
- engine.recordMetric('cpu_load', 45.0, 'metric');
89
- engine.recordMetric('cpu_load', 47.2, 'metric');
90
- const rows = db.prepare('SELECT * FROM prediction_metrics WHERE metric = ?').all('cpu_load');
91
- expect(rows).toHaveLength(3);
92
- });
93
- // ── predict ─────────────────────────────────────────────
94
- it('predict returns null when insufficient data (< 2 points)', () => {
95
- engine.recordMetric('sparse', 10);
96
- const result = engine.predict({ domain: 'metric', metric: 'sparse' });
97
- expect(result).toBeNull();
98
- });
99
- it('predict returns a Prediction with EWMA when 2-4 data points exist', () => {
100
- seedMetrics(db, 'short_series', 3, { baseValue: 10, step: 5 });
101
- const prediction = engine.predict({ domain: 'metric', metric: 'short_series' });
102
- expect(prediction).not.toBeNull();
103
- expect(prediction.method).toBe('ewma');
104
- expect(prediction.status).toBe('pending');
105
- expect(prediction.domain).toBe('metric');
106
- expect(prediction.metric).toBe('short_series');
107
- expect(prediction.prediction_id).toBeTruthy();
108
- expect(prediction.confidence).toBeGreaterThan(0);
109
- expect(prediction.horizon_ms).toBe(600_000);
110
- });
111
- it('predict returns a Prediction with holt_winters when >= minDataPoints', () => {
112
- seedMetrics(db, 'long_series', 10, { baseValue: 100, step: 2 });
113
- const prediction = engine.predict({ domain: 'trade', metric: 'long_series' });
114
- expect(prediction).not.toBeNull();
115
- expect(prediction.method).toBe('holt_winters');
116
- expect(prediction.predicted_direction).toBe('up');
117
- expect(prediction.evidence).toHaveProperty('dataPoints', 10);
118
- expect(prediction.evidence).toHaveProperty('trend');
119
- });
120
- it('predict increments total_predictions in prediction_state', () => {
121
- seedMetrics(db, 'counter_test', 3, { baseValue: 10, step: 1 });
122
- engine.predict({ domain: 'metric', metric: 'counter_test' });
123
- engine.predict({ domain: 'metric', metric: 'counter_test' });
124
- const state = db.prepare('SELECT total_predictions FROM prediction_state WHERE id = 1').get();
125
- expect(state.total_predictions).toBe(2);
126
- });
127
- // ── forecast ────────────────────────────────────────────
128
- it('forecast uses EWMA for small datasets and holt_winters for large', () => {
129
- const shortResult = engine.forecast([10, 20, 30], 60_000);
130
- expect(shortResult.method).toBe('ewma');
131
- expect(shortResult.dataPoints).toBe(3);
132
- const longResult = engine.forecast([10, 20, 30, 40, 50, 60, 70], 60_000);
133
- expect(longResult.method).toBe('holt_winters');
134
- expect(longResult.dataPoints).toBe(7);
135
- expect(longResult.direction).toBe('up');
136
- });
137
- // ── list ────────────────────────────────────────────────
138
- it('list returns stored predictions, optionally filtered by domain/status', () => {
139
- seedMetrics(db, 'm1', 3, { baseValue: 10, step: 1, domain: 'error' });
140
- seedMetrics(db, 'm2', 3, { baseValue: 50, step: 5, domain: 'trade' });
141
- engine.predict({ domain: 'error', metric: 'm1' });
142
- engine.predict({ domain: 'trade', metric: 'm2' });
143
- const all = engine.list();
144
- expect(all).toHaveLength(2);
145
- const errorOnly = engine.list('error');
146
- expect(errorOnly).toHaveLength(1);
147
- expect(errorOnly[0].domain).toBe('error');
148
- const pendingOnly = engine.list(undefined, 'pending');
149
- expect(pendingOnly).toHaveLength(2);
150
- });
151
- // ── getAccuracy ─────────────────────────────────────────
152
- it('getAccuracy returns per-domain accuracy stats after resolution', () => {
153
- // Insert a prediction directly, then resolve it via the tracker
154
- seedMetrics(db, 'acc_metric', 5, { baseValue: 100, step: 1 });
155
- const pred = engine.predict({ domain: 'error', metric: 'acc_metric' });
156
- expect(pred).not.toBeNull();
157
- // Manually resolve: set status to 'correct' in DB
158
- db.prepare("UPDATE predictions SET status = 'correct', actual_value = ?, error = 0.01 WHERE prediction_id = ?")
159
- .run(pred.predicted_value, pred.prediction_id);
160
- const accuracy = engine.getAccuracy('error');
161
- expect(accuracy).toHaveLength(1);
162
- expect(accuracy[0].domain).toBe('error');
163
- expect(accuracy[0].correct).toBe(1);
164
- expect(accuracy[0].accuracy_rate).toBe(1);
165
- });
166
- // ── getSummary ──────────────────────────────────────────
167
- it('getSummary returns a full summary with totals and recent predictions', () => {
168
- seedMetrics(db, 'sum_m', 4, { baseValue: 5, step: 2 });
169
- engine.predict({ domain: 'metric', metric: 'sum_m' });
170
- const summary = engine.getSummary();
171
- expect(summary.total_predictions).toBe(1);
172
- expect(summary.pending).toBe(1);
173
- expect(summary.resolved).toBe(0);
174
- expect(summary.accuracy_rate).toBe(0);
175
- expect(summary.calibration_offset).toBe(0);
176
- expect(summary.recent).toHaveLength(1);
177
- expect(summary.by_domain).toEqual([]);
178
- });
179
- // ── resolveExpired ──────────────────────────────────────
180
- it('resolveExpired marks predictions past expires_at as expired', () => {
181
- seedMetrics(db, 'exp_m', 3, { baseValue: 10, step: 1 });
182
- const pred = engine.predict({ domain: 'metric', metric: 'exp_m' });
183
- expect(pred).not.toBeNull();
184
- // Force the prediction to be expired by setting expires_at to the past
185
- const past = Date.now() - 10_000;
186
- db.prepare('UPDATE predictions SET expires_at = ? WHERE prediction_id = ?')
187
- .run(past, pred.prediction_id);
188
- const resolved = engine.resolveExpired();
189
- expect(resolved).toBeGreaterThanOrEqual(1);
190
- const updated = engine.list(undefined, 'expired');
191
- expect(updated).toHaveLength(1);
192
- expect(updated[0].prediction_id).toBe(pred.prediction_id);
193
- });
194
- it('resolveExpired resolves predictions past their horizon against actual data', () => {
195
- seedMetrics(db, 'res_m', 4, { baseValue: 50, step: 2 });
196
- const pred = engine.predict({ domain: 'metric', metric: 'res_m' });
197
- expect(pred).not.toBeNull();
198
- // Make the prediction resolvable: created_at + horizon_ms <= now AND expires_at >= now
199
- const now = Date.now();
200
- db.prepare('UPDATE predictions SET created_at = ?, expires_at = ? WHERE prediction_id = ?')
201
- .run(now - pred.horizon_ms - 1000, now + 100_000, pred.prediction_id);
202
- // Insert post-prediction metric values (timestamp > created_at)
203
- const predCreatedAt = now - pred.horizon_ms - 1000;
204
- for (let i = 0; i < 5; i++) {
205
- db.prepare('INSERT INTO prediction_metrics (metric, value, domain, timestamp) VALUES (?, ?, ?, ?)')
206
- .run('res_m', pred.predicted_value + i * 0.1, 'metric', predCreatedAt + 1000 + i * 1000);
207
- }
208
- const resolved = engine.resolveExpired();
209
- expect(resolved).toBeGreaterThanOrEqual(1);
210
- // The prediction should no longer be 'pending'
211
- const pending = engine.list(undefined, 'pending');
212
- const resolvedPred = pending.find(p => p.prediction_id === pred.prediction_id);
213
- expect(resolvedPred).toBeUndefined();
214
- });
215
- // ── getMetricHistory ────────────────────────────────────
216
- it('getMetricHistory returns data points in ascending timestamp order', () => {
217
- engine.recordMetric('hist_m', 10);
218
- engine.recordMetric('hist_m', 20);
219
- engine.recordMetric('hist_m', 30);
220
- const history = engine.getMetricHistory('hist_m', 10);
221
- expect(history).toHaveLength(3);
222
- expect(history[0].value).toBe(10);
223
- expect(history[2].value).toBe(30);
224
- expect(history[0].timestamp).toBeLessThanOrEqual(history[1].timestamp);
225
- expect(history[1].timestamp).toBeLessThanOrEqual(history[2].timestamp);
226
- });
227
- it('getMetricHistory respects the limit parameter', () => {
228
- for (let i = 0; i < 20; i++) {
229
- engine.recordMetric('limited_m', i);
230
- }
231
- const limited = engine.getMetricHistory('limited_m', 5);
232
- expect(limited).toHaveLength(5);
233
- });
234
- // ── start / stop ────────────────────────────────────────
235
- it('start and stop manage the resolution timer without error', () => {
236
- expect(() => engine.start()).not.toThrow();
237
- // calling start again is a no-op
238
- expect(() => engine.start()).not.toThrow();
239
- expect(() => engine.stop()).not.toThrow();
240
- // stopping again is safe
241
- expect(() => engine.stop()).not.toThrow();
242
- });
243
- // ── getCalibration ─────────────────────────────────────
244
- it('getCalibration returns offset and accuracy by domain', () => {
245
- const calibration = engine.getCalibration();
246
- expect(calibration).toHaveProperty('offset');
247
- expect(calibration).toHaveProperty('accuracyByDomain');
248
- expect(typeof calibration.offset).toBe('number');
249
- expect(Array.isArray(calibration.accuracyByDomain)).toBe(true);
250
- });
251
- });
252
- //# sourceMappingURL=prediction-engine.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prediction-engine.test.js","sourceRoot":"","sources":["../../../src/prediction/__tests__/prediction-engine.test.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,183 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import Database from 'better-sqlite3';
3
- vi.mock('../../utils/logger.js', () => ({
4
- getLogger: () => ({
5
- info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn(),
6
- }),
7
- }));
8
- import { ProactiveEngine, runProactiveMigration } from '../proactive-engine.js';
9
- function createDb() {
10
- return new Database(':memory:');
11
- }
12
- describe('ProactiveEngine', () => {
13
- let db;
14
- beforeEach(() => {
15
- db = createDb();
16
- });
17
- afterEach(() => {
18
- db.close();
19
- });
20
- it('creates a suggestion and retrieves it', () => {
21
- const engine = new ProactiveEngine(db, { brainName: 'test' });
22
- const ok = engine.createSuggestion('info', 'Test Suggestion', 'A description', 'Do something', 0.7);
23
- expect(ok).toBe(true);
24
- const suggestions = engine.getSuggestions();
25
- expect(suggestions).toHaveLength(1);
26
- expect(suggestions[0].title).toBe('Test Suggestion');
27
- expect(suggestions[0].priority).toBe(0.7);
28
- expect(suggestions[0].type).toBe('info');
29
- });
30
- it('returns suggestions sorted by priority descending', () => {
31
- const engine = new ProactiveEngine(db, { brainName: 'test' });
32
- engine.createSuggestion('low', 'Low Priority', undefined, undefined, 0.2);
33
- engine.createSuggestion('high', 'High Priority', undefined, undefined, 0.9);
34
- engine.createSuggestion('mid', 'Mid Priority', undefined, undefined, 0.5);
35
- const suggestions = engine.getSuggestions();
36
- expect(suggestions).toHaveLength(3);
37
- expect(suggestions[0].title).toBe('High Priority');
38
- expect(suggestions[1].title).toBe('Mid Priority');
39
- expect(suggestions[2].title).toBe('Low Priority');
40
- });
41
- it('dismisses a suggestion', () => {
42
- const engine = new ProactiveEngine(db, { brainName: 'test' });
43
- engine.createSuggestion('info', 'To Dismiss', 'desc');
44
- const before = engine.getSuggestions();
45
- expect(before).toHaveLength(1);
46
- engine.dismiss(before[0].id);
47
- const after = engine.getSuggestions();
48
- expect(after).toHaveLength(0);
49
- });
50
- it('respects rate limiting (max per hour)', () => {
51
- const engine = new ProactiveEngine(db, {
52
- brainName: 'test',
53
- maxSuggestionsPerHour: 2,
54
- });
55
- expect(engine.createSuggestion('a', 'First')).toBe(true);
56
- expect(engine.createSuggestion('b', 'Second')).toBe(true);
57
- expect(engine.createSuggestion('c', 'Third')).toBe(false); // Rate limited
58
- });
59
- it('checks recurring errors trigger', () => {
60
- const engine = new ProactiveEngine(db, {
61
- brainName: 'test',
62
- recurringThreshold: 3,
63
- });
64
- // Create error_memory table and populate
65
- db.exec(`
66
- CREATE TABLE error_memory (
67
- id INTEGER PRIMARY KEY,
68
- fingerprint TEXT NOT NULL,
69
- message TEXT NOT NULL
70
- )
71
- `);
72
- // Insert 3 errors with same fingerprint
73
- const insert = db.prepare('INSERT INTO error_memory (fingerprint, message) VALUES (?, ?)');
74
- insert.run('null-ref-001', 'Cannot read property of null');
75
- insert.run('null-ref-001', 'Cannot read property of null');
76
- insert.run('null-ref-001', 'Cannot read property of null');
77
- const created = engine.analyze({ db });
78
- expect(created).toBeGreaterThanOrEqual(1);
79
- const suggestions = engine.getSuggestions();
80
- const errorSuggestion = suggestions.find(s => s.type === 'recurring_error');
81
- expect(errorSuggestion).toBeDefined();
82
- expect(errorSuggestion.title).toContain('null-ref-001');
83
- });
84
- it('checks stale knowledge trigger', () => {
85
- const engine = new ProactiveEngine(db, {
86
- brainName: 'test',
87
- staleDays: 30,
88
- });
89
- // Create insights table with old high-confidence insight
90
- db.exec(`
91
- CREATE TABLE insights (
92
- id INTEGER PRIMARY KEY,
93
- topic TEXT NOT NULL,
94
- created_at TEXT NOT NULL,
95
- confidence REAL NOT NULL
96
- )
97
- `);
98
- db.prepare(`
99
- INSERT INTO insights (topic, created_at, confidence)
100
- VALUES (?, datetime('now', '-60 days'), 0.9)
101
- `).run('old-topic');
102
- const created = engine.analyze({ db });
103
- expect(created).toBeGreaterThanOrEqual(1);
104
- const suggestions = engine.getSuggestions();
105
- const staleSuggestion = suggestions.find(s => s.type === 'stale_knowledge');
106
- expect(staleSuggestion).toBeDefined();
107
- expect(staleSuggestion.title).toContain('old-topic');
108
- });
109
- it('getStatus returns correct counts', () => {
110
- const engine = new ProactiveEngine(db, { brainName: 'test' });
111
- engine.createSuggestion('a', 'Active 1');
112
- engine.createSuggestion('b', 'Active 2');
113
- const suggestions = engine.getSuggestions();
114
- engine.dismiss(suggestions[0].id);
115
- const status = engine.getStatus();
116
- expect(status.totalSuggestions).toBe(2);
117
- expect(status.activeSuggestions).toBe(1);
118
- expect(status.dismissedCount).toBe(1);
119
- expect(status.lastAnalysis).toBeNull(); // No analyze() called
120
- });
121
- it('migration is idempotent', () => {
122
- const engine1 = new ProactiveEngine(db, { brainName: 'test' });
123
- engine1.createSuggestion('test', 'Survives Migration');
124
- // Run migration again
125
- runProactiveMigration(db);
126
- const engine2 = new ProactiveEngine(db, { brainName: 'test' });
127
- const suggestions = engine2.getSuggestions();
128
- expect(suggestions).toHaveLength(1);
129
- expect(suggestions[0].title).toBe('Survives Migration');
130
- });
131
- it('returns zero suggestions from empty analysis', () => {
132
- const engine = new ProactiveEngine(db, { brainName: 'test' });
133
- // No error_memory, insights, or tool_usage tables exist
134
- const created = engine.analyze({ db });
135
- expect(created).toBe(0);
136
- });
137
- it('dismissed suggestions not returned by default', () => {
138
- const engine = new ProactiveEngine(db, { brainName: 'test' });
139
- engine.createSuggestion('a', 'Visible');
140
- engine.createSuggestion('b', 'Hidden');
141
- const all = engine.getSuggestions();
142
- engine.dismiss(all.find(s => s.title === 'Hidden').id);
143
- const active = engine.getSuggestions();
144
- expect(active).toHaveLength(1);
145
- expect(active[0].title).toBe('Visible');
146
- const withDismissed = engine.getSuggestions(20, true);
147
- expect(withDismissed).toHaveLength(2);
148
- });
149
- it('deduplicates suggestions with same title', () => {
150
- const engine = new ProactiveEngine(db, { brainName: 'test' });
151
- expect(engine.createSuggestion('a', 'Same Title')).toBe(true);
152
- expect(engine.createSuggestion('b', 'Same Title')).toBe(false); // Duplicate
153
- const suggestions = engine.getSuggestions();
154
- expect(suggestions).toHaveLength(1);
155
- });
156
- it('checks quick wins trigger (tool_usage table)', () => {
157
- const engine = new ProactiveEngine(db, { brainName: 'test' });
158
- // Create tool_usage table
159
- db.exec(`
160
- CREATE TABLE IF NOT EXISTS tool_usage (
161
- id INTEGER PRIMARY KEY,
162
- tool_name TEXT NOT NULL,
163
- context TEXT,
164
- duration_ms INTEGER,
165
- outcome TEXT DEFAULT 'success',
166
- metadata TEXT,
167
- created_at TEXT DEFAULT (datetime('now'))
168
- )
169
- `);
170
- // Insert a tool with high success rate but low usage
171
- const insert = db.prepare('INSERT INTO tool_usage (tool_name, outcome) VALUES (?, ?)');
172
- insert.run('rare-but-good', 'success');
173
- insert.run('rare-but-good', 'success');
174
- insert.run('rare-but-good', 'success');
175
- const created = engine.analyze({ db });
176
- expect(created).toBeGreaterThanOrEqual(1);
177
- const suggestions = engine.getSuggestions();
178
- const quickWin = suggestions.find(s => s.type === 'quick_win');
179
- expect(quickWin).toBeDefined();
180
- expect(quickWin.title).toContain('rare-but-good');
181
- });
182
- });
183
- //# sourceMappingURL=proactive-engine.test.js.map