@animalabs/agent-framework 0.31.0 → 0.33.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 (298) hide show
  1. package/README.md +204 -14
  2. package/dist/src/admission/admit.d.ts +18 -0
  3. package/dist/src/admission/admit.d.ts.map +1 -1
  4. package/dist/src/admission/admit.js +16 -3
  5. package/dist/src/admission/admit.js.map +1 -1
  6. package/dist/src/agent.d.ts +185 -78
  7. package/dist/src/agent.d.ts.map +1 -1
  8. package/dist/src/agent.js +279 -102
  9. package/dist/src/agent.js.map +1 -1
  10. package/dist/src/api/mcp-server-core.d.ts.map +1 -1
  11. package/dist/src/api/mcp-server-core.js +50 -12
  12. package/dist/src/api/mcp-server-core.js.map +1 -1
  13. package/dist/src/api/server.d.ts.map +1 -1
  14. package/dist/src/api/server.js +4 -20
  15. package/dist/src/api/server.js.map +1 -1
  16. package/dist/src/code-execution/isolate/scripts.d.ts +12 -8
  17. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -1
  18. package/dist/src/code-execution/isolate/scripts.js +24 -0
  19. package/dist/src/code-execution/isolate/scripts.js.map +1 -1
  20. package/dist/src/config-checks.d.ts +7 -0
  21. package/dist/src/config-checks.d.ts.map +1 -1
  22. package/dist/src/config-checks.js +14 -0
  23. package/dist/src/config-checks.js.map +1 -1
  24. package/dist/src/context-manager-errors.d.ts +25 -0
  25. package/dist/src/context-manager-errors.d.ts.map +1 -0
  26. package/dist/src/context-manager-errors.js +31 -0
  27. package/dist/src/context-manager-errors.js.map +1 -0
  28. package/dist/src/context-options.d.ts +67 -0
  29. package/dist/src/context-options.d.ts.map +1 -0
  30. package/dist/src/context-options.js +85 -0
  31. package/dist/src/context-options.js.map +1 -0
  32. package/dist/src/deferred-import.d.ts +93 -0
  33. package/dist/src/deferred-import.d.ts.map +1 -0
  34. package/dist/src/deferred-import.js +177 -0
  35. package/dist/src/deferred-import.js.map +1 -0
  36. package/dist/src/dendrite/audience.d.ts +223 -0
  37. package/dist/src/dendrite/audience.d.ts.map +1 -0
  38. package/dist/src/dendrite/audience.js +202 -0
  39. package/dist/src/dendrite/audience.js.map +1 -0
  40. package/dist/src/dendrite/index.d.ts +5 -3
  41. package/dist/src/dendrite/index.d.ts.map +1 -1
  42. package/dist/src/dendrite/index.js +2 -1
  43. package/dist/src/dendrite/index.js.map +1 -1
  44. package/dist/src/dendrite/presets.d.ts +10 -5
  45. package/dist/src/dendrite/presets.d.ts.map +1 -1
  46. package/dist/src/dendrite/presets.js +17 -5
  47. package/dist/src/dendrite/presets.js.map +1 -1
  48. package/dist/src/dendrite/registry.d.ts +62 -7
  49. package/dist/src/dendrite/registry.d.ts.map +1 -1
  50. package/dist/src/dendrite/registry.js +179 -10
  51. package/dist/src/dendrite/registry.js.map +1 -1
  52. package/dist/src/dendrite/types.d.ts +91 -8
  53. package/dist/src/dendrite/types.d.ts.map +1 -1
  54. package/dist/src/foreign-rounds.d.ts +69 -0
  55. package/dist/src/foreign-rounds.d.ts.map +1 -0
  56. package/dist/src/foreign-rounds.js +152 -0
  57. package/dist/src/foreign-rounds.js.map +1 -0
  58. package/dist/src/framework.d.ts +1977 -820
  59. package/dist/src/framework.d.ts.map +1 -1
  60. package/dist/src/framework.js +7571 -3457
  61. package/dist/src/framework.js.map +1 -1
  62. package/dist/src/gate/event-gate.d.ts +85 -15
  63. package/dist/src/gate/event-gate.d.ts.map +1 -1
  64. package/dist/src/gate/event-gate.js +421 -47
  65. package/dist/src/gate/event-gate.js.map +1 -1
  66. package/dist/src/gate/index.d.ts +1 -1
  67. package/dist/src/gate/index.d.ts.map +1 -1
  68. package/dist/src/gate/index.js.map +1 -1
  69. package/dist/src/gate/rule-scope.d.ts +30 -0
  70. package/dist/src/gate/rule-scope.d.ts.map +1 -0
  71. package/dist/src/gate/rule-scope.js +41 -0
  72. package/dist/src/gate/rule-scope.js.map +1 -0
  73. package/dist/src/gate/suppress-script-worker.d.ts +2 -0
  74. package/dist/src/gate/suppress-script-worker.d.ts.map +1 -0
  75. package/dist/src/gate/suppress-script-worker.js +103 -0
  76. package/dist/src/gate/suppress-script-worker.js.map +1 -0
  77. package/dist/src/gate/suppress-scripts.d.ts +105 -0
  78. package/dist/src/gate/suppress-scripts.d.ts.map +1 -0
  79. package/dist/src/gate/suppress-scripts.js +403 -0
  80. package/dist/src/gate/suppress-scripts.js.map +1 -0
  81. package/dist/src/gate/suppression-review.d.ts +143 -0
  82. package/dist/src/gate/suppression-review.d.ts.map +1 -0
  83. package/dist/src/gate/suppression-review.js +463 -0
  84. package/dist/src/gate/suppression-review.js.map +1 -0
  85. package/dist/src/gate/suppression-stats.d.ts +125 -0
  86. package/dist/src/gate/suppression-stats.d.ts.map +1 -0
  87. package/dist/src/gate/suppression-stats.js +214 -0
  88. package/dist/src/gate/suppression-stats.js.map +1 -0
  89. package/dist/src/gate/types.d.ts +135 -7
  90. package/dist/src/gate/types.d.ts.map +1 -1
  91. package/dist/src/gate/wake-onboarding.d.ts +119 -0
  92. package/dist/src/gate/wake-onboarding.d.ts.map +1 -0
  93. package/dist/src/gate/wake-onboarding.js +277 -0
  94. package/dist/src/gate/wake-onboarding.js.map +1 -0
  95. package/dist/src/held-writes.d.ts +31 -23
  96. package/dist/src/held-writes.d.ts.map +1 -1
  97. package/dist/src/held-writes.js +44 -59
  98. package/dist/src/held-writes.js.map +1 -1
  99. package/dist/src/index.d.ts +5 -2
  100. package/dist/src/index.d.ts.map +1 -1
  101. package/dist/src/index.js +3 -0
  102. package/dist/src/index.js.map +1 -1
  103. package/dist/src/jsonrpc-envelope.d.ts +69 -0
  104. package/dist/src/jsonrpc-envelope.d.ts.map +1 -0
  105. package/dist/src/jsonrpc-envelope.js +66 -0
  106. package/dist/src/jsonrpc-envelope.js.map +1 -0
  107. package/dist/src/mcpl/channel-registry.d.ts +131 -15
  108. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  109. package/dist/src/mcpl/channel-registry.js +290 -46
  110. package/dist/src/mcpl/channel-registry.js.map +1 -1
  111. package/dist/src/mcpl/checkpoint-manager.d.ts +2 -4
  112. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  113. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  114. package/dist/src/mcpl/feature-set-manager.d.ts +2 -4
  115. package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
  116. package/dist/src/mcpl/feature-set-manager.js.map +1 -1
  117. package/dist/src/mcpl/inbound-source.d.ts +2 -1
  118. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  119. package/dist/src/mcpl/inbound-source.js +2 -1
  120. package/dist/src/mcpl/inbound-source.js.map +1 -1
  121. package/dist/src/mcpl/inference-router.d.ts +6 -6
  122. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  123. package/dist/src/mcpl/inference-router.js.map +1 -1
  124. package/dist/src/mcpl/push-coalescer.d.ts +132 -22
  125. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  126. package/dist/src/mcpl/push-coalescer.js +105 -15
  127. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  128. package/dist/src/mcpl/push-handler.d.ts +9 -7
  129. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  130. package/dist/src/mcpl/push-handler.js.map +1 -1
  131. package/dist/src/mcpl/server-connection.d.ts +13 -10
  132. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  133. package/dist/src/mcpl/server-connection.js +134 -56
  134. package/dist/src/mcpl/server-connection.js.map +1 -1
  135. package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
  136. package/dist/src/mcpl/tool-classes.js +3 -0
  137. package/dist/src/mcpl/tool-classes.js.map +1 -1
  138. package/dist/src/mcpl/types.d.ts +8 -2
  139. package/dist/src/mcpl/types.d.ts.map +1 -1
  140. package/dist/src/mcpl/types.js.map +1 -1
  141. package/dist/src/module-registry.d.ts +24 -1
  142. package/dist/src/module-registry.d.ts.map +1 -1
  143. package/dist/src/module-registry.js +68 -18
  144. package/dist/src/module-registry.js.map +1 -1
  145. package/dist/src/modules/discord/index.d.ts +45 -8
  146. package/dist/src/modules/discord/index.d.ts.map +1 -1
  147. package/dist/src/modules/discord/index.js +237 -86
  148. package/dist/src/modules/discord/index.js.map +1 -1
  149. package/dist/src/modules/history/index.d.ts +59 -0
  150. package/dist/src/modules/history/index.d.ts.map +1 -1
  151. package/dist/src/modules/history/index.js +432 -67
  152. package/dist/src/modules/history/index.js.map +1 -1
  153. package/dist/src/modules/history/semantic.d.ts +6 -5
  154. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  155. package/dist/src/modules/history/semantic.js +15 -22
  156. package/dist/src/modules/history/semantic.js.map +1 -1
  157. package/dist/src/modules/workspace/disk-agreement.d.ts +1 -1
  158. package/dist/src/modules/workspace/disk-agreement.js +1 -1
  159. package/dist/src/modules/workspace/index.d.ts +28 -7
  160. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  161. package/dist/src/modules/workspace/index.js +76 -22
  162. package/dist/src/modules/workspace/index.js.map +1 -1
  163. package/dist/src/notice-tags.d.ts +10 -1
  164. package/dist/src/notice-tags.d.ts.map +1 -1
  165. package/dist/src/notice-tags.js +10 -1
  166. package/dist/src/notice-tags.js.map +1 -1
  167. package/dist/src/operator-log.d.ts +36 -3
  168. package/dist/src/operator-log.d.ts.map +1 -1
  169. package/dist/src/operator-log.js +2 -2
  170. package/dist/src/operator-log.js.map +1 -1
  171. package/dist/src/presentation.d.ts +746 -0
  172. package/dist/src/presentation.d.ts.map +1 -0
  173. package/dist/src/presentation.js +1435 -0
  174. package/dist/src/presentation.js.map +1 -0
  175. package/dist/src/prose-drafts.d.ts +15 -11
  176. package/dist/src/prose-drafts.d.ts.map +1 -1
  177. package/dist/src/prose-drafts.js +16 -12
  178. package/dist/src/prose-drafts.js.map +1 -1
  179. package/dist/src/read-marks.d.ts +192 -0
  180. package/dist/src/read-marks.d.ts.map +1 -0
  181. package/dist/src/read-marks.js +242 -0
  182. package/dist/src/read-marks.js.map +1 -0
  183. package/dist/src/recovery/offline-branch.d.ts +91 -6
  184. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  185. package/dist/src/recovery/offline-branch.js +273 -29
  186. package/dist/src/recovery/offline-branch.js.map +1 -1
  187. package/dist/src/recovery/recover-cli.js +22 -3
  188. package/dist/src/recovery/recover-cli.js.map +1 -1
  189. package/dist/src/send-tools.d.ts +5 -9
  190. package/dist/src/send-tools.d.ts.map +1 -1
  191. package/dist/src/send-tools.js +40 -7
  192. package/dist/src/send-tools.js.map +1 -1
  193. package/dist/src/stored-injections.d.ts +2 -2
  194. package/dist/src/stored-injections.js +2 -2
  195. package/dist/src/stored-removal.d.ts +17 -4
  196. package/dist/src/stored-removal.d.ts.map +1 -1
  197. package/dist/src/stored-removal.js +29 -5
  198. package/dist/src/stored-removal.js.map +1 -1
  199. package/dist/src/tool-result-guard.d.ts +12 -1
  200. package/dist/src/tool-result-guard.d.ts.map +1 -1
  201. package/dist/src/tool-result-guard.js +42 -8
  202. package/dist/src/tool-result-guard.js.map +1 -1
  203. package/dist/src/tune-out/coordinator.d.ts +1159 -79
  204. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  205. package/dist/src/tune-out/coordinator.js +3709 -363
  206. package/dist/src/tune-out/coordinator.js.map +1 -1
  207. package/dist/src/tune-out/tools.d.ts +114 -17
  208. package/dist/src/tune-out/tools.d.ts.map +1 -1
  209. package/dist/src/tune-out/tools.js +87 -27
  210. package/dist/src/tune-out/tools.js.map +1 -1
  211. package/dist/src/tune-out/window-anchor.d.ts +143 -0
  212. package/dist/src/tune-out/window-anchor.d.ts.map +1 -0
  213. package/dist/src/tune-out/window-anchor.js +202 -0
  214. package/dist/src/tune-out/window-anchor.js.map +1 -0
  215. package/dist/src/types/agent.d.ts +86 -31
  216. package/dist/src/types/agent.d.ts.map +1 -1
  217. package/dist/src/types/events.d.ts +2 -0
  218. package/dist/src/types/events.d.ts.map +1 -1
  219. package/dist/src/types/framework.d.ts +43 -21
  220. package/dist/src/types/framework.d.ts.map +1 -1
  221. package/dist/src/types/module.d.ts +180 -69
  222. package/dist/src/types/module.d.ts.map +1 -1
  223. package/dist/src/types/trace.d.ts +510 -36
  224. package/dist/src/types/trace.d.ts.map +1 -1
  225. package/package.json +3 -3
  226. package/src/admission/admit.ts +32 -3
  227. package/src/agent.ts +323 -120
  228. package/src/api/mcp-server-core.ts +54 -17
  229. package/src/api/server.ts +4 -23
  230. package/src/code-execution/isolate/scripts.ts +28 -3
  231. package/src/config-checks.ts +14 -0
  232. package/src/context-manager-errors.ts +37 -0
  233. package/src/context-options.ts +96 -0
  234. package/src/deferred-import.ts +239 -0
  235. package/src/dendrite/audience.ts +315 -0
  236. package/src/dendrite/index.ts +14 -2
  237. package/src/dendrite/presets.ts +18 -6
  238. package/src/dendrite/registry.ts +209 -12
  239. package/src/dendrite/types.ts +92 -8
  240. package/src/foreign-rounds.ts +199 -0
  241. package/src/framework.ts +7814 -3585
  242. package/src/gate/event-gate.ts +428 -65
  243. package/src/gate/index.ts +3 -0
  244. package/src/gate/rule-scope.ts +45 -0
  245. package/src/gate/suppress-script-worker.ts +89 -0
  246. package/src/gate/suppress-scripts.ts +414 -0
  247. package/src/gate/suppression-review.ts +517 -0
  248. package/src/gate/suppression-stats.ts +314 -0
  249. package/src/gate/types.ts +141 -7
  250. package/src/gate/wake-onboarding.ts +309 -0
  251. package/src/held-writes.ts +49 -60
  252. package/src/index.ts +9 -2
  253. package/src/jsonrpc-envelope.ts +81 -0
  254. package/src/mcpl/channel-registry.ts +353 -85
  255. package/src/mcpl/checkpoint-manager.ts +3 -2
  256. package/src/mcpl/feature-set-manager.ts +2 -1
  257. package/src/mcpl/inbound-source.ts +2 -1
  258. package/src/mcpl/inference-router.ts +7 -4
  259. package/src/mcpl/push-coalescer.ts +193 -34
  260. package/src/mcpl/push-handler.ts +10 -5
  261. package/src/mcpl/server-connection.ts +141 -60
  262. package/src/mcpl/tool-classes.ts +3 -0
  263. package/src/mcpl/types.ts +8 -2
  264. package/src/module-registry.ts +73 -17
  265. package/src/modules/discord/index.ts +229 -81
  266. package/src/modules/history/index.ts +439 -70
  267. package/src/modules/history/semantic.ts +15 -21
  268. package/src/modules/workspace/disk-agreement.ts +1 -1
  269. package/src/modules/workspace/index.ts +85 -23
  270. package/src/notice-tags.ts +10 -1
  271. package/src/operator-log.ts +36 -3
  272. package/src/presentation.ts +1676 -0
  273. package/src/prose-drafts.ts +16 -12
  274. package/src/read-marks.ts +328 -0
  275. package/src/recovery/offline-branch.ts +346 -32
  276. package/src/recovery/recover-cli.ts +21 -3
  277. package/src/send-tools.ts +40 -7
  278. package/src/stored-injections.ts +2 -2
  279. package/src/stored-removal.ts +31 -7
  280. package/src/tool-result-guard.ts +41 -7
  281. package/src/tune-out/coordinator.ts +4089 -457
  282. package/src/tune-out/tools.ts +160 -43
  283. package/src/tune-out/window-anchor.ts +277 -0
  284. package/src/types/agent.ts +90 -31
  285. package/src/types/events.ts +2 -0
  286. package/src/types/framework.ts +43 -21
  287. package/src/types/module.ts +181 -68
  288. package/src/types/trace.ts +542 -40
  289. package/dist/src/reasoning-loss-notice.d.ts +0 -23
  290. package/dist/src/reasoning-loss-notice.d.ts.map +0 -1
  291. package/dist/src/reasoning-loss-notice.js +0 -52
  292. package/dist/src/reasoning-loss-notice.js.map +0 -1
  293. package/dist/src/reasoning-loss.d.ts +0 -24
  294. package/dist/src/reasoning-loss.d.ts.map +0 -1
  295. package/dist/src/reasoning-loss.js +0 -102
  296. package/dist/src/reasoning-loss.js.map +0 -1
  297. package/src/reasoning-loss-notice.ts +0 -64
  298. package/src/reasoning-loss.ts +0 -120
