@animalabs/agent-framework 0.26.2 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/README.md +99 -8
  2. package/dist/src/agent.d.ts +291 -23
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +596 -61
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/server.d.ts.map +1 -1
  7. package/dist/src/api/server.js +5 -4
  8. package/dist/src/api/server.js.map +1 -1
  9. package/dist/src/auto-continue.d.ts +34 -0
  10. package/dist/src/auto-continue.d.ts.map +1 -0
  11. package/dist/src/auto-continue.js +36 -0
  12. package/dist/src/auto-continue.js.map +1 -0
  13. package/dist/src/code-execution/isolate/scripts.d.ts +11 -0
  14. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
  15. package/dist/src/code-execution/isolate/scripts.js +5 -1
  16. package/dist/src/code-execution/isolate/scripts.js.map +1 -1
  17. package/dist/src/cut-off-round.d.ts +24 -0
  18. package/dist/src/cut-off-round.d.ts.map +1 -0
  19. package/dist/src/cut-off-round.js +87 -0
  20. package/dist/src/cut-off-round.js.map +1 -0
  21. package/dist/src/framework.d.ts +1038 -193
  22. package/dist/src/framework.d.ts.map +1 -1
  23. package/dist/src/framework.js +5967 -1514
  24. package/dist/src/framework.js.map +1 -1
  25. package/dist/src/gate/event-gate.d.ts +405 -46
  26. package/dist/src/gate/event-gate.d.ts.map +1 -1
  27. package/dist/src/gate/event-gate.js +2646 -399
  28. package/dist/src/gate/event-gate.js.map +1 -1
  29. package/dist/src/gate/index.d.ts +3 -2
  30. package/dist/src/gate/index.d.ts.map +1 -1
  31. package/dist/src/gate/index.js +2 -1
  32. package/dist/src/gate/index.js.map +1 -1
  33. package/dist/src/gate/recipe-reconcile.d.ts +103 -0
  34. package/dist/src/gate/recipe-reconcile.d.ts.map +1 -0
  35. package/dist/src/gate/recipe-reconcile.js +325 -0
  36. package/dist/src/gate/recipe-reconcile.js.map +1 -0
  37. package/dist/src/gate/reply-judge.d.ts +116 -0
  38. package/dist/src/gate/reply-judge.d.ts.map +1 -0
  39. package/dist/src/gate/reply-judge.js +467 -0
  40. package/dist/src/gate/reply-judge.js.map +1 -0
  41. package/dist/src/gate/types.d.ts +229 -8
  42. package/dist/src/gate/types.d.ts.map +1 -1
  43. package/dist/src/heartbeat/heartbeat.d.ts +184 -0
  44. package/dist/src/heartbeat/heartbeat.d.ts.map +1 -0
  45. package/dist/src/heartbeat/heartbeat.js +752 -0
  46. package/dist/src/heartbeat/heartbeat.js.map +1 -0
  47. package/dist/src/heartbeat/reminder-time.d.ts +5 -0
  48. package/dist/src/heartbeat/reminder-time.d.ts.map +1 -0
  49. package/dist/src/heartbeat/reminder-time.js +107 -0
  50. package/dist/src/heartbeat/reminder-time.js.map +1 -0
  51. package/dist/src/index.d.ts +10 -4
  52. package/dist/src/index.d.ts.map +1 -1
  53. package/dist/src/index.js +7 -2
  54. package/dist/src/index.js.map +1 -1
  55. package/dist/src/mcpl/capability-mask.d.ts.map +1 -1
  56. package/dist/src/mcpl/capability-mask.js +3 -2
  57. package/dist/src/mcpl/capability-mask.js.map +1 -1
  58. package/dist/src/mcpl/channel-registry.d.ts +433 -113
  59. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  60. package/dist/src/mcpl/channel-registry.js +1154 -435
  61. package/dist/src/mcpl/channel-registry.js.map +1 -1
  62. package/dist/src/mcpl/conversation-router.d.ts +16 -8
  63. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  64. package/dist/src/mcpl/conversation-router.js +29 -15
  65. package/dist/src/mcpl/conversation-router.js.map +1 -1
  66. package/dist/src/mcpl/convert-block.d.ts.map +1 -1
  67. package/dist/src/mcpl/convert-block.js +14 -2
  68. package/dist/src/mcpl/convert-block.js.map +1 -1
  69. package/dist/src/mcpl/hook-orchestrator.d.ts +7 -1
  70. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  71. package/dist/src/mcpl/hook-orchestrator.js +32 -7
  72. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  73. package/dist/src/mcpl/inbound-source.d.ts +26 -10
  74. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  75. package/dist/src/mcpl/inbound-source.js +40 -69
  76. package/dist/src/mcpl/inbound-source.js.map +1 -1
  77. package/dist/src/mcpl/index.d.ts +5 -1
  78. package/dist/src/mcpl/index.d.ts.map +1 -1
  79. package/dist/src/mcpl/index.js +4 -0
  80. package/dist/src/mcpl/index.js.map +1 -1
  81. package/dist/src/mcpl/inference-router.d.ts +14 -2
  82. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  83. package/dist/src/mcpl/inference-router.js +73 -28
  84. package/dist/src/mcpl/inference-router.js.map +1 -1
  85. package/dist/src/mcpl/prose-grammar.d.ts +4 -0
  86. package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
  87. package/dist/src/mcpl/prose-grammar.js +6 -0
  88. package/dist/src/mcpl/prose-grammar.js.map +1 -1
  89. package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
  90. package/dist/src/mcpl/protocol-family.js +3 -0
  91. package/dist/src/mcpl/protocol-family.js.map +1 -1
  92. package/dist/src/mcpl/push-coalescer.d.ts +20 -2
  93. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  94. package/dist/src/mcpl/push-coalescer.js +33 -11
  95. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  96. package/dist/src/mcpl/reference-fetcher.d.ts +63 -42
  97. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  98. package/dist/src/mcpl/reference-fetcher.js +177 -145
  99. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  100. package/dist/src/mcpl/references.d.ts +380 -46
  101. package/dist/src/mcpl/references.d.ts.map +1 -1
  102. package/dist/src/mcpl/references.js +736 -77
  103. package/dist/src/mcpl/references.js.map +1 -1
  104. package/dist/src/mcpl/server-connection.d.ts +93 -4
  105. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  106. package/dist/src/mcpl/server-connection.js +176 -11
  107. package/dist/src/mcpl/server-connection.js.map +1 -1
  108. package/dist/src/mcpl/tags.d.ts +9 -2
  109. package/dist/src/mcpl/tags.d.ts.map +1 -1
  110. package/dist/src/mcpl/tags.js +12 -2
  111. package/dist/src/mcpl/tags.js.map +1 -1
  112. package/dist/src/mcpl/tool-lifecycle.d.ts +11 -0
  113. package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
  114. package/dist/src/mcpl/tool-lifecycle.js +21 -0
  115. package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
  116. package/dist/src/mcpl/tool-presence.d.ts +311 -0
  117. package/dist/src/mcpl/tool-presence.d.ts.map +1 -0
  118. package/dist/src/mcpl/tool-presence.js +697 -0
  119. package/dist/src/mcpl/tool-presence.js.map +1 -0
  120. package/dist/src/mcpl/tool-result-normalize.d.ts +9 -3
  121. package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
  122. package/dist/src/mcpl/tool-result-normalize.js +14 -6
  123. package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
  124. package/dist/src/mcpl/tool-signature.d.ts +46 -0
  125. package/dist/src/mcpl/tool-signature.d.ts.map +1 -0
  126. package/dist/src/mcpl/tool-signature.js +321 -0
  127. package/dist/src/mcpl/tool-signature.js.map +1 -0
  128. package/dist/src/mcpl/toolset-host.d.ts +251 -0
  129. package/dist/src/mcpl/toolset-host.d.ts.map +1 -0
  130. package/dist/src/mcpl/toolset-host.js +720 -0
  131. package/dist/src/mcpl/toolset-host.js.map +1 -0
  132. package/dist/src/mcpl/toolsets-module.d.ts +83 -0
  133. package/dist/src/mcpl/toolsets-module.d.ts.map +1 -0
  134. package/dist/src/mcpl/toolsets-module.js +523 -0
  135. package/dist/src/mcpl/toolsets-module.js.map +1 -0
  136. package/dist/src/mcpl/transport.d.ts +2 -2
  137. package/dist/src/mcpl/transport.d.ts.map +1 -1
  138. package/dist/src/mcpl/transport.js +3 -2
  139. package/dist/src/mcpl/transport.js.map +1 -1
  140. package/dist/src/mcpl/types.d.ts +24 -2
  141. package/dist/src/mcpl/types.d.ts.map +1 -1
  142. package/dist/src/mcpl/types.js.map +1 -1
  143. package/dist/src/mcpl/visible-content.d.ts +7 -9
  144. package/dist/src/mcpl/visible-content.d.ts.map +1 -1
  145. package/dist/src/mcpl/visible-content.js +21 -9
  146. package/dist/src/mcpl/visible-content.js.map +1 -1
  147. package/dist/src/module-registry.d.ts +27 -9
  148. package/dist/src/module-registry.d.ts.map +1 -1
  149. package/dist/src/module-registry.js +77 -17
  150. package/dist/src/module-registry.js.map +1 -1
  151. package/dist/src/modules/discord/index.js +1 -1
  152. package/dist/src/modules/discord/index.js.map +1 -1
  153. package/dist/src/modules/history/index.d.ts +2 -1
  154. package/dist/src/modules/history/index.d.ts.map +1 -1
  155. package/dist/src/modules/history/index.js +73 -28
  156. package/dist/src/modules/history/index.js.map +1 -1
  157. package/dist/src/modules/history/semantic.d.ts +108 -6
  158. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  159. package/dist/src/modules/history/semantic.js +273 -57
  160. package/dist/src/modules/history/semantic.js.map +1 -1
  161. package/dist/src/modules/workspace/answers.d.ts +22 -0
  162. package/dist/src/modules/workspace/answers.d.ts.map +1 -0
  163. package/dist/src/modules/workspace/answers.js +123 -0
  164. package/dist/src/modules/workspace/answers.js.map +1 -0
  165. package/dist/src/modules/workspace/branch-intent.d.ts +5 -3
  166. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  167. package/dist/src/modules/workspace/branch-intent.js +6 -2
  168. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  169. package/dist/src/modules/workspace/direct-write.d.ts +184 -0
  170. package/dist/src/modules/workspace/direct-write.d.ts.map +1 -0
  171. package/dist/src/modules/workspace/direct-write.js +417 -0
  172. package/dist/src/modules/workspace/direct-write.js.map +1 -0
  173. package/dist/src/modules/workspace/disk-agreement.d.ts +33 -11
  174. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  175. package/dist/src/modules/workspace/disk-agreement.js +48 -17
  176. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  177. package/dist/src/modules/workspace/edit-text.d.ts +27 -12
  178. package/dist/src/modules/workspace/edit-text.d.ts.map +1 -1
  179. package/dist/src/modules/workspace/edit-text.js +61 -29
  180. package/dist/src/modules/workspace/edit-text.js.map +1 -1
  181. package/dist/src/modules/workspace/effects.d.ts +10 -0
  182. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  183. package/dist/src/modules/workspace/effects.js +21 -14
  184. package/dist/src/modules/workspace/effects.js.map +1 -1
  185. package/dist/src/modules/workspace/index.d.ts +308 -78
  186. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  187. package/dist/src/modules/workspace/index.js +2103 -720
  188. package/dist/src/modules/workspace/index.js.map +1 -1
  189. package/dist/src/modules/workspace/observe.d.ts +75 -63
  190. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  191. package/dist/src/modules/workspace/observe.js +366 -180
  192. package/dist/src/modules/workspace/observe.js.map +1 -1
  193. package/dist/src/modules/workspace/read-page.d.ts +41 -0
  194. package/dist/src/modules/workspace/read-page.d.ts.map +1 -0
  195. package/dist/src/modules/workspace/read-page.js +219 -0
  196. package/dist/src/modules/workspace/read-page.js.map +1 -0
  197. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  198. package/dist/src/modules/workspace/reconcile.js +26 -16
  199. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  200. package/dist/src/modules/workspace/result-text.d.ts +68 -0
  201. package/dist/src/modules/workspace/result-text.d.ts.map +1 -0
  202. package/dist/src/modules/workspace/result-text.js +94 -0
  203. package/dist/src/modules/workspace/result-text.js.map +1 -0
  204. package/dist/src/modules/workspace/sync.d.ts +9 -0
  205. package/dist/src/modules/workspace/sync.d.ts.map +1 -1
  206. package/dist/src/modules/workspace/sync.js +14 -0
  207. package/dist/src/modules/workspace/sync.js.map +1 -1
  208. package/dist/src/modules/workspace/text.d.ts +29 -12
  209. package/dist/src/modules/workspace/text.d.ts.map +1 -1
  210. package/dist/src/modules/workspace/text.js +35 -33
  211. package/dist/src/modules/workspace/text.js.map +1 -1
  212. package/dist/src/modules/workspace/types.d.ts +137 -60
  213. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  214. package/dist/src/modules/workspace/types.js.map +1 -1
  215. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  216. package/dist/src/modules/workspace/watcher.js +8 -3
  217. package/dist/src/modules/workspace/watcher.js.map +1 -1
  218. package/dist/src/prose-drafts.d.ts +4 -3
  219. package/dist/src/prose-drafts.d.ts.map +1 -1
  220. package/dist/src/prose-drafts.js +3 -2
  221. package/dist/src/prose-drafts.js.map +1 -1
  222. package/dist/src/reasoning-loss-notice.d.ts +23 -0
  223. package/dist/src/reasoning-loss-notice.d.ts.map +1 -0
  224. package/dist/src/reasoning-loss-notice.js +50 -0
  225. package/dist/src/reasoning-loss-notice.js.map +1 -0
  226. package/dist/src/reasoning-loss.d.ts +24 -0
  227. package/dist/src/reasoning-loss.d.ts.map +1 -0
  228. package/dist/src/reasoning-loss.js +102 -0
  229. package/dist/src/reasoning-loss.js.map +1 -0
  230. package/dist/src/send-tools.d.ts +3 -2
  231. package/dist/src/send-tools.d.ts.map +1 -1
  232. package/dist/src/send-tools.js +3 -2
  233. package/dist/src/send-tools.js.map +1 -1
  234. package/dist/src/sent-rows.d.ts +59 -0
  235. package/dist/src/sent-rows.d.ts.map +1 -0
  236. package/dist/src/sent-rows.js +145 -0
  237. package/dist/src/sent-rows.js.map +1 -0
  238. package/dist/src/silent-heartbeat.d.ts +17 -10
  239. package/dist/src/silent-heartbeat.d.ts.map +1 -1
  240. package/dist/src/silent-heartbeat.js.map +1 -1
  241. package/dist/src/stable-hash.d.ts +3 -0
  242. package/dist/src/stable-hash.d.ts.map +1 -0
  243. package/dist/src/stable-hash.js +15 -0
  244. package/dist/src/stable-hash.js.map +1 -0
  245. package/dist/src/stored-injections.d.ts +99 -0
  246. package/dist/src/stored-injections.d.ts.map +1 -0
  247. package/dist/src/stored-injections.js +106 -0
  248. package/dist/src/stored-injections.js.map +1 -0
  249. package/dist/src/text-as-stored.d.ts +4 -3
  250. package/dist/src/text-as-stored.d.ts.map +1 -1
  251. package/dist/src/text-as-stored.js +4 -3
  252. package/dist/src/text-as-stored.js.map +1 -1
  253. package/dist/src/thinking-drops.d.ts +74 -0
  254. package/dist/src/thinking-drops.d.ts.map +1 -0
  255. package/dist/src/thinking-drops.js +96 -0
  256. package/dist/src/thinking-drops.js.map +1 -0
  257. package/dist/src/tool-args.d.ts +12 -0
  258. package/dist/src/tool-args.d.ts.map +1 -1
  259. package/dist/src/tool-args.js +35 -1
  260. package/dist/src/tool-args.js.map +1 -1
  261. package/dist/src/tool-image-ledger.d.ts +9 -8
  262. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  263. package/dist/src/tool-image-ledger.js +9 -8
  264. package/dist/src/tool-image-ledger.js.map +1 -1
  265. package/dist/src/tool-presentation.d.ts.map +1 -1
  266. package/dist/src/tool-presentation.js +3 -1
  267. package/dist/src/tool-presentation.js.map +1 -1
  268. package/dist/src/tool-result-guard.d.ts +12 -6
  269. package/dist/src/tool-result-guard.d.ts.map +1 -1
  270. package/dist/src/tool-result-guard.js +44 -17
  271. package/dist/src/tool-result-guard.js.map +1 -1
  272. package/dist/src/tool-result-history.d.ts +176 -24
  273. package/dist/src/tool-result-history.d.ts.map +1 -1
  274. package/dist/src/tool-result-history.js +411 -91
  275. package/dist/src/tool-result-history.js.map +1 -1
  276. package/dist/src/tune-out/coordinator.d.ts +17 -9
  277. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  278. package/dist/src/tune-out/coordinator.js +84 -37
  279. package/dist/src/tune-out/coordinator.js.map +1 -1
  280. package/dist/src/tune-out/tools.d.ts +4 -1
  281. package/dist/src/tune-out/tools.d.ts.map +1 -1
  282. package/dist/src/types/agent.d.ts +217 -7
  283. package/dist/src/types/agent.d.ts.map +1 -1
  284. package/dist/src/types/events.d.ts +33 -9
  285. package/dist/src/types/events.d.ts.map +1 -1
  286. package/dist/src/types/framework.d.ts +39 -3
  287. package/dist/src/types/framework.d.ts.map +1 -1
  288. package/dist/src/types/module.d.ts +95 -9
  289. package/dist/src/types/module.d.ts.map +1 -1
  290. package/dist/src/types/trace.d.ts +91 -3
  291. package/dist/src/types/trace.d.ts.map +1 -1
  292. package/package.json +5 -4
  293. package/src/agent.ts +661 -67
  294. package/src/api/server.ts +5 -4
  295. package/src/auto-continue.ts +43 -0
  296. package/src/code-execution/isolate/scripts.ts +11 -3
  297. package/src/cut-off-round.ts +98 -0
  298. package/src/framework.ts +6168 -1540
  299. package/src/gate/event-gate.ts +2895 -405
  300. package/src/gate/index.ts +10 -1
  301. package/src/gate/recipe-reconcile.ts +355 -0
  302. package/src/gate/reply-judge.ts +512 -0
  303. package/src/gate/types.ts +234 -9
  304. package/src/heartbeat/heartbeat.ts +804 -0
  305. package/src/heartbeat/reminder-time.ts +107 -0
  306. package/src/index.ts +11 -4
  307. package/src/mcpl/capability-mask.ts +3 -2
  308. package/src/mcpl/channel-registry.ts +1222 -468
  309. package/src/mcpl/conversation-router.ts +34 -16
  310. package/src/mcpl/convert-block.ts +14 -1
  311. package/src/mcpl/hook-orchestrator.ts +33 -6
  312. package/src/mcpl/inbound-source.ts +42 -69
  313. package/src/mcpl/index.ts +6 -1
  314. package/src/mcpl/inference-router.ts +79 -34
  315. package/src/mcpl/prose-grammar.ts +7 -0
  316. package/src/mcpl/protocol-family.ts +2 -0
  317. package/src/mcpl/push-coalescer.ts +51 -13
  318. package/src/mcpl/reference-fetcher.ts +201 -162
  319. package/src/mcpl/references.ts +851 -77
  320. package/src/mcpl/server-connection.ts +189 -11
  321. package/src/mcpl/tags.ts +13 -2
  322. package/src/mcpl/tool-lifecycle.ts +21 -0
  323. package/src/mcpl/tool-presence.ts +716 -0
  324. package/src/mcpl/tool-result-normalize.ts +18 -6
  325. package/src/mcpl/tool-signature.ts +316 -0
  326. package/src/mcpl/toolset-host.ts +727 -0
  327. package/src/mcpl/toolsets-module.ts +545 -0
  328. package/src/mcpl/transport.ts +3 -2
  329. package/src/mcpl/types.ts +25 -2
  330. package/src/mcpl/visible-content.ts +22 -9
  331. package/src/module-registry.ts +85 -26
  332. package/src/modules/discord/index.ts +1 -1
  333. package/src/modules/history/index.ts +70 -30
  334. package/src/modules/history/semantic.ts +308 -54
  335. package/src/modules/workspace/answers.ts +133 -0
  336. package/src/modules/workspace/branch-intent.ts +10 -5
  337. package/src/modules/workspace/direct-write.ts +460 -0
  338. package/src/modules/workspace/disk-agreement.ts +52 -21
  339. package/src/modules/workspace/edit-text.ts +84 -35
  340. package/src/modules/workspace/effects.ts +22 -13
  341. package/src/modules/workspace/index.ts +2142 -723
  342. package/src/modules/workspace/observe.ts +381 -177
  343. package/src/modules/workspace/read-page.ts +228 -0
  344. package/src/modules/workspace/reconcile.ts +27 -15
  345. package/src/modules/workspace/result-text.ts +121 -0
  346. package/src/modules/workspace/sync.ts +16 -0
  347. package/src/modules/workspace/text.ts +58 -32
  348. package/src/modules/workspace/types.ts +137 -60
  349. package/src/modules/workspace/watcher.ts +8 -3
  350. package/src/prose-drafts.ts +4 -3
  351. package/src/reasoning-loss-notice.ts +62 -0
  352. package/src/reasoning-loss.ts +120 -0
  353. package/src/send-tools.ts +3 -2
  354. package/src/sent-rows.ts +162 -0
  355. package/src/silent-heartbeat.ts +17 -10
  356. package/src/stable-hash.ts +14 -0
  357. package/src/stored-injections.ts +131 -0
  358. package/src/text-as-stored.ts +4 -3
  359. package/src/thinking-drops.ts +135 -0
  360. package/src/tool-args.ts +34 -1
  361. package/src/tool-image-ledger.ts +9 -8
  362. package/src/tool-presentation.ts +3 -1
  363. package/src/tool-result-guard.ts +45 -17
  364. package/src/tool-result-history.ts +471 -90
  365. package/src/tune-out/coordinator.ts +80 -37
  366. package/src/tune-out/tools.ts +4 -1
  367. package/src/types/agent.ts +220 -7
  368. package/src/types/events.ts +33 -9
  369. package/src/types/framework.ts +36 -3
  370. package/src/types/module.ts +91 -9
  371. package/src/types/trace.ts +94 -3
