@monoes/monomindcli 2.16.12 → 2.16.14

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 (386) hide show
  1. package/.claude/agents/core/coder.md +1 -1
  2. package/.claude/agents/engineering/engineering-devops-automator.md +1 -1
  3. package/.claude/agents/github/repo-architect.md +1 -1
  4. package/.claude/agents/testing/production-validator.md +1 -1
  5. package/.claude/agents/testing/testing-tool-evaluator.md +1 -1
  6. package/.claude/commands/github/pr-manager.md +1 -1
  7. package/.claude/helpers/pick-rank.cjs +34 -4
  8. package/.claude/skills/monolean-audit/SKILL.md +1 -1
  9. package/README.md +1 -1
  10. package/dist/src/commands/cleanup-data.d.ts +30 -0
  11. package/dist/src/commands/cleanup-data.d.ts.map +1 -0
  12. package/dist/src/commands/cleanup-data.js +138 -0
  13. package/dist/src/commands/cleanup-data.js.map +1 -0
  14. package/dist/src/commands/cleanup-scratch.d.ts +43 -0
  15. package/dist/src/commands/cleanup-scratch.d.ts.map +1 -0
  16. package/dist/src/commands/cleanup-scratch.js +125 -0
  17. package/dist/src/commands/cleanup-scratch.js.map +1 -0
  18. package/dist/src/commands/cleanup.d.ts +2 -39
  19. package/dist/src/commands/cleanup.d.ts.map +1 -1
  20. package/dist/src/commands/cleanup.js +5 -247
  21. package/dist/src/commands/cleanup.js.map +1 -1
  22. package/dist/src/commands/doctor-gitignore-checks.d.ts +10 -0
  23. package/dist/src/commands/doctor-gitignore-checks.d.ts.map +1 -0
  24. package/dist/src/commands/doctor-gitignore-checks.js +141 -0
  25. package/dist/src/commands/doctor-gitignore-checks.js.map +1 -0
  26. package/dist/src/commands/doctor-helpers-checks.d.ts +10 -0
  27. package/dist/src/commands/doctor-helpers-checks.d.ts.map +1 -0
  28. package/dist/src/commands/doctor-helpers-checks.js +292 -0
  29. package/dist/src/commands/doctor-helpers-checks.js.map +1 -0
  30. package/dist/src/commands/doctor-memory-checks.d.ts +47 -0
  31. package/dist/src/commands/doctor-memory-checks.d.ts.map +1 -0
  32. package/dist/src/commands/doctor-memory-checks.js +298 -0
  33. package/dist/src/commands/doctor-memory-checks.js.map +1 -0
  34. package/dist/src/commands/doctor-monograph-checks.d.ts +9 -0
  35. package/dist/src/commands/doctor-monograph-checks.d.ts.map +1 -0
  36. package/dist/src/commands/doctor-monograph-checks.js +331 -0
  37. package/dist/src/commands/doctor-monograph-checks.js.map +1 -0
  38. package/dist/src/commands/doctor-project-checks.d.ts +7 -66
  39. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  40. package/dist/src/commands/doctor-project-checks.js +10 -1331
  41. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  42. package/dist/src/commands/doctor-routing-checks.d.ts +10 -0
  43. package/dist/src/commands/doctor-routing-checks.d.ts.map +1 -0
  44. package/dist/src/commands/doctor-routing-checks.js +194 -0
  45. package/dist/src/commands/doctor-routing-checks.js.map +1 -0
  46. package/dist/src/commands/doctor-worker-checks.d.ts +17 -0
  47. package/dist/src/commands/doctor-worker-checks.d.ts.map +1 -0
  48. package/dist/src/commands/doctor-worker-checks.js +122 -0
  49. package/dist/src/commands/doctor-worker-checks.js.map +1 -0
  50. package/dist/src/commands/hooks-routing-commands.js +1 -1
  51. package/dist/src/commands/hooks-routing-commands.js.map +1 -1
  52. package/dist/src/commands/init.d.ts.map +1 -1
  53. package/dist/src/commands/init.js +6 -15
  54. package/dist/src/commands/init.js.map +1 -1
  55. package/dist/src/commands/org-control.d.ts +117 -0
  56. package/dist/src/commands/org-control.d.ts.map +1 -0
  57. package/dist/src/commands/org-control.js +274 -0
  58. package/dist/src/commands/org-control.js.map +1 -0
  59. package/dist/src/commands/org-lifecycle.d.ts +7 -0
  60. package/dist/src/commands/org-lifecycle.d.ts.map +1 -0
  61. package/dist/src/commands/org-lifecycle.js +298 -0
  62. package/dist/src/commands/org-lifecycle.js.map +1 -0
  63. package/dist/src/commands/org-manage.d.ts +7 -0
  64. package/dist/src/commands/org-manage.d.ts.map +1 -0
  65. package/dist/src/commands/org-manage.js +357 -0
  66. package/dist/src/commands/org-manage.js.map +1 -0
  67. package/dist/src/commands/org-memory-command.d.ts +3 -0
  68. package/dist/src/commands/org-memory-command.d.ts.map +1 -0
  69. package/dist/src/commands/org-memory-command.js +178 -0
  70. package/dist/src/commands/org-memory-command.js.map +1 -0
  71. package/dist/src/commands/org-observe-approvals.d.ts +8 -0
  72. package/dist/src/commands/org-observe-approvals.d.ts.map +1 -0
  73. package/dist/src/commands/org-observe-approvals.js +211 -0
  74. package/dist/src/commands/org-observe-approvals.js.map +1 -0
  75. package/dist/src/commands/org-observe-checkpoint.d.ts +26 -0
  76. package/dist/src/commands/org-observe-checkpoint.d.ts.map +1 -0
  77. package/dist/src/commands/org-observe-checkpoint.js +180 -0
  78. package/dist/src/commands/org-observe-checkpoint.js.map +1 -0
  79. package/dist/src/commands/org-observe-config.d.ts +8 -0
  80. package/dist/src/commands/org-observe-config.d.ts.map +1 -0
  81. package/dist/src/commands/org-observe-config.js +160 -0
  82. package/dist/src/commands/org-observe-config.js.map +1 -0
  83. package/dist/src/commands/org-observe-gates.d.ts +4 -0
  84. package/dist/src/commands/org-observe-gates.d.ts.map +1 -0
  85. package/dist/src/commands/org-observe-gates.js +182 -0
  86. package/dist/src/commands/org-observe-gates.js.map +1 -0
  87. package/dist/src/commands/org-observe-inbox.d.ts +18 -0
  88. package/dist/src/commands/org-observe-inbox.d.ts.map +1 -0
  89. package/dist/src/commands/org-observe-inbox.js +154 -0
  90. package/dist/src/commands/org-observe-inbox.js.map +1 -0
  91. package/dist/src/commands/org-observe-logs.d.ts +31 -0
  92. package/dist/src/commands/org-observe-logs.d.ts.map +1 -0
  93. package/dist/src/commands/org-observe-logs.js +272 -0
  94. package/dist/src/commands/org-observe-logs.js.map +1 -0
  95. package/dist/src/commands/org-observe-questions.d.ts +8 -0
  96. package/dist/src/commands/org-observe-questions.d.ts.map +1 -0
  97. package/dist/src/commands/org-observe-questions.js +201 -0
  98. package/dist/src/commands/org-observe-questions.js.map +1 -0
  99. package/dist/src/commands/org-observe-report.d.ts +8 -0
  100. package/dist/src/commands/org-observe-report.d.ts.map +1 -0
  101. package/dist/src/commands/org-observe-report.js +366 -0
  102. package/dist/src/commands/org-observe-report.js.map +1 -0
  103. package/dist/src/commands/org-observe-shared.d.ts +20 -0
  104. package/dist/src/commands/org-observe-shared.d.ts.map +1 -0
  105. package/dist/src/commands/org-observe-shared.js +55 -0
  106. package/dist/src/commands/org-observe-shared.js.map +1 -0
  107. package/dist/src/commands/org-observe.d.ts +9 -101
  108. package/dist/src/commands/org-observe.d.ts.map +1 -1
  109. package/dist/src/commands/org-observe.js +12 -1675
  110. package/dist/src/commands/org-observe.js.map +1 -1
  111. package/dist/src/commands/org-poll.d.ts +57 -0
  112. package/dist/src/commands/org-poll.d.ts.map +1 -0
  113. package/dist/src/commands/org-poll.js +194 -0
  114. package/dist/src/commands/org-poll.js.map +1 -0
  115. package/dist/src/commands/org-run.d.ts +3 -0
  116. package/dist/src/commands/org-run.d.ts.map +1 -0
  117. package/dist/src/commands/org-run.js +449 -0
  118. package/dist/src/commands/org-run.js.map +1 -0
  119. package/dist/src/commands/org-serve.d.ts +19 -0
  120. package/dist/src/commands/org-serve.d.ts.map +1 -0
  121. package/dist/src/commands/org-serve.js +395 -0
  122. package/dist/src/commands/org-serve.js.map +1 -0
  123. package/dist/src/commands/org-subcommands-config.d.ts +8 -0
  124. package/dist/src/commands/org-subcommands-config.d.ts.map +1 -0
  125. package/dist/src/commands/org-subcommands-config.js +93 -0
  126. package/dist/src/commands/org-subcommands-config.js.map +1 -0
  127. package/dist/src/commands/org-subcommands-hil.d.ts +11 -0
  128. package/dist/src/commands/org-subcommands-hil.d.ts.map +1 -0
  129. package/dist/src/commands/org-subcommands-hil.js +216 -0
  130. package/dist/src/commands/org-subcommands-hil.js.map +1 -0
  131. package/dist/src/commands/org-subcommands-observe.d.ts +12 -0
  132. package/dist/src/commands/org-subcommands-observe.d.ts.map +1 -0
  133. package/dist/src/commands/org-subcommands-observe.js +249 -0
  134. package/dist/src/commands/org-subcommands-observe.js.map +1 -0
  135. package/dist/src/commands/org-subcommands-runtime.d.ts +12 -0
  136. package/dist/src/commands/org-subcommands-runtime.d.ts.map +1 -0
  137. package/dist/src/commands/org-subcommands-runtime.js +163 -0
  138. package/dist/src/commands/org-subcommands-runtime.js.map +1 -0
  139. package/dist/src/commands/org.d.ts +3 -151
  140. package/dist/src/commands/org.d.ts.map +1 -1
  141. package/dist/src/commands/org.js +43 -2735
  142. package/dist/src/commands/org.js.map +1 -1
  143. package/dist/src/index.js +2 -2
  144. package/dist/src/index.js.map +1 -1
  145. package/dist/src/init/never-commit.d.ts +3 -3
  146. package/dist/src/init/types.d.ts +1 -1
  147. package/dist/src/init/types.js +1 -1
  148. package/dist/src/knowledge/document-store.js +1 -1
  149. package/dist/src/knowledge/document-store.js.map +1 -1
  150. package/dist/src/mcp-tools/hooks-edit-command.d.ts +10 -0
  151. package/dist/src/mcp-tools/hooks-edit-command.d.ts.map +1 -0
  152. package/dist/src/mcp-tools/hooks-edit-command.js +247 -0
  153. package/dist/src/mcp-tools/hooks-edit-command.js.map +1 -0
  154. package/dist/src/mcp-tools/hooks-learning.d.ts +9 -0
  155. package/dist/src/mcp-tools/hooks-learning.d.ts.map +1 -0
  156. package/dist/src/mcp-tools/hooks-learning.js +408 -0
  157. package/dist/src/mcp-tools/hooks-learning.js.map +1 -0
  158. package/dist/src/mcp-tools/hooks-metrics-list.d.ts +8 -0
  159. package/dist/src/mcp-tools/hooks-metrics-list.d.ts.map +1 -0
  160. package/dist/src/mcp-tools/hooks-metrics-list.js +205 -0
  161. package/dist/src/mcp-tools/hooks-metrics-list.js.map +1 -0
  162. package/dist/src/mcp-tools/hooks-route.d.ts +12 -0
  163. package/dist/src/mcp-tools/hooks-route.d.ts.map +1 -0
  164. package/dist/src/mcp-tools/hooks-route.js +251 -0
  165. package/dist/src/mcp-tools/hooks-route.js.map +1 -0
  166. package/dist/src/mcp-tools/hooks-routing.d.ts +6 -27
  167. package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
  168. package/dist/src/mcp-tools/hooks-routing.js +6 -1727
  169. package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
  170. package/dist/src/mcp-tools/hooks-session.d.ts +9 -0
  171. package/dist/src/mcp-tools/hooks-session.d.ts.map +1 -0
  172. package/dist/src/mcp-tools/hooks-session.js +243 -0
  173. package/dist/src/mcp-tools/hooks-session.js.map +1 -0
  174. package/dist/src/mcp-tools/hooks-task.d.ts +17 -0
  175. package/dist/src/mcp-tools/hooks-task.d.ts.map +1 -0
  176. package/dist/src/mcp-tools/hooks-task.js +427 -0
  177. package/dist/src/mcp-tools/hooks-task.js.map +1 -0
  178. package/dist/src/mcp-tools/hooks-tools.d.ts +2 -1
  179. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  180. package/dist/src/mcp-tools/hooks-tools.js +2 -1
  181. package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
  182. package/dist/src/mcp-tools/memory-tools.js +1 -1
  183. package/dist/src/mcp-tools/memory-tools.js.map +1 -1
  184. package/dist/src/memory/bm25-index.d.ts +2 -2
  185. package/dist/src/memory/bm25-index.js +2 -2
  186. package/dist/src/memory/embedding-operations.js +2 -2
  187. package/dist/src/memory/embedding-operations.js.map +1 -1
  188. package/dist/src/memory/entity-name-key.d.ts +1 -1
  189. package/dist/src/memory/entity-name-key.js +1 -1
  190. package/dist/src/memory/hnsw-operations.d.ts +1 -1
  191. package/dist/src/memory/hnsw-operations.js +1 -1
  192. package/dist/src/memory/memory-bridge-backend.d.ts +43 -0
  193. package/dist/src/memory/memory-bridge-backend.d.ts.map +1 -0
  194. package/dist/src/memory/memory-bridge-backend.js +363 -0
  195. package/dist/src/memory/memory-bridge-backend.js.map +1 -0
  196. package/dist/src/memory/memory-bridge-core.d.ts +42 -0
  197. package/dist/src/memory/memory-bridge-core.d.ts.map +1 -0
  198. package/dist/src/memory/memory-bridge-core.js +126 -0
  199. package/dist/src/memory/memory-bridge-core.js.map +1 -0
  200. package/dist/src/memory/memory-bridge-entries.d.ts +131 -0
  201. package/dist/src/memory/memory-bridge-entries.d.ts.map +1 -0
  202. package/dist/src/memory/memory-bridge-entries.js +227 -0
  203. package/dist/src/memory/memory-bridge-entries.js.map +1 -0
  204. package/dist/src/memory/memory-bridge-feedback.d.ts +60 -0
  205. package/dist/src/memory/memory-bridge-feedback.d.ts.map +1 -0
  206. package/dist/src/memory/memory-bridge-feedback.js +118 -0
  207. package/dist/src/memory/memory-bridge-feedback.js.map +1 -0
  208. package/dist/src/memory/memory-bridge-paths.d.ts +123 -0
  209. package/dist/src/memory/memory-bridge-paths.d.ts.map +1 -0
  210. package/dist/src/memory/memory-bridge-paths.js +335 -0
  211. package/dist/src/memory/memory-bridge-paths.js.map +1 -0
  212. package/dist/src/memory/memory-bridge-search.d.ts +48 -0
  213. package/dist/src/memory/memory-bridge-search.d.ts.map +1 -0
  214. package/dist/src/memory/memory-bridge-search.js +383 -0
  215. package/dist/src/memory/memory-bridge-search.js.map +1 -0
  216. package/dist/src/memory/memory-bridge-sessions.d.ts +38 -0
  217. package/dist/src/memory/memory-bridge-sessions.d.ts.map +1 -0
  218. package/dist/src/memory/memory-bridge-sessions.js +109 -0
  219. package/dist/src/memory/memory-bridge-sessions.js.map +1 -0
  220. package/dist/src/memory/memory-bridge-store.d.ts +58 -0
  221. package/dist/src/memory/memory-bridge-store.d.ts.map +1 -0
  222. package/dist/src/memory/memory-bridge-store.js +201 -0
  223. package/dist/src/memory/memory-bridge-store.js.map +1 -0
  224. package/dist/src/memory/memory-bridge.d.ts +10 -438
  225. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  226. package/dist/src/memory/memory-bridge.js +14 -1787
  227. package/dist/src/memory/memory-bridge.js.map +1 -1
  228. package/dist/src/memory/memory-kg-claims.d.ts +52 -0
  229. package/dist/src/memory/memory-kg-claims.d.ts.map +1 -0
  230. package/dist/src/memory/memory-kg-claims.js +99 -0
  231. package/dist/src/memory/memory-kg-claims.js.map +1 -0
  232. package/dist/src/memory/memory-kg-index.d.ts +86 -0
  233. package/dist/src/memory/memory-kg-index.d.ts.map +1 -0
  234. package/dist/src/memory/memory-kg-index.js +256 -0
  235. package/dist/src/memory/memory-kg-index.js.map +1 -0
  236. package/dist/src/memory/memory-kg-ingest.d.ts +44 -0
  237. package/dist/src/memory/memory-kg-ingest.d.ts.map +1 -0
  238. package/dist/src/memory/memory-kg-ingest.js +361 -0
  239. package/dist/src/memory/memory-kg-ingest.js.map +1 -0
  240. package/dist/src/memory/memory-kg-model.d.ts +168 -0
  241. package/dist/src/memory/memory-kg-model.d.ts.map +1 -0
  242. package/dist/src/memory/memory-kg-model.js +158 -0
  243. package/dist/src/memory/memory-kg-model.js.map +1 -0
  244. package/dist/src/memory/memory-kg-names.d.ts +64 -0
  245. package/dist/src/memory/memory-kg-names.d.ts.map +1 -0
  246. package/dist/src/memory/memory-kg-names.js +187 -0
  247. package/dist/src/memory/memory-kg-names.js.map +1 -0
  248. package/dist/src/memory/memory-kg-promote.d.ts +79 -0
  249. package/dist/src/memory/memory-kg-promote.d.ts.map +1 -0
  250. package/dist/src/memory/memory-kg-promote.js +248 -0
  251. package/dist/src/memory/memory-kg-promote.js.map +1 -0
  252. package/dist/src/memory/memory-kg-rebuild.d.ts +77 -0
  253. package/dist/src/memory/memory-kg-rebuild.d.ts.map +1 -0
  254. package/dist/src/memory/memory-kg-rebuild.js +299 -0
  255. package/dist/src/memory/memory-kg-rebuild.js.map +1 -0
  256. package/dist/src/memory/memory-kg-rollback.d.ts +47 -0
  257. package/dist/src/memory/memory-kg-rollback.d.ts.map +1 -0
  258. package/dist/src/memory/memory-kg-rollback.js +193 -0
  259. package/dist/src/memory/memory-kg-rollback.js.map +1 -0
  260. package/dist/src/memory/memory-kg-rules.d.ts +64 -0
  261. package/dist/src/memory/memory-kg-rules.d.ts.map +1 -0
  262. package/dist/src/memory/memory-kg-rules.js +251 -0
  263. package/dist/src/memory/memory-kg-rules.js.map +1 -0
  264. package/dist/src/memory/memory-kg-scan.d.ts +118 -0
  265. package/dist/src/memory/memory-kg-scan.d.ts.map +1 -0
  266. package/dist/src/memory/memory-kg-scan.js +209 -0
  267. package/dist/src/memory/memory-kg-scan.js.map +1 -0
  268. package/dist/src/memory/memory-kg-search.d.ts +80 -0
  269. package/dist/src/memory/memory-kg-search.d.ts.map +1 -0
  270. package/dist/src/memory/memory-kg-search.js +239 -0
  271. package/dist/src/memory/memory-kg-search.js.map +1 -0
  272. package/dist/src/memory/memory-kg.d.ts +19 -547
  273. package/dist/src/memory/memory-kg.d.ts.map +1 -1
  274. package/dist/src/memory/memory-kg.js +10 -2389
  275. package/dist/src/memory/memory-kg.js.map +1 -1
  276. package/dist/src/orgrt/daemon-types.d.ts +196 -0
  277. package/dist/src/orgrt/daemon-types.d.ts.map +1 -0
  278. package/dist/src/orgrt/daemon-types.js +38 -0
  279. package/dist/src/orgrt/daemon-types.js.map +1 -0
  280. package/dist/src/orgrt/daemon.d.ts +70 -300
  281. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  282. package/dist/src/orgrt/daemon.js +41 -2536
  283. package/dist/src/orgrt/daemon.js.map +1 -1
  284. package/dist/src/orgrt/idle-watchdog.d.ts +39 -0
  285. package/dist/src/orgrt/idle-watchdog.d.ts.map +1 -0
  286. package/dist/src/orgrt/idle-watchdog.js +289 -0
  287. package/dist/src/orgrt/idle-watchdog.js.map +1 -0
  288. package/dist/src/orgrt/org-reload.d.ts +7 -0
  289. package/dist/src/orgrt/org-reload.d.ts.map +1 -0
  290. package/dist/src/orgrt/org-reload.js +111 -0
  291. package/dist/src/orgrt/org-reload.js.map +1 -0
  292. package/dist/src/orgrt/org-start-steps.d.ts +21 -0
  293. package/dist/src/orgrt/org-start-steps.d.ts.map +1 -0
  294. package/dist/src/orgrt/org-start-steps.js +305 -0
  295. package/dist/src/orgrt/org-start-steps.js.map +1 -0
  296. package/dist/src/orgrt/org-start.d.ts +7 -0
  297. package/dist/src/orgrt/org-start.d.ts.map +1 -0
  298. package/dist/src/orgrt/org-start.js +435 -0
  299. package/dist/src/orgrt/org-start.js.map +1 -0
  300. package/dist/src/orgrt/org-state-file.d.ts +8 -0
  301. package/dist/src/orgrt/org-state-file.d.ts.map +1 -0
  302. package/dist/src/orgrt/org-state-file.js +116 -0
  303. package/dist/src/orgrt/org-state-file.js.map +1 -0
  304. package/dist/src/orgrt/org-stop.d.ts +6 -0
  305. package/dist/src/orgrt/org-stop.d.ts.map +1 -0
  306. package/dist/src/orgrt/org-stop.js +332 -0
  307. package/dist/src/orgrt/org-stop.js.map +1 -0
  308. package/dist/src/orgrt/org-tools.d.ts +11 -0
  309. package/dist/src/orgrt/org-tools.d.ts.map +1 -0
  310. package/dist/src/orgrt/org-tools.js +305 -0
  311. package/dist/src/orgrt/org-tools.js.map +1 -0
  312. package/dist/src/orgrt/role-incarnation.d.ts +18 -0
  313. package/dist/src/orgrt/role-incarnation.d.ts.map +1 -0
  314. package/dist/src/orgrt/role-incarnation.js +374 -0
  315. package/dist/src/orgrt/role-incarnation.js.map +1 -0
  316. package/dist/src/orgrt/role-respawn.d.ts +7 -0
  317. package/dist/src/orgrt/role-respawn.d.ts.map +1 -0
  318. package/dist/src/orgrt/role-respawn.js +318 -0
  319. package/dist/src/orgrt/role-respawn.js.map +1 -0
  320. package/dist/src/orgrt/role-session-opts.d.ts +389 -0
  321. package/dist/src/orgrt/role-session-opts.d.ts.map +1 -0
  322. package/dist/src/orgrt/role-session-opts.js +289 -0
  323. package/dist/src/orgrt/role-session-opts.js.map +1 -0
  324. package/dist/src/orgrt/runner-resolve.d.ts +43 -0
  325. package/dist/src/orgrt/runner-resolve.d.ts.map +1 -0
  326. package/dist/src/orgrt/runner-resolve.js +77 -0
  327. package/dist/src/orgrt/runner-resolve.js.map +1 -0
  328. package/dist/src/orgrt/session-gate.d.ts +34 -0
  329. package/dist/src/orgrt/session-gate.d.ts.map +1 -0
  330. package/dist/src/orgrt/session-gate.js +74 -0
  331. package/dist/src/orgrt/session-gate.js.map +1 -0
  332. package/dist/src/orgrt/session-prompt.d.ts +31 -0
  333. package/dist/src/orgrt/session-prompt.d.ts.map +1 -0
  334. package/dist/src/orgrt/session-prompt.js +115 -0
  335. package/dist/src/orgrt/session-prompt.js.map +1 -0
  336. package/dist/src/orgrt/session-run.d.ts +18 -0
  337. package/dist/src/orgrt/session-run.d.ts.map +1 -0
  338. package/dist/src/orgrt/session-run.js +429 -0
  339. package/dist/src/orgrt/session-run.js.map +1 -0
  340. package/dist/src/orgrt/session-stream.d.ts +21 -0
  341. package/dist/src/orgrt/session-stream.d.ts.map +1 -0
  342. package/dist/src/orgrt/session-stream.js +173 -0
  343. package/dist/src/orgrt/session-stream.js.map +1 -0
  344. package/dist/src/orgrt/session-types.d.ts +219 -0
  345. package/dist/src/orgrt/session-types.d.ts.map +1 -0
  346. package/dist/src/orgrt/session-types.js +2 -0
  347. package/dist/src/orgrt/session-types.js.map +1 -0
  348. package/dist/src/orgrt/session-usage.d.ts +29 -0
  349. package/dist/src/orgrt/session-usage.d.ts.map +1 -0
  350. package/dist/src/orgrt/session-usage.js +64 -0
  351. package/dist/src/orgrt/session-usage.js.map +1 -0
  352. package/dist/src/orgrt/session.d.ts +5 -281
  353. package/dist/src/orgrt/session.d.ts.map +1 -1
  354. package/dist/src/orgrt/session.js +8 -1117
  355. package/dist/src/orgrt/session.js.map +1 -1
  356. package/dist/src/ui/org-hil.mjs +1 -1
  357. package/dist/src/ui/routes-org-agents.mjs +318 -0
  358. package/dist/src/ui/routes-org-approvals.mjs +133 -0
  359. package/dist/src/ui/routes-org-config.mjs +459 -0
  360. package/dist/src/ui/routes-org-control.mjs +300 -0
  361. package/dist/src/ui/routes-org-files.mjs +172 -0
  362. package/dist/src/ui/routes-org-helpers.mjs +84 -0
  363. package/dist/src/ui/routes-org-knowledge.mjs +262 -0
  364. package/dist/src/ui/routes-org-lifecycle.mjs +224 -0
  365. package/dist/src/ui/routes-org-live.mjs +278 -0
  366. package/dist/src/ui/routes-org-mastermind.mjs +346 -0
  367. package/dist/src/ui/routes-org-planning.mjs +398 -0
  368. package/dist/src/ui/routes-org-runs.mjs +430 -0
  369. package/dist/src/ui/routes-org-status.mjs +342 -0
  370. package/dist/src/ui/routes-org-workflows.mjs +212 -0
  371. package/dist/src/ui/routes-org.mjs +26 -3847
  372. package/dist/src/ui/server.mjs +1 -1
  373. package/dist/src/utils/native-error.d.ts +1 -1
  374. package/dist/src/utils/native-error.js +1 -1
  375. package/dist/src/utils/paths.d.ts +2 -1
  376. package/dist/src/utils/paths.d.ts.map +1 -1
  377. package/dist/src/utils/paths.js +2 -1
  378. package/dist/src/utils/paths.js.map +1 -1
  379. package/dist/tsconfig.tsbuildinfo +1 -1
  380. package/org-skills/adversarial-reviewer/SKILL.md +1 -1
  381. package/org-skills/board-deck-builder/SKILL.md +1 -1
  382. package/org-skills/code-reviewer/SKILL.md +1 -1
  383. package/org-skills/debugging-wizard/SKILL.md +1 -1
  384. package/org-skills/scientific-thinking-literature-review/SKILL.md +1 -1
  385. package/org-skills/scientific-thinking-scholar-evaluation/SKILL.md +1 -1
  386. package/package.json +5 -5