package/README.md CHANGED
@@ -148,7 +148,7 @@ Each agent has a `ContextManager` (from `@connectome/context-manager`) that main
148
148
  - **PassthroughStrategy** - No compression, raw message replay up to budget
149
149
  - **AutobiographicalStrategy** - Chunks old messages and summarizes them into diary entries, preserving recent context uncompressed
150
150
 
151
- A turn keeps the messages it opened with whole: at a start that opens a turn, the framework pins raw (`pinRange`, named `agent-framework:turn-inputs`) the rows the agent sees that were stored after both the newest of its own messages that it sees and its consumed watermark, starting at the first such row that holds more than tool results, and removes the pin when the turn ends. The pinned rows' tokens count against the budget. If a committing compile refuses as over budget with the pin held, the pin is removed and the compile runs once more, so the turn goes on as it would have without it. A silent heartbeat tick pins nothing, and neither does a strategy without pins.
151
+ A turn keeps the messages it opened with whole: at a start that opens a turn, the framework pins raw (`pinRange`, named `agent-framework:turn-inputs`) the rows of the agent's window (#291) that it sees after both the newest of its own messages there and its consumed watermark, in the window's order, starting at the first such row that holds more than tool results, and removes the pin when the turn ends. Those are the rows presented to it since the mark, a row stored before the mark and presented after it included, and a row presented to it again, also when the mark was taken before its window was written down; a row stored and not yet presented is in neither its window nor the pin. The pinned rows' tokens count against the budget. If a committing compile refuses as over budget with the pin held, the pin is removed and the compile runs once more, so the turn goes on as it would have without it. A silent heartbeat tick pins nothing, and neither does a strategy without pins, or an agent whose configuration sets `turnInputsPin: false`.
152
152
 
