@mxf-dev/core 1.0.1 → 2.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 (298) hide show
  1. package/README.md +18 -0
  2. package/dist/adapters/FrameworkAdapter.js +1 -1
  3. package/dist/adapters/FrameworkAdapter.js.map +1 -1
  4. package/dist/config/ConfigManager.d.ts +9 -8
  5. package/dist/config/ConfigManager.d.ts.map +1 -1
  6. package/dist/config/ConfigManager.js +47 -17
  7. package/dist/config/ConfigManager.js.map +1 -1
  8. package/dist/config/memory-strata.config.d.ts +25 -0
  9. package/dist/config/memory-strata.config.d.ts.map +1 -0
  10. package/dist/config/memory-strata.config.js +107 -0
  11. package/dist/config/memory-strata.config.js.map +1 -0
  12. package/dist/constants/ToolNames.d.ts +1 -29
  13. package/dist/constants/ToolNames.d.ts.map +1 -1
  14. package/dist/constants/ToolNames.js +4 -17
  15. package/dist/constants/ToolNames.js.map +1 -1
  16. package/dist/database/DatabaseAdapterFactory.d.ts +14 -2
  17. package/dist/database/DatabaseAdapterFactory.d.ts.map +1 -1
  18. package/dist/database/DatabaseAdapterFactory.js +21 -6
  19. package/dist/database/DatabaseAdapterFactory.js.map +1 -1
  20. package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts +7 -1
  21. package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts.map +1 -1
  22. package/dist/database/adapters/mongodb/MongoBaseRepository.js +12 -2
  23. package/dist/database/adapters/mongodb/MongoBaseRepository.js.map +1 -1
  24. package/dist/events/ClientEventBus.d.ts +16 -77
  25. package/dist/events/ClientEventBus.d.ts.map +1 -1
  26. package/dist/events/ClientEventBus.js +38 -311
  27. package/dist/events/ClientEventBus.js.map +1 -1
  28. package/dist/events/EventBus.d.ts +1 -1
  29. package/dist/events/EventBus.d.ts.map +1 -1
  30. package/dist/events/EventBus.js +5 -4
  31. package/dist/events/EventBus.js.map +1 -1
  32. package/dist/events/EventBusBase.d.ts +139 -34
  33. package/dist/events/EventBusBase.d.ts.map +1 -1
  34. package/dist/events/EventBusBase.js +366 -88
  35. package/dist/events/EventBusBase.js.map +1 -1
  36. package/dist/events/EventNames.d.ts +10 -1
  37. package/dist/events/EventNames.d.ts.map +1 -1
  38. package/dist/events/EventNames.js +3 -0
  39. package/dist/events/EventNames.js.map +1 -1
  40. package/dist/events/PublicEvents.d.ts +6 -2
  41. package/dist/events/PublicEvents.d.ts.map +1 -1
  42. package/dist/events/PublicEvents.js +7 -4
  43. package/dist/events/PublicEvents.js.map +1 -1
  44. package/dist/events/ServerEventBus.d.ts +23 -112
  45. package/dist/events/ServerEventBus.d.ts.map +1 -1
  46. package/dist/events/ServerEventBus.js +58 -323
  47. package/dist/events/ServerEventBus.js.map +1 -1
  48. package/dist/events/event-definitions/LlmBudgetEvents.d.ts +68 -0
  49. package/dist/events/event-definitions/LlmBudgetEvents.d.ts.map +1 -0
  50. package/dist/events/event-definitions/LlmBudgetEvents.js +35 -0
  51. package/dist/events/event-definitions/LlmBudgetEvents.js.map +1 -0
  52. package/dist/interfaces/IMemoryPersistence.d.ts +41 -0
  53. package/dist/interfaces/IMemoryPersistence.d.ts.map +1 -0
  54. package/dist/interfaces/IMemoryPersistence.js +15 -0
  55. package/dist/interfaces/IMemoryPersistence.js.map +1 -0
  56. package/dist/middleware/MxpMiddleware.d.ts +8 -1
  57. package/dist/middleware/MxpMiddleware.d.ts.map +1 -1
  58. package/dist/middleware/MxpMiddleware.js +42 -20
  59. package/dist/middleware/MxpMiddleware.js.map +1 -1
  60. package/dist/models/channelKey.d.ts +1 -0
  61. package/dist/models/channelKey.d.ts.map +1 -1
  62. package/dist/models/channelKey.js +5 -0
  63. package/dist/models/channelKey.js.map +1 -1
  64. package/dist/models/memoryUtility.d.ts +39 -0
  65. package/dist/models/memoryUtility.d.ts.map +1 -0
  66. package/dist/models/memoryUtility.js +39 -0
  67. package/dist/models/memoryUtility.js.map +1 -0
  68. package/dist/models/user.d.ts.map +1 -1
  69. package/dist/models/user.js +23 -1
  70. package/dist/models/user.js.map +1 -1
  71. package/dist/mxp/BinaryProtocolLayer.d.ts +24 -8
  72. package/dist/mxp/BinaryProtocolLayer.d.ts.map +1 -1
  73. package/dist/mxp/BinaryProtocolLayer.js +90 -103
  74. package/dist/mxp/BinaryProtocolLayer.js.map +1 -1
  75. package/dist/mxp/ContextCompressionEngine.d.ts +57 -10
  76. package/dist/mxp/ContextCompressionEngine.d.ts.map +1 -1
  77. package/dist/mxp/ContextCompressionEngine.js +170 -128
  78. package/dist/mxp/ContextCompressionEngine.js.map +1 -1
  79. package/dist/mxp/MxpTokenOptimizer.d.ts +7 -3
  80. package/dist/mxp/MxpTokenOptimizer.d.ts.map +1 -1
  81. package/dist/mxp/MxpTokenOptimizer.js +8 -5
  82. package/dist/mxp/MxpTokenOptimizer.js.map +1 -1
  83. package/dist/prompts/MxfAgentSystemPrompt.d.ts +1 -1
  84. package/dist/prompts/MxfAgentSystemPrompt.d.ts.map +1 -1
  85. package/dist/prompts/MxfAgentSystemPrompt.js +47 -57
  86. package/dist/prompts/MxfAgentSystemPrompt.js.map +1 -1
  87. package/dist/protocols/mcp/ToolError.d.ts +123 -0
  88. package/dist/protocols/mcp/ToolError.d.ts.map +1 -0
  89. package/dist/protocols/mcp/ToolError.js +108 -0
  90. package/dist/protocols/mcp/ToolError.js.map +1 -0
  91. package/dist/protocols/mcp/defineTool.d.ts +133 -0
  92. package/dist/protocols/mcp/defineTool.d.ts.map +1 -0
  93. package/dist/protocols/mcp/defineTool.js +236 -0
  94. package/dist/protocols/mcp/defineTool.js.map +1 -0
  95. package/dist/protocols/mcp/security/HttpTargetGuard.d.ts +38 -0
  96. package/dist/protocols/mcp/security/HttpTargetGuard.d.ts.map +1 -0
  97. package/dist/protocols/mcp/security/HttpTargetGuard.js +227 -0
  98. package/dist/protocols/mcp/security/HttpTargetGuard.js.map +1 -0
  99. package/dist/protocols/mcp/security/McpSecurityGuard.d.ts +9 -1
  100. package/dist/protocols/mcp/security/McpSecurityGuard.d.ts.map +1 -1
  101. package/dist/protocols/mcp/security/McpSecurityGuard.js +10 -2
  102. package/dist/protocols/mcp/security/McpSecurityGuard.js.map +1 -1
  103. package/dist/protocols/mcp/security/McpToolPolicy.d.ts +81 -0
  104. package/dist/protocols/mcp/security/McpToolPolicy.d.ts.map +1 -0
  105. package/dist/protocols/mcp/security/McpToolPolicy.js +202 -0
  106. package/dist/protocols/mcp/security/McpToolPolicy.js.map +1 -0
  107. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts +51 -18
  108. package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts.map +1 -1
  109. package/dist/protocols/mcp/services/ExternalMcpServerManager.js +256 -283
  110. package/dist/protocols/mcp/services/ExternalMcpServerManager.js.map +1 -1
  111. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts +39 -6
  112. package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts.map +1 -1
  113. package/dist/protocols/mcp/services/ExternalServerConfigs.js +76 -18
  114. package/dist/protocols/mcp/services/ExternalServerConfigs.js.map +1 -1
  115. package/dist/protocols/mcp/tools/AnalyticsTools.js +1 -1
  116. package/dist/protocols/mcp/tools/AnalyticsTools.js.map +1 -1
  117. package/dist/protocols/mcp/tools/CodeAnalysisTools.d.ts.map +1 -1
  118. package/dist/protocols/mcp/tools/CodeAnalysisTools.js +15 -0
  119. package/dist/protocols/mcp/tools/CodeAnalysisTools.js.map +1 -1
  120. package/dist/protocols/mcp/tools/EffectivenessTools.js +3 -3
  121. package/dist/protocols/mcp/tools/EffectivenessTools.js.map +1 -1
  122. package/dist/protocols/mcp/tools/GitTools.d.ts +9 -369
  123. package/dist/protocols/mcp/tools/GitTools.d.ts.map +1 -1
  124. package/dist/protocols/mcp/tools/GitTools.js +222 -517
  125. package/dist/protocols/mcp/tools/GitTools.js.map +1 -1
  126. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts +56 -24
  127. package/dist/protocols/mcp/tools/InfrastructureTools.d.ts.map +1 -1
  128. package/dist/protocols/mcp/tools/InfrastructureTools.js +117 -26
  129. package/dist/protocols/mcp/tools/InfrastructureTools.js.map +1 -1
  130. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts +0 -3
  131. package/dist/protocols/mcp/tools/MemorySearchTools.d.ts.map +1 -1
  132. package/dist/protocols/mcp/tools/MemorySearchTools.js +58 -1
  133. package/dist/protocols/mcp/tools/MemorySearchTools.js.map +1 -1
  134. package/dist/protocols/mcp/tools/OrparTools.d.ts +8 -0
  135. package/dist/protocols/mcp/tools/OrparTools.d.ts.map +1 -1
  136. package/dist/protocols/mcp/tools/OrparTools.js +66 -0
  137. package/dist/protocols/mcp/tools/OrparTools.js.map +1 -1
  138. package/dist/protocols/mcp/tools/SafetyTools.d.ts +7 -525
  139. package/dist/protocols/mcp/tools/SafetyTools.d.ts.map +1 -1
  140. package/dist/protocols/mcp/tools/SafetyTools.js +349 -514
  141. package/dist/protocols/mcp/tools/SafetyTools.js.map +1 -1
  142. package/dist/protocols/mcp/tools/TaskPlanningTools.d.ts.map +1 -1
  143. package/dist/protocols/mcp/tools/TaskPlanningTools.js +56 -26
  144. package/dist/protocols/mcp/tools/TaskPlanningTools.js.map +1 -1
  145. package/dist/protocols/mcp/tools/TestTools.d.ts +15 -376
  146. package/dist/protocols/mcp/tools/TestTools.d.ts.map +1 -1
  147. package/dist/protocols/mcp/tools/TestTools.js +241 -363
  148. package/dist/protocols/mcp/tools/TestTools.js.map +1 -1
  149. package/dist/protocols/mcp/tools/TypeScriptTools.d.ts +6 -276
  150. package/dist/protocols/mcp/tools/TypeScriptTools.d.ts.map +1 -1
  151. package/dist/protocols/mcp/tools/TypeScriptTools.js +223 -337
  152. package/dist/protocols/mcp/tools/TypeScriptTools.js.map +1 -1
  153. package/dist/protocols/mcp/tools/WebTools.d.ts +15 -728
  154. package/dist/protocols/mcp/tools/WebTools.d.ts.map +1 -1
  155. package/dist/protocols/mcp/tools/WebTools.js +151 -257
  156. package/dist/protocols/mcp/tools/WebTools.js.map +1 -1
  157. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts +5 -3
  158. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts.map +1 -1
  159. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js +31 -6
  160. package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js.map +1 -1
  161. package/dist/schemas/EventPayloadSchema.d.ts +21 -0
  162. package/dist/schemas/EventPayloadSchema.d.ts.map +1 -1
  163. package/dist/schemas/EventPayloadSchema.js +14 -0
  164. package/dist/schemas/EventPayloadSchema.js.map +1 -1
  165. package/dist/services/BackgroundTaskManager.d.ts.map +1 -1
  166. package/dist/services/BackgroundTaskManager.js +12 -4
  167. package/dist/services/BackgroundTaskManager.js.map +1 -1
  168. package/dist/services/BrowserManager.d.ts +1 -1
  169. package/dist/services/BrowserManager.d.ts.map +1 -1
  170. package/dist/services/BrowserManager.js +26 -3
  171. package/dist/services/BrowserManager.js.map +1 -1
  172. package/dist/services/MemoryCompressor.d.ts +11 -2
  173. package/dist/services/MemoryCompressor.d.ts.map +1 -1
  174. package/dist/services/MemoryCompressor.js +8 -26
  175. package/dist/services/MemoryCompressor.js.map +1 -1
  176. package/dist/services/MemoryService.d.ts +16 -3
  177. package/dist/services/MemoryService.d.ts.map +1 -1
  178. package/dist/services/MemoryService.js +79 -55
  179. package/dist/services/MemoryService.js.map +1 -1
  180. package/dist/services/PredictiveAnalyticsService.d.ts +34 -4
  181. package/dist/services/PredictiveAnalyticsService.d.ts.map +1 -1
  182. package/dist/services/PredictiveAnalyticsService.js +41 -25
  183. package/dist/services/PredictiveAnalyticsService.js.map +1 -1
  184. package/dist/services/QValueManager.d.ts +7 -0
  185. package/dist/services/QValueManager.d.ts.map +1 -1
  186. package/dist/services/QValueManager.js +9 -0
  187. package/dist/services/QValueManager.js.map +1 -1
  188. package/dist/services/RewardSignalProcessor.d.ts +38 -1
  189. package/dist/services/RewardSignalProcessor.d.ts.map +1 -1
  190. package/dist/services/RewardSignalProcessor.js +109 -7
  191. package/dist/services/RewardSignalProcessor.js.map +1 -1
  192. package/dist/services/SharedStateService.d.ts +16 -2
  193. package/dist/services/SharedStateService.d.ts.map +1 -1
  194. package/dist/services/SharedStateService.js +44 -3
  195. package/dist/services/SharedStateService.js.map +1 -1
  196. package/dist/services/TaskEffectivenessService.d.ts +34 -18
  197. package/dist/services/TaskEffectivenessService.d.ts.map +1 -1
  198. package/dist/services/TaskEffectivenessService.js +91 -155
  199. package/dist/services/TaskEffectivenessService.js.map +1 -1
  200. package/dist/services/WebSearchService.d.ts.map +1 -1
  201. package/dist/services/WebSearchService.js.map +1 -1
  202. package/dist/services/dag/TaskDagService.d.ts.map +1 -1
  203. package/dist/services/dag/TaskDagService.js +2 -0
  204. package/dist/services/dag/TaskDagService.js.map +1 -1
  205. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts +7 -0
  206. package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts.map +1 -1
  207. package/dist/services/orpar-memory/OrparMemoryCoordinator.js +71 -10
  208. package/dist/services/orpar-memory/OrparMemoryCoordinator.js.map +1 -1
  209. package/dist/types/MemoryUtilityTypes.d.ts +2 -0
  210. package/dist/types/MemoryUtilityTypes.d.ts.map +1 -1
  211. package/dist/types/MemoryUtilityTypes.js.map +1 -1
  212. package/dist/utils/Logger.d.ts +43 -3
  213. package/dist/utils/Logger.d.ts.map +1 -1
  214. package/dist/utils/Logger.js +78 -36
  215. package/dist/utils/Logger.js.map +1 -1
  216. package/dist/utils/MxpEncryption.d.ts +19 -6
  217. package/dist/utils/MxpEncryption.d.ts.map +1 -1
  218. package/dist/utils/MxpEncryption.js +48 -16
  219. package/dist/utils/MxpEncryption.js.map +1 -1
  220. package/package.json +19 -4
  221. package/src/adapters/FrameworkAdapter.ts +1 -1
  222. package/src/config/ConfigManager.ts +52 -19
  223. package/src/config/memory-strata.config.ts +136 -0
  224. package/src/constants/ToolNames.ts +4 -18
  225. package/src/database/DatabaseAdapterFactory.ts +23 -6
  226. package/src/database/adapters/mongodb/MongoBaseRepository.ts +16 -2
  227. package/src/events/ClientEventBus.ts +68 -403
  228. package/src/events/EventBus.ts +7 -8
  229. package/src/events/EventBusBase.ts +479 -116
  230. package/src/events/EventNames.ts +6 -0
  231. package/src/events/PublicEvents.ts +7 -4
  232. package/src/events/ServerEventBus.ts +78 -473
  233. package/src/events/event-definitions/LlmBudgetEvents.ts +74 -0
  234. package/src/interfaces/IMemoryPersistence.ts +51 -0
  235. package/src/middleware/MxpMiddleware.ts +51 -24
  236. package/src/models/channelKey.ts +18 -4
  237. package/src/models/memoryUtility.ts +64 -0
  238. package/src/models/user.ts +36 -4
  239. package/src/mxp/BinaryProtocolLayer.ts +108 -124
  240. package/src/mxp/ContextCompressionEngine.ts +219 -161
  241. package/src/mxp/MxpTokenOptimizer.ts +10 -10
  242. package/src/prompts/MxfAgentSystemPrompt.ts +45 -55
  243. package/src/protocols/mcp/ToolError.ts +201 -0
  244. package/src/protocols/mcp/defineTool.ts +379 -0
  245. package/src/protocols/mcp/security/HttpTargetGuard.ts +267 -0
  246. package/src/protocols/mcp/security/McpSecurityGuard.ts +10 -3
  247. package/src/protocols/mcp/security/McpToolPolicy.ts +221 -0
  248. package/src/protocols/mcp/services/ExternalMcpServerManager.ts +340 -322
  249. package/src/protocols/mcp/services/ExternalServerConfigs.ts +82 -19
  250. package/src/protocols/mcp/tools/AnalyticsTools.ts +1 -1
  251. package/src/protocols/mcp/tools/CodeAnalysisTools.ts +15 -0
  252. package/src/protocols/mcp/tools/EffectivenessTools.ts +3 -3
  253. package/src/protocols/mcp/tools/GitTools.ts +290 -569
  254. package/src/protocols/mcp/tools/InfrastructureTools.ts +189 -43
  255. package/src/protocols/mcp/tools/MemorySearchTools.ts +77 -1
  256. package/src/protocols/mcp/tools/OrparTools.ts +87 -0
  257. package/src/protocols/mcp/tools/SafetyTools.ts +501 -579
  258. package/src/protocols/mcp/tools/TaskPlanningTools.ts +81 -39
  259. package/src/protocols/mcp/tools/TestTools.ts +339 -419
  260. package/src/protocols/mcp/tools/TypeScriptTools.ts +316 -376
  261. package/src/protocols/mcp/tools/WebTools.ts +209 -307
  262. package/src/protocols/mcp/tools/shell/ShellExecuteHandler.ts +53 -14
  263. package/src/schemas/EventPayloadSchema.ts +37 -0
  264. package/src/services/BackgroundTaskManager.ts +12 -4
  265. package/src/services/BrowserManager.ts +41 -1
  266. package/src/services/MemoryCompressor.ts +20 -32
  267. package/src/services/MemoryService.ts +96 -58
  268. package/src/services/PredictiveAnalyticsService.ts +55 -32
  269. package/src/services/QValueManager.ts +10 -0
  270. package/src/services/RewardSignalProcessor.ts +138 -9
  271. package/src/services/SharedStateService.ts +56 -8
  272. package/src/services/TaskEffectivenessService.ts +114 -187
  273. package/src/services/WebSearchService.ts +2 -1
  274. package/src/services/dag/TaskDagService.ts +2 -0
  275. package/src/services/orpar-memory/OrparMemoryCoordinator.ts +86 -10
  276. package/src/types/MemoryUtilityTypes.ts +2 -0
  277. package/src/utils/Logger.ts +116 -40
  278. package/src/utils/MxpEncryption.ts +69 -34
  279. package/dist/mxp/MxpEventForwardingEnhancer.d.ts +0 -134
  280. package/dist/mxp/MxpEventForwardingEnhancer.d.ts.map +0 -1
  281. package/dist/mxp/MxpEventForwardingEnhancer.js +0 -361
  282. package/dist/mxp/MxpEventForwardingEnhancer.js.map +0 -1
  283. package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts +0 -56
  284. package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts.map +0 -1
  285. package/dist/protocols/mcp/services/ToolSchemaEnhancements.js +0 -57
  286. package/dist/protocols/mcp/services/ToolSchemaEnhancements.js.map +0 -1
  287. package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts +0 -270
  288. package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts.map +0 -1
  289. package/dist/protocols/mcp/tools/ControlLoopLifecycle.js +0 -256
  290. package/dist/protocols/mcp/tools/ControlLoopLifecycle.js.map +0 -1
  291. package/dist/protocols/mcp/tools/LspTools.d.ts +0 -495
  292. package/dist/protocols/mcp/tools/LspTools.d.ts.map +0 -1
  293. package/dist/protocols/mcp/tools/LspTools.js +0 -469
  294. package/dist/protocols/mcp/tools/LspTools.js.map +0 -1
  295. package/src/mxp/MxpEventForwardingEnhancer.ts +0 -471
  296. package/src/protocols/mcp/services/ToolSchemaEnhancements.ts +0 -92
  297. package/src/protocols/mcp/tools/ControlLoopLifecycle.ts +0 -302
  298. package/src/protocols/mcp/tools/LspTools.ts +0 -476
