@soleri/core 2.10.0 → 2.11.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 (499) hide show
  1. package/dist/agency/agency-manager.d.ts +47 -0
  2. package/dist/agency/agency-manager.d.ts.map +1 -0
  3. package/dist/agency/agency-manager.js +281 -0
  4. package/dist/agency/agency-manager.js.map +1 -0
  5. package/dist/agency/index.d.ts +3 -0
  6. package/dist/agency/index.d.ts.map +1 -0
  7. package/dist/agency/index.js +2 -0
  8. package/dist/agency/index.js.map +1 -0
  9. package/dist/agency/types.d.ts +69 -0
  10. package/dist/agency/types.d.ts.map +1 -0
  11. package/dist/agency/types.js +5 -0
  12. package/dist/agency/types.js.map +1 -0
  13. package/dist/brain/brain.d.ts +0 -1
  14. package/dist/brain/brain.d.ts.map +1 -1
  15. package/dist/brain/brain.js +14 -0
  16. package/dist/brain/brain.js.map +1 -1
  17. package/dist/brain/intelligence.d.ts +5 -1
  18. package/dist/brain/intelligence.d.ts.map +1 -1
  19. package/dist/brain/intelligence.js +83 -0
  20. package/dist/brain/intelligence.js.map +1 -1
  21. package/dist/brain/types.d.ts +21 -0
  22. package/dist/brain/types.d.ts.map +1 -1
  23. package/dist/chat/agent-loop-types.d.ts +82 -0
  24. package/dist/chat/agent-loop-types.d.ts.map +1 -0
  25. package/dist/chat/agent-loop-types.js +8 -0
  26. package/dist/chat/agent-loop-types.js.map +1 -0
  27. package/dist/chat/agent-loop.d.ts +19 -0
  28. package/dist/chat/agent-loop.d.ts.map +1 -0
  29. package/dist/chat/agent-loop.js +261 -0
  30. package/dist/chat/agent-loop.js.map +1 -0
  31. package/dist/chat/auth-manager.d.ts +49 -0
  32. package/dist/chat/auth-manager.d.ts.map +1 -0
  33. package/dist/chat/auth-manager.js +152 -0
  34. package/dist/chat/auth-manager.js.map +1 -0
  35. package/dist/chat/browser-session.d.ts +86 -0
  36. package/dist/chat/browser-session.d.ts.map +1 -0
  37. package/dist/chat/browser-session.js +143 -0
  38. package/dist/chat/browser-session.js.map +1 -0
  39. package/dist/chat/cancellation.d.ts +54 -0
  40. package/dist/chat/cancellation.d.ts.map +1 -0
  41. package/dist/chat/cancellation.js +80 -0
  42. package/dist/chat/cancellation.js.map +1 -0
  43. package/dist/chat/chat-session.d.ts +86 -0
  44. package/dist/chat/chat-session.d.ts.map +1 -0
  45. package/dist/chat/chat-session.js +252 -0
  46. package/dist/chat/chat-session.js.map +1 -0
  47. package/dist/chat/file-handler.d.ts +63 -0
  48. package/dist/chat/file-handler.d.ts.map +1 -0
  49. package/dist/chat/file-handler.js +182 -0
  50. package/dist/chat/file-handler.js.map +1 -0
  51. package/dist/chat/fragment-buffer.d.ts +49 -0
  52. package/dist/chat/fragment-buffer.d.ts.map +1 -0
  53. package/dist/chat/fragment-buffer.js +130 -0
  54. package/dist/chat/fragment-buffer.js.map +1 -0
  55. package/dist/chat/index.d.ts +24 -0
  56. package/dist/chat/index.d.ts.map +1 -0
  57. package/dist/chat/index.js +15 -0
  58. package/dist/chat/index.js.map +1 -0
  59. package/dist/chat/mcp-bridge.d.ts +60 -0
  60. package/dist/chat/mcp-bridge.d.ts.map +1 -0
  61. package/dist/chat/mcp-bridge.js +111 -0
  62. package/dist/chat/mcp-bridge.js.map +1 -0
  63. package/dist/chat/notifications.d.ts +82 -0
  64. package/dist/chat/notifications.d.ts.map +1 -0
  65. package/dist/chat/notifications.js +119 -0
  66. package/dist/chat/notifications.js.map +1 -0
  67. package/dist/chat/output-compressor.d.ts +30 -0
  68. package/dist/chat/output-compressor.d.ts.map +1 -0
  69. package/dist/chat/output-compressor.js +95 -0
  70. package/dist/chat/output-compressor.js.map +1 -0
  71. package/dist/chat/queue.d.ts +91 -0
  72. package/dist/chat/queue.d.ts.map +1 -0
  73. package/dist/chat/queue.js +146 -0
  74. package/dist/chat/queue.js.map +1 -0
  75. package/dist/chat/response-chunker.d.ts +29 -0
  76. package/dist/chat/response-chunker.d.ts.map +1 -0
  77. package/dist/chat/response-chunker.js +163 -0
  78. package/dist/chat/response-chunker.js.map +1 -0
  79. package/dist/chat/self-update.d.ts +62 -0
  80. package/dist/chat/self-update.d.ts.map +1 -0
  81. package/dist/chat/self-update.js +90 -0
  82. package/dist/chat/self-update.js.map +1 -0
  83. package/dist/chat/types.d.ts +105 -0
  84. package/dist/chat/types.d.ts.map +1 -0
  85. package/dist/chat/types.js +8 -0
  86. package/dist/chat/types.js.map +1 -0
  87. package/dist/chat/voice.d.ts +39 -0
  88. package/dist/chat/voice.d.ts.map +1 -0
  89. package/dist/chat/voice.js +80 -0
  90. package/dist/chat/voice.js.map +1 -0
  91. package/dist/claudemd/compose.d.ts +31 -0
  92. package/dist/claudemd/compose.d.ts.map +1 -0
  93. package/dist/claudemd/compose.js +105 -0
  94. package/dist/claudemd/compose.js.map +1 -0
  95. package/dist/claudemd/index.d.ts +5 -0
  96. package/dist/claudemd/index.d.ts.map +1 -0
  97. package/dist/claudemd/index.js +3 -0
  98. package/dist/claudemd/index.js.map +1 -0
  99. package/dist/claudemd/inject.d.ts +31 -0
  100. package/dist/claudemd/inject.d.ts.map +1 -0
  101. package/dist/claudemd/inject.js +157 -0
  102. package/dist/claudemd/inject.js.map +1 -0
  103. package/dist/claudemd/types.d.ts +41 -0
  104. package/dist/claudemd/types.d.ts.map +1 -0
  105. package/dist/claudemd/types.js +5 -0
  106. package/dist/claudemd/types.js.map +1 -0
  107. package/dist/context/context-engine.d.ts +31 -0
  108. package/dist/context/context-engine.d.ts.map +1 -0
  109. package/dist/context/context-engine.js +245 -0
  110. package/dist/context/context-engine.js.map +1 -0
  111. package/dist/context/index.d.ts +3 -0
  112. package/dist/context/index.d.ts.map +1 -0
  113. package/dist/context/index.js +2 -0
  114. package/dist/context/index.js.map +1 -0
  115. package/dist/context/types.d.ts +54 -0
  116. package/dist/context/types.d.ts.map +1 -0
  117. package/dist/context/types.js +5 -0
  118. package/dist/context/types.js.map +1 -0
  119. package/dist/enforcement/adapters/claude-code.d.ts +18 -0
  120. package/dist/enforcement/adapters/claude-code.d.ts.map +1 -0
  121. package/dist/enforcement/adapters/claude-code.js +106 -0
  122. package/dist/enforcement/adapters/claude-code.js.map +1 -0
  123. package/dist/enforcement/adapters/index.d.ts +2 -0
  124. package/dist/enforcement/adapters/index.d.ts.map +1 -0
  125. package/dist/enforcement/adapters/index.js +2 -0
  126. package/dist/enforcement/adapters/index.js.map +1 -0
  127. package/dist/enforcement/index.d.ts +4 -0
  128. package/dist/enforcement/index.d.ts.map +1 -0
  129. package/dist/enforcement/index.js +3 -0
  130. package/dist/enforcement/index.js.map +1 -0
  131. package/dist/enforcement/registry.d.ts +23 -0
  132. package/dist/enforcement/registry.d.ts.map +1 -0
  133. package/dist/enforcement/registry.js +63 -0
  134. package/dist/enforcement/registry.js.map +1 -0
  135. package/dist/enforcement/types.d.ts +51 -0
  136. package/dist/enforcement/types.d.ts.map +1 -0
  137. package/dist/enforcement/types.js +8 -0
  138. package/dist/enforcement/types.js.map +1 -0
  139. package/dist/facades/facade-factory.d.ts +10 -3
  140. package/dist/facades/facade-factory.d.ts.map +1 -1
  141. package/dist/facades/facade-factory.js +94 -5
  142. package/dist/facades/facade-factory.js.map +1 -1
  143. package/dist/facades/types.d.ts +15 -1
  144. package/dist/facades/types.d.ts.map +1 -1
  145. package/dist/facades/types.js +6 -0
  146. package/dist/facades/types.js.map +1 -1
  147. package/dist/health/health-registry.d.ts +40 -0
  148. package/dist/health/health-registry.d.ts.map +1 -0
  149. package/dist/health/health-registry.js +134 -0
  150. package/dist/health/health-registry.js.map +1 -0
  151. package/dist/health/index.d.ts +5 -0
  152. package/dist/health/index.d.ts.map +1 -0
  153. package/dist/health/index.js +3 -0
  154. package/dist/health/index.js.map +1 -0
  155. package/dist/health/vault-integrity.d.ts +13 -0
  156. package/dist/health/vault-integrity.d.ts.map +1 -0
  157. package/dist/health/vault-integrity.js +49 -0
  158. package/dist/health/vault-integrity.js.map +1 -0
  159. package/dist/index.d.ts +67 -6
  160. package/dist/index.d.ts.map +1 -1
  161. package/dist/index.js +51 -3
  162. package/dist/index.js.map +1 -1
  163. package/dist/intake/intake-pipeline.d.ts +0 -7
  164. package/dist/intake/intake-pipeline.d.ts.map +1 -1
  165. package/dist/intake/intake-pipeline.js +1 -1
  166. package/dist/intake/intake-pipeline.js.map +1 -1
  167. package/dist/intelligence/types.d.ts +1 -0
  168. package/dist/intelligence/types.d.ts.map +1 -1
  169. package/dist/migrations/index.d.ts +6 -0
  170. package/dist/migrations/index.d.ts.map +1 -0
  171. package/dist/migrations/index.js +5 -0
  172. package/dist/migrations/index.js.map +1 -0
  173. package/dist/migrations/migration-runner.d.ts +51 -0
  174. package/dist/migrations/migration-runner.d.ts.map +1 -0
  175. package/dist/migrations/migration-runner.js +141 -0
  176. package/dist/migrations/migration-runner.js.map +1 -0
  177. package/dist/packs/index.d.ts +10 -0
  178. package/dist/packs/index.d.ts.map +1 -0
  179. package/dist/packs/index.js +8 -0
  180. package/dist/packs/index.js.map +1 -0
  181. package/dist/packs/lockfile.d.ts +97 -0
  182. package/dist/packs/lockfile.d.ts.map +1 -0
  183. package/dist/packs/lockfile.js +129 -0
  184. package/dist/packs/lockfile.js.map +1 -0
  185. package/dist/packs/pack-installer.d.ts +41 -0
  186. package/dist/packs/pack-installer.d.ts.map +1 -0
  187. package/dist/packs/pack-installer.js +253 -0
  188. package/dist/packs/pack-installer.js.map +1 -0
  189. package/dist/packs/resolver.d.ts +51 -0
  190. package/dist/packs/resolver.d.ts.map +1 -0
  191. package/dist/packs/resolver.js +195 -0
  192. package/dist/packs/resolver.js.map +1 -0
  193. package/dist/packs/types.d.ts +186 -0
  194. package/dist/packs/types.d.ts.map +1 -0
  195. package/dist/packs/types.js +69 -0
  196. package/dist/packs/types.js.map +1 -0
  197. package/dist/persistence/postgres-provider.d.ts +42 -7
  198. package/dist/persistence/postgres-provider.d.ts.map +1 -1
  199. package/dist/persistence/postgres-provider.js +187 -46
  200. package/dist/persistence/postgres-provider.js.map +1 -1
  201. package/dist/playbooks/index.d.ts +2 -0
  202. package/dist/playbooks/index.d.ts.map +1 -1
  203. package/dist/playbooks/index.js +2 -0
  204. package/dist/playbooks/index.js.map +1 -1
  205. package/dist/playbooks/playbook-executor.d.ts +100 -0
  206. package/dist/playbooks/playbook-executor.d.ts.map +1 -0
  207. package/dist/playbooks/playbook-executor.js +207 -0
  208. package/dist/playbooks/playbook-executor.js.map +1 -0
  209. package/dist/plugins/index.d.ts +7 -0
  210. package/dist/plugins/index.d.ts.map +1 -0
  211. package/dist/plugins/index.js +7 -0
  212. package/dist/plugins/index.js.map +1 -0
  213. package/dist/plugins/plugin-loader.d.ts +28 -0
  214. package/dist/plugins/plugin-loader.d.ts.map +1 -0
  215. package/dist/plugins/plugin-loader.js +150 -0
  216. package/dist/plugins/plugin-loader.js.map +1 -0
  217. package/dist/plugins/plugin-registry.d.ts +58 -0
  218. package/dist/plugins/plugin-registry.d.ts.map +1 -0
  219. package/dist/plugins/plugin-registry.js +157 -0
  220. package/dist/plugins/plugin-registry.js.map +1 -0
  221. package/dist/plugins/types.d.ts +180 -0
  222. package/dist/plugins/types.d.ts.map +1 -0
  223. package/dist/plugins/types.js +48 -0
  224. package/dist/plugins/types.js.map +1 -0
  225. package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
  226. package/dist/runtime/admin-extra-ops.js +181 -8
  227. package/dist/runtime/admin-extra-ops.js.map +1 -1
  228. package/dist/runtime/capture-ops.d.ts.map +1 -1
  229. package/dist/runtime/capture-ops.js +106 -7
  230. package/dist/runtime/capture-ops.js.map +1 -1
  231. package/dist/runtime/deprecation.d.ts +33 -0
  232. package/dist/runtime/deprecation.d.ts.map +1 -0
  233. package/dist/runtime/deprecation.js +41 -0
  234. package/dist/runtime/deprecation.js.map +1 -0
  235. package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
  236. package/dist/runtime/facades/admin-facade.js +12 -1
  237. package/dist/runtime/facades/admin-facade.js.map +1 -1
  238. package/dist/runtime/facades/agency-facade.d.ts +7 -0
  239. package/dist/runtime/facades/agency-facade.d.ts.map +1 -0
  240. package/dist/runtime/facades/agency-facade.js +103 -0
  241. package/dist/runtime/facades/agency-facade.js.map +1 -0
  242. package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
  243. package/dist/runtime/facades/brain-facade.js +58 -0
  244. package/dist/runtime/facades/brain-facade.js.map +1 -1
  245. package/dist/runtime/facades/chat-facade.d.ts +7 -0
  246. package/dist/runtime/facades/chat-facade.d.ts.map +1 -0
  247. package/dist/runtime/facades/chat-facade.js +808 -0
  248. package/dist/runtime/facades/chat-facade.js.map +1 -0
  249. package/dist/runtime/facades/context-facade.d.ts +7 -0
  250. package/dist/runtime/facades/context-facade.d.ts.map +1 -0
  251. package/dist/runtime/facades/context-facade.js +45 -0
  252. package/dist/runtime/facades/context-facade.js.map +1 -0
  253. package/dist/runtime/facades/index.d.ts.map +1 -1
  254. package/dist/runtime/facades/index.js +18 -0
  255. package/dist/runtime/facades/index.js.map +1 -1
  256. package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
  257. package/dist/runtime/facades/vault-facade.js +247 -1
  258. package/dist/runtime/facades/vault-facade.js.map +1 -1
  259. package/dist/runtime/feature-flags.d.ts +18 -0
  260. package/dist/runtime/feature-flags.d.ts.map +1 -0
  261. package/dist/runtime/feature-flags.js +90 -0
  262. package/dist/runtime/feature-flags.js.map +1 -0
  263. package/dist/runtime/pack-ops.d.ts +9 -0
  264. package/dist/runtime/pack-ops.d.ts.map +1 -0
  265. package/dist/runtime/pack-ops.js +76 -0
  266. package/dist/runtime/pack-ops.js.map +1 -0
  267. package/dist/runtime/playbook-ops.d.ts +3 -7
  268. package/dist/runtime/playbook-ops.d.ts.map +1 -1
  269. package/dist/runtime/playbook-ops.js +101 -10
  270. package/dist/runtime/playbook-ops.js.map +1 -1
  271. package/dist/runtime/plugin-ops.d.ts +9 -0
  272. package/dist/runtime/plugin-ops.d.ts.map +1 -0
  273. package/dist/runtime/plugin-ops.js +235 -0
  274. package/dist/runtime/plugin-ops.js.map +1 -0
  275. package/dist/runtime/runtime.d.ts.map +1 -1
  276. package/dist/runtime/runtime.js +72 -5
  277. package/dist/runtime/runtime.js.map +1 -1
  278. package/dist/runtime/telemetry-ops.d.ts +10 -0
  279. package/dist/runtime/telemetry-ops.d.ts.map +1 -0
  280. package/dist/runtime/telemetry-ops.js +53 -0
  281. package/dist/runtime/telemetry-ops.js.map +1 -0
  282. package/dist/runtime/types.d.ts +35 -0
  283. package/dist/runtime/types.d.ts.map +1 -1
  284. package/dist/runtime/vault-sharing-ops.d.ts +13 -0
  285. package/dist/runtime/vault-sharing-ops.d.ts.map +1 -0
  286. package/dist/runtime/vault-sharing-ops.js +345 -0
  287. package/dist/runtime/vault-sharing-ops.js.map +1 -0
  288. package/dist/streams/index.d.ts +1 -1
  289. package/dist/streams/index.d.ts.map +1 -1
  290. package/dist/streams/index.js +1 -1
  291. package/dist/streams/index.js.map +1 -1
  292. package/dist/streams/replayable-stream.d.ts +13 -1
  293. package/dist/streams/replayable-stream.d.ts.map +1 -1
  294. package/dist/streams/replayable-stream.js +27 -3
  295. package/dist/streams/replayable-stream.js.map +1 -1
  296. package/dist/text/similarity.d.ts +0 -1
  297. package/dist/text/similarity.d.ts.map +1 -1
  298. package/dist/text/similarity.js +1 -1
  299. package/dist/text/similarity.js.map +1 -1
  300. package/dist/transport/http-server.d.ts +56 -0
  301. package/dist/transport/http-server.d.ts.map +1 -0
  302. package/dist/transport/http-server.js +210 -0
  303. package/dist/transport/http-server.js.map +1 -0
  304. package/dist/transport/index.d.ts +11 -0
  305. package/dist/transport/index.d.ts.map +1 -0
  306. package/dist/transport/index.js +10 -0
  307. package/dist/transport/index.js.map +1 -0
  308. package/dist/transport/lsp-server.d.ts +140 -0
  309. package/dist/transport/lsp-server.d.ts.map +1 -0
  310. package/dist/transport/lsp-server.js +239 -0
  311. package/dist/transport/lsp-server.js.map +1 -0
  312. package/dist/transport/rate-limiter.d.ts +35 -0
  313. package/dist/transport/rate-limiter.d.ts.map +1 -0
  314. package/dist/transport/rate-limiter.js +72 -0
  315. package/dist/transport/rate-limiter.js.map +1 -0
  316. package/dist/transport/session-manager.d.ts +49 -0
  317. package/dist/transport/session-manager.d.ts.map +1 -0
  318. package/dist/transport/session-manager.js +83 -0
  319. package/dist/transport/session-manager.js.map +1 -0
  320. package/dist/transport/token-auth.d.ts +29 -0
  321. package/dist/transport/token-auth.d.ts.map +1 -0
  322. package/dist/transport/token-auth.js +84 -0
  323. package/dist/transport/token-auth.js.map +1 -0
  324. package/dist/transport/types.d.ts +61 -0
  325. package/dist/transport/types.d.ts.map +1 -0
  326. package/dist/transport/types.js +5 -0
  327. package/dist/transport/types.js.map +1 -0
  328. package/dist/transport/ws-server.d.ts +78 -0
  329. package/dist/transport/ws-server.d.ts.map +1 -0
  330. package/dist/transport/ws-server.js +342 -0
  331. package/dist/transport/ws-server.js.map +1 -0
  332. package/dist/vault/git-vault-sync.d.ts +107 -0
  333. package/dist/vault/git-vault-sync.d.ts.map +1 -0
  334. package/dist/vault/git-vault-sync.js +251 -0
  335. package/dist/vault/git-vault-sync.js.map +1 -0
  336. package/dist/vault/knowledge-review.d.ts +67 -0
  337. package/dist/vault/knowledge-review.d.ts.map +1 -0
  338. package/dist/vault/knowledge-review.js +133 -0
  339. package/dist/vault/knowledge-review.js.map +1 -0
  340. package/dist/vault/obsidian-sync.d.ts +94 -0
  341. package/dist/vault/obsidian-sync.d.ts.map +1 -0
  342. package/dist/vault/obsidian-sync.js +247 -0
  343. package/dist/vault/obsidian-sync.js.map +1 -0
  344. package/dist/vault/scope-detector.d.ts +31 -0
  345. package/dist/vault/scope-detector.d.ts.map +1 -0
  346. package/dist/vault/scope-detector.js +182 -0
  347. package/dist/vault/scope-detector.js.map +1 -0
  348. package/dist/vault/vault-branching.d.ts +71 -0
  349. package/dist/vault/vault-branching.d.ts.map +1 -0
  350. package/dist/vault/vault-branching.js +180 -0
  351. package/dist/vault/vault-branching.js.map +1 -0
  352. package/dist/vault/vault-manager.d.ts +89 -0
  353. package/dist/vault/vault-manager.d.ts.map +1 -0
  354. package/dist/vault/vault-manager.js +199 -0
  355. package/dist/vault/vault-manager.js.map +1 -0
  356. package/dist/vault/vault-types.d.ts +30 -0
  357. package/dist/vault/vault-types.d.ts.map +1 -0
  358. package/dist/vault/vault-types.js +10 -0
  359. package/dist/vault/vault-types.js.map +1 -0
  360. package/dist/vault/vault.d.ts +10 -0
  361. package/dist/vault/vault.d.ts.map +1 -1
  362. package/dist/vault/vault.js +36 -3
  363. package/dist/vault/vault.js.map +1 -1
  364. package/package.json +1 -1
  365. package/src/__tests__/admin-extra-ops.test.ts +31 -11
  366. package/src/__tests__/agency-manager.test.ts +374 -0
  367. package/src/__tests__/agent-loop.test.ts +256 -0
  368. package/src/__tests__/capture-ops.test.ts +275 -0
  369. package/src/__tests__/chat-differentiators.test.ts +251 -0
  370. package/src/__tests__/chat-enhanced.test.ts +390 -0
  371. package/src/__tests__/chat-transport.test.ts +665 -0
  372. package/src/__tests__/claudemd.test.ts +282 -0
  373. package/src/__tests__/context-engine.test.ts +256 -0
  374. package/src/__tests__/core-ops.test.ts +97 -5
  375. package/src/__tests__/deprecation.test.ts +78 -0
  376. package/src/__tests__/enforcement.test.ts +153 -0
  377. package/src/__tests__/facade-factory.test.ts +271 -0
  378. package/src/__tests__/feature-flags.test.ts +138 -0
  379. package/src/__tests__/git-vault-sync.test.ts +230 -0
  380. package/src/__tests__/health-registry.test.ts +173 -0
  381. package/src/__tests__/knowledge-review.test.ts +104 -0
  382. package/src/__tests__/lsp-transport.test.ts +442 -0
  383. package/src/__tests__/migration-runner.test.ts +170 -0
  384. package/src/__tests__/normalize.test.ts +10 -0
  385. package/src/__tests__/obsidian-sync.test.ts +354 -0
  386. package/src/__tests__/pack-lockfile.test.ts +261 -0
  387. package/src/__tests__/pack-ops.test.ts +146 -0
  388. package/src/__tests__/pack-system.test.ts +423 -0
  389. package/src/__tests__/playbook-executor.test.ts +249 -0
  390. package/src/__tests__/playbook-ops-execution.test.ts +189 -0
  391. package/src/__tests__/plugin-ops.test.ts +411 -0
  392. package/src/__tests__/plugin-system.test.ts +509 -0
  393. package/src/__tests__/postgres-provider.test.ts +64 -6
  394. package/src/__tests__/replayable-stream.test.ts +112 -1
  395. package/src/__tests__/scope-detector.test.ts +121 -0
  396. package/src/__tests__/session-lifecycle.test.ts +259 -0
  397. package/src/__tests__/transport.test.ts +758 -0
  398. package/src/__tests__/vault-branching.test.ts +274 -0
  399. package/src/__tests__/vault-connect.test.ts +179 -0
  400. package/src/__tests__/vault-integrity.test.ts +71 -0
  401. package/src/__tests__/vault-manager.test.ts +238 -0
  402. package/src/__tests__/vault-scaling.test.ts +281 -0
  403. package/src/__tests__/vault-sharing.test.ts +270 -0
  404. package/src/__tests__/ws-transport.test.ts +479 -0
  405. package/src/agency/agency-manager.ts +326 -0
  406. package/src/agency/index.ts +13 -0
  407. package/src/agency/types.ts +88 -0
  408. package/src/brain/brain.ts +15 -11
  409. package/src/brain/intelligence.ts +103 -0
  410. package/src/brain/types.ts +26 -0
  411. package/src/chat/agent-loop-types.ts +99 -0
  412. package/src/chat/agent-loop.ts +357 -0
  413. package/src/chat/auth-manager.ts +171 -0
  414. package/src/chat/browser-session.ts +188 -0
  415. package/src/chat/cancellation.ts +99 -0
  416. package/src/chat/chat-session.ts +283 -0
  417. package/src/chat/file-handler.ts +230 -0
  418. package/src/chat/fragment-buffer.ts +160 -0
  419. package/src/chat/index.ts +72 -0
  420. package/src/chat/mcp-bridge.ts +135 -0
  421. package/src/chat/notifications.ts +164 -0
  422. package/src/chat/output-compressor.ts +116 -0
  423. package/src/chat/queue.ts +208 -0
  424. package/src/chat/response-chunker.ts +200 -0
  425. package/src/chat/self-update.ts +117 -0
  426. package/src/chat/types.ts +126 -0
  427. package/src/chat/voice.ts +134 -0
  428. package/src/claudemd/compose.ts +142 -0
  429. package/src/claudemd/index.ts +17 -0
  430. package/src/claudemd/inject.ts +170 -0
  431. package/src/claudemd/types.ts +45 -0
  432. package/src/context/context-engine.ts +302 -0
  433. package/src/context/index.ts +11 -0
  434. package/src/context/types.ts +69 -0
  435. package/src/enforcement/adapters/claude-code.ts +135 -0
  436. package/src/enforcement/adapters/index.ts +1 -0
  437. package/src/enforcement/index.ts +10 -0
  438. package/src/enforcement/registry.ts +82 -0
  439. package/src/enforcement/types.ts +56 -0
  440. package/src/facades/facade-factory.ts +138 -5
  441. package/src/facades/types.ts +21 -0
  442. package/src/health/health-registry.ts +165 -0
  443. package/src/health/index.ts +11 -0
  444. package/src/health/vault-integrity.ts +66 -0
  445. package/src/index.ts +294 -2
  446. package/src/intake/intake-pipeline.ts +1 -1
  447. package/src/intelligence/types.ts +1 -0
  448. package/src/migrations/index.ts +6 -0
  449. package/src/migrations/migration-runner.ts +185 -0
  450. package/src/packs/index.ts +20 -0
  451. package/src/packs/lockfile.ts +180 -0
  452. package/src/packs/pack-installer.ts +289 -0
  453. package/src/packs/resolver.ts +237 -0
  454. package/src/packs/types.ts +125 -0
  455. package/src/persistence/postgres-provider.ts +211 -58
  456. package/src/playbooks/index.ts +11 -0
  457. package/src/playbooks/playbook-executor.ts +301 -0
  458. package/src/plugins/index.ts +19 -0
  459. package/src/plugins/plugin-loader.ts +183 -0
  460. package/src/plugins/plugin-registry.ts +187 -0
  461. package/src/plugins/types.ts +119 -0
  462. package/src/runtime/admin-extra-ops.ts +193 -8
  463. package/src/runtime/capture-ops.ts +113 -8
  464. package/src/runtime/deprecation.ts +58 -0
  465. package/src/runtime/facades/admin-facade.ts +16 -1
  466. package/src/runtime/facades/agency-facade.ts +111 -0
  467. package/src/runtime/facades/brain-facade.ts +60 -0
  468. package/src/runtime/facades/chat-facade.ts +918 -0
  469. package/src/runtime/facades/context-facade.ts +55 -0
  470. package/src/runtime/facades/index.ts +22 -1
  471. package/src/runtime/facades/vault-facade.ts +261 -1
  472. package/src/runtime/feature-flags.ts +101 -0
  473. package/src/runtime/pack-ops.ts +85 -0
  474. package/src/runtime/playbook-ops.ts +113 -9
  475. package/src/runtime/plugin-ops.ts +258 -0
  476. package/src/runtime/runtime.ts +84 -5
  477. package/src/runtime/telemetry-ops.ts +57 -0
  478. package/src/runtime/types.ts +35 -0
  479. package/src/runtime/vault-sharing-ops.ts +372 -0
  480. package/src/streams/index.ts +1 -1
  481. package/src/streams/replayable-stream.ts +34 -3
  482. package/src/text/similarity.ts +1 -1
  483. package/src/transport/http-server.ts +269 -0
  484. package/src/transport/index.ts +48 -0
  485. package/src/transport/lsp-server.ts +401 -0
  486. package/src/transport/rate-limiter.ts +97 -0
  487. package/src/transport/session-manager.ts +120 -0
  488. package/src/transport/token-auth.ts +96 -0
  489. package/src/transport/types.ts +66 -0
  490. package/src/transport/ws-server.ts +415 -0
  491. package/src/vault/git-vault-sync.ts +318 -0
  492. package/src/vault/knowledge-review.ts +221 -0
  493. package/src/vault/obsidian-sync.ts +346 -0
  494. package/src/vault/scope-detector.ts +219 -0
  495. package/src/vault/vault-branching.ts +264 -0
  496. package/src/vault/vault-manager.ts +237 -0
  497. package/src/vault/vault-types.ts +50 -0
  498. package/src/vault/vault.ts +41 -3
  499. package/src/governance/index.ts +0 -18
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Claude Code host adapter — translates enforcement rules to Claude Code hooks.
3
+ *
4
+ * Maps:
5
+ * - pre-tool-use → PreToolUse hooks in settings.json
6
+ * - pre-commit → UserPromptSubmit hook checking git commit
7
+ * - pre-compact → PreCompact hook
8
+ * - session-start → SessionStart hook
9
+ */
10
+
11
+ import type {
12
+ EnforcementConfig,
13
+ EnforcementTrigger,
14
+ HostAdapter,
15
+ HostAdapterResult,
16
+ } from '../types.js';
17
+
18
+ const TRIGGER_TO_EVENT: Partial<Record<EnforcementTrigger, string>> = {
19
+ 'pre-tool-use': 'PreToolUse',
20
+ 'post-tool-use': 'PostToolUse',
21
+ 'pre-compact': 'PreCompact',
22
+ 'session-start': 'SessionStart',
23
+ };
24
+
25
+ export class ClaudeCodeAdapter implements HostAdapter {
26
+ readonly host = 'claude-code';
27
+
28
+ supports(trigger: EnforcementTrigger): boolean {
29
+ return trigger in TRIGGER_TO_EVENT || trigger === 'pre-commit';
30
+ }
31
+
32
+ translate(config: EnforcementConfig): HostAdapterResult {
33
+ const hooks: Array<{ event: string; command: string; ruleId: string }> = [];
34
+ const hookFiles: Array<{ path: string; content: string; ruleId: string }> = [];
35
+ const skipped: Array<{ ruleId: string; reason: string }> = [];
36
+
37
+ for (const rule of config.rules) {
38
+ if (!this.supports(rule.trigger)) {
39
+ skipped.push({ ruleId: rule.id, reason: `Trigger '${rule.trigger}' not supported` });
40
+ continue;
41
+ }
42
+
43
+ if (rule.trigger === 'pre-commit') {
44
+ // Pre-commit uses a hookify-style .local.md file
45
+ hookFiles.push({
46
+ path: `.claude/hookify.${rule.id}.local.md`,
47
+ content: this.generateHookFile(rule.id, rule.description, rule.pattern, rule.message),
48
+ ruleId: rule.id,
49
+ });
50
+ continue;
51
+ }
52
+
53
+ const event = TRIGGER_TO_EVENT[rule.trigger];
54
+ if (!event) {
55
+ skipped.push({ ruleId: rule.id, reason: `No event mapping for '${rule.trigger}'` });
56
+ continue;
57
+ }
58
+
59
+ if (rule.pattern) {
60
+ // Pattern-based hook
61
+ hooks.push({
62
+ event,
63
+ command: this.generatePatternCommand(rule.id, rule.pattern, rule.action, rule.message),
64
+ ruleId: rule.id,
65
+ });
66
+ } else {
67
+ // Simple event hook
68
+ hooks.push({
69
+ event,
70
+ command: `echo "[${rule.id}] ${rule.message}"`,
71
+ ruleId: rule.id,
72
+ });
73
+ }
74
+ }
75
+
76
+ const files: Array<{ path: string; content: string }> = [];
77
+
78
+ // Generate settings.json hooks section
79
+ if (hooks.length > 0) {
80
+ const settingsHooks = hooks.map((h) => ({
81
+ event: h.event,
82
+ command: h.command,
83
+ }));
84
+ files.push({
85
+ path: '.claude/settings.json',
86
+ content: JSON.stringify({ hooks: settingsHooks }, null, 2),
87
+ });
88
+ }
89
+
90
+ // Add hookify files
91
+ for (const hf of hookFiles) {
92
+ files.push({ path: hf.path, content: hf.content });
93
+ }
94
+
95
+ return { host: this.host, files, skipped };
96
+ }
97
+
98
+ private generatePatternCommand(
99
+ ruleId: string,
100
+ pattern: string,
101
+ action: string,
102
+ message: string,
103
+ ): string {
104
+ if (action === 'block') {
105
+ return `grep -rn '${pattern}' "$TOOL_INPUT" 2>/dev/null && echo "BLOCKED [${ruleId}]: ${message}" && exit 1 || exit 0`;
106
+ }
107
+ return `grep -rn '${pattern}' "$TOOL_INPUT" 2>/dev/null && echo "WARNING [${ruleId}]: ${message}" || true`;
108
+ }
109
+
110
+ private generateHookFile(
111
+ id: string,
112
+ description: string,
113
+ pattern?: string,
114
+ message?: string,
115
+ ): string {
116
+ const lines = [
117
+ '---',
118
+ `name: ${id}`,
119
+ `description: ${description}`,
120
+ '---',
121
+ '',
122
+ `# ${id}`,
123
+ '',
124
+ description,
125
+ '',
126
+ ];
127
+ if (pattern) {
128
+ lines.push(`Pattern: \`${pattern}\``);
129
+ }
130
+ if (message) {
131
+ lines.push('', message);
132
+ }
133
+ return lines.join('\n');
134
+ }
135
+ }
@@ -0,0 +1 @@
1
+ export { ClaudeCodeAdapter } from './claude-code.js';
@@ -0,0 +1,10 @@
1
+ export { EnforcementRegistry } from './registry.js';
2
+ export { ClaudeCodeAdapter } from './adapters/index.js';
3
+ export type {
4
+ EnforcementTrigger,
5
+ EnforcementAction,
6
+ EnforcementRule,
7
+ EnforcementConfig,
8
+ HostAdapterResult,
9
+ HostAdapter,
10
+ } from './types.js';
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Enforcement registry — manages rules and adapters.
3
+ */
4
+
5
+ import type {
6
+ EnforcementConfig,
7
+ EnforcementRule,
8
+ HostAdapter,
9
+ HostAdapterResult,
10
+ } from './types.js';
11
+
12
+ export class EnforcementRegistry {
13
+ private rules: EnforcementRule[] = [];
14
+ private adapters = new Map<string, HostAdapter>();
15
+
16
+ addRule(rule: EnforcementRule): void {
17
+ // Replace if same ID exists
18
+ this.rules = this.rules.filter((r) => r.id !== rule.id);
19
+ this.rules.push(rule);
20
+ }
21
+
22
+ addRules(rules: EnforcementRule[]): void {
23
+ for (const rule of rules) {
24
+ this.addRule(rule);
25
+ }
26
+ }
27
+
28
+ removeRule(id: string): boolean {
29
+ const before = this.rules.length;
30
+ this.rules = this.rules.filter((r) => r.id !== id);
31
+ return this.rules.length < before;
32
+ }
33
+
34
+ getRule(id: string): EnforcementRule | undefined {
35
+ return this.rules.find((r) => r.id === id);
36
+ }
37
+
38
+ getRules(): EnforcementRule[] {
39
+ return [...this.rules];
40
+ }
41
+
42
+ getEnabledRules(): EnforcementRule[] {
43
+ return this.rules.filter((r) => r.enabled !== false);
44
+ }
45
+
46
+ getConfig(): EnforcementConfig {
47
+ return { rules: this.getEnabledRules() };
48
+ }
49
+
50
+ registerAdapter(adapter: HostAdapter): void {
51
+ this.adapters.set(adapter.host, adapter);
52
+ }
53
+
54
+ getAdapter(host: string): HostAdapter | undefined {
55
+ return this.adapters.get(host);
56
+ }
57
+
58
+ listAdapters(): string[] {
59
+ return [...this.adapters.keys()];
60
+ }
61
+
62
+ /** Translate rules for a specific host */
63
+ translate(host: string): HostAdapterResult {
64
+ const adapter = this.adapters.get(host);
65
+ if (!adapter) {
66
+ return {
67
+ host,
68
+ files: [],
69
+ skipped: this.getEnabledRules().map((r) => ({
70
+ ruleId: r.id,
71
+ reason: `No adapter registered for host: ${host}`,
72
+ })),
73
+ };
74
+ }
75
+ return adapter.translate(this.getConfig());
76
+ }
77
+
78
+ /** Translate rules for all registered adapters */
79
+ translateAll(): HostAdapterResult[] {
80
+ return [...this.adapters.keys()].map((host) => this.translate(host));
81
+ }
82
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Host-agnostic enforcement declarations.
3
+ *
4
+ * Agents declare rules abstractly; host adapters translate
5
+ * to platform-specific enforcement (Claude Code hooks, Cursor rules, etc.)
6
+ */
7
+
8
+ /** When the rule should trigger */
9
+ export type EnforcementTrigger =
10
+ | 'pre-tool-use' // Before a tool executes (e.g., PreToolUse hook)
11
+ | 'post-tool-use' // After a tool executes
12
+ | 'pre-commit' // Before git commit
13
+ | 'pre-compact' // Before context compaction
14
+ | 'session-start' // On session initialization
15
+ | 'on-save'; // On file save
16
+
17
+ /** What happens when a rule matches */
18
+ export type EnforcementAction = 'block' | 'warn' | 'suggest';
19
+
20
+ /** A single enforcement rule declared by the agent */
21
+ export interface EnforcementRule {
22
+ id: string;
23
+ description: string;
24
+ trigger: EnforcementTrigger;
25
+ /** Regex pattern to match (in file content, tool args, etc.) */
26
+ pattern?: string;
27
+ /** Context filter — only applies when this context is active */
28
+ context?: string;
29
+ /** What to do on match */
30
+ action: EnforcementAction;
31
+ /** Message shown to user/LLM when triggered */
32
+ message: string;
33
+ /** Whether this rule is enabled (default: true) */
34
+ enabled?: boolean;
35
+ }
36
+
37
+ /** Complete enforcement config for an agent */
38
+ export interface EnforcementConfig {
39
+ rules: EnforcementRule[];
40
+ }
41
+
42
+ /** Result of translating rules for a specific host */
43
+ export interface HostAdapterResult {
44
+ host: string;
45
+ files: Array<{ path: string; content: string }>;
46
+ skipped: Array<{ ruleId: string; reason: string }>;
47
+ }
48
+
49
+ /** Host adapter interface — translates abstract rules to host-specific config */
50
+ export interface HostAdapter {
51
+ readonly host: string;
52
+ /** Check if this adapter supports a given trigger type */
53
+ supports(trigger: EnforcementTrigger): boolean;
54
+ /** Translate rules to host-specific config files */
55
+ translate(config: EnforcementConfig): HostAdapterResult;
56
+ }
@@ -1,8 +1,13 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { z } from 'zod';
3
- import type { FacadeConfig, FacadeResponse } from './types.js';
3
+ import type { FacadeConfig, FacadeResponse, AuthPolicy, OpDefinition } from './types.js';
4
+ import { AUTH_LEVEL_RANK } from './types.js';
4
5
 
5
- export function registerFacade(server: McpServer, facade: FacadeConfig): void {
6
+ export function registerFacade(
7
+ server: McpServer,
8
+ facade: FacadeConfig,
9
+ authPolicy?: () => AuthPolicy,
10
+ ): void {
6
11
  const opNames = facade.ops.map((o) => o.name);
7
12
 
8
13
  server.tool(
@@ -13,16 +18,47 @@ export function registerFacade(server: McpServer, facade: FacadeConfig): void {
13
18
  params: z.record(z.unknown()).optional().default({}).describe('Operation parameters'),
14
19
  },
15
20
  async ({ op, params }): Promise<{ content: Array<{ type: 'text'; text: string }> }> => {
16
- const response = await dispatchOp(facade, op, params);
21
+ const response = await dispatchOp(facade, op, params, authPolicy?.());
17
22
  return { content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }] };
18
23
  },
19
24
  );
20
25
  }
