@animalabs/agent-framework 0.22.2 → 0.22.4

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 (940) hide show
  1. package/README.md +3 -1
  2. package/dist/src/agent.d.ts +77 -12
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +143 -41
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/mcp-server-core.js +1 -1
  7. package/dist/src/api/mcp-server-core.js.map +1 -1
  8. package/dist/src/api/server.d.ts.map +1 -1
  9. package/dist/src/api/server.js +5 -1
  10. package/dist/src/api/server.js.map +1 -1
  11. package/dist/src/api/types.d.ts +1 -1
  12. package/dist/src/api/types.d.ts.map +1 -1
  13. package/dist/src/branch-names.d.ts +14 -0
  14. package/dist/src/branch-names.d.ts.map +1 -0
  15. package/dist/src/branch-names.js +22 -0
  16. package/dist/src/branch-names.js.map +1 -0
  17. package/dist/src/closest-names.d.ts +28 -0
  18. package/dist/src/closest-names.d.ts.map +1 -0
  19. package/dist/src/closest-names.js +98 -0
  20. package/dist/src/closest-names.js.map +1 -0
  21. package/dist/src/code-execution/py-runner.d.ts +16 -5
  22. package/dist/src/code-execution/py-runner.d.ts.map +1 -1
  23. package/dist/src/code-execution/py-runner.js +186 -74
  24. package/dist/src/code-execution/py-runner.js.map +1 -1
  25. package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
  26. package/dist/src/code-execution/runtime-py.js +49 -3
  27. package/dist/src/code-execution/runtime-py.js.map +1 -1
  28. package/dist/src/code-execution/tool-definition.d.ts +12 -1
  29. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  30. package/dist/src/code-execution/tool-definition.js +21 -3
  31. package/dist/src/code-execution/tool-definition.js.map +1 -1
  32. package/dist/src/config-checks.d.ts +28 -0
  33. package/dist/src/config-checks.d.ts.map +1 -0
  34. package/dist/src/config-checks.js +52 -0
  35. package/dist/src/config-checks.js.map +1 -0
  36. package/dist/src/deadline-timer.d.ts +21 -0
  37. package/dist/src/deadline-timer.d.ts.map +1 -0
  38. package/dist/src/deadline-timer.js +43 -0
  39. package/dist/src/deadline-timer.js.map +1 -0
  40. package/dist/src/error-message.d.ts +30 -0
  41. package/dist/src/error-message.d.ts.map +1 -0
  42. package/dist/src/error-message.js +50 -0
  43. package/dist/src/error-message.js.map +1 -0
  44. package/dist/src/framework.d.ts +828 -88
  45. package/dist/src/framework.d.ts.map +1 -1
  46. package/dist/src/framework.js +5011 -1326
  47. package/dist/src/framework.js.map +1 -1
  48. package/dist/src/gate/event-gate.d.ts +8 -0
  49. package/dist/src/gate/event-gate.d.ts.map +1 -1
  50. package/dist/src/gate/event-gate.js +27 -3
  51. package/dist/src/gate/event-gate.js.map +1 -1
  52. package/dist/src/index.d.ts +4 -2
  53. package/dist/src/index.d.ts.map +1 -1
  54. package/dist/src/index.js +4 -2
  55. package/dist/src/index.js.map +1 -1
  56. package/dist/src/mcpl/channel-registry.d.ts +144 -6
  57. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  58. package/dist/src/mcpl/channel-registry.js +424 -263
  59. package/dist/src/mcpl/channel-registry.js.map +1 -1
  60. package/dist/src/mcpl/checkpoint-manager.d.ts +21 -1
  61. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  62. package/dist/src/mcpl/checkpoint-manager.js +91 -30
  63. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  64. package/dist/src/mcpl/conversation-router.d.ts +19 -3
  65. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  66. package/dist/src/mcpl/conversation-router.js +23 -8
  67. package/dist/src/mcpl/conversation-router.js.map +1 -1
  68. package/dist/src/mcpl/convert-block.d.ts +20 -0
  69. package/dist/src/mcpl/convert-block.d.ts.map +1 -0
  70. package/dist/src/mcpl/convert-block.js +89 -0
  71. package/dist/src/mcpl/convert-block.js.map +1 -0
  72. package/dist/src/mcpl/errors.d.ts +13 -0
  73. package/dist/src/mcpl/errors.d.ts.map +1 -1
  74. package/dist/src/mcpl/errors.js +28 -0
  75. package/dist/src/mcpl/errors.js.map +1 -1
  76. package/dist/src/mcpl/hook-orchestrator.d.ts +23 -0
  77. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  78. package/dist/src/mcpl/hook-orchestrator.js +83 -72
  79. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  80. package/dist/src/mcpl/inbound-source.d.ts +114 -0
  81. package/dist/src/mcpl/inbound-source.d.ts.map +1 -0
  82. package/dist/src/mcpl/inbound-source.js +83 -0
  83. package/dist/src/mcpl/inbound-source.js.map +1 -0
  84. package/dist/src/mcpl/index.d.ts +3 -1
  85. package/dist/src/mcpl/index.d.ts.map +1 -1
  86. package/dist/src/mcpl/index.js +3 -1
  87. package/dist/src/mcpl/index.js.map +1 -1
  88. package/dist/src/mcpl/inference-router.d.ts +15 -11
  89. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  90. package/dist/src/mcpl/inference-router.js +153 -84
  91. package/dist/src/mcpl/inference-router.js.map +1 -1
  92. package/dist/src/mcpl/push-coalescer.d.ts +33 -11
  93. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  94. package/dist/src/mcpl/push-coalescer.js +52 -20
  95. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  96. package/dist/src/mcpl/push-handler.d.ts +16 -9
  97. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  98. package/dist/src/mcpl/push-handler.js +18 -83
  99. package/dist/src/mcpl/push-handler.js.map +1 -1
  100. package/dist/src/mcpl/reference-fetcher.d.ts +14 -2
  101. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  102. package/dist/src/mcpl/reference-fetcher.js +72 -30
  103. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  104. package/dist/src/mcpl/references.d.ts +47 -12
  105. package/dist/src/mcpl/references.d.ts.map +1 -1
  106. package/dist/src/mcpl/references.js +74 -21
  107. package/dist/src/mcpl/references.js.map +1 -1
  108. package/dist/src/mcpl/server-connection.d.ts +89 -10
  109. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  110. package/dist/src/mcpl/server-connection.js +405 -129
  111. package/dist/src/mcpl/server-connection.js.map +1 -1
  112. package/dist/src/mcpl/server-registry.d.ts +10 -1
  113. package/dist/src/mcpl/server-registry.d.ts.map +1 -1
  114. package/dist/src/mcpl/server-registry.js +14 -3
  115. package/dist/src/mcpl/server-registry.js.map +1 -1
  116. package/dist/src/mcpl/skip-reply-wake.d.ts +36 -0
  117. package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -0
  118. package/dist/src/mcpl/skip-reply-wake.js +55 -0
  119. package/dist/src/mcpl/skip-reply-wake.js.map +1 -0
  120. package/dist/src/mcpl/transport.d.ts +51 -2
  121. package/dist/src/mcpl/transport.d.ts.map +1 -1
  122. package/dist/src/mcpl/transport.js +114 -20
  123. package/dist/src/mcpl/transport.js.map +1 -1
  124. package/dist/src/mcpl/types.d.ts +14 -3
  125. package/dist/src/mcpl/types.d.ts.map +1 -1
  126. package/dist/src/mcpl/types.js.map +1 -1
  127. package/dist/src/mcpl/visible-content.d.ts +15 -0
  128. package/dist/src/mcpl/visible-content.d.ts.map +1 -1
  129. package/dist/src/mcpl/visible-content.js +25 -0
  130. package/dist/src/mcpl/visible-content.js.map +1 -1
  131. package/dist/src/module-registry.d.ts +19 -1
  132. package/dist/src/module-registry.d.ts.map +1 -1
  133. package/dist/src/module-registry.js +54 -25
  134. package/dist/src/module-registry.js.map +1 -1
  135. package/dist/src/modules/api/index.js +1 -1
  136. package/dist/src/modules/api/index.js.map +1 -1
  137. package/dist/src/modules/discord/discord-js-client.d.ts +1 -0
  138. package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
  139. package/dist/src/modules/discord/discord-js-client.js +25 -9
  140. package/dist/src/modules/discord/discord-js-client.js.map +1 -1
  141. package/dist/src/modules/discord/index.d.ts +29 -3
  142. package/dist/src/modules/discord/index.d.ts.map +1 -1
  143. package/dist/src/modules/discord/index.js +379 -143
  144. package/dist/src/modules/discord/index.js.map +1 -1
  145. package/dist/src/modules/discord/types.d.ts +14 -1
  146. package/dist/src/modules/discord/types.d.ts.map +1 -1
  147. package/dist/src/modules/health/index.d.ts.map +1 -1
  148. package/dist/src/modules/health/index.js +2 -1
  149. package/dist/src/modules/health/index.js.map +1 -1
  150. package/dist/src/modules/history/index.d.ts +3 -1
  151. package/dist/src/modules/history/index.d.ts.map +1 -1
  152. package/dist/src/modules/history/index.js +359 -127
  153. package/dist/src/modules/history/index.js.map +1 -1
  154. package/dist/src/modules/history/semantic.d.ts +28 -1
  155. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  156. package/dist/src/modules/history/semantic.js +177 -32
  157. package/dist/src/modules/history/semantic.js.map +1 -1
  158. package/dist/src/modules/unknown-tool.d.ts +10 -0
  159. package/dist/src/modules/unknown-tool.d.ts.map +1 -0
  160. package/dist/src/modules/unknown-tool.js +17 -0
  161. package/dist/src/modules/unknown-tool.js.map +1 -0
  162. package/dist/src/modules/workspace/disk-agreement.d.ts +32 -2
  163. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  164. package/dist/src/modules/workspace/disk-agreement.js +30 -2
  165. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  166. package/dist/src/modules/workspace/effects.d.ts +64 -6
  167. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  168. package/dist/src/modules/workspace/effects.js +291 -44
  169. package/dist/src/modules/workspace/effects.js.map +1 -1
  170. package/dist/src/modules/workspace/index.d.ts +119 -23
  171. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  172. package/dist/src/modules/workspace/index.js +793 -247
  173. package/dist/src/modules/workspace/index.js.map +1 -1
  174. package/dist/src/modules/workspace/observe.d.ts +75 -8
  175. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  176. package/dist/src/modules/workspace/observe.js +174 -14
  177. package/dist/src/modules/workspace/observe.js.map +1 -1
  178. package/dist/src/modules/workspace/reconcile.d.ts +58 -7
  179. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  180. package/dist/src/modules/workspace/reconcile.js +521 -56
  181. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  182. package/dist/src/modules/workspace/types.d.ts +18 -4
  183. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  184. package/dist/src/modules/workspace/types.js.map +1 -1
  185. package/dist/src/modules/workspace/watcher.d.ts +7 -2
  186. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  187. package/dist/src/modules/workspace/watcher.js +28 -4
  188. package/dist/src/modules/workspace/watcher.js.map +1 -1
  189. package/dist/src/prose-drafts.d.ts +240 -0
  190. package/dist/src/prose-drafts.d.ts.map +1 -0
  191. package/dist/src/prose-drafts.js +362 -0
  192. package/dist/src/prose-drafts.js.map +1 -0
  193. package/dist/src/prose-segments.d.ts +21 -2
  194. package/dist/src/prose-segments.d.ts.map +1 -1
  195. package/dist/src/prose-segments.js +46 -9
  196. package/dist/src/prose-segments.js.map +1 -1
  197. package/dist/src/recovery/offline-branch.d.ts +1 -0
  198. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  199. package/dist/src/recovery/offline-branch.js +3 -1
  200. package/dist/src/recovery/offline-branch.js.map +1 -1
  201. package/dist/src/safe-slice.d.ts +5 -1
  202. package/dist/src/safe-slice.d.ts.map +1 -1
  203. package/dist/src/safe-slice.js +9 -1
  204. package/dist/src/safe-slice.js.map +1 -1
  205. package/dist/src/thinking-token-stamp.d.ts +12 -0
  206. package/dist/src/thinking-token-stamp.d.ts.map +1 -1
  207. package/dist/src/thinking-token-stamp.js +34 -3
  208. package/dist/src/thinking-token-stamp.js.map +1 -1
  209. package/dist/src/tool-image-ledger.d.ts +87 -19
  210. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  211. package/dist/src/tool-image-ledger.js +135 -32
  212. package/dist/src/tool-image-ledger.js.map +1 -1
  213. package/dist/src/tool-presentation.d.ts +9 -0
  214. package/dist/src/tool-presentation.d.ts.map +1 -1
  215. package/dist/src/tool-presentation.js +257 -60
  216. package/dist/src/tool-presentation.js.map +1 -1
  217. package/dist/src/tool-result-guard.d.ts.map +1 -1
  218. package/dist/src/tool-result-guard.js +7 -10
  219. package/dist/src/tool-result-guard.js.map +1 -1
  220. package/dist/src/tool-result-history.d.ts +32 -3
  221. package/dist/src/tool-result-history.d.ts.map +1 -1
  222. package/dist/src/tool-result-history.js +106 -19
  223. package/dist/src/tool-result-history.js.map +1 -1
  224. package/dist/src/tune-out/coordinator.d.ts +25 -1
  225. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  226. package/dist/src/tune-out/coordinator.js +260 -65
  227. package/dist/src/tune-out/coordinator.js.map +1 -1
  228. package/dist/src/types/agent.d.ts +17 -5
  229. package/dist/src/types/agent.d.ts.map +1 -1
  230. package/dist/src/types/events.d.ts +17 -0
  231. package/dist/src/types/events.d.ts.map +1 -1
  232. package/dist/src/types/framework.d.ts +21 -5
  233. package/dist/src/types/framework.d.ts.map +1 -1
  234. package/dist/src/types/inference-log.d.ts +1 -1
  235. package/dist/src/types/inference-log.d.ts.map +1 -1
  236. package/dist/src/types/module.d.ts +23 -4
  237. package/dist/src/types/module.d.ts.map +1 -1
  238. package/dist/src/types/trace.d.ts +95 -6
  239. package/dist/src/types/trace.d.ts.map +1 -1
  240. package/dist/src/usage/usage-tracker.d.ts +5 -0
  241. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  242. package/dist/src/usage/usage-tracker.js +35 -8
  243. package/dist/src/usage/usage-tracker.js.map +1 -1
  244. package/package.json +6 -4
  245. package/src/agent.ts +169 -41
  246. package/src/api/mcp-server-core.ts +1 -1
  247. package/src/api/server.ts +4 -1
  248. package/src/api/types.ts +1 -1
  249. package/src/branch-names.ts +19 -0
  250. package/src/closest-names.ts +94 -0
  251. package/src/code-execution/py-runner.ts +200 -76
  252. package/src/code-execution/runtime-py.ts +49 -3
  253. package/src/code-execution/tool-definition.ts +28 -4
  254. package/src/config-checks.ts +48 -0
  255. package/src/deadline-timer.ts +44 -0
  256. package/src/error-message.ts +48 -0
  257. package/src/framework.ts +5352 -1388
  258. package/src/gate/event-gate.ts +28 -3
  259. package/src/index.ts +11 -2
  260. package/src/mcpl/channel-registry.ts +517 -286
  261. package/src/mcpl/checkpoint-manager.ts +104 -29
  262. package/src/mcpl/conversation-router.ts +28 -8
  263. package/src/mcpl/convert-block.ts +97 -0
  264. package/src/mcpl/errors.ts +28 -0
  265. package/src/mcpl/hook-orchestrator.ts +84 -77
  266. package/src/mcpl/inbound-source.ts +156 -0
  267. package/src/mcpl/index.ts +10 -1
  268. package/src/mcpl/inference-router.ts +174 -99
  269. package/src/mcpl/push-coalescer.ts +60 -24
  270. package/src/mcpl/push-handler.ts +20 -90
  271. package/src/mcpl/reference-fetcher.ts +71 -26
  272. package/src/mcpl/references.ts +81 -22
  273. package/src/mcpl/server-connection.ts +427 -132
  274. package/src/mcpl/server-registry.ts +15 -4
  275. package/src/mcpl/skip-reply-wake.ts +73 -0
  276. package/src/mcpl/transport.ts +120 -18
  277. package/src/mcpl/types.ts +14 -3
  278. package/src/mcpl/visible-content.ts +27 -0
  279. package/src/module-registry.ts +58 -23
  280. package/src/modules/api/index.ts +1 -1
  281. package/src/modules/discord/discord-js-client.ts +26 -10
  282. package/src/modules/discord/index.ts +391 -158
  283. package/src/modules/discord/types.ts +15 -2
  284. package/src/modules/health/index.ts +2 -1
  285. package/src/modules/history/index.ts +410 -120
  286. package/src/modules/history/semantic.ts +189 -32
  287. package/src/modules/unknown-tool.ts +16 -0
  288. package/src/modules/workspace/disk-agreement.ts +51 -3
  289. package/src/modules/workspace/effects.ts +279 -35
  290. package/src/modules/workspace/index.ts +810 -260
  291. package/src/modules/workspace/observe.ts +194 -20
  292. package/src/modules/workspace/reconcile.ts +619 -64
  293. package/src/modules/workspace/types.ts +18 -4
  294. package/src/modules/workspace/watcher.ts +27 -4
  295. package/src/prose-drafts.ts +481 -0
  296. package/src/prose-segments.ts +51 -8
  297. package/src/recovery/offline-branch.ts +4 -1
  298. package/src/safe-slice.ts +9 -1
  299. package/src/thinking-token-stamp.ts +34 -3
  300. package/src/tool-image-ledger.ts +153 -34
  301. package/src/tool-presentation.ts +224 -40
  302. package/src/tool-result-guard.ts +7 -8
  303. package/src/tool-result-history.ts +124 -20
  304. package/src/tune-out/coordinator.ts +259 -65
  305. package/src/types/agent.ts +17 -7
  306. package/src/types/events.ts +17 -0
  307. package/src/types/framework.ts +21 -5
  308. package/src/types/inference-log.ts +1 -1
  309. package/src/types/module.ts +24 -4
  310. package/src/types/trace.ts +101 -6
  311. package/src/usage/usage-tracker.ts +32 -8
  312. package/dist/test/activation-request-sanitize.test.d.ts +0 -2
  313. package/dist/test/activation-request-sanitize.test.d.ts.map +0 -1
  314. package/dist/test/activation-request-sanitize.test.js +0 -89
  315. package/dist/test/activation-request-sanitize.test.js.map +0 -1
  316. package/dist/test/agent-cache-ttl.test.d.ts +0 -2
  317. package/dist/test/agent-cache-ttl.test.d.ts.map +0 -1
  318. package/dist/test/agent-cache-ttl.test.js +0 -41
  319. package/dist/test/agent-cache-ttl.test.js.map +0 -1
  320. package/dist/test/agent-runtime-settings.test.d.ts +0 -2
  321. package/dist/test/agent-runtime-settings.test.d.ts.map +0 -1
  322. package/dist/test/agent-runtime-settings.test.js +0 -1598
  323. package/dist/test/agent-runtime-settings.test.js.map +0 -1
  324. package/dist/test/api-admin-gate.test.d.ts +0 -2
  325. package/dist/test/api-admin-gate.test.d.ts.map +0 -1
  326. package/dist/test/api-admin-gate.test.js +0 -116
  327. package/dist/test/api-admin-gate.test.js.map +0 -1
  328. package/dist/test/assistant-persist-refusal.test.d.ts +0 -2
  329. package/dist/test/assistant-persist-refusal.test.d.ts.map +0 -1
  330. package/dist/test/assistant-persist-refusal.test.js +0 -63
  331. package/dist/test/assistant-persist-refusal.test.js.map +0 -1
  332. package/dist/test/batched-wake-locus.test.d.ts +0 -2
  333. package/dist/test/batched-wake-locus.test.d.ts.map +0 -1
  334. package/dist/test/batched-wake-locus.test.js +0 -166
  335. package/dist/test/batched-wake-locus.test.js.map +0 -1
  336. package/dist/test/busy-agent-scheduler.test.d.ts +0 -2
  337. package/dist/test/busy-agent-scheduler.test.d.ts.map +0 -1
  338. package/dist/test/busy-agent-scheduler.test.js +0 -92
  339. package/dist/test/busy-agent-scheduler.test.js.map +0 -1
  340. package/dist/test/channel-incoming-targeting.test.d.ts +0 -2
  341. package/dist/test/channel-incoming-targeting.test.d.ts.map +0 -1
  342. package/dist/test/channel-incoming-targeting.test.js +0 -81
  343. package/dist/test/channel-incoming-targeting.test.js.map +0 -1
  344. package/dist/test/channel-label-history.test.d.ts +0 -2
  345. package/dist/test/channel-label-history.test.d.ts.map +0 -1
  346. package/dist/test/channel-label-history.test.js +0 -424
  347. package/dist/test/channel-label-history.test.js.map +0 -1
  348. package/dist/test/channel-lifecycle-provenance.test.d.ts +0 -2
  349. package/dist/test/channel-lifecycle-provenance.test.d.ts.map +0 -1
  350. package/dist/test/channel-lifecycle-provenance.test.js +0 -47
  351. package/dist/test/channel-lifecycle-provenance.test.js.map +0 -1
  352. package/dist/test/channel-registry-routing.test.d.ts +0 -2
  353. package/dist/test/channel-registry-routing.test.d.ts.map +0 -1
  354. package/dist/test/channel-registry-routing.test.js +0 -446
  355. package/dist/test/channel-registry-routing.test.js.map +0 -1
  356. package/dist/test/channel-registry-typing.test.d.ts +0 -2
  357. package/dist/test/channel-registry-typing.test.d.ts.map +0 -1
  358. package/dist/test/channel-registry-typing.test.js +0 -91
  359. package/dist/test/channel-registry-typing.test.js.map +0 -1
  360. package/dist/test/channels-changed-respond-first.test.d.ts +0 -2
  361. package/dist/test/channels-changed-respond-first.test.d.ts.map +0 -1
  362. package/dist/test/channels-changed-respond-first.test.js +0 -74
  363. package/dist/test/channels-changed-respond-first.test.js.map +0 -1
  364. package/dist/test/checkpoint-attribution.test.d.ts +0 -2
  365. package/dist/test/checkpoint-attribution.test.d.ts.map +0 -1
  366. package/dist/test/checkpoint-attribution.test.js +0 -200
  367. package/dist/test/checkpoint-attribution.test.js.map +0 -1
  368. package/dist/test/code-execution.test.d.ts +0 -11
  369. package/dist/test/code-execution.test.d.ts.map +0 -1
  370. package/dist/test/code-execution.test.js +0 -1272
  371. package/dist/test/code-execution.test.js.map +0 -1
  372. package/dist/test/component-defaults.test.d.ts +0 -2
  373. package/dist/test/component-defaults.test.d.ts.map +0 -1
  374. package/dist/test/component-defaults.test.js +0 -54
  375. package/dist/test/component-defaults.test.js.map +0 -1
  376. package/dist/test/conversation-fork-injection-scoping.test.d.ts +0 -2
  377. package/dist/test/conversation-fork-injection-scoping.test.d.ts.map +0 -1
  378. package/dist/test/conversation-fork-injection-scoping.test.js +0 -200
  379. package/dist/test/conversation-fork-injection-scoping.test.js.map +0 -1
  380. package/dist/test/conversation-router.test.d.ts +0 -2
  381. package/dist/test/conversation-router.test.d.ts.map +0 -1
  382. package/dist/test/conversation-router.test.js +0 -174
  383. package/dist/test/conversation-router.test.js.map +0 -1
  384. package/dist/test/conversation-routing.test.d.ts +0 -7
  385. package/dist/test/conversation-routing.test.d.ts.map +0 -1
  386. package/dist/test/conversation-routing.test.js +0 -621
  387. package/dist/test/conversation-routing.test.js.map +0 -1
  388. package/dist/test/deferred-wake-integrity.test.d.ts +0 -29
  389. package/dist/test/deferred-wake-integrity.test.d.ts.map +0 -1
  390. package/dist/test/deferred-wake-integrity.test.js +0 -320
  391. package/dist/test/deferred-wake-integrity.test.js.map +0 -1
  392. package/dist/test/discord-awareness-outbox.test.d.ts +0 -2
  393. package/dist/test/discord-awareness-outbox.test.d.ts.map +0 -1
  394. package/dist/test/discord-awareness-outbox.test.js +0 -371
  395. package/dist/test/discord-awareness-outbox.test.js.map +0 -1
  396. package/dist/test/discord-history-delete-window.test.d.ts +0 -2
  397. package/dist/test/discord-history-delete-window.test.d.ts.map +0 -1
  398. package/dist/test/discord-history-delete-window.test.js +0 -81
  399. package/dist/test/discord-history-delete-window.test.js.map +0 -1
  400. package/dist/test/discord-history-sync.test.d.ts +0 -2
  401. package/dist/test/discord-history-sync.test.d.ts.map +0 -1
  402. package/dist/test/discord-history-sync.test.js +0 -56
  403. package/dist/test/discord-history-sync.test.js.map +0 -1
  404. package/dist/test/discord-typing-keepalive.test.d.ts +0 -2
  405. package/dist/test/discord-typing-keepalive.test.d.ts.map +0 -1
  406. package/dist/test/discord-typing-keepalive.test.js +0 -77
  407. package/dist/test/discord-typing-keepalive.test.js.map +0 -1
  408. package/dist/test/ephemeral-settle.test.d.ts +0 -2
  409. package/dist/test/ephemeral-settle.test.d.ts.map +0 -1
  410. package/dist/test/ephemeral-settle.test.js +0 -354
  411. package/dist/test/ephemeral-settle.test.js.map +0 -1
  412. package/dist/test/event-gate-passthrough.test.d.ts +0 -15
  413. package/dist/test/event-gate-passthrough.test.d.ts.map +0 -1
  414. package/dist/test/event-gate-passthrough.test.js +0 -289
  415. package/dist/test/event-gate-passthrough.test.js.map +0 -1
  416. package/dist/test/event-gate-policy-mutation.test.d.ts +0 -2
  417. package/dist/test/event-gate-policy-mutation.test.d.ts.map +0 -1
  418. package/dist/test/event-gate-policy-mutation.test.js +0 -137
  419. package/dist/test/event-gate-policy-mutation.test.js.map +0 -1
  420. package/dist/test/event-gate-rate-limit.test.d.ts +0 -2
  421. package/dist/test/event-gate-rate-limit.test.d.ts.map +0 -1
  422. package/dist/test/event-gate-rate-limit.test.js +0 -627
  423. package/dist/test/event-gate-rate-limit.test.js.map +0 -1
  424. package/dist/test/event-gate-script.test.d.ts +0 -2
  425. package/dist/test/event-gate-script.test.d.ts.map +0 -1
  426. package/dist/test/event-gate-script.test.js +0 -95
  427. package/dist/test/event-gate-script.test.js.map +0 -1
  428. package/dist/test/event-gate-selfwake.test.d.ts +0 -15
  429. package/dist/test/event-gate-selfwake.test.d.ts.map +0 -1
  430. package/dist/test/event-gate-selfwake.test.js +0 -125
  431. package/dist/test/event-gate-selfwake.test.js.map +0 -1
  432. package/dist/test/event-gate-tags.test.d.ts +0 -2
  433. package/dist/test/event-gate-tags.test.d.ts.map +0 -1
  434. package/dist/test/event-gate-tags.test.js +0 -76
  435. package/dist/test/event-gate-tags.test.js.map +0 -1
  436. package/dist/test/event-gate.test.d.ts +0 -2
  437. package/dist/test/event-gate.test.d.ts.map +0 -1
  438. package/dist/test/event-gate.test.js +0 -919
  439. package/dist/test/event-gate.test.js.map +0 -1
  440. package/dist/test/explicit-prose-routing.test.d.ts +0 -11
  441. package/dist/test/explicit-prose-routing.test.d.ts.map +0 -1
  442. package/dist/test/explicit-prose-routing.test.js +0 -1715
  443. package/dist/test/explicit-prose-routing.test.js.map +0 -1
  444. package/dist/test/framework.test.d.ts +0 -5
  445. package/dist/test/framework.test.d.ts.map +0 -1
  446. package/dist/test/framework.test.js +0 -1048
  447. package/dist/test/framework.test.js.map +0 -1
  448. package/dist/test/gather-context-timeout.test.d.ts +0 -2
  449. package/dist/test/gather-context-timeout.test.d.ts.map +0 -1
  450. package/dist/test/gather-context-timeout.test.js +0 -120
  451. package/dist/test/gather-context-timeout.test.js.map +0 -1
  452. package/dist/test/health-snapshot.test.d.ts +0 -2
  453. package/dist/test/health-snapshot.test.d.ts.map +0 -1
  454. package/dist/test/health-snapshot.test.js +0 -74
  455. package/dist/test/health-snapshot.test.js.map +0 -1
  456. package/dist/test/helpers/coalescing-fixture.d.ts +0 -74
  457. package/dist/test/helpers/coalescing-fixture.d.ts.map +0 -1
  458. package/dist/test/helpers/coalescing-fixture.js +0 -152
  459. package/dist/test/helpers/coalescing-fixture.js.map +0 -1
  460. package/dist/test/helpers/coalescing-kill-child.d.ts +0 -2
  461. package/dist/test/helpers/coalescing-kill-child.d.ts.map +0 -1
  462. package/dist/test/helpers/coalescing-kill-child.js +0 -24
  463. package/dist/test/helpers/coalescing-kill-child.js.map +0 -1
  464. package/dist/test/helpers/mock-membrane.d.ts +0 -53
  465. package/dist/test/helpers/mock-membrane.d.ts.map +0 -1
  466. package/dist/test/helpers/mock-membrane.js +0 -168
  467. package/dist/test/helpers/mock-membrane.js.map +0 -1
  468. package/dist/test/helpers/pytc-stop-rows.d.ts +0 -11
  469. package/dist/test/helpers/pytc-stop-rows.d.ts.map +0 -1
  470. package/dist/test/helpers/pytc-stop-rows.js +0 -143
  471. package/dist/test/helpers/pytc-stop-rows.js.map +0 -1
  472. package/dist/test/helpers/quiesce-crash-child.d.ts +0 -2
  473. package/dist/test/helpers/quiesce-crash-child.d.ts.map +0 -1
  474. package/dist/test/helpers/quiesce-crash-child.js +0 -156
  475. package/dist/test/helpers/quiesce-crash-child.js.map +0 -1
  476. package/dist/test/hide-then-turn.test.d.ts +0 -2
  477. package/dist/test/hide-then-turn.test.d.ts.map +0 -1
  478. package/dist/test/hide-then-turn.test.js +0 -101
  479. package/dist/test/hide-then-turn.test.js.map +0 -1
  480. package/dist/test/history-module-overview.test.d.ts +0 -2
  481. package/dist/test/history-module-overview.test.d.ts.map +0 -1
  482. package/dist/test/history-module-overview.test.js +0 -711
  483. package/dist/test/history-module-overview.test.js.map +0 -1
  484. package/dist/test/history-module-realstore.test.d.ts +0 -2
  485. package/dist/test/history-module-realstore.test.d.ts.map +0 -1
  486. package/dist/test/history-module-realstore.test.js +0 -363
  487. package/dist/test/history-module-realstore.test.js.map +0 -1
  488. package/dist/test/history-module-semantic.test.d.ts +0 -2
  489. package/dist/test/history-module-semantic.test.d.ts.map +0 -1
  490. package/dist/test/history-module-semantic.test.js +0 -213
  491. package/dist/test/history-module-semantic.test.js.map +0 -1
  492. package/dist/test/history-module-ux.test.d.ts +0 -2
  493. package/dist/test/history-module-ux.test.d.ts.map +0 -1
  494. package/dist/test/history-module-ux.test.js +0 -304
  495. package/dist/test/history-module-ux.test.js.map +0 -1
  496. package/dist/test/history-module.test.d.ts +0 -2
  497. package/dist/test/history-module.test.d.ts.map +0 -1
  498. package/dist/test/history-module.test.js +0 -619
  499. package/dist/test/history-module.test.js.map +0 -1
  500. package/dist/test/history-semantic-review-findings.test.d.ts +0 -2
  501. package/dist/test/history-semantic-review-findings.test.d.ts.map +0 -1
  502. package/dist/test/history-semantic-review-findings.test.js +0 -338
  503. package/dist/test/history-semantic-review-findings.test.js.map +0 -1
  504. package/dist/test/history-semantic-sync-converges.test.d.ts +0 -2
  505. package/dist/test/history-semantic-sync-converges.test.d.ts.map +0 -1
  506. package/dist/test/history-semantic-sync-converges.test.js +0 -109
  507. package/dist/test/history-semantic-sync-converges.test.js.map +0 -1
  508. package/dist/test/host-quiesce.test.d.ts +0 -2
  509. package/dist/test/host-quiesce.test.d.ts.map +0 -1
  510. package/dist/test/host-quiesce.test.js +0 -988
  511. package/dist/test/host-quiesce.test.js.map +0 -1
  512. package/dist/test/inference-exhaustion-rewind.test.d.ts +0 -2
  513. package/dist/test/inference-exhaustion-rewind.test.d.ts.map +0 -1
  514. package/dist/test/inference-exhaustion-rewind.test.js +0 -387
  515. package/dist/test/inference-exhaustion-rewind.test.js.map +0 -1
  516. package/dist/test/inference-failure-bounds.test.d.ts +0 -2
  517. package/dist/test/inference-failure-bounds.test.d.ts.map +0 -1
  518. package/dist/test/inference-failure-bounds.test.js +0 -1202
  519. package/dist/test/inference-failure-bounds.test.js.map +0 -1
  520. package/dist/test/inference-failure-observability.test.d.ts +0 -2
  521. package/dist/test/inference-failure-observability.test.d.ts.map +0 -1
  522. package/dist/test/inference-failure-observability.test.js +0 -84
  523. package/dist/test/inference-failure-observability.test.js.map +0 -1
  524. package/dist/test/journal-tool.test.d.ts +0 -2
  525. package/dist/test/journal-tool.test.d.ts.map +0 -1
  526. package/dist/test/journal-tool.test.js +0 -33
  527. package/dist/test/journal-tool.test.js.map +0 -1
  528. package/dist/test/kv-unified-open-flight-retry.test.d.ts +0 -2
  529. package/dist/test/kv-unified-open-flight-retry.test.d.ts.map +0 -1
  530. package/dist/test/kv-unified-open-flight-retry.test.js +0 -189
  531. package/dist/test/kv-unified-open-flight-retry.test.js.map +0 -1
  532. package/dist/test/kv-unified-wiring.test.d.ts +0 -2
  533. package/dist/test/kv-unified-wiring.test.d.ts.map +0 -1
  534. package/dist/test/kv-unified-wiring.test.js +0 -95
  535. package/dist/test/kv-unified-wiring.test.js.map +0 -1
  536. package/dist/test/late-events-after-stop.test.d.ts +0 -2
  537. package/dist/test/late-events-after-stop.test.d.ts.map +0 -1
  538. package/dist/test/late-events-after-stop.test.js +0 -122
  539. package/dist/test/late-events-after-stop.test.js.map +0 -1
  540. package/dist/test/liveness-watchdog.test.d.ts +0 -2
  541. package/dist/test/liveness-watchdog.test.d.ts.map +0 -1
  542. package/dist/test/liveness-watchdog.test.js +0 -94
  543. package/dist/test/liveness-watchdog.test.js.map +0 -1
  544. package/dist/test/machine-close-provenance.test.d.ts +0 -2
  545. package/dist/test/machine-close-provenance.test.d.ts.map +0 -1
  546. package/dist/test/machine-close-provenance.test.js +0 -116
  547. package/dist/test/machine-close-provenance.test.js.map +0 -1
  548. package/dist/test/maintenance-timer.test.d.ts +0 -2
  549. package/dist/test/maintenance-timer.test.d.ts.map +0 -1
  550. package/dist/test/maintenance-timer.test.js +0 -1827
  551. package/dist/test/maintenance-timer.test.js.map +0 -1
  552. package/dist/test/mcp-server-bin.test.d.ts +0 -2
  553. package/dist/test/mcp-server-bin.test.d.ts.map +0 -1
  554. package/dist/test/mcp-server-bin.test.js +0 -142
  555. package/dist/test/mcp-server-bin.test.js.map +0 -1
  556. package/dist/test/mcpl-access-provider.test.d.ts +0 -2
  557. package/dist/test/mcpl-access-provider.test.d.ts.map +0 -1
  558. package/dist/test/mcpl-access-provider.test.js +0 -20
  559. package/dist/test/mcpl-access-provider.test.js.map +0 -1
  560. package/dist/test/mcpl-awareness-barrier.test.d.ts +0 -2
  561. package/dist/test/mcpl-awareness-barrier.test.d.ts.map +0 -1
  562. package/dist/test/mcpl-awareness-barrier.test.js +0 -769
  563. package/dist/test/mcpl-awareness-barrier.test.js.map +0 -1
  564. package/dist/test/mcpl-capability-grant.test.d.ts +0 -10
  565. package/dist/test/mcpl-capability-grant.test.d.ts.map +0 -1
  566. package/dist/test/mcpl-capability-grant.test.js +0 -111
  567. package/dist/test/mcpl-capability-grant.test.js.map +0 -1
  568. package/dist/test/mcpl-capability-scoping.test.d.ts +0 -2
  569. package/dist/test/mcpl-capability-scoping.test.d.ts.map +0 -1
  570. package/dist/test/mcpl-capability-scoping.test.js +0 -266
  571. package/dist/test/mcpl-capability-scoping.test.js.map +0 -1
  572. package/dist/test/mcpl-child-env.test.d.ts +0 -2
  573. package/dist/test/mcpl-child-env.test.d.ts.map +0 -1
  574. package/dist/test/mcpl-child-env.test.js +0 -158
  575. package/dist/test/mcpl-child-env.test.js.map +0 -1
  576. package/dist/test/mcpl-coalesced-content-parity.test.d.ts +0 -2
  577. package/dist/test/mcpl-coalesced-content-parity.test.d.ts.map +0 -1
  578. package/dist/test/mcpl-coalesced-content-parity.test.js +0 -532
  579. package/dist/test/mcpl-coalesced-content-parity.test.js.map +0 -1
  580. package/dist/test/mcpl-coalescing.test.d.ts +0 -2
  581. package/dist/test/mcpl-coalescing.test.d.ts.map +0 -1
  582. package/dist/test/mcpl-coalescing.test.js +0 -1125
  583. package/dist/test/mcpl-coalescing.test.js.map +0 -1
  584. package/dist/test/mcpl-config-diagnostics.test.d.ts +0 -2
  585. package/dist/test/mcpl-config-diagnostics.test.d.ts.map +0 -1
  586. package/dist/test/mcpl-config-diagnostics.test.js +0 -452
  587. package/dist/test/mcpl-config-diagnostics.test.js.map +0 -1
  588. package/dist/test/mcpl-empty-content.test.d.ts +0 -2
  589. package/dist/test/mcpl-empty-content.test.d.ts.map +0 -1
  590. package/dist/test/mcpl-empty-content.test.js +0 -368
  591. package/dist/test/mcpl-empty-content.test.js.map +0 -1
  592. package/dist/test/mcpl-gate-roundtrip.test.d.ts +0 -2
  593. package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +0 -1
  594. package/dist/test/mcpl-gate-roundtrip.test.js +0 -285
  595. package/dist/test/mcpl-gate-roundtrip.test.js.map +0 -1
  596. package/dist/test/mcpl-list-status.test.d.ts +0 -2
  597. package/dist/test/mcpl-list-status.test.d.ts.map +0 -1
  598. package/dist/test/mcpl-list-status.test.js +0 -82
  599. package/dist/test/mcpl-list-status.test.js.map +0 -1
  600. package/dist/test/mcpl-manifest-changed.test.d.ts +0 -2
  601. package/dist/test/mcpl-manifest-changed.test.d.ts.map +0 -1
  602. package/dist/test/mcpl-manifest-changed.test.js +0 -178
  603. package/dist/test/mcpl-manifest-changed.test.js.map +0 -1
  604. package/dist/test/mcpl-push-convert.test.d.ts +0 -2
  605. package/dist/test/mcpl-push-convert.test.d.ts.map +0 -1
  606. package/dist/test/mcpl-push-convert.test.js +0 -42
  607. package/dist/test/mcpl-push-convert.test.js.map +0 -1
  608. package/dist/test/mcpl-reconnect-events.test.d.ts +0 -2
  609. package/dist/test/mcpl-reconnect-events.test.d.ts.map +0 -1
  610. package/dist/test/mcpl-reconnect-events.test.js +0 -144
  611. package/dist/test/mcpl-reconnect-events.test.js.map +0 -1
  612. package/dist/test/mcpl-reconnect-reregistration.test.d.ts +0 -2
  613. package/dist/test/mcpl-reconnect-reregistration.test.d.ts.map +0 -1
  614. package/dist/test/mcpl-reconnect-reregistration.test.js +0 -238
  615. package/dist/test/mcpl-reconnect-reregistration.test.js.map +0 -1
  616. package/dist/test/mcpl-reference-fetcher.test.d.ts +0 -2
  617. package/dist/test/mcpl-reference-fetcher.test.d.ts.map +0 -1
  618. package/dist/test/mcpl-reference-fetcher.test.js +0 -427
  619. package/dist/test/mcpl-reference-fetcher.test.js.map +0 -1
  620. package/dist/test/mcpl-reference-fields.test.d.ts +0 -2
  621. package/dist/test/mcpl-reference-fields.test.d.ts.map +0 -1
  622. package/dist/test/mcpl-reference-fields.test.js +0 -149
  623. package/dist/test/mcpl-reference-fields.test.js.map +0 -1
  624. package/dist/test/mcpl-rejection-log-lines.test.d.ts +0 -2
  625. package/dist/test/mcpl-rejection-log-lines.test.d.ts.map +0 -1
  626. package/dist/test/mcpl-rejection-log-lines.test.js +0 -349
  627. package/dist/test/mcpl-rejection-log-lines.test.js.map +0 -1
  628. package/dist/test/mcpl-request-timeout.test.d.ts +0 -2
  629. package/dist/test/mcpl-request-timeout.test.d.ts.map +0 -1
  630. package/dist/test/mcpl-request-timeout.test.js +0 -138
  631. package/dist/test/mcpl-request-timeout.test.js.map +0 -1
  632. package/dist/test/mcpl-runtime-lifecycle.test.d.ts +0 -7
  633. package/dist/test/mcpl-runtime-lifecycle.test.d.ts.map +0 -1
  634. package/dist/test/mcpl-runtime-lifecycle.test.js +0 -142
  635. package/dist/test/mcpl-runtime-lifecycle.test.js.map +0 -1
  636. package/dist/test/mcpl-stderr-tail.test.d.ts +0 -2
  637. package/dist/test/mcpl-stderr-tail.test.d.ts.map +0 -1
  638. package/dist/test/mcpl-stderr-tail.test.js +0 -210
  639. package/dist/test/mcpl-stderr-tail.test.js.map +0 -1
  640. package/dist/test/mcpl-tool-class-listing.test.d.ts +0 -2
  641. package/dist/test/mcpl-tool-class-listing.test.d.ts.map +0 -1
  642. package/dist/test/mcpl-tool-class-listing.test.js +0 -147
  643. package/dist/test/mcpl-tool-class-listing.test.js.map +0 -1
  644. package/dist/test/mcpl-tool-classes.test.d.ts +0 -7
  645. package/dist/test/mcpl-tool-classes.test.d.ts.map +0 -1
  646. package/dist/test/mcpl-tool-classes.test.js +0 -80
  647. package/dist/test/mcpl-tool-classes.test.js.map +0 -1
  648. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +0 -2
  649. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +0 -1
  650. package/dist/test/mcpl-tool-lifecycle-e2e.test.js +0 -237
  651. package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +0 -1
  652. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +0 -11
  653. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +0 -1
  654. package/dist/test/mcpl-tool-lifecycle-emitter.test.js +0 -412
  655. package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +0 -1
  656. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts +0 -2
  657. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts.map +0 -1
  658. package/dist/test/mcpl-tool-lifecycle-script.test.js +0 -288
  659. package/dist/test/mcpl-tool-lifecycle-script.test.js.map +0 -1
  660. package/dist/test/mcpl-tool-lifecycle.test.d.ts +0 -11
  661. package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +0 -1
  662. package/dist/test/mcpl-tool-lifecycle.test.js +0 -270
  663. package/dist/test/mcpl-tool-lifecycle.test.js.map +0 -1
  664. package/dist/test/mcpl-transport-close.test.d.ts +0 -2
  665. package/dist/test/mcpl-transport-close.test.d.ts.map +0 -1
  666. package/dist/test/mcpl-transport-close.test.js +0 -373
  667. package/dist/test/mcpl-transport-close.test.js.map +0 -1
  668. package/dist/test/mcpl-transport-spawn.test.d.ts +0 -2
  669. package/dist/test/mcpl-transport-spawn.test.d.ts.map +0 -1
  670. package/dist/test/mcpl-transport-spawn.test.js +0 -58
  671. package/dist/test/mcpl-transport-spawn.test.js.map +0 -1
  672. package/dist/test/mcpl-ws-transport.test.d.ts +0 -2
  673. package/dist/test/mcpl-ws-transport.test.d.ts.map +0 -1
  674. package/dist/test/mcpl-ws-transport.test.js +0 -259
  675. package/dist/test/mcpl-ws-transport.test.js.map +0 -1
  676. package/dist/test/module-context-integration.test.d.ts +0 -18
  677. package/dist/test/module-context-integration.test.d.ts.map +0 -1
  678. package/dist/test/module-context-integration.test.js +0 -181
  679. package/dist/test/module-context-integration.test.js.map +0 -1
  680. package/dist/test/offline-recovery-branch.test.d.ts +0 -2
  681. package/dist/test/offline-recovery-branch.test.d.ts.map +0 -1
  682. package/dist/test/offline-recovery-branch.test.js +0 -570
  683. package/dist/test/offline-recovery-branch.test.js.map +0 -1
  684. package/dist/test/operator-surgery.test.d.ts +0 -2
  685. package/dist/test/operator-surgery.test.d.ts.map +0 -1
  686. package/dist/test/operator-surgery.test.js +0 -595
  687. package/dist/test/operator-surgery.test.js.map +0 -1
  688. package/dist/test/ops-alert.test.d.ts +0 -2
  689. package/dist/test/ops-alert.test.d.ts.map +0 -1
  690. package/dist/test/ops-alert.test.js +0 -153
  691. package/dist/test/ops-alert.test.js.map +0 -1
  692. package/dist/test/overbudget-drain-breaker.test.d.ts +0 -2
  693. package/dist/test/overbudget-drain-breaker.test.d.ts.map +0 -1
  694. package/dist/test/overbudget-drain-breaker.test.js +0 -198
  695. package/dist/test/overbudget-drain-breaker.test.js.map +0 -1
  696. package/dist/test/pack-installs-alone.test.d.ts +0 -2
  697. package/dist/test/pack-installs-alone.test.d.ts.map +0 -1
  698. package/dist/test/pack-installs-alone.test.js +0 -284
  699. package/dist/test/pack-installs-alone.test.js.map +0 -1
  700. package/dist/test/per-agent-delivery.test.d.ts +0 -2
  701. package/dist/test/per-agent-delivery.test.d.ts.map +0 -1
  702. package/dist/test/per-agent-delivery.test.js +0 -108
  703. package/dist/test/per-agent-delivery.test.js.map +0 -1
  704. package/dist/test/physical-window-restart.test.d.ts +0 -16
  705. package/dist/test/physical-window-restart.test.d.ts.map +0 -1
  706. package/dist/test/physical-window-restart.test.js +0 -487
  707. package/dist/test/physical-window-restart.test.js.map +0 -1
  708. package/dist/test/placed-reaction-baseline.test.d.ts +0 -2
  709. package/dist/test/placed-reaction-baseline.test.d.ts.map +0 -1
  710. package/dist/test/placed-reaction-baseline.test.js +0 -312
  711. package/dist/test/placed-reaction-baseline.test.js.map +0 -1
  712. package/dist/test/present-while-acting.test.d.ts +0 -19
  713. package/dist/test/present-while-acting.test.d.ts.map +0 -1
  714. package/dist/test/present-while-acting.test.js +0 -1649
  715. package/dist/test/present-while-acting.test.js.map +0 -1
  716. package/dist/test/prose-segments.test.d.ts +0 -2
  717. package/dist/test/prose-segments.test.d.ts.map +0 -1
  718. package/dist/test/prose-segments.test.js +0 -52
  719. package/dist/test/prose-segments.test.js.map +0 -1
  720. package/dist/test/prose-stream-router.test.d.ts +0 -2
  721. package/dist/test/prose-stream-router.test.d.ts.map +0 -1
  722. package/dist/test/prose-stream-router.test.js +0 -171
  723. package/dist/test/prose-stream-router.test.js.map +0 -1
  724. package/dist/test/provider-acceleration-cooldown.test.d.ts +0 -2
  725. package/dist/test/provider-acceleration-cooldown.test.d.ts.map +0 -1
  726. package/dist/test/provider-acceleration-cooldown.test.js +0 -435
  727. package/dist/test/provider-acceleration-cooldown.test.js.map +0 -1
  728. package/dist/test/provider-waits.test.d.ts +0 -2
  729. package/dist/test/provider-waits.test.d.ts.map +0 -1
  730. package/dist/test/provider-waits.test.js +0 -2259
  731. package/dist/test/provider-waits.test.js.map +0 -1
  732. package/dist/test/puppet-tool-call.test.d.ts +0 -2
  733. package/dist/test/puppet-tool-call.test.d.ts.map +0 -1
  734. package/dist/test/puppet-tool-call.test.js +0 -226
  735. package/dist/test/puppet-tool-call.test.js.map +0 -1
  736. package/dist/test/puppet-turn-reservation.test.d.ts +0 -2
  737. package/dist/test/puppet-turn-reservation.test.d.ts.map +0 -1
  738. package/dist/test/puppet-turn-reservation.test.js +0 -139
  739. package/dist/test/puppet-turn-reservation.test.js.map +0 -1
  740. package/dist/test/reaction-baseline-platform.test.d.ts +0 -2
  741. package/dist/test/reaction-baseline-platform.test.d.ts.map +0 -1
  742. package/dist/test/reaction-baseline-platform.test.js +0 -124
  743. package/dist/test/reaction-baseline-platform.test.js.map +0 -1
  744. package/dist/test/record-journal.test.d.ts +0 -6
  745. package/dist/test/record-journal.test.d.ts.map +0 -1
  746. package/dist/test/record-journal.test.js +0 -269
  747. package/dist/test/record-journal.test.js.map +0 -1
  748. package/dist/test/refusal-reaction-baseline.test.d.ts +0 -2
  749. package/dist/test/refusal-reaction-baseline.test.d.ts.map +0 -1
  750. package/dist/test/refusal-reaction-baseline.test.js +0 -81
  751. package/dist/test/refusal-reaction-baseline.test.js.map +0 -1
  752. package/dist/test/refusal-rewind.test.d.ts +0 -2
  753. package/dist/test/refusal-rewind.test.d.ts.map +0 -1
  754. package/dist/test/refusal-rewind.test.js +0 -117
  755. package/dist/test/refusal-rewind.test.js.map +0 -1
  756. package/dist/test/refusal-single-call.test.d.ts +0 -2
  757. package/dist/test/refusal-single-call.test.d.ts.map +0 -1
  758. package/dist/test/refusal-single-call.test.js +0 -177
  759. package/dist/test/refusal-single-call.test.js.map +0 -1
  760. package/dist/test/release-bump.test.d.ts +0 -2
  761. package/dist/test/release-bump.test.d.ts.map +0 -1
  762. package/dist/test/release-bump.test.js +0 -248
  763. package/dist/test/release-bump.test.js.map +0 -1
  764. package/dist/test/release-changelog.test.d.ts +0 -2
  765. package/dist/test/release-changelog.test.d.ts.map +0 -1
  766. package/dist/test/release-changelog.test.js +0 -159
  767. package/dist/test/release-changelog.test.js.map +0 -1
  768. package/dist/test/release-holds.test.d.ts +0 -2
  769. package/dist/test/release-holds.test.d.ts.map +0 -1
  770. package/dist/test/release-holds.test.js +0 -456
  771. package/dist/test/release-holds.test.js.map +0 -1
  772. package/dist/test/same-round-think-policy.test.d.ts +0 -2
  773. package/dist/test/same-round-think-policy.test.d.ts.map +0 -1
  774. package/dist/test/same-round-think-policy.test.js +0 -853
  775. package/dist/test/same-round-think-policy.test.js.map +0 -1
  776. package/dist/test/save-recent-image.test.d.ts +0 -26
  777. package/dist/test/save-recent-image.test.d.ts.map +0 -1
  778. package/dist/test/save-recent-image.test.js +0 -974
  779. package/dist/test/save-recent-image.test.js.map +0 -1
  780. package/dist/test/shutdown-errors.test.d.ts +0 -2
  781. package/dist/test/shutdown-errors.test.d.ts.map +0 -1
  782. package/dist/test/shutdown-errors.test.js +0 -662
  783. package/dist/test/shutdown-errors.test.js.map +0 -1
  784. package/dist/test/silent-heartbeat-rows.test.d.ts +0 -2
  785. package/dist/test/silent-heartbeat-rows.test.d.ts.map +0 -1
  786. package/dist/test/silent-heartbeat-rows.test.js +0 -451
  787. package/dist/test/silent-heartbeat-rows.test.js.map +0 -1
  788. package/dist/test/silent-heartbeat.test.d.ts +0 -2
  789. package/dist/test/silent-heartbeat.test.d.ts.map +0 -1
  790. package/dist/test/silent-heartbeat.test.js +0 -165
  791. package/dist/test/silent-heartbeat.test.js.map +0 -1
  792. package/dist/test/state-scaling-e2e.test.d.ts +0 -22
  793. package/dist/test/state-scaling-e2e.test.d.ts.map +0 -1
  794. package/dist/test/state-scaling-e2e.test.js +0 -206
  795. package/dist/test/state-scaling-e2e.test.js.map +0 -1
  796. package/dist/test/state-scaling.test.d.ts +0 -12
  797. package/dist/test/state-scaling.test.d.ts.map +0 -1
  798. package/dist/test/state-scaling.test.js +0 -251
  799. package/dist/test/state-scaling.test.js.map +0 -1
  800. package/dist/test/stop-with-host-operations.test.d.ts +0 -20
  801. package/dist/test/stop-with-host-operations.test.d.ts.map +0 -1
  802. package/dist/test/stop-with-host-operations.test.js +0 -1174
  803. package/dist/test/stop-with-host-operations.test.js.map +0 -1
  804. package/dist/test/stop-with-work-in-flight.test.d.ts +0 -23
  805. package/dist/test/stop-with-work-in-flight.test.d.ts.map +0 -1
  806. package/dist/test/stop-with-work-in-flight.test.js +0 -784
  807. package/dist/test/stop-with-work-in-flight.test.js.map +0 -1
  808. package/dist/test/surgery-marks-receipt.test.d.ts +0 -2
  809. package/dist/test/surgery-marks-receipt.test.d.ts.map +0 -1
  810. package/dist/test/surgery-marks-receipt.test.js +0 -540
  811. package/dist/test/surgery-marks-receipt.test.js.map +0 -1
  812. package/dist/test/thinking-token-stamp.test.d.ts +0 -12
  813. package/dist/test/thinking-token-stamp.test.d.ts.map +0 -1
  814. package/dist/test/thinking-token-stamp.test.js +0 -129
  815. package/dist/test/thinking-token-stamp.test.js.map +0 -1
  816. package/dist/test/timezone.test.d.ts +0 -2
  817. package/dist/test/timezone.test.d.ts.map +0 -1
  818. package/dist/test/timezone.test.js +0 -18
  819. package/dist/test/timezone.test.js.map +0 -1
  820. package/dist/test/tool-batch-hook.test.d.ts +0 -8
  821. package/dist/test/tool-batch-hook.test.d.ts.map +0 -1
  822. package/dist/test/tool-batch-hook.test.js +0 -275
  823. package/dist/test/tool-batch-hook.test.js.map +0 -1
  824. package/dist/test/tool-policy.test.d.ts +0 -2
  825. package/dist/test/tool-policy.test.d.ts.map +0 -1
  826. package/dist/test/tool-policy.test.js +0 -51
  827. package/dist/test/tool-policy.test.js.map +0 -1
  828. package/dist/test/tool-presentation.test.d.ts +0 -2
  829. package/dist/test/tool-presentation.test.d.ts.map +0 -1
  830. package/dist/test/tool-presentation.test.js +0 -268
  831. package/dist/test/tool-presentation.test.js.map +0 -1
  832. package/dist/test/tool-result-content.test.d.ts +0 -2
  833. package/dist/test/tool-result-content.test.d.ts.map +0 -1
  834. package/dist/test/tool-result-content.test.js +0 -37
  835. package/dist/test/tool-result-content.test.js.map +0 -1
  836. package/dist/test/tool-result-guard.test.d.ts +0 -2
  837. package/dist/test/tool-result-guard.test.d.ts.map +0 -1
  838. package/dist/test/tool-result-guard.test.js +0 -3729
  839. package/dist/test/tool-result-guard.test.js.map +0 -1
  840. package/dist/test/tool-result-history.test.d.ts +0 -7
  841. package/dist/test/tool-result-history.test.d.ts.map +0 -1
  842. package/dist/test/tool-result-history.test.js +0 -156
  843. package/dist/test/tool-result-history.test.js.map +0 -1
  844. package/dist/test/tool-result-spill.test.d.ts +0 -13
  845. package/dist/test/tool-result-spill.test.d.ts.map +0 -1
  846. package/dist/test/tool-result-spill.test.js +0 -586
  847. package/dist/test/tool-result-spill.test.js.map +0 -1
  848. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts +0 -2
  849. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts.map +0 -1
  850. package/dist/test/tool-wrapper-prose-guard-integration.test.js +0 -485
  851. package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +0 -1
  852. package/dist/test/tool-wrapper-prose-guard.test.d.ts +0 -2
  853. package/dist/test/tool-wrapper-prose-guard.test.d.ts.map +0 -1
  854. package/dist/test/tool-wrapper-prose-guard.test.js +0 -34
  855. package/dist/test/tool-wrapper-prose-guard.test.js.map +0 -1
  856. package/dist/test/tools-observe-parser-conformance.test.d.ts +0 -2
  857. package/dist/test/tools-observe-parser-conformance.test.d.ts.map +0 -1
  858. package/dist/test/tools-observe-parser-conformance.test.js +0 -129
  859. package/dist/test/tools-observe-parser-conformance.test.js.map +0 -1
  860. package/dist/test/trunk-channel-routing.test.d.ts +0 -19
  861. package/dist/test/trunk-channel-routing.test.d.ts.map +0 -1
  862. package/dist/test/trunk-channel-routing.test.js +0 -652
  863. package/dist/test/trunk-channel-routing.test.js.map +0 -1
  864. package/dist/test/tune-out-e2e.test.d.ts +0 -2
  865. package/dist/test/tune-out-e2e.test.d.ts.map +0 -1
  866. package/dist/test/tune-out-e2e.test.js +0 -142
  867. package/dist/test/tune-out-e2e.test.js.map +0 -1
  868. package/dist/test/tune-out-gate-composition.test.d.ts +0 -2
  869. package/dist/test/tune-out-gate-composition.test.d.ts.map +0 -1
  870. package/dist/test/tune-out-gate-composition.test.js +0 -221
  871. package/dist/test/tune-out-gate-composition.test.js.map +0 -1
  872. package/dist/test/tune-out-lifecycle.test.d.ts +0 -2
  873. package/dist/test/tune-out-lifecycle.test.d.ts.map +0 -1
  874. package/dist/test/tune-out-lifecycle.test.js +0 -121
  875. package/dist/test/tune-out-lifecycle.test.js.map +0 -1
  876. package/dist/test/turn-trigger-provenance.test.d.ts +0 -2
  877. package/dist/test/turn-trigger-provenance.test.d.ts.map +0 -1
  878. package/dist/test/turn-trigger-provenance.test.js +0 -137
  879. package/dist/test/turn-trigger-provenance.test.js.map +0 -1
  880. package/dist/test/unconvertible-tool-result.test.d.ts +0 -2
  881. package/dist/test/unconvertible-tool-result.test.d.ts.map +0 -1
  882. package/dist/test/unconvertible-tool-result.test.js +0 -358
  883. package/dist/test/unconvertible-tool-result.test.js.map +0 -1
  884. package/dist/test/unsent-compiles.test.d.ts +0 -2
  885. package/dist/test/unsent-compiles.test.d.ts.map +0 -1
  886. package/dist/test/unsent-compiles.test.js +0 -139
  887. package/dist/test/unsent-compiles.test.js.map +0 -1
  888. package/dist/test/usage-accounting.test.d.ts +0 -2
  889. package/dist/test/usage-accounting.test.d.ts.map +0 -1
  890. package/dist/test/usage-accounting.test.js +0 -13
  891. package/dist/test/usage-accounting.test.js.map +0 -1
  892. package/dist/test/usage-tracker.test.d.ts +0 -2
  893. package/dist/test/usage-tracker.test.d.ts.map +0 -1
  894. package/dist/test/usage-tracker.test.js +0 -129
  895. package/dist/test/usage-tracker.test.js.map +0 -1
  896. package/dist/test/utils-surface.test.d.ts +0 -2
  897. package/dist/test/utils-surface.test.d.ts.map +0 -1
  898. package/dist/test/utils-surface.test.js +0 -145
  899. package/dist/test/utils-surface.test.js.map +0 -1
  900. package/dist/test/workspace-branch-continuation.test.d.ts +0 -15
  901. package/dist/test/workspace-branch-continuation.test.d.ts.map +0 -1
  902. package/dist/test/workspace-branch-continuation.test.js +0 -183
  903. package/dist/test/workspace-branch-continuation.test.js.map +0 -1
  904. package/dist/test/workspace-materialize-freshness.test.d.ts +0 -16
  905. package/dist/test/workspace-materialize-freshness.test.d.ts.map +0 -1
  906. package/dist/test/workspace-materialize-freshness.test.js +0 -252
  907. package/dist/test/workspace-materialize-freshness.test.js.map +0 -1
  908. package/dist/test/workspace-path-containment.test.d.ts +0 -19
  909. package/dist/test/workspace-path-containment.test.d.ts.map +0 -1
  910. package/dist/test/workspace-path-containment.test.js +0 -91
  911. package/dist/test/workspace-path-containment.test.js.map +0 -1
  912. package/dist/test/workspace-read-file-from-disk.test.d.ts +0 -17
  913. package/dist/test/workspace-read-file-from-disk.test.d.ts.map +0 -1
  914. package/dist/test/workspace-read-file-from-disk.test.js +0 -174
  915. package/dist/test/workspace-read-file-from-disk.test.js.map +0 -1
  916. package/dist/test/workspace-read-image.test.d.ts +0 -2
  917. package/dist/test/workspace-read-image.test.d.ts.map +0 -1
  918. package/dist/test/workspace-read-image.test.js +0 -597
  919. package/dist/test/workspace-read-image.test.js.map +0 -1
  920. package/dist/test/workspace-read-text.test.d.ts +0 -2
  921. package/dist/test/workspace-read-text.test.d.ts.map +0 -1
  922. package/dist/test/workspace-read-text.test.js +0 -101
  923. package/dist/test/workspace-read-text.test.js.map +0 -1
  924. package/dist/test/workspace-restore-order.test.d.ts +0 -16
  925. package/dist/test/workspace-restore-order.test.d.ts.map +0 -1
  926. package/dist/test/workspace-restore-order.test.js +0 -140
  927. package/dist/test/workspace-restore-order.test.js.map +0 -1
  928. package/dist/test/workspace-three-way.test.d.ts +0 -12
  929. package/dist/test/workspace-three-way.test.d.ts.map +0 -1
  930. package/dist/test/workspace-three-way.test.js +0 -4094
  931. package/dist/test/workspace-three-way.test.js.map +0 -1
  932. package/dist/test/workspace-watcher.test.d.ts +0 -2
  933. package/dist/test/workspace-watcher.test.d.ts.map +0 -1
  934. package/dist/test/workspace-watcher.test.js +0 -281
  935. package/dist/test/workspace-watcher.test.js.map +0 -1
  936. package/dist/test/xml-round-persist.test.d.ts +0 -19
  937. package/dist/test/xml-round-persist.test.d.ts.map +0 -1
  938. package/dist/test/xml-round-persist.test.js +0 -235
  939. package/dist/test/xml-round-persist.test.js.map +0 -1
  940. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,919 +0,0 @@