@@ -11,8 +11,8 @@
11
11
  * inference tokens, not whether the agent should know about the event.
12
12
  */
13
13
  import type { ToolDefinition } from '../types/events.js';
14
- import type { GateConfig, GatePolicy, GateDecision, GateEventInfo, GateStatus, ShadowWarning, GateProbeRow } from './types.js';
15
- export type { GateConfig, GateOptions, GateDecision, GateEventInfo } from './types.js';
14
+ import type { GateConfig, GatePolicy, GateDecision, GateEntryRef, WakeLine, GateEventInfo, GateStatus, ShadowWarning, GateProbeRow, JudgeFn, UpcomingWake } from './types.js';
15
+ export type { GateConfig, GateOptions, GateDecision, GateEntryRef, GateEventInfo, WakeLine, JudgeConfig, JudgeEventSummary, JudgeFn, JudgeRequest, JudgeVerdict, ReplyJudgeOptions, UpcomingWake, } from './types.js';
16
16
  interface PendingEvent {
17
17
  policyName: string;
18
18
  content: string;
@@ -44,11 +44,24 @@ interface PendingEvent {
44
44
  * whose `channelId` is the adapter's raw id (a bare Discord snowflake for a
45
45
  * DM) — unroutable. Absent when the host could not resolve one. */
46
46
  routeChannelId?: string;
47
+ /** The event's own identity among what the framework stored at arrival:
48
+ * a channel message's id, a push event's event id (isNewestEntry). */
49
+ messageId?: string;
50
+ eventId?: string;
51
+ }
52
+ /** Where the host put a message the gate wrote: the agent whose window it
53
+ * went to and, when it was held for that agent's live turn, the id it waits
54
+ * under in the host's queue, or else the id it was stored under. */
55
+ export interface WritePlacement {
56
+ agent?: string;
57
+ deferredId?: string;
58
+ messageId?: string;
47
59
  }