21
26
 
27
+ function checkAuth(
28
+ opName: string,
29
+ opAuth: string,
30
+ facadeName: string,
31
+ policy: AuthPolicy | undefined,
32
+ ): FacadeResponse | null {
33
+ if (!policy || policy.mode === 'permissive') return null;
34
+
35
+ const requiredLevel = policy.overrides?.[opName] ?? (opAuth as keyof typeof AUTH_LEVEL_RANK);
36
+ const callerRank = AUTH_LEVEL_RANK[policy.callerLevel] ?? 0;
37
+ const requiredRank = AUTH_LEVEL_RANK[requiredLevel as keyof typeof AUTH_LEVEL_RANK] ?? 0;
38
+
39
+ if (callerRank >= requiredRank) return null;
40
+
41
+ const message = `Auth denied: "${opName}" requires ${requiredLevel}, caller has ${policy.callerLevel}`;
42
+
43
+ if (policy.mode === 'warn') {
44
+ console.error(`[auth-warn] ${message}`);
45
+ return null; // warn but allow
46
+ }
47
+
48
+ // enforce mode — block
49
+ return {
50
+ success: false,
51
+ error: message,
52
+ op: opName,
53
+ facade: facadeName,
54
+ };
55
+ }
56
+
22
57
  async function dispatchOp(
23
58
  facade: FacadeConfig,
24
59
  opName: string,
25
60
  params: Record<string, unknown>,
61
+ authPolicy?: AuthPolicy,
26
62
  ): Promise<FacadeResponse> {
27
63
  const op = facade.ops.find((o) => o.name === opName);
28
64
  if (!op) {
@@ -34,6 +70,10 @@ async function dispatchOp(
34
70
  };
35
71
  }
36
72
 
73
+ // Auth check — before validation or execution
74
+ const authResult = checkAuth(opName, op.auth, facade.name, authPolicy);
75
+ if (authResult) return authResult;
76
+
37
77
  try {
38
78
  let validatedParams = params;
39
79
  if (op.schema) {
@@ -57,8 +97,101 @@ async function dispatchOp(
57
97
  }
58
98
  }
59
99
 
60
- export function registerAllFacades(server: McpServer, facades: FacadeConfig[]): void {
100
+ /**
101
+ * Register a single hot op as a standalone MCP tool with full schema discovery.
102
+ * The op remains in its facade too — this is additive, not a move.
103
+ */
104
+ function registerHotOp(
105
+ server: McpServer,
106
+ agentId: string,
107
+ facadeName: string,
108
+ op: OpDefinition,
109
+ authPolicy?: () => AuthPolicy,
110
+ ): void {
111
+ const toolName = `${agentId}_${op.name}`;
112
+ const schema = op.schema
113
+ ? (op.schema as z.ZodObject<z.ZodRawShape>).shape
114
+ ? (op.schema as z.ZodObject<z.ZodRawShape>)
115
+ : z.object({ params: op.schema })
116
+ : z.object({});
117
+
118
+ server.tool(
119
+ toolName,
120
+ op.description,
121
+ schema instanceof z.ZodObject ? schema.shape : {},
122
+ async (params): Promise<{ content: Array<{ type: 'text'; text: string }> }> => {
123
+ const policy = authPolicy?.();
124
+ const authResult = checkAuth(op.name, op.auth, facadeName, policy);
125
+ if (authResult) {
126
+ return { content: [{ type: 'text' as const, text: JSON.stringify(authResult, null, 2) }] };
127
+ }
128
+
129
+ try {
130
+ let validatedParams = params as Record<string, unknown>;
131
+ if (op.schema) {
132
+ const result = op.schema.safeParse(params);
133
+ if (!result.success) {
134
+ const response: FacadeResponse = {
135
+ success: false,
136
+ error: `Invalid params: ${result.error.message}`,
137
+ op: op.name,
138
+ facade: facadeName,
139
+ };
140
+ return {
141
+ content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }],
142
+ };
143
+ }
144
+ validatedParams = result.data as Record<string, unknown>;
145
+ }
146
+
147
+ const data = await op.handler(validatedParams);
148
+ const response: FacadeResponse = { success: true, data, op: op.name, facade: facadeName };
149
+ return { content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }] };
150
+ } catch (err) {
151
+ const message = err instanceof Error ? err.message : String(err);
152
+ const response: FacadeResponse = {
153
+ success: false,
154
+ error: message,
155
+ op: op.name,
156
+ facade: facadeName,
157
+ };
158
+ return { content: [{ type: 'text' as const, text: JSON.stringify(response, null, 2) }] };
159
+ }
160
+ },
161
+ );
162
+ }
163
+
164
+ export interface RegisterOptions {
165
+ authPolicy?: () => AuthPolicy;
166
+ /** Agent ID prefix for hot op tool names */
167
+ agentId?: string;
168
+ /** Op names to promote to standalone MCP tools (requires agentId) */
169
+ hotOps?: Set<string> | string[];
170
+ }
171
+
172
+ export function registerAllFacades(
173
+ server: McpServer,
174
+ facades: FacadeConfig[],
175
+ authPolicyOrOptions?: (() => AuthPolicy) | RegisterOptions,
176
+ ): void {
177
+ // Support both legacy signature and new options
178
+ const opts: RegisterOptions =
179
+ typeof authPolicyOrOptions === 'function'
180
+ ? { authPolicy: authPolicyOrOptions }
181
+ : (authPolicyOrOptions ?? {});
182
+
183
+ const hotSet = opts.hotOps instanceof Set ? opts.hotOps : new Set(opts.hotOps ?? []);
184
+
61
185
  for (const facade of facades) {
62
- registerFacade(server, facade);
186
+ registerFacade(server, facade, opts.authPolicy);
187
+
188
+ // Promote hot ops to standalone tools
189
+ if (opts.agentId) {
190
+ for (const op of facade.ops) {
191
+ if (op.hot || hotSet.has(op.name)) {
192
+ registerHotOp(server, opts.agentId, facade.name, op, opts.authPolicy);
193
+ }
194
+ }
195
+ }
63
196
  }
64
197
  }