1
- import { describe, it, beforeEach, afterEach } from 'node:test';
2
- import assert from 'node:assert';
3
- import { existsSync, mkdirSync, writeFileSync, rmSync, readFileSync } from 'node:fs';
4
- import { join } from 'node:path';
5
- import { EventGate } from '../src/gate/event-gate.js';
6
- // ---------------------------------------------------------------------------
7
- // Helpers
8
- // ---------------------------------------------------------------------------
9
- const TMP_DIR = join(import.meta.dirname, '../.test-tmp-gate');
10
- function tmpPath(name) {
11
- return join(TMP_DIR, name);
12
- }
13
- function writeConfig(name, config) {
14
- const path = tmpPath(name);
15
- mkdirSync(TMP_DIR, { recursive: true });
16
- writeFileSync(path, JSON.stringify(config, null, 2));
17
- return path;
18
- }
19
- function makeGate(configPath, opts) {
20
- const traces = [];
21
- const messages = [];
22
- const inferenceRequests = [];
23
- const gate = new EventGate({
24
- configPath,
25
- initialConfig: opts?.initialConfig,
26
- ...(opts?.resolveRouteChannel ? { resolveRouteChannel: opts.resolveRouteChannel } : {}),
27
- emitTrace: (e) => traces.push(e),
28
- addMessage: (p, c, m) => { messages.push({ participant: p, content: c, metadata: m }); return ''; },
29
- requestInference: (a, r, s, p) => inferenceRequests.push({ agentName: a, reason: r, source: s, ...(p ?? {}) }),
30
- getAgentNames: () => ['agent'],
31
- });
32
- return { gate, traces, messages, inferenceRequests };
33
- }
34
- function event(overrides) {
35
- return {
36
- content: 'test message',
37
- eventType: 'mcpl:push-event',
38
- serverId: '',
39
- channelId: '',
40
- ...overrides,
41
- };
42
- }
43
- // ---------------------------------------------------------------------------
44
- // Setup / Teardown
45
- // ---------------------------------------------------------------------------
46
- beforeEach(() => {
47
- mkdirSync(TMP_DIR, { recursive: true });
48
- });
49
- afterEach(() => {
50
- if (existsSync(TMP_DIR)) {
51
- rmSync(TMP_DIR, { recursive: true, force: true });
52
- }
53
- });
54
- // ---------------------------------------------------------------------------
55
- // Default behavior (no config file)
56
- // ---------------------------------------------------------------------------
57
- describe('default behavior', () => {
58
- it('no config file + no initial config → all-pass', () => {
59
- const { gate } = makeGate(tmpPath('nonexistent.json'));
60
- const decision = gate.evaluate(event());
61
- assert.strictEqual(decision.trigger, true);
62
- assert.strictEqual(decision.policyName, null);
63
- });
64
- it('default: skip → all skipped', () => {
65
- const path = writeConfig('skip-default.json', {
66
- policies: [],
67
- default: 'skip',
68
- });
69
- const { gate } = makeGate(path);
70
- const decision = gate.evaluate(event());
71
- assert.strictEqual(decision.trigger, false);
72
- });
73
- });
74
- // ---------------------------------------------------------------------------
75
- // Policy matching
76
- // ---------------------------------------------------------------------------
77
- describe('policy matching', () => {
78
- it('scope match — matching event type', () => {
79
- const path = writeConfig('scope.json', {
80
- policies: [
81
- { name: 'channels', match: { scope: ['mcpl:channel-incoming'] }, behavior: 'always' },
82
- ],
83
- default: 'skip',
84
- });
85
- const { gate } = makeGate(path);
86
- assert.strictEqual(gate.evaluate(event({ eventType: 'mcpl:channel-incoming' })).trigger, true);
87
- assert.strictEqual(gate.evaluate(event({ eventType: 'mcpl:push-event' })).trigger, false);
88
- });
89
- it('source match — exact serverId', () => {
90
- const path = writeConfig('source.json', {
91
- policies: [
92
- { name: 'zulip', match: { source: 'zulip' }, behavior: 'always' },
93
- ],
94
- default: 'skip',
95
- });
96
- const { gate } = makeGate(path);
97
- assert.strictEqual(gate.evaluate(event({ serverId: 'zulip' })).trigger, true);
98
- assert.strictEqual(gate.evaluate(event({ serverId: 'discord' })).trigger, false);
99
- });
100
- it('source match — glob pattern', () => {
101
- const path = writeConfig('source-glob.json', {
102
- policies: [
103
- { name: 'any-zulip', match: { source: 'zulip-*' }, behavior: 'always' },
104
- ],
105
- default: 'skip',
106
- });
107
- const { gate } = makeGate(path);
108
- assert.strictEqual(gate.evaluate(event({ serverId: 'zulip-prod' })).trigger, true);
109
- assert.strictEqual(gate.evaluate(event({ serverId: 'zulip-staging' })).trigger, true);
110
- assert.strictEqual(gate.evaluate(event({ serverId: 'discord' })).trigger, false);
111
- });
112
- it('channel match — glob pattern', () => {
113
- const path = writeConfig('channel-glob.json', {
114
- policies: [
115
- { name: 'dev-channels', match: { channel: 'dev-*' }, behavior: 'always' },
116
- ],
117
- default: 'skip',
118
- });
119
- const { gate } = makeGate(path);
120
- assert.strictEqual(gate.evaluate(event({ channelId: 'dev-backend' })).trigger, true);
121
- assert.strictEqual(gate.evaluate(event({ channelId: 'prod-alerts' })).trigger, false);
122
- });
123
- it('mount match — exact name', () => {
124
- const path = writeConfig('mount-exact.json', {
125
- policies: [
126
- {
127
- name: 'tickets',
128
- match: { scope: ['workspace:created'], mount: 'knowledge-requests' },
129
- behavior: 'always',
130
- },
131
- ],
132
- default: 'skip',
133
- });
134
- const { gate } = makeGate(path);
135
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:created', mount: 'knowledge-requests', paths: ['knowledge-requests/t1.md'] })).trigger, true);
136
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:created', mount: 'library-mined', paths: ['library-mined/r1.md'] })).trigger, false);
137
- // Event without a mount must not match a mount-scoped policy.
138
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:created' })).trigger, false);
139
- });
140
- it('pathGlob match — any path matches', () => {
141
- const path = writeConfig('path-glob.json', {
142
- policies: [
143
- {
144
- name: 'md-only',
145
- match: { scope: ['workspace:modified'], pathGlob: '*.md' },
146
- behavior: 'always',
147
- },
148
- ],
149
- default: 'skip',
150
- });
151
- const { gate } = makeGate(path);
152
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:modified', paths: ['tickets/a.md'] })).trigger, true);
153
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:modified', paths: ['logs/a.txt'] })).trigger, false);
154
- // ANY-match: one matching path is enough.
155
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:modified', paths: ['logs/a.txt', 'tickets/b.md'] })).trigger, true);
156
- // Empty paths can't match a pathGlob policy.
157
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:modified', paths: [] })).trigger, false);
158
- });
159
- it('content filter — text match (case insensitive)', () => {
160
- const path = writeConfig('filter-text.json', {
161
- policies: [
162
- { name: 'errors', match: { filter: { type: 'text', pattern: 'ERROR' } }, behavior: 'always' },
163
- ],
164
- default: 'skip',
165
- });
166
- const { gate } = makeGate(path);
167
- assert.strictEqual(gate.evaluate(event({ content: 'Something error happened' })).trigger, true);
168
- assert.strictEqual(gate.evaluate(event({ content: 'All good' })).trigger, false);
169
- });
170
- it('content filter — regex match', () => {
171
- const path = writeConfig('filter-regex.json', {
172
- policies: [
173
- { name: 'deploys', match: { filter: { type: 'regex', pattern: 'deploy|rollback' } }, behavior: 'always' },
174
- ],
175
- default: 'skip',
176
- });
177
- const { gate } = makeGate(path);
178
- assert.strictEqual(gate.evaluate(event({ content: 'Starting deploy v2.3' })).trigger, true);
179
- assert.strictEqual(gate.evaluate(event({ content: 'rollback initiated' })).trigger, true);
180
- assert.strictEqual(gate.evaluate(event({ content: 'Rolling back' })).trigger, false);
181
- });
182
- it('combined match — scope + source + filter (AND logic)', () => {
183
- const path = writeConfig('combined.json', {
184
- policies: [
185
- {
186
- name: 'zulip-errors',
187
- match: {
188
- scope: ['mcpl:channel-incoming'],
189
- source: 'zulip',
190
- filter: { type: 'text', pattern: 'error' },
191
- },
192
- behavior: 'always',
193
- },
194
- ],
195
- default: 'skip',
196
- });
197
- const { gate } = makeGate(path);
198
- // All conditions met
199
- assert.strictEqual(gate.evaluate(event({
200
- content: 'An error occurred',
201
- eventType: 'mcpl:channel-incoming',
202
- serverId: 'zulip',
203
- })).trigger, true);
204
- // Wrong scope
205
- assert.strictEqual(gate.evaluate(event({
206
- content: 'An error occurred',
207
- eventType: 'mcpl:push-event',
208
- serverId: 'zulip',
209
- })).trigger, false);
210
- // Wrong source
211
- assert.strictEqual(gate.evaluate(event({
212
- content: 'An error occurred',
213
- eventType: 'mcpl:channel-incoming',
214
- serverId: 'discord',
215
- })).trigger, false);
216
- // No error keyword
217
- assert.strictEqual(gate.evaluate(event({
218
- content: 'All good',
219
- eventType: 'mcpl:channel-incoming',
220
- serverId: 'zulip',
221
- })).trigger, false);
222
- });
223
- it('first match wins — order matters', () => {
224
- const path = writeConfig('order.json', {
225
- policies: [
226
- { name: 'suppress-noise', match: { filter: { type: 'text', pattern: 'heartbeat' } }, behavior: 'skip' },
227
- { name: 'catch-all', match: {}, behavior: 'always' },
228
- ],
229
- default: 'skip',
230
- });
231
- const { gate } = makeGate(path);
232
- assert.strictEqual(gate.evaluate(event({ content: 'heartbeat ping' })).trigger, false);
233
- assert.strictEqual(gate.evaluate(event({ content: 'real message' })).trigger, true);
234
- });
235
- it('empty match object matches everything', () => {
236
- const path = writeConfig('empty-match.json', {
237
- policies: [
238
- { name: 'catch-all', match: {}, behavior: 'always' },
239
- ],
240
- default: 'skip',
241
- });
242
- const { gate } = makeGate(path);
243
- assert.strictEqual(gate.evaluate(event({ serverId: 'any', channelId: 'any' })).trigger, true);
244
- });
245
- });
246
- // ---------------------------------------------------------------------------
247
- // Behaviors
248
- // ---------------------------------------------------------------------------
249
- describe('behaviors', () => {
250
- it('always → trigger: true', () => {
251
- const path = writeConfig('always.json', {
252
- policies: [{ name: 'all', match: {}, behavior: 'always' }],
253
- default: 'skip',
254
- });
255
- const { gate } = makeGate(path);
256
- const d = gate.evaluate(event());
257
- assert.strictEqual(d.trigger, true);
258
- assert.strictEqual(d.behavior, 'always');
259
- });
260
- it('skip → trigger: false', () => {
261
- const path = writeConfig('skip.json', {
262
- policies: [{ name: 'quiet', match: {}, behavior: 'skip' }],
263
- default: 'always',
264
- });
265
- const { gate } = makeGate(path);
266
- const d = gate.evaluate(event());
267
- assert.strictEqual(d.trigger, false);
268
- assert.strictEqual(d.behavior, 'skip');
269
- assert.strictEqual(d.policyName, 'quiet');
270
- });
271
- });
272
- // ---------------------------------------------------------------------------
273
- // Debounce
274
- // ---------------------------------------------------------------------------
275
- describe('debounce', () => {
276
- it('returns false immediately', () => {
277
- const path = writeConfig('debounce.json', {
278
- policies: [
279
- { name: 'editor', match: { scope: ['mcpl:push-event'] }, behavior: { debounce: 100 } },
280
- ],
281
- default: 'skip',
282
- });
283
- const { gate } = makeGate(path);
284
- const d = gate.evaluate(event());
285
- assert.strictEqual(d.trigger, false);
286
- assert.deepStrictEqual(d.behavior, { debounce: 100 });
287
- });
288
- it('batches events and fires after delay', async () => {
289
- const path = writeConfig('debounce-fire.json', {
290
- policies: [
291
- { name: 'editor', match: { scope: ['mcpl:push-event'] }, behavior: { debounce: 150 } },
292
- ],
293
- default: 'skip',
294
- });
295
- const { gate, messages, inferenceRequests } = makeGate(path);
296
- gate.evaluate(event({ content: 'edit 1' }));
297
- gate.evaluate(event({ content: 'edit 2' }));
298
- gate.evaluate(event({ content: 'edit 3' }));
299
- // Should not have delivered yet
300
- assert.strictEqual(messages.length, 0);
301
- // Wait for debounce to fire
302
- await new Promise(r => setTimeout(r, 200));
303
- assert.strictEqual(messages.length, 1);
304
- const text = messages[0].content[0].text;
305
- assert.ok(text.includes('3 event'));
306
- // MCPL events (push-event / channel-incoming) are stored in the context
307
- // window AT ARRIVAL by the framework, so the batched wake references them
308
- // instead of re-quoting — a re-quote minutes later reads as fresh, stale
309
- // duplicate input (observed live: Sol's "step was a bit too small" echo).
310
- assert.ok(text.includes('already shown above'));
311
- assert.ok(!text.includes('edit 1'), 'must not re-quote in-context event content');
312
- assert.strictEqual(inferenceRequests.length, 1);
313
- assert.strictEqual(inferenceRequests[0].agentName, 'agent');
314
- });
315
- it('a batched wake carries the newest channel event\'s channel AND author together (provenance)', async () => {
316
- const path = writeConfig('debounce-provenance.json', {
317
- policies: [
318
- { name: 'chat', match: { scope: ['mcpl:channel-incoming'] }, behavior: { debounce: 100 } },
319
- ],
320
- default: 'skip',
321
- });
322
- const { gate, inferenceRequests } = makeGate(path);
323
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:alice-room', content: 'a',
324
- metadata: { author: { id: '111', name: 'alice' } } }));
325
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:bob-room', content: 'b',
326
- metadata: { authorId: '222' } }));
327
- await new Promise(r => setTimeout(r, 150));
328
- assert.strictEqual(inferenceRequests.length, 1);
329
- assert.strictEqual(inferenceRequests[0].reason, 'gate:debounce');
330
- assert.strictEqual(inferenceRequests[0].channelId, 'discord:g:bob-room', 'newest channel event wins when none is addressed');
331
- assert.strictEqual(inferenceRequests[0].counterparty, 'discord:user:222', 'author comes from the SAME event as the channel');
332
- assert.strictEqual(inferenceRequests[0].addressed, undefined);
333
- });
334
- it('an older ADDRESSED event outranks newer ambient chatter — channel, author and addressed stay together', async () => {
335
- const path = writeConfig('debounce-addressed.json', {
336
- policies: [
337
- { name: 'chat', match: { scope: ['mcpl:channel-incoming'] }, behavior: { debounce: 100 } },
338
- ],
339
- default: 'skip',
340
- });
341
- const { gate, inferenceRequests } = makeGate(path);
342
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:alice-room', content: 'hey agent',
343
- tags: ['chat:addressed'], metadata: { author: { id: '111' } } }));
344
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:bob-room', content: 'ambient',
345
- metadata: { authorId: '222' } }));
346
- await new Promise(r => setTimeout(r, 150));
347
- assert.strictEqual(inferenceRequests.length, 1);
348
- assert.strictEqual(inferenceRequests[0].channelId, 'discord:g:alice-room');
349
- assert.strictEqual(inferenceRequests[0].counterparty, 'discord:user:111');
350
- assert.strictEqual(inferenceRequests[0].addressed, true);
351
- });
352
- it('the counterparty is namespaced by the event\'s server id, not the channel id\'s first segment', async () => {
353
- const path = writeConfig('debounce-namespace.json', {
354
- policies: [
355
- { name: 'chat', match: { scope: ['mcpl:channel-incoming'] }, behavior: { debounce: 100 } },
356
- ],
357
- default: 'skip',
358
- });
359
- const { gate, inferenceRequests } = makeGate(path);
360
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'beta', channelId: 'shared', content: 'x',
361
- metadata: { authorId: '42' } }));
362
- await new Promise(r => setTimeout(r, 150));
363
- assert.strictEqual(inferenceRequests[0].channelId, 'shared');
364
- assert.strictEqual(inferenceRequests[0].counterparty, 'beta:user:42');
365
- assert.ok(typeof inferenceRequests[0].at === 'number', 'provenance carries the chosen event\'s timestamp');
366
- });
367
- it('a push-event wake (raw adapter channel id) names its author but reports no channel', async () => {
368
- const path = writeConfig('debounce-push-raw.json', {
369
- policies: [
370
- { name: 'all', match: { scope: ['mcpl:push-event', 'mcpl:channel-incoming'] }, behavior: { debounce: 100 } },
371
- ],
372
- default: 'skip',
373
- });
374
- const { gate, inferenceRequests } = makeGate(path);
375
- // exactly what PushHandler builds for a discord-mcpl DM push event
376
- gate.evaluate(event({ eventType: 'mcpl:push-event', serverId: 'discord', channelId: '123456789012345678', content: 'hi',
377
- tags: ['chat:dm', 'chat:addressed', 'chat:private'], metadata: { authorId: '42', channelId: '123456789012345678' } }));
378
- await new Promise(r => setTimeout(r, 150));
379
- assert.strictEqual(inferenceRequests.length, 1);
380
- assert.strictEqual(inferenceRequests[0].channelId, undefined, 'a raw snowflake is not a composite channel id — not reported');
381
- assert.strictEqual(inferenceRequests[0].counterparty, 'discord:user:42');
382
- assert.strictEqual(inferenceRequests[0].addressed, true);
383
- });
384
- it('an addressed batch names its registered route channel; ambient-only batches name none', async () => {
385
- const path = writeConfig('debounce-route.json', {
386
- policies: [
387
- { name: 'chat', match: { scope: ['mcpl:channel-incoming', 'mcpl:push-event'] }, behavior: { debounce: 100 } },
388
- ],
389
- default: 'skip',
390
- });
391
- // The host maps a push origin to its registered composite id.
392
- const resolveRouteChannel = (info) => info.eventType === 'mcpl:push-event' ? `discord:dm:${String(info.metadata?.channelId)}` : info.channelId;
393
- const { gate, inferenceRequests, messages } = makeGate(path, { resolveRouteChannel });
394
- // DM (addressed, raw id) then newer ambient chatter elsewhere.
395
- gate.evaluate(event({ eventType: 'mcpl:push-event', serverId: 'discord', channelId: '1548', content: 'dm',
396
- tags: ['chat:dm', 'chat:addressed'], metadata: { authorId: '42', channelId: '1548' } }));
397
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:general', content: 'chatter',
398
- metadata: { authorId: '7' } }));
399
- await new Promise(r => setTimeout(r, 150));
400
- assert.strictEqual(inferenceRequests.length, 1);
401
- assert.strictEqual(inferenceRequests[0].routeChannelId, 'discord:dm:1548', 'the addressed event names the route');
402
- assert.strictEqual(inferenceRequests[0].counterparty, 'discord:user:42', 'route and author come from the same event');
403
- assert.strictEqual(inferenceRequests[0].channelId, undefined, 'telemetry channel unchanged for push events');
404
- // The batched-wake line names the registered id, not the raw snowflake.
405
- const text = JSON.stringify(messages.at(-1)?.content);
406
- assert.ok(text.includes('discord:dm:1548'), 'gate line shows the registered channel id');
407
- // Ambient-only batch: telemetry provenance, no route.
408
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:room', content: 'x',
409
- metadata: { authorId: '8' } }));
410
- await new Promise(r => setTimeout(r, 150));
411
- assert.strictEqual(inferenceRequests.length, 2);
412
- assert.strictEqual(inferenceRequests[1].channelId, 'discord:g:room');
413
- assert.strictEqual(inferenceRequests[1].routeChannelId, undefined, 'ambient chatter never sets a route');
414
- });
415
- it('the default resolver routes an addressed channel-incoming event; a push event needs the host resolver', async () => {
416
- const path = writeConfig('debounce-route-default.json', {
417
- policies: [
418
- { name: 'chat', match: { scope: ['mcpl:channel-incoming', 'mcpl:push-event'] }, behavior: { debounce: 100 } },
419
- ],
420
- default: 'skip',
421
- });
422
- const { gate, inferenceRequests } = makeGate(path);
423
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:room', content: '@agent hi',
424
- tags: ['chat:addressed'], metadata: { authorId: '1' } }));
425
- await new Promise(r => setTimeout(r, 150));
426
- assert.strictEqual(inferenceRequests[0].routeChannelId, 'discord:g:room');
427
- gate.evaluate(event({ eventType: 'mcpl:push-event', serverId: 'discord', channelId: '1548', content: 'dm',
428
- tags: ['chat:dm', 'chat:addressed'], metadata: { authorId: '42', channelId: '1548' } }));
429
- await new Promise(r => setTimeout(r, 150));
430
- assert.strictEqual(inferenceRequests[1].routeChannelId, undefined, 'a raw id is never used as a route');
431
- });
432
- it('the newest addressed event decides the route even when it has none (no guessing an older one)', async () => {
433
- const path = writeConfig('debounce-route-newest.json', {
434
- policies: [
435
- { name: 'chat', match: { scope: ['mcpl:channel-incoming', 'mcpl:push-event'] }, behavior: { debounce: 100 } },
436
- ],
437
- default: 'skip',
438
- });
439
- const { gate, inferenceRequests } = makeGate(path); // default resolver: push → no route
440
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:room', content: '@agent first',
441
- tags: ['chat:addressed'], metadata: { authorId: '1' } }));
442
- gate.evaluate(event({ eventType: 'mcpl:push-event', serverId: 'discord', channelId: '1548', content: 'dm later',
443
- tags: ['chat:dm', 'chat:addressed'], metadata: { authorId: '42', channelId: '1548' } }));
444
- await new Promise(r => setTimeout(r, 150));
445
- assert.strictEqual(inferenceRequests[0].counterparty, 'discord:user:42');
446
- assert.strictEqual(inferenceRequests[0].routeChannelId, undefined, 'the DM is the newest addressed event; replying to the older mention would answer the wrong person');
447
- });
448
- it('an addressed push that names only its registered channel (no raw id, no author) still routes', async () => {
449
- const path = writeConfig('debounce-route-only.json', {
450
- policies: [
451
- { name: 'chat', match: { scope: ['mcpl:channel-incoming', 'mcpl:push-event'] }, behavior: { debounce: 100 } },
452
- ],
453
- default: 'skip',
454
- });
455
- const resolveRouteChannel = (info) => typeof info.metadata?.mcplChannelId === 'string' ? info.metadata.mcplChannelId : undefined;
456
- const { gate, inferenceRequests } = makeGate(path, { resolveRouteChannel });
457
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'surface', channelId: 'surface:room:general',
458
- content: 'chatter', metadata: { authorId: '7' } }));
459
- gate.evaluate(event({ eventType: 'mcpl:push-event', serverId: 'surface', content: 'dm',
460
- tags: ['chat:dm', 'chat:addressed'], metadata: { mcplChannelId: 'surface:dm:42' } }));
461
- await new Promise(r => setTimeout(r, 150));
462
- assert.strictEqual(inferenceRequests.length, 1);
463
- assert.strictEqual(inferenceRequests[0].routeChannelId, 'surface:dm:42');
464
- assert.strictEqual(inferenceRequests[0].addressed, true);
465
- assert.strictEqual(inferenceRequests[0].counterparty, undefined, 'no author on the chosen event, none borrowed from the chatter');
466
- });
467
- it('a newer AMBIENT route-only push does not hide an earlier event\'s channel and author', async () => {
468
- const path = writeConfig('debounce-route-only-ambient.json', {
469
- policies: [
470
- { name: 'chat', match: { scope: ['mcpl:channel-incoming', 'mcpl:push-event'] }, behavior: { debounce: 100 } },
471
- ],
472
- default: 'skip',
473
- });
474
- const resolveRouteChannel = (info) => typeof info.metadata?.mcplChannelId === 'string' ? info.metadata.mcplChannelId : info.channelId || undefined;
475
- const { gate, inferenceRequests } = makeGate(path, { resolveRouteChannel });
476
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'surface', channelId: 'surface:room:general',
477
- content: 'chatter', metadata: { authorId: '7' } }));
478
- gate.evaluate(event({ eventType: 'mcpl:push-event', serverId: 'surface', content: 'status ping',
479
- metadata: { mcplChannelId: 'surface:room:feed' } }));
480
- await new Promise(r => setTimeout(r, 150));
481
- assert.strictEqual(inferenceRequests.length, 1);
482
- assert.strictEqual(inferenceRequests[0].channelId, 'surface:room:general', 'telemetry keeps the attributable event');
483
- assert.strictEqual(inferenceRequests[0].counterparty, 'surface:user:7');
484
- assert.strictEqual(inferenceRequests[0].routeChannelId, undefined, 'ambient batches never route');
485
- });
486
- it('a throwing route resolver never breaks gating', async () => {
487
- const path = writeConfig('debounce-route-throw.json', {
488
- policies: [
489
- { name: 'chat', match: { scope: ['mcpl:channel-incoming'] }, behavior: { debounce: 100 } },
490
- ],
491
- default: 'skip',
492
- });
493
- const { gate, inferenceRequests } = makeGate(path, { resolveRouteChannel: () => { throw new Error('boom'); } });
494
- const decision = gate.evaluate(event({ eventType: 'mcpl:channel-incoming', serverId: 'discord', channelId: 'discord:g:room',
495
- content: '@agent hi', tags: ['chat:addressed'] }));
496
- assert.strictEqual(decision.policyName, 'chat');
497
- await new Promise(r => setTimeout(r, 150));
498
- assert.strictEqual(inferenceRequests.length, 1);
499
- assert.strictEqual(inferenceRequests[0].routeChannelId, undefined);
500
- });
501
- it('a batched wake with no channel-bearing event carries no provenance', async () => {
502
- const path = writeConfig('debounce-noprov.json', {
503
- policies: [
504
- { name: 'editor', match: { scope: ['mcpl:push-event'] }, behavior: { debounce: 100 } },
505
- ],
506
- default: 'skip',
507
- });
508
- const { gate, inferenceRequests } = makeGate(path);
509
- gate.evaluate(event({ content: 'edit' }));
510
- await new Promise(r => setTimeout(r, 150));
511
- assert.strictEqual(inferenceRequests.length, 1);
512
- assert.strictEqual(inferenceRequests[0].channelId, undefined);
513
- assert.strictEqual(inferenceRequests[0].counterparty, undefined);
514
- });
515
- it('quotes content for non-MCPL events (no context entry of their own)', async () => {
516
- const path = writeConfig('debounce-quote.json', {
517
- policies: [
518
- { name: 'editor', match: { scope: ['module:custom'] }, behavior: { debounce: 150 } },
519
- ],
520
- default: 'skip',
521
- });
522
- const { gate, messages } = makeGate(path);
523
- gate.evaluate(event({ content: 'compile finished', eventType: 'module:custom' }));
524
- await new Promise(r => setTimeout(r, 200));
525
- assert.strictEqual(messages.length, 1);
526
- const text = messages[0].content[0].text;
527
- assert.ok(text.includes('[editor]'));
528
- assert.ok(text.includes('compile finished'), 'non-MCPL events carry their content');
529
- });
530
- it('resets timer on new events', async () => {
531
- const path = writeConfig('debounce-reset.json', {
532
- policies: [
533
- { name: 'editor', match: {}, behavior: { debounce: 150 } },
534
- ],
535
- default: 'skip',
536
- });
537
- const { gate, messages } = makeGate(path);
538
- gate.evaluate(event({ content: 'edit 1' }));
539
- await new Promise(r => setTimeout(r, 80));
540
- // Timer hasn't fired yet, send another
541
- gate.evaluate(event({ content: 'edit 2' }));
542
- await new Promise(r => setTimeout(r, 80));
543
- // Still within debounce window of second event
544
- assert.strictEqual(messages.length, 0);
545
- await new Promise(r => setTimeout(r, 100));
546
- // Now it should have fired
547
- assert.strictEqual(messages.length, 1);
548
- });
549
- });
550
- // ---------------------------------------------------------------------------
551
- // Debounce bounds validation
552
- // ---------------------------------------------------------------------------
553
- describe('debounce bounds', () => {
554
- it('rejects debounce < 100ms', () => {
555
- const path = tmpPath('low-debounce.json');
556
- mkdirSync(TMP_DIR, { recursive: true });
557
- writeFileSync(path, JSON.stringify({
558
- policies: [{ name: 'fast', match: {}, behavior: { debounce: 50 } }],
559
- default: 'always',
560
- }));
561
- const { gate, traces } = makeGate(path);
562
- // Should fall back to default config, emit error trace
563
- assert.strictEqual(gate.evaluate(event()).trigger, true);
564
- assert.ok(traces.some(t => t.type === 'gate:config-error'));
565
- });
566
- it('rejects debounce > 300000ms', () => {
567
- const path = tmpPath('high-debounce.json');
568
- mkdirSync(TMP_DIR, { recursive: true });
569
- writeFileSync(path, JSON.stringify({
570
- policies: [{ name: 'slow', match: {}, behavior: { debounce: 500000 } }],
571
- default: 'always',
572
- }));
573
- const { gate, traces } = makeGate(path);
574
- assert.strictEqual(gate.evaluate(event()).trigger, true);
575
- assert.ok(traces.some(t => t.type === 'gate:config-error'));
576
- });
577
- });
578
- // ---------------------------------------------------------------------------
579
- // Inference buffering
580
- // ---------------------------------------------------------------------------
581
- describe('inference buffering', () => {
582
- it('inference buffer is capped at MAX_INFERENCE_BUFFER', async () => {
583
- const path = writeConfig('infer-cap.json', {
584
- policies: [
585
- { name: 'chat', match: {}, behavior: { debounce: 100 } },
586
- ],
587
- default: 'skip',
588
- });
589
- const { gate, messages } = makeGate(path);
590
- gate.onInferenceStarted('agent');
591
- // Fire many debounce batches — each with 20 events, 6 batches = 120 events
592
- for (let batch = 0; batch < 6; batch++) {
593
- for (let i = 0; i < 20; i++) {
594
- gate.evaluate(event({ content: `batch${batch}-msg${i}` }));
595
- }
596
- // Let debounce fire (into inference buffer since inferring)
597
- await new Promise(r => setTimeout(r, 150));
598
- }
599
- // Buffer should be capped at 100 (oldest dropped)
600
- const bufferLen = gate.inferenceBuffer.length;
601
- assert.ok(bufferLen <= 100, `Expected buffer <= 100, got ${bufferLen}`);
602
- assert.ok(bufferLen > 0, 'Expected buffer to have events');
603
- // First event should NOT be from batch 0 (those were dropped)
604
- const firstEvent = gate.inferenceBuffer[0];
605
- assert.ok(!firstEvent.content.startsWith('batch0'), `Expected oldest events dropped, but first is ${firstEvent.content}`);
606
- // End inference → flush
607
- gate.onInferenceEnded('agent');
608
- await new Promise(r => setTimeout(r, 10));
609
- assert.strictEqual(messages.length, 1);
610
- gate.dispose();
611
- });
612
- it('debounce during inference → buffer → flush on end', async () => {
613
- const path = writeConfig('infer-debounce.json', {
614
- policies: [
615
- { name: 'chat', match: {}, behavior: { debounce: 150 } },
616
- ],
617
- default: 'skip',
618
- });
619
- const { gate, messages } = makeGate(path);
620
- gate.evaluate(event({ content: 'msg 1' }));
621
- gate.evaluate(event({ content: 'msg 2' }));
622
- // Simulate inference started before debounce fires
623
- gate.onInferenceStarted('agent');
624
- // Wait for debounce timer to fire
625
- await new Promise(r => setTimeout(r, 200));
626
- // Should be buffered, not delivered (inference is active)
627
- assert.strictEqual(messages.length, 0);
628
- // End inference → flush
629
- gate.onInferenceEnded('agent');
630
- // queueMicrotask defers delivery
631
- await new Promise(r => setTimeout(r, 10));
632
- assert.strictEqual(messages.length, 1);
633
- });
634
- });
635
- // ---------------------------------------------------------------------------
636
- // Config hot-reload
637
- // ---------------------------------------------------------------------------
638
- describe('config hot-reload', () => {
639
- it('reloads config when file changes', async () => {
640
- const path = writeConfig('reload.json', {
641
- policies: [{ name: 'all', match: {}, behavior: 'always' }],
642
- default: 'skip',
643
- });
644
- const { gate } = makeGate(path);
645
- assert.strictEqual(gate.evaluate(event()).trigger, true);
646
- // Force throttle to expire
647
- gate.lastReloadCheck = 0;
648
- // Wait for mtime to differ
649
- await new Promise(r => setTimeout(r, 50));
650
- // Rewrite config — now skip everything
651
- writeFileSync(path, JSON.stringify({ policies: [], default: 'skip' }));
652
- assert.strictEqual(gate.evaluate(event()).trigger, false);
653
- });
654
- it('config error keeps previous valid config', async () => {
655
- const path = writeConfig('error-reload.json', {
656
- policies: [{ name: 'all', match: {}, behavior: 'always' }],
657
- default: 'skip',
658
- });
659
- const { gate, traces } = makeGate(path);
660
- assert.strictEqual(gate.evaluate(event()).trigger, true);
661
- // Force throttle to expire
662
- gate.lastReloadCheck = 0;
663
- await new Promise(r => setTimeout(r, 50));
664
- // Write invalid JSON
665
- writeFileSync(path, 'not valid json{{{');
666
- // Should still use previous config
667
- assert.strictEqual(gate.evaluate(event()).trigger, true);
668
- assert.ok(traces.some(t => t.type === 'gate:config-error'));
669
- });
670
- });
671
- // ---------------------------------------------------------------------------
672
- // Config seeding
673
- // ---------------------------------------------------------------------------
674
- describe('config seeding', () => {
675
- it('seeds config file from initialConfig when file does not exist', () => {
676
- const path = tmpPath('seeded.json');
677
- const config = {
678
- policies: [{ name: 'test', match: {}, behavior: 'always' }],
679
- default: 'skip',
680
- };
681
- makeGate(path, { initialConfig: config });
682
- assert.ok(existsSync(path));
683
- const written = JSON.parse(readFileSync(path, 'utf-8'));
684
- assert.strictEqual(written.policies[0].name, 'test');
685
- });
686
- it('does not overwrite existing file', () => {
687
- const path = writeConfig('existing.json', {
688
- policies: [{ name: 'original', match: {}, behavior: 'always' }],
689
- default: 'always',
690
- });
691
- makeGate(path, {
692
- initialConfig: {
693
- policies: [{ name: 'new', match: {}, behavior: 'skip' }],
694
- default: 'skip',
695
- },
696
- });
697
- const written = JSON.parse(readFileSync(path, 'utf-8'));
698
- assert.strictEqual(written.policies[0].name, 'original');
699
- });
700
- });
701
- // ---------------------------------------------------------------------------
702
- // gate:status tool
703
- // ---------------------------------------------------------------------------
704
- describe('gate:status tool', () => {
705
- it('returns correct status structure', async () => {
706
- const path = writeConfig('status.json', {
707
- policies: [
708
- { name: 'always-policy', match: {}, behavior: 'always' },
709
- { name: 'debounce-policy', match: { scope: ['mcpl:push-event'] }, behavior: { debounce: 1000 } },
710
- ],
711
- default: 'skip',
712
- });
713
- const { gate } = makeGate(path);
714
- // Trigger some matches
715
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming' }));
716
- gate.evaluate(event({ eventType: 'mcpl:channel-incoming' }));
717
- const result = await gate.handleToolCall();
718
- assert.strictEqual(result.success, true);
719
- const status = result.data;
720
- assert.strictEqual(status.configPath, path);
721
- assert.strictEqual(status.configSource, 'file');
722
- assert.strictEqual(status.default, 'skip');
723
- assert.strictEqual(status.policies.length, 2);
724
- assert.strictEqual(status.policies[0].name, 'always-policy');
725
- assert.strictEqual(status.policies[0].matchCount, 2);
726
- assert.strictEqual(status.errors.length, 0);
727
- });
728
- });
729
- // ---------------------------------------------------------------------------
730
- // asShouldTriggerCallback
731
- // ---------------------------------------------------------------------------
732
- describe('asShouldTriggerCallback', () => {
733
- it('returns a function with the shouldTriggerInference signature', () => {
734
- const path = writeConfig('callback.json', {
735
- policies: [
736
- { name: 'allow-zulip', match: { source: 'zulip' }, behavior: 'always' },
737
- ],
738
- default: 'skip',
739
- });
740
- const { gate } = makeGate(path);
741
- const cb = gate.asShouldTriggerCallback();
742
- assert.strictEqual(typeof cb, 'function');
743
- assert.strictEqual(cb('hello', { eventType: 'mcpl:push-event', serverId: 'zulip' }), true);
744
- assert.strictEqual(cb('hello', { eventType: 'mcpl:push-event', serverId: 'discord' }), false);
745
- });
746
- });
747
- // ---------------------------------------------------------------------------
748
- // Trace events
749
- // ---------------------------------------------------------------------------
750
- describe('trace events', () => {
751
- it('emits gate:policy-matched on match', () => {
752
- const path = writeConfig('trace-match.json', {
753
- policies: [{ name: 'test', match: {}, behavior: 'always' }],
754
- default: 'skip',
755
- });
756
- const { gate, traces } = makeGate(path);
757
- gate.evaluate(event());
758
- const matchTraces = traces.filter(t => t.type === 'gate:policy-matched');
759
- assert.strictEqual(matchTraces.length, 1);
760
- assert.strictEqual(matchTraces[0].policyName, 'test');
761
- });
762
- it('emits gate:config-reloaded on successful reload', async () => {
763
- const path = writeConfig('trace-reload.json', {
764
- policies: [],
765
- default: 'always',
766
- });
767
- const { gate, traces } = makeGate(path);
768
- gate.evaluate(event()); // initial eval
769
- gate.lastReloadCheck = 0;
770
- await new Promise(r => setTimeout(r, 50));
771
- writeFileSync(path, JSON.stringify({ policies: [{ name: 'new', match: {}, behavior: 'skip' }], default: 'always' }));
772
- gate.evaluate(event());
773
- assert.ok(traces.some(t => t.type === 'gate:config-reloaded'));
774
- });
775
- });
776
- // ---------------------------------------------------------------------------
777
- // Cleanup
778
- // ---------------------------------------------------------------------------
779
- describe('dispose', () => {
780
- it('clears debounce timers without delivering', () => {
781
- const path = writeConfig('dispose.json', {
782
- policies: [{ name: 'debounced', match: {}, behavior: { debounce: 10000 } }],
783
- default: 'skip',
784
- });
785
- const { gate, messages } = makeGate(path);
786
- gate.evaluate(event());
787
- gate.dispose();
788
- // No delivery should happen
789
- assert.strictEqual(messages.length, 0);
790
- });
791
- });
792
- // ---------------------------------------------------------------------------
793
- // Policy reconciliation on restart (postmortem: clerk stuck on old policies)
794
- // ---------------------------------------------------------------------------
795
- describe('policy reconciliation', () => {
796
- it('appends missing-by-name policies from initialConfig when gate.json already exists', () => {
797
- // Simulate a prior session that seeded gate.json with 2 policies
798
- const path = writeConfig('reconcile-add.json', {
799
- default: 'skip',
800
- policies: [
801
- { name: 'user-input', match: { scope: ['external-message'] }, behavior: 'always' },
802
- { name: 'subagent-completions', match: { scope: ['inference-request'] }, behavior: 'always' },
803
- ],
804
- });
805
- // New session starts with a recipe that added a third policy
806
- const { gate, traces } = makeGate(path, {
807
- initialConfig: {
808
- default: 'skip',
809
- policies: [
810
- { name: 'user-input', match: { scope: ['external-message'] }, behavior: 'always' },
811
- { name: 'subagent-completions', match: { scope: ['inference-request'] }, behavior: 'always' },
812
- { name: 'reviewed-responses', match: { scope: ['workspace:created'] }, behavior: 'always' },
813
- ],
814
- },
815
- });
816
- // gate.json on disk should now contain all three policies
817
- const onDisk = JSON.parse(readFileSync(path, 'utf-8'));
818
- assert.strictEqual(onDisk.policies.length, 3);
819
- assert.ok(onDisk.policies.some((p) => p.name === 'reviewed-responses'));
820
- // Reconciliation trace emitted
821
- assert.ok(traces.some(t => t.type === 'gate:config-reconciled'));
822
- // Live gate honors the new policy
823
- assert.strictEqual(gate.evaluate(event({ eventType: 'workspace:created' })).trigger, true);
824
- });
825
- it("leaves existing policies alone — user's workspace--edit survives recipe changes", () => {
826
- const path = writeConfig('reconcile-preserve.json', {
827
- default: 'skip',
828
- policies: [
829
- {
830
- name: 'user-input',
831
- // User edited this policy to also filter on content
832
- match: { scope: ['external-message'], filter: { type: 'text', pattern: 'urgent' } },
833
- behavior: 'always',
834
- },
835
- ],
836
- });
837
- makeGate(path, {
838
- initialConfig: {
839
- default: 'skip',
840
- policies: [
841
- // Recipe declares it without the filter
842
- { name: 'user-input', match: { scope: ['external-message'] }, behavior: 'always' },
843
- ],
844
- },
845
- });
846
- const onDisk = JSON.parse(readFileSync(path, 'utf-8'));
847
- assert.strictEqual(onDisk.policies.length, 1);
848
- assert.deepStrictEqual(onDisk.policies[0].match.filter, { type: 'text', pattern: 'urgent' });
849
- });
850
- });
851
- // ---------------------------------------------------------------------------
852
- // Observability: defaultDecisions counts help diagnose silent drops
853
- // ---------------------------------------------------------------------------
854
- describe('defaultDecisions counters', () => {
855
- it('counts events that fell through to default (by eventType)', () => {
856
- const path = writeConfig('default-counts.json', {
857
- default: 'skip',
858
- policies: [
859
- { name: 'user-input', match: { scope: ['external-message'] }, behavior: 'always' },
860
- ],
861
- });
862
- const { gate } = makeGate(path);
863
- gate.evaluate(event({ eventType: 'external-message' })); // matches
864
- gate.evaluate(event({ eventType: 'workspace:created' })); // default skip
865
- gate.evaluate(event({ eventType: 'workspace:created' })); // default skip
866
- gate.evaluate(event({ eventType: 'other' })); // default skip
867
- const status = gate.getStatus();
868
- assert.strictEqual(status.totalEvaluations, 4);
869
- assert.strictEqual(status.defaultDecisions.skipped, 3);
870
- assert.strictEqual(status.defaultDecisions.triggered, 0);
871
- assert.strictEqual(status.defaultDecisions.byEventType['workspace:created'].skipped, 2);
872
- assert.strictEqual(status.defaultDecisions.byEventType['other'].skipped, 1);
873
- });
874
- });
875
- // ---------------------------------------------------------------------------
876
- // Host quiesce suppression (issue #122)
877
- // ---------------------------------------------------------------------------
878
- describe('quiesce suppression', () => {
879
- it('buffers debounce firings while quiesced and flushes on setQuiesced(false)', async () => {
880
- const path = writeConfig('quiesce-debounce.json', {
881
- policies: [
882
- { name: 'editor', match: { scope: ['mcpl:push-event'] }, behavior: { debounce: 120 } },
883
- ],
884
- default: 'skip',
885
- });
886
- const { gate, messages, inferenceRequests } = makeGate(path);
887
- gate.setQuiesced(true);
888
- gate.evaluate(event({ content: 'edit 1' }));
889
- gate.evaluate(event({ content: 'edit 2' }));
890
- // Debounce fires while quiesced → buffered, no context write, no wake.
891
- await new Promise(r => setTimeout(r, 250));
892
- assert.strictEqual(messages.length, 0, 'no gate message mid-surgery');
893
- assert.strictEqual(inferenceRequests.length, 0);
894
- assert.strictEqual(gate.inferenceDiagnostics().bufferedEvents, 2);
895
- gate.setQuiesced(false);
896
- await new Promise(r => setTimeout(r, 20)); // flush is deferred a microtask
897
- assert.strictEqual(messages.length, 1, 'buffered events compose one delivery');
898
- assert.strictEqual(inferenceRequests.length, 1);
899
- assert.strictEqual(gate.inferenceDiagnostics().bufferedEvents, 0);
900
- });
901
- it('a turn ending while quiesced does not flush the buffer', async () => {
902
- const path = writeConfig('quiesce-turn-end.json', {
903
- policies: [
904
- { name: 'editor', match: { scope: ['mcpl:push-event'] }, behavior: { debounce: 120 } },
905
- ],
906
- default: 'skip',
907
- });
908
- const { gate, messages } = makeGate(path);
909
- gate.setQuiesced(true);
910
- gate.onInferenceStarted('agent');
911
- gate.evaluate(event({ content: 'during drain' }));
912
- await new Promise(r => setTimeout(r, 250));
913
- gate.onInferenceEnded('agent'); // drain completes mid-quiesce
914
- await new Promise(r => setTimeout(r, 20));
915
- assert.strictEqual(messages.length, 0, 'buffer holds until resume, not turn end');
916
- assert.strictEqual(gate.inferenceDiagnostics().bufferedEvents, 1);
917
- });
918
- });
919
- //# sourceMappingURL=event-gate.test.js.map