@soleri/core 9.0.4 → 9.3.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 (744) hide show
  1. package/data/flows/build.flow.yaml +8 -9
  2. package/data/flows/deliver.flow.yaml +9 -10
  3. package/data/flows/design.flow.yaml +3 -4
  4. package/data/flows/enhance.flow.yaml +5 -6
  5. package/data/flows/explore.flow.yaml +3 -4
  6. package/data/flows/fix.flow.yaml +5 -6
  7. package/data/flows/plan.flow.yaml +4 -5
  8. package/data/flows/review.flow.yaml +3 -4
  9. package/dist/brain/intelligence.d.ts +27 -0
  10. package/dist/brain/intelligence.d.ts.map +1 -1
  11. package/dist/brain/intelligence.js +160 -14
  12. package/dist/brain/intelligence.js.map +1 -1
  13. package/dist/brain/learning-radar.d.ts +4 -0
  14. package/dist/brain/learning-radar.d.ts.map +1 -1
  15. package/dist/brain/learning-radar.js +20 -1
  16. package/dist/brain/learning-radar.js.map +1 -1
  17. package/dist/brain/strength-scorer.d.ts +31 -0
  18. package/dist/brain/strength-scorer.d.ts.map +1 -0
  19. package/dist/brain/strength-scorer.js +264 -0
  20. package/dist/brain/strength-scorer.js.map +1 -0
  21. package/dist/chat/agent-loop.d.ts.map +1 -1
  22. package/dist/chat/agent-loop.js +2 -0
  23. package/dist/chat/agent-loop.js.map +1 -1
  24. package/dist/chat/notifications.d.ts.map +1 -1
  25. package/dist/chat/notifications.js +2 -0
  26. package/dist/chat/notifications.js.map +1 -1
  27. package/dist/claudemd/compose.js +1 -1
  28. package/dist/claudemd/compose.js.map +1 -1
  29. package/dist/control/intent-router.d.ts.map +1 -1
  30. package/dist/control/intent-router.js +12 -4
  31. package/dist/control/intent-router.js.map +1 -1
  32. package/dist/curator/contradiction-detector.d.ts +27 -0
  33. package/dist/curator/contradiction-detector.d.ts.map +1 -0
  34. package/dist/curator/contradiction-detector.js +62 -0
  35. package/dist/curator/contradiction-detector.js.map +1 -0
  36. package/dist/curator/curator.d.ts +3 -4
  37. package/dist/curator/curator.d.ts.map +1 -1
  38. package/dist/curator/curator.js +94 -453
  39. package/dist/curator/curator.js.map +1 -1
  40. package/dist/curator/duplicate-detector.d.ts +14 -0
  41. package/dist/curator/duplicate-detector.d.ts.map +1 -0
  42. package/dist/curator/duplicate-detector.js +77 -0
  43. package/dist/curator/duplicate-detector.js.map +1 -0
  44. package/dist/curator/health-audit.d.ts +15 -0
  45. package/dist/curator/health-audit.d.ts.map +1 -0
  46. package/dist/curator/health-audit.js +97 -0
  47. package/dist/curator/health-audit.js.map +1 -0
  48. package/dist/curator/metadata-enricher.d.ts +17 -0
  49. package/dist/curator/metadata-enricher.d.ts.map +1 -0
  50. package/dist/curator/metadata-enricher.js +60 -0
  51. package/dist/curator/metadata-enricher.js.map +1 -0
  52. package/dist/curator/schema.d.ts +7 -0
  53. package/dist/curator/schema.d.ts.map +1 -0
  54. package/dist/curator/schema.js +62 -0
  55. package/dist/curator/schema.js.map +1 -0
  56. package/dist/curator/tag-manager.d.ts +36 -0
  57. package/dist/curator/tag-manager.d.ts.map +1 -0
  58. package/dist/curator/tag-manager.js +78 -0
  59. package/dist/curator/tag-manager.js.map +1 -0
  60. package/dist/engine/bin/soleri-engine.js +24 -3
  61. package/dist/engine/bin/soleri-engine.js.map +1 -1
  62. package/dist/engine/core-ops.d.ts.map +1 -1
  63. package/dist/engine/core-ops.js +23 -8
  64. package/dist/engine/core-ops.js.map +1 -1
  65. package/dist/engine/module-manifest.d.ts.map +1 -1
  66. package/dist/engine/module-manifest.js +42 -2
  67. package/dist/engine/module-manifest.js.map +1 -1
  68. package/dist/engine/register-engine.d.ts.map +1 -1
  69. package/dist/engine/register-engine.js +50 -2
  70. package/dist/engine/register-engine.js.map +1 -1
  71. package/dist/errors/retry.d.ts.map +1 -1
  72. package/dist/errors/retry.js +2 -0
  73. package/dist/errors/retry.js.map +1 -1
  74. package/dist/facades/types.d.ts +1 -1
  75. package/dist/flows/chain-types.d.ts +18 -18
  76. package/dist/flows/gate-evaluator.d.ts.map +1 -1
  77. package/dist/flows/gate-evaluator.js +22 -0
  78. package/dist/flows/gate-evaluator.js.map +1 -1
  79. package/dist/flows/types.d.ts +157 -28
  80. package/dist/flows/types.d.ts.map +1 -1
  81. package/dist/flows/types.js +4 -0
  82. package/dist/flows/types.js.map +1 -1
  83. package/dist/index.d.ts +10 -2
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +9 -1
  86. package/dist/index.js.map +1 -1
  87. package/dist/intake/intake-pipeline.d.ts.map +1 -1
  88. package/dist/intake/intake-pipeline.js +1 -0
  89. package/dist/intake/intake-pipeline.js.map +1 -1
  90. package/dist/intake/text-ingester.d.ts.map +1 -1
  91. package/dist/intake/text-ingester.js +2 -0
  92. package/dist/intake/text-ingester.js.map +1 -1
  93. package/dist/llm/key-pool.d.ts +1 -1
  94. package/dist/llm/key-pool.d.ts.map +1 -1
  95. package/dist/llm/key-pool.js +3 -4
  96. package/dist/llm/key-pool.js.map +1 -1
  97. package/dist/llm/utils.d.ts.map +1 -1
  98. package/dist/llm/utils.js +2 -0
  99. package/dist/llm/utils.js.map +1 -1
  100. package/dist/migrations/migration-runner.test-helpers.d.ts +13 -0
  101. package/dist/migrations/migration-runner.test-helpers.d.ts.map +1 -0
  102. package/dist/migrations/migration-runner.test-helpers.js +47 -0
  103. package/dist/migrations/migration-runner.test-helpers.js.map +1 -0
  104. package/dist/operator/operator-profile.d.ts +44 -0
  105. package/dist/operator/operator-profile.d.ts.map +1 -0
  106. package/dist/operator/operator-profile.js +383 -0
  107. package/dist/operator/operator-profile.js.map +1 -0
  108. package/dist/operator/operator-signals.d.ts +45 -0
  109. package/dist/operator/operator-signals.d.ts.map +1 -0
  110. package/dist/operator/operator-signals.js +228 -0
  111. package/dist/operator/operator-signals.js.map +1 -0
  112. package/dist/operator/operator-types.d.ts +360 -0
  113. package/dist/operator/operator-types.d.ts.map +1 -0
  114. package/dist/operator/operator-types.js +24 -0
  115. package/dist/operator/operator-types.js.map +1 -0
  116. package/dist/packs/types.d.ts +27 -27
  117. package/dist/paths.d.ts +40 -0
  118. package/dist/paths.d.ts.map +1 -0
  119. package/dist/paths.js +98 -0
  120. package/dist/paths.js.map +1 -0
  121. package/dist/persistence/index.d.ts +1 -1
  122. package/dist/persistence/index.d.ts.map +1 -1
  123. package/dist/persistence/index.js +1 -1
  124. package/dist/persistence/index.js.map +1 -1
  125. package/dist/persistence/sqlite-provider.d.ts +2 -0
  126. package/dist/persistence/sqlite-provider.d.ts.map +1 -1
  127. package/dist/persistence/sqlite-provider.js +8 -5
  128. package/dist/persistence/sqlite-provider.js.map +1 -1
  129. package/dist/planning/evidence-collector.d.ts +13 -1
  130. package/dist/planning/evidence-collector.d.ts.map +1 -1
  131. package/dist/planning/evidence-collector.js +33 -0
  132. package/dist/planning/evidence-collector.js.map +1 -1
  133. package/dist/planning/gap-analysis.d.ts +5 -4
  134. package/dist/planning/gap-analysis.d.ts.map +1 -1
  135. package/dist/planning/gap-analysis.js +7 -341
  136. package/dist/planning/gap-analysis.js.map +1 -1
  137. package/dist/planning/gap-passes.d.ts +19 -0
  138. package/dist/planning/gap-passes.d.ts.map +1 -0
  139. package/dist/planning/gap-passes.js +174 -0
  140. package/dist/planning/gap-passes.js.map +1 -0
  141. package/dist/planning/gap-patterns.d.ts +29 -0
  142. package/dist/planning/gap-patterns.d.ts.map +1 -0
  143. package/dist/planning/gap-patterns.js +175 -0
  144. package/dist/planning/gap-patterns.js.map +1 -0
  145. package/dist/planning/gap-types.d.ts +1 -1
  146. package/dist/planning/gap-types.d.ts.map +1 -1
  147. package/dist/planning/gap-types.js +1 -0
  148. package/dist/planning/gap-types.js.map +1 -1
  149. package/dist/planning/github-projection.d.ts +122 -0
  150. package/dist/planning/github-projection.d.ts.map +1 -0
  151. package/dist/planning/github-projection.js +313 -0
  152. package/dist/planning/github-projection.js.map +1 -0
  153. package/dist/planning/impact-analyzer.d.ts +26 -0
  154. package/dist/planning/impact-analyzer.d.ts.map +1 -0
  155. package/dist/planning/impact-analyzer.js +201 -0
  156. package/dist/planning/impact-analyzer.js.map +1 -0
  157. package/dist/planning/plan-lifecycle.d.ts +136 -0
  158. package/dist/planning/plan-lifecycle.d.ts.map +1 -0
  159. package/dist/planning/plan-lifecycle.js +309 -0
  160. package/dist/planning/plan-lifecycle.js.map +1 -0
  161. package/dist/planning/planner-types.d.ts +202 -0
  162. package/dist/planning/planner-types.d.ts.map +1 -0
  163. package/dist/planning/planner-types.js +6 -0
  164. package/dist/planning/planner-types.js.map +1 -0
  165. package/dist/planning/planner.d.ts +31 -383
  166. package/dist/planning/planner.d.ts.map +1 -1
  167. package/dist/planning/planner.js +151 -832
  168. package/dist/planning/planner.js.map +1 -1
  169. package/dist/planning/rationalization-detector.d.ts +32 -0
  170. package/dist/planning/rationalization-detector.d.ts.map +1 -0
  171. package/dist/planning/rationalization-detector.js +89 -0
  172. package/dist/planning/rationalization-detector.js.map +1 -0
  173. package/dist/planning/reconciliation-engine.d.ts +47 -0
  174. package/dist/planning/reconciliation-engine.d.ts.map +1 -0
  175. package/dist/planning/reconciliation-engine.js +128 -0
  176. package/dist/planning/reconciliation-engine.js.map +1 -0
  177. package/dist/planning/task-verifier.d.ts +85 -0
  178. package/dist/planning/task-verifier.d.ts.map +1 -0
  179. package/dist/planning/task-verifier.js +235 -0
  180. package/dist/planning/task-verifier.js.map +1 -0
  181. package/dist/plugins/types.d.ts +4 -4
  182. package/dist/runtime/admin-ops.d.ts +2 -2
  183. package/dist/runtime/admin-ops.d.ts.map +1 -1
  184. package/dist/runtime/admin-ops.js +44 -17
  185. package/dist/runtime/admin-ops.js.map +1 -1
  186. package/dist/runtime/admin-setup-ops.d.ts.map +1 -1
  187. package/dist/runtime/admin-setup-ops.js +22 -46
  188. package/dist/runtime/admin-setup-ops.js.map +1 -1
  189. package/dist/runtime/archive-ops.d.ts +10 -0
  190. package/dist/runtime/archive-ops.d.ts.map +1 -0
  191. package/dist/runtime/archive-ops.js +310 -0
  192. package/dist/runtime/archive-ops.js.map +1 -0
  193. package/dist/runtime/branching-ops.d.ts +12 -0
  194. package/dist/runtime/branching-ops.d.ts.map +1 -0
  195. package/dist/runtime/branching-ops.js +100 -0
  196. package/dist/runtime/branching-ops.js.map +1 -0
  197. package/dist/runtime/capture-ops.d.ts.map +1 -1
  198. package/dist/runtime/capture-ops.js +42 -7
  199. package/dist/runtime/capture-ops.js.map +1 -1
  200. package/dist/runtime/claude-md-helpers.js +1 -1
  201. package/dist/runtime/claude-md-helpers.js.map +1 -1
  202. package/dist/runtime/context-health.d.ts +31 -0
  203. package/dist/runtime/context-health.d.ts.map +1 -0
  204. package/dist/runtime/context-health.js +57 -0
  205. package/dist/runtime/context-health.js.map +1 -0
  206. package/dist/runtime/facades/archive-facade.d.ts +10 -0
  207. package/dist/runtime/facades/archive-facade.d.ts.map +1 -0
  208. package/dist/runtime/facades/archive-facade.js +11 -0
  209. package/dist/runtime/facades/archive-facade.js.map +1 -0
  210. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  211. package/dist/runtime/facades/brain-facade.js +2 -0
  212. package/dist/runtime/facades/brain-facade.js.map +1 -1
  213. package/dist/runtime/facades/branching-facade.d.ts +7 -0
  214. package/dist/runtime/facades/branching-facade.d.ts.map +1 -0
  215. package/dist/runtime/facades/branching-facade.js +8 -0
  216. package/dist/runtime/facades/branching-facade.js.map +1 -0
  217. package/dist/runtime/facades/chat-facade.d.ts +7 -0
  218. package/dist/runtime/facades/chat-facade.d.ts.map +1 -1
  219. package/dist/runtime/facades/chat-facade.js +15 -800
  220. package/dist/runtime/facades/chat-facade.js.map +1 -1
  221. package/dist/runtime/facades/chat-service-ops.d.ts +9 -0
  222. package/dist/runtime/facades/chat-service-ops.d.ts.map +1 -0
  223. package/dist/runtime/facades/chat-service-ops.js +332 -0
  224. package/dist/runtime/facades/chat-service-ops.js.map +1 -0
  225. package/dist/runtime/facades/chat-session-ops.d.ts +8 -0
  226. package/dist/runtime/facades/chat-session-ops.d.ts.map +1 -0
  227. package/dist/runtime/facades/chat-session-ops.js +136 -0
  228. package/dist/runtime/facades/chat-session-ops.js.map +1 -0
  229. package/dist/runtime/facades/chat-state.d.ts +31 -0
  230. package/dist/runtime/facades/chat-state.d.ts.map +1 -0
  231. package/dist/runtime/facades/chat-state.js +32 -0
  232. package/dist/runtime/facades/chat-state.js.map +1 -0
  233. package/dist/runtime/facades/chat-transport-ops.d.ts +9 -0
  234. package/dist/runtime/facades/chat-transport-ops.d.ts.map +1 -0
  235. package/dist/runtime/facades/chat-transport-ops.js +337 -0
  236. package/dist/runtime/facades/chat-transport-ops.js.map +1 -0
  237. package/dist/runtime/facades/control-facade.d.ts.map +1 -1
  238. package/dist/runtime/facades/control-facade.js +4 -1
  239. package/dist/runtime/facades/control-facade.js.map +1 -1
  240. package/dist/runtime/facades/index.d.ts.map +1 -1
  241. package/dist/runtime/facades/index.js +48 -0
  242. package/dist/runtime/facades/index.js.map +1 -1
  243. package/dist/runtime/facades/intake-facade.d.ts +9 -0
  244. package/dist/runtime/facades/intake-facade.d.ts.map +1 -0
  245. package/dist/runtime/facades/intake-facade.js +11 -0
  246. package/dist/runtime/facades/intake-facade.js.map +1 -0
  247. package/dist/runtime/facades/links-facade.d.ts +9 -0
  248. package/dist/runtime/facades/links-facade.d.ts.map +1 -0
  249. package/dist/runtime/facades/links-facade.js +10 -0
  250. package/dist/runtime/facades/links-facade.js.map +1 -0
  251. package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
  252. package/dist/runtime/facades/memory-facade.js +75 -6
  253. package/dist/runtime/facades/memory-facade.js.map +1 -1
  254. package/dist/runtime/facades/operator-facade.d.ts +8 -0
  255. package/dist/runtime/facades/operator-facade.d.ts.map +1 -0
  256. package/dist/runtime/facades/operator-facade.js +220 -0
  257. package/dist/runtime/facades/operator-facade.js.map +1 -0
  258. package/dist/runtime/facades/orchestrate-facade.js +3 -3
  259. package/dist/runtime/facades/orchestrate-facade.js.map +1 -1
  260. package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
  261. package/dist/runtime/facades/plan-facade.js +42 -6
  262. package/dist/runtime/facades/plan-facade.js.map +1 -1
  263. package/dist/runtime/facades/review-facade.d.ts +7 -0
  264. package/dist/runtime/facades/review-facade.d.ts.map +1 -0
  265. package/dist/runtime/facades/review-facade.js +8 -0
  266. package/dist/runtime/facades/review-facade.js.map +1 -0
  267. package/dist/runtime/facades/sync-facade.d.ts +7 -0
  268. package/dist/runtime/facades/sync-facade.d.ts.map +1 -0
  269. package/dist/runtime/facades/sync-facade.js +8 -0
  270. package/dist/runtime/facades/sync-facade.js.map +1 -0
  271. package/dist/runtime/facades/tier-facade.d.ts +7 -0
  272. package/dist/runtime/facades/tier-facade.d.ts.map +1 -0
  273. package/dist/runtime/facades/tier-facade.js +8 -0
  274. package/dist/runtime/facades/tier-facade.js.map +1 -0
  275. package/dist/runtime/facades/vault-facade.d.ts +12 -1
  276. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  277. package/dist/runtime/facades/vault-facade.js +55 -251
  278. package/dist/runtime/facades/vault-facade.js.map +1 -1
  279. package/dist/runtime/github-integration.d.ts +49 -0
  280. package/dist/runtime/github-integration.d.ts.map +1 -0
  281. package/dist/runtime/github-integration.js +120 -0
  282. package/dist/runtime/github-integration.js.map +1 -0
  283. package/dist/runtime/grading-ops.js +1 -1
  284. package/dist/runtime/grading-ops.js.map +1 -1
  285. package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
  286. package/dist/runtime/memory-extra-ops.js +6 -2
  287. package/dist/runtime/memory-extra-ops.js.map +1 -1
  288. package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
  289. package/dist/runtime/orchestrate-ops.js +386 -37
  290. package/dist/runtime/orchestrate-ops.js.map +1 -1
  291. package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
  292. package/dist/runtime/planning-extra-ops.js +69 -4
  293. package/dist/runtime/planning-extra-ops.js.map +1 -1
  294. package/dist/runtime/review-ops.d.ts +10 -0
  295. package/dist/runtime/review-ops.d.ts.map +1 -0
  296. package/dist/runtime/review-ops.js +97 -0
  297. package/dist/runtime/review-ops.js.map +1 -0
  298. package/dist/runtime/runtime.d.ts.map +1 -1
  299. package/dist/runtime/runtime.js +29 -12
  300. package/dist/runtime/runtime.js.map +1 -1
  301. package/dist/runtime/session-briefing.d.ts +3 -0
  302. package/dist/runtime/session-briefing.d.ts.map +1 -1
  303. package/dist/runtime/session-briefing.js +72 -1
  304. package/dist/runtime/session-briefing.js.map +1 -1
  305. package/dist/runtime/sync-ops.d.ts +12 -0
  306. package/dist/runtime/sync-ops.d.ts.map +1 -0
  307. package/dist/runtime/sync-ops.js +288 -0
  308. package/dist/runtime/sync-ops.js.map +1 -0
  309. package/dist/runtime/tier-ops.d.ts +13 -0
  310. package/dist/runtime/tier-ops.d.ts.map +1 -0
  311. package/dist/runtime/tier-ops.js +110 -0
  312. package/dist/runtime/tier-ops.js.map +1 -0
  313. package/dist/runtime/types.d.ts +10 -4
  314. package/dist/runtime/types.d.ts.map +1 -1
  315. package/dist/runtime/vault-extra-ops.d.ts +5 -4
  316. package/dist/runtime/vault-extra-ops.d.ts.map +1 -1
  317. package/dist/runtime/vault-extra-ops.js +5 -300
  318. package/dist/runtime/vault-extra-ops.js.map +1 -1
  319. package/dist/runtime/vault-sharing-ops.d.ts +4 -4
  320. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -1
  321. package/dist/runtime/vault-sharing-ops.js +5 -300
  322. package/dist/runtime/vault-sharing-ops.js.map +1 -1
  323. package/dist/skills/sync-skills.d.ts +27 -0
  324. package/dist/skills/sync-skills.d.ts.map +1 -0
  325. package/dist/skills/sync-skills.js +81 -0
  326. package/dist/skills/sync-skills.js.map +1 -0
  327. package/dist/update-check.d.ts +14 -0
  328. package/dist/update-check.d.ts.map +1 -0
  329. package/dist/update-check.js +96 -0
  330. package/dist/update-check.js.map +1 -0
  331. package/dist/vault/linking.d.ts +10 -12
  332. package/dist/vault/linking.d.ts.map +1 -1
  333. package/dist/vault/linking.js +140 -161
  334. package/dist/vault/linking.js.map +1 -1
  335. package/dist/vault/vault-entries.d.ts +69 -0
  336. package/dist/vault/vault-entries.d.ts.map +1 -0
  337. package/dist/vault/vault-entries.js +299 -0
  338. package/dist/vault/vault-entries.js.map +1 -0
  339. package/dist/vault/vault-interfaces.d.ts +153 -0
  340. package/dist/vault/vault-interfaces.d.ts.map +1 -0
  341. package/dist/vault/vault-interfaces.js +2 -0
  342. package/dist/vault/vault-interfaces.js.map +1 -0
  343. package/dist/vault/vault-maintenance.d.ts +40 -0
  344. package/dist/vault/vault-maintenance.d.ts.map +1 -0
  345. package/dist/vault/vault-maintenance.js +146 -0
  346. package/dist/vault/vault-maintenance.js.map +1 -0
  347. package/dist/vault/vault-markdown-sync.d.ts +22 -0
  348. package/dist/vault/vault-markdown-sync.d.ts.map +1 -0
  349. package/dist/vault/vault-markdown-sync.js +143 -0
  350. package/dist/vault/vault-markdown-sync.js.map +1 -0
  351. package/dist/vault/vault-memories.d.ts +61 -0
  352. package/dist/vault/vault-memories.d.ts.map +1 -0
  353. package/dist/vault/vault-memories.js +242 -0
  354. package/dist/vault/vault-memories.js.map +1 -0
  355. package/dist/vault/vault-schema.d.ts +9 -0
  356. package/dist/vault/vault-schema.d.ts.map +1 -0
  357. package/dist/vault/vault-schema.js +205 -0
  358. package/dist/vault/vault-schema.js.map +1 -0
  359. package/dist/vault/vault.d.ts +29 -81
  360. package/dist/vault/vault.d.ts.map +1 -1
  361. package/dist/vault/vault.js +82 -931
  362. package/dist/vault/vault.js.map +1 -1
  363. package/package.json +7 -7
  364. package/src/agency/agency-manager.test.ts +620 -0
  365. package/src/agency/default-rules.test.ts +236 -0
  366. package/src/{__tests__ → brain}/brain-intelligence.test.ts +37 -14
  367. package/src/{__tests__ → brain}/brain.test.ts +1 -1
  368. package/src/brain/intelligence.ts +196 -15
  369. package/src/brain/learning-radar.ts +22 -1
  370. package/src/{__tests__ → brain}/second-brain-features.test.ts +4 -4
  371. package/src/{__tests__ → brain}/session-lifecycle.test.ts +2 -2
  372. package/src/capabilities/chain-mapping.test.ts +66 -0
  373. package/src/capabilities/registry.test.ts +359 -0
  374. package/src/chat/agent-loop.test.ts +384 -0
  375. package/src/chat/agent-loop.ts +2 -0
  376. package/src/{__tests__ → chat}/chat-differentiators.test.ts +3 -3
  377. package/src/{__tests__ → chat}/chat-enhanced.test.ts +4 -4
  378. package/src/{__tests__ → chat}/chat-transport.test.ts +6 -6
  379. package/src/chat/mcp-bridge.test.ts +178 -0
  380. package/src/chat/notifications.ts +2 -0
  381. package/src/chat/output-compressor.test.ts +164 -0
  382. package/src/claudemd/compose.test.ts +178 -0
  383. package/src/claudemd/compose.ts +1 -1
  384. package/src/claudemd/inject.test.ts +201 -0
  385. package/src/context/context-engine.test.ts +506 -0
  386. package/src/control/identity-manager.test.ts +305 -0
  387. package/src/control/intent-router.test.ts +360 -0
  388. package/src/control/intent-router.ts +13 -4
  389. package/src/curator/classifier.test.ts +110 -0
  390. package/src/curator/contradiction-detector.test.ts +205 -0
  391. package/src/curator/contradiction-detector.ts +87 -0
  392. package/src/{__tests__ → curator}/curator-pipeline-e2e.test.ts +10 -10
  393. package/src/{__tests__ → curator}/curator.test.ts +77 -1
  394. package/src/curator/curator.ts +160 -600
  395. package/src/curator/duplicate-detector.test.ts +245 -0
  396. package/src/curator/duplicate-detector.ts +103 -0
  397. package/src/curator/health-audit.ts +126 -0
  398. package/src/curator/metadata-enricher.ts +84 -0
  399. package/src/curator/quality-gate.test.ts +175 -0
  400. package/src/curator/schema.ts +65 -0
  401. package/src/curator/tag-manager.test.ts +173 -0
  402. package/src/curator/tag-manager.ts +109 -0
  403. package/src/domain-packs/inject-rules.test.ts +117 -0
  404. package/src/domain-packs/knowledge-installer.test.ts +163 -0
  405. package/src/domain-packs/loader.test.ts +86 -0
  406. package/src/domain-packs/pack-runtime.test.ts +140 -0
  407. package/src/domain-packs/skills-installer.test.ts +135 -0
  408. package/src/domain-packs/token-resolver.test.ts +148 -0
  409. package/src/domain-packs/types.test.ts +144 -0
  410. package/src/enforcement/adapters/claude-code.test.ts +216 -0
  411. package/src/enforcement/registry.test.ts +258 -0
  412. package/src/engine/bin/soleri-engine.ts +30 -4
  413. package/src/engine/core-ops.test.ts +254 -0
  414. package/src/engine/core-ops.ts +25 -8
  415. package/src/engine/module-manifest.test.ts +125 -0
  416. package/src/engine/module-manifest.ts +42 -2
  417. package/src/engine/register-engine.test.ts +235 -0
  418. package/src/engine/register-engine.ts +50 -3
  419. package/src/errors/classify.test.ts +203 -0
  420. package/src/errors/retry.test.ts +153 -0
  421. package/src/errors/retry.ts +2 -0
  422. package/src/errors/types.test.ts +108 -0
  423. package/src/events/event-bus.test.ts +149 -0
  424. package/src/extensions/middleware.test.ts +234 -0
  425. package/src/facades/facade-factory.test.ts +470 -0
  426. package/src/flows/chain-runner.test.ts +273 -0
  427. package/src/flows/context-router.test.ts +52 -0
  428. package/src/flows/dispatch-registry.test.ts +128 -0
  429. package/src/flows/epilogue.test.ts +113 -0
  430. package/src/flows/executor.test.ts +263 -0
  431. package/src/flows/gate-evaluator.test.ts +200 -0
  432. package/src/flows/gate-evaluator.ts +23 -0
  433. package/src/flows/types.ts +4 -0
  434. package/src/governance/governance.test.ts +842 -0
  435. package/src/{__tests__ → health}/health-registry.test.ts +75 -55
  436. package/src/health/vault-integrity.test.ts +110 -0
  437. package/src/index.ts +92 -0
  438. package/src/intake/content-classifier.test.ts +279 -0
  439. package/src/intake/dedup-gate.test.ts +147 -0
  440. package/src/intake/intake-pipeline.test.ts +508 -0
  441. package/src/intake/intake-pipeline.ts +1 -0
  442. package/src/intake/text-ingester.test.ts +200 -0
  443. package/src/intake/text-ingester.ts +2 -0
  444. package/src/llm/key-pool.test.ts +234 -0
  445. package/src/llm/key-pool.ts +3 -4
  446. package/src/llm/llm-client.test.ts +342 -0
  447. package/src/llm/oauth-discovery.test.ts +180 -0
  448. package/src/llm/utils.test.ts +371 -0
  449. package/src/llm/utils.ts +2 -0
  450. package/src/{__tests__ → logging}/logger.test.ts +44 -62
  451. package/src/loop/loop-manager.test.ts +515 -0
  452. package/src/migrations/migration-runner.edge-cases.test.ts +314 -0
  453. package/src/migrations/migration-runner.test-helpers.ts +64 -0
  454. package/src/migrations/migration-runner.test.ts +385 -0
  455. package/src/operator/auto-signal-pipeline.test.ts +207 -0
  456. package/src/operator/operator-profile-extended.test.ts +330 -0
  457. package/src/operator/operator-profile.test.ts +332 -0
  458. package/src/operator/operator-profile.ts +485 -0
  459. package/src/operator/operator-signals-extended.test.ts +257 -0
  460. package/src/operator/operator-signals.test.ts +277 -0
  461. package/src/operator/operator-signals.ts +262 -0
  462. package/src/operator/operator-types.ts +444 -0
  463. package/src/operator/prompts/hook-precompact-operator-dispatch.md +98 -0
  464. package/src/operator/prompts/subagent-soft-signal-extractor.md +130 -0
  465. package/src/operator/prompts/subagent-synthesis-cognition.md +190 -0
  466. package/src/operator/prompts/subagent-synthesis-communication.md +146 -0
  467. package/src/operator/prompts/subagent-synthesis-technical.md +170 -0
  468. package/src/operator/prompts/subagent-synthesis-trust.md +149 -0
  469. package/src/{__tests__ → packs}/pack-lockfile.test.ts +3 -3
  470. package/src/{__tests__ → packs}/pack-system.test.ts +2 -2
  471. package/src/paths.ts +115 -0
  472. package/src/persistence/index.ts +1 -1
  473. package/src/persistence/sqlite-provider.test.ts +540 -0
  474. package/src/persistence/sqlite-provider.ts +8 -5
  475. package/src/persona/defaults.test.ts +55 -0
  476. package/src/persona/loader.test.ts +67 -0
  477. package/src/persona/prompt-generator.test.ts +127 -0
  478. package/src/planning/evidence-collector.test.ts +515 -0
  479. package/src/planning/evidence-collector.ts +47 -0
  480. package/src/planning/gap-analysis-alternatives.test.ts +199 -0
  481. package/src/planning/gap-analysis.ts +21 -636
  482. package/src/planning/gap-passes.test.ts +554 -0
  483. package/src/planning/gap-passes.ts +367 -0
  484. package/src/planning/gap-patterns.test.ts +394 -0
  485. package/src/planning/gap-patterns.ts +317 -0
  486. package/src/planning/gap-types.ts +4 -1
  487. package/src/planning/github-projection.test.ts +182 -0
  488. package/src/planning/github-projection.ts +446 -0
  489. package/src/planning/impact-analyzer.test.ts +167 -0
  490. package/src/planning/impact-analyzer.ts +251 -0
  491. package/src/planning/plan-lifecycle.test.ts +379 -0
  492. package/src/planning/plan-lifecycle.ts +377 -0
  493. package/src/planning/planner-types.ts +215 -0
  494. package/src/{__tests__ → planning}/planner.test.ts +179 -15
  495. package/src/planning/planner.ts +221 -1112
  496. package/src/planning/rationalization-detector.test.ts +156 -0
  497. package/src/planning/rationalization-detector.ts +136 -0
  498. package/src/planning/reconciliation-engine.test.ts +158 -0
  499. package/src/planning/reconciliation-engine.ts +161 -0
  500. package/src/planning/task-verifier.test.ts +267 -0
  501. package/src/planning/task-verifier.ts +309 -0
  502. package/src/planning/verification-protocol.test.ts +201 -0
  503. package/src/playbooks/generic/generic-playbooks.test.ts +438 -0
  504. package/src/playbooks/index.test.ts +77 -0
  505. package/src/playbooks/playbook-executor.test.ts +253 -0
  506. package/src/playbooks/playbook-registry.test.ts +232 -0
  507. package/src/playbooks/playbook-seeder.test.ts +153 -0
  508. package/src/plugins/plugin-loader.test.ts +217 -0
  509. package/src/plugins/plugin-registry.test.ts +284 -0
  510. package/src/project/project-registry.test.ts +439 -0
  511. package/src/prompts/parser.test.ts +100 -0
  512. package/src/prompts/template-manager.test.ts +112 -0
  513. package/src/{__tests__ → queue}/async-infrastructure.test.ts +3 -3
  514. package/src/queue/job-queue.test.ts +327 -0
  515. package/src/queue/pipeline-runner.test.ts +209 -0
  516. package/src/runtime/admin-extra-ops.test.ts +513 -0
  517. package/src/runtime/admin-ops.test.ts +255 -0
  518. package/src/runtime/admin-ops.ts +45 -17
  519. package/src/runtime/admin-setup-ops.test.ts +327 -0
  520. package/src/runtime/admin-setup-ops.ts +26 -42
  521. package/src/runtime/archive-ops.test.ts +272 -0
  522. package/src/runtime/archive-ops.ts +347 -0
  523. package/src/runtime/branching-ops.test.ts +144 -0
  524. package/src/runtime/branching-ops.ts +107 -0
  525. package/src/runtime/capture-ops.test.ts +419 -0
  526. package/src/runtime/capture-ops.ts +50 -8
  527. package/src/runtime/chain-ops.test.ts +159 -0
  528. package/src/runtime/claude-md-helpers.test.ts +189 -0
  529. package/src/runtime/claude-md-helpers.ts +1 -1
  530. package/src/runtime/context-health.test.ts +76 -0
  531. package/src/runtime/context-health.ts +83 -0
  532. package/src/runtime/curator-extra-ops.test.ts +204 -0
  533. package/src/runtime/deprecation.test.ts +98 -0
  534. package/src/runtime/domain-ops.test.ts +278 -0
  535. package/src/runtime/facades/admin-facade.test.ts +330 -0
  536. package/src/runtime/facades/agency-facade.test.ts +278 -0
  537. package/src/runtime/facades/archive-facade.test.ts +308 -0
  538. package/src/runtime/facades/archive-facade.ts +14 -0
  539. package/src/runtime/facades/brain-facade.test.ts +818 -0
  540. package/src/runtime/facades/brain-facade.ts +2 -0
  541. package/src/runtime/facades/branching-facade.test.ts +43 -0
  542. package/src/runtime/facades/branching-facade.ts +11 -0
  543. package/src/runtime/facades/chat-facade.test.ts +219 -0
  544. package/src/runtime/facades/chat-facade.ts +15 -906
  545. package/src/runtime/facades/chat-service-ops.test.ts +381 -0
  546. package/src/runtime/facades/chat-service-ops.ts +376 -0
  547. package/src/runtime/facades/chat-session-ops.test.ts +212 -0
  548. package/src/runtime/facades/chat-session-ops.ts +146 -0
  549. package/src/runtime/facades/chat-state.ts +60 -0
  550. package/src/runtime/facades/chat-transport-ops.test.ts +336 -0
  551. package/src/runtime/facades/chat-transport-ops.ts +379 -0
  552. package/src/runtime/facades/context-facade.test.ts +123 -0
  553. package/src/runtime/facades/control-facade.test.ts +436 -0
  554. package/src/runtime/facades/control-facade.ts +6 -1
  555. package/src/runtime/facades/curator-facade.test.ts +303 -0
  556. package/src/runtime/facades/index.ts +48 -0
  557. package/src/runtime/facades/intake-facade.test.ts +215 -0
  558. package/src/runtime/facades/intake-facade.ts +14 -0
  559. package/src/runtime/facades/links-facade.test.ts +203 -0
  560. package/src/runtime/facades/links-facade.ts +13 -0
  561. package/src/runtime/facades/loop-facade.test.ts +262 -0
  562. package/src/runtime/facades/memory-facade.test.ts +283 -0
  563. package/src/runtime/facades/memory-facade.ts +78 -6
  564. package/src/runtime/facades/operator-facade.test.ts +221 -0
  565. package/src/runtime/facades/operator-facade.ts +244 -0
  566. package/src/runtime/facades/orchestrate-facade.test.ts +191 -0
  567. package/src/runtime/facades/orchestrate-facade.ts +3 -3
  568. package/src/runtime/facades/plan-facade.test.ts +283 -0
  569. package/src/runtime/facades/plan-facade.ts +47 -6
  570. package/src/runtime/facades/review-facade.test.ts +82 -0
  571. package/src/runtime/facades/review-facade.ts +11 -0
  572. package/src/runtime/facades/sync-facade.test.ts +113 -0
  573. package/src/runtime/facades/sync-facade.ts +11 -0
  574. package/src/runtime/facades/tier-facade.test.ts +47 -0
  575. package/src/runtime/facades/tier-facade.ts +11 -0
  576. package/src/runtime/facades/vault-facade.test.ts +563 -0
  577. package/src/runtime/facades/vault-facade.ts +66 -265
  578. package/src/runtime/feature-flags.test.ts +140 -0
  579. package/src/runtime/github-integration.test.ts +89 -0
  580. package/src/runtime/github-integration.ts +162 -0
  581. package/src/runtime/grading-ops.test.ts +172 -0
  582. package/src/runtime/grading-ops.ts +1 -1
  583. package/src/runtime/intake-ops.test.ts +261 -0
  584. package/src/runtime/loop-ops.test.ts +248 -0
  585. package/src/runtime/memory-cross-project-ops.test.ts +188 -0
  586. package/src/runtime/memory-extra-ops.test.ts +453 -0
  587. package/src/runtime/memory-extra-ops.ts +6 -2
  588. package/src/runtime/orchestrate-ops.test.ts +302 -0
  589. package/src/runtime/orchestrate-ops.ts +461 -45
  590. package/src/runtime/pack-ops.test.ts +175 -0
  591. package/src/runtime/planning-extra-ops.test.ts +593 -0
  592. package/src/runtime/planning-extra-ops.ts +74 -4
  593. package/src/{__tests__ → runtime}/playbook-ops-execution.test.ts +3 -3
  594. package/src/runtime/playbook-ops.test.ts +285 -0
  595. package/src/runtime/plugin-ops.test.ts +259 -0
  596. package/src/runtime/project-ops.test.ts +255 -0
  597. package/src/runtime/review-ops.test.ts +142 -0
  598. package/src/runtime/review-ops.ts +99 -0
  599. package/src/runtime/runtime.test.ts +363 -0
  600. package/src/runtime/runtime.ts +41 -12
  601. package/src/runtime/session-briefing.test.ts +431 -0
  602. package/src/runtime/session-briefing.ts +86 -1
  603. package/src/runtime/sync-ops.test.ts +212 -0
  604. package/src/runtime/sync-ops.ts +325 -0
  605. package/src/runtime/telemetry-ops.test.ts +157 -0
  606. package/src/runtime/tier-ops.test.ts +159 -0
  607. package/src/runtime/tier-ops.ts +119 -0
  608. package/src/runtime/types.ts +10 -4
  609. package/src/runtime/vault-extra-ops.test.ts +270 -0
  610. package/src/runtime/vault-extra-ops.ts +5 -332
  611. package/src/runtime/vault-linking-ops.test.ts +237 -0
  612. package/src/runtime/vault-sharing-ops.test.ts +127 -0
  613. package/src/runtime/vault-sharing-ops.ts +5 -329
  614. package/src/skills/sync-skills.ts +98 -0
  615. package/src/streams/normalize.test.ts +95 -0
  616. package/src/streams/replayable-stream.test.ts +166 -0
  617. package/src/telemetry/telemetry.test.ts +143 -0
  618. package/src/transport/http-server.test.ts +394 -0
  619. package/src/transport/lsp-server.test.ts +458 -0
  620. package/src/transport/rate-limiter.test.ts +126 -0
  621. package/src/transport/session-manager.test.ts +133 -0
  622. package/src/transport/token-auth.test.ts +136 -0
  623. package/src/transport/ws-server.test.ts +297 -0
  624. package/src/update-check.ts +111 -0
  625. package/src/vault/__tests__/vault-characterization.test.ts +579 -0
  626. package/src/vault/content-hash.test.ts +78 -0
  627. package/src/vault/git-vault-sync.test.ts +234 -0
  628. package/src/vault/knowledge-review.test.ts +269 -0
  629. package/src/vault/linking.test.ts +391 -0
  630. package/src/vault/linking.ts +188 -181
  631. package/src/vault/obsidian-sync.test.ts +345 -0
  632. package/src/vault/playbook.test.ts +152 -0
  633. package/src/vault/scope-detector.test.ts +185 -0
  634. package/src/vault/vault-branching.test.ts +252 -0
  635. package/src/{__tests__ → vault}/vault-connect.test.ts +1 -1
  636. package/src/vault/vault-entries.ts +426 -0
  637. package/src/vault/vault-maintenance.ts +200 -0
  638. package/src/vault/vault-manager.test.ts +206 -0
  639. package/src/vault/vault-markdown-sync.test.ts +203 -0
  640. package/src/vault/vault-markdown-sync.ts +163 -0
  641. package/src/vault/vault-memories.ts +339 -0
  642. package/src/{__tests__ → vault}/vault-scaling.test.ts +1 -1
  643. package/src/vault/vault-schema.ts +238 -0
  644. package/src/{__tests__ → vault}/vault-sharing.test.ts +4 -4
  645. package/src/{__tests__ → vault}/vault.test.ts +2 -2
  646. package/src/vault/vault.ts +87 -1123
  647. package/dist/cognee/client.d.ts +0 -43
  648. package/dist/cognee/client.d.ts.map +0 -1
  649. package/dist/cognee/client.js +0 -375
  650. package/dist/cognee/client.js.map +0 -1
  651. package/dist/cognee/sync-manager.d.ts +0 -153
  652. package/dist/cognee/sync-manager.d.ts.map +0 -1
  653. package/dist/cognee/sync-manager.js +0 -390
  654. package/dist/cognee/sync-manager.js.map +0 -1
  655. package/dist/cognee/types.d.ts +0 -62
  656. package/dist/cognee/types.d.ts.map +0 -1
  657. package/dist/cognee/types.js +0 -3
  658. package/dist/cognee/types.js.map +0 -1
  659. package/dist/governance/index.d.ts +0 -3
  660. package/dist/governance/index.d.ts.map +0 -1
  661. package/dist/governance/index.js +0 -2
  662. package/dist/governance/index.js.map +0 -1
  663. package/dist/health/doctor-checks.d.ts +0 -15
  664. package/dist/health/doctor-checks.d.ts.map +0 -1
  665. package/dist/health/doctor-checks.js +0 -98
  666. package/dist/health/doctor-checks.js.map +0 -1
  667. package/dist/persistence/postgres-provider.d.ts +0 -81
  668. package/dist/persistence/postgres-provider.d.ts.map +0 -1
  669. package/dist/persistence/postgres-provider.js +0 -256
  670. package/dist/persistence/postgres-provider.js.map +0 -1
  671. package/dist/runtime/cognee-sync-ops.d.ts +0 -12
  672. package/dist/runtime/cognee-sync-ops.d.ts.map +0 -1
  673. package/dist/runtime/cognee-sync-ops.js +0 -93
  674. package/dist/runtime/cognee-sync-ops.js.map +0 -1
  675. package/dist/runtime/core-ops.d.ts +0 -23
  676. package/dist/runtime/core-ops.d.ts.map +0 -1
  677. package/dist/runtime/core-ops.js +0 -1296
  678. package/dist/runtime/core-ops.js.map +0 -1
  679. package/dist/runtime/facades/cognee-facade.d.ts +0 -8
  680. package/dist/runtime/facades/cognee-facade.d.ts.map +0 -1
  681. package/dist/runtime/facades/cognee-facade.js +0 -156
  682. package/dist/runtime/facades/cognee-facade.js.map +0 -1
  683. package/src/__tests__/admin-extra-ops.test.ts +0 -484
  684. package/src/__tests__/admin-ops.test.ts +0 -268
  685. package/src/__tests__/admin-setup-ops.test.ts +0 -355
  686. package/src/__tests__/agency-manager.test.ts +0 -374
  687. package/src/__tests__/agent-loop.test.ts +0 -256
  688. package/src/__tests__/capture-ops.test.ts +0 -784
  689. package/src/__tests__/claudemd.test.ts +0 -282
  690. package/src/__tests__/content-hash.test.ts +0 -60
  691. package/src/__tests__/context-engine.test.ts +0 -251
  692. package/src/__tests__/core-ops.test.ts +0 -550
  693. package/src/__tests__/curator-extra-ops.test.ts +0 -383
  694. package/src/__tests__/deprecation.test.ts +0 -78
  695. package/src/__tests__/domain-ops.test.ts +0 -226
  696. package/src/__tests__/domain-packs.test.ts +0 -421
  697. package/src/__tests__/enforcement.test.ts +0 -153
  698. package/src/__tests__/errors.test.ts +0 -388
  699. package/src/__tests__/extensions.test.ts +0 -233
  700. package/src/__tests__/facade-factory.test.ts +0 -271
  701. package/src/__tests__/feature-flags.test.ts +0 -137
  702. package/src/__tests__/flows.test.ts +0 -604
  703. package/src/__tests__/git-vault-sync.test.ts +0 -230
  704. package/src/__tests__/governance.test.ts +0 -522
  705. package/src/__tests__/grading-ops.test.ts +0 -361
  706. package/src/__tests__/identity-manager.test.ts +0 -243
  707. package/src/__tests__/intake-pipeline.test.ts +0 -162
  708. package/src/__tests__/intent-router.test.ts +0 -222
  709. package/src/__tests__/knowledge-review.test.ts +0 -104
  710. package/src/__tests__/llm-client.test.ts +0 -69
  711. package/src/__tests__/llm.test.ts +0 -556
  712. package/src/__tests__/loader.test.ts +0 -176
  713. package/src/__tests__/loop-ops.test.ts +0 -469
  714. package/src/__tests__/lsp-transport.test.ts +0 -442
  715. package/src/__tests__/memory-cross-project-ops.test.ts +0 -248
  716. package/src/__tests__/memory-extra-ops.test.ts +0 -352
  717. package/src/__tests__/migration-runner.test.ts +0 -170
  718. package/src/__tests__/module-manifest-drift.test.ts +0 -59
  719. package/src/__tests__/normalize.test.ts +0 -85
  720. package/src/__tests__/obsidian-sync.test.ts +0 -354
  721. package/src/__tests__/orchestrate-ops.test.ts +0 -289
  722. package/src/__tests__/pack-ops.test.ts +0 -146
  723. package/src/__tests__/persistence.test.ts +0 -291
  724. package/src/__tests__/planning-extra-ops.test.ts +0 -706
  725. package/src/__tests__/playbook-executor.test.ts +0 -249
  726. package/src/__tests__/playbook-registry.test.ts +0 -326
  727. package/src/__tests__/playbook-seeder.test.ts +0 -163
  728. package/src/__tests__/playbook.test.ts +0 -389
  729. package/src/__tests__/plugin-ops.test.ts +0 -411
  730. package/src/__tests__/plugin-system.test.ts +0 -509
  731. package/src/__tests__/project-ops.test.ts +0 -381
  732. package/src/__tests__/replayable-stream.test.ts +0 -177
  733. package/src/__tests__/runtime.test.ts +0 -95
  734. package/src/__tests__/scope-detector.test.ts +0 -121
  735. package/src/__tests__/template-manager.test.ts +0 -222
  736. package/src/__tests__/token-resolver.test.ts +0 -79
  737. package/src/__tests__/transport.test.ts +0 -758
  738. package/src/__tests__/vault-branching.test.ts +0 -274
  739. package/src/__tests__/vault-extra-ops.test.ts +0 -482
  740. package/src/__tests__/vault-integrity.test.ts +0 -71
  741. package/src/__tests__/vault-manager.test.ts +0 -238
  742. package/src/__tests__/ws-transport.test.ts +0 -479
  743. package/src/engine/index.ts +0 -21
  744. package/src/persona/index.ts +0 -9
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Session Manager Tests — session CRUD, expiry, and reaping.
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
6
+ import { SessionManager } from './session-manager.js';
7
+
8
+ describe('SessionManager', () => {
9
+ let manager: SessionManager;
10
+
11
+ beforeEach(() => {
12
+ manager = new SessionManager();
13
+ });
14
+
15
+ afterEach(() => {
16
+ manager.close();
17
+ });
18
+
19
+ describe('generateId', () => {
20
+ it('returns a UUID string', () => {
21
+ const id = manager.generateId();
22
+ expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
23
+ });
24
+
25
+ it('generates unique IDs', () => {
26
+ const ids = new Set(Array.from({ length: 10 }, () => manager.generateId()));
27
+ expect(ids.size).toBe(10);
28
+ });
29
+ });
30
+
31
+ describe('add / get / remove', () => {
32
+ it('adds and retrieves a session', () => {
33
+ const session = manager.add('s1', 'transport', 'server');
34
+ expect(session.id).toBe('s1');
35
+ expect(session.transport).toBe('transport');
36
+ expect(session.server).toBe('server');
37
+ expect(session.createdAt).toBeGreaterThan(0);
38
+ expect(manager.get('s1')).toBe(session);
39
+ });
40
+
41
+ it('returns undefined for missing session', () => {
42
+ expect(manager.get('nonexistent')).toBeUndefined();
43
+ });
44
+
45
+ it('removes a session', () => {
46
+ manager.add('s1', null, null);
47
+ expect(manager.remove('s1')).toBe(true);
48
+ expect(manager.get('s1')).toBeUndefined();
49
+ });
50
+
51
+ it('returns false when removing nonexistent session', () => {
52
+ expect(manager.remove('nope')).toBe(false);
53
+ });
54
+ });
55
+
56
+ describe('size', () => {
57
+ it('starts at zero', () => {
58
+ expect(manager.size).toBe(0);
59
+ });
60
+
61
+ it('reflects additions and removals', () => {
62
+ manager.add('s1', null, null);
63
+ manager.add('s2', null, null);
64
+ expect(manager.size).toBe(2);
65
+ manager.remove('s1');
66
+ expect(manager.size).toBe(1);
67
+ });
68
+ });
69
+
70
+ describe('listIds', () => {
71
+ it('returns all session IDs', () => {
72
+ manager.add('a', null, null);
73
+ manager.add('b', null, null);
74
+ const ids = manager.listIds();
75
+ expect(ids).toContain('a');
76
+ expect(ids).toContain('b');
77
+ expect(ids).toHaveLength(2);
78
+ });
79
+ });
80
+
81
+ describe('close', () => {
82
+ it('clears all sessions and stops reaper', () => {
83
+ manager.add('s1', null, null);
84
+ manager.add('s2', null, null);
85
+ manager.startReaper();
86
+ manager.close();
87
+ expect(manager.size).toBe(0);
88
+ });
89
+ });
90
+
91
+ describe('reaper', () => {
92
+ it('does not start when ttl is 0', () => {
93
+ const m = new SessionManager({ ttl: 0 });
94
+ m.startReaper();
95
+ m.add('s1', null, null);
96
+ // No timer should be running - just verify it doesn't throw
97
+ m.close();
98
+ });
99
+
100
+ it('reaps expired sessions', async () => {
101
+ const onReap = vi.fn();
102
+ const m = new SessionManager({ ttl: 30, reaperInterval: 20, onReap });
103
+ m.add('s1', null, null);
104
+ m.startReaper();
105
+
106
+ await new Promise((r) => setTimeout(r, 80));
107
+ expect(m.size).toBe(0);
108
+ expect(onReap).toHaveBeenCalledTimes(1);
109
+ expect(onReap.mock.calls[0][0].id).toBe('s1');
110
+ m.close();
111
+ });
112
+
113
+ it('keeps fresh sessions alive', async () => {
114
+ const m = new SessionManager({ ttl: 200, reaperInterval: 20 });
115
+ m.add('s1', null, null);
116
+ m.startReaper();
117
+
118
+ await new Promise((r) => setTimeout(r, 50));
119
+ expect(m.size).toBe(1);
120
+ m.close();
121
+ });
122
+
123
+ it('stopReaper prevents further reaping', () => {
124
+ const m = new SessionManager({ ttl: 50, reaperInterval: 20 });
125
+ m.startReaper();
126
+ m.stopReaper();
127
+ m.add('s1', null, null);
128
+ // Session should remain because reaper is stopped
129
+ expect(m.size).toBe(1);
130
+ m.close();
131
+ });
132
+ });
133
+ });
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Token Auth Tests — token generation, validation, persistence, and request auth.
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
6
+ import { mkdtempSync, rmSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+ import { tmpdir } from 'node:os';
9
+ import {
10
+ generateToken,
11
+ validateBearerToken,
12
+ authenticateRequest,
13
+ loadToken,
14
+ } from './token-auth.js';
15
+
16
+ describe('generateToken', () => {
17
+ it('returns a 64-character hex string', () => {
18
+ const token = generateToken();
19
+ expect(token).toMatch(/^[0-9a-f]{64}$/);
20
+ });
21
+
22
+ it('generates unique tokens', () => {
23
+ const tokens = new Set(Array.from({ length: 10 }, () => generateToken()));
24
+ expect(tokens.size).toBe(10);
25
+ });
26
+ });
27
+
28
+ describe('validateBearerToken', () => {
29
+ const expected = 'secret-token-123';
30
+
31
+ it('returns true for valid bearer token', () => {
32
+ expect(validateBearerToken('Bearer secret-token-123', expected)).toBe(true);
33
+ });
34
+
35
+ it('returns false for missing header', () => {
36
+ expect(validateBearerToken(undefined, expected)).toBe(false);
37
+ });
38
+
39
+ it('returns false for wrong prefix', () => {
40
+ expect(validateBearerToken('Basic secret-token-123', expected)).toBe(false);
41
+ });
42
+
43
+ it('returns false for wrong token', () => {
44
+ expect(validateBearerToken('Bearer wrong-token', expected)).toBe(false);
45
+ });
46
+
47
+ it('returns false for empty string', () => {
48
+ expect(validateBearerToken('', expected)).toBe(false);
49
+ });
50
+
51
+ it('returns false for length mismatch', () => {
52
+ expect(validateBearerToken('Bearer short', expected)).toBe(false);
53
+ });
54
+ });
55
+
56
+ describe('authenticateRequest', () => {
57
+ const token = 'test-token';
58
+
59
+ function makeReq(authorization?: string) {
60
+ return { headers: { authorization } } as unknown;
61
+ }
62
+
63
+ function makeRes() {
64
+ const res: Record<string, unknown> = {
65
+ writeHead: vi.fn().mockReturnThis(),
66
+ end: vi.fn(),
67
+ };
68
+ return res;
69
+ }
70
+
71
+ it('returns true for valid auth', () => {
72
+ const result = authenticateRequest(makeReq(`Bearer ${token}`), makeRes(), token);
73
+ expect(result).toBe(true);
74
+ });
75
+
76
+ it('returns false and sends 401 for invalid auth', () => {
77
+ const res = makeRes();
78
+ const result = authenticateRequest(makeReq('Bearer wrong'), res, token);
79
+ expect(result).toBe(false);
80
+ expect(res.writeHead).toHaveBeenCalledWith(401, { 'Content-Type': 'application/json' });
81
+ expect(res.end).toHaveBeenCalled();
82
+ });
83
+
84
+ it('returns false when no auth header present', () => {
85
+ const res = makeRes();
86
+ const result = authenticateRequest(makeReq(), res, token);
87
+ expect(result).toBe(false);
88
+ expect(res.writeHead).toHaveBeenCalledWith(401, expect.any(Object));
89
+ });
90
+ });
91
+
92
+ describe('loadToken / saveToken / getOrGenerateToken', () => {
93
+ let tmpDir: string;
94
+ const _agentId = 'test-agent';
95
+
96
+ beforeEach(() => {
97
+ tmpDir = mkdtempSync(join(tmpdir(), 'token-auth-test-'));
98
+ // Override homedir by setting the env and using a custom agent path
99
+ vi.stubEnv('TEST_AGENT_HTTP_TOKEN', '');
100
+ });
101
+
102
+ afterEach(() => {
103
+ vi.unstubAllEnvs();
104
+ rmSync(tmpDir, { recursive: true, force: true });
105
+ });
106
+
107
+ it('loadToken returns undefined when no env or file exists', () => {
108
+ const result = loadToken('nonexistent-agent-xyz');
109
+ expect(result).toBeUndefined();
110
+ });
111
+
112
+ it('loadToken reads from environment variable', () => {
113
+ vi.stubEnv('MY_AGENT_HTTP_TOKEN', 'env-token-value');
114
+ const result = loadToken('my-agent');
115
+ expect(result).toBe('env-token-value');
116
+ });
117
+
118
+ it('loadToken trims whitespace from env var', () => {
119
+ vi.stubEnv('MY_AGENT_HTTP_TOKEN', ' trimmed-token ');
120
+ const result = loadToken('my-agent');
121
+ expect(result).toBe('trimmed-token');
122
+ });
123
+
124
+ it('loadToken returns undefined for empty env var', () => {
125
+ vi.stubEnv('MY_AGENT_HTTP_TOKEN', ' ');
126
+ const result = loadToken('my-agent');
127
+ // Falls through to file-based lookup
128
+ expect(result === undefined || typeof result === 'string').toBe(true);
129
+ });
130
+
131
+ it('generateToken produces different tokens each call', () => {
132
+ const t1 = generateToken();
133
+ const t2 = generateToken();
134
+ expect(t1).not.toBe(t2);
135
+ });
136
+ });
@@ -0,0 +1,297 @@
1
+ /**
2
+ * WebSocket MCP Server Tests — handshake, messaging, heartbeat, lifecycle.
3
+ *
4
+ * Tests the WsMcpServer using a real localhost server but no external connections.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
8
+ import { createHash } from 'node:crypto';
9
+ import { createServer, type Server } from 'node:http';
10
+ import { connect } from 'node:net';
11
+ import { WsMcpServer, type WsServerCallbacks } from './ws-server.js';
12
+
13
+ const AUTH_TOKEN = 'ws-test-token';
14
+ const WS_MAGIC = '258EAFA5-E914-47DA-95CA-5AB5A4085CE3';
15
+
16
+ function defaultCallbacks(): WsServerCallbacks {
17
+ return {
18
+ onConnect: vi.fn(async () => {}),
19
+ onMessage: vi.fn(async () => {}),
20
+ onClose: vi.fn(),
21
+ onError: vi.fn(),
22
+ };
23
+ }
24
+
25
+ /** Build a raw WebSocket upgrade request */
26
+ function buildUpgradeRequest(opts?: { token?: string; key?: string; path?: string }): string {
27
+ const key = opts?.key ?? 'dGhlIHNhbXBsZSBub25jZQ==';
28
+ const token = opts?.token ?? AUTH_TOKEN;
29
+ const path = opts?.path ?? `/?token=${token}`;
30
+ return [
31
+ `GET ${path} HTTP/1.1`,
32
+ 'Host: localhost',
33
+ 'Upgrade: websocket',
34
+ 'Connection: Upgrade',
35
+ `Sec-WebSocket-Key: ${key}`,
36
+ 'Sec-WebSocket-Version: 13',
37
+ '',
38
+ '',
39
+ ].join('\r\n');
40
+ }
41
+
42
+ /** Encode a WebSocket text frame (unmasked, for reading) / masked for sending to server */
43
+ function encodeTextFrame(text: string, masked = true): Buffer {
44
+ const payload = Buffer.from(text, 'utf-8');
45
+ const len = payload.length;
46
+ let header: Buffer;
47
+
48
+ if (len < 126) {
49
+ header = Buffer.alloc(2);
50
+ header[0] = 0x81; // FIN + TEXT
51
+ header[1] = masked ? len | 0x80 : len;
52
+ } else {
53
+ header = Buffer.alloc(4);
54
+ header[0] = 0x81;
55
+ header[1] = masked ? 126 | 0x80 : 126;
56
+ header.writeUInt16BE(len, 2);
57
+ }
58
+
59
+ if (masked) {
60
+ const mask = Buffer.from([0x12, 0x34, 0x56, 0x78]);
61
+ const maskedPayload = Buffer.alloc(payload.length);
62
+ for (let i = 0; i < payload.length; i++) {
63
+ maskedPayload[i] = payload[i] ^ mask[i & 3];
64
+ }
65
+ return Buffer.concat([header, mask, maskedPayload]);
66
+ }
67
+
68
+ return Buffer.concat([header, payload]);
69
+ }
70
+
71
+ describe('WsMcpServer', () => {
72
+ let server: WsMcpServer;
73
+ let callbacks: WsServerCallbacks;
74
+
75
+ beforeEach(() => {
76
+ callbacks = defaultCallbacks();
77
+ server = new WsMcpServer(
78
+ { authToken: AUTH_TOKEN, heartbeatInterval: 0, sessionTTL: 0 },
79
+ callbacks,
80
+ );
81
+ });
82
+
83
+ afterEach(async () => {
84
+ // The WsMcpServer.stop() can hang when the underlying HTTP server
85
+ // waits for upgraded WebSocket connections to drain. Force-destroy.
86
+ const httpServer = (server as unknown).server as Server | undefined;
87
+ if (httpServer) {
88
+ // Force immediate close of all tracked sockets
89
+ for (const conn of ((server as unknown).connections as Map<string, unknown>)?.values() ??
90
+ []) {
91
+ conn.socket?.destroy();
92
+ }
93
+ ((server as unknown).connections as Map<string, unknown>)?.clear();
94
+ // Close with a force-destroy fallback
95
+ await Promise.race([
96
+ server.stop(),
97
+ new Promise<void>((resolve) => {
98
+ setTimeout(() => {
99
+ httpServer.closeAllConnections?.();
100
+ httpServer.close(() => {});
101
+ (server as unknown).server = undefined;
102
+ resolve();
103
+ }, 200);
104
+ }),
105
+ ]);
106
+ } else {
107
+ await server.stop().catch(() => {});
108
+ }
109
+ });
110
+
111
+ describe('construction', () => {
112
+ it('exposes sessionManager', () => {
113
+ expect(server.sessionManager).toBeDefined();
114
+ expect(server.sessionManager.size).toBe(0);
115
+ });
116
+
117
+ it('reports zero stats before start', () => {
118
+ const stats = server.getStats();
119
+ expect(stats.connections).toBe(0);
120
+ expect(stats.uptime).toBe(0);
121
+ });
122
+ });
123
+
124
+ describe('standalone start / stop', () => {
125
+ it('starts and stops without error', async () => {
126
+ await server.start(0);
127
+ expect(server.getStats().uptime).toBeGreaterThanOrEqual(0);
128
+ await server.stop();
129
+ });
130
+
131
+ it('stop is idempotent', async () => {
132
+ await server.start(0);
133
+ await server.stop();
134
+ await server.stop();
135
+ });
136
+ });
137
+
138
+ describe('attachTo', () => {
139
+ it('attaches to an existing HTTP server', async () => {
140
+ const httpServer = createServer();
141
+ await new Promise<void>((resolve) => httpServer.listen(0, '127.0.0.1', resolve));
142
+
143
+ const wsServer = new WsMcpServer(
144
+ { authToken: AUTH_TOKEN, heartbeatInterval: 0, sessionTTL: 0 },
145
+ callbacks,
146
+ );
147
+ wsServer.attachTo(httpServer);
148
+ expect(wsServer.getStats().uptime).toBeGreaterThanOrEqual(0);
149
+
150
+ await wsServer.stop();
151
+ await new Promise<void>((resolve, reject) => {
152
+ httpServer.close((err) => (err ? reject(err) : resolve()));
153
+ });
154
+ });
155
+ });
156
+
157
+ describe('WebSocket handshake', () => {
158
+ it('completes handshake with valid token', async () => {
159
+ await server.start(0);
160
+ const addr = (server as unknown).server?.address();
161
+ if (!addr || typeof addr === 'string') return;
162
+
163
+ const wsKey = 'dGhlIHNhbXBsZSBub25jZQ==';
164
+ const expectedAccept = createHash('sha1')
165
+ .update(wsKey + WS_MAGIC)
166
+ .digest('base64');
167
+
168
+ const socket = connect(addr.port, '127.0.0.1');
169
+ await new Promise<void>((resolve) => socket.on('connect', resolve));
170
+
171
+ socket.write(buildUpgradeRequest({ key: wsKey }));
172
+
173
+ const response = await new Promise<string>((resolve) => {
174
+ socket.once('data', (data) => resolve(data.toString()));
175
+ });
176
+
177
+ expect(response).toContain('101 Switching Protocols');
178
+ expect(response).toContain(`Sec-WebSocket-Accept: ${expectedAccept}`);
179
+ expect(response).toContain('mcp-session-id:');
180
+
181
+ // Wait for onConnect callback
182
+ await new Promise((r) => setTimeout(r, 50));
183
+ expect(callbacks.onConnect).toHaveBeenCalled();
184
+
185
+ socket.destroy();
186
+ });
187
+
188
+ it('rejects connection with invalid token', async () => {
189
+ await server.start(0);
190
+ const addr = (server as unknown).server?.address();
191
+ if (!addr || typeof addr === 'string') return;
192
+
193
+ const socket = connect(addr.port, '127.0.0.1');
194
+ await new Promise<void>((resolve) => socket.on('connect', resolve));
195
+
196
+ socket.write(buildUpgradeRequest({ token: 'wrong-token' }));
197
+
198
+ const response = await new Promise<string>((resolve) => {
199
+ socket.once('data', (data) => resolve(data.toString()));
200
+ });
201
+
202
+ expect(response).toContain('401');
203
+ socket.destroy();
204
+ });
205
+
206
+ it('supports Authorization header auth', async () => {
207
+ await server.start(0);
208
+ const addr = (server as unknown).server?.address();
209
+ if (!addr || typeof addr === 'string') return;
210
+
211
+ const socket = connect(addr.port, '127.0.0.1');
212
+ await new Promise<void>((resolve) => socket.on('connect', resolve));
213
+
214
+ const request = [
215
+ 'GET / HTTP/1.1',
216
+ 'Host: localhost',
217
+ 'Upgrade: websocket',
218
+ 'Connection: Upgrade',
219
+ 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==',
220
+ 'Sec-WebSocket-Version: 13',
221
+ `Authorization: Bearer ${AUTH_TOKEN}`,
222
+ '',
223
+ '',
224
+ ].join('\r\n');
225
+
226
+ socket.write(request);
227
+
228
+ const response = await new Promise<string>((resolve) => {
229
+ socket.once('data', (data) => resolve(data.toString()));
230
+ });
231
+
232
+ expect(response).toContain('101 Switching Protocols');
233
+ socket.destroy();
234
+ });
235
+ });
236
+
237
+ describe('send / broadcast', () => {
238
+ it('send returns false for unknown session', () => {
239
+ expect(server.send('nonexistent', { test: true })).toBe(false);
240
+ });
241
+
242
+ it('broadcast returns 0 with no connections', () => {
243
+ expect(server.broadcast({ test: true })).toBe(0);
244
+ });
245
+ });
246
+
247
+ describe('message handling', () => {
248
+ it('calls onMessage for valid JSON text frames', async () => {
249
+ await server.start(0);
250
+ const addr = (server as unknown).server?.address();
251
+ if (!addr || typeof addr === 'string') return;
252
+
253
+ const socket = connect(addr.port, '127.0.0.1');
254
+ await new Promise<void>((resolve) => socket.on('connect', resolve));
255
+ socket.write(buildUpgradeRequest());
256
+
257
+ // Wait for handshake
258
+ await new Promise<string>((resolve) => {
259
+ socket.once('data', (data) => resolve(data.toString()));
260
+ });
261
+
262
+ // Wait for onConnect
263
+ await new Promise((r) => setTimeout(r, 50));
264
+
265
+ // Send a masked text frame
266
+ const frame = encodeTextFrame(JSON.stringify({ method: 'test' }));
267
+ socket.write(frame);
268
+
269
+ await new Promise((r) => setTimeout(r, 100));
270
+ expect(callbacks.onMessage).toHaveBeenCalled();
271
+
272
+ socket.destroy();
273
+ });
274
+ });
275
+
276
+ describe('cleanup on stop', () => {
277
+ it('cleans up connections when server stops', async () => {
278
+ await server.start(0);
279
+ const addr = (server as unknown).server?.address();
280
+ if (!addr || typeof addr === 'string') return;
281
+
282
+ const socket = connect(addr.port, '127.0.0.1');
283
+ await new Promise<void>((resolve) => socket.on('connect', resolve));
284
+ socket.write(buildUpgradeRequest());
285
+ await new Promise<string>((resolve) => {
286
+ socket.once('data', (data) => resolve(data.toString()));
287
+ });
288
+
289
+ await new Promise((r) => setTimeout(r, 50));
290
+ expect(server.getStats().connections).toBe(1);
291
+
292
+ // server.stop() closes all connections and destroys sockets
293
+ socket.destroy();
294
+ await new Promise((r) => setTimeout(r, 50));
295
+ });
296
+ });
297
+ });
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Lightweight update notification — checks npm registry for newer @soleri/core.
3
+ *
4
+ * - Non-blocking: call without await, notifications appear in stderr
5
+ * - Rate-limited: at most once per 24 hours via cache file
6
+ * - Opt-out: set SOLERI_NO_UPDATE_CHECK=1
7
+ * - Zero dependencies: uses Node.js built-in fetch()
8
+ */
9
+
10
+ import { join } from 'node:path';
11
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
12
+ import { SOLERI_HOME, usedLegacyFallback } from './paths.js';
13
+
14
+ const CACHE_FILE = join(SOLERI_HOME, 'update-check.json');
15
+ const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
16
+ const NPM_REGISTRY_URL = 'https://registry.npmjs.org/@soleri/core/latest';
17
+ const FETCH_TIMEOUT_MS = 5_000;
18
+
19
+ interface CacheEntry {
20
+ checkedAt: number;
21
+ latestVersion: string | null;
22
+ }
23
+
24
+ function readCache(): CacheEntry | null {
25
+ try {
26
+ if (!existsSync(CACHE_FILE)) return null;
27
+ return JSON.parse(readFileSync(CACHE_FILE, 'utf-8'));
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ function writeCache(entry: CacheEntry): void {
34
+ try {
35
+ mkdirSync(SOLERI_HOME, { recursive: true });
36
+ writeFileSync(CACHE_FILE, JSON.stringify(entry), 'utf-8');
37
+ } catch {
38
+ // Non-critical — skip silently
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Simple semver comparison: returns true if b is newer than a.
44
+ * Handles x.y.z format only (no pre-release tags).
45
+ */
46
+ function isNewer(current: string, latest: string): boolean {
47
+ const a = current.split('.').map(Number);
48
+ const b = latest.split('.').map(Number);
49
+ for (let i = 0; i < 3; i++) {
50
+ if ((b[i] ?? 0) > (a[i] ?? 0)) return true;
51
+ if ((b[i] ?? 0) < (a[i] ?? 0)) return false;
52
+ }
53
+ return false;
54
+ }
55
+
56
+ /**
57
+ * Check for updates and emit stderr notifications.
58
+ * Call fire-and-forget (no await needed). Never throws.
59
+ */
60
+ export async function checkForUpdate(agentId: string, currentVersion: string): Promise<void> {
61
+ // Opt-out via env var
62
+ if (process.env.SOLERI_NO_UPDATE_CHECK === '1') return;
63
+
64
+ const tag = '[soleri]';
65
+
66
+ // Migration notification (always check, regardless of rate limit)
67
+ if (usedLegacyFallback(agentId)) {
68
+ console.error(
69
+ `${tag} Migration available: run "soleri agent migrate ${agentId}" to consolidate data under ~/.soleri/`,
70
+ );
71
+ }
72
+
73
+ // Rate limit: skip if checked recently
74
+ const cache = readCache();
75
+ if (cache && Date.now() - cache.checkedAt < CHECK_INTERVAL_MS) {
76
+ // Use cached result
77
+ if (cache.latestVersion && isNewer(currentVersion, cache.latestVersion)) {
78
+ console.error(
79
+ `${tag} Update available: @soleri/core ${currentVersion} → ${cache.latestVersion}`,
80
+ );
81
+ console.error(`${tag} Run: soleri agent update`);
82
+ }
83
+ return;
84
+ }
85
+
86
+ // Fetch latest version from npm
87
+ try {
88
+ const response = await fetch(NPM_REGISTRY_URL, {
89
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
90
+ headers: { Accept: 'application/json' },
91
+ });
92
+
93
+ if (!response.ok) {
94
+ writeCache({ checkedAt: Date.now(), latestVersion: null });
95
+ return;
96
+ }
97
+
98
+ const data = (await response.json()) as { version?: string };
99
+ const latestVersion = data.version ?? null;
100
+
101
+ writeCache({ checkedAt: Date.now(), latestVersion });
102
+
103
+ if (latestVersion && isNewer(currentVersion, latestVersion)) {
104
+ console.error(`${tag} Update available: @soleri/core ${currentVersion} → ${latestVersion}`);
105
+ console.error(`${tag} Run: soleri agent update`);
106
+ }
107
+ } catch {
108
+ // Network error, timeout, etc. — fail silently
109
+ writeCache({ checkedAt: Date.now(), latestVersion: null });
110
+ }
111
+ }