@@ -4,1731 +4,10 @@
4
4
  * transfer, session, list, metrics, pre-task, post-task, intelligence.
5
5
  * Extracted from hooks-tools.ts.
6
6
  */
7
- import { randomUUID } from 'node:crypto';
8
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
9
- import { join, resolve, sep } from 'node:path';
10
- import { DEFAULT_EMBEDDING_DIMS, DEFAULT_EMBEDDING_MODEL } from '../init/types.js';
11
- import { deriveRecentSuccess, recordCommand } from '../monovector/command-outcomes.js';
12
- import { joinLatestUnresolved, joinOutcome, recordRoute } from '../monovector/route-outcomes.js';
13
- import { pickAgents } from '../routing/agent-pick.js';
14
- import { validateMcpString } from '../utils/input-guards.js';
15
- import { mergeRecordsById } from '../utils/json-file.js';
16
- import { activeTrajectories, assessCommandRisk, extractKeywords, getFileExtension, getIntelligenceStatsFromMemory, getMemoryPath, getRealSearchFunction, getRealStoreFunction, getRouteOutcomesBaseDir, getRoutingOutcomesPath, getSONAOptimizer, loadMemoryStore, loadRoutingOutcomes, MEMORY_DIR, saveRoutingOutcomes, suggestAgentsForFile, } from './hooks-embedding.js';
17
- import { getProjectCwd } from './types.js';
18
- // MCP Tool implementations - return raw data for direct CLI use
19
- export const hooksPreEdit = {
20
- name: 'hooks_pre-edit',
21
- description: 'Get context and agent suggestions before editing a file',
22
- inputSchema: {
23
- type: 'object',
24
- properties: {
25
- filePath: { type: 'string', description: 'Path to the file being edited' },
26
- operation: {
27
- type: 'string',
28
- description: 'Type of operation (create, update, delete, refactor)',
29
- },
30
- context: { type: 'string', description: 'Additional context' },
31
- },
32
- required: ['filePath'],
33
- },
34
- handler: async (params) => {
35
- // Cap filePath: passed to suggestAgentsForFile (O(n) regex) and reflected in
36
- // response. Cap operation to prevent oversized strings in recommendations.
37
- const MAX_PRE_EDIT_PATH_LEN = 4 * 1024;
38
- const MAX_PRE_EDIT_OP_LEN = 64;
39
- const filePath = validateMcpString(params.filePath, 'filePath', MAX_PRE_EDIT_PATH_LEN);
40
- if (!filePath) {
41
- return { error: 'filePath is required (non-empty string, no control chars, max 4KB)' };
42
- }
43
- const operation = validateMcpString(params.operation, 'operation', MAX_PRE_EDIT_OP_LEN) ?? 'update';
44
- const suggestedAgents = suggestAgentsForFile(filePath);
45
- const ext = getFileExtension(filePath);
46
- return {
47
- filePath,
48
- operation,
49
- context: {
50
- fileExists: existsSync(resolve(getProjectCwd(), filePath)),
51
- fileType: ext || 'unknown',
52
- suggestedAgents,
53
- risks: operation === 'delete' ? ['File deletion is irreversible'] : [],
54
- },
55
- recommendations: [
56
- `Recommended agents: ${suggestedAgents.join(', ')}`,
57
- 'Run tests after changes',
58
- ],
59
- };
60
- },
61
- };
62
- export const hooksPostEdit = {
63
- name: 'hooks_post-edit',
64
- description: 'Record editing outcome for learning',
65
- inputSchema: {
66
- type: 'object',
67
- properties: {
68
- filePath: { type: 'string', description: 'Path to the edited file' },
69
- success: { type: 'boolean', description: 'Whether the edit was successful' },
70
- agent: { type: 'string', description: 'Agent that performed the edit' },
71
- },
72
- required: ['filePath'],
73
- },
74
- handler: async (params) => {
75
- // Cap filePath: interpolated into taskId and task text forwarded to
76
- // bridgeRecordFeedback (which calls generateEmbedding — O(n) hash fallback).
77
- // Cap agent: stored in feedback record and forwarded to bridge.
78
- const MAX_POST_EDIT_PATH_LEN = 4 * 1024;
79
- const MAX_POST_EDIT_AGENT_LEN = 256;
80
- const filePath = validateMcpString(params.filePath, 'filePath', MAX_POST_EDIT_PATH_LEN);
81
- if (!filePath) {
82
- return { error: 'filePath is required (non-empty string, no control chars, max 4KB)' };
83
- }
84
- const success = params.success !== false;
85
- const agent = validateMcpString(params.agent, 'agent', MAX_POST_EDIT_AGENT_LEN) ?? undefined;
86
- // Wire recordFeedback through bridge (issue #1209)
87
- let feedbackResult = null;
88
- try {
89
- const bridge = await import('../memory/memory-bridge.js');
90
- feedbackResult = await bridge.bridgeRecordFeedback({
91
- taskType: agent ?? 'coder',
92
- action: `edit ${filePath}`,
93
- outcome: success ? 'success' : 'failure',
94
- confidence: success ? 0.85 : 0.3,
95
- });
96
- }
97
- catch (e) {
98
- // Bridge not available — continue with basic response
99
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
100
- console.error('[hooks-post-edit] memory bridge feedback failed:', e);
101
- }
102
- return {
103
- // The feedback record is the only write this hook makes.
104
- recorded: feedbackResult?.success === true,
105
- filePath,
106
- success,
107
- timestamp: new Date().toISOString(),
108
- feedback: feedbackResult
109
- ? {
110
- recorded: feedbackResult.success,
111
- controller: feedbackResult.success ? 'sqlite' : 'unavailable',
112
- updates: feedbackResult.success ? 1 : 0,
113
- }
114
- : { recorded: false, controller: 'unavailable', updates: 0 },
115
- };
116
- },
117
- };
118
- export const hooksPreCommand = {
119
- name: 'hooks_pre-command',
120
- description: 'Assess risk before executing a command',
121
- inputSchema: {
122
- type: 'object',
123
- properties: {
124
- command: { type: 'string', description: 'Command to execute' },
125
- },
126
- required: ['command'],
127
- },
128
- handler: async (params) => {
129
- // Cap command length: assessCommandRisk runs O(n) string searches, and the
130
- // raw command is reflected verbatim in the response. Limit to 4 KB which
131
- // is far beyond any realistic shell command.
132
- const MAX_CMD_LEN = 4 * 1024;
133
- const command = validateMcpString(params.command, 'command', MAX_CMD_LEN);
134
- if (!command) {
135
- return { error: 'command is required (non-empty string, no control chars, max 4KB)' };
136
- }
137
- const assessment = assessCommandRisk(command);
138
- const riskLevel = assessment.level >= 0.8
139
- ? 'critical'
140
- : assessment.level >= 0.6
141
- ? 'high'
142
- : assessment.level >= 0.3
143
- ? 'medium'
144
- : 'low';
145
- return {
146
- command,
147
- riskLevel,
148
- risks: assessment.warnings.map((warning, i) => ({
149
- type: `risk-${i + 1}`,
150
- severity: assessment.level >= 0.6 ? 'high' : 'medium',
151
- description: warning,
152
- })),
153
- recommendations: assessment.warnings.length > 0
154
- ? ['Review warnings before proceeding', 'Consider using safer alternative']
155
- : ['Command appears safe to execute'],
156
- safeAlternatives: [],
157
- shouldProceed: assessment.level < 0.7,
158
- };
159
- },
160
- };
161
- export const hooksPostCommand = {
162
- name: 'hooks_post-command',
163
- description: 'Record command execution outcome',
164
- inputSchema: {
165
- type: 'object',
166
- properties: {
167
- command: { type: 'string', description: 'Executed command' },
168
- exitCode: { type: 'number', description: 'Command exit code' },
169
- success: {
170
- type: 'boolean',
171
- description: 'Whether the command succeeded. false records a failure even with exit code 0; a non-zero exit code is always a failure.',
172
- },
173
- },
174
- required: ['command'],
175
- },
176
- handler: async (params) => {
177
- // Cap command: it is stored in JSON memory store (line 824), forwarded to
178
- // bridgeStoreEntry which calls generateEmbedding by default — O(n) hash
179
- // fallback, and reflected verbatim in the response. The recordCommand path
180
- // already caps to 200 chars; apply a consistent 4 KB cap here that still
181
- // covers any realistic shell command.
182
- const MAX_POST_CMD_LEN = 4 * 1024;
183
- const command = validateMcpString(params.command, 'command', MAX_POST_CMD_LEN);
184
- if (!command) {
185
- return { error: 'command is required (non-empty string, no control chars, max 4KB)' };
186
- }
187
- const exitCode = typeof params.exitCode === 'number' && Number.isFinite(params.exitCode)
188
- ? Math.floor(params.exitCode)
189
- : 0;
190
- // An explicit success: false wins over a 0 exit code (e.g. a command that
191
- // exited 0 but printed errors); a non-zero exit code is always a failure.
192
- const success = exitCode === 0 && params.success !== false;
193
- // Record the real exit code in the time-windowed command-outcome store so
194
- // post-task can derive a MEASURED success signal (grounded in actual exit
195
- // codes) when the caller does not explicitly assert --success. Non-fatal.
196
- await recordCommand(getRouteOutcomesBaseDir(), {
197
- ts: Date.now(),
198
- command: typeof command === 'string' ? command.slice(0, 200) : String(command).slice(0, 200),
199
- exitCode,
200
- success,
201
- });
202
- // Persist command outcome via memory backend
203
- let _storedIn = 'none';
204
- try {
205
- const bridge = await import('../memory/memory-bridge.js');
206
- const stored = await bridge.bridgeStoreEntry({
207
- key: `cmd-${Date.now()}`,
208
- value: JSON.stringify({ command, exitCode, success }),
209
- namespace: 'commands',
210
- tags: [success ? 'success' : 'error'],
211
- });
212
- // #293: bridgeStoreEntry RETURNS null when the backend cannot be loaded,
213
- // it does not throw. Claiming `_storedIn = 'sqlite'` on that return
214
- // reported `recorded: true` for a write that never happened AND skipped
215
- // the JSON fallback below, so the record was lost twice over.
216
- if (!stored?.success)
217
- throw new Error(stored?.error ?? 'memory backend unavailable');
218
- _storedIn = 'sqlite';
219
- }
220
- catch {
221
- // memory backend unavailable or refused the write — store in JSON
222
- try {
223
- const store = loadMemoryStore();
224
- const key = `cmd-${Date.now()}`;
225
- store.entries[key] = {
226
- key,
227
- value: JSON.stringify({ command, exitCode, success }),
228
- namespace: 'commands',
229
- createdAt: new Date().toISOString(),
230
- };
231
- const memDir = join(getProjectCwd(), MEMORY_DIR);
232
- if (!existsSync(memDir))
233
- mkdirSync(memDir, { recursive: true });
234
- const _mp = getMemoryPath();
235
- const _mptmp = `${_mp}.tmp`;
236
- writeFileSync(_mptmp, JSON.stringify(store, null, 2), 'utf-8');
237
- renameSync(_mptmp, _mp);
238
- _storedIn = 'json-store';
239
- }
240
- catch {
241
- /* non-critical */
242
- }
243
- }
244
- return {
245
- recorded: _storedIn !== 'none',
246
- command,
247
- exitCode,
248
- success,
249
- timestamp: new Date().toISOString(),
250
- _storedIn,
251
- };
252
- },
253
- };
254
- /** Rough effort band from task wording — shared by hooks_route and hooks_pre-task. */
255
- function taskComplexity(task) {
256
- const lower = task.toLowerCase();
257
- if (lower.includes('complex') || lower.includes('architecture') || task.length > 200) {
258
- return 'high';
259
- }
260
- if (lower.includes('simple') || lower.includes('fix') || task.length < 50)
261
- return 'low';
262
- return 'medium';
263
- }
264
- function estimatedDuration(complexity) {
265
- return complexity === 'high' ? '2-4 hours' : complexity === 'medium' ? '30-60 min' : '10-30 min';
266
- }
267
- export const hooksRoute = {
268
- name: 'hooks_route',
269
- description: 'Route a task to the best agent — a thin wrapper over the central picker (same ranking as ' +
270
- 'the `pick` tool and `monomind pick`). primaryAgent.type is a spawnable Task subagent_type.',
271
- inputSchema: {
272
- type: 'object',
273
- properties: {
274
- task: { type: 'string', description: 'Task description' },
275
- context: { type: 'string', description: 'Additional context' },
276
- topK: { type: 'number', description: 'Number of agents to return, 1-20 (default: 3)' },
277
- },
278
- required: ['task'],
279
- },
280
- handler: async (params) => {
281
- // Cap task and context lengths: task is ranked and stored in
282
- // route-outcomes.jsonl. 16 KB matches the cap in hooksPatternSearch.
283
- const MAX_ROUTE_TASK_LEN = 16 * 1024;
284
- const MAX_ROUTE_CTX_LEN = 4 * 1024;
285
- const task = validateMcpString(params.task, 'task', MAX_ROUTE_TASK_LEN);
286
- if (!task) {
287
- return { error: 'task is required (non-empty string, no control chars, max 16KB)' };
288
- }
289
- const _context = validateMcpString(params.context, 'context', MAX_ROUTE_CTX_LEN) ?? undefined;
290
- const topK = Math.max(1, Math.min(20, Math.trunc(Number(params.topK)) || 3));
291
- const started = Date.now();
292
- const pick = await pickAgents(task, topK);
293
- const routingLatencyMs = Date.now() - started;
294
- const [primary, ...alternatives] = pick.agents;
295
- const agents = pick.agents.map((a) => a.type);
296
- const routingMethod = pick.method;
297
- const complexity = taskComplexity(task);
298
- // Record the route recommendation so post-task can join the actual outcome
299
- const routeId = randomUUID();
300
- await recordRoute(getRouteOutcomesBaseDir(), {
301
- routeId,
302
- ts: Date.now(),
303
- task,
304
- recommendedAgent: primary.type,
305
- routingMethod,
306
- confidence: primary.confidence,
307
- learningMode: 'js',
308
- });
309
- return {
310
- routeId,
311
- task,
312
- routing: {
313
- method: routingMethod,
314
- backend: pick.provider ? `jev: ${pick.provider}` : 'monomind pick',
315
- latencyMs: routingLatencyMs,
316
- throughput: routingLatencyMs > 0 ? `${Math.round(1000 / routingLatencyMs)} routes/s` : 'N/A',
317
- },
318
- matchedPattern: routingMethod,
319
- semanticMatches: [],
320
- primaryAgent: primary,
321
- alternativeAgents: alternatives,
322
- estimatedMetrics: {
323
- successProbability: primary.confidence,
324
- estimatedDuration: estimatedDuration(complexity),
325
- complexity,
326
- },
327
- swarmRecommendation: agents.length > 2
328
- ? {
329
- topology: 'hierarchical',
330
- agents,
331
- coordination: 'queen-led',
332
- }
333
- : null,
334
- };
335
- },
336
- };
337
- export const hooksRouteSemantic = {
338
- name: 'hooks_route_semantic',
339
- description: 'Route a task through the central picker first (the decision model, then the @monoes/routing ' +
340
- 'keyword patterns, then a clearly leading keyword pick), and only when none decides through ' +
341
- 'real-embedding cosine-similarity matching (isolated worker) with a headless Claude (Haiku) ' +
342
- 'fallback below the confidence threshold. Slower than hooks_route — use for ambiguous or ' +
343
- 'highly specialized tasks (e.g. Solidity, embedded, DevOps) where keyword matching is likely ' +
344
- 'to under-specify the agent. agentSlug is a spawnable Task subagent_type.',
345
- inputSchema: {
346
- type: 'object',
347
- properties: {
348
- task: { type: 'string', description: 'Task description' },
349
- debug: {
350
- type: 'boolean',
351
- description: 'Include all route scores in the response (default: false)',
352
- },
353
- },
354
- required: ['task'],
355
- },
356
- handler: async (params) => {
357
- const MAX_ROUTE_TASK_LEN = 2000; // matches route-layer-factory's MAX_TASK_LENGTH
358
- const task = validateMcpString(params.task, 'task', MAX_ROUTE_TASK_LEN);
359
- const debug = params.debug === true;
360
- if (!task) {
361
- throw new Error('task is required (non-empty string, no control chars, max 2000 chars)');
362
- }
363
- const { createConfiguredRouteLayer } = await import('../routing/route-layer-factory.js');
364
- const layer = await createConfiguredRouteLayer({ debug });
365
- const result = await layer.route(task);
366
- const routeId = randomUUID();
367
- await recordRoute(getRouteOutcomesBaseDir(), {
368
- routeId,
369
- ts: Date.now(),
370
- task,
371
- recommendedAgent: result.agentSlug,
372
- routingMethod: `routing-pkg:${result.method}`,
373
- confidence: result.confidence,
374
- learningMode: 'js',
375
- }).catch(() => {
376
- /* non-fatal — outcome joining is best-effort */
377
- });
378
- return { routeId, task, ...result };
379
- },
380
- };
381
- export const hooksMetrics = {
382
- name: 'hooks_metrics',
383
- description: 'View learning metrics dashboard',
384
- inputSchema: {
385
- type: 'object',
386
- properties: {
387
- period: { type: 'string', description: 'Metrics period (1h, 24h, 7d, 30d)' },
388
- includeV1: { type: 'boolean', description: 'Include v1 performance metrics' },
389
- },
390
- },
391
- handler: async (params) => {
392
- const period = validateMcpString(params.period, 'period', 32) ?? '24h';
393
- // Try to read real counts from memory store
394
- const store = loadMemoryStore();
395
- const entries = Object.values(store.entries);
396
- // Count patterns by looking at stored pattern entries
397
- const patternEntries = entries.filter((e) => e.key.includes('pattern'));
398
- const routingEntries = entries.filter((e) => e.key.includes('route') || e.key.includes('routing'));
399
- const taskEntries = entries.filter((e) => e.key.includes('task'));
400
- if (entries.length === 0) {
401
- return {
402
- _real: true,
403
- _note: 'No metrics data collected yet. Data populates from hooks_post-task, hooks_post-edit, hooks_post-command, and hooks_route calls.',
404
- period,
405
- patterns: { total: 0, successful: 0, failed: 0, avgConfidence: null },
406
- agents: { routingAccuracy: null, totalRoutes: 0, topAgent: null },
407
- commands: { totalExecuted: 0, successRate: null, avgRiskScore: null },
408
- lastUpdated: new Date().toISOString(),
409
- };
410
- }
411
- return {
412
- period,
413
- patterns: {
414
- total: patternEntries.length,
415
- _note: 'Success/failure breakdown not tracked yet — store outcomes via hooks_post-task to populate.',
416
- },
417
- agents: {
418
- totalRoutes: routingEntries.length,
419
- _note: 'Routing accuracy not tracked yet — requires route-outcome correlation data.',
420
- },
421
- commands: {
422
- totalExecuted: taskEntries.length,
423
- _note: 'Success rate not tracked yet — requires command-outcomes.jsonl data.',
424
- },
425
- dataSource: 'memory-store',
426
- entriesFound: entries.length,
427
- lastUpdated: new Date().toISOString(),
428
- };
429
- },
430
- };
431
- /**
432
- * The only per-hook execution data monomind actually persists: invocation
433
- * counters written by `.claude/helpers/hook-handler.cjs` into
434
- * `.monomind/metrics/hook-latency.json` as `{ count, total, max, mean }`.
435
- *
436
- * It is keyed by *handler* name (`pre-bash`, `pre-write`, `agent-start`, …) —
437
- * the wiring `readClaudeCodeHookWiring` reports, not the subcommand registry
438
- * `hooks_list` returns. The two name spaces overlap on 6 of 24 entries and
439
- * diverge elsewhere (registry `pre-command` vs. handler `pre-bash`, registry
440
- * `pre-edit` vs. handler `pre-write`), so joining them would be a guess. These
441
- * counts are therefore reported alongside the wiring they measure.
442
- *
443
- * There is no per-hook timestamp and no per-hook priority anywhere on disk:
444
- * the file carries one file-global `lastUpdated`, and `HookPriority` lives
445
- * only in @monoes/hooks' in-memory registry, which this process never fills.
446
- */
447
- function readHookHandlerInvocations() {
448
- const metricsPath = join(getProjectCwd(), '.monomind', 'metrics', 'hook-latency.json');
449
- const handlers = [];
450
- let raw;
451
- try {
452
- raw = JSON.parse(readFileSync(metricsPath, 'utf8'));
453
- }
454
- catch {
455
- return { metricsPath, recorded: false, handlers };
456
- }
457
- if (typeof raw !== 'object' || raw === null)
458
- return { metricsPath, recorded: false, handlers };
459
- for (const [name, value] of Object.entries(raw)) {
460
- // `lastUpdated` is a file-global epoch, not a handler.
461
- if (name === 'lastUpdated' || typeof value !== 'object' || value === null)
462
- continue;
463
- const entry = value;
464
- // Report only what the writer actually recorded — never a defaulted zero.
465
- if (typeof entry.count !== 'number')
466
- continue;
467
- handlers.push({
468
- name,
469
- count: entry.count,
470
- meanMs: typeof entry.mean === 'number' ? entry.mean : 0,
471
- maxMs: typeof entry.max === 'number' ? entry.max : 0,
472
- });
473
- }
474
- handlers.sort((a, b) => b.count - a.count);
475
- return { metricsPath, recorded: handlers.length > 0, handlers };
476
- }
477
- /**
478
- * Claude Code event wiring, as written into `.claude/settings.json` by
479
- * `monomind init hooks`. This is a *different* subsystem from the hook
480
- * subcommand registry below — it is keyed by Claude Code event and handler
481
- * script, not by these subcommand names — so `hooks list` reports it
482
- * separately instead of folding it into the registry's own state (#270).
483
- */
484
- function readClaudeCodeHookWiring() {
485
- const settingsPath = join(getProjectCwd(), '.claude', 'settings.json');
486
- const invocations = readHookHandlerInvocations();
487
- const empty = { configured: false, settingsPath, wired: 0, events: [], invocations };
488
- let hooks;
489
- try {
490
- const parsed = JSON.parse(readFileSync(settingsPath, 'utf8'));
491
- hooks = (parsed?.hooks ?? {});
492
- }
493
- catch {
494
- return empty;
495
- }
496
- const events = [];
497
- let wired = 0;
498
- for (const [event, matchers] of Object.entries(hooks)) {
499
- let eventWired = 0;
500
- for (const matcher of Array.isArray(matchers) ? matchers : []) {
501
- for (const entry of Array.isArray(matcher?.hooks) ? matcher.hooks : []) {
502
- // Only ours: every command monomind generates runs a script out of
503
- // .claude/helpers. Third-party hooks in the same file are not ours
504
- // to report on.
505
- if (typeof entry?.command === 'string' && entry.command.includes('.claude/helpers/')) {
506
- eventWired++;
507
- }
508
- }
509
- }
510
- if (eventWired > 0) {
511
- events.push(event);
512
- wired += eventWired;
513
- }
514
- }
515
- return { configured: wired > 0, settingsPath, wired, events, invocations };
516
- }
517
- export const hooksList = {
518
- name: 'hooks_list',
519
- description: 'List all registered hooks',
520
- inputSchema: {
521
- type: 'object',
522
- properties: {},
523
- },
524
- handler: async () => {
525
- // Static registry — not live discovery from handler objects.
526
- // Update this list when hooks are added or removed.
527
- const hooks = [
528
- // Core hooks
529
- { name: 'pre-edit', type: 'PreToolUse', status: 'active' },
530
- { name: 'post-edit', type: 'PostToolUse', status: 'active' },
531
- { name: 'pre-command', type: 'PreToolUse', status: 'active' },
532
- { name: 'post-command', type: 'PostToolUse', status: 'active' },
533
- { name: 'pre-task', type: 'PreToolUse', status: 'active' },
534
- { name: 'post-task', type: 'PostToolUse', status: 'active' },
535
- // Routing hooks
536
- { name: 'route', type: 'intelligence', status: 'active' },
537
- { name: 'explain', type: 'intelligence', status: 'active' },
538
- // Session hooks
539
- { name: 'session-start', type: 'SessionStart', status: 'active' },
540
- { name: 'session-end', type: 'SessionEnd', status: 'active' },
541
- { name: 'session-restore', type: 'SessionStart', status: 'active' },
542
- // Learning hooks
543
- { name: 'pretrain', type: 'intelligence', status: 'active' },
544
- { name: 'transfer', type: 'intelligence', status: 'active' },
545
- { name: 'metrics', type: 'analytics', status: 'active' },
546
- // System hooks
547
- { name: 'init', type: 'system', status: 'active' },
548
- { name: 'notify', type: 'coordination', status: 'active' },
549
- // Intelligence subcommands
550
- { name: 'intelligence', type: 'intelligence', status: 'active' },
551
- { name: 'intelligence_trajectory-start', type: 'intelligence', status: 'active' },
552
- { name: 'intelligence_trajectory-step', type: 'intelligence', status: 'active' },
553
- { name: 'intelligence_trajectory-end', type: 'intelligence', status: 'active' },
554
- { name: 'intelligence_pattern-store', type: 'intelligence', status: 'active' },
555
- { name: 'intelligence_pattern-search', type: 'intelligence', status: 'active' },
556
- { name: 'intelligence_stats', type: 'analytics', status: 'active' },
557
- { name: 'intelligence_learn', type: 'intelligence', status: 'active' },
558
- ];
559
- return {
560
- _note: 'Two independent things. `hooks` is a static registry of monomind CLI ' +
561
- 'hook subcommands (update it when hooks are added or removed); each is ' +
562
- 'enabled when its status is active. `claudeCode` is the Claude Code ' +
563
- 'event wiring in .claude/settings.json that `monomind init hooks` ' +
564
- 'writes — keyed by event and handler script, not by these names. A hook ' +
565
- 'can be registered here without that wiring being present. Registry ' +
566
- 'entries carry no priority, execution count or last-executed timestamp: ' +
567
- 'nothing persists those. The only recorded execution data is ' +
568
- '`claudeCode.invocations` — per-handler counters from ' +
569
- '.monomind/metrics/hook-latency.json, in the wiring name space, not this one.',
570
- hooks: hooks.map((hook) => ({ ...hook, enabled: hook.status === 'active' })),
571
- total: hooks.length,
572
- claudeCode: readClaudeCodeHookWiring(),
573
- };
574
- },
575
- };
576
- export const hooksPreTask = {
577
- name: 'hooks_pre-task',
578
- description: 'Record task start and get agent suggestions with intelligent model routing (ADR-026)',
579
- inputSchema: {
580
- type: 'object',
581
- properties: {
582
- taskId: { type: 'string', description: 'Task identifier' },
583
- description: { type: 'string', description: 'Task description' },
584
- filePath: { type: 'string', description: 'Optional file path for AST analysis' },
585
- },
586
- required: ['taskId', 'description'],
587
- },
588
- handler: async (params) => {
589
- // Cap taskId: it is used as a suffix in SQLite memory keys (heuristic:${taskId},
590
- // routing-decision:${taskId}, textual_gradient:${taskId}) and as sourceId/targetId
591
- // in causal-graph edges persisted to SQLite. An uncapped ID can inflate the DB key
592
- // column and every JSON payload that includes the ID.
593
- const MAX_TASK_ID_LEN = 256;
594
- const taskId = validateMcpString(params.taskId, 'taskId', MAX_TASK_ID_LEN);
595
- if (!taskId) {
596
- return { error: 'taskId is required (non-empty string, no control chars, max 256 chars)' };
597
- }
598
- // Cap description: it is forwarded to generateEmbedding twice (ERL heuristics
599
- // + TextGrad gradient queries) and used in O(n) keyword extraction.
600
- // 16 KB matches the cap applied in hooks_route and hooksPatternSearch.
601
- const MAX_PRE_TASK_DESC_LEN = 16 * 1024;
602
- const description = validateMcpString(params.description, 'description', MAX_PRE_TASK_DESC_LEN);
603
- if (!description) {
604
- return { error: 'description is required (non-empty string, no control chars, max 16KB)' };
605
- }
606
- const _filePath = validateMcpString(params.filePath, 'filePath', 4 * 1024) ?? undefined;
607
- const suggestion = await pickAgents(description, 3);
608
- const complexity = taskComplexity(description);
609
- // Enhanced model routing module was never shipped — modelRouting stays undefined.
610
- const modelRouting = undefined;
611
- // ERL: Retrieve past heuristics to inject into recommendations
612
- // Source: https://arxiv.org/abs/2603.24639
613
- const erlHints = [];
614
- try {
615
- const searchFn = await getRealSearchFunction();
616
- if (searchFn) {
617
- const heuristicResults = await searchFn({
618
- query: description,
619
- namespace: 'heuristics',
620
- limit: 3,
621
- threshold: 0.6,
622
- });
623
- for (const r of heuristicResults?.results ?? []) {
624
- try {
625
- const h = JSON.parse(r.content ?? '{}');
626
- if (h.action && h.confidence !== undefined && h.confidence >= 0.6) {
627
- erlHints.push(`ERL hint (conf=${h.confidence.toFixed(2)}): use "${h.action}" for tasks involving "${h.condition ?? 'similar context'}"`);
628
- }
629
- }
630
- catch {
631
- /* skip malformed */
632
- }
633
- }
634
- // TextGrad: also inject relevant past failure gradients to guide away from known pitfalls
635
- // Source: https://arxiv.org/abs/2406.07496
636
- const gradientResults = await searchFn({
637
- query: description,
638
- namespace: 'gradients',
639
- limit: 2,
640
- threshold: 0.55,
641
- });
642
- for (const r of gradientResults?.results ?? []) {
643
- const critique = r.content ?? '';
644
- if (critique && critique.length > 10) {
645
- erlHints.push(`TextGrad warning: ${critique.slice(0, 120)}`);
646
- }
647
- }
648
- }
649
- }
650
- catch {
651
- /* non-critical */
652
- }
653
- // NOTE: a LATS planning pass used to be attempted here via
654
- // `import('@monoes/hooks').buildLATSPlan` — that function never existed
655
- // in the package (the planning module was removed), so the import failed
656
- // silently on every call. The dead block was removed.
657
- let plan;
658
- // P2-15: Retrieve Reflexion reflections for this task — past failures
659
- // on similar tasks are injected as recommendations so the agent avoids
660
- // repeating mistakes. This closes the self-learning loop.
661
- let reflexionWarnings = [];
662
- try {
663
- const hooksPkg = await import('@monoes/hooks').catch(() => null);
664
- const fn = hooksPkg?.getReflectionsForTask;
665
- if (typeof fn === 'function') {
666
- const cwd = process.cwd();
667
- const reflections = await fn(cwd, description, 3);
668
- reflexionWarnings = reflections.map((r) => `⚠ Past failure: ${r.reflection.slice(0, 200)}`);
669
- }
670
- }
671
- catch {
672
- /* non-critical — reflexion store may not exist yet */
673
- }
674
- return {
675
- taskId,
676
- description,
677
- suggestedAgents: suggestion.agents,
678
- complexity,
679
- estimatedDuration: estimatedDuration(complexity),
680
- risks: complexity === 'high' ? ['Complex task may require multiple iterations'] : [],
681
- recommendations: [
682
- `Use ${suggestion.agents[0].type} as primary agent`,
683
- suggestion.agents.length > 2
684
- ? 'Consider using swarm coordination'
685
- : 'Single agent recommended',
686
- ...erlHints,
687
- ...reflexionWarnings,
688
- ],
689
- modelRouting,
690
- plan,
691
- timestamp: new Date().toISOString(),
692
- };
693
- },
694
- };
695
- /** Provenance ref for the causal edge this hook writes.
696
- *
697
- * Every post-task hook used to ingest under the bare string
698
- * `hooks-post-task`, so a graph rollback aimed at one bad task withdrew the
699
- * causal record of every task the hook had ever seen, and there was no ref
700
- * that named a single one. Keying on the task id makes the ref unique per
701
- * operation and stable for it: re-running post-task for the same task
702
- * re-asserts the same support rather than minting a second one. */
703
- export function postTaskOriginRef(taskId) {
704
- return `hooks-post-task:${taskId}`;
705
- }
706
- export const hooksPostTask = {
707
- name: 'hooks_post-task',
708
- description: 'Record task completion for learning',
709
- inputSchema: {
710
- type: 'object',
711
- properties: {
712
- taskId: { type: 'string', description: 'Task identifier' },
713
- success: { type: 'boolean', description: 'Whether task was successful' },
714
- agent: { type: 'string', description: 'Agent that completed the task' },
715
- quality: { type: 'number', description: 'Quality score (0-1)' },
716
- task: {
717
- type: 'string',
718
- description: 'Task description text (used for learning keyword extraction)',
719
- },
720
- storeDecisions: { type: 'boolean', description: 'Also store routing decision in memory DB' },
721
- routeId: {
722
- type: 'string',
723
- description: 'Route ID from a prior hooks_route call — joins the recommendation to this outcome',
724
- },
725
- },
726
- required: ['taskId'],
727
- },
728
- handler: async (params) => {
729
- // Cap taskId for the same reason as hooks_pre_task: it flows into SQLite memory keys
730
- // (heuristic:${taskId}, routing-decision:${taskId}, textual_gradient:${taskId}) and
731
- // into causal-graph edge IDs persisted to the DB. Without a cap an attacker can
732
- // inflate every row that stores the raw ID.
733
- const MAX_POST_TASK_ID_LEN = 256;
734
- const taskId = validateMcpString(params.taskId, 'taskId', MAX_POST_TASK_ID_LEN);
735
- if (!taskId) {
736
- return { error: 'taskId is required (non-empty string, no control chars, max 256 chars)' };
737
- }
738
- // The success flag, when the caller asserts it (--success true), is taken as
739
- // ground truth. But callers usually do NOT pass it. Rather than treating every
740
- // unverified task as "unknown" (and thus excluding it from learning), we now
741
- // derive a MEASURED success signal from the real command exit codes recorded by
742
- // post-command within a recent time window. post-command appends each exit code
743
- // to the command-outcome store keyed by timestamp; deriveRecentSuccess returns:
744
- // true → recent commands exist and the LAST command exited 0 (final-state heuristic)
745
- // false → recent commands exist and the LAST command exited non-zero
746
- // null → no recent commands (genuinely no signal → stays unknown)
747
- // Note: "final-state" not "all must pass" — intermediate failures (e.g. grep no-match,
748
- // test-then-fix cycles) are intentionally ignored; the last exit code decides.
749
- // Precedence: an explicit --success ALWAYS wins; the derived signal only fills
750
- // in when no explicit flag is given; only when there is also no recent command
751
- // signal does the outcome stay unknown (and excluded from SONA + route join,
752
- // per the existing "unknown ≠ success" principle).
753
- const explicitSuccess = typeof params.success === 'boolean';
754
- let outcomeKnown = explicitSuccess;
755
- let success = params.success !== false;
756
- let successSource = explicitSuccess
757
- ? 'explicit'
758
- : 'unknown';
759
- if (!explicitSuccess) {
760
- const derived = await deriveRecentSuccess(getRouteOutcomesBaseDir());
761
- if (derived !== null) {
762
- outcomeKnown = true;
763
- success = derived;
764
- successSource = 'derived-commands';
765
- }
766
- }
767
- // Cap agent: forwarded to bridgeRecordFeedback where it is stored in the
768
- // feedback record and used as a tag string in the JSON store. An uncapped
769
- // agent value inflates the on-disk store entry.
770
- const MAX_POST_TASK_AGENT_LEN = 256;
771
- const agent = validateMcpString(params.agent, 'agent', MAX_POST_TASK_AGENT_LEN) ?? undefined;
772
- const quality = typeof params.quality === 'number' && Number.isFinite(params.quality)
773
- ? Math.max(0, Math.min(1, params.quality))
774
- : success
775
- ? 0.85
776
- : 0.3;
777
- const startTime = Date.now();
778
- // Cap task description: passed to generateEmbedding via bridgeRecordFeedback
779
- // and persisted to route-outcomes.jsonl. 16 KB matches hooks_route cap.
780
- const MAX_POST_TASK_LEN = 16 * 1024;
781
- const cappedPostTask = validateMcpString(params.task, 'task', MAX_POST_TASK_LEN) ?? undefined;
782
- // Phase 3: Wire recordFeedback through bridge → LearningSystem + ReasoningBank
783
- let feedbackResult = null;
784
- try {
785
- const bridge = await import('../memory/memory-bridge.js');
786
- feedbackResult = await bridge.bridgeRecordFeedback({
787
- taskType: agent ?? 'task',
788
- action: cappedPostTask?.slice(0, 80) ?? taskId,
789
- outcome: success ? 'success' : outcomeKnown ? 'failure' : 'partial',
790
- confidence: quality,
791
- metadata: {
792
- taskId,
793
- duration: typeof params.duration === 'number' && Number.isFinite(params.duration)
794
- ? params.duration
795
- : undefined,
796
- patterns: Array.isArray(params.patterns)
797
- ? params.patterns
798
- .filter((p) => typeof p === 'string' && p.length > 0 && p.length <= 200)
799
- .slice(0, 50)
800
- : undefined,
801
- },
802
- });
803
- }
804
- catch (e) {
805
- // Bridge not available — continue with basic response
806
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
807
- console.error('[hooks-post-task] memory bridge feedback failed:', e);
808
- }
809
- // Phase 3: Record causal edge (task → outcome) as a real, traversable
810
- // knowledge-graph edge (via memory_kg_ingest — same path as the
811
- // memory_causal-edge MCP tool), not the opaque write-only `causal:` bridge namespace.
812
- try {
813
- const kg = await import('../memory/memory-kg.js');
814
- const outcomeId = `outcome-${taskId}`;
815
- await kg.kgIngest({
816
- nodes: [{ name: taskId }, { name: outcomeId }],
817
- edges: [
818
- {
819
- source: taskId,
820
- target: outcomeId,
821
- relation: success ? 'succeeded' : 'failed',
822
- },
823
- ],
824
- originRef: postTaskOriginRef(taskId),
825
- });
826
- }
827
- catch (e) {
828
- // Non-fatal
829
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
830
- console.error('[hooks-post-task] causal edge record failed:', e);
831
- }
832
- // Persist routing outcome for runtime learning (file-based, always reliable).
833
- // B1.3: also gate this sibling learning sink on a known outcome — an unverified
834
- // task must not train the router as a success either. When the caller did not
835
- // assert success, the outcome is unknown and we skip persisting a labeled sample.
836
- const taskText = cappedPostTask || '';
837
- const outcomeKeywords = extractKeywords(taskText);
838
- let outcomePersisted = false;
839
- if (outcomeKnown &&
840
- taskText &&
841
- agent &&
842
- agent.length <= 100 &&
843
- /^[a-zA-Z0-9_-]+$/.test(agent)) {
844
- try {
845
- const outcomes = loadRoutingOutcomes();
846
- outcomes.push({
847
- task: taskText,
848
- agent,
849
- success,
850
- quality,
851
- keywords: outcomeKeywords,
852
- timestamp: new Date().toISOString(),
853
- });
854
- outcomePersisted = saveRoutingOutcomes(outcomes);
855
- }
856
- catch {
857
- /* non-critical */
858
- }
859
- }
860
- // Join this outcome back onto the original route recommendation. This is the
861
- // recommendation→actual→success link that routing-accuracy metrics and SONA
862
- // labels depend on. When the caller threads an explicit routeId we join that
863
- // record; otherwise we auto-correlate to the most recent unresolved route
864
- // (within a 10-min window) so the loop closes without the LLM manually
865
- // threading the routeId. Only join when the outcome is actually measured —
866
- // per "unknown ≠ success", an unverified task must not pollute the metric.
867
- if (outcomeKnown) {
868
- const outcome = {
869
- agentActuallyUsed: agent,
870
- measuredSuccess: success,
871
- quality: typeof params.quality === 'number' ? params.quality : undefined,
872
- };
873
- if (params.routeId) {
874
- const routeId = validateMcpString(params.routeId, 'routeId', 256);
875
- if (routeId) {
876
- await joinOutcome(getRouteOutcomesBaseDir(), routeId, outcome);
877
- }
878
- }
879
- else {
880
- await joinLatestUnresolved(getRouteOutcomesBaseDir(), outcome);
881
- }
882
- }
883
- // ERL: Extract and persist structured heuristic for future pre-task injection
884
- // Source: https://arxiv.org/abs/2603.24639
885
- if (taskText && agent && success !== undefined) {
886
- try {
887
- const storeFn = await getRealStoreFunction();
888
- if (storeFn) {
889
- const heuristic = {
890
- condition: outcomeKeywords.slice(0, 3).join(', ') || taskText.slice(0, 60),
891
- action: agent,
892
- confidence: success ? (quality ?? 0.8) : 0.2,
893
- };
894
- await storeFn({
895
- key: `heuristic:${taskId}`,
896
- value: JSON.stringify(heuristic),
897
- namespace: 'heuristics',
898
- tags: ['erl', agent, success ? 'success' : 'failure'],
899
- });
900
- }
901
- }
902
- catch {
903
- /* non-critical */
904
- }
905
- }
906
- // Optionally store in memory DB for cross-session vector retrieval
907
- if (params.storeDecisions && taskText && agent) {
908
- try {
909
- const storeFn = await getRealStoreFunction();
910
- if (storeFn) {
911
- await storeFn({
912
- key: `routing-decision:${taskId}`,
913
- namespace: 'patterns',
914
- value: JSON.stringify({
915
- task: taskText,
916
- agent,
917
- success,
918
- quality,
919
- keywords: outcomeKeywords,
920
- }),
921
- tags: ['routing-decision'],
922
- });
923
- }
924
- }
925
- catch {
926
- /* non-critical */
927
- }
928
- }
929
- const duration = Date.now() - startTime;
930
- // TextGrad: Store textual gradient critique for failed tasks
931
- // Source: https://arxiv.org/abs/2406.07496 (TextGrad — Nature)
932
- if (!success && taskText) {
933
- try {
934
- const storeFn = await getRealStoreFunction();
935
- if (storeFn) {
936
- const critique = `Task "${taskText.slice(0, 80)}" failed with agent "${agent}". ` +
937
- `Quality score: ${quality ?? 'unknown'}. ` +
938
- `Improvement direction: review agent selection, consider more capable agent or task decomposition.`;
939
- await storeFn({
940
- key: `textual_gradient:${taskId}`,
941
- value: critique,
942
- namespace: 'gradients',
943
- tags: ['textual_gradient', agent ?? 'unknown', 'failure'],
944
- });
945
- }
946
- }
947
- catch {
948
- /* non-critical */
949
- }
950
- }
951
- // MAR: Structured multi-agent reflection on failure
952
- // Source: https://arxiv.org/html/2512.20845 (MAR — December 2025)
953
- const marReflection = !success
954
- ? {
955
- needed: true,
956
- suggestedAgents: [
957
- { role: 'diagnoser', description: 'Analyze root cause of task failure' },
958
- { role: 'critic-1', description: 'Critique from correctness angle (temperature 0.3)' },
959
- { role: 'critic-2', description: 'Critique from efficiency angle (temperature 0.8)' },
960
- {
961
- role: 'aggregator',
962
- description: 'Synthesize critiques into actionable reflection heuristic',
963
- },
964
- ],
965
- storeAs: 'heuristics',
966
- note: 'Spawn agents sequentially: Diagnoser → Critics in parallel → Aggregator',
967
- }
968
- : { needed: false };
969
- return {
970
- taskId,
971
- success,
972
- outcomeKnown,
973
- successSource,
974
- duration,
975
- learningUpdates: {
976
- controller: feedbackResult?.success ? 'sqlite' : 'none',
977
- outcomePersisted,
978
- },
979
- quality,
980
- feedback: feedbackResult
981
- ? {
982
- recorded: feedbackResult.success,
983
- controller: feedbackResult.success ? 'sqlite' : 'unavailable',
984
- updates: feedbackResult.success ? 1 : 0,
985
- }
986
- : { recorded: false, controller: 'unavailable', updates: 0 },
987
- marReflection,
988
- timestamp: new Date().toISOString(),
989
- };
990
- },
991
- };
992
- // Explain hook - transparent routing explanation
993
- export const hooksExplain = {
994
- name: 'hooks_explain',
995
- description: 'Explain routing decision with full transparency',
996
- inputSchema: {
997
- type: 'object',
998
- properties: {
999
- task: { type: 'string', description: 'Task description' },
1000
- agent: { type: 'string', description: 'Specific agent to explain' },
1001
- verbose: { type: 'boolean', description: 'Verbose explanation' },
1002
- },
1003
- required: ['task'],
1004
- },
1005
- handler: async (params) => {
1006
- // Cap task: ranked by the central picker and
1007
- // reflected verbatim in the response.
1008
- const MAX_EXPLAIN_TASK_LEN = 16 * 1024;
1009
- const task = validateMcpString(params.task, 'task', MAX_EXPLAIN_TASK_LEN);
1010
- if (!task) {
1011
- return { error: 'task is required (non-empty string, no control chars, max 16KB)' };
1012
- }
1013
- // Same pick hooks_route makes, so the explanation matches the decision.
1014
- const pick = await pickAgents(task, 3);
1015
- const top = pick.agents[0];
1016
- const how = pick.method === 'jev'
1017
- ? `the decision model${pick.provider ? ` (${pick.provider})` : ''} ranked the registry agents`
1018
- : pick.method === 'keyword'
1019
- ? 'task words were matched against registry agent names and descriptions'
1020
- : 'no registry agent matched, so the default agent was used';
1021
- // The patterns that matched are the agents the picker ranked.
1022
- const matchedPatterns = pick.agents.map((a) => ({
1023
- pattern: a.type,
1024
- matchScore: a.confidence,
1025
- examples: [a.reason],
1026
- }));
1027
- // Calculate real historical success rate from routing outcomes file
1028
- let historicalSuccess = null;
1029
- let historicalNote = 'No historical data yet';
1030
- try {
1031
- const outcomesPath = getRoutingOutcomesPath();
1032
- if (existsSync(outcomesPath)) {
1033
- const data = JSON.parse(readFileSync(outcomesPath, 'utf-8'));
1034
- const outcomes = data.outcomes || [];
1035
- if (outcomes.length > 0) {
1036
- historicalSuccess = outcomes.filter((o) => o.success).length / outcomes.length;
1037
- historicalNote = `Calculated from ${outcomes.length} recorded outcomes`;
1038
- }
1039
- }
1040
- }
1041
- catch (e) {
1042
- // File unreadable or corrupt; leave as null
1043
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1044
- console.error('[hooks-explain] routing outcomes file read/parse failed:', e);
1045
- }
1046
- return {
1047
- task,
1048
- explanation: `The routing decision was made by the central picker: ${how}. ` +
1049
- `"${top.type}" ranked first with ${(top.confidence * 100).toFixed(0)}% confidence.`,
1050
- factors: [
1051
- {
1052
- factor: pick.method === 'jev' ? 'Decision Model' : 'Keyword Match',
1053
- weight: 0.4,
1054
- value: top.confidence,
1055
- impact: 'Primary routing signal',
1056
- },
1057
- {
1058
- factor: 'Historical Success',
1059
- weight: 0.3,
1060
- value: historicalSuccess,
1061
- impact: historicalNote,
1062
- },
1063
- {
1064
- factor: 'Agent Availability',
1065
- weight: 0.2,
1066
- value: null,
1067
- impact: 'Agent availability tracking not implemented',
1068
- },
1069
- {
1070
- factor: 'Task Complexity',
1071
- weight: 0.1,
1072
- value: task.length > 100 ? 0.8 : 0.3,
1073
- impact: 'Complexity assessment',
1074
- },
1075
- ],
1076
- patterns: matchedPatterns.length > 0
1077
- ? matchedPatterns
1078
- : [
1079
- {
1080
- pattern: 'general-task',
1081
- matchScore: 0.7,
1082
- examples: ['Default pattern for unclassified tasks'],
1083
- },
1084
- ],
1085
- decision: {
1086
- agent: top.type,
1087
- confidence: top.confidence,
1088
- reasoning: [
1089
- `Ranking method: ${pick.method} — ${how}`,
1090
- `"${top.type}" ranked first`,
1091
- pick.agents.length > 1
1092
- ? `Alternatives: ${pick.agents
1093
- .slice(1)
1094
- .map((a) => a.type)
1095
- .join(', ')}`
1096
- : 'No alternative agent ranked',
1097
- historicalSuccess !== null
1098
- ? `Historical success rate for similar tasks: ${(historicalSuccess * 100).toFixed(0)}%`
1099
- : `No historical outcome data available yet`,
1100
- ],
1101
- },
1102
- };
1103
- },
1104
- };
1105
- // Pretrain hook - repository analysis for intelligence bootstrap
1106
- export const hooksPretrain = {
1107
- name: 'hooks_pretrain',
1108
- description: 'Walk the repository counting file extensions and directory patterns to seed the keyword router. This is a filesystem scan writing JSON state — despite the name, no model is trained.',
1109
- inputSchema: {
1110
- type: 'object',
1111
- properties: {
1112
- path: { type: 'string', description: 'Repository path' },
1113
- depth: { type: 'string', description: 'Analysis depth (shallow, medium, deep)' },
1114
- skipCache: { type: 'boolean', description: 'Skip cached analysis' },
1115
- },
1116
- },
1117
- handler: async (params) => {
1118
- const repoPath = resolve(validateMcpString(params.path, 'path', 4 * 1024) ?? '.');
1119
- const projectRoot = getProjectCwd();
1120
- if (repoPath !== projectRoot && !repoPath.startsWith(projectRoot + sep)) {
1121
- return { error: 'Invalid path: must be within the project directory.' };
1122
- }
1123
- const depth = validateMcpString(params.depth, 'depth', 16) ?? 'medium';
1124
- const allowedDepths = new Set(['shallow', 'medium', 'deep']);
1125
- if (!allowedDepths.has(depth)) {
1126
- return { error: 'Invalid depth: must be shallow, medium, or deep' };
1127
- }
1128
- const startTime = performance.now();
1129
- // Real file scanning — count files by extension, extract patterns
1130
- const { readdirSync, statSync } = await import('node:fs');
1131
- const extCounts = {};
1132
- let filesAnalyzed = 0;
1133
- let totalLines = 0;
1134
- const maxDepth = depth === 'shallow' ? 2 : depth === 'deep' ? 6 : 4;
1135
- const patterns = [];
1136
- const scan = (dir, currentDepth) => {
1137
- if (currentDepth > maxDepth)
1138
- return;
1139
- try {
1140
- const entries = readdirSync(dir, { withFileTypes: true });
1141
- for (const entry of entries) {
1142
- if (entry.name.startsWith('.') || entry.name === 'node_modules' || entry.name === 'dist')
1143
- continue;
1144
- const full = join(dir, entry.name);
1145
- if (entry.isDirectory()) {
1146
- scan(full, currentDepth + 1);
1147
- }
1148
- else if (entry.isFile()) {
1149
- const ext = entry.name.includes('.')
1150
- ? entry.name.slice(entry.name.lastIndexOf('.'))
1151
- : '';
1152
- if (ext)
1153
- extCounts[ext] = (extCounts[ext] || 0) + 1;
1154
- filesAnalyzed++;
1155
- // For code files, count lines and extract imports
1156
- if (['.ts', '.js', '.py', '.go', '.rs', '.java'].includes(ext)) {
1157
- try {
1158
- // Skip very large files (minified bundles, generated code) to prevent OOM.
1159
- // 1 MB is generous for a source file; anything larger is unlikely to have
1160
- // useful import patterns in the first 30 lines anyway.
1161
- const MAX_CODE_FILE_BYTES = 1 * 1024 * 1024;
1162
- if (statSync(full).size > MAX_CODE_FILE_BYTES)
1163
- continue;
1164
- const content = readFileSync(full, 'utf-8');
1165
- const lines = content.split('\n');
1166
- totalLines += lines.length;
1167
- // Extract import patterns (first 50 files max for performance)
1168
- if (filesAnalyzed <= 50) {
1169
- for (const line of lines.slice(0, 30)) {
1170
- if (line.startsWith('import ') ||
1171
- line.startsWith('from ') ||
1172
- (line.startsWith('const ') && line.includes('require('))) {
1173
- const trimmed = line.trim();
1174
- if (trimmed.length < 120 && !patterns.includes(trimmed))
1175
- patterns.push(trimmed);
1176
- if (patterns.length >= 100)
1177
- break;
1178
- }
1179
- }
1180
- }
1181
- }
1182
- catch {
1183
- /* skip unreadable */
1184
- }
1185
- }
1186
- }
1187
- }
1188
- }
1189
- catch {
1190
- /* skip inaccessible dirs */
1191
- }
1192
- };
1193
- scan(repoPath, 0);
1194
- const elapsed = Math.round(performance.now() - startTime);
1195
- // Store extracted patterns in memory backend
1196
- let patternsStored = 0;
1197
- try {
1198
- const bridge = await import('../memory/memory-bridge.js');
1199
- const stored = await bridge.bridgeStoreEntry({
1200
- key: `pretrain-${Date.now()}`,
1201
- value: JSON.stringify({
1202
- filesAnalyzed,
1203
- totalLines,
1204
- topExtensions: Object.entries(extCounts)
1205
- .sort((a, b) => b[1] - a[1])
1206
- .slice(0, 10),
1207
- importPatterns: patterns.slice(0, 20),
1208
- }),
1209
- namespace: 'pretrain',
1210
- tags: ['pretrain', depth],
1211
- });
1212
- // #293: only count what actually persisted. bridgeStoreEntry returns
1213
- // null (never throws) when the backend cannot be loaded, so this used to
1214
- // report every scanned pattern as stored on a store that did nothing.
1215
- if (stored?.success)
1216
- patternsStored = patterns.length;
1217
- else
1218
- console.warn(`[hooks-pretrain] patterns were NOT stored (${stored?.error ?? 'memory backend unavailable'})`);
1219
- }
1220
- catch (e) {
1221
- /* memory backend unavailable */
1222
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1223
- console.error('[hooks-pretrain] pattern store failed:', e);
1224
- }
1225
- // Feed extracted import patterns into the neural training system so
1226
- // pretrain actually trains, not just scans.
1227
- let neuralPatternsLearned = 0;
1228
- if (patterns.length > 0) {
1229
- try {
1230
- const intel = await import('../memory/intelligence.js');
1231
- await intel.initializeIntelligence({
1232
- confidenceLearningRate: 0.002,
1233
- maxTrajectorySize: patterns.length,
1234
- });
1235
- // Record each extracted pattern as an action step
1236
- for (const pat of patterns.slice(0, 50)) {
1237
- await intel.recordStep({
1238
- type: 'action',
1239
- content: pat,
1240
- metadata: { source: 'pretrain', depth },
1241
- });
1242
- }
1243
- // Record the entire scan as a completed trajectory
1244
- const steps = patterns.slice(0, 50).map((p) => ({ type: 'action', content: p }));
1245
- const recorded = await intel.recordTrajectory(steps, 'success');
1246
- intel.flushPatterns();
1247
- if (recorded)
1248
- neuralPatternsLearned = steps.length;
1249
- }
1250
- catch (e) {
1251
- /* intelligence not available */
1252
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1253
- console.error('[hooks-pretrain] intelligence training failed:', e);
1254
- }
1255
- }
1256
- return {
1257
- success: true,
1258
- _real: true,
1259
- path: repoPath,
1260
- depth,
1261
- durationMs: elapsed,
1262
- stats: {
1263
- filesAnalyzed,
1264
- totalLines,
1265
- patternsExtracted: patterns.length,
1266
- patternsStored,
1267
- neuralPatternsLearned,
1268
- fileTypes: Object.entries(extCounts)
1269
- .sort((a, b) => b[1] - a[1])
1270
- .slice(0, 15)
1271
- .map(([ext, count]) => ({ ext, count })),
1272
- },
1273
- };
1274
- },
1275
- };
1276
- // Transfer hook - transfer patterns from another project
1277
- export const hooksTransfer = {
1278
- name: 'hooks_transfer',
1279
- description: 'Transfer learned patterns from another project',
1280
- inputSchema: {
1281
- type: 'object',
1282
- properties: {
1283
- sourcePath: { type: 'string', description: 'Source project path' },
1284
- filter: { type: 'string', description: 'Filter patterns by type' },
1285
- minConfidence: { type: 'number', description: 'Minimum confidence threshold' },
1286
- },
1287
- required: ['sourcePath'],
1288
- },
1289
- handler: async (params) => {
1290
- const sourcePath = validateMcpString(params.sourcePath, 'sourcePath', 4 * 1024);
1291
- if (!sourcePath) {
1292
- return { error: 'sourcePath is required (non-empty string, no control chars, max 4KB)' };
1293
- }
1294
- const minConfidence = typeof params.minConfidence === 'number' && Number.isFinite(params.minConfidence)
1295
- ? Math.max(0, Math.min(1, params.minConfidence))
1296
- : 0.7;
1297
- const filter = validateMcpString(params.filter, 'filter', 64) ?? undefined;
1298
- // Validate sourcePath is an existing directory before reading from it
1299
- const resolvedSource = resolve(sourcePath);
1300
- const { statSync } = await import('node:fs');
1301
- const { homedir } = await import('node:os');
1302
- const home = homedir();
1303
- if (resolvedSource !== home && !resolvedSource.startsWith(home + sep)) {
1304
- return { error: 'sourcePath must be within the home directory.' };
1305
- }
1306
- try {
1307
- const st = statSync(resolvedSource);
1308
- if (!st.isDirectory()) {
1309
- return { error: 'sourcePath must be a directory' };
1310
- }
1311
- }
1312
- catch {
1313
- return { error: 'sourcePath does not exist' };
1314
- }
1315
- // Load learned patterns from the source project's neural pattern store —
1316
- // the same `.monomind/neural/patterns.json` file `hooks intelligence
1317
- // import` writes to and intelligence.ts reads from (src/memory/intelligence.ts
1318
- // getPatternsPath()).
1319
- const sourcePatternsPath = join(resolvedSource, '.monomind', 'neural', 'patterns.json');
1320
- let sourcePatterns = [];
1321
- const MAX_SOURCE_PATTERNS_BYTES = 50 * 1024 * 1024; // 50 MB — matches other store readers
1322
- try {
1323
- if (existsSync(sourcePatternsPath) &&
1324
- statSync(sourcePatternsPath).size <= MAX_SOURCE_PATTERNS_BYTES) {
1325
- const parsed = JSON.parse(readFileSync(sourcePatternsPath, 'utf-8'));
1326
- if (Array.isArray(parsed))
1327
- sourcePatterns = parsed;
1328
- }
1329
- }
1330
- catch (e) {
1331
- // Fall back to empty list
1332
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1333
- console.error('[hooks-transfer] source patterns.json read/parse failed:', e);
1334
- }
1335
- if (sourcePatterns.length === 0) {
1336
- return {
1337
- success: false,
1338
- message: 'No patterns found in source project',
1339
- sourcePath,
1340
- transferred: { total: 0, byType: {} },
1341
- };
1342
- }
1343
- // Qualifying patterns: confidence at/above threshold, and (if given) type
1344
- // matches the filter.
1345
- const qualifying = sourcePatterns.filter((p) => typeof p.id === 'string' &&
1346
- p.id.length > 0 &&
1347
- (typeof p.confidence !== 'number' || p.confidence >= minConfidence) &&
1348
- (!filter || (typeof p.type === 'string' && p.type.includes(filter))));
1349
- if (qualifying.length === 0) {
1350
- return {
1351
- success: false,
1352
- message: 'No patterns in source project meet the filter/confidence threshold',
1353
- sourcePath,
1354
- transferred: { total: 0, byType: {} },
1355
- };
1356
- }
1357
- // Merge into this project's pattern store, reusing the same by-id dedupe
1358
- // logic as `hooks intelligence import` (neural-registry.ts's importCommand).
1359
- const destDir = join(getProjectCwd(), '.monomind', 'neural');
1360
- const destPatternsPath = join(destDir, 'patterns.json');
1361
- let destPatterns = [];
1362
- try {
1363
- if (existsSync(destPatternsPath) &&
1364
- statSync(destPatternsPath).size <= MAX_SOURCE_PATTERNS_BYTES) {
1365
- const parsed = JSON.parse(readFileSync(destPatternsPath, 'utf-8'));
1366
- if (Array.isArray(parsed))
1367
- destPatterns = parsed;
1368
- }
1369
- }
1370
- catch (e) {
1371
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1372
- console.error('[hooks-transfer] destination patterns.json read/parse failed:', e);
1373
- }
1374
- const { merged, added } = mergeRecordsById(destPatterns, qualifying);
1375
- if (!existsSync(destDir))
1376
- mkdirSync(destDir, { recursive: true });
1377
- const tmpDest = `${destPatternsPath}.${process.pid}.${Date.now()}.tmp`;
1378
- writeFileSync(tmpDest, JSON.stringify(merged, null, 2), 'utf-8');
1379
- renameSync(tmpDest, destPatternsPath);
1380
- // Real counts of what was actually transferred, grouped by each pattern's
1381
- // own `type` field (falling back to 'unknown' when absent).
1382
- const byType = {};
1383
- for (const p of added) {
1384
- const type = typeof p.type === 'string' && p.type.length > 0 ? p.type : 'unknown';
1385
- byType[type] = (byType[type] || 0) + 1;
1386
- }
1387
- return {
1388
- success: true,
1389
- sourcePath,
1390
- transferred: {
1391
- total: added.length,
1392
- byType,
1393
- },
1394
- dataSource: 'source-project',
1395
- };
1396
- },
1397
- };
1398
- // Session start hook
1399
- export const hooksSessionStart = {
1400
- name: 'hooks_session-start',
1401
- description: 'Initialize a new session',
1402
- inputSchema: {
1403
- type: 'object',
1404
- properties: {
1405
- sessionId: { type: 'string', description: 'Optional session ID' },
1406
- restoreLatest: {
1407
- type: 'boolean',
1408
- description: 'Load the most recent previous session record and return it as previousSession',
1409
- },
1410
- },
1411
- },
1412
- handler: async (params) => {
1413
- const sessionId = validateMcpString(params.sessionId, 'sessionId', 256) ?? `session-${Date.now()}`;
1414
- const restoreLatest = params.restoreLatest === true;
1415
- // Look up the previous session before this one's row is written, and
1416
- // report only what that row actually holds — nothing when there is none.
1417
- let previousSession = null;
1418
- let controller = 'none';
1419
- try {
1420
- const bridge = await import('../memory/memory-bridge.js');
1421
- if (restoreLatest) {
1422
- previousSession = await bridge.bridgeLatestSession({ excludeSessionId: sessionId });
1423
- }
1424
- const result = await bridge.bridgeSessionStart({
1425
- sessionId,
1426
- metadata: { context: restoreLatest ? 'restore previous session patterns' : 'new session' },
1427
- });
1428
- if (result?.success)
1429
- controller = 'sqlite';
1430
- }
1431
- catch (e) {
1432
- // Bridge not available
1433
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1434
- console.error('[hooks-session-start] memory bridge failed:', e);
1435
- }
1436
- return {
1437
- sessionId,
1438
- started: new Date().toISOString(),
1439
- restored: previousSession !== null,
1440
- sessionMemory: { controller },
1441
- previousSession,
1442
- };
1443
- },
1444
- };
1445
- // Session restore hook — hooks.ts's `hooks session-restore` (and its
1446
- // `session-start` alias) called this tool name, but it was never registered
1447
- // anywhere in the tool registry, so both always failed. This repo has no
1448
- // per-session snapshot of agents/tasks to restore from, so "restore" here
1449
- // means: report the currently-live (non-terminated/non-terminal) agents and
1450
- // tasks as "carried forward", and reinitialize the memory-bridge session
1451
- // context the same way hooks_session-start does — an honest, working
1452
- // implementation rather than a fabricated one.
1453
- export const hooksSessionRestore = {
1454
- name: 'hooks_session-restore',
1455
- description: 'Restore a previous session — reports currently-live agents/tasks and reinitializes memory-bridge session context',
1456
- inputSchema: {
1457
- type: 'object',
1458
- properties: {
1459
- sessionId: { type: 'string', description: 'Session ID to restore, or "latest"' },
1460
- restoreAgents: {
1461
- type: 'boolean',
1462
- description: 'Include a count of currently-live agents (default true)',
1463
- },
1464
- restoreTasks: {
1465
- type: 'boolean',
1466
- description: 'Include a count of currently-live tasks (default true)',
1467
- },
1468
- },
1469
- },
1470
- handler: async (params) => {
1471
- const originalSessionId = validateMcpString(params.sessionId, 'sessionId', 256) ?? 'latest';
1472
- const newSessionId = `session-${Date.now()}`;
1473
- const warnings = [];
1474
- let agentsRestored = 0;
1475
- if (params.restoreAgents !== false) {
1476
- try {
1477
- const { loadAgentStore } = await import('./agent-tools.js');
1478
- const store = loadAgentStore();
1479
- agentsRestored = Object.values(store.agents).filter((a) => a.status !== 'terminated').length;
1480
- }
1481
- catch (e) {
1482
- warnings.push('Agent store unavailable — agent count not restored');
1483
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1484
- console.error('[hooks-session-restore] agent store read failed:', e);
1485
- }
1486
- }
1487
- let tasksRestored = 0;
1488
- if (params.restoreTasks !== false) {
1489
- try {
1490
- const { loadTaskStore } = await import('./task-tools.js');
1491
- const store = loadTaskStore();
1492
- tasksRestored = Object.values(store.tasks).filter((t) => t.status === 'pending' || t.status === 'in_progress').length;
1493
- }
1494
- catch (e) {
1495
- warnings.push('Task store unavailable — task count not restored');
1496
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1497
- console.error('[hooks-session-restore] task store read failed:', e);
1498
- }
1499
- }
1500
- // bridgeSessionStart only stores a new "session active" marker entry —
1501
- // it has no pattern-restoration data to count, so there is no real
1502
- // "memoryRestored" number to report. Track whether the bridge itself
1503
- // came up instead of faking a count.
1504
- let memoryBridgeInitialized = false;
1505
- try {
1506
- const bridge = await import('../memory/memory-bridge.js');
1507
- const result = await bridge.bridgeSessionStart({
1508
- sessionId: newSessionId,
1509
- metadata: { context: 'restore previous session patterns' },
1510
- });
1511
- if (result) {
1512
- memoryBridgeInitialized = result.success;
1513
- }
1514
- else {
1515
- warnings.push('Memory bridge unavailable — pattern restoration skipped');
1516
- }
1517
- }
1518
- catch (e) {
1519
- warnings.push('Memory bridge failed to initialize');
1520
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1521
- console.error('[hooks-session-restore] memory bridge failed:', e);
1522
- }
1523
- return {
1524
- sessionId: newSessionId,
1525
- originalSessionId,
1526
- restoredState: { tasksRestored, agentsRestored, memoryBridgeInitialized },
1527
- warnings: warnings.length > 0 ? warnings : undefined,
1528
- };
1529
- },
1530
- };
1531
- // Session end hook - persists state
1532
- export const hooksSessionEnd = {
1533
- name: 'hooks_session-end',
1534
- description: 'End current session and persist state',
1535
- inputSchema: {
1536
- type: 'object',
1537
- properties: {
1538
- saveState: { type: 'boolean', description: 'Save session state' },
1539
- exportMetrics: { type: 'boolean', description: 'Export session metrics' },
1540
- },
1541
- },
1542
- handler: async (params) => {
1543
- const saveState = params.saveState !== false;
1544
- // Use caller-supplied sessionId if provided, otherwise generate a current-time ID.
1545
- // The -3600000 offset was incorrect — it prevented matching session-start IDs.
1546
- const sessionId = typeof params.sessionId === 'string' && params.sessionId
1547
- ? params.sessionId
1548
- : `session-${Date.now()}`;
1549
- // Read actual counts from stores
1550
- const store = loadMemoryStore();
1551
- const allEntries = Object.values(store.entries);
1552
- const taskCount = allEntries.filter((e) => e.key.includes('task')).length;
1553
- const agentCount = allEntries.filter((e) => e.key.includes('agent')).length;
1554
- const patternCount = allEntries.filter((e) => e.key.includes('pattern')).length;
1555
- const trajectoryCount = activeTrajectories.size;
1556
- // Check for pending-insights.jsonl
1557
- let insightCount = 0;
1558
- try {
1559
- const insightsPath = join(getProjectCwd(), '.monomind', 'data', 'pending-insights.jsonl');
1560
- if (existsSync(insightsPath)) {
1561
- const content = readFileSync(insightsPath, 'utf-8').trim();
1562
- insightCount = content ? content.split('\n').length : 0;
1563
- }
1564
- }
1565
- catch {
1566
- // File not available
1567
- }
1568
- // Phase 5: Wire ReflexionMemory session end + NightlyLearner consolidation via bridge
1569
- let sessionPersistence = null;
1570
- try {
1571
- const bridge = await import('../memory/memory-bridge.js');
1572
- const result = await bridge.bridgeSessionEnd({
1573
- sessionId,
1574
- summary: saveState ? 'Session ended with state saved' : 'Session ended',
1575
- metrics: { tasksCompleted: taskCount, patternsLearned: patternCount },
1576
- });
1577
- if (result) {
1578
- sessionPersistence = {
1579
- controller: result.success ? 'sqlite' : 'none',
1580
- persisted: result.success,
1581
- };
1582
- }
1583
- }
1584
- catch (e) {
1585
- // Bridge not available
1586
- if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
1587
- console.error('[hooks-session-end] memory bridge failed:', e);
1588
- }
1589
- // KG nudge: check if knowledge graph is empty and suggest distillation
1590
- let kgNudge = { empty: false };
1591
- if (process.env.MONOMIND_KG_NUDGE !== 'false') {
1592
- try {
1593
- const kg = await import('../memory/memory-kg.js');
1594
- const stats = await kg.kgStats();
1595
- const kgEmpty = stats.nodes === 0 && stats.edges === 0 && stats.rules === 0;
1596
- if (kgEmpty && taskCount > 0) {
1597
- kgNudge = {
1598
- empty: true,
1599
- prompt: [
1600
- 'The knowledge graph is empty (0 nodes, 0 edges, 0 rules). Before ending, distill 2-5 key insights:',
1601
- '1. Identify important entities (functions, patterns, architectural decisions)',
1602
- '2. Call memory_kg_ingest with nodes [{name, type, description}], edges [{source, target, relation}],',
1603
- ' and any durable rules [{rule, context}] — use session ID as originRef',
1604
- '3. Check existing entities first: memory_kg_stats with glossary:true',
1605
- 'Skip for trivial sessions. Disable with MONOMIND_KG_NUDGE=false',
1606
- ].join('\n'),
1607
- };
1608
- }
1609
- }
1610
- catch {
1611
- // non-fatal — skip nudge if KG module unavailable
1612
- }
1613
- }
1614
- return {
1615
- sessionId,
1616
- sessionPersistence: sessionPersistence || { controller: 'none', persisted: false },
1617
- summary: {
1618
- tasksExecuted: taskCount,
1619
- agentsSpawned: agentCount,
1620
- pendingInsights: insightCount,
1621
- memoryEntries: allEntries.length,
1622
- },
1623
- learningUpdates: {
1624
- patternsLearned: patternCount,
1625
- trajectoriesRecorded: trajectoryCount,
1626
- },
1627
- kgNudge,
1628
- };
1629
- },
1630
- };
1631
- // Intelligence hook - JS pattern/trajectory logging
1632
- export const hooksIntelligence = {
1633
- name: 'hooks_intelligence',
1634
- description: 'Intelligence status: pattern/trajectory logging metrics from the memory store',
1635
- inputSchema: {
1636
- type: 'object',
1637
- properties: {
1638
- enableHnsw: { type: 'boolean', description: 'Enable HNSW search' },
1639
- forceTraining: { type: 'boolean', description: 'Force training cycle' },
1640
- showStatus: { type: 'boolean', description: 'Show status only' },
1641
- },
1642
- },
1643
- handler: async (params) => {
1644
- const enableHnsw = params.enableHnsw !== false;
1645
- // Get REAL statistics from memory store
1646
- const realStats = getIntelligenceStatsFromMemory();
1647
- // Check actual implementation availability
1648
- const sonaAvailable = (await getSONAOptimizer()) !== null;
1649
- return {
1650
- status: 'active',
1651
- components: {
1652
- sona: {
1653
- enabled: sonaAvailable,
1654
- status: sonaAvailable ? 'active' : 'idle',
1655
- implemented: true,
1656
- trajectoriesRecorded: realStats.trajectories.total,
1657
- trajectoriesSuccessful: realStats.trajectories.successful,
1658
- patternsLearned: realStats.patterns.learned,
1659
- note: 'Trajectory + pattern logging (no neural training in the lean build)',
1660
- },
1661
- moe: {
1662
- enabled: false,
1663
- status: 'removed',
1664
- implemented: false,
1665
- routingDecisions: realStats.routing.decisions,
1666
- note: 'MoE removed in lean build; keyword routing is used instead (see monoes-full-loop)',
1667
- },
1668
- hnsw: {
1669
- enabled: enableHnsw,
1670
- status: enableHnsw ? 'active' : 'disabled',
1671
- implemented: true,
1672
- indexSize: realStats.memory.indexSize,
1673
- memorySizeBytes: realStats.memory.memorySizeBytes,
1674
- note: 'Pure-JS HNSW vector indexing (O(log n) vs O(n))',
1675
- },
1676
- flashAttention: {
1677
- enabled: false,
1678
- status: 'removed',
1679
- implemented: false,
1680
- note: 'Flash Attention removed in lean build; lives on monoes-full-loop branch',
1681
- },
1682
- ewc: {
1683
- enabled: false,
1684
- status: 'removed',
1685
- implemented: false,
1686
- note: 'EWC++ removed in lean build; lives on monoes-full-loop branch',
1687
- },
1688
- lora: {
1689
- enabled: false,
1690
- status: 'removed',
1691
- implemented: false,
1692
- note: 'LoRA removed in lean build; lives on monoes-full-loop branch',
1693
- },
1694
- embeddings: {
1695
- provider: 'transformers',
1696
- model: DEFAULT_EMBEDDING_MODEL,
1697
- dimension: DEFAULT_EMBEDDING_DIMS,
1698
- implemented: true,
1699
- note: `Real ONNX embeddings via ${DEFAULT_EMBEDDING_MODEL}`,
1700
- },
1701
- },
1702
- realMetrics: {
1703
- trajectories: realStats.trajectories,
1704
- patterns: realStats.patterns,
1705
- memory: realStats.memory,
1706
- routing: realStats.routing,
1707
- },
1708
- implementationStatus: {
1709
- working: [
1710
- 'memory-store',
1711
- 'embeddings',
1712
- 'trajectory-recording',
1713
- 'claims',
1714
- 'swarm-coordination',
1715
- 'hnsw-index',
1716
- 'pattern-storage',
1717
- 'keyword-routing',
1718
- ],
1719
- partial: [],
1720
- notImplemented: [],
1721
- removed: [
1722
- 'moe-routing',
1723
- 'flash-attention',
1724
- 'lora-adapter',
1725
- 'native-sona-engine',
1726
- 'native-router',
1727
- 'native-attention',
1728
- ],
1729
- },
1730
- version: '3.0.0-alpha.102',
1731
- };
1732
- },
1733
- };
7
+ export { hooksPostCommand, hooksPostEdit, hooksPreCommand, hooksPreEdit, } from './hooks-edit-command.js';
8
+ export { hooksIntelligence, hooksPretrain, hooksTransfer } from './hooks-learning.js';
9
+ export { hooksList, hooksMetrics } from './hooks-metrics-list.js';
10
+ export { hooksExplain, hooksRoute, hooksRouteSemantic } from './hooks-route.js';
11
+ export { hooksSessionEnd, hooksSessionRestore, hooksSessionStart } from './hooks-session.js';
12
+ export { hooksPostTask, hooksPreTask, postTaskOriginRef } from './hooks-task.js';
1734
13
  //# sourceMappingURL=hooks-routing.js.map