153
153
  Before inference, modules and MCPL hooks can inject additional context via `gatherContext()`. An `afterUser` injection is stored in the agent's window, as the message `compile()` would have placed after the last user message, so it stays where the agent saw it: the replies after it keep their thinking, and the cache keeps the turns before it. A source's unchanged content isn't stored again while the copy the agent will read as current has it whole: the one its last request held, or a newer one a start stored whose compile then didn't record (it threw, or the start failed before it); once a fold has summarized it or the strategy's window has passed it, it's stored again, as one more row. Where a changed one lands right after the agent's own latest message, with no one else's message between, `[Continue]` still ends the request, after it. A stored row is history to the strategy, capped, sharded, budgeted and folded like any message. Its metadata carries `system: true`, `kind: 'context-injection'` and `contextInjection: { agent, namespace, contentHash, part, parts }`, which `storedInjectionMarkOf` reads, and every other agent's view leaves it out. A module's injection can set `placedEachCompile: true` to be placed by `compile()` at each start instead, near the end, at the cost of the thinking of every reply after its old place.
154
154
 
@@ -180,10 +180,17 @@ agent-framework-recover \
180
180
  ```
181
181
 
182
182
  The specified Discord message is the last message the agent will still see;
183
- everything after it is left on the old branch. The command scans in bounded
184
- windows, never compiles message content, and activates the new Chronicle
185
- branch. By default the recovery is local to the resident: nothing is posted to
186
- Discord. To let the people involved see that the agent no longer has their
183
+ everything after it is left on the old branch (on a window presented since
184
+ #291, but for the rows stored before the write that presented it, which the
185
+ new branch keeps and the window takes again after that message, and the rows
186
+ that one write presented together with it, which stay after it in the window).
187
+ The command
188
+ scans in bounded windows (on a presented window, a `--messages` count and the
189
+ walk of the rows after the anchor, which the cut returns or keeps, read the
190
+ window whole), never compiles
191
+ message content, and activates the new Chronicle branch. By default the
192
+ recovery is local to the resident: nothing is posted to Discord. To let the
193
+ people involved see that the agent no longer has their
187
194
  messages, choose awareness marks explicitly with `--marks addressed` (removed
188
195
  messages that mentioned or replied to the bot, and DMs) or `--marks all`
189
196
  (every removed Discord message). The output counts what will be marked and
@@ -229,7 +236,9 @@ agent-framework-recover \
229
236
 
230
237
  `--suppress` may be repeated or given a comma-separated list.
231
238
  `--suppress-range <first>..<last>` suppresses the inclusive context interval
232
- between two Discord messages, including intervening agent/tool entries. These
239
+ between two Discord messages, including intervening agent/tool entries: every
240
+ row stored between the two, any agent's, so on a slot residents share, rows
241
+ an agent's window never held too. These
233
242
  removals exist only on the recovery branch; the source branch remains intact.
234
243
  Suppressed Discord messages follow the same `--marks` choice.
235
244
  Selections that split a sharded body group or a tool-use/tool-result exchange
@@ -449,14 +458,15 @@ first.
449
458
 
450
459
  Plain content stays in context and is delivered on arrival through the ordinary
451
460
  channel/push path; the host only remembers where it landed. "Unread" means:
452
- above the agent's consumed watermark (set when the agent is created, and
461
+ above the agent's consumed watermark (a position in the agent's window, #291:
462
+ a row not in the window yet is unread wherever it is in the store; set when the agent is created, and
453
463
  advanced at every compile of a request it sends, which a preview isn't, and at
454
464
  a tool boundary that injects messages into a stream declaring it carries them,
455
465
  as membrane's native path does from 0.6.0), on the current branch, not a
456
466
  sharded message, and not folded into a summary by compression. A stream that
457
467
  doesn't say whether it carries injections is taken as one that doesn't: at a
458
- tool boundary nothing is injected into it, and what's queued waits for the
459
- turn's end. On any doubt — restart, branch switch, eviction — the host
468
+ tool boundary nothing is injected into it, and what arrived for the agent
469
+ waits out of its window for the turn's end. On any doubt — restart, branch switch, eviction — the host
460
470
  appends, as it does today. There is no per-subject cap: a busy channel's unread
461
471
  backlog is simply its unread backlog. Receipts and subject history are kept in
462
472
  the `mcpl/coalescing` state (retry window 1 h); audit lines are
@@ -514,9 +524,150 @@ tool list itself (RFC-014 §8.5 host-made toolsets, §8.1 surface presentation;
514
524
  and works for every server, with or without RFC-014. The `toolsets--` tools
515
525
  are registered for every agent, MCPL or none, unless a module holds the name.
516
526
 
527
+ - **Wake onboarding** (`src/gate/wake-onboarding.ts`). An MCPL server's
528
+ events are often let by, without waking the agent, by a rule written for
529
+ something else (a catch-all with no `source`) or by the gate's default. The
530
+ first such event from a server is followed by a `[wake onboarding]` notice:
531
+ the rule that let it by, and the server's suggested treatment (MCPL RFC-001
532
+ §5), numbered, with each rule's rationale, presented as the claims of a
533
+ server that may not be trustworthy. An event tagged `chat:addressed`,
534
+ `surface:turn` or `surface:alert` wakes the agent to decide.
535
+ `wake_accept_suggestions { server, rules? }` writes the chosen suggestions as
536
+ `suggested:<server>:<n>` rules scoped to that server, ahead of the first
537
+ catch-all; `wake_decline { server }` removes them. Decisions are kept in
538
+ `wake-decisions.json` beside `gate.json`, keyed to the server's declared
539
+ ontology, so the agent is asked again only when it changes (and at most once
540
+ a day per server). `gate_status.catchAll` names the catch-all; `event_tags`
541
+ shows each server's offer. `gate.onboarding: false` turns it off.
542
+
543
+ - **Event suppression** (`EventGate.decideSuppression`, `src/gate/suppress-scripts.ts`,
544
+ `src/gate/suppression-stats.ts`, `src/gate/suppression-review.ts`). A wake
545
+ rule with `suppress: { description, script? }` keeps the events it takes out
546
+ of the agent's context entirely. A rule that only doesn't wake still shows
547
+ its events. A suppressed event is stored in the chronicle as it arrives,
548
+ with `metadata.suppressed = { rule, eventType }`. Every view filter the
549
+ framework sets leaves stamped rows out: the residents', the subconscious's,
550
+ and every view derived from them. The row is stamped for nobody (an empty
551
+ `metadata.audience`), so the presentation index presents it to no window.
552
+ So a suppressed row is never compiled,
553
+ never injected at a tool boundary, never folded into memory, and never
554
+ woken for. It never becomes the speech locus and never brings a clock row
555
+ in ahead of it. The decision is made once, at arrival, before the hold, the
556
+ veto and the gate's evaluate, so no debounce batch forms for the event. The
557
+ suppress rule's `matchCount` counts what it took, and a passthrough rule ahead
558
+ of it counts it too, so a sampler fires on schedule. Because the view reads only the stamp, editing or removing the
559
+ rule changes only what arrives afterwards; the rows already hidden stay
560
+ hidden, which keeps each row's visibility fixed, as context-manager's
561
+ `viewFilter` requires. **Rollback needs a step.** A release without
562
+ suppression doesn't read the stamp. Where compression formed a summary around
563
+ a hidden row, that summary is non-contiguous under such a release's view, and
564
+ context-manager refuses the store at open (`StoreTopologyError`), unless the
565
+ strategy sets `topologyPolicy` or a kv-unified gap flag. Before rolling back,
566
+ with the host stopped, run this release's `agent-framework-recover --store
567
+ <path> --agent <name> --remove-suppressed`: it makes and activates a branch
568
+ without the hidden rows, which such a release opens, and the source branch
569
+ keeps them. That holds unless this release has made a window write of two or
570
+ more rows (the first write-down of a window that holds a row, as at the first
571
+ boot on a store with history, or a presentation of more than one row): the
572
+ store's MANIFEST is then at version 2, which no earlier release opens, and
573
+ only a copy taken before the upgrade goes back (the 291-presentation-mandatory
574
+ changelog entry). Skipped where no summary spans one, the rows render again where
575
+ they were stored (a prompt-cache miss from the first). Suppress rules load as
576
+ `defer` in every release back to 0.22, so nothing wakes for their events.
577
+ Releases 0.22 to 0.26 rewrite gate.json without `suppress` at their first
578
+ rule edit, so rolling back that far and forward again leaves rules that defer
579
+ and no longer suppress.
580
+ - **The rule.** It needs `behavior: "defer"` (or the legacy `"skip"`) written out, so an earlier
581
+ release that doesn't know `suppress` defers those events instead of
582
+ waking on them, a match that narrows it, and a `description` of what it's
583
+ for, which the review checks against. Three kinds of event are never
584
+ suppressed and go on to the next rules: an event addressed to the agent
585
+ (`chat:addressed`), the heartbeat's, and console or API input. A suppress
586
+ rule decides no wake for an event suppression was asked about: `evaluate`
587
+ and `probe` pass over it there, and the rule-order notes and the catch-all
588
+ check pass over it always. Where suppression isn't
589
+ asked, as for an event delivered to a conversation fork's own store, a
590
+ suppress rule defers the events it matches, as its behavior says.
591
+ - **The agent's own logic.** `script` is the source of a function
592
+ `(event, state) => boolean`, called for each event the rule's match takes
593
+ that reaches it (not one an earlier rule decides, an addressed one, or the
594
+ heartbeat's);
595
+ true hides it, and anything else (a truthy string included) lets the event
596
+ on to the rules after it.
597
+ `event` carries the event type, source, channel, author, tags, text,
598
+ arrival time (`at`, ms) and metadata. `state` is the rule's own JSON object
599
+ (at most 64 KB), which the script reads and changes as it likes, so a rule
600
+ can hide repeats, count, or keep a window of its own. The framework keeps
601
+ it between events and across restarts in `suppress-state.json` beside
602
+ gate.json, and starts it afresh when the script changes or the rule is
603
+ removed (not for a new description). Scripts run on one worker thread,
604
+ called synchronously with a 50 ms timeout (`gate.suppressScriptTimeoutMs`), as
605
+ gate.js is: a robustness boundary for the agent's own code, not a security
606
+ sandbox. A script that throws, times out, isn't a function, or leaves a
607
+ state it can't keep lets the event on to the rules after it, as one that
608
+ says show does, keeps its state as it was, and is named in `gate_status`
609
+ (`suppress.scriptStatus`). A timeout restarts the worker, which loads every
610
+ script again one at a time; a script that times out three times in its
611
+ last twenty runs, probes included, isn't run again until its script
612
+ changes or the host restarts, and a worker that fails to start is tried again with a later
613
+ event, later each time. wake_add_rule compiles a
614
+ script on the worker before it saves the rule. `suppressionFor` runs a
615
+ script on a copy of its state, for the probe table; the arrival paths call
616
+ `decideSuppression`, once per event, which keeps the state the script
617
+ leaves. The worker starts with the first rule that has a script.
618
+ - **Covered:** MCPL channel messages and push events (admission; a deferred
619
+ coalesced push is decided once, at its wake, and a suppressed batch is
620
+ stored at once; a batch's row follows its latest occurrence, as its wake
621
+ does, unless the batch holds an addressed occurrence, when it's shown), a module's events (every message its responses add, and
622
+ every wake they ask for, the event decided once whichever module answers
623
+ first), and a server's `[toolsets]` notices, gated as its
624
+ `mcpl:tool-changes` events.
625
+ Not covered: deliveries into a conversation fork's own store, which has no
626
+ view filter.
627
+ - **Tools.** `wake_add_rule { …, suppress: {…} }` adds a suppress rule (saved
628
+ with behavior "defer"), and `wake_remove_rule` removes it. `gate_status`
629
+ shows each suppress rule's settings and how its script has run, and counts
630
+ what it suppressed since start. `suppression_stats { rule?, recent?, since? }`
631
+ reads the stamped rows in the caller's message slot on its current
632
+ branch, so its counts cover every start and follow the branch. Per rule it
633
+ reports the count, the text size, the first and last arrival, a breakdown
634
+ by source and event type, and the newest rows with a one-line preview.
635
+ Rules removed since are listed with `inForce: false`.
636
+ `dump_suppressed { path?, rule?, since?, until?, format? }` writes the
637
+ rows to a workspace file, their text in full and any other block named:
638
+ a transcript, or JSON lines. Times are when each row was stored. At most
639
+ 4 MB; past that, the newest that fit, and the result counts the rest.
640
+ Hosts read the same rows with `AgentFramework.suppressedEvents()`.
641
+ - **Review.** Every `gate.suppressionReview.intervalMs` (two hours by
642
+ default), for each rule that hid events since the last review, a small
643
+ model (`model`, Claude Haiku 5.5 by default, on the reply judge's
644
+ membrane) reads the rule's description, its match and script while it's in
645
+ force (the script cut to 3,000 characters), and a sample of the events it hid: at most
646
+ `maxEventsPerRule` (60) spread across the period, sharing 24,000 characters
647
+ of text, so a short event is read whole and a long one takes what the
648
+ others leave. These bounds are chosen, not measured: they keep one rule's
649
+ request to roughly 8,000 input tokens. It flags any that don't fit the
650
+ description or that the agent would plausibly need to see. The agent gets a `[suppression review]`
651
+ notice naming each rule, what it hid and what was flagged, with the first
652
+ five flagged events of each rule shown, each cut short. A rule the
653
+ reviewer couldn't answer about is reviewed again next time, from where its
654
+ events begin (at most a week back; older events aren't reviewed again). A flag wakes the agent (`wakeOnFlag`, default true), unless it's asleep. With
655
+ `notify: "flagged"` the agent is told only of a flag; with the default,
656
+ `"always"`, after every review in which something was hidden. The notice
657
+ is the framework's own and never suppressed. Progress, retries and each
658
+ rule's last description (noted as the rule hides a row) are kept in
659
+ `suppression-review.json` beside gate.json, written as the review starts,
660
+ so a restart resumes and a removed rule's events are still judged. Its
661
+ calls count toward the agent's usage, as the reply judge's do, and a wake
662
+ on a flag is a full turn of the agent's own model, so a false flag costs
663
+ that turn.
664
+ `gate.suppressionReview: false` turns it off; `AgentFramework.reviewSuppression()`
665
+ runs one now. The `gate:suppression-review` trace records each review.
666
+
517
667
  - **The built-in toolset, `settings`.** The host tools an agent reaches for
518
668
  rarely: `agent_settings`, `wake_add_rule`, `wake_remove_rule`,
519
- `gate_status`, `event_tags`, `set_tool_visibility`, `set_tool_description`,
669
+ `wake_accept_suggestions`, `wake_decline`,
670
+ `gate_status`, `suppression_stats`, `dump_suppressed`, `event_tags`, `set_tool_visibility`, `set_tool_description`,
520
671
  `heartbeat--heartbeat_status`, `heartbeat--heartbeat_trigger`,
521
672
  `workspace--status`, every module utility (`Module.getUtilities`), and a
522
673
  module's tools it places there (`Module.toolPlacement` answering
@@ -691,10 +842,14 @@ Pause the inference thread and MCPL data planes while keeping the framework,
691
842
  context managers, and membrane hot — so compression/refold/quarantine work runs
692
843
  through the live machinery instead of offline scripts (issue #122). Quiesce
693
844
  persists across restarts; `resume` gates on a fresh per-agent feasibility
694
- preview of the current runtime settings (`force` overrides).
845
+ preview of the current runtime settings (`force` overrides). While quiesced, a
846
+ context write (a module event, an API `message.send`) is stored at once, unless
847
+ a surgery's hold or a context manager refusing its work keeps it in memory, and
848
+ enters the agents' windows at `resume`, or, for an agent whose turn is still
849
+ draining then, at that turn's next point (#291).
695
850
 
696
851
  ```typescript
