@soleri/core 9.0.4 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (701) hide show
  1. package/dist/brain/intelligence.d.ts +27 -0
  2. package/dist/brain/intelligence.d.ts.map +1 -1
  3. package/dist/brain/intelligence.js +160 -14
  4. package/dist/brain/intelligence.js.map +1 -1
  5. package/dist/brain/learning-radar.d.ts +4 -0
  6. package/dist/brain/learning-radar.d.ts.map +1 -1
  7. package/dist/brain/learning-radar.js +20 -1
  8. package/dist/brain/learning-radar.js.map +1 -1
  9. package/dist/brain/strength-scorer.d.ts +31 -0
  10. package/dist/brain/strength-scorer.d.ts.map +1 -0
  11. package/dist/brain/strength-scorer.js +264 -0
  12. package/dist/brain/strength-scorer.js.map +1 -0
  13. package/dist/chat/agent-loop.d.ts.map +1 -1
  14. package/dist/chat/agent-loop.js +2 -0
  15. package/dist/chat/agent-loop.js.map +1 -1
  16. package/dist/chat/notifications.d.ts.map +1 -1
  17. package/dist/chat/notifications.js +2 -0
  18. package/dist/chat/notifications.js.map +1 -1
  19. package/dist/claudemd/compose.js +1 -1
  20. package/dist/claudemd/compose.js.map +1 -1
  21. package/dist/control/intent-router.d.ts.map +1 -1
  22. package/dist/control/intent-router.js +12 -4
  23. package/dist/control/intent-router.js.map +1 -1
  24. package/dist/curator/contradiction-detector.d.ts +27 -0
  25. package/dist/curator/contradiction-detector.d.ts.map +1 -0
  26. package/dist/curator/contradiction-detector.js +62 -0
  27. package/dist/curator/contradiction-detector.js.map +1 -0
  28. package/dist/curator/curator.d.ts +3 -4
  29. package/dist/curator/curator.d.ts.map +1 -1
  30. package/dist/curator/curator.js +90 -525
  31. package/dist/curator/curator.js.map +1 -1
  32. package/dist/curator/duplicate-detector.d.ts +14 -0
  33. package/dist/curator/duplicate-detector.d.ts.map +1 -0
  34. package/dist/curator/duplicate-detector.js +77 -0
  35. package/dist/curator/duplicate-detector.js.map +1 -0
  36. package/dist/curator/health-audit.d.ts +15 -0
  37. package/dist/curator/health-audit.d.ts.map +1 -0
  38. package/dist/curator/health-audit.js +97 -0
  39. package/dist/curator/health-audit.js.map +1 -0
  40. package/dist/curator/metadata-enricher.d.ts +17 -0
  41. package/dist/curator/metadata-enricher.d.ts.map +1 -0
  42. package/dist/curator/metadata-enricher.js +60 -0
  43. package/dist/curator/metadata-enricher.js.map +1 -0
  44. package/dist/curator/schema.d.ts +7 -0
  45. package/dist/curator/schema.d.ts.map +1 -0
  46. package/dist/curator/schema.js +62 -0
  47. package/dist/curator/schema.js.map +1 -0
  48. package/dist/curator/tag-manager.d.ts +36 -0
  49. package/dist/curator/tag-manager.d.ts.map +1 -0
  50. package/dist/curator/tag-manager.js +78 -0
  51. package/dist/curator/tag-manager.js.map +1 -0
  52. package/dist/engine/bin/soleri-engine.js +24 -3
  53. package/dist/engine/bin/soleri-engine.js.map +1 -1
  54. package/dist/engine/core-ops.d.ts.map +1 -1
  55. package/dist/engine/core-ops.js +23 -8
  56. package/dist/engine/core-ops.js.map +1 -1
  57. package/dist/engine/module-manifest.d.ts.map +1 -1
  58. package/dist/engine/module-manifest.js +22 -2
  59. package/dist/engine/module-manifest.js.map +1 -1
  60. package/dist/engine/register-engine.d.ts.map +1 -1
  61. package/dist/engine/register-engine.js +26 -2
  62. package/dist/engine/register-engine.js.map +1 -1
  63. package/dist/errors/retry.d.ts.map +1 -1
  64. package/dist/errors/retry.js +2 -0
  65. package/dist/errors/retry.js.map +1 -1
  66. package/dist/facades/types.d.ts +1 -1
  67. package/dist/flows/chain-types.d.ts +18 -18
  68. package/dist/flows/gate-evaluator.d.ts.map +1 -1
  69. package/dist/flows/gate-evaluator.js +22 -0
  70. package/dist/flows/gate-evaluator.js.map +1 -1
  71. package/dist/flows/types.d.ts +157 -28
  72. package/dist/flows/types.d.ts.map +1 -1
  73. package/dist/flows/types.js +4 -0
  74. package/dist/flows/types.js.map +1 -1
  75. package/dist/index.d.ts +10 -2
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +9 -1
  78. package/dist/index.js.map +1 -1
  79. package/dist/intake/intake-pipeline.d.ts.map +1 -1
  80. package/dist/intake/intake-pipeline.js +1 -0
  81. package/dist/intake/intake-pipeline.js.map +1 -1
  82. package/dist/intake/text-ingester.d.ts.map +1 -1
  83. package/dist/intake/text-ingester.js +2 -0
  84. package/dist/intake/text-ingester.js.map +1 -1
  85. package/dist/llm/key-pool.d.ts +1 -1
  86. package/dist/llm/key-pool.d.ts.map +1 -1
  87. package/dist/llm/key-pool.js +3 -4
  88. package/dist/llm/key-pool.js.map +1 -1
  89. package/dist/llm/utils.d.ts.map +1 -1
  90. package/dist/llm/utils.js +2 -0
  91. package/dist/llm/utils.js.map +1 -1
  92. package/dist/migrations/migration-runner.test-helpers.d.ts +13 -0
  93. package/dist/migrations/migration-runner.test-helpers.d.ts.map +1 -0
  94. package/dist/migrations/migration-runner.test-helpers.js +47 -0
  95. package/dist/migrations/migration-runner.test-helpers.js.map +1 -0
  96. package/dist/operator/operator-profile.d.ts +44 -0
  97. package/dist/operator/operator-profile.d.ts.map +1 -0
  98. package/dist/operator/operator-profile.js +377 -0
  99. package/dist/operator/operator-profile.js.map +1 -0
  100. package/dist/operator/operator-signals.d.ts +45 -0
  101. package/dist/operator/operator-signals.d.ts.map +1 -0
  102. package/dist/operator/operator-signals.js +228 -0
  103. package/dist/operator/operator-signals.js.map +1 -0
  104. package/dist/operator/operator-types.d.ts +360 -0
  105. package/dist/operator/operator-types.d.ts.map +1 -0
  106. package/dist/operator/operator-types.js +24 -0
  107. package/dist/operator/operator-types.js.map +1 -0
  108. package/dist/packs/types.d.ts +27 -27
  109. package/dist/paths.d.ts +40 -0
  110. package/dist/paths.d.ts.map +1 -0
  111. package/dist/paths.js +98 -0
  112. package/dist/paths.js.map +1 -0
  113. package/dist/persistence/index.d.ts +1 -1
  114. package/dist/persistence/index.d.ts.map +1 -1
  115. package/dist/persistence/index.js +1 -1
  116. package/dist/persistence/index.js.map +1 -1
  117. package/dist/persistence/sqlite-provider.d.ts +2 -0
  118. package/dist/persistence/sqlite-provider.d.ts.map +1 -1
  119. package/dist/persistence/sqlite-provider.js +8 -5
  120. package/dist/persistence/sqlite-provider.js.map +1 -1
  121. package/dist/planning/evidence-collector.d.ts +13 -1
  122. package/dist/planning/evidence-collector.d.ts.map +1 -1
  123. package/dist/planning/evidence-collector.js +33 -0
  124. package/dist/planning/evidence-collector.js.map +1 -1
  125. package/dist/planning/gap-analysis.d.ts +5 -4
  126. package/dist/planning/gap-analysis.d.ts.map +1 -1
  127. package/dist/planning/gap-analysis.js +7 -341
  128. package/dist/planning/gap-analysis.js.map +1 -1
  129. package/dist/planning/gap-passes.d.ts +19 -0
  130. package/dist/planning/gap-passes.d.ts.map +1 -0
  131. package/dist/planning/gap-passes.js +157 -0
  132. package/dist/planning/gap-passes.js.map +1 -0
  133. package/dist/planning/gap-patterns.d.ts +29 -0
  134. package/dist/planning/gap-patterns.d.ts.map +1 -0
  135. package/dist/planning/gap-patterns.js +129 -0
  136. package/dist/planning/gap-patterns.js.map +1 -0
  137. package/dist/planning/gap-types.d.ts +1 -1
  138. package/dist/planning/gap-types.d.ts.map +1 -1
  139. package/dist/planning/gap-types.js +1 -0
  140. package/dist/planning/gap-types.js.map +1 -1
  141. package/dist/planning/github-projection.d.ts +122 -0
  142. package/dist/planning/github-projection.d.ts.map +1 -0
  143. package/dist/planning/github-projection.js +294 -0
  144. package/dist/planning/github-projection.js.map +1 -0
  145. package/dist/planning/impact-analyzer.d.ts +26 -0
  146. package/dist/planning/impact-analyzer.d.ts.map +1 -0
  147. package/dist/planning/impact-analyzer.js +199 -0
  148. package/dist/planning/impact-analyzer.js.map +1 -0
  149. package/dist/planning/plan-lifecycle.d.ts +136 -0
  150. package/dist/planning/plan-lifecycle.d.ts.map +1 -0
  151. package/dist/planning/plan-lifecycle.js +296 -0
  152. package/dist/planning/plan-lifecycle.js.map +1 -0
  153. package/dist/planning/planner-types.d.ts +202 -0
  154. package/dist/planning/planner-types.d.ts.map +1 -0
  155. package/dist/planning/planner-types.js +6 -0
  156. package/dist/planning/planner-types.js.map +1 -0
  157. package/dist/planning/planner.d.ts +31 -383
  158. package/dist/planning/planner.d.ts.map +1 -1
  159. package/dist/planning/planner.js +154 -878
  160. package/dist/planning/planner.js.map +1 -1
  161. package/dist/planning/rationalization-detector.d.ts +32 -0
  162. package/dist/planning/rationalization-detector.d.ts.map +1 -0
  163. package/dist/planning/rationalization-detector.js +89 -0
  164. package/dist/planning/rationalization-detector.js.map +1 -0
  165. package/dist/planning/reconciliation-engine.d.ts +47 -0
  166. package/dist/planning/reconciliation-engine.d.ts.map +1 -0
  167. package/dist/planning/reconciliation-engine.js +128 -0
  168. package/dist/planning/reconciliation-engine.js.map +1 -0
  169. package/dist/planning/task-verifier.d.ts +85 -0
  170. package/dist/planning/task-verifier.d.ts.map +1 -0
  171. package/dist/planning/task-verifier.js +227 -0
  172. package/dist/planning/task-verifier.js.map +1 -0
  173. package/dist/plugins/types.d.ts +4 -4
  174. package/dist/runtime/admin-ops.d.ts +2 -2
  175. package/dist/runtime/admin-ops.d.ts.map +1 -1
  176. package/dist/runtime/admin-ops.js +44 -17
  177. package/dist/runtime/admin-ops.js.map +1 -1
  178. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  179. package/dist/runtime/admin-setup-ops.js +21 -46
  180. package/dist/runtime/admin-setup-ops.js.map +1 -1
  181. package/dist/runtime/archive-ops.d.ts +10 -0
  182. package/dist/runtime/archive-ops.d.ts.map +1 -0
  183. package/dist/runtime/archive-ops.js +310 -0
  184. package/dist/runtime/archive-ops.js.map +1 -0
  185. package/dist/runtime/capture-ops.d.ts.map +1 -1
  186. package/dist/runtime/capture-ops.js +42 -7
  187. package/dist/runtime/capture-ops.js.map +1 -1
  188. package/dist/runtime/claude-md-helpers.js +1 -1
  189. package/dist/runtime/claude-md-helpers.js.map +1 -1
  190. package/dist/runtime/context-health.d.ts +31 -0
  191. package/dist/runtime/context-health.d.ts.map +1 -0
  192. package/dist/runtime/context-health.js +57 -0
  193. package/dist/runtime/context-health.js.map +1 -0
  194. package/dist/runtime/facades/archive-facade.d.ts +10 -0
  195. package/dist/runtime/facades/archive-facade.d.ts.map +1 -0
  196. package/dist/runtime/facades/archive-facade.js +11 -0
  197. package/dist/runtime/facades/archive-facade.js.map +1 -0
  198. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  199. package/dist/runtime/facades/brain-facade.js +2 -0
  200. package/dist/runtime/facades/brain-facade.js.map +1 -1
  201. package/dist/runtime/facades/chat-facade.d.ts +7 -0
  202. package/dist/runtime/facades/chat-facade.d.ts.map +1 -1
  203. package/dist/runtime/facades/chat-facade.js +15 -800
  204. package/dist/runtime/facades/chat-facade.js.map +1 -1
  205. package/dist/runtime/facades/chat-service-ops.d.ts +9 -0
  206. package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -0
  207. package/dist/runtime/facades/chat-service-ops.js +330 -0
  208. package/dist/runtime/facades/chat-service-ops.js.map +1 -0
  209. package/dist/runtime/facades/chat-session-ops.d.ts +8 -0
  210. package/dist/runtime/facades/chat-session-ops.d.ts.map +1 -0
  211. package/dist/runtime/facades/chat-session-ops.js +136 -0
  212. package/dist/runtime/facades/chat-session-ops.js.map +1 -0
  213. package/dist/runtime/facades/chat-state.d.ts +31 -0
  214. package/dist/runtime/facades/chat-state.d.ts.map +1 -0
  215. package/dist/runtime/facades/chat-state.js +32 -0
  216. package/dist/runtime/facades/chat-state.js.map +1 -0
  217. package/dist/runtime/facades/chat-transport-ops.d.ts +9 -0
  218. package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -0
  219. package/dist/runtime/facades/chat-transport-ops.js +337 -0
  220. package/dist/runtime/facades/chat-transport-ops.js.map +1 -0
  221. package/dist/runtime/facades/control-facade.d.ts.map +1 -1
  222. package/dist/runtime/facades/control-facade.js +4 -1
  223. package/dist/runtime/facades/control-facade.js.map +1 -1
  224. package/dist/runtime/facades/index.d.ts.map +1 -1
  225. package/dist/runtime/facades/index.js +6 -0
  226. package/dist/runtime/facades/index.js.map +1 -1
  227. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  228. package/dist/runtime/facades/memory-facade.js +75 -6
  229. package/dist/runtime/facades/memory-facade.js.map +1 -1
  230. package/dist/runtime/facades/operator-facade.d.ts +8 -0
  231. package/dist/runtime/facades/operator-facade.d.ts.map +1 -0
  232. package/dist/runtime/facades/operator-facade.js +220 -0
  233. package/dist/runtime/facades/operator-facade.js.map +1 -0
  234. package/dist/runtime/facades/orchestrate-facade.js +3 -3
  235. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  236. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  237. package/dist/runtime/facades/plan-facade.js +39 -6
  238. package/dist/runtime/facades/plan-facade.js.map +1 -1
  239. package/dist/runtime/facades/review-facade.d.ts +7 -0
  240. package/dist/runtime/facades/review-facade.d.ts.map +1 -0
  241. package/dist/runtime/facades/review-facade.js +8 -0
  242. package/dist/runtime/facades/review-facade.js.map +1 -0
  243. package/dist/runtime/facades/sync-facade.d.ts +7 -0
  244. package/dist/runtime/facades/sync-facade.d.ts.map +1 -0
  245. package/dist/runtime/facades/sync-facade.js +8 -0
  246. package/dist/runtime/facades/sync-facade.js.map +1 -0
  247. package/dist/runtime/facades/vault-facade.d.ts +4 -1
  248. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  249. package/dist/runtime/facades/vault-facade.js +13 -66
  250. package/dist/runtime/facades/vault-facade.js.map +1 -1
  251. package/dist/runtime/github-integration.d.ts +49 -0
  252. package/dist/runtime/github-integration.d.ts.map +1 -0
  253. package/dist/runtime/github-integration.js +113 -0
  254. package/dist/runtime/github-integration.js.map +1 -0
  255. package/dist/runtime/grading-ops.js +1 -1
  256. package/dist/runtime/grading-ops.js.map +1 -1
  257. package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
  258. package/dist/runtime/memory-extra-ops.js +6 -2
  259. package/dist/runtime/memory-extra-ops.js.map +1 -1
  260. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  261. package/dist/runtime/orchestrate-ops.js +367 -40
  262. package/dist/runtime/orchestrate-ops.js.map +1 -1
  263. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  264. package/dist/runtime/planning-extra-ops.js +69 -4
  265. package/dist/runtime/planning-extra-ops.js.map +1 -1
  266. package/dist/runtime/review-ops.d.ts +10 -0
  267. package/dist/runtime/review-ops.d.ts.map +1 -0
  268. package/dist/runtime/review-ops.js +97 -0
  269. package/dist/runtime/review-ops.js.map +1 -0
  270. package/dist/runtime/runtime.d.ts.map +1 -1
  271. package/dist/runtime/runtime.js +27 -12
  272. package/dist/runtime/runtime.js.map +1 -1
  273. package/dist/runtime/session-briefing.d.ts +3 -0
  274. package/dist/runtime/session-briefing.d.ts.map +1 -1
  275. package/dist/runtime/session-briefing.js +68 -1
  276. package/dist/runtime/session-briefing.js.map +1 -1
  277. package/dist/runtime/sync-ops.d.ts +12 -0
  278. package/dist/runtime/sync-ops.d.ts.map +1 -0
  279. package/dist/runtime/sync-ops.js +288 -0
  280. package/dist/runtime/sync-ops.js.map +1 -0
  281. package/dist/runtime/types.d.ts +10 -4
  282. package/dist/runtime/types.d.ts.map +1 -1
  283. package/dist/runtime/vault-extra-ops.d.ts +5 -4
  284. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  285. package/dist/runtime/vault-extra-ops.js +5 -300
  286. package/dist/runtime/vault-extra-ops.js.map +1 -1
  287. package/dist/runtime/vault-sharing-ops.d.ts +4 -4
  288. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
  289. package/dist/runtime/vault-sharing-ops.js +5 -300
  290. package/dist/runtime/vault-sharing-ops.js.map +1 -1
  291. package/dist/skills/sync-skills.d.ts +27 -0
  292. package/dist/skills/sync-skills.d.ts.map +1 -0
  293. package/dist/skills/sync-skills.js +81 -0
  294. package/dist/skills/sync-skills.js.map +1 -0
  295. package/dist/update-check.d.ts +14 -0
  296. package/dist/update-check.d.ts.map +1 -0
  297. package/dist/update-check.js +96 -0
  298. package/dist/update-check.js.map +1 -0
  299. package/dist/vault/linking.d.ts +10 -12
  300. package/dist/vault/linking.d.ts.map +1 -1
  301. package/dist/vault/linking.js +104 -161
  302. package/dist/vault/linking.js.map +1 -1
  303. package/dist/vault/vault-entries.d.ts +69 -0
  304. package/dist/vault/vault-entries.d.ts.map +1 -0
  305. package/dist/vault/vault-entries.js +257 -0
  306. package/dist/vault/vault-entries.js.map +1 -0
  307. package/dist/vault/vault-interfaces.d.ts +153 -0
  308. package/dist/vault/vault-interfaces.d.ts.map +1 -0
  309. package/dist/vault/vault-interfaces.js +2 -0
  310. package/dist/vault/vault-interfaces.js.map +1 -0
  311. package/dist/vault/vault-maintenance.d.ts +40 -0
  312. package/dist/vault/vault-maintenance.d.ts.map +1 -0
  313. package/dist/vault/vault-maintenance.js +142 -0
  314. package/dist/vault/vault-maintenance.js.map +1 -0
  315. package/dist/vault/vault-markdown-sync.d.ts +22 -0
  316. package/dist/vault/vault-markdown-sync.d.ts.map +1 -0
  317. package/dist/vault/vault-markdown-sync.js +143 -0
  318. package/dist/vault/vault-markdown-sync.js.map +1 -0
  319. package/dist/vault/vault-memories.d.ts +61 -0
  320. package/dist/vault/vault-memories.d.ts.map +1 -0
  321. package/dist/vault/vault-memories.js +240 -0
  322. package/dist/vault/vault-memories.js.map +1 -0
  323. package/dist/vault/vault-schema.d.ts +9 -0
  324. package/dist/vault/vault-schema.d.ts.map +1 -0
  325. package/dist/vault/vault-schema.js +179 -0
  326. package/dist/vault/vault-schema.js.map +1 -0
  327. package/dist/vault/vault.d.ts +29 -81
  328. package/dist/vault/vault.d.ts.map +1 -1
  329. package/dist/vault/vault.js +78 -931
  330. package/dist/vault/vault.js.map +1 -1
  331. package/package.json +1 -1
  332. package/src/agency/agency-manager.test.ts +600 -0
  333. package/src/agency/default-rules.test.ts +228 -0
  334. package/src/{__tests__ → brain}/brain-intelligence.test.ts +37 -14
  335. package/src/{__tests__ → brain}/brain.test.ts +1 -1
  336. package/src/brain/intelligence.ts +196 -15
  337. package/src/brain/learning-radar.ts +22 -1
  338. package/src/{__tests__ → brain}/second-brain-features.test.ts +4 -4
  339. package/src/{__tests__ → brain}/session-lifecycle.test.ts +2 -2
  340. package/src/brain/strength-scorer.ts +404 -0
  341. package/src/capabilities/chain-mapping.test.ts +66 -0
  342. package/src/capabilities/registry.test.ts +369 -0
  343. package/src/chat/agent-loop.test.ts +394 -0
  344. package/src/chat/agent-loop.ts +2 -0
  345. package/src/{__tests__ → chat}/chat-differentiators.test.ts +3 -3
  346. package/src/{__tests__ → chat}/chat-enhanced.test.ts +4 -4
  347. package/src/{__tests__ → chat}/chat-transport.test.ts +6 -6
  348. package/src/chat/mcp-bridge.test.ts +173 -0
  349. package/src/chat/notifications.ts +2 -0
  350. package/src/chat/output-compressor.test.ts +164 -0
  351. package/src/claudemd/compose.test.ts +178 -0
  352. package/src/claudemd/compose.ts +1 -1
  353. package/src/claudemd/inject.test.ts +211 -0
  354. package/src/context/context-engine.test.ts +461 -0
  355. package/src/control/identity-manager.test.ts +305 -0
  356. package/src/control/intent-router.test.ts +360 -0
  357. package/src/control/intent-router.ts +13 -4
  358. package/src/curator/classifier.test.ts +104 -0
  359. package/src/curator/contradiction-detector.test.ts +180 -0
  360. package/src/curator/contradiction-detector.ts +87 -0
  361. package/src/{__tests__ → curator}/curator-pipeline-e2e.test.ts +10 -10
  362. package/src/{__tests__ → curator}/curator.test.ts +77 -1
  363. package/src/curator/curator.ts +115 -777
  364. package/src/curator/duplicate-detector.test.ts +183 -0
  365. package/src/curator/duplicate-detector.ts +103 -0
  366. package/src/curator/health-audit.ts +126 -0
  367. package/src/curator/metadata-enricher.ts +84 -0
  368. package/src/curator/quality-gate.test.ts +135 -0
  369. package/src/curator/schema.ts +65 -0
  370. package/src/curator/tag-manager.test.ts +165 -0
  371. package/src/curator/tag-manager.ts +109 -0
  372. package/src/domain-packs/inject-rules.test.ts +117 -0
  373. package/src/domain-packs/knowledge-installer.test.ts +171 -0
  374. package/src/domain-packs/loader.test.ts +86 -0
  375. package/src/domain-packs/pack-runtime.test.ts +140 -0
  376. package/src/domain-packs/skills-installer.test.ts +135 -0
  377. package/src/domain-packs/token-resolver.test.ts +150 -0
  378. package/src/domain-packs/types.test.ts +130 -0
  379. package/src/enforcement/adapters/claude-code.test.ts +216 -0
  380. package/src/enforcement/registry.test.ts +264 -0
  381. package/src/engine/bin/soleri-engine.ts +28 -4
  382. package/src/engine/core-ops.test.ts +254 -0
  383. package/src/engine/core-ops.ts +25 -8
  384. package/src/engine/module-manifest.test.ts +124 -0
  385. package/src/engine/module-manifest.ts +22 -2
  386. package/src/engine/register-engine.test.ts +230 -0
  387. package/src/engine/register-engine.ts +26 -2
  388. package/src/errors/classify.test.ts +199 -0
  389. package/src/errors/retry.test.ts +156 -0
  390. package/src/errors/retry.ts +2 -0
  391. package/src/errors/types.test.ts +108 -0
  392. package/src/events/event-bus.test.ts +149 -0
  393. package/src/extensions/middleware.test.ts +234 -0
  394. package/src/facades/facade-factory.test.ts +424 -0
  395. package/src/flows/chain-runner.test.ts +273 -0
  396. package/src/flows/context-router.test.ts +52 -0
  397. package/src/flows/dispatch-registry.test.ts +128 -0
  398. package/src/flows/epilogue.test.ts +107 -0
  399. package/src/flows/executor.test.ts +263 -0
  400. package/src/flows/gate-evaluator.test.ts +194 -0
  401. package/src/flows/gate-evaluator.ts +25 -0
  402. package/src/flows/types.ts +4 -0
  403. package/src/governance/governance.test.ts +726 -0
  404. package/src/health/health-registry.test.ts +186 -0
  405. package/src/health/vault-integrity.test.ts +110 -0
  406. package/src/index.ts +92 -0
  407. package/src/intake/content-classifier.test.ts +209 -0
  408. package/src/intake/dedup-gate.test.ts +131 -0
  409. package/src/intake/intake-pipeline.test.ts +506 -0
  410. package/src/intake/intake-pipeline.ts +1 -0
  411. package/src/intake/text-ingester.test.ts +194 -0
  412. package/src/intake/text-ingester.ts +2 -0
  413. package/src/llm/key-pool.test.ts +236 -0
  414. package/src/llm/key-pool.ts +3 -4
  415. package/src/llm/llm-client.test.ts +345 -0
  416. package/src/llm/oauth-discovery.test.ts +180 -0
  417. package/src/llm/utils.test.ts +327 -0
  418. package/src/llm/utils.ts +2 -0
  419. package/src/{__tests__ → logging}/logger.test.ts +41 -62
  420. package/src/loop/loop-manager.test.ts +519 -0
  421. package/src/migrations/migration-runner.edge-cases.test.ts +319 -0
  422. package/src/migrations/migration-runner.test-helpers.ts +64 -0
  423. package/src/migrations/migration-runner.test.ts +385 -0
  424. package/src/operator/auto-signal-pipeline.test.ts +207 -0
  425. package/src/operator/operator-profile-extended.test.ts +320 -0
  426. package/src/operator/operator-profile.test.ts +314 -0
  427. package/src/operator/operator-profile.ts +469 -0
  428. package/src/operator/operator-signals-extended.test.ts +245 -0
  429. package/src/operator/operator-signals.test.ts +281 -0
  430. package/src/operator/operator-signals.ts +261 -0
  431. package/src/operator/operator-types.ts +444 -0
  432. package/src/operator/prompts/hook-precompact-operator-dispatch.md +94 -0
  433. package/src/operator/prompts/subagent-soft-signal-extractor.md +125 -0
  434. package/src/operator/prompts/subagent-synthesis-cognition.md +181 -0
  435. package/src/operator/prompts/subagent-synthesis-communication.md +140 -0
  436. package/src/operator/prompts/subagent-synthesis-technical.md +160 -0
  437. package/src/operator/prompts/subagent-synthesis-trust.md +143 -0
  438. package/src/{__tests__ → packs}/pack-lockfile.test.ts +3 -3
  439. package/src/{__tests__ → packs}/pack-system.test.ts +2 -2
  440. package/src/paths.ts +115 -0
  441. package/src/persistence/index.ts +1 -1
  442. package/src/persistence/sqlite-provider.test.ts +540 -0
  443. package/src/persistence/sqlite-provider.ts +8 -5
  444. package/src/persona/defaults.test.ts +59 -0
  445. package/src/persona/loader.test.ts +67 -0
  446. package/src/persona/prompt-generator.test.ts +127 -0
  447. package/src/planning/evidence-collector.test.ts +406 -0
  448. package/src/planning/evidence-collector.ts +50 -0
  449. package/src/planning/gap-analysis-alternatives.test.ts +169 -0
  450. package/src/planning/gap-analysis.ts +21 -636
  451. package/src/planning/gap-passes.test.ts +372 -0
  452. package/src/planning/gap-passes.ts +298 -0
  453. package/src/planning/gap-patterns.test.ts +320 -0
  454. package/src/planning/gap-patterns.ts +234 -0
  455. package/src/planning/gap-types.ts +4 -1
  456. package/src/planning/github-projection.test.ts +177 -0
  457. package/src/planning/github-projection.ts +425 -0
  458. package/src/planning/impact-analyzer.test.ts +180 -0
  459. package/src/planning/impact-analyzer.ts +264 -0
  460. package/src/planning/plan-lifecycle.test.ts +312 -0
  461. package/src/planning/plan-lifecycle.ts +346 -0
  462. package/src/planning/planner-types.ts +215 -0
  463. package/src/{__tests__ → planning}/planner.test.ts +169 -15
  464. package/src/planning/planner.ts +197 -1228
  465. package/src/planning/rationalization-detector.test.ts +171 -0
  466. package/src/planning/rationalization-detector.ts +138 -0
  467. package/src/planning/reconciliation-engine.test.ts +141 -0
  468. package/src/planning/reconciliation-engine.ts +162 -0
  469. package/src/planning/task-verifier.test.ts +235 -0
  470. package/src/planning/task-verifier.ts +303 -0
  471. package/src/planning/verification-protocol.test.ts +201 -0
  472. package/src/playbooks/generic/generic-playbooks.test.ts +438 -0
  473. package/src/playbooks/index.test.ts +77 -0
  474. package/src/playbooks/playbook-executor.test.ts +255 -0
  475. package/src/playbooks/playbook-registry.test.ts +232 -0
  476. package/src/playbooks/playbook-seeder.test.ts +153 -0
  477. package/src/plugins/plugin-loader.test.ts +212 -0
  478. package/src/plugins/plugin-registry.test.ts +272 -0
  479. package/src/project/project-registry.test.ts +428 -0
  480. package/src/prompts/parser.test.ts +100 -0
  481. package/src/prompts/template-manager.test.ts +109 -0
  482. package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
  483. package/src/queue/job-queue.test.ts +331 -0
  484. package/src/queue/pipeline-runner.test.ts +209 -0
  485. package/src/runtime/admin-extra-ops.test.ts +527 -0
  486. package/src/runtime/admin-ops.test.ts +257 -0
  487. package/src/runtime/admin-ops.ts +45 -17
  488. package/src/runtime/admin-setup-ops.test.ts +328 -0
  489. package/src/runtime/admin-setup-ops.ts +20 -43
  490. package/src/runtime/archive-ops.test.ts +269 -0
  491. package/src/runtime/archive-ops.ts +347 -0
  492. package/src/runtime/capture-ops.test.ts +433 -0
  493. package/src/runtime/capture-ops.ts +50 -8
  494. package/src/runtime/chain-ops.test.ts +149 -0
  495. package/src/runtime/claude-md-helpers.test.ts +191 -0
  496. package/src/runtime/claude-md-helpers.ts +1 -1
  497. package/src/runtime/context-health.test.ts +78 -0
  498. package/src/runtime/context-health.ts +85 -0
  499. package/src/runtime/curator-extra-ops.test.ts +202 -0
  500. package/src/runtime/deprecation.test.ts +98 -0
  501. package/src/runtime/domain-ops.test.ts +268 -0
  502. package/src/runtime/facades/admin-facade.test.ts +333 -0
  503. package/src/runtime/facades/agency-facade.test.ts +278 -0
  504. package/src/runtime/facades/archive-facade.test.ts +294 -0
  505. package/src/runtime/facades/archive-facade.ts +14 -0
  506. package/src/runtime/facades/brain-facade.test.ts +714 -0
  507. package/src/runtime/facades/brain-facade.ts +2 -0
  508. package/src/runtime/facades/chat-facade.test.ts +166 -0
  509. package/src/runtime/facades/chat-facade.ts +15 -906
  510. package/src/runtime/facades/chat-service-ops.test.ts +276 -0
  511. package/src/runtime/facades/chat-service-ops.ts +374 -0
  512. package/src/runtime/facades/chat-session-ops.test.ts +197 -0
  513. package/src/runtime/facades/chat-session-ops.ts +146 -0
  514. package/src/runtime/facades/chat-state.ts +60 -0
  515. package/src/runtime/facades/chat-transport-ops.test.ts +269 -0
  516. package/src/runtime/facades/chat-transport-ops.ts +380 -0
  517. package/src/runtime/facades/context-facade.test.ts +108 -0
  518. package/src/runtime/facades/control-facade.test.ts +436 -0
  519. package/src/runtime/facades/control-facade.ts +6 -1
  520. package/src/runtime/facades/curator-facade.test.ts +303 -0
  521. package/src/runtime/facades/index.ts +6 -0
  522. package/src/runtime/facades/loop-facade.test.ts +245 -0
  523. package/src/runtime/facades/memory-facade.test.ts +269 -0
  524. package/src/runtime/facades/memory-facade.ts +78 -6
  525. package/src/runtime/facades/operator-facade.test.ts +208 -0
  526. package/src/runtime/facades/operator-facade.ts +236 -0
  527. package/src/runtime/facades/orchestrate-facade.test.ts +185 -0
  528. package/src/runtime/facades/orchestrate-facade.ts +3 -3
  529. package/src/runtime/facades/plan-facade.test.ts +266 -0
  530. package/src/runtime/facades/plan-facade.ts +42 -6
  531. package/src/runtime/facades/review-facade.test.ts +82 -0
  532. package/src/runtime/facades/review-facade.ts +11 -0
  533. package/src/runtime/facades/sync-facade.test.ts +113 -0
  534. package/src/runtime/facades/sync-facade.ts +11 -0
  535. package/src/runtime/facades/vault-facade.test.ts +631 -0
  536. package/src/runtime/facades/vault-facade.ts +15 -70
  537. package/src/runtime/feature-flags.test.ts +140 -0
  538. package/src/runtime/github-integration.test.ts +89 -0
  539. package/src/runtime/github-integration.ts +159 -0
  540. package/src/runtime/grading-ops.test.ts +141 -0
  541. package/src/runtime/grading-ops.ts +1 -1
  542. package/src/runtime/intake-ops.test.ts +208 -0
  543. package/src/runtime/loop-ops.test.ts +238 -0
  544. package/src/runtime/memory-cross-project-ops.test.ts +177 -0
  545. package/src/runtime/memory-extra-ops.test.ts +453 -0
  546. package/src/runtime/memory-extra-ops.ts +6 -2
  547. package/src/runtime/orchestrate-ops.test.ts +302 -0
  548. package/src/runtime/orchestrate-ops.ts +435 -46
  549. package/src/runtime/pack-ops.test.ts +158 -0
  550. package/src/runtime/planning-extra-ops.test.ts +583 -0
  551. package/src/runtime/planning-extra-ops.ts +72 -4
  552. package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
  553. package/src/runtime/playbook-ops.test.ts +262 -0
  554. package/src/runtime/plugin-ops.test.ts +201 -0
  555. package/src/runtime/project-ops.test.ts +235 -0
  556. package/src/runtime/review-ops.test.ts +142 -0
  557. package/src/runtime/review-ops.ts +99 -0
  558. package/src/runtime/runtime.test.ts +363 -0
  559. package/src/runtime/runtime.ts +39 -12
  560. package/src/runtime/session-briefing.test.ts +302 -0
  561. package/src/runtime/session-briefing.ts +80 -1
  562. package/src/runtime/sync-ops.test.ts +221 -0
  563. package/src/runtime/sync-ops.ts +325 -0
  564. package/src/runtime/telemetry-ops.test.ts +132 -0
  565. package/src/runtime/types.ts +10 -4
  566. package/src/runtime/vault-extra-ops.test.ts +246 -0
  567. package/src/runtime/vault-extra-ops.ts +5 -332
  568. package/src/runtime/vault-linking-ops.test.ts +237 -0
  569. package/src/runtime/vault-sharing-ops.test.ts +130 -0
  570. package/src/runtime/vault-sharing-ops.ts +5 -329
  571. package/src/skills/sync-skills.ts +108 -0
  572. package/src/streams/normalize.test.ts +95 -0
  573. package/src/streams/replayable-stream.test.ts +166 -0
  574. package/src/telemetry/telemetry.test.ts +143 -0
  575. package/src/transport/http-server.test.ts +394 -0
  576. package/src/transport/lsp-server.test.ts +458 -0
  577. package/src/transport/rate-limiter.test.ts +126 -0
  578. package/src/transport/session-manager.test.ts +133 -0
  579. package/src/transport/token-auth.test.ts +136 -0
  580. package/src/transport/ws-server.test.ts +294 -0
  581. package/src/update-check.ts +111 -0
  582. package/src/vault/__tests__/vault-characterization.test.ts +168 -0
  583. package/src/vault/content-hash.test.ts +78 -0
  584. package/src/vault/git-vault-sync.test.ts +234 -0
  585. package/src/vault/knowledge-review.test.ts +269 -0
  586. package/src/vault/linking.test.ts +358 -0
  587. package/src/vault/linking.ts +149 -183
  588. package/src/vault/obsidian-sync.test.ts +342 -0
  589. package/src/vault/playbook.test.ts +152 -0
  590. package/src/vault/scope-detector.test.ts +187 -0
  591. package/src/vault/vault-branching.test.ts +250 -0
  592. package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
  593. package/src/vault/vault-entries.ts +282 -0
  594. package/src/vault/vault-interfaces.ts +56 -0
  595. package/src/vault/vault-maintenance.ts +205 -0
  596. package/src/vault/vault-manager.test.ts +206 -0
  597. package/src/vault/vault-markdown-sync.test.ts +203 -0
  598. package/src/vault/vault-markdown-sync.ts +160 -0
  599. package/src/vault/vault-memories.ts +339 -0
  600. package/src/{__tests__ → vault}/vault-scaling.test.ts +1 -1
  601. package/src/vault/vault-schema.ts +181 -0
  602. package/src/{__tests__ → vault}/vault-sharing.test.ts +4 -4
  603. package/src/{__tests__ → vault}/vault.test.ts +2 -2
  604. package/src/vault/vault.ts +89 -1171
  605. package/dist/cognee/client.d.ts +0 -43
  606. package/dist/cognee/client.d.ts.map +0 -1
  607. package/dist/cognee/client.js +0 -375
  608. package/dist/cognee/client.js.map +0 -1
  609. package/dist/cognee/sync-manager.d.ts +0 -153
  610. package/dist/cognee/sync-manager.d.ts.map +0 -1
  611. package/dist/cognee/sync-manager.js +0 -390
  612. package/dist/cognee/sync-manager.js.map +0 -1
  613. package/dist/cognee/types.d.ts +0 -62
  614. package/dist/cognee/types.d.ts.map +0 -1
  615. package/dist/cognee/types.js +0 -3
  616. package/dist/cognee/types.js.map +0 -1
  617. package/dist/governance/index.d.ts +0 -3
  618. package/dist/governance/index.d.ts.map +0 -1
  619. package/dist/governance/index.js +0 -2
  620. package/dist/governance/index.js.map +0 -1
  621. package/dist/health/doctor-checks.d.ts +0 -15
  622. package/dist/health/doctor-checks.d.ts.map +0 -1
  623. package/dist/health/doctor-checks.js +0 -98
  624. package/dist/health/doctor-checks.js.map +0 -1
  625. package/dist/persistence/postgres-provider.d.ts +0 -81
  626. package/dist/persistence/postgres-provider.d.ts.map +0 -1
  627. package/dist/persistence/postgres-provider.js +0 -256
  628. package/dist/persistence/postgres-provider.js.map +0 -1
  629. package/dist/runtime/cognee-sync-ops.d.ts +0 -12
  630. package/dist/runtime/cognee-sync-ops.d.ts.map +0 -1
  631. package/dist/runtime/cognee-sync-ops.js +0 -93
  632. package/dist/runtime/cognee-sync-ops.js.map +0 -1
  633. package/dist/runtime/core-ops.d.ts +0 -23
  634. package/dist/runtime/core-ops.d.ts.map +0 -1
  635. package/dist/runtime/core-ops.js +0 -1296
  636. package/dist/runtime/core-ops.js.map +0 -1
  637. package/dist/runtime/facades/cognee-facade.d.ts +0 -8
  638. package/dist/runtime/facades/cognee-facade.d.ts.map +0 -1
  639. package/dist/runtime/facades/cognee-facade.js +0 -156
  640. package/dist/runtime/facades/cognee-facade.js.map +0 -1
  641. package/src/__tests__/admin-extra-ops.test.ts +0 -484
  642. package/src/__tests__/admin-ops.test.ts +0 -268
  643. package/src/__tests__/admin-setup-ops.test.ts +0 -355
  644. package/src/__tests__/agency-manager.test.ts +0 -374
  645. package/src/__tests__/agent-loop.test.ts +0 -256
  646. package/src/__tests__/capture-ops.test.ts +0 -784
  647. package/src/__tests__/claudemd.test.ts +0 -282
  648. package/src/__tests__/content-hash.test.ts +0 -60
  649. package/src/__tests__/context-engine.test.ts +0 -251
  650. package/src/__tests__/core-ops.test.ts +0 -550
  651. package/src/__tests__/curator-extra-ops.test.ts +0 -383
  652. package/src/__tests__/deprecation.test.ts +0 -78
  653. package/src/__tests__/domain-ops.test.ts +0 -226
  654. package/src/__tests__/domain-packs.test.ts +0 -421
  655. package/src/__tests__/enforcement.test.ts +0 -153
  656. package/src/__tests__/errors.test.ts +0 -388
  657. package/src/__tests__/extensions.test.ts +0 -233
  658. package/src/__tests__/facade-factory.test.ts +0 -271
  659. package/src/__tests__/feature-flags.test.ts +0 -137
  660. package/src/__tests__/flows.test.ts +0 -604
  661. package/src/__tests__/git-vault-sync.test.ts +0 -230
  662. package/src/__tests__/governance.test.ts +0 -522
  663. package/src/__tests__/grading-ops.test.ts +0 -361
  664. package/src/__tests__/health-registry.test.ts +0 -173
  665. package/src/__tests__/identity-manager.test.ts +0 -243
  666. package/src/__tests__/intake-pipeline.test.ts +0 -162
  667. package/src/__tests__/intent-router.test.ts +0 -222
  668. package/src/__tests__/knowledge-review.test.ts +0 -104
  669. package/src/__tests__/llm-client.test.ts +0 -69
  670. package/src/__tests__/llm.test.ts +0 -556
  671. package/src/__tests__/loader.test.ts +0 -176
  672. package/src/__tests__/loop-ops.test.ts +0 -469
  673. package/src/__tests__/lsp-transport.test.ts +0 -442
  674. package/src/__tests__/memory-cross-project-ops.test.ts +0 -248
  675. package/src/__tests__/memory-extra-ops.test.ts +0 -352
  676. package/src/__tests__/migration-runner.test.ts +0 -170
  677. package/src/__tests__/module-manifest-drift.test.ts +0 -59
  678. package/src/__tests__/normalize.test.ts +0 -85
  679. package/src/__tests__/obsidian-sync.test.ts +0 -354
  680. package/src/__tests__/orchestrate-ops.test.ts +0 -289
  681. package/src/__tests__/pack-ops.test.ts +0 -146
  682. package/src/__tests__/persistence.test.ts +0 -291
  683. package/src/__tests__/planning-extra-ops.test.ts +0 -706
  684. package/src/__tests__/playbook-executor.test.ts +0 -249
  685. package/src/__tests__/playbook-registry.test.ts +0 -326
  686. package/src/__tests__/playbook-seeder.test.ts +0 -163
  687. package/src/__tests__/playbook.test.ts +0 -389
  688. package/src/__tests__/plugin-ops.test.ts +0 -411
  689. package/src/__tests__/plugin-system.test.ts +0 -509
  690. package/src/__tests__/project-ops.test.ts +0 -381
  691. package/src/__tests__/replayable-stream.test.ts +0 -177
  692. package/src/__tests__/runtime.test.ts +0 -95
  693. package/src/__tests__/scope-detector.test.ts +0 -121
  694. package/src/__tests__/template-manager.test.ts +0 -222
  695. package/src/__tests__/token-resolver.test.ts +0 -79
  696. package/src/__tests__/transport.test.ts +0 -758
  697. package/src/__tests__/vault-branching.test.ts +0 -274
  698. package/src/__tests__/vault-extra-ops.test.ts +0 -482
  699. package/src/__tests__/vault-integrity.test.ts +0 -71
  700. package/src/__tests__/vault-manager.test.ts +0 -238
  701. package/src/__tests__/ws-transport.test.ts +0 -479