@@ -55,8 +55,10 @@ export class TaskEffectivenessService {
55
55
  private readonly taskDefinitions = new Map<string, TaskDefinition>();
56
56
  private readonly taskEvents = new Map<string, TaskExecutionEvent[]>();
57
57
 
58
- // Historical data (in production, this would be in MongoDB)
59
- private readonly completedTasks = new Map<string, TaskEffectivenessMetrics>();
58
+ // Completed tasks live in MongoDB (TaskEffectivenessModel), not in memory.
59
+ // They were previously kept in a `completedTasks` Map, so all effectiveness
60
+ // history vanished on restart and any ranking built from it only ever saw
61
+ // the tasks this process happened to run.
60
62
 
61
63
  // Configuration
62
64
  private config: EffectivenessConfig = {
@@ -213,7 +215,9 @@ export class TaskEffectivenessService {
213
215
  updates: Partial<TaskEffectivenessMetrics['quality']>,
214
216
  agentId?: AgentId
215
217
  ): void {
216
- const metrics = this.activeTasks.get(taskId) || this.completedTasks.get(taskId);
218
+ // Quality is recorded while a task is running. A completed task's metrics
219
+ // are already persisted and are not amended here.
220
+ const metrics = this.activeTasks.get(taskId);
217
221
  if (metrics) {
218
222
  metrics.quality = { ...metrics.quality, ...updates };
219
223
 
@@ -261,12 +265,10 @@ export class TaskEffectivenessService {
261
265
  metrics.collaboration.collaborationScore = this.calculateCollaborationScore(metrics);
262
266
  }
263
267
 
264
- // Move to completed
265
- this.activeTasks.delete(taskId);
266
- this.completedTasks.set(taskId, metrics);
267
-
268
- // Persist to MongoDB
268
+ // Persist to MongoDB, then drop from the active set. Persist first: if
269
+ // it throws, the task stays active rather than disappearing entirely.
269
270
  await this.persistTaskToDB(taskId, metrics);
271
+ this.activeTasks.delete(taskId);
270
272
 
271
273
  // Emit completion event
272
274
  EventBus.server.emit(Events.Analytics.TASK_COMPLETED, createBaseEventPayload(
@@ -285,12 +287,25 @@ export class TaskEffectivenessService {
285
287
  }
286
288
 
287
289
  /**
288
- * Get comparison with baseline
290
+ * Compare a task against its baseline.
291
+ *
292
+ * Reads a running task from memory and a finished one from MongoDB, so this
293
+ * keeps working across a restart.
294
+ *
295
+ * @returns null when the task or its definition is unknown
289
296
  */
290
- public compareWithBaseline(taskId: string): EffectivenessComparison | null {
291
- const metrics = this.completedTasks.get(taskId) || this.activeTasks.get(taskId);
292
- const definition = this.taskDefinitions.get(taskId);
293
-
297
+ public async compareWithBaseline(taskId: string): Promise<EffectivenessComparison | null> {
298
+ let metrics = this.activeTasks.get(taskId);
299
+ let definition = this.taskDefinitions.get(taskId);
300
+
301
+ if (!metrics || !definition) {
302
+ const taskDoc = await TaskEffectivenessModel.findOne({ taskId }).exec();
303
+ if (taskDoc) {
304
+ metrics = metrics ?? (taskDoc.metrics as TaskEffectivenessMetrics);
305
+ definition = definition ?? (taskDoc.definition as TaskDefinition);
306
+ }
307
+ }
308
+
294
309
  if (!metrics || !definition) {
295
310
  return null;
296
311
  }
@@ -341,99 +356,82 @@ export class TaskEffectivenessService {
341
356
  }
342
357
 
343
358
  /**
344
- * Get analytics for a time period
359
+ * Effectiveness analytics for a time period, computed from persisted tasks.
360
+ *
361
+ * Reads from MongoDB, so results cover every task ever completed — not just
362
+ * the ones this process happened to run.
363
+ *
364
+ * @param startTime Start of the window (epoch ms)
365
+ * @param endTime End of the window (epoch ms)
366
+ * @param channelId Optional channel filter
367
+ * @param taskType Optional task-type filter
368
+ * @throws If the query fails. Effectiveness numbers computed from an empty
369
+ * result set would look like real "no activity" data.
345
370
  */
346
- public getAnalytics(
371
+ public async getAnalytics(
347
372
  startTime: number,
348
373
  endTime: number,
349
- channelId?: ChannelId
350
- ): EffectivenessAnalytics {
351
- const relevantTasks = Array.from(this.completedTasks.values()).filter(task => {
352
- const inTimeRange = task.metadata.startTime >= startTime &&
353
- task.metadata.startTime <= endTime;
354
- const inChannel = !channelId ||
355
- this.taskDefinitions.get(task.taskId)?.channelId === channelId;
356
- return inTimeRange && inChannel;
357
- });
358
-
359
- // Initialize analytics
360
- const analytics: EffectivenessAnalytics = {
361
- period: { start: startTime, end: endTime },
362
- byTaskType: {},
363
- byChannel: {},
364
- trends: {
365
- effectivenessOverTime: [],
366
- improving: [],
367
- declining: []
368
- },
369
- patterns: {
370
- highPerformanceTasks: [],
371
- lowPerformanceTasks: [],
372
- effectiveTeams: []
373
- }
374
+ channelId?: ChannelId,
375
+ taskType?: string
376
+ ): Promise<EffectivenessAnalytics> {
377
+ const tasks = await this.findCompletedTasks({ startTime, endTime, channelId, taskType });
378
+
379
+ return this.computeAnalyticsFromMetrics(tasks, startTime, endTime);
380
+ }
381
+
382
+ /**
383
+ * Query persisted task effectiveness records.
384
+ *
385
+ * @throws If the query fails
386
+ */
387
+ private async findCompletedTasks(filter: {
388
+ startTime: number;
389
+ endTime: number;
390
+ channelId?: ChannelId;
391
+ taskType?: string;
392
+ agentId?: AgentId;
393
+ }): Promise<TaskEffectivenessMetrics[]> {
394
+ const query: Record<string, unknown> = {
395
+ 'metrics.metadata.startTime': { $gte: filter.startTime, $lte: filter.endTime }
374
396
  };
375
-
376
- // Aggregate by task type
377
- for (const task of relevantTasks) {
378
- const type = task.metadata.type;
379
- if (!analytics.byTaskType[type]) {
380
- analytics.byTaskType[type] = {
381
- count: 0,
382
- avgCompletionTime: 0,
383
- successRate: 0,
384
- avgAutonomyScore: 0,
385
- commonTools: []
386
- };
387
- }
388
-
389
- const typeStats = analytics.byTaskType[type];
390
- typeStats.count++;
391
- typeStats.avgCompletionTime =
392
- (typeStats.avgCompletionTime * (typeStats.count - 1) +
393
- (task.performance.completionTime || 0)) / typeStats.count;
394
- typeStats.avgAutonomyScore =
395
- (typeStats.avgAutonomyScore * (typeStats.count - 1) +
396
- task.performance.autonomyScore) / typeStats.count;
397
-
398
- // Track tools
399
- for (const tool of task.performance.uniqueTools) {
400
- if (!typeStats.commonTools.includes(tool)) {
401
- typeStats.commonTools.push(tool);
402
- }
403
- }
397
+
398
+ if (filter.channelId) {
399
+ query.channelId = filter.channelId;
404
400
  }
405
-
406
- // Calculate success rates
407
- for (const [type, stats] of Object.entries(analytics.byTaskType)) {
408
- const typeTasks = relevantTasks.filter(t => t.metadata.type === type);
409
- const successful = typeTasks.filter(t => t.quality.goalAchieved).length;
410
- stats.successRate = typeTasks.length > 0 ? successful / typeTasks.length : 0;
401
+
402
+ if (filter.taskType) {
403
+ query['metrics.metadata.type'] = filter.taskType;
404
+ }
405
+
406
+ if (filter.agentId) {
407
+ query.agentIds = filter.agentId;
408
+ }
409
+
410
+ try {
411
+ const docs = await TaskEffectivenessModel.find(query).exec();
412
+ return docs.map(doc => doc.metrics as TaskEffectivenessMetrics);
413
+ } catch (error) {
414
+ const message = error instanceof Error ? error.message : String(error);
415
+ this.logger.error(`Failed to query task effectiveness data: ${message}`);
416
+ throw new Error(`Failed to query task effectiveness data: ${message}`);
411
417
  }
412
-
413
- // Identify patterns
414
- analytics.patterns.highPerformanceTasks = Object.entries(analytics.byTaskType)
415
- .filter(([_, stats]) => stats.successRate > 0.8 && stats.avgAutonomyScore > 0.7)
416
- .map(([type]) => type);
417
-
418
- analytics.patterns.lowPerformanceTasks = Object.entries(analytics.byTaskType)
419
- .filter(([_, stats]) => stats.successRate < 0.5 || stats.avgAutonomyScore < 0.3)
420
- .map(([type]) => type);
421
-
422
- return analytics;
423
418
  }
424
419
 
425
420
  /**
426
- * Persist task effectiveness data to MongoDB
421
+ * Persist task effectiveness data to MongoDB.
422
+ *
423
+ * @throws If the task has no definition, or the write fails. A completed task
424
+ * that is not written down is history that is simply gone; the caller
425
+ * needs to know.
427
426
  */
428
427
  private async persistTaskToDB(taskId: string, metrics: TaskEffectivenessMetrics): Promise<void> {
429
- try {
430
- const definition = this.taskDefinitions.get(taskId);
431
- if (!definition) {
432
- this.logger.warn(`No definition found for task ${taskId}, skipping DB persistence`);
433
- return;
434
- }
428
+ const definition = this.taskDefinitions.get(taskId);
429
+ if (!definition) {
430
+ throw new Error(`Cannot persist task ${taskId}: no task definition was registered for it`);
431
+ }
435
432
 
436
- const taskDoc = await TaskEffectivenessModel.findOneAndUpdate(
433
+ try {
434
+ await TaskEffectivenessModel.findOneAndUpdate(
437
435
  { taskId },
438
436
  {
439
437
  $set: {
@@ -445,67 +443,11 @@ export class TaskEffectivenessService {
445
443
  }
446
444
  },
447
445
  { upsert: true, new: true }
448
- );
449
-
446
+ ).exec();
450
447
  } catch (error) {
451
- this.logger.error(`Failed to persist task effectiveness data: ${error}`);
452
- }
453
- }
454
-
455
- /**
456
- * Load task effectiveness data from MongoDB
457
- */
458
- private async loadTaskFromDB(taskId: string): Promise<TaskEffectivenessMetrics | null> {
459
- try {
460
- const taskDoc = await TaskEffectivenessModel.findOne({ taskId });
461
- if (!taskDoc) {
462
- return null;
463
- }
464
-
465
- // Store in caches
466
- this.completedTasks.set(taskId, taskDoc.metrics);
467
- this.taskDefinitions.set(taskId, taskDoc.definition);
468
-
469
- return taskDoc.metrics;
470
- } catch (error) {
471
- this.logger.error(`Failed to load task effectiveness data: ${error}`);
472
- return null;
473
- }
474
- }
475
-
476
- /**
477
- * Enhanced analytics with MongoDB queries
478
- */
479
- public async getEnhancedAnalytics(
480
- startTime: number,
481
- endTime: number,
482
- channelId?: ChannelId,
483
- taskType?: string
484
- ): Promise<EffectivenessAnalytics> {
485
- try {
486
- const query: any = {
487
- 'metrics.metadata.startTime': { $gte: startTime, $lte: endTime }
488
- };
489
-
490
- if (channelId) {
491
- query.channelId = channelId;
492
- }
493
-
494
- if (taskType) {
495
- query['metrics.metadata.type'] = taskType;
496
- }
497
-
498
- const tasks = await TaskEffectivenessModel.find(query).exec();
499
-
500
- // Convert to in-memory format and use existing analytics logic
501
- const taskMetrics = tasks.map(task => task.metrics);
502
-
503
- // Use existing analytics logic but with MongoDB data
504
- return this.computeAnalyticsFromMetrics(taskMetrics, startTime, endTime);
505
- } catch (error) {
506
- this.logger.error(`Failed to get enhanced analytics: ${error}`);
507
- // Fallback to in-memory analytics
508
- return this.getAnalytics(startTime, endTime, channelId);
448
+ const message = error instanceof Error ? error.message : String(error);
449
+ this.logger.error(`Failed to persist task effectiveness data for ${taskId}: ${message}`);
450
+ throw new Error(`Failed to persist task effectiveness data for ${taskId}: ${message}`);
509
451
  }
510
452
  }
511
453
 
@@ -820,29 +762,20 @@ export class TaskEffectivenessService {
820
762
  * Get task metrics by ID
821
763
  */
822
764
  public async getTaskMetrics(taskId: string): Promise<TaskEffectivenessMetrics | null> {
823
- // Check active tasks first
765
+ // A running task lives in memory; a finished one lives in MongoDB.
824
766
  const activeTask = this.activeTasks.get(taskId);
825
767
  if (activeTask) {
826
768
  return activeTask;
827
769
  }
828
-
829
- // Check completed tasks
830
- const completedTask = this.completedTasks.get(taskId);
831
- if (completedTask) {
832
- return completedTask;
833
- }
834
-
835
- // Try to load from MongoDB
770
+
836
771
  try {
837
- const taskDoc = await TaskEffectivenessModel.findOne({ taskId });
838
- if (taskDoc) {
839
- return taskDoc.metrics as TaskEffectivenessMetrics;
840
- }
772
+ const taskDoc = await TaskEffectivenessModel.findOne({ taskId }).exec();
773
+ return taskDoc ? (taskDoc.metrics as TaskEffectivenessMetrics) : null;
841
774
  } catch (error) {
842
- this.logger.error(`Error loading task from DB: ${error}`);
775
+ const message = error instanceof Error ? error.message : String(error);
776
+ this.logger.error(`Failed to load task ${taskId}: ${message}`);
777
+ throw new Error(`Failed to load task ${taskId}: ${message}`);
843
778
  }
844
-
845
- return null;
846
779
  }
847
780
 
848
781
  /**
@@ -856,17 +789,18 @@ export class TaskEffectivenessService {
856
789
  ): Promise<any> {
857
790
  const dataPoints: any[] = [];
858
791
  const intervals = Math.floor((endTime - startTime) / intervalMs);
859
-
792
+
793
+ // One query for the whole window, then bucket in memory.
794
+ const tasks = await this.findCompletedTasks({ startTime, endTime, channelId });
795
+
860
796
  for (let i = 0; i < intervals; i++) {
861
797
  const intervalStart = startTime + (i * intervalMs);
862
798
  const intervalEnd = intervalStart + intervalMs;
863
-
864
- const intervalTasks = Array.from(this.completedTasks.values()).filter(task => {
865
- const taskChannel = this.taskDefinitions.get(task.taskId)?.channelId;
866
- return task.metadata.startTime >= intervalStart &&
867
- task.metadata.startTime < intervalEnd &&
868
- (!channelId || taskChannel === channelId);
869
- });
799
+
800
+ const intervalTasks = tasks.filter(task =>
801
+ task.metadata.startTime >= intervalStart &&
802
+ task.metadata.startTime < intervalEnd
803
+ );
870
804
 
871
805
  if (intervalTasks.length > 0) {
872
806
  const avgScore = intervalTasks.reduce((sum, task) =>
@@ -904,15 +838,8 @@ export class TaskEffectivenessService {
904
838
  endTime: number,
905
839
  channelId?: ChannelId
906
840
  ): Promise<any> {
907
- const agentTasks = Array.from(this.completedTasks.values()).filter(task => {
908
- const taskChannel = this.taskDefinitions.get(task.taskId)?.channelId;
909
- const hasAgent = task.collaboration.participatingAgents.includes(agentId);
910
-
911
- return hasAgent &&
912
- task.metadata.startTime >= startTime &&
913
- task.metadata.startTime <= endTime &&
914
- (!channelId || taskChannel === channelId);
915
- });
841
+ // The agentIds index on the document does the channel/time/agent filtering.
842
+ const agentTasks = await this.findCompletedTasks({ startTime, endTime, channelId, agentId });
916
843
 
917
844
  const totalTasks = agentTasks.length;
918
845
  const successfulTasks = agentTasks.filter(t => t.quality.goalAchieved).length;
@@ -25,7 +25,8 @@
25
25
 
26
26
  import { BrowserManager, BrowserConfig } from './BrowserManager.js';
27
27
  import { ContentProcessor, OptimizationOptions } from './ContentProcessor.js';
28
- import { Page } from 'puppeteer';
28
+ // Type-only: erased at compile time, so puppeteer stays an optional peer dependency.
29
+ import type { Page } from 'puppeteer';
29
30
 
30
31
  export interface WebSearchArgs {
31
32
  query: string;
@@ -163,6 +163,8 @@ export class TaskDagService {
163
163
  this.cleanupInterval = setInterval(() => {
164
164
  this.cleanupExpiredCaches();
165
165
  }, cleanupIntervalMs);
166
+ // Cache expiry sweep — must not keep the event loop alive on its own.
167
+ this.cleanupInterval.unref();
166
168
  }
167
169
 
168
170
  /**
@@ -211,6 +211,8 @@ export class OrparMemoryCoordinator {
211
211
  this.cleanupIntervalId = setInterval(() => {
212
212
  this.cleanupStaleCycles();
213
213
  }, OrparMemoryCoordinator.CLEANUP_INTERVAL_MS);
214
+ // Background sweep — must not keep the event loop alive on its own.
215
+ this.cleanupIntervalId.unref();
214
216
 
215
217
  this.logger.debug('[OrparMemoryCoordinator] Started stale cycle cleanup interval');
216
218
  }
@@ -323,6 +325,20 @@ export class OrparMemoryCoordinator {
323
325
  this.onOrparToolEvent('reflection', payload);
324
326
  });
325
327
 
328
+ // Fill phase memory usage from actual retrievals.
329
+ //
330
+ // PhaseStrataRouter already emits every phase retrieval with the memory ids it
331
+ // returned, but nothing consumed it: the only way to populate phaseUsage was the
332
+ // public recordMemoryUsage(), which no production code ever called. phaseUsage was
333
+ // therefore always empty, so PhaseWeightedRewarder returned no rewards and cycle
334
+ // consolidation iterated zero memories. Subscribing here is what makes
335
+ // phase-weighted rewards real.
336
+ EventBus.server.on(OrparMemoryEvents.PHASE_MEMORY_RETRIEVED, (payload: any) => {
337
+ if (this.enabled) {
338
+ this.onPhaseMemoryRetrieved(payload);
339
+ }
340
+ });
341
+
326
342
  // Listen for task completion to retroactively update rewards when
327
343
  // the ORPAR cycle completed before task_complete was called
328
344
  EventBus.server.on(Events.Task.COMPLETED, (payload: any) => {
@@ -331,7 +347,7 @@ export class OrparMemoryCoordinator {
331
347
  }
332
348
  });
333
349
 
334
- this.logger.debug('[OrparMemoryCoordinator] Event listeners registered for ControlLoop, OrparTools, and TaskEvents');
350
+ this.logger.debug('[OrparMemoryCoordinator] Event listeners registered for ControlLoop, OrparTools, PhaseMemory, and TaskEvents');
335
351
  }
336
352
 
337
353
  /**
@@ -341,11 +357,23 @@ export class OrparMemoryCoordinator {
341
357
  private onPhaseEvent(phase: OrparPhase, payload: any, source: string = 'controlLoop'): void {
342
358
  if (!this.enabled) return;
343
359
 
344
- const { agentId, channelId } = payload.data || payload;
345
- if (!agentId) return;
360
+ // agentId/channelId are top-level fields on BaseEventPayload, and loopId lives in
361
+ // `data` (ControlLoopSpecificData). This previously read both from the wrong
362
+ // level — `payload.data || payload` resolved to `data`, which carries no agentId —
363
+ // so every control-loop phase event hit the guard below and returned, and no
364
+ // server-side ORPAR cycle ever accumulated a phase.
365
+ const agentId = payload.agentId;
366
+ const channelId = payload.channelId;
367
+ if (!agentId) {
368
+ this.logger.warn(
369
+ `[OrparMemoryCoordinator] Ignoring ${phase} event from ${source}: payload has no agentId`
370
+ );
371
+ return;
372
+ }
346
373
 
347
- // Get or create cycle state
348
- const cycleId = payload.loopId || `${agentId}-${Date.now()}`;
374
+ // Fall back to a stable per-agent key rather than a timestamp: a timestamped key
375
+ // would start a fresh cycle on every event and no cycle would ever accumulate.
376
+ const cycleId = payload.data?.loopId || `${agentId}:${channelId ?? 'default'}`;
349
377
 
350
378
  // Fix #2: Acquire lock before modifying cycle state
351
379
  if (!this.acquireCycleLock(cycleId)) {
@@ -510,14 +538,28 @@ export class OrparMemoryCoordinator {
510
538
  const cycleState = this.activeCycles.get(cycleKey);
511
539
  if (!cycleState || cycleState.isComplete) return;
512
540
 
513
- // Build outcome from reflection data
541
+ // Build the outcome from what we actually observed.
542
+ //
543
+ // This previously hardcoded qualityScore (0.8/0.4), errorCount (0), toolCallCount
544
+ // (5) and taskCompleted (true) and fed them into the reward calculation as though
545
+ // they were measurements. Rewards derived from invented numbers are worse than no
546
+ // rewards, so every field below is either observed or omitted.
514
547
  const reflectionData = reflectionPayload.data || {};
548
+
549
+ // Phases actually entered during this cycle — a real count, not an assumption
550
+ // that every cycle runs all five.
551
+ const phasesObserved = Object.keys(cycleState.phaseStartTimes).length;
552
+
515
553
  const outcome: CycleOutcome = {
516
554
  success: reflectionData.expectationsMet !== false,
517
- qualityScore: reflectionData.expectationsMet !== false ? 0.8 : 0.4,
518
- errorCount: 0,
519
- toolCallCount: 5, // ORPAR tools count as one call per phase
520
- taskCompleted: true,
555
+ // Only report a quality score if reflection actually produced one.
556
+ ...(typeof reflectionData.qualityScore === 'number'
557
+ ? { qualityScore: reflectionData.qualityScore }
558
+ : {}),
559
+ errorCount: Array.isArray(reflectionData.errors) ? reflectionData.errors.length : 0,
560
+ toolCallCount: phasesObserved,
561
+ // Only true when reflection says so — the coordinator cannot see task state.
562
+ taskCompleted: reflectionData.taskCompleted === true,
521
563
  metadata: {
522
564
  source: 'orparTools',
523
565
  learnings: reflectionData.learnings,
@@ -735,6 +777,40 @@ export class OrparMemoryCoordinator {
735
777
  /**
736
778
  * Record memory usage in a cycle
737
779
  */
780
+ /**
781
+ * Record a phase retrieval reported by PhaseStrataRouter.
782
+ *
783
+ * Resolves the agent's active cycle and records every returned memory against the
784
+ * phase it was retrieved in, so the cycle carries real usage by the time it completes.
785
+ */
786
+ private onPhaseMemoryRetrieved(payload: any): void {
787
+ const agentId = payload.agentId;
788
+ const channelId = payload.channelId;
789
+ const phase: OrparPhase | undefined = payload.data?.phase;
790
+ const memoryIds: string[] = payload.data?.memoryIds ?? [];
791
+
792
+ if (!agentId || !phase || memoryIds.length === 0) {
793
+ return;
794
+ }
795
+
796
+ // Match the cycle key used by onPhaseEvent so retrievals land on the live cycle.
797
+ const cycleId = payload.data?.loopId || `${agentId}:${channelId ?? 'default'}`;
798
+ if (!this.activeCycles.has(cycleId)) {
799
+ this.logger.debug(
800
+ `[OrparMemoryCoordinator] Phase retrieval for ${cycleId} has no active cycle; ignoring`
801
+ );
802
+ return;
803
+ }
804
+
805
+ for (const memoryId of memoryIds) {
806
+ this.recordMemoryUsage(cycleId, phase, memoryId, 'context');
807
+ }
808
+
809
+ this.logger.debug(
810
+ `[OrparMemoryCoordinator] Recorded ${memoryIds.length} memories for cycle ${cycleId} (phase=${phase})`
811
+ );
812
+ }
813
+
738
814
  public recordMemoryUsage(
739
815
  cycleId: string,
740
816
  phase: OrparPhase,
@@ -448,6 +448,8 @@ export interface UtilityRetrievalOptions {
448
448
  maxResults?: number;
449
449
  /** Similarity threshold */
450
450
  similarityThreshold?: number;
451
+ /** Hybrid search balance passed to Meilisearch (0 = keyword, 1 = semantic) */
452
+ hybridRatio?: number;
451
453
  /** Include score breakdown */
452
454
  includeBreakdown?: boolean;
453
455
  }