@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,230 @@
1
+ /**
2
+ * Colocated tests for register-engine.ts
3
+ *
4
+ * Validates registerEngine() registration mechanics:
5
+ * - Module tool naming convention
6
+ * - Engine module ordering and completeness
7
+ * - Core ops registration
8
+ * - Domain and domain pack registration
9
+ * - Hot ops as standalone tools
10
+ * - Auth policy enforcement
11
+ * - Error handling for unknown ops
12
+ * - Dynamic tool registration (registerTool)
13
+ */
14
+
15
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
16
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
17
+ import { createAgentRuntime } from '../runtime/runtime.js';
18
+ import { registerEngine, ENGINE_MODULES } from './register-engine.js';
19
+ import { ENGINE_MODULE_MANIFEST } from './module-manifest.js';
20
+ import type { AgentRuntime } from '../runtime/types.js';
21
+ import type { OpDefinition } from '../facades/types.js';
22
+
23
+ let runtime: AgentRuntime;
24
+
25
+ beforeAll(() => {
26
+ runtime = createAgentRuntime({
27
+ agentId: 'reg-test',
28
+ vaultPath: ':memory:',
29
+ });
30
+ });
31
+
32
+ afterAll(() => {
33
+ runtime.close();
34
+ });
35
+
36
+ function makeServer(): McpServer {
37
+ return new McpServer({ name: 'test-server', version: '1.0.0' });
38
+ }
39
+
40
+ describe('registerEngine — tool naming', () => {
41
+ it('prefixes all tools with agentId', () => {
42
+ const server = makeServer();
43
+ const result = registerEngine(server, runtime, { agentId: 'mybot' });
44
+ for (const tool of result.tools) {
45
+ expect(tool.startsWith('mybot_')).toBe(true);
46
+ }
47
+ });
48
+
49
+ it('creates {agentId}_{suffix} for each engine module', () => {
50
+ const server = makeServer();
51
+ const result = registerEngine(server, runtime, { agentId: 'alfa' });
52
+ const expectedSuffixes = ENGINE_MODULES.map((m) => m.suffix);
53
+ for (const suffix of expectedSuffixes) {
54
+ expect(result.tools).toContain(`alfa_${suffix}`);
55
+ }
56
+ });
57
+ });
58
+
59
+ describe('registerEngine — module completeness', () => {
60
+ it('ENGINE_MODULES matches ENGINE_MODULE_MANIFEST suffixes', () => {
61
+ const moduleSuffixes = ENGINE_MODULES.map((m) => m.suffix);
62
+ const manifestSuffixes = ENGINE_MODULE_MANIFEST.map((m) => m.suffix);
63
+ expect(moduleSuffixes).toEqual(manifestSuffixes);
64
+ });
65
+
66
+ it('ENGINE_MODULES and manifest have same count', () => {
67
+ expect(ENGINE_MODULES.length).toBe(ENGINE_MODULE_MANIFEST.length);
68
+ });
69
+
70
+ it('registers all unconditional modules', () => {
71
+ const server = makeServer();
72
+ const result = registerEngine(server, runtime, { agentId: 'check' });
73
+ const unconditional = ENGINE_MODULES.filter((m) => !m.condition);
74
+ for (const mod of unconditional) {
75
+ expect(result.tools).toContain(`check_${mod.suffix}`);
76
+ }
77
+ });
78
+ });
79
+
80
+ describe('registerEngine — module ordering', () => {
81
+ it('registers vault before brain (dependency order)', () => {
82
+ const server = makeServer();
83
+ const result = registerEngine(server, runtime, { agentId: 'ord' });
84
+ const vaultIdx = result.tools.indexOf('ord_vault');
85
+ const brainIdx = result.tools.indexOf('ord_brain');
86
+ expect(vaultIdx).toBeLessThan(brainIdx);
87
+ });
88
+
89
+ it('registers vault as the first engine module tool', () => {
90
+ const server = makeServer();
91
+ const result = registerEngine(server, runtime, { agentId: 'first' });
92
+ expect(result.tools[0]).toBe('first_vault');
93
+ });
94
+ });
95
+
96
+ describe('registerEngine — core ops', () => {
97
+ it('registers core facade when coreOps provided', () => {
98
+ const server = makeServer();
99
+ const coreOps: OpDefinition[] = [
100
+ { name: 'health', description: 'Health check', auth: 'read', handler: async () => ({ ok: true }) },
101
+ ];
102
+ const result = registerEngine(server, runtime, { agentId: 'core', coreOps });
103
+ expect(result.tools).toContain('core_core');
104
+ expect(result.totalOps).toBeGreaterThan(ENGINE_MODULES.length); // at least 1 per module + 1 core
105
+ });
106
+
107
+ it('does not register core facade when coreOps is empty', () => {
108
+ const server = makeServer();
109
+ const result = registerEngine(server, runtime, { agentId: 'nocore', coreOps: [] });
110
+ expect(result.tools).not.toContain('nocore_core');
111
+ });
112
+
113
+ it('does not register core facade when coreOps is undefined', () => {
114
+ const server = makeServer();
115
+ const result = registerEngine(server, runtime, { agentId: 'nocore2' });
116
+ expect(result.tools).not.toContain('nocore2_core');
117
+ });
118
+ });
119
+
120
+ describe('registerEngine — hot ops', () => {
121
+ it('registers hot ops as standalone tools', () => {
122
+ const server = makeServer();
123
+ const result = registerEngine(server, runtime, {
124
+ agentId: 'hot',
125
+ hotOps: ['search_intelligent', 'capture_knowledge'],
126
+ });
127
+ expect(result.tools).toContain('hot_search_intelligent');
128
+ expect(result.tools).toContain('hot_capture_knowledge');
129
+ });
130
+
131
+ it('counts hot ops in totalOps', () => {
132
+ const server = makeServer();
133
+ const baseResult = registerEngine(server, runtime, { agentId: 'base' });
134
+
135
+ const server2 = makeServer();
136
+ const hotResult = registerEngine(server2, runtime, {
137
+ agentId: 'hotcount',
138
+ hotOps: ['search_intelligent'],
139
+ });
140
+ // Hot ops don't add to totalOps (they mirror existing ops)
141
+ // But they do add to tools array
142
+ expect(hotResult.tools.length).toBeGreaterThan(baseResult.tools.length);
143
+ });
144
+ });
145
+
146
+ describe('registerEngine — domains', () => {
147
+ it('registers domain facades with correct naming', () => {
148
+ const server = makeServer();
149
+ const result = registerEngine(server, runtime, {
150
+ agentId: 'dom',
151
+ domains: ['testing', 'architecture'],
152
+ });
153
+ expect(result.tools).toContain('dom_testing');
154
+ expect(result.tools).toContain('dom_architecture');
155
+ });
156
+
157
+ it('increments totalOps for domain facade ops', () => {
158
+ const server1 = makeServer();
159
+ const noDomains = registerEngine(server1, runtime, { agentId: 'nod' });
160
+
161
+ const server2 = makeServer();
162
+ const withDomains = registerEngine(server2, runtime, {
163
+ agentId: 'wd',
164
+ domains: ['testing'],
165
+ });
166
+ expect(withDomains.totalOps).toBeGreaterThan(noDomains.totalOps);
167
+ });
168
+ });
169
+
170
+ describe('registerEngine — domain packs', () => {
171
+ it('registers domain pack facades with agentId prefix', () => {
172
+ const server = makeServer();
173
+ const packOp: OpDefinition = {
174
+ name: 'custom_search',
175
+ description: 'Custom search',
176
+ auth: 'read',
177
+ handler: async () => [],
178
+ };
179
+ const result = registerEngine(server, runtime, {
180
+ agentId: 'pk',
181
+ domainPacks: [{ name: 'my-pack', facades: [{ name: 'custom', ops: [packOp] }] }],
182
+ });
183
+ expect(result.tools).toContain('pk_custom');
184
+ });
185
+
186
+ it('skips packs without facades', () => {
187
+ const server = makeServer();
188
+ const result = registerEngine(server, runtime, {
189
+ agentId: 'skip',
190
+ domainPacks: [{ name: 'empty-pack' }],
191
+ });
192
+ // Should still register normally without errors
193
+ expect(result.tools.length).toBeGreaterThan(0);
194
+ });
195
+ });
196
+
197
+ describe('registerEngine — return value', () => {
198
+ it('returns tools array, totalOps count, and registerTool function', () => {
199
+ const server = makeServer();
200
+ const result = registerEngine(server, runtime, { agentId: 'ret' });
201
+ expect(Array.isArray(result.tools)).toBe(true);
202
+ expect(typeof result.totalOps).toBe('number');
203
+ expect(typeof result.registerTool).toBe('function');
204
+ expect(result.totalOps).toBeGreaterThan(0);
205
+ });
206
+
207
+ it('registerTool adds a new tool at runtime', () => {
208
+ const server = makeServer();
209
+ const result = registerEngine(server, runtime, { agentId: 'dyn' });
210
+ const initialCount = result.tools.length;
211
+
212
+ result.registerTool('dyn_extra', 'Extra tool', [
213
+ { name: 'ping', description: 'Ping', auth: 'read', handler: async () => 'pong' },
214
+ ]);
215
+
216
+ expect(result.tools.length).toBe(initialCount + 1);
217
+ expect(result.tools).toContain('dyn_extra');
218
+ });
219
+ });
220
+
221
+ describe('ENGINE_MODULES descriptions match manifest', () => {
222
+ it('each module description aligns with manifest', () => {
223
+ for (let i = 0; i < ENGINE_MODULES.length; i++) {
224
+ const mod = ENGINE_MODULES[i];
225
+ const manifest = ENGINE_MODULE_MANIFEST[i];
226
+ expect(mod.suffix).toBe(manifest.suffix);
227
+ // Descriptions may diverge slightly but suffix must match
228
+ }
229
+ });
230
+ });
@@ -35,6 +35,10 @@ import { createControlFacadeOps } from '../runtime/facades/control-facade.js';
35
35
  import { createContextFacadeOps } from '../runtime/facades/context-facade.js';