697
- await framework.quiesce({ reason: 'refold', timeoutMs: 120_000, abandon: false }); // throws QuiesceBlockedError if the deferred writes can't reach disk
852
+ await framework.quiesce({ reason: 'refold', timeoutMs: 120_000, abandon: false });
698
853
  await framework.maintenanceTick(); // drain quarantine / advance merges
699
854
  await framework.resume(); // throws ResumeBlockedError if the layout won't compile
700
855
  ```
@@ -715,7 +870,8 @@ for deployments that front the port with a proxy.
715
870
  message and switches to the fork; `suppressMessages(agent, { messageIds })`
716
871
  forks at the head and removes the chosen messages on the fork. The source
717
872
  branch stays intact either way. Removing Discord messages from an agent's
718
- context is local to that agent unless the operator also chooses to mark them:
873
+ context marks nothing on Discord unless the operator also chooses to mark
874
+ them:
719
875
 
720
876
  ```typescript
721
877
  const preview = framework.previewSurgeryMarks('cairn', { rollbackTo: messageId });
@@ -727,6 +883,36 @@ const result = await framework.rollbackToMessage('cairn', {
727
883
  // result.markers: { status: 'none' | 'queued' | 'not-scheduled', ... }
728
884
  ```
729
885
 
886
+ An agent's context follows its own window (#291), so the cut is the write
887
+ that presented the target: a rollback removes only the rows stored after
888
+ that write, and the rows stored before it that the window took after the
889
+ target leave the window (`returnedToArrivals`, on the result and the
890
+ preview). The agent's own rows among them enter it again at its next
891
+ presentation point, the surgery's release; the rest wait outside it until
892
+ the agent's next turn start, so for them the cut holds until the agent
893
+ speaks again, on the rollback's branch: a later move of the store's branch,
894
+ a suppression or rollback through another agent included, ends it. That hold
895
+ is in memory: a restart before then presents them at its pass over every
896
+ agent at rest, or, where it boots quiesced, at the resume. Rows that one write presented together with
897
+ the target stay after it (`keptInWindowAfterTarget`), since no branch cut
898
+ separates them from it: a rollback that only they follow is refused and
899
+ names them, and `suppressMessages` (on the slot's owner, for a row of a slot
900
+ the agent observes, which the refusal names), or, for those with a Discord message id,
901
+ the host's `hide` by it, run on the agent whose own slot holds the row (the
902
+ refusal names it), takes them out. A row holding a result of a call at or
903
+ before the target (a tool boundary presents a round's reply and its results
904
+ in one write) isn't advised for suppression, which would leave the call
905
+ without its result: the refusal says to roll back before the call. The preview's `neverPresented` counts the messages it
906
+ removes that no live agent is shown: no window holds them, or only windows
907
+ whose view leaves them out (a row a tune-out holds); a message that may be in
908
+ a window that couldn't be read isn't counted, and is logged. The host command's
909
+ `/undo n` counts back over the rows of the agent's own slot in its window. A
910
+ removal in place
911
+ (a `hide`, a suppression on its fork, a module's or the coalescer's removal)
912
+ takes the rows out of every other live agent's window on that branch that
913
+ held them too, each at its own place; a window on a branch whose record
914
+ still holds them keeps them.
915
+
730
916
  - **`marks`** is `'none'` (the default), or `{ scope: 'addressed' | 'all', refs? }`.
731
917
  `addressed` covers messages tagged `chat:addressed` (mentions, replies to
732
918
  the bot, DMs). Passing a preview's `refs` binds the choice to exactly that
@@ -878,7 +1064,11 @@ framework.onTrace((event) => {
878
1064
  Trace events are observability-only. They are intended for logs, metrics, UI
879
1065
  updates, and debugging, not framework-internal control flow. Internal lifecycle
880
1066
  code should use state-machine signals or process events instead of consuming
881
- traces, so trace emit order does not become an API contract.
1067
+ traces, so trace emit order does not become an API contract. One exception: the
1068
+ Discord module applies the edits and deletes it kept for a held create on
1069
+ `message:added` (source `surgery-release`), and ends a lost create's record on
1070
+ `message:lost`, so those two traces, emitted as a surgery's release stores a
1071
+ held write or loses it, are a contract.
882
1072
 
883
1073
  Query raw inference logs:
884
1074
 
@@ -22,6 +22,11 @@
22
22
  * gets the same disposition. A reader of the slot (the subconscious, or a
23
23
  * reader fork) sees held traffic through its own view; that is not a
24
24
  * delivery decision of this stage.
25
+ *
26
+ * Suppression is the other disposition: a suppress rule (a gate rule with
27
+ * a `suppress` object) took the event, so it's stored and never rendered, for
28
+ * any reader. It's decided first. A suppressed event is never held, never
29
+ * shown to the gate, never woken for, and never the locus.
25
30
  */
26
31
  export interface InboundEnvelope {
27
32
  /** Which MCPL lane carried it. */
@@ -70,11 +75,24 @@ export interface AdmissionPolicy {
70
75
  evaluate(env: InboundEnvelope): boolean;
71
76
  probe(env: InboundEnvelope): boolean;
72
77
  };
78
+ /**
79
+ * The suppress rule that takes this event, or null; null where the event
80
+ * would land in a view that doesn't hide suppressed rows. Asked once per
81
+ * event, since it commits (a rule's script keeps the state it leaves, the
82
+ * gate's decideSuppression). Left out, nothing is suppressed.
83
+ */
84
+ suppressionFor?(env: InboundEnvelope): string | null;
85
+ }
86
+ /** The record a suppressed event's row carries: the rule that took it. */
87
+ export interface SuppressionRecord {
88
+ rule: string;
73
89
  }
74
90
  export interface AdmissionDecision {
75
91
  recipients: string[];
76
92
  /** Null = delivered into the recipients' view; otherwise held, with the record to stamp. */
77
93
  held: HoldRecord | null;
94
+ /** Null unless a suppress rule took the event: then it's stored, never rendered, and nothing else is decided for it. */
95
+ suppressed: SuppressionRecord | null;
78
96
  /** Whether the recipients may be woken by this event. */
79
97
  wake: boolean;
80
98
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"admit.d.ts","sourceRoot":"","sources":["../../../src/admission/admit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB;qEACiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,oBAAoB,IAAI,MAAM,EAAE,CAAC;IACjC,mDAAmD;IACnD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IAChE;;;;;OAKG;IACH,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;QACxC,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;KACtC,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,4FAA4F;IAC5F,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,yDAAyD;IACzD,IAAI,EAAE,OAAO,CAAC;IACd;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,GAAG,iBAAiB,CAmBtF"}
1
+ {"version":3,"file":"admit.d.ts","sourceRoot":"","sources":["../../../src/admission/admit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB;qEACiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,0EAA0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,oBAAoB,IAAI,MAAM,EAAE,CAAC;IACjC,mDAAmD;IACnD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IAChE;;;;;OAKG;IACH,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;QACxC,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;KACtC,CAAC;IACF;;;;;OAKG;IACH,cAAc,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAAC;CACtD;AAED,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,4FAA4F;IAC5F,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,wHAAwH;IACxH,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACrC,yDAAyD;IACzD,IAAI,EAAE,OAAO,CAAC;IACd;;;;OAIG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,GAAG,iBAAiB,CA6BtF"}
@@ -22,22 +22,35 @@
22
22
  * gets the same disposition. A reader of the slot (the subconscious, or a
23
23
  * reader fork) sees held traffic through its own view; that is not a
24
24
  * delivery decision of this stage.
25
+ *
26
+ * Suppression is the other disposition: a suppress rule (a gate rule with
27
+ * a `suppress` object) took the event, so it's stored and never rendered, for
28
+ * any reader. It's decided first. A suppressed event is never held, never
29
+ * shown to the gate, never woken for, and never the locus.
25
30
  */
26
31
  export function admit(env, policy) {
27
32
  const recipients = env.targetAgents ?? policy.untargetedRecipients();
33
+ // Suppressed: stored where it arrived and never rendered, so nothing
34
+ // downstream acts for anyone. Not held (a reader would see it), not shown
35
+ // to the gate's evaluate (no batch forms; the passthrough rules ahead of its
36
+ // rule have counted it), not a wake, not the locus.
37
+ const rule = policy.suppressionFor?.(env) ?? null;
38
+ if (rule !== null) {
39
+ return { recipients, held: null, suppressed: { rule }, wake: false, gatePass: false, locus: false };
40
+ }
28
41
  const held = env.channelId ? policy.holdFor(env.serverId, env.channelId) : null;
29
42
  if (held) {
30
43
  // Held: nothing downstream may act for the recipients. The gate is only
31
44
  // asked what it would have done — no batch forms, no counter moves.
32
45
  const gatePass = env.vetoed ? false : (policy.gate ? policy.gate.probe(env) : true);
33
- return { recipients, held, wake: false, gatePass, locus: false };
46
+ return { recipients, held, suppressed: null, wake: false, gatePass, locus: false };
34
47
  }
35
48
  if (env.vetoed) {
36
- return { recipients, held: null, wake: false, gatePass: false, locus: true };
49
+ return { recipients, held: null, suppressed: null, wake: false, gatePass: false, locus: true };
37
50
  }
38
51
  // Deliverable: now the gate may take its side effects (a debounce batch
39
52
  // is the gate's own deferred wake and is consumed later by the same rule).
40
53
  const gatePass = policy.gate ? policy.gate.evaluate(env) : true;
41
- return { recipients, held: null, wake: gatePass, gatePass, locus: true };
54
+ return { recipients, held: null, suppressed: null, wake: gatePass, gatePass, locus: true };
42
55
  }
43
56
  //# sourceMappingURL=admit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"admit.js","sourceRoot":"","sources":["../../../src/admission/admit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAqEH,MAAM,UAAU,KAAK,CAAC,GAAoB,EAAE,MAAuB;IACjE,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;IACrE,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEhF,IAAI,IAAI,EAAE,CAAC;QACT,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/E,CAAC;IAED,wEAAwE;IACxE,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"admit.js","sourceRoot":"","sources":["../../../src/admission/admit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAmFH,MAAM,UAAU,KAAK,CAAC,GAAoB,EAAE,MAAuB;IACjE,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;IAErE,qEAAqE;IACrE,0EAA0E;IAC1E,6EAA6E;IAC7E,oDAAoD;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IAClD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACtG,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEhF,IAAI,IAAI,EAAE,CAAC;QACT,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACrF,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACjG,CAAC;IAED,wEAAwE;IACxE,2EAA2E;IAC3E,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7F,CAAC"}