48
60
  /**
49
61
  * Where a gate-requested wake came from, handed to the framework alongside the
50
62
  * reason so the turn's InferenceRequest can carry it (host telemetry stamps
51
- * "who woke the agent" from it). Ids only, never content or display names.
63
+ * "who woke the agent" from it). Ids only, never content or display names,
64
+ * except `line`, which is the batch's own text for the agent's window.
52
65
  */
53
66
  export interface WakeProvenance {
54
67
  /** Composite channel id of the chosen event — telemetry only, never a
@@ -70,9 +83,20 @@ export interface WakeProvenance {
70
83
  * (2026-09-30: a DM reply published into a guild channel). Ambient-only
71
84
  * batches still set nothing and keep the legacy fallback. */
72
85
  routeChannelId?: string;
86
+ /** The server of `routeChannelId`'s channel, beside it whenever the chosen
87
+ * event named its server: channel ids are unique only within one
88
+ * server's connection (MCPL §14.2). */
89
+ routeServerId?: string;
73
90
  /** Timestamp (ms) of the chosen event, so a consumer coalescing several
74
91
  * requests can order by event recency, not by flush order. */
75
92
  at?: number;
93
+ /** The batch's `[Gate: …]` line, when the gate handed it to the wake rather
94
+ * than wrote it: a WakeLine, the parts its text is rendered from when it's
95
+ * written (wakeLineText), decided by a fresh start of the wake's turn as
96
+ * WakeLine says. Unlike the fields above, this is content for the agent's
97
+ * window, not telemetry: it carries the channel's name as the agent is
98
+ * shown it. */
99
+ line?: WakeLine;
76
100
  }