@@ -0,0 +1,714 @@
1
+ /**
2
+ * Colocated contract tests for brain-facade.ts.
3
+ * Tests every op handler — valid params, error paths, edge cases.
4
+ * All runtime dependencies are mocked.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
8
+ import { createBrainFacadeOps } from './brain-facade.js';
9
+ import { captureOps, executeOp } from '../../engine/test-helpers.js';
10
+ import type { CapturedOp } from '../../engine/test-helpers.js';
11
+ import type { AgentRuntime } from '../types.js';
12
+
13
+ // ─── Mock factories ──────────────────────────────────────────────────
14
+
15
+ function makeMockBrain() {
16
+ return {
17
+ recordFeedback: vi.fn().mockReturnValue({ id: 'fb-1', recorded: true }),
18
+ getFeedbackStats: vi.fn().mockReturnValue({ total: 5, accepted: 3, dismissed: 2 }),
19
+ rebuildVocabulary: vi.fn(),
20
+ getVocabularySize: vi.fn().mockReturnValue(42),
21
+ getStats: vi.fn().mockReturnValue({ vocabularySize: 42, feedbackCount: 5 }),
22
+ getDecayReport: vi.fn().mockResolvedValue([
23
+ { id: 'e1', title: 'Test', decayScore: 0.8, status: 'active' },
24
+ ]),
25
+ intelligentSearch: vi.fn().mockResolvedValue([]),
26
+ scanSearch: vi.fn().mockResolvedValue([]),
27
+ enrichAndCapture: vi.fn().mockReturnValue({ captured: true, id: 'cap-1', autoTags: [] }),
28
+ };
29
+ }
30
+
31
+ function makeMockBrainIntelligence() {
32
+ return {
33
+ getStats: vi.fn().mockReturnValue({ pipelineRuns: 3 }),
34
+ getSessionContext: vi.fn().mockReturnValue({ sessions: [], toolUsage: {}, fileChanges: {} }),
35
+ getStrengths: vi.fn().mockReturnValue([{ name: 'test-pattern', strength: 80 }]),
36
+ getGlobalPatterns: vi.fn().mockReturnValue([{ name: 'cross-domain-1' }]),
37
+ recommend: vi.fn().mockReturnValue([{ name: 'recommended-1', score: 0.9 }]),
38
+ buildIntelligence: vi.fn().mockReturnValue({ success: true }),
39
+ exportData: vi.fn().mockReturnValue({ strengths: [], sessions: [], proposals: [] }),
40
+ importData: vi.fn().mockReturnValue({ imported: { strengths: 0, sessions: 0, proposals: 0 } }),
41
+ extractKnowledge: vi.fn().mockReturnValue({ proposals: [], count: 0 }),
42
+ archiveSessions: vi.fn().mockReturnValue({ archived: 2 }),
43
+ promoteProposals: vi.fn().mockReturnValue({ promoted: 1 }),
44
+ lifecycle: vi.fn().mockReturnValue({ sessionId: 'sess-1', action: 'start' }),
45
+ listSessions: vi.fn().mockReturnValue([{ id: 'sess-1', domain: 'test' }]),
46
+ getSessionById: vi.fn().mockReturnValue({ id: 'sess-1', domain: 'test' }),
47
+ computeSessionQuality: vi.fn().mockReturnValue({ score: 75 }),
48
+ replaySession: vi.fn().mockReturnValue({ session: {}, quality: 75 }),
49
+ resetExtracted: vi.fn().mockReturnValue({ reset: 1 }),
50
+ maybeAutoBuildOnFeedback: vi.fn(),
51
+ };
52
+ }
53
+
54
+ function makeMockLlmClient() {
55
+ return {
56
+ isAvailable: vi.fn().mockReturnValue({ openai: true, anthropic: false }),
57
+ getRoutes: vi.fn().mockReturnValue({ enrichment: 'openai' }),
58
+ };
59
+ }
60
+
61
+ function makeMockKeyPool() {
62
+ return {
63
+ openai: { hasKeys: true, getStatus: vi.fn().mockReturnValue({ active: 1, total: 2 }) },
64
+ anthropic: { hasKeys: false, getStatus: vi.fn() },
65
+ };
66
+ }
67
+
68
+ function makeMockLearningRadar() {
69
+ return {
70
+ analyze: vi.fn().mockReturnValue({ action: 'queued', candidateId: 1 }),
71
+ getCandidates: vi.fn().mockReturnValue([{ id: 1, title: 'test' }]),
72
+ approve: vi.fn().mockReturnValue({ approved: true }),
73
+ dismiss: vi.fn().mockReturnValue({ dismissed: true }),
74
+ flush: vi.fn().mockReturnValue({ captured: 2, skipped: 1 }),
75
+ getStats: vi.fn().mockReturnValue({ analyzed: 10, captured: 5, queued: 2 }),
76
+ };
77
+ }
78
+
79
+ function makeMockKnowledgeSynthesizer() {
80
+ return {
81
+ synthesize: vi.fn().mockResolvedValue({
82
+ content: 'Synthesized output',
83
+ format: 'brief',
84
+ sources: [],
85
+ coverageScore: 0.8,
86
+ }),
87
+ };
88
+ }
89
+
90
+ function makeMockGovernance() {
91
+ return {
92
+ evaluateCapture: vi.fn().mockReturnValue({ action: 'capture' }),
93
+ };
94
+ }
95
+
96
+ function makeRuntime(overrides: Partial<Record<string, unknown>> = {}): AgentRuntime {
97
+ return {
98
+ brain: makeMockBrain(),
99
+ brainIntelligence: makeMockBrainIntelligence(),
100
+ llmClient: makeMockLlmClient(),
101
+ keyPool: makeMockKeyPool(),
102
+ governance: makeMockGovernance(),
103
+ learningRadar: makeMockLearningRadar(),
104
+ knowledgeSynthesizer: makeMockKnowledgeSynthesizer(),
105
+ ...overrides,
106
+ } as unknown as AgentRuntime;
107
+ }
108
+
109
+ // ─── Tests ────────────────────────────────────────────────────────────
110
+
111
+ describe('brain-facade', () => {
112
+ let runtime: AgentRuntime;
113
+ let ops: Map<string, CapturedOp>;
114
+
115
+ beforeEach(() => {
116
+ runtime = makeRuntime();
117
+ ops = captureOps(createBrainFacadeOps(runtime));
118
+ });
119
+
120
+ // ─── Registration ─────────────────────────────────────────────────
121
+
122
+ it('registers all 30 ops', () => {
123
+ expect(ops.size).toBe(30);
124
+ });
125
+
126
+ it('includes all expected op names', () => {
127
+ const expected = [
128
+ 'record_feedback', 'brain_feedback', 'brain_feedback_stats',
129
+ 'rebuild_vocabulary', 'brain_stats', 'brain_decay_report',
130
+ 'llm_status', 'brain_session_context', 'brain_strengths',
131
+ 'brain_global_patterns', 'brain_recommend', 'brain_build_intelligence',
132
+ 'brain_export', 'brain_import', 'brain_extract_knowledge',
133
+ 'brain_archive_sessions', 'brain_promote_proposals', 'brain_lifecycle',
134
+ 'session_list', 'session_get', 'session_quality', 'session_replay',
135
+ 'brain_reset_extracted', 'radar_analyze', 'radar_candidates',
136
+ 'radar_approve', 'radar_dismiss', 'radar_flush', 'radar_stats',
137
+ 'synthesize',
138
+ ];
139
+ for (const name of expected) {
140
+ expect(ops.has(name), `missing op: ${name}`).toBe(true);
141
+ }
142
+ });
143
+
144
+ // ─── Auth levels ─────────────────────────────────────────────────
145
+
146
+ it('has correct auth levels for read ops', () => {
147
+ const readOps = [
148
+ 'brain_feedback_stats', 'brain_stats', 'brain_decay_report',
149
+ 'llm_status', 'brain_session_context', 'brain_strengths',
150
+ 'brain_global_patterns', 'brain_recommend', 'brain_export',
151
+ 'session_list', 'session_get', 'session_quality', 'session_replay',
152
+ 'radar_candidates', 'radar_stats', 'synthesize',
153
+ ];
154
+ for (const name of readOps) {
155
+ expect(ops.get(name)!.auth, `${name} should be read`).toBe('read');
156
+ }
157
+ });
158
+
159
+ it('has correct auth levels for write ops', () => {
160
+ const writeOps = [
161
+ 'record_feedback', 'brain_feedback', 'rebuild_vocabulary',
162
+ 'brain_build_intelligence', 'brain_import', 'brain_extract_knowledge',
163
+ 'brain_archive_sessions', 'brain_promote_proposals', 'brain_lifecycle',
164
+ 'brain_reset_extracted', 'radar_analyze', 'radar_approve',
165
+ 'radar_dismiss', 'radar_flush',
166
+ ];
167
+ for (const name of writeOps) {
168
+ expect(ops.get(name)!.auth, `${name} should be write`).toBe('write');
169
+ }
170
+ });
171
+
172
+ // ─── record_feedback ───────────────────────────────────────────────
173
+
174
+ describe('record_feedback', () => {
175
+ it('records feedback and returns confirmation', async () => {
176
+ const result = await executeOp(ops, 'record_feedback', {
177
+ query: 'test query',
178
+ entryId: 'e-1',
179
+ action: 'accepted',
180
+ });
181
+ expect(result.success).toBe(true);
182
+ const data = result.data as { recorded: boolean; query: string; entryId: string; action: string };
183
+ expect(data.recorded).toBe(true);
184
+ expect(data.query).toBe('test query');
185
+ expect(data.entryId).toBe('e-1');
186
+ expect(data.action).toBe('accepted');
187
+ });
188
+
189
+ it('calls brain.recordFeedback with positional args', async () => {
190
+ await executeOp(ops, 'record_feedback', {
191
+ query: 'q', entryId: 'e', action: 'dismissed',
192
+ });
193
+ const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
194
+ expect(brain.recordFeedback).toHaveBeenCalledWith('q', 'e', 'dismissed');
195
+ });
196
+
197
+ it('rejects invalid action enum', async () => {
198
+ const result = await executeOp(ops, 'record_feedback', {
199
+ query: 'q', entryId: 'e', action: 'invalid',
200
+ });
201
+ expect(result.success).toBe(false);
202
+ expect(result.error).toContain('Invalid params');
203
+ });
204
+ });
205
+
206
+ // ─── brain_feedback ────────────────────────────────────────────────
207
+
208
+ describe('brain_feedback', () => {
209
+ it('records enhanced feedback with all fields', async () => {
210
+ const result = await executeOp(ops, 'brain_feedback', {
211
+ query: 'design tokens', entryId: 'e-2', action: 'modified',
212
+ source: 'search', confidence: 0.9, duration: 1200,
213
+ context: '{}', reason: 'too verbose',
214
+ });
215
+ expect(result.success).toBe(true);
216
+ const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
217
+ expect(brain.recordFeedback).toHaveBeenCalledWith({
218
+ query: 'design tokens', entryId: 'e-2', action: 'modified',
219
+ source: 'search', confidence: 0.9, duration: 1200,
220
+ context: '{}', reason: 'too verbose',
221
+ });
222
+ });
223
+
224
+ it('works with minimal required fields', async () => {
225
+ const result = await executeOp(ops, 'brain_feedback', {
226
+ query: 'q', entryId: 'e', action: 'failed',
227
+ });
228
+ expect(result.success).toBe(true);
229
+ });
230
+
231
+ it('accepts all 4 action types', async () => {
232
+ for (const action of ['accepted', 'dismissed', 'modified', 'failed']) {
233
+ const result = await executeOp(ops, 'brain_feedback', {
234
+ query: 'q', entryId: 'e', action,
235
+ });
236
+ expect(result.success, `action ${action} should succeed`).toBe(true);
237
+ }
238
+ });
239
+ });
240
+
241
+ // ─── brain_feedback_stats ──────────────────────────────────────────
242
+
243
+ describe('brain_feedback_stats', () => {
244
+ it('returns feedback stats', async () => {
245
+ const result = await executeOp(ops, 'brain_feedback_stats', {});
246
+ expect(result.success).toBe(true);
247
+ const data = result.data as { total: number; accepted: number };
248
+ expect(data.total).toBe(5);
249
+ expect(data.accepted).toBe(3);
250
+ });
251
+ });
252
+
253
+ // ─── rebuild_vocabulary ────────────────────────────────────────────
254
+
255
+ describe('rebuild_vocabulary', () => {
256
+ it('rebuilds and returns size', async () => {
257
+ const result = await executeOp(ops, 'rebuild_vocabulary', {});
258
+ expect(result.success).toBe(true);
259
+ const data = result.data as { rebuilt: boolean; vocabularySize: number };
260
+ expect(data.rebuilt).toBe(true);
261
+ expect(data.vocabularySize).toBe(42);
262
+ });
263
+
264
+ it('calls brain.rebuildVocabulary', async () => {
265
+ await executeOp(ops, 'rebuild_vocabulary', {});
266
+ const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
267
+ expect(brain.rebuildVocabulary).toHaveBeenCalledOnce();
268
+ });
269
+ });
270
+
271
+ // ─── brain_stats ───────────────────────────────────────────────────
272
+
273
+ describe('brain_stats', () => {
274
+ it('merges brain and intelligence stats', async () => {
275
+ const result = await executeOp(ops, 'brain_stats', {});
276
+ expect(result.success).toBe(true);
277
+ const data = result.data as { vocabularySize: number; intelligence: { pipelineRuns: number } };
278
+ expect(data.vocabularySize).toBe(42);
279
+ expect(data.intelligence.pipelineRuns).toBe(3);
280
+ });
281
+ });
282
+
283
+ // ─── brain_decay_report ────────────────────────────────────────────
284
+
285
+ describe('brain_decay_report', () => {
286
+ it('returns decay report with defaults', async () => {
287
+ const result = await executeOp(ops, 'brain_decay_report', { query: 'test' });
288
+ expect(result.success).toBe(true);
289
+ const data = result.data as { results: unknown[]; count: number };
290
+ expect(data.count).toBe(1);
291
+ const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
292
+ expect(brain.getDecayReport).toHaveBeenCalledWith('test', 10);
293
+ });
294
+
295
+ it('passes custom limit', async () => {
296
+ await executeOp(ops, 'brain_decay_report', { query: 'test', limit: 5 });
297
+ const brain = runtime.brain as ReturnType<typeof makeMockBrain>;
298
+ expect(brain.getDecayReport).toHaveBeenCalledWith('test', 5);
299
+ });
300
+ });
301
+
302
+ // ─── llm_status ────────────────────────────────────────────────────
303
+
304
+ describe('llm_status', () => {
305
+ it('returns provider availability and routes', async () => {
306
+ const result = await executeOp(ops, 'llm_status', {});
307
+ expect(result.success).toBe(true);
308
+ const data = result.data as {
309
+ providers: {
310
+ openai: { available: boolean; keyPool: unknown };
311
+ anthropic: { available: boolean; keyPool: unknown };
312
+ };
313
+ routes: unknown;
314
+ };
315
+ expect(data.providers.openai.available).toBe(true);
316
+ expect(data.providers.openai.keyPool).toEqual({ active: 1, total: 2 });
317
+ expect(data.providers.anthropic.available).toBe(false);
318
+ expect(data.providers.anthropic.keyPool).toBeNull();
319
+ expect(data.routes).toEqual({ enrichment: 'openai' });
320
+ });
321
+ });
322
+
323
+ // ─── brain_session_context ─────────────────────────────────────────
324
+
325
+ describe('brain_session_context', () => {
326
+ it('uses default limit of 10', async () => {
327
+ await executeOp(ops, 'brain_session_context', {});
328
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
329
+ expect(bi.getSessionContext).toHaveBeenCalledWith(10);
330
+ });
331
+
332
+ it('passes custom limit', async () => {
333
+ await executeOp(ops, 'brain_session_context', { limit: 25 });
334
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
335
+ expect(bi.getSessionContext).toHaveBeenCalledWith(25);
336
+ });
337
+ });
338
+
339
+ // ─── brain_strengths ───────────────────────────────────────────────
340
+
341
+ describe('brain_strengths', () => {
342
+ it('returns strengths with defaults', async () => {
343
+ const result = await executeOp(ops, 'brain_strengths', {});
344
+ expect(result.success).toBe(true);
345
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
346
+ expect(bi.getStrengths).toHaveBeenCalledWith({
347
+ domain: undefined, minStrength: undefined, limit: 50,
348
+ });
349
+ });
350
+
351
+ it('passes all filter params', async () => {
352
+ await executeOp(ops, 'brain_strengths', {
353
+ domain: 'design', minStrength: 60, limit: 10,
354
+ });
355
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
356
+ expect(bi.getStrengths).toHaveBeenCalledWith({
357
+ domain: 'design', minStrength: 60, limit: 10,
358
+ });
359
+ });
360
+ });
361
+
362
+ // ─── brain_global_patterns ─────────────────────────────────────────
363
+
364
+ describe('brain_global_patterns', () => {
365
+ it('defaults limit to 20', async () => {
366
+ await executeOp(ops, 'brain_global_patterns', {});
367
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
368
+ expect(bi.getGlobalPatterns).toHaveBeenCalledWith(20);
369
+ });
370
+
371
+ it('passes custom limit', async () => {
372
+ await executeOp(ops, 'brain_global_patterns', { limit: 5 });
373
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
374
+ expect(bi.getGlobalPatterns).toHaveBeenCalledWith(5);
375
+ });
376
+ });
377
+
378
+ // ─── brain_recommend ───────────────────────────────────────────────
379
+
380
+ describe('brain_recommend', () => {
381
+ it('passes all params with defaults', async () => {
382
+ const result = await executeOp(ops, 'brain_recommend', {
383
+ domain: 'css', task: 'build button',
384
+ });
385
+ expect(result.success).toBe(true);
386
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
387
+ expect(bi.recommend).toHaveBeenCalledWith({
388
+ domain: 'css', task: 'build button', source: undefined, limit: 5,
389
+ });
390
+ });
391
+ });
392
+
393
+ // ─── brain_build_intelligence ──────────────────────────────────────
394
+
395
+ describe('brain_build_intelligence', () => {
396
+ it('runs the full pipeline', async () => {
397
+ const result = await executeOp(ops, 'brain_build_intelligence', {});
398
+ expect(result.success).toBe(true);
399
+ expect((result.data as { success: boolean }).success).toBe(true);
400
+ });
401
+ });
402
+
403
+ // ─── brain_export / brain_import ───────────────────────────────────
404
+
405
+ describe('brain_export', () => {
406
+ it('returns exported data', async () => {
407
+ const result = await executeOp(ops, 'brain_export', {});
408
+ expect(result.success).toBe(true);
409
+ const data = result.data as { strengths: unknown[] };
410
+ expect(data.strengths).toEqual([]);
411
+ });
412
+ });
413
+
414
+ describe('brain_import', () => {
415
+ it('imports data', async () => {
416
+ const importData = { strengths: [], sessions: [], proposals: [] };
417
+ const result = await executeOp(ops, 'brain_import', { data: importData });
418
+ expect(result.success).toBe(true);
419
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
420
+ expect(bi.importData).toHaveBeenCalledWith(importData);
421
+ });
422
+ });
423
+
424
+ // ─── brain_extract_knowledge ───────────────────────────────────────
425
+
426
+ describe('brain_extract_knowledge', () => {
427
+ it('extracts from session', async () => {
428
+ const result = await executeOp(ops, 'brain_extract_knowledge', {
429
+ sessionId: 'sess-1',
430
+ });
431
+ expect(result.success).toBe(true);
432
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
433
+ expect(bi.extractKnowledge).toHaveBeenCalledWith('sess-1');
434
+ });
435
+ });
436
+
437
+ // ─── brain_archive_sessions ────────────────────────────────────────
438
+
439
+ describe('brain_archive_sessions', () => {
440
+ it('defaults to 30 days', async () => {
441
+ await executeOp(ops, 'brain_archive_sessions', {});
442
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
443
+ expect(bi.archiveSessions).toHaveBeenCalledWith(30);
444
+ });
445
+
446
+ it('passes custom days', async () => {
447
+ await executeOp(ops, 'brain_archive_sessions', { olderThanDays: 7 });
448
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
449
+ expect(bi.archiveSessions).toHaveBeenCalledWith(7);
450
+ });
451
+ });
452
+
453
+ // ─── brain_promote_proposals ───────────────────────────────────────
454
+
455
+ describe('brain_promote_proposals', () => {
456
+ it('promotes with governance and default project path', async () => {
457
+ const result = await executeOp(ops, 'brain_promote_proposals', {
458
+ proposalIds: ['p1', 'p2'],
459
+ });
460
+ expect(result.success).toBe(true);
461
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
462
+ expect(bi.promoteProposals).toHaveBeenCalledWith(
463
+ ['p1', 'p2'],
464
+ runtime.governance,
465
+ '.',
466
+ );
467
+ });
468
+
469
+ it('uses custom project path', async () => {
470
+ await executeOp(ops, 'brain_promote_proposals', {
471
+ proposalIds: ['p1'], projectPath: '/my/project',
472
+ });
473
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
474
+ expect(bi.promoteProposals).toHaveBeenCalledWith(
475
+ ['p1'],
476
+ runtime.governance,
477
+ '/my/project',
478
+ );
479
+ });
480
+ });
481
+
482
+ // ─── brain_lifecycle ───────────────────────────────────────────────
483
+
484
+ describe('brain_lifecycle', () => {
485
+ it('starts a session', async () => {
486
+ const result = await executeOp(ops, 'brain_lifecycle', {
487
+ action: 'start', domain: 'test',
488
+ });
489
+ expect(result.success).toBe(true);
490
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
491
+ expect(bi.lifecycle).toHaveBeenCalledWith(
492
+ expect.objectContaining({ action: 'start', domain: 'test' }),
493
+ );
494
+ });
495
+
496
+ it('ends a session with all metadata', async () => {
497
+ await executeOp(ops, 'brain_lifecycle', {
498
+ action: 'end', sessionId: 's1',
499
+ toolsUsed: ['search', 'capture'], filesModified: ['a.ts'],
500
+ planId: 'plan-1', planOutcome: 'success',
501
+ });
502
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
503
+ expect(bi.lifecycle).toHaveBeenCalledWith({
504
+ action: 'end', sessionId: 's1', domain: undefined, context: undefined,
505
+ toolsUsed: ['search', 'capture'], filesModified: ['a.ts'],
506
+ planId: 'plan-1', planOutcome: 'success',
507
+ });
508
+ });
509
+ });
510
+
511
+ // ─── session_list ──────────────────────────────────────────────────
512
+
513
+ describe('session_list', () => {
514
+ it('returns sessions with default pagination', async () => {
515
+ const result = await executeOp(ops, 'session_list', {});
516
+ expect(result.success).toBe(true);
517
+ const data = result.data as { sessions: unknown[]; count: number };
518
+ expect(data.count).toBe(1);
519
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
520
+ expect(bi.listSessions).toHaveBeenCalledWith(
521
+ expect.objectContaining({ limit: 50, offset: 0 }),
522
+ );
523
+ });
524
+
525
+ it('passes all filter params', async () => {
526
+ await executeOp(ops, 'session_list', {
527
+ domain: 'design', active: true, extracted: false, limit: 10, offset: 5,
528
+ });
529
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
530
+ expect(bi.listSessions).toHaveBeenCalledWith({
531
+ domain: 'design', active: true, extracted: false, limit: 10, offset: 5,
532
+ });
533
+ });
534
+ });
535
+
536
+ // ─── session_get ───────────────────────────────────────────────────
537
+
538
+ describe('session_get', () => {
539
+ it('returns session by id', async () => {
540
+ const result = await executeOp(ops, 'session_get', { sessionId: 'sess-1' });
541
+ expect(result.success).toBe(true);
542
+ expect((result.data as { id: string }).id).toBe('sess-1');
543
+ });
544
+
545
+ it('returns error when session not found', async () => {
546
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
547
+ bi.getSessionById.mockReturnValue(null);
548
+ const result = await executeOp(ops, 'session_get', { sessionId: 'missing' });
549
+ expect(result.success).toBe(true);
550
+ expect((result.data as { error: string }).error).toBe('Session not found');
551
+ });
552
+ });
553
+
554
+ // ─── session_quality ───────────────────────────────────────────────
555
+
556
+ describe('session_quality', () => {
557
+ it('computes quality score', async () => {
558
+ const result = await executeOp(ops, 'session_quality', { sessionId: 'sess-1' });
559
+ expect(result.success).toBe(true);
560
+ expect((result.data as { score: number }).score).toBe(75);
561
+ });
562
+ });
563
+
564
+ // ─── session_replay ────────────────────────────────────────────────
565
+
566
+ describe('session_replay', () => {
567
+ it('replays session', async () => {
568
+ const result = await executeOp(ops, 'session_replay', { sessionId: 'sess-1' });
569
+ expect(result.success).toBe(true);
570
+ expect((result.data as { quality: number }).quality).toBe(75);
571
+ });
572
+ });
573
+
574
+ // ─── brain_reset_extracted ─────────────────────────────────────────
575
+
576
+ describe('brain_reset_extracted', () => {
577
+ it('resets by session id', async () => {
578
+ await executeOp(ops, 'brain_reset_extracted', { sessionId: 'sess-1' });
579
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
580
+ expect(bi.resetExtracted).toHaveBeenCalledWith({
581
+ sessionId: 'sess-1', since: undefined, all: undefined,
582
+ });
583
+ });
584
+
585
+ it('resets all', async () => {
586
+ await executeOp(ops, 'brain_reset_extracted', { all: true });
587
+ const bi = runtime.brainIntelligence as ReturnType<typeof makeMockBrainIntelligence>;
588
+ expect(bi.resetExtracted).toHaveBeenCalledWith({
589
+ sessionId: undefined, since: undefined, all: true,
590
+ });
591
+ });
592
+ });
593
+
594
+ // ─── radar_analyze ─────────────────────────────────────────────────
595
+
596
+ describe('radar_analyze', () => {
597
+ it('analyzes a learning signal', async () => {
598
+ const result = await executeOp(ops, 'radar_analyze', {
599
+ type: 'correction',
600
+ title: 'Token naming',
601
+ description: 'Use semantic tokens over primitives',
602
+ });
603
+ expect(result.success).toBe(true);
604
+ const data = result.data as { action: string; candidateId: number };
605
+ expect(data.action).toBe('queued');
606
+ expect(data.candidateId).toBe(1);
607
+ });
608
+
609
+ it('passes all optional fields', async () => {
610
+ await executeOp(ops, 'radar_analyze', {
611
+ type: 'search_miss', title: 't', description: 'd',
612
+ suggestedType: 'anti-pattern', confidence: 0.95,
613
+ sourceQuery: 'tokens', context: 'extra',
614
+ });
615
+ const radar = runtime.learningRadar as ReturnType<typeof makeMockLearningRadar>;
616
+ expect(radar.analyze).toHaveBeenCalledWith({
617
+ type: 'search_miss', title: 't', description: 'd',
618
+ suggestedType: 'anti-pattern', confidence: 0.95,
619
+ sourceQuery: 'tokens', context: 'extra',
620
+ });
621
+ });
622
+ });
623
+
624
+ // ─── radar_candidates ──────────────────────────────────────────────
625
+
626
+ describe('radar_candidates', () => {
627
+ it('returns candidates with default limit', async () => {
628
+ const result = await executeOp(ops, 'radar_candidates', {});
629
+ expect(result.success).toBe(true);
630
+ const radar = runtime.learningRadar as ReturnType<typeof makeMockLearningRadar>;
631
+ expect(radar.getCandidates).toHaveBeenCalledWith(20);
632
+ });
633
+ });
634
+
635
+ // ─── radar_approve / radar_dismiss ─────────────────────────────────
636
+
637
+ describe('radar_approve', () => {
638
+ it('approves a candidate', async () => {
639
+ const result = await executeOp(ops, 'radar_approve', { candidateId: 1 });
640
+ expect(result.success).toBe(true);
641
+ expect((result.data as { approved: boolean }).approved).toBe(true);
642
+ });
643
+ });
644
+
645
+ describe('radar_dismiss', () => {
646
+ it('dismisses a candidate', async () => {
647
+ const result = await executeOp(ops, 'radar_dismiss', { candidateId: 1 });
648
+ expect(result.success).toBe(true);
649
+ expect((result.data as { dismissed: boolean }).dismissed).toBe(true);
650
+ });
651
+ });
652
+
653
+ // ─── radar_flush ───────────────────────────────────────────────────
654
+
655
+ describe('radar_flush', () => {
656
+ it('flushes with default confidence', async () => {
657
+ const result = await executeOp(ops, 'radar_flush', {});
658
+ expect(result.success).toBe(true);
659
+ const radar = runtime.learningRadar as ReturnType<typeof makeMockLearningRadar>;
660
+ expect(radar.flush).toHaveBeenCalledWith(0.8);
661
+ });
662
+
663
+ it('uses custom confidence threshold', async () => {
664
+ await executeOp(ops, 'radar_flush', { minConfidence: 0.5 });
665
+ const radar = runtime.learningRadar as ReturnType<typeof makeMockLearningRadar>;
666
+ expect(radar.flush).toHaveBeenCalledWith(0.5);
667
+ });
668
+ });
669
+
670
+ // ─── radar_stats ───────────────────────────────────────────────────
671
+
672
+ describe('radar_stats', () => {
673
+ it('returns stats', async () => {
674
+ const result = await executeOp(ops, 'radar_stats', {});
675
+ expect(result.success).toBe(true);
676
+ const data = result.data as { analyzed: number; captured: number };
677
+ expect(data.analyzed).toBe(10);
678
+ expect(data.captured).toBe(5);
679
+ });
680
+ });
681
+
682
+ // ─── synthesize ────────────────────────────────────────────────────
683
+
684
+ describe('synthesize', () => {
685
+ it('synthesizes with all params', async () => {
686
+ const result = await executeOp(ops, 'synthesize', {
687
+ query: 'design tokens', format: 'brief',
688
+ maxEntries: 5, audience: 'technical',
689
+ });
690
+ expect(result.success).toBe(true);
691
+ const data = result.data as { content: string; coverageScore: number };
692
+ expect(data.content).toBe('Synthesized output');
693
+ expect(data.coverageScore).toBe(0.8);
694
+ });
695
+
696
+ it('uses default audience and maxEntries', async () => {
697
+ await executeOp(ops, 'synthesize', {
698
+ query: 'test', format: 'outline',
699
+ });
700
+ const synth = runtime.knowledgeSynthesizer as ReturnType<typeof makeMockKnowledgeSynthesizer>;
701
+ expect(synth.synthesize).toHaveBeenCalledWith('test', {
702
+ format: 'outline', maxEntries: 10, audience: 'general',
703
+ });
704
+ });
705
+
706
+ it('rejects invalid format', async () => {
707
+ const result = await executeOp(ops, 'synthesize', {
708
+ query: 'test', format: 'invalid',
709
+ });
710
+ expect(result.success).toBe(false);
711
+ expect(result.error).toContain('Invalid params');
712
+ });
713
+ });
714
+ });