@@ -6,6 +6,25 @@ export type OpHandler = (params: Record<string, unknown>) => Promise<unknown>;
6
6
  /** Auth level required for an operation */
7
7
  export type AuthLevel = 'read' | 'write' | 'admin';
8
8
 
9
+ /** Auth enforcement mode */
10
+ export type AuthMode = 'permissive' | 'warn' | 'enforce';
11
+
12
+ /** Auth policy for facade dispatch */
13
+ export interface AuthPolicy {
14
+ mode: AuthMode;
15
+ /** Caller's auth level — ops requiring a higher level are blocked/warned */
16
+ callerLevel: AuthLevel;
17
+ /** Per-op overrides: opName → required level */
18
+ overrides?: Record<string, AuthLevel>;
19
+ }
20
+
21
+ /** Numeric auth level for comparison: read=0, write=1, admin=2 */
22
+ export const AUTH_LEVEL_RANK: Record<AuthLevel, number> = {
23
+ read: 0,
24
+ write: 1,
25
+ admin: 2,
26
+ };
27
+
9
28
  /** Operation definition within a facade */
10
29
  export interface OpDefinition {
11
30
  name: string;
@@ -13,6 +32,8 @@ export interface OpDefinition {
13
32
  auth: AuthLevel;
14
33
  handler: OpHandler;
15
34
  schema?: z.ZodType;
35
+ /** Promote to a first-class MCP tool with full schema discovery. */
36
+ hot?: boolean;
16
37
  }
17
38
 
18
39
  /** Facade configuration — one MCP tool */
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Centralized health registry — subsystems report status,
3
+ * consumers observe transitions, self-healing retries on recovery.
4
+ */
5
+
6
+ export type SubsystemStatus = 'healthy' | 'degraded' | 'down';
7
+
8
+ export interface SubsystemHealth {
9
+ name: string;
10
+ status: SubsystemStatus;
11
+ lastCheckedAt: number;
12
+ lastHealthyAt: number | null;
13
+ failureCount: number;
14
+ lastError: string | null;
15
+ }
16
+
17
+ export type StatusChangeListener = (
18
+ name: string,
19
+ prev: SubsystemStatus,
20
+ next: SubsystemStatus,
21
+ ) => void;
22
+
23
+ export type RecoveryHook = (name: string) => void | Promise<void>;
24
+
25
+ export interface HealthSnapshot {
26
+ overall: SubsystemStatus;
27
+ subsystems: Record<string, SubsystemHealth>;
28
+ registeredAt: number;
29
+ }
30
+
31
+ export class HealthRegistry {
32
+ private subsystems = new Map<string, SubsystemHealth>();
33
+ private listeners: StatusChangeListener[] = [];
34
+ private recoveryHooks = new Map<string, RecoveryHook[]>();
35
+ private readonly registeredAt = Date.now();
36
+
37
+ register(name: string, initialStatus: SubsystemStatus = 'healthy'): void {
38
+ if (this.subsystems.has(name)) return;
39
+ this.subsystems.set(name, {
40
+ name,
41
+ status: initialStatus,
42
+ lastCheckedAt: Date.now(),
43
+ lastHealthyAt: initialStatus === 'healthy' ? Date.now() : null,
44
+ failureCount: 0,
45
+ lastError: null,
46
+ });
47
+ }
48
+
49
+ update(name: string, status: SubsystemStatus, error?: string): void {
50
+ let sub = this.subsystems.get(name);
51
+ if (!sub) {
52
+ this.register(name, status);
53
+ sub = this.subsystems.get(name)!;
54
+ if (error) sub.lastError = error;
55
+ return;
56
+ }
57
+
58
+ const prev = sub.status;
59
+ sub.status = status;
60
+ sub.lastCheckedAt = Date.now();
61
+
62
+ if (status === 'healthy') {
63
+ sub.lastHealthyAt = Date.now();
64
+ sub.failureCount = 0;
65
+ sub.lastError = null;
66
+ } else {
67
+ sub.failureCount++;
68
+ if (error) sub.lastError = error;
69
+ }
70
+
71
+ if (prev !== status) {
72
+ for (const listener of this.listeners) {
73
+ try {
74
+ listener(name, prev, status);
75
+ } catch {
76
+ // Listener errors must not crash the registry
77
+ }
78
+ }
79
+
80
+ // Trigger recovery hooks when transitioning TO healthy
81
+ if (status === 'healthy' && prev !== 'healthy') {
82
+ this.triggerRecovery(name);
83
+ }
84
+ }
85
+ }
86
+
87
+ get(name: string): SubsystemHealth | undefined {
88
+ return this.subsystems.get(name);
89
+ }
90
+
91
+ snapshot(): HealthSnapshot {
92
+ const subsystems: Record<string, SubsystemHealth> = {};
93
+ for (const [name, health] of this.subsystems) {
94
+ subsystems[name] = { ...health };
95
+ }
96
+ return {
97
+ overall: this.computeOverall(),
98
+ subsystems,
99
+ registeredAt: this.registeredAt,
100
+ };
101
+ }
102
+
103
+ onStatusChange(listener: StatusChangeListener): void {
104
+ this.listeners.push(listener);
105
+ }
106
+
107
+ onRecovery(subsystem: string, hook: RecoveryHook): void {
108
+ const hooks = this.recoveryHooks.get(subsystem) ?? [];
109
+ hooks.push(hook);
110
+ this.recoveryHooks.set(subsystem, hooks);
111
+ }
112
+
113
+ private triggerRecovery(name: string): void {
114
+ const hooks = this.recoveryHooks.get(name);
115
+ if (!hooks) return;
116
+ for (const hook of hooks) {
117
+ try {
118
+ const result = hook(name);
119
+ if (result instanceof Promise) {
120
+ result.catch(() => {
121
+ // Recovery hook failure is non-fatal
122
+ });
123
+ }
124
+ } catch {
125
+ // Recovery hook failure is non-fatal
126
+ }
127
+ }
128
+ }
129
+
130
+ private computeOverall(): SubsystemStatus {
131
+ let hasDown = false;
132
+ let hasDegraded = false;
133
+ for (const sub of this.subsystems.values()) {
134
+ if (sub.status === 'down') hasDown = true;
135
+ if (sub.status === 'degraded') hasDegraded = true;
136
+ }
137
+ if (hasDown) return 'down';
138
+ if (hasDegraded) return 'degraded';
139
+ return 'healthy';
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Wrap an async call with graceful degradation.
145
+ * On failure, returns the fallback value and updates health registry.
146
+ */
147
+ export async function withDegradation<T>(
148
+ registry: HealthRegistry,
149
+ subsystem: string,
150
+ fn: () => Promise<T>,
151
+ fallback: T,
152
+ ): Promise<T> {
153
+ try {
154
+ const result = await fn();
155
+ registry.update(subsystem, 'healthy');
156
+ return result;
157
+ } catch (err) {
158
+ const message = err instanceof Error ? err.message : String(err);
159
+ const current = registry.get(subsystem);
160
+ // First failure = degraded, repeated = down
161
+ const status: SubsystemStatus = current && current.status === 'degraded' ? 'down' : 'degraded';
162
+ registry.update(subsystem, status, message);
163
+ return fallback;
164
+ }
165
+ }
@@ -0,0 +1,11 @@
1
+ export { HealthRegistry, withDegradation } from './health-registry.js';
2
+ export type {
3
+ SubsystemStatus,
4
+ SubsystemHealth,
5
+ StatusChangeListener,
6
+ RecoveryHook,
7
+ HealthSnapshot,
8
+ } from './health-registry.js';
9
+
10
+ export { checkVaultIntegrity } from './vault-integrity.js';
11
+ export type { IntegrityResult } from './vault-integrity.js';