77
101
  interface TraceEventLike {
78
102
  type: string;
@@ -85,6 +109,24 @@ interface TraceEventLike {
85
109
  * addressed all come from that one event, so they can never disagree.
86
110
  */
87
111
  export declare function wakeProvenance(events: PendingEvent[]): WakeProvenance | undefined;
112
+ /** A handed batched-wake line's text (WakeLine), as it reads when written at
113
+ * `now`: the gate's words, its message's age counted to then. */
114
+ export declare function wakeLineText(line: WakeLine, now: number): string;
115
+ /**
116
+ * A value as a message quotes it: its JSON, cut short when long, never inside a
117
+ * surrogate pair, since the message reaches the agent's context.
118
+ */
119
+ export declare function shownValue(value: unknown): string;
120
+ /**
121
+ * A tool's input, its parameters given by its schema's `properties`, read as a
122
+ * rule's fields are: a null or "" parameter is left out (a note names each "",
123
+ * with what leaving it out does where `means` says), a slip of a parameter
124
+ * (fieldNames) is refused, naming the one meant, and so is a field of one of
125
+ * its object parameters given on its own, naming that parameter; any other
126
+ * name is noted, or named in that refusal. Returns the input without what was
127
+ * left out.
128
+ */
129
+ export declare function checkToolInput(tool: string, input: Record<string, unknown>, properties: Readonly<Record<string, unknown>>, notes: string[], means?: Readonly<Record<string, string>>): Record<string, unknown>;
88
130
  /**
89
131
  * Find rules made unreachable by earlier, broader rules (first match wins).
90
132
  * The 2026-08-08 Mythos incident is the canonical catch: a prepended
@@ -103,12 +145,57 @@ export declare class EventGate {
103
145
  /** Optional agent-authored programmable gate (gate.js). */
104
146
  private gateScript;
105
147
  private compiledPolicies;
106
- private configMtime;
148
+ /** The text of gate.json whose rules are in force, from a load or a write
149
+ * (or the start's reconcile, whose write failed); or, while what's in force
150
+ * is what a start ran beside gate.json or in its place (configSource not
151
+ * "file"), gate.json's text as that start found it.
152
+ * A reload parses the file again only when its text differs; a file that
153
+ * holds it again after failing to load (a chmod that makes it readable,
154
+ * an edit undone) needs nothing applied, only its error cleared. */
155
+ private configText;
156
+ /** The notes on fields the text in force has that the gate doesn't read, if any. */
157
+ private configNote;
107
158
  private lastReloadCheck;
108
159
  private configSource;
109
160
  private lastReloadTimestamp;
110
- private configErrors;
161
+ /** The current problem with each file the gate reads, one each, replaced
162
+ * whenever that file is read again (gate_status `errors`). */
163
+ private configError;
164
+ /** Whether gate.json's error is one that keeps what it holds out of force
165
+ * (configUnreadable), so gate_status says what's in force instead. */
166
+ private configUnused;
167
+ private privilegedError;
168
+ /** What the start did with the host's starting rules that it couldn't use
169
+ * or add (describeStart), kept apart from gate.json's own error, until the
170
+ * next start. */
171
+ private startNotice;
172
+ /** The rules in force that the start couldn't save (describeUnsaved),
173
+ * until gate.json is written or a reload applies its text. */
174
+ private startUnsaved;
175
+ /** What the start's merge of the recipe couldn't do (seedOrReconcile), said with startNotice until the next start. */
176
+ private startMergeNote;
177
+ /** Whether the start's unsaved rules (startUnsaved) are a merge's that did more than add rules. */
178
+ private startUnsavedMerged;
111
179
  private debounceTimers;
180
+ private judgeFn;
181
+ private judgeTimeoutMs;
182
+ private judgeOnError;
183
+ /** Per rule, the batch the judge is deciding now. */
184
+ private judging;
185
+ /** Per rule, a batch that fired while a turn changing the judged context ran or the host was
186
+ * quiesced, held to be judged once both are clear: the judge reads the
187
+ * context the turn leaves, which may already answer it. */
188
+ private judgeHeld;
189
+ private judgeRecords;
190
+ private changesJudgedContextFn;
191
+ /** Lifetime count of events dropped from batches waiting on the judge, at
192
+ * the inference buffer's cap (MAX_INFERENCE_BUFFER per rule). */
193
+ private droppedJudgeEvents;
194
+ /** Judge requests failed in a row, and the newest failure's reason: a host
195
+ * whose provider can't serve the judge's model fails every time, which
196
+ * gate_status says once it's a streak (judgeFailingNotice). */
197
+ private judgeFailStreak;
198
+ private judgeLastFailure;
112
199
  private rateLimitBuckets;
113
200
  private passiveSampleCounters;
114
201
  private rateLimitDenied;
@@ -133,15 +220,23 @@ export declare class EventGate {
133
220
  private sleepAgent;
134
221
  private disposed;
135
222
  private selfWakeTimers;
223
+ /** When each agent's pending self-wake fires, and what armed it
224
+ * (upcomingWakes). Read only while its timer is in selfWakeTimers, so an
225
+ * entry a fire or a cancel left behind says nothing. */
226
+ private selfWakeDue;
136
227
  private privilegedUsersPath;
137
228
  private privilegedUserIds;
138
- private privilegedMtime;
229
+ /** The privileged-users file's text as last read, whether or not it loaded;
230
+ * undefined when it was missing or its last read failed. */
231
+ private privilegedText;
139
232
  private lastPrivilegedCheck;
140
233
  private emitTrace;
141
234
  private addMessageFn;
142
235
  private requestInferenceFn;
143
236
  private getAgentNamesFn;
144
237
  private resolveRouteChannelFn;
238
+ private channelShownFn?;
239
+ private isNewestEntryFn?;
145
240
  /** Clock injection — keeps the new rate_limit / passive_sample paths
146
241
  * testable without monkey-patching Date.now globally. */
147
242
  private now;
@@ -153,40 +248,191 @@ export declare class EventGate {
153
248
  addMessage: (participant: string, content: Array<{
154
249
  type: 'text';
155
250
  text: string;
156
- }>, metadata?: Record<string, unknown>, forAgent?: string) => unknown;
157
- requestInference: (agentName: string, reason: string, source: string, provenance?: WakeProvenance) => void;
251
+ }>, metadata?: Record<string, unknown>, forAgent?: string, placement?: WritePlacement) => unknown;
252
+ /** `after`: the placement of the message the wake is for, when it has
253
+ * one, so the host can drop the wake once a request that carried the
254
+ * message is answered. */
255
+ requestInference: (agentName: string, reason: string, source: string, provenance?: WakeProvenance, after?: WritePlacement) => void;
158
256
  getAgentNames: () => string[];
159
257
  /** Optional clock — defaults to Date.now. Tests inject for deterministic time. */
160
258
  now?: () => number;
161
259
  /** Per-event timeout (ms) for the optional gate.js script. Default 50. */
162
260
  scriptTimeoutMs?: number;
261
+ /** The reply judge `judge` rules ask (JudgeConfig). Absent: a judge
262
+ * rule's batch is delivered as a debounce's, and gate_status says so. */
263
+ judge?: JudgeFn;
264
+ /** Whether a turn of this agent changes the context the judge reads. Such
265
+ * turns, and only they, hold a judge rule's batch until they end, and one
266
+ * that starts while the judge decides stops the judge, whose batch is
267
+ * then judged after the turn. Absent: every agent's turns do. */
268
+ changesJudgedContext?: (agentName: string) => boolean;
269
+ /** How long a judge request may take (ms). Default 20,000. */
270
+ judgeTimeoutMs?: number;
271
+ /** What a judge failure does: wake (default) or skip. */
272
+ judgeOnError?: 'wake' | 'skip';
163
273
  /** Map an event to the registered channel it arrived on (the host knows
164
- * how push-event origins compose into channel ids). Default: a
165
- * channel-incoming event's own channel id; nothing for push events. */
274
+ * how push-event origins compose into channel ids). The gate routes a
275
+ * batched wake by it, tests a policy's `match.channel` against it when
276
+ * the event's own id misses, and keys `keyBy: "channelId"` counts on it.
277
+ * A resolver that throws counts as returning nothing. Default: a
278
+ * channel-incoming event's own channel id; nothing for push events, so
279
+ * a push then matches and counts by its own id alone. */
166
280
  resolveRouteChannel?: (info: GateEventInfo) => string | undefined;
281
+ /** How the agent is shown a channel, its server's and its id (the
282
+ * framework's ChannelRegistry.nameShown): a batched wake's summary names
283
+ * each channel so, since two servers' channels can share an id. Default:
284
+ * the id. */
285
+ channelShown?: (channel: {
286
+ serverId: string;
287
+ channelId: string;
288
+ }) => string;
289
+ /** Whether an MCPL event's own context entry is still the newest entry in
290
+ * the window a batched wake's line would be written to, with nothing
291
+ * waiting to be written there. A batched wake for that one message
292
+ * doesn't write its line when it fires: it hands the line to the wake
293
+ * (WakeProvenance.line), for a fresh start of the wake's turn to decide
294
+ * (WakeLine). Absent: every batched wake writes its line, as before. */
295
+ isNewestEntry?: (entry: GateEntryRef) => boolean;
167
296
  });