36
36
  import { createAgencyFacadeOps } from '../runtime/facades/agency-facade.js';
37
37
  import { createChatFacadeOps } from '../runtime/facades/chat-facade.js';
38
+ import { createOperatorFacadeOps } from '../runtime/facades/operator-facade.js';
39
+ import { createArchiveFacadeOps } from '../runtime/facades/archive-facade.js';
40
+ import { createSyncFacadeOps } from '../runtime/facades/sync-facade.js';
41
+ import { createReviewFacadeOps } from '../runtime/facades/review-facade.js';
38
42
  import { createDomainFacade } from '../runtime/domain-ops.js';
39
43
 
40
44
  // ─── Types ────────────────────────────────────────────────────────────
@@ -84,7 +88,7 @@ interface ModuleDef {
84
88
  export const ENGINE_MODULES: ModuleDef[] = [
85
89
  {
86
90
  suffix: 'vault',
87
- description: 'Knowledge management — search, CRUD, import/export, intake, archival.',
91
+ description: 'Knowledge management — search, CRUD, import/export, intake, sharing, linking.',
88
92
  createOps: createVaultFacadeOps,
89
93
  },
90
94
  {
@@ -120,7 +124,7 @@ export const ENGINE_MODULES: ModuleDef[] = [
120
124
  {
121
125
  suffix: 'orchestrate',
122
126
  description:
123
- 'Execution orchestration — project registration, playbooks, plan/execute/complete.',
127
+ 'Execution orchestration — session start, playbooks, plan/execute/complete.',
124
128
  createOps: createOrchestrateFacadeOps,
125
129
  },
126
130
  {
@@ -143,6 +147,26 @@ export const ENGINE_MODULES: ModuleDef[] = [
143
147
  description: 'Chat transport — session management, response chunking, authentication.',
144
148
  createOps: createChatFacadeOps,
145
149
  },
150
+ {
151
+ suffix: 'operator',
152
+ description: 'Operator profile — personality learning, signals, adaptation.',
153
+ createOps: createOperatorFacadeOps,
154
+ },
155
+ {
156
+ suffix: 'archive',
157
+ description: 'Archival, lifecycle, and knowledge maintenance.',
158
+ createOps: createArchiveFacadeOps,
159
+ },
160
+ {
161
+ suffix: 'sync',
162
+ description: 'Git, Obsidian, and pack sync operations.',
163
+ createOps: createSyncFacadeOps,
164
+ },
165
+ {
166
+ suffix: 'review',
167
+ description: 'Knowledge review workflow.',
168
+ createOps: createReviewFacadeOps,
169
+ },
146
170
  ];
147
171
 
148
172
  // ─── Core Registration ────────────────────────────────────────────────
@@ -0,0 +1,199 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { classifyError } from './classify.js';
3
+ import { SoleriError, SoleriErrorCode } from './types.js';
4
+
5
+ describe('classifyError', () => {
6
+ describe('passthrough', () => {
7
+ it('should return a SoleriError as-is', () => {
8
+ const original = new SoleriError('already classified', SoleriErrorCode.TIMEOUT);
9
+ const result = classifyError(original);
10
+ expect(result).toBe(original);
11
+ });
12
+ });
13
+
14
+ describe('HTTP status classification', () => {
15
+ it('should classify 401 as AUTH', () => {
16
+ const result = classifyError({ status: 401, message: 'Unauthorized' });
17
+ expect(result.code).toBe(SoleriErrorCode.AUTH);
18
+ expect(result.context).toEqual({ httpStatus: 401 });
19
+ });
20
+
21
+ it('should classify 403 as AUTH', () => {
22
+ const result = classifyError({ status: 403, message: 'Forbidden' });
23
+ expect(result.code).toBe(SoleriErrorCode.AUTH);
24
+ });
25
+
26
+ it('should classify 404 as RESOURCE_NOT_FOUND', () => {
27
+ const result = classifyError({ statusCode: 404, message: 'Not found' });
28
+ expect(result.code).toBe(SoleriErrorCode.RESOURCE_NOT_FOUND);
29
+ });
30
+
31
+ it('should classify 408 as TIMEOUT', () => {
32
+ const result = classifyError({ status: 408, message: 'Request Timeout' });
33
+ expect(result.code).toBe(SoleriErrorCode.TIMEOUT);
34
+ });
35
+
36
+ it('should classify 429 as RATE_LIMIT', () => {
37
+ const result = classifyError({ status: 429, message: 'Too Many Requests' });
38
+ expect(result.code).toBe(SoleriErrorCode.RATE_LIMIT);
39
+ });
40
+
41
+ it('should classify 422 as VALIDATION', () => {
42
+ const result = classifyError({ status: 422, message: 'Unprocessable' });
43
+ expect(result.code).toBe(SoleriErrorCode.VALIDATION);
44
+ });
45
+
46
+ it('should classify 500 as INTERNAL', () => {
47
+ const result = classifyError({ status: 500, message: 'Server Error' });
48
+ expect(result.code).toBe(SoleriErrorCode.INTERNAL);
49
+ });
50
+
51
+ it('should classify 503 as INTERNAL', () => {
52
+ const result = classifyError({ status: 503, message: 'Service Unavailable' });
53
+ expect(result.code).toBe(SoleriErrorCode.INTERNAL);
54
+ });
55
+
56
+ it('should prefer statusCode when status is absent', () => {
57
+ const result = classifyError({ statusCode: 429, message: 'throttled' });
58
+ expect(result.code).toBe(SoleriErrorCode.RATE_LIMIT);
59
+ });
60
+ });
61
+
62
+ describe('Node.js error code classification', () => {
63
+ it('should classify ECONNREFUSED as NETWORK', () => {
64
+ const err = Object.assign(new Error('connect failed'), { code: 'ECONNREFUSED' });
65
+ const result = classifyError(err);
66
+ expect(result.code).toBe(SoleriErrorCode.NETWORK);
67
+ expect(result.context).toEqual({ errorCode: 'ECONNREFUSED' });
68
+ });
69
+
70
+ it('should classify ENOTFOUND as NETWORK', () => {
71
+ const err = Object.assign(new Error('dns fail'), { code: 'ENOTFOUND' });
72
+ expect(classifyError(err).code).toBe(SoleriErrorCode.NETWORK);
73
+ });
74
+
75
+ it('should classify ECONNRESET as NETWORK', () => {
76
+ const err = Object.assign(new Error('reset'), { code: 'ECONNRESET' });
77
+ expect(classifyError(err).code).toBe(SoleriErrorCode.NETWORK);
78
+ });
79
+
80
+ it('should classify ETIMEDOUT as TIMEOUT', () => {
81
+ const err = Object.assign(new Error('timed out'), { code: 'ETIMEDOUT' });
82
+ expect(classifyError(err).code).toBe(SoleriErrorCode.TIMEOUT);
83
+ });
84
+
85
+ it('should classify ESOCKETTIMEDOUT as TIMEOUT', () => {
86
+ const err = Object.assign(new Error('socket'), { code: 'ESOCKETTIMEDOUT' });
87
+ expect(classifyError(err).code).toBe(SoleriErrorCode.TIMEOUT);
88
+ });
89
+
90
+ it('should classify UND_ERR_CONNECT_TIMEOUT as TIMEOUT', () => {
91
+ const err = Object.assign(new Error('undici'), { code: 'UND_ERR_CONNECT_TIMEOUT' });
92
+ expect(classifyError(err).code).toBe(SoleriErrorCode.TIMEOUT);
93
+ });
94
+ });
95
+
96
+ describe('message pattern classification', () => {
97
+ it('should classify "overloaded" as LLM_OVERLOAD', () => {
98
+ expect(classifyError(new Error('server is overloaded')).code).toBe(SoleriErrorCode.LLM_OVERLOAD);
99
+ });
100
+
101
+ it('should classify "model busy" as LLM_OVERLOAD', () => {
102
+ expect(classifyError(new Error('model is busy')).code).toBe(SoleriErrorCode.LLM_OVERLOAD);
103
+ });
104
+
105
+ it('should classify "timeout" message as TIMEOUT', () => {
106
+ expect(classifyError(new Error('operation timed out')).code).toBe(SoleriErrorCode.TIMEOUT);
107
+ });
108
+
109
+ it('should classify "sqlite" as VAULT_UNREACHABLE', () => {
110
+ expect(classifyError(new Error('sqlite error')).code).toBe(SoleriErrorCode.VAULT_UNREACHABLE);
111
+ });
112
+
113
+ it('should classify "validation" as VALIDATION', () => {
114
+ expect(classifyError(new Error('validation failed')).code).toBe(SoleriErrorCode.VALIDATION);
115
+ });
116
+
117
+ it('should classify "missing key" as CONFIG_ERROR', () => {
118
+ expect(classifyError(new Error('missing key FOO')).code).toBe(SoleriErrorCode.CONFIG_ERROR);
119
+ });
120
+
121
+ it('should classify "unauthorized" as AUTH', () => {
122
+ expect(classifyError(new Error('unauthorized access')).code).toBe(SoleriErrorCode.AUTH);
123
+ });
124
+
125
+ it('should classify "not found" as RESOURCE_NOT_FOUND', () => {
126
+ expect(classifyError(new Error('resource not found')).code).toBe(SoleriErrorCode.RESOURCE_NOT_FOUND);
127
+ });
128
+
129
+ it('should classify "rate limit" as RATE_LIMIT', () => {
130
+ expect(classifyError(new Error('rate limit exceeded')).code).toBe(SoleriErrorCode.RATE_LIMIT);
131
+ });
132
+
133
+ it('should classify "network" as NETWORK', () => {
134
+ expect(classifyError(new Error('network failure')).code).toBe(SoleriErrorCode.NETWORK);
135
+ });
136
+ });
137
+
138
+ describe('fallback classification', () => {
139
+ it('should default to INTERNAL for unknown errors', () => {
140
+ const result = classifyError(new Error('something weird'));
141
+ expect(result.code).toBe(SoleriErrorCode.INTERNAL);
142
+ });
143
+
144
+ it('should handle string thrown values', () => {
145
+ const result = classifyError('a string error');
146
+ expect(result).toBeInstanceOf(SoleriError);
147
+ expect(result.message).toBe('a string error');
148
+ });
149
+
150
+ it('should handle number thrown values', () => {
151
+ const result = classifyError(42);
152
+ expect(result).toBeInstanceOf(SoleriError);
153
+ expect(result.message).toBe('42');
154
+ });
155
+
156
+ it('should handle null thrown values', () => {
157
+ const result = classifyError(null);
158
+ expect(result).toBeInstanceOf(SoleriError);
159
+ });
160
+
161
+ it('should handle undefined thrown values', () => {
162
+ const result = classifyError(undefined);
163
+ expect(result).toBeInstanceOf(SoleriError);
164
+ });
165
+
166
+ it('should handle plain objects with no message', () => {
167
+ const result = classifyError({});
168
+ expect(result).toBeInstanceOf(SoleriError);
169
+ expect(result.message).toBe('Unknown error');
170
+ expect(result.code).toBe(SoleriErrorCode.INTERNAL);
171
+ });
172
+ });
173
+
174
+ describe('priority order', () => {
175
+ it('should prefer HTTP status over message pattern', () => {
176
+ const result = classifyError({ status: 404, message: 'network error not found' });
177
+ expect(result.code).toBe(SoleriErrorCode.RESOURCE_NOT_FOUND);
178
+ });
179
+
180
+ it('should prefer error code over message pattern', () => {
181
+ const err = Object.assign(new Error('timeout in database'), { code: 'ECONNREFUSED' });
182
+ const result = classifyError(err);
183
+ expect(result.code).toBe(SoleriErrorCode.NETWORK);
184
+ });
185
+ });
186
+
187
+ describe('cause preservation', () => {
188
+ it('should preserve original Error as cause', () => {
189
+ const original = new Error('root');
190
+ const result = classifyError(original);
191
+ expect(result.cause).toBe(original);
192
+ });
193
+
194
+ it('should not set cause for non-Error values', () => {
195
+ const result = classifyError('string error');
196
+ expect(result.cause).toBeUndefined();
197
+ });
198
+ });
199
+ });
@@ -0,0 +1,156 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { shouldRetry, getRetryDelay, retryWithPreset, RETRY_PRESETS } from './retry.js';
3
+ import { SoleriError, SoleriErrorCode } from './types.js';
4
+
5
+ describe('RETRY_PRESETS', () => {
6
+ it('should define fast, normal, and patient presets', () => {
7
+ expect(RETRY_PRESETS.fast.maxAttempts).toBe(3);
8
+ expect(RETRY_PRESETS.normal.maxAttempts).toBe(10);
9
+ expect(RETRY_PRESETS.patient.maxAttempts).toBe(25);
10
+ });
11
+ });
12
+
13
+ describe('shouldRetry', () => {
14
+ it('should return true for retryable error below max attempts', () => {
15
+ const error = new SoleriError('timeout', SoleriErrorCode.TIMEOUT);
16
+ expect(shouldRetry(error, 1, 'fast')).toBe(true);
17
+ });
18
+
19
+ it('should return false for retryable error at max attempts', () => {
20
+ const error = new SoleriError('timeout', SoleriErrorCode.TIMEOUT);
21
+ expect(shouldRetry(error, 3, 'fast')).toBe(false);
22
+ });
23
+
24
+ it('should return false for non-retryable error', () => {
25
+ const error = new SoleriError('bad auth', SoleriErrorCode.AUTH);
26
+ expect(shouldRetry(error, 1, 'fast')).toBe(false);
27
+ });
28
+
29
+ it('should return false for fixable error', () => {
30
+ const error = new SoleriError('invalid', SoleriErrorCode.VALIDATION);
31
+ expect(shouldRetry(error, 1, 'normal')).toBe(false);
32
+ });
33
+ });
34
+
35
+ describe('getRetryDelay', () => {
36
+ it('should return a positive number', () => {
37
+ const delay = getRetryDelay(0, 'fast');
38
+ expect(delay).toBeGreaterThanOrEqual(0);
39
+ });
40
+
41
+ it('should increase with attempt number', () => {
42
+ const delays = Array.from({ length: 5 }, (_, i) => {
43
+ // Average over multiple samples to reduce jitter impact
44
+ const samples = Array.from({ length: 100 }, () => getRetryDelay(i, 'normal'));
45
+ return samples.reduce((a, b) => a + b, 0) / samples.length;
46
+ });
47
+ // Each averaged delay should generally be >= the previous
48
+ for (let i = 1; i < delays.length - 1; i++) {
49
+ expect(delays[i]).toBeGreaterThanOrEqual(delays[i - 1] * 0.5);
50
+ }
51
+ });
52
+
53
+ it('should not exceed maxIntervalMs plus jitter', () => {
54
+ const config = RETRY_PRESETS.fast;
55
+ const maxWithJitter = config.maxIntervalMs * 1.25;
56
+ for (let i = 0; i < 20; i++) {
57
+ expect(getRetryDelay(10, 'fast')).toBeLessThanOrEqual(maxWithJitter);
58
+ }
59
+ });
60
+
61
+ it('should never return a negative value', () => {
62
+ for (let i = 0; i < 50; i++) {
63
+ expect(getRetryDelay(0, 'fast')).toBeGreaterThanOrEqual(0);
64
+ }
65
+ });
66
+ });
67
+
68
+ describe('retryWithPreset', () => {
69
+ beforeEach(() => {
70
+ vi.useFakeTimers();
71
+ });
72
+
73
+ afterEach(() => {
74
+ vi.useRealTimers();
75
+ });
76
+
77
+ it('should return ok on first success', async () => {
78
+ const fn = vi.fn().mockResolvedValue('done');
79
+ const resultPromise = retryWithPreset(fn, 'fast');
80
+ const result = await resultPromise;
81
+ expect(result).toEqual({ ok: true, value: 'done' });
82
+ expect(fn).toHaveBeenCalledTimes(1);
83
+ });
84
+
85
+ it('should retry retryable errors and succeed', async () => {
86
+ const fn = vi
87
+ .fn()
88
+ .mockRejectedValueOnce(new Error('network error'))
89
+ .mockResolvedValue('recovered');
90
+
91
+ const resultPromise = retryWithPreset(fn, 'fast');
92
+ // Advance past the sleep delay
93
+ await vi.advanceTimersByTimeAsync(20_000);
94
+ const result = await resultPromise;
95
+ expect(result).toEqual({ ok: true, value: 'recovered' });
96
+ expect(fn).toHaveBeenCalledTimes(2);
97
+ });
98
+
99
+ it('should return err immediately for permanent errors', async () => {
100
+ const fn = vi.fn().mockRejectedValue(new SoleriError('denied', SoleriErrorCode.AUTH));
101
+ const result = await retryWithPreset(fn, 'fast');
102
+ expect(result.ok).toBe(false);
103
+ if (!result.ok) {
104
+ expect(result.error.code).toBe(SoleriErrorCode.AUTH);
105
+ }
106
+ expect(fn).toHaveBeenCalledTimes(1);
107
+ });
108
+
109
+ it('should return err after exhausting all attempts', async () => {
110
+ const fn = vi.fn().mockRejectedValue(new SoleriError('down', SoleriErrorCode.NETWORK));
111
+ const resultPromise = retryWithPreset(fn, 'fast');
112
+ // Advance enough time for all retries
113
+ await vi.advanceTimersByTimeAsync(100_000);
114
+ const result = await resultPromise;
115
+ expect(result.ok).toBe(false);
116
+ expect(fn).toHaveBeenCalledTimes(3);
117
+ });
118
+
119
+ it('should call onRetry callback on each retry', async () => {
120
+ const onRetry = vi.fn();
121
+ const fn = vi
122
+ .fn()
123
+ .mockRejectedValueOnce(new Error('network fail'))
124
+ .mockResolvedValue('ok');
125
+
126
+ const resultPromise = retryWithPreset(fn, 'fast', { onRetry });
127
+ await vi.advanceTimersByTimeAsync(20_000);
128
+ await resultPromise;
129
+ expect(onRetry).toHaveBeenCalledTimes(1);
130
+ expect(onRetry).toHaveBeenCalledWith(expect.any(SoleriError), 1, expect.any(Number));
131
+ });
132
+
133
+ it('should abort when signal is aborted during sleep', async () => {
134
+ const controller = new AbortController();
135
+ const fn = vi.fn().mockRejectedValue(new Error('network error'));
136
+
137
+ const resultPromise = retryWithPreset(fn, 'fast', { signal: controller.signal });
138
+ // Let the first attempt fail and enter sleep
139
+ await vi.advanceTimersByTimeAsync(0);
140
+ // Abort during sleep
141
+ controller.abort(new Error('cancelled'));
142
+ await vi.advanceTimersByTimeAsync(0);
143
+ const result = await resultPromise;
144
+ expect(result.ok).toBe(false);
145
+ });
146
+
147
+ it('should return err for fixable errors without retrying', async () => {
148
+ const fn = vi.fn().mockRejectedValue(new SoleriError('bad', SoleriErrorCode.VALIDATION));
149
+ const result = await retryWithPreset(fn, 'fast');
150
+ expect(result.ok).toBe(false);
151
+ expect(fn).toHaveBeenCalledTimes(1);
152
+ });
153
+ });
154
+
155
+ // Need to import afterEach at top level
156
+ import { afterEach } from 'vitest';
@@ -104,6 +104,7 @@ export async function retryWithPreset<T>(
104
104
 
105
105
  for (let attempt = 0; attempt < RETRY_PRESETS[preset].maxAttempts; attempt++) {
106
106
  try {
107
+ // oxlint-disable-next-line eslint(no-await-in-loop)
107
108
  const value = await fn();
108
109
  return ok(value);
109
110
  } catch (thrown: unknown) {
@@ -117,6 +118,7 @@ export async function retryWithPreset<T>(
117
118
  options?.onRetry?.(lastError, attempt + 1, delay);
118
119
 
119
120
  try {
121
+ // oxlint-disable-next-line eslint(no-await-in-loop)
120
122
  await sleep(delay, options?.signal);
121
123
  } catch {
122
124
  // Aborted during sleep