168
- private loadConfig;
297
+ /**
298
+ * Write the starting rules to gate.json, as given, when it's absent, and
299
+ * record them as the recipe last applied (lastRecipePath); or, when it
300
+ * loads, merge them into its own rule list against that record, three ways
301
+ * and as written (reconcileWithRecipe), and record them. A rule as the last
302
+ * recipe left it follows the new one, a rule edited since keeps its edit, a
303
+ * rule no recipe declared stays, and `default` follows the same rule. A
304
+ * rule gate.json holds holds its name, whether the gate reads it or leaves
305
+ * it out. gate.json is written before the record, so a stop between the two
306
+ * leaves a state the next start reads rightly: the other order would make
307
+ * the old recipe's rules read as edits. Nothing is recorded where gate.json
308
+ * isn't written as the merge asks, or a name is given twice. Where
309
+ * gate.json has no rules of its own and, under its default, one of them that
310
+ * could wake the agent can't be put in force (left out, with no name, or kept
311
+ * out by a rule of gate.json's of its name that the gate leaves out), or
312
+ * they're refused whole and that default holds events back, gate.json isn't
313
+ * used at this start, which runs as one without it does. Otherwise, where
314
+ * gate.json has no rule list to add them to, it writes nothing, and the gate
315
+ * runs beside it those of them it reads. Says what it did when that wasn't
316
+ * simply done or not needed.
317
+ */
318
+ private seedOrReconcile;
319
+ /**
320
+ * Record the starting config, as given, as the recipe last applied, after
321
+ * gate.json holds what the start merged (`holds` says what that is). A
322
+ * write that fails is said with the start: the next start merges against
323
+ * the record as the write left it.
324
+ */
325
+ private recordRecipe;
326
+ /**
327
+ * gate.json as it is on disk: absent; loaded; refused, when it's JSON that
328
+ * readConfig doesn't use; or unreadable, when it can't be read or isn't
329
+ * JSON (`notJson`, where it could be read). A loaded file comes with its note,
330
+ * which names what it holds that does nothing or is read past a problem, and
331
+ * a loaded or refused one with its own fields and rule list as written, for a
332
+ * write to edit (Listed).
333
+ * Reading applies nothing: whoever applies a loaded config records its text
334
+ * as `configText`. With `unlessUnchanged`, a file whose text is
335
+ * `configText` comes back `unchanged`, unparsed, since the rules in force
336
+ * came from it, or are what a start ran beside it or in its place.
337
+ */
338
+ private readConfigFile;
339
+ /**
340
+ * gate.json's current error, replacing the last one, and traced and logged
341
+ * when it's new, so an edit that doesn't load is in the log once.
342
+ */
343
+ private configUnreadable;
344
+ /**
345
+ * gate.json's error as gate_status shows it: one that keeps what the file
346
+ * holds out of force says what's in force instead, so it reads on its own.
347
+ */
348
+ private configErrorShown;
349
+ /** What the gate runs, by where its rules came from, for a text that says so: "the host's starting rules". */
350
+ private rulesRun;
351
+ /**
352
+ * What a policy change edits: gate.json's own fields and rule list as
353
+ * written, each rule as written, so a write keeps every rule it doesn't
354
+ * change, problems and unknown fields included, whether gate.json loads or
355
+ * is JSON the gate doesn't use. Over one it doesn't use, writeConfig writes
356
+ * only what loads, so a change is refused, naming what keeps the file out
357
+ * and what would bring it into force (`remedy`), unless it mends that, and
358
+ * the file stays as its operator wrote it. When
359
+ * gate.json is absent, the same of the text whose rules are in force, so a
360
+ * rule it leaves out keeps its name; or the rules in force, where no text
361
+ * is, it has no rule list, or what's in force is what a start ran beside or
362
+ * in place of it. A change is refused (`refused`) for a gate.json that can't
363
+ * be read or isn't JSON (unusableRefusal), whose rules can't be edited
364
+ * without writing over what it holds, and for one with no rule list a write
365
+ * could edit without that (a list, a "policies" that isn't one and holds
366
+ * something, or JSON that isn't an object): so a removal or an anchor is
367
+ * refused too, rather than looked for in rules that may not be what the
368
+ * file holds. It's refused as well for a gate.json that holds the text a
369
+ * start didn't use (start-without), since what the change wrote would put
370
+ * its rules in force in place of what the start runs.
371
+ */
372
+ private rulesForChange;
169
373
  private compilePolicies;
374
+ /**
375
+ * Clear the state of each rule `was` held in force that `next` leaves out or
376
+ * gives another behavior: a reload calls it before it puts `next` in force,
377
+ * a write after. Without this, a rule that came back, or whose tokens 100
378
+ * became 5 (or keyBy switched, or every 10 became 3), would run on the
379
+ * buckets and counters of the rule it was. A rule left out loses its stats
380
+ * (matchCount, lastMatchTimestamp) too; a rule kept keeps them, which are
381
+ * history, not live state, and one kept with the same behavior keeps all its
382
+ * state, its denial and fire counts included. Rules that share a name share
383
+ * its state, so a name keeps it only where its rules, in order, keep their
384
+ * behaviors. Each pending debounce batch is sent last, as its timer would
385
+ * have sent it, once every rule's state is cleared; one whose delivery throws
386
+ * is named in the log and dropped (fireDebounce), and the rest are still
387
+ * sent, so the write or reload that cleared it has done what it was for, its
388
+ * caller hears that it did, and no state is left behind.
389
+ */
390
+ private clearStateFor;
170
391
  private reloadIfChanged;
171
392
  /**
172
393
  * Add or replace (upsert) a single policy in gate.json and apply it live.
173
394
  *
174
- * The raw policy is validated with the SAME `validatePolicy` used when loading
175
- * gate.json — an invalid shape throws (nothing is written) and the caller
176
- * surfaces it as a tool error. On success the policy is persisted to gate.json
177
- * (so it survives restart and is visible to `workspace--edit _config/gate.json`)
395
+ * The raw policy is read with the SAME `readRule` used when loading gate.json,
396
+ * and since its caller is there to fix it, any problem it has throws, naming
397
+ * every one (nothing is written), and the caller surfaces it as a tool error,
398
+ * where a load reads past it (readConfig). On success the policy is persisted
399
+ * to gate.json (so it survives restart and is visible to `workspace--edit _config/gate.json`)
178
400
  * and the in-memory config is swapped in immediately, so the rule takes effect
179
- * without waiting for the throttled mtime reload.
401
+ * without waiting for the throttled reload.
180
402
  *
181
403
  * The freshest on-disk config is re-read first, so a concurrent operator edit
182
- * isn't clobbered. A policy with the same `name` is replaced IN PLACE when no
183
- * `position` is given (order preserved); WITH a `position` it is moved there
184
- * — so re-issuing a rule is also how you reposition it. New policies append
185
- * by default; `'prepend'` puts one at the very front (ahead of EVERYTHING,
186
- * including addressed-message wake rules — see the shadow lint), and the
187
- * anchored forms `{before: name}` / `{after: name}` insert relative to an
188
- * existing rule, which is almost always the safer way to order a sampler
189
- * or debounce against a specific catch-all.
404
+ * isn't clobbered, and the change edits gate.json's own rule list by name:
405
+ * every rule it doesn't change is written back as it was written, problems and
406
+ * fields the gate doesn't read included, and so is everything else gate.json
407
+ * holds, such as a list of rules parked under another name, beside which a
408
+ * change adds a "policies" list where there's none (rulesForChange). Over a
409
+ * gate.json the gate doesn't use, only a change after which it loads is
410
+ * written, such as one replacing or removing the rule that keeps it out, and
411
+ * that leaves it rules in force, since it holds events back by default; any
412
+ * other is refused, naming what does, and the file stays as written. When
413
+ * gate.json is absent, the change edits the text whose rules are in force the
414
+ * same way, or the rules in force where there's none. A gate.json that can't
415
+ * be read or isn't JSON is refused (unusableRefusal), and stays as it is. A policy with the
416
+ * same `name` is replaced IN PLACE when no `position` is given (order
417
+ * preserved); WITH a `position` it is moved there — so re-issuing a rule is
418
+ * also how you reposition it. New policies append by default; `'prepend'` puts
419
+ * one at the very front (ahead of EVERYTHING, including addressed-message wake
420
+ * rules — see the shadow lint), and the anchored forms `{before: name}` /
421
+ * `{after: name}` insert relative to an existing rule, which is almost always
422
+ * the safer way to order a sampler or debounce against a specific catch-all.
423
+ * Fields of the policy the gate reads nowhere, and that aren't a slip of one
424
+ * it does, are left out of what's written, and named to `onIgnoredFields` once
425
+ * the change is written and traced. A throw from the callback is logged,
426
+ * and the change stands (afterChange). A field it reads at another level is a
427
+ * problem, like a slip.
428
+ *
429
+ * Throws, writing nothing, for an invalid policy, a placement it can't make,
430
+ * a gate.json that can't be read or isn't JSON, one with no rule list it
431
+ * could edit without writing over what it holds, one a start didn't use,
432
+ * which runs as one without it does, while it's unchanged, or one the gate
433
+ * doesn't use that the change doesn't mend or would leave with no rules in
434
+ * force; and throws when the write fails, which may leave gate.json
435
+ * part-written.
190
436
  */
191
437
  addPolicy(rawPolicy: unknown, options?: {
192
438
  position?: 'append' | 'prepend' | {
@@ -194,31 +440,63 @@ export declare class EventGate {
194
440
  } | {
195
441
  after: string;
196
442
  };
443
+ onIgnoredFields?: (notes: string[]) => void;
197
444
  }): GatePolicy;
198
445
  /**
199
446
  * Remove a policy by name from gate.json and clear its live state. Any pending
200
- * debounce batch is delivered first (matching reloadIfChanged's removal path,
201
- * so buffered events aren't silently dropped). Returns false if no policy of
202
- * that name exists (nothing written). Freshest on-disk config is re-read first
203
- * (see addPolicy).
447
+ * debounce batch is sent once the removal is written and in force, as its
448
+ * timer would have sent it, so buffered events aren't silently dropped
449
+ * (clearStateFor). Freshest on-disk config is re-read first, and every other
450
+ * rule is written back as it was written (see addPolicy). A name that isn't
451
+ * a non-empty string names no rule, so it returns false, writing nothing,
452
+ * whatever gate.json holds. Otherwise it throws, writing nothing, for a
453
+ * gate.json that can't be read or isn't JSON, one with no rule list it could
454
+ * edit, or one a start didn't use, as addPolicy does, and returns false,
455
+ * writing nothing, if no policy of that name exists, gate.json's own rules
456
+ * included, so one the gate leaves out can be removed by name too. For a name
457
+ * it holds, it throws, writing nothing, for a gate.json the gate doesn't use
458
+ * that the removal doesn't mend or would leave with no rules in force, and
459
+ * throws when the write fails, which may
460
+ * leave gate.json part-written; the rules in force then stay as they were,
461
+ * with their state.
204
462
  */
205
463
  removePolicy(name: string): boolean;
206
464
  /**
207
- * List the current policy names (freshest on-disk view). Cheap helper for
465
+ * List the current policy names: those of a newer gate.json that loads (the
466
+ * freshest on-disk view), and otherwise the rules in force, which beside a
467
+ * gate.json with no rule list are the host's starting rules. Cheap helper for
208
468
  * tools/UX that want to show what's active without the full status payload.
209
469
  */
210
470
  listPolicyNames(): string[];
211
471
  /**
212
- * Persist a config to gate.json and apply it in memory together: write the
213
- * file, swap in the compiled policies, and sync `configMtime` to the new file
214
- * so `reloadIfChanged` doesn't redundantly re-parse identical content. Throws
215
- * if the write fails (disk/permission) — callers surface it as a tool error.
472
+ * Persist gate.json and apply it in memory together: `top`, its own fields,
473
+ * with `rules` as its rule list. Only what loads is written: a change to a
474
+ * gate.json the gate doesn't use, for which `remedy` is given, what would
475
+ * bring it into force, throws, naming that and `remedy`, and writes nothing,
476
+ * where the change doesn't mend what keeps it out, or where it would leave
477
+ * gate.json with no rules in force: such a gate.json holds events back by
478
+ * default, so putting it in force would hold back every event, those the
479
+ * rules in force wake on included. The rules in force are then what the text
480
+ * written reads as, as at a load, so what it still holds that the gate reads
481
+ * past or leaves out stays named; the text is kept as `configText`, so
482
+ * `reloadIfChanged` doesn't parse it again. Once the text is written and its
483
+ * rules are in force, a rule that was in force that it leaves out or gives
484
+ * another behavior loses its state (clearStateFor), last, since a pending
485
+ * batch it sends can't be taken back, and a write that fails leaves the
486
+ * rules in force with their state; a batch that can't be delivered is
487
+ * logged, not thrown. A write that fails throws, saying whether gate.json was
488
+ * changed: one that fails before writing leaves it as it was, and one that
489
+ * fails after its open may leave it part-written (beforeWriting). Callers
490
+ * surface it as a tool error.
216
491
  */
217
492
  private writeConfig;
218
493
  private compiledMatches;
219
494
  evaluate(info: GateEventInfo): GateDecision;
220
495
  private computeDecision;
221
- /** Resolve the partition key for keyBy-style behaviors. */
496
+ /** Resolve the partition key for keyBy-style behaviors. `keyBy:
497
+ * "channelId"` takes the registered id the gate resolves for the event when
498
+ * it has one, as channel matching does, so a channel's push events count
499
+ * with its channels/incoming messages rather than under their raw id. */
222
500
  private resolveKey;
223
501
  private applyRateLimit;
224
502
  private applyPassiveSample;
@@ -229,11 +507,12 @@ export declare class EventGate {
229
507
  */
230
508
  private applyResets;
231
509
  /**
232
- * Clear ALL per-policy state (debounce timer, rate-limit buckets,
233
- * passive-sample counters, denial / fire counters) for one policy.
234
- * Used by reloadIfChanged when a policy is removed or its behavior
235
- * params change. Stats (matchCount, lastMatchTimestamp) are preserved
236
- * — those are historical and shouldn't reset on a config edit.
510
+ * Clear one policy's live state (rate-limit buckets, passive-sample
511
+ * counters, denial / fire counters) and stop its debounce timer, leaving
512
+ * its pending batch for fireDebounce to send, as clearStateFor does once
513
+ * every policy's state is cleared. It leaves stats (matchCount,
514
+ * lastMatchTimestamp), which are history; clearStateFor deletes a removed
515
+ * policy's.
237
516
  */
238
517
  private clearPolicyState;
239
518
  /**
@@ -250,6 +529,15 @@ export declare class EventGate {
250
529
  * may be stateful, and a probe must never perturb state.
251
530
  */
252
531
  probe(info: GateEventInfo): GateDecision;
532
+ /** The canonical synthetic events the probe table runs: chat shapes as MCPL delivers them, and a heartbeat. */
533
+ private probeEvents;
534
+ /**
535
+ * The rules no probe event matches, such as one scoped to an event type
536
+ * the probes don't model (`external-message`, how a module's messages are
537
+ * gated): the probe table can't show what they do, so a result that shows
538
+ * the table names them rather than let its rows read as their effect.
539
+ */
540
+ probeUnreached(): string[];
253
541
  /**
254
542
  * Probe a canonical set of synthetic chat/heartbeat events and report which
255
543
  * rule wins each and whether it would wake. Backs the before/after table in
@@ -257,7 +545,8 @@ export declare class EventGate {
257
545
  * must become legible (af#105; the Mythos stand-back-density incident would
258
546
  * have been visible as `dm: discord-direct-address → stand-back-density`).
259
547
  * Probes are representative shapes, not an exhaustive event space — rules
260
- * keyed on specific channels/mounts may not match any probe.
548
+ * keyed on specific channels/mounts, or on other event types, may not match
549
+ * any probe; `probeUnreached` names those.
261
550
  */
262
551
  probeTable(): GateProbeRow[];
263
552
  /** Current shadow-lint findings for the live policy order. Fresh compute —
@@ -280,6 +569,61 @@ export declare class EventGate {
280
569
  private handleDebounce;
281
570
  private fireDebounce;
282
571
  private deliverEvents;
572
+ /** isNewestEntry for one event; a callback fault keeps the line. */
573
+ private newestEntry;
574
+ /**
575
+ * Send one of a judge rule's batches to the reply judge. While a resident's
576
+ * turn runs or the host is quiesced the batch is held instead, merged with
577
+ * any the rule already holds, and judged once both are clear
578
+ * (flushJudgeHeldIfClear): the judge then reads the context the turn left,
579
+ * which may already have answered it. While the judge decides one of the
580
+ * rule's batches, a later one waits for that verdict (finishJudging), so the
581
+ * judge never decides two of a rule's batches at once.
582
+ */
583
+ private judgeBatch;
584
+ /** Hold a batch for the judge until no turn changing the context it reads
585
+ * runs and the host isn't quiesced, merged with what the rule already holds. */
586
+ private holdForJudge;
587
+ /**
588
+ * Keep a rule's events waiting on the judge to the inference buffer's cap,
589
+ * dropping the oldest, counted and logged as bufferForInference counts its
590
+ * drops: a turn that never ends (the wake-wedge) or a long quiesce on a busy
591
+ * channel would otherwise grow them without bound. A queue beside a batch
592
+ * the judge is deciding is capped on its own, so its newest events are never
593
+ * the ones dropped for the batch ahead of it.
594
+ */
595
+ private capJudgeEvents;
596
+ /** The rule's judge as it is now, when the rule is still a judge rule; else the one the batch was asked with. */
597
+ private currentJudge;
598
+ /**
599
+ * The gate's own timers that will wake `agentNames` with no new event, for
600
+ * the judge to weigh what waiting costs: each agent's pending self-wake
601
+ * (skip_reply's wake_in_seconds), the end of a sleep, and the pending
602
+ * batches of rules other than `exceptPolicy` (a debounce's wakes the agent
603
+ * when it fires; a judge rule's goes to the judge, so it only may).
604
+ */
605
+ upcomingWakes(agentNames: string[], exceptPolicy?: string): UpcomingWake[];
606
+ /** A batch's event as the judge is shown it. */
607
+ private judgeEventSummary;
608
+ /**
609
+ * Apply the judge's verdict on a batch. Reply: the batch, with any of the
610
+ * rule's batches that fired meanwhile, is delivered as a debounce's is
611
+ * (held for a turn that started meanwhile, as fireDebounce holds one). Wait:
612
+ * nothing is delivered, and batches that fired meanwhile go to the judge
613
+ * afresh. A judge that failed, timed out or answered nothing usable decides
614
+ * by onError: "wake" delivers, "skip" doesn't. Each verdict is traced and
615
+ * counted for gate_status, and a failure is logged.
616
+ */
617
+ private finishJudging;
618
+ /** Deliver a batch now, or hold it for the agents' turns and the host's
619
+ * quiesce to end, as fireDebounce does; a delivery that throws drops it,
620
+ * named in the log. */
621
+ private deliverOrBuffer;
622
+ private changesJudgedContext;
623
+ private judgedTurnRunning;
624
+ private stopJudging;
625
+ /** Send the batches held for the judge once no turn changing the context it reads runs and the host isn't quiesced. */
626
+ private flushJudgeHeldIfClear;
283
627
  onInferenceStarted(agentName: string): void;
284
628
  /** A turn that continues another (a budget restart, a tool-result-guard
285
629
  * retry) holds the entry its predecessor kept for it, and takes it again
@@ -310,6 +654,9 @@ export declare class EventGate {
310
654
  bufferedEvents: number;
311
655
  droppedBufferedEvents: number;
312
656
  sleepUntil: number;
657
+ /** Events held for the reply judge until the turn or quiesce ends, and the judge's own drops at the cap. */
658
+ judgeHeldEvents: number;
659
+ droppedJudgeEvents: number;
313
660
  };
314
661
  /** Called internally when debounce fires during inference. */
315
662
  private bufferForInference;
@@ -334,10 +681,9 @@ export declare class EventGate {
334
681
  private armSleepWake;
335
682
  /**
336
683
  * `agentName` is gone, as a conversation fork's end or an ephemeral run's
337
- * removes one: its pending self-wake is cancelled, and a sleep it set ends.
338
- * The gate's sleep holds back every agent's wakes, so nobody is asleep once
339
- * its agent is gone, and neither wake would reach a name that no longer
340
- * exists. A sleep another agent set, or one set with no agent, stays.
684
+ * removes one: its pending self-wake is cancelled, rather than wake a name
685
+ * that no longer exists. It holds no sleep: neither can set one (the
686
+ * framework refuses their `sleep`).
341
687
  */
342
688
  agentGone(agentName: string): void;
343
689
  /**
@@ -372,15 +718,24 @@ export declare class EventGate {
372
718
  } | null;
373
719
  /** Author id from an event's metadata, across the discord ingest shapes. */
374
720
  private extractAuthorId;
375
- /** Load the privileged-users file (bare array or { userIds: [...] }). */
376
721
  /**
377
722
  * Whether an author id is on the privileged-users list (hot-reloaded).
378
723
  * Shared by sleep bypass and tune-out wake classification (#77: wakes are
379
724
  * "mentions, gate-privileged authors, etc.").
380
725
  */
381
726
  isPrivilegedUser(authorId: string | null | undefined): boolean;
727
+ /**
728
+ * Read the privileged-users file: a list of user ids, or `{"userIds": [...]}`,
729
+ * each a non-empty string or a safe integer (a whole number within 2^53 - 1 of zero). An absent file
730
+ * means no one is privileged. A file that can't be read, isn't JSON, or
731
+ * holds no list leaves the list that last loaded in this process in effect
732
+ * (none, at startup), with its error in gate_status until the file is read
733
+ * again. In a list, an entry that isn't a user id is skipped, and named in
734
+ * the file's error, and the rest load. With `unlessUnchanged`, a file whose
735
+ * text is the text last read isn't parsed again.
736
+ */
382
737
  private loadPrivileged;
383
- /** Throttled mtime-based reload of the privileged-users file. */
738
+ /** At most once a second, the privileged-users file read again, and loaded when its text has changed. */
384
739
  private reloadPrivilegedIfChanged;
385
740
  getToolDefinition(): ToolDefinition;
386
741
  handleToolCall(): Promise<{
@@ -389,6 +744,10 @@ export declare class EventGate {
389
744
  error?: string;
390
745
  }>;
391
746
  getStatus(): GateStatus;
747
+ /** gate_status's word on judge rules in force with no judge wired. */
748
+ private judgeUnwiredNotice;
749
+ /** gate_status's word on a judge that keeps failing (JUDGE_FAILING_STREAK in a row). */
750
+ private judgeFailingNotice;
392
751
  dispose(): void;
393
752
  }
394
753
  //# sourceMappingURL=event-gate.d.ts.map