@animalabs/agent-framework 0.22.2 → 0.22.3

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 (935) hide show
  1. package/README.md +3 -1
  2. package/dist/src/agent.d.ts +77 -12
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +136 -40
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/mcp-server-core.js +1 -1
  7. package/dist/src/api/mcp-server-core.js.map +1 -1
  8. package/dist/src/api/server.d.ts.map +1 -1
  9. package/dist/src/api/server.js +5 -1
  10. package/dist/src/api/server.js.map +1 -1
  11. package/dist/src/api/types.d.ts +1 -1
  12. package/dist/src/api/types.d.ts.map +1 -1
  13. package/dist/src/branch-names.d.ts +14 -0
  14. package/dist/src/branch-names.d.ts.map +1 -0
  15. package/dist/src/branch-names.js +22 -0
  16. package/dist/src/branch-names.js.map +1 -0
  17. package/dist/src/closest-names.d.ts +28 -0
  18. package/dist/src/closest-names.d.ts.map +1 -0
  19. package/dist/src/closest-names.js +98 -0
  20. package/dist/src/closest-names.js.map +1 -0
  21. package/dist/src/code-execution/py-runner.d.ts +16 -5
  22. package/dist/src/code-execution/py-runner.d.ts.map +1 -1
  23. package/dist/src/code-execution/py-runner.js +186 -74
  24. package/dist/src/code-execution/py-runner.js.map +1 -1
  25. package/dist/src/code-execution/runtime-py.d.ts.map +1 -1
  26. package/dist/src/code-execution/runtime-py.js +49 -3
  27. package/dist/src/code-execution/runtime-py.js.map +1 -1
  28. package/dist/src/code-execution/tool-definition.d.ts +12 -1
  29. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  30. package/dist/src/code-execution/tool-definition.js +21 -3
  31. package/dist/src/code-execution/tool-definition.js.map +1 -1
  32. package/dist/src/config-checks.d.ts +28 -0
  33. package/dist/src/config-checks.d.ts.map +1 -0
  34. package/dist/src/config-checks.js +52 -0
  35. package/dist/src/config-checks.js.map +1 -0
  36. package/dist/src/deadline-timer.d.ts +21 -0
  37. package/dist/src/deadline-timer.d.ts.map +1 -0
  38. package/dist/src/deadline-timer.js +43 -0
  39. package/dist/src/deadline-timer.js.map +1 -0
  40. package/dist/src/error-message.d.ts +30 -0
  41. package/dist/src/error-message.d.ts.map +1 -0
  42. package/dist/src/error-message.js +50 -0
  43. package/dist/src/error-message.js.map +1 -0
  44. package/dist/src/framework.d.ts +828 -88
  45. package/dist/src/framework.d.ts.map +1 -1
  46. package/dist/src/framework.js +5011 -1326
  47. package/dist/src/framework.js.map +1 -1
  48. package/dist/src/gate/event-gate.d.ts +8 -0
  49. package/dist/src/gate/event-gate.d.ts.map +1 -1
  50. package/dist/src/gate/event-gate.js +27 -3
  51. package/dist/src/gate/event-gate.js.map +1 -1
  52. package/dist/src/index.d.ts +4 -2
  53. package/dist/src/index.d.ts.map +1 -1
  54. package/dist/src/index.js +4 -2
  55. package/dist/src/index.js.map +1 -1
  56. package/dist/src/mcpl/channel-registry.d.ts +144 -6
  57. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  58. package/dist/src/mcpl/channel-registry.js +424 -263
  59. package/dist/src/mcpl/channel-registry.js.map +1 -1
  60. package/dist/src/mcpl/checkpoint-manager.d.ts +21 -1
  61. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  62. package/dist/src/mcpl/checkpoint-manager.js +91 -30
  63. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  64. package/dist/src/mcpl/conversation-router.d.ts +19 -3
  65. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  66. package/dist/src/mcpl/conversation-router.js +23 -8
  67. package/dist/src/mcpl/conversation-router.js.map +1 -1
  68. package/dist/src/mcpl/convert-block.d.ts +20 -0
  69. package/dist/src/mcpl/convert-block.d.ts.map +1 -0
  70. package/dist/src/mcpl/convert-block.js +89 -0
  71. package/dist/src/mcpl/convert-block.js.map +1 -0
  72. package/dist/src/mcpl/errors.d.ts +13 -0
  73. package/dist/src/mcpl/errors.d.ts.map +1 -1
  74. package/dist/src/mcpl/errors.js +28 -0
  75. package/dist/src/mcpl/errors.js.map +1 -1
  76. package/dist/src/mcpl/hook-orchestrator.d.ts +23 -0
  77. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
  78. package/dist/src/mcpl/hook-orchestrator.js +83 -72
  79. package/dist/src/mcpl/hook-orchestrator.js.map +1 -1
  80. package/dist/src/mcpl/inbound-source.d.ts +114 -0
  81. package/dist/src/mcpl/inbound-source.d.ts.map +1 -0
  82. package/dist/src/mcpl/inbound-source.js +83 -0
  83. package/dist/src/mcpl/inbound-source.js.map +1 -0
  84. package/dist/src/mcpl/index.d.ts +3 -1
  85. package/dist/src/mcpl/index.d.ts.map +1 -1
  86. package/dist/src/mcpl/index.js +3 -1
  87. package/dist/src/mcpl/index.js.map +1 -1
  88. package/dist/src/mcpl/inference-router.d.ts +15 -11
  89. package/dist/src/mcpl/inference-router.d.ts.map +1 -1
  90. package/dist/src/mcpl/inference-router.js +153 -84
  91. package/dist/src/mcpl/inference-router.js.map +1 -1
  92. package/dist/src/mcpl/push-coalescer.d.ts +33 -11
  93. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  94. package/dist/src/mcpl/push-coalescer.js +52 -20
  95. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  96. package/dist/src/mcpl/push-handler.d.ts +16 -9
  97. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  98. package/dist/src/mcpl/push-handler.js +18 -83
  99. package/dist/src/mcpl/push-handler.js.map +1 -1
  100. package/dist/src/mcpl/reference-fetcher.d.ts +14 -2
  101. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  102. package/dist/src/mcpl/reference-fetcher.js +72 -30
  103. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  104. package/dist/src/mcpl/references.d.ts +47 -12
  105. package/dist/src/mcpl/references.d.ts.map +1 -1
  106. package/dist/src/mcpl/references.js +74 -21
  107. package/dist/src/mcpl/references.js.map +1 -1
  108. package/dist/src/mcpl/server-connection.d.ts +89 -10
  109. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  110. package/dist/src/mcpl/server-connection.js +405 -129
  111. package/dist/src/mcpl/server-connection.js.map +1 -1
  112. package/dist/src/mcpl/server-registry.d.ts +10 -1
  113. package/dist/src/mcpl/server-registry.d.ts.map +1 -1
  114. package/dist/src/mcpl/server-registry.js +14 -3
  115. package/dist/src/mcpl/server-registry.js.map +1 -1
  116. package/dist/src/mcpl/skip-reply-wake.d.ts +36 -0
  117. package/dist/src/mcpl/skip-reply-wake.d.ts.map +1 -0
  118. package/dist/src/mcpl/skip-reply-wake.js +55 -0
  119. package/dist/src/mcpl/skip-reply-wake.js.map +1 -0
  120. package/dist/src/mcpl/transport.d.ts +51 -2
  121. package/dist/src/mcpl/transport.d.ts.map +1 -1
  122. package/dist/src/mcpl/transport.js +114 -20
  123. package/dist/src/mcpl/transport.js.map +1 -1
  124. package/dist/src/mcpl/types.d.ts +14 -3
  125. package/dist/src/mcpl/types.d.ts.map +1 -1
  126. package/dist/src/mcpl/types.js.map +1 -1
  127. package/dist/src/mcpl/visible-content.d.ts +15 -0
  128. package/dist/src/mcpl/visible-content.d.ts.map +1 -1
  129. package/dist/src/mcpl/visible-content.js +25 -0
  130. package/dist/src/mcpl/visible-content.js.map +1 -1
  131. package/dist/src/module-registry.d.ts +19 -1
  132. package/dist/src/module-registry.d.ts.map +1 -1
  133. package/dist/src/module-registry.js +54 -25
  134. package/dist/src/module-registry.js.map +1 -1
  135. package/dist/src/modules/api/index.js +1 -1
  136. package/dist/src/modules/api/index.js.map +1 -1
  137. package/dist/src/modules/discord/discord-js-client.d.ts +1 -0
  138. package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
  139. package/dist/src/modules/discord/discord-js-client.js +25 -9
  140. package/dist/src/modules/discord/discord-js-client.js.map +1 -1
  141. package/dist/src/modules/discord/index.d.ts +29 -3
  142. package/dist/src/modules/discord/index.d.ts.map +1 -1
  143. package/dist/src/modules/discord/index.js +379 -143
  144. package/dist/src/modules/discord/index.js.map +1 -1
  145. package/dist/src/modules/discord/types.d.ts +14 -1
  146. package/dist/src/modules/discord/types.d.ts.map +1 -1
  147. package/dist/src/modules/health/index.d.ts.map +1 -1
  148. package/dist/src/modules/health/index.js +2 -1
  149. package/dist/src/modules/health/index.js.map +1 -1
  150. package/dist/src/modules/history/index.d.ts +3 -1
  151. package/dist/src/modules/history/index.d.ts.map +1 -1
  152. package/dist/src/modules/history/index.js +359 -127
  153. package/dist/src/modules/history/index.js.map +1 -1
  154. package/dist/src/modules/history/semantic.d.ts +28 -1
  155. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  156. package/dist/src/modules/history/semantic.js +177 -32
  157. package/dist/src/modules/history/semantic.js.map +1 -1
  158. package/dist/src/modules/unknown-tool.d.ts +10 -0
  159. package/dist/src/modules/unknown-tool.d.ts.map +1 -0
  160. package/dist/src/modules/unknown-tool.js +17 -0
  161. package/dist/src/modules/unknown-tool.js.map +1 -0
  162. package/dist/src/modules/workspace/disk-agreement.d.ts +32 -2
  163. package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
  164. package/dist/src/modules/workspace/disk-agreement.js +30 -2
  165. package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
  166. package/dist/src/modules/workspace/effects.d.ts +64 -6
  167. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  168. package/dist/src/modules/workspace/effects.js +291 -44
  169. package/dist/src/modules/workspace/effects.js.map +1 -1
  170. package/dist/src/modules/workspace/index.d.ts +119 -23
  171. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  172. package/dist/src/modules/workspace/index.js +793 -247
  173. package/dist/src/modules/workspace/index.js.map +1 -1
  174. package/dist/src/modules/workspace/observe.d.ts +75 -8
  175. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  176. package/dist/src/modules/workspace/observe.js +174 -14
  177. package/dist/src/modules/workspace/observe.js.map +1 -1
  178. package/dist/src/modules/workspace/reconcile.d.ts +58 -7
  179. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  180. package/dist/src/modules/workspace/reconcile.js +521 -56
  181. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  182. package/dist/src/modules/workspace/types.d.ts +18 -4
  183. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  184. package/dist/src/modules/workspace/types.js.map +1 -1
  185. package/dist/src/modules/workspace/watcher.d.ts +7 -2
  186. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  187. package/dist/src/modules/workspace/watcher.js +28 -4
  188. package/dist/src/modules/workspace/watcher.js.map +1 -1
  189. package/dist/src/prose-drafts.d.ts +240 -0
  190. package/dist/src/prose-drafts.d.ts.map +1 -0
  191. package/dist/src/prose-drafts.js +362 -0
  192. package/dist/src/prose-drafts.js.map +1 -0
  193. package/dist/src/prose-segments.d.ts +21 -2
  194. package/dist/src/prose-segments.d.ts.map +1 -1
  195. package/dist/src/prose-segments.js +46 -9
  196. package/dist/src/prose-segments.js.map +1 -1
  197. package/dist/src/recovery/offline-branch.d.ts +1 -0
  198. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  199. package/dist/src/recovery/offline-branch.js +3 -1
  200. package/dist/src/recovery/offline-branch.js.map +1 -1
  201. package/dist/src/safe-slice.d.ts +5 -1
  202. package/dist/src/safe-slice.d.ts.map +1 -1
  203. package/dist/src/safe-slice.js +9 -1
  204. package/dist/src/safe-slice.js.map +1 -1
  205. package/dist/src/tool-image-ledger.d.ts +87 -19
  206. package/dist/src/tool-image-ledger.d.ts.map +1 -1
  207. package/dist/src/tool-image-ledger.js +135 -32
  208. package/dist/src/tool-image-ledger.js.map +1 -1
  209. package/dist/src/tool-presentation.d.ts +9 -0
  210. package/dist/src/tool-presentation.d.ts.map +1 -1
  211. package/dist/src/tool-presentation.js +257 -60
  212. package/dist/src/tool-presentation.js.map +1 -1
  213. package/dist/src/tool-result-guard.d.ts.map +1 -1
  214. package/dist/src/tool-result-guard.js +7 -10
  215. package/dist/src/tool-result-guard.js.map +1 -1
  216. package/dist/src/tool-result-history.d.ts +32 -3
  217. package/dist/src/tool-result-history.d.ts.map +1 -1
  218. package/dist/src/tool-result-history.js +106 -19
  219. package/dist/src/tool-result-history.js.map +1 -1
  220. package/dist/src/tune-out/coordinator.d.ts +25 -1
  221. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  222. package/dist/src/tune-out/coordinator.js +260 -65
  223. package/dist/src/tune-out/coordinator.js.map +1 -1
  224. package/dist/src/types/agent.d.ts +17 -5
  225. package/dist/src/types/agent.d.ts.map +1 -1
  226. package/dist/src/types/events.d.ts +17 -0
  227. package/dist/src/types/events.d.ts.map +1 -1
  228. package/dist/src/types/framework.d.ts +21 -5
  229. package/dist/src/types/framework.d.ts.map +1 -1
  230. package/dist/src/types/inference-log.d.ts +1 -1
  231. package/dist/src/types/inference-log.d.ts.map +1 -1
  232. package/dist/src/types/module.d.ts +23 -4
  233. package/dist/src/types/module.d.ts.map +1 -1
  234. package/dist/src/types/trace.d.ts +95 -6
  235. package/dist/src/types/trace.d.ts.map +1 -1
  236. package/dist/src/usage/usage-tracker.d.ts +5 -0
  237. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  238. package/dist/src/usage/usage-tracker.js +35 -8
  239. package/dist/src/usage/usage-tracker.js.map +1 -1
  240. package/package.json +3 -4
  241. package/src/agent.ts +162 -40
  242. package/src/api/mcp-server-core.ts +1 -1
  243. package/src/api/server.ts +4 -1
  244. package/src/api/types.ts +1 -1
  245. package/src/branch-names.ts +19 -0
  246. package/src/closest-names.ts +94 -0
  247. package/src/code-execution/py-runner.ts +200 -76
  248. package/src/code-execution/runtime-py.ts +49 -3
  249. package/src/code-execution/tool-definition.ts +28 -4
  250. package/src/config-checks.ts +48 -0
  251. package/src/deadline-timer.ts +44 -0
  252. package/src/error-message.ts +48 -0
  253. package/src/framework.ts +5352 -1388
  254. package/src/gate/event-gate.ts +28 -3
  255. package/src/index.ts +11 -2
  256. package/src/mcpl/channel-registry.ts +517 -286
  257. package/src/mcpl/checkpoint-manager.ts +104 -29
  258. package/src/mcpl/conversation-router.ts +28 -8
  259. package/src/mcpl/convert-block.ts +97 -0
  260. package/src/mcpl/errors.ts +28 -0
  261. package/src/mcpl/hook-orchestrator.ts +84 -77
  262. package/src/mcpl/inbound-source.ts +156 -0
  263. package/src/mcpl/index.ts +10 -1
  264. package/src/mcpl/inference-router.ts +174 -99
  265. package/src/mcpl/push-coalescer.ts +60 -24
  266. package/src/mcpl/push-handler.ts +20 -90
  267. package/src/mcpl/reference-fetcher.ts +71 -26
  268. package/src/mcpl/references.ts +81 -22
  269. package/src/mcpl/server-connection.ts +427 -132
  270. package/src/mcpl/server-registry.ts +15 -4
  271. package/src/mcpl/skip-reply-wake.ts +73 -0
  272. package/src/mcpl/transport.ts +120 -18
  273. package/src/mcpl/types.ts +14 -3
  274. package/src/mcpl/visible-content.ts +27 -0
  275. package/src/module-registry.ts +58 -23
  276. package/src/modules/api/index.ts +1 -1
  277. package/src/modules/discord/discord-js-client.ts +26 -10
  278. package/src/modules/discord/index.ts +391 -158
  279. package/src/modules/discord/types.ts +15 -2
  280. package/src/modules/health/index.ts +2 -1
  281. package/src/modules/history/index.ts +410 -120
  282. package/src/modules/history/semantic.ts +189 -32
  283. package/src/modules/unknown-tool.ts +16 -0
  284. package/src/modules/workspace/disk-agreement.ts +51 -3
  285. package/src/modules/workspace/effects.ts +279 -35
  286. package/src/modules/workspace/index.ts +810 -260
  287. package/src/modules/workspace/observe.ts +194 -20
  288. package/src/modules/workspace/reconcile.ts +619 -64
  289. package/src/modules/workspace/types.ts +18 -4
  290. package/src/modules/workspace/watcher.ts +27 -4
  291. package/src/prose-drafts.ts +481 -0
  292. package/src/prose-segments.ts +51 -8
  293. package/src/recovery/offline-branch.ts +4 -1
  294. package/src/safe-slice.ts +9 -1
  295. package/src/tool-image-ledger.ts +153 -34
  296. package/src/tool-presentation.ts +224 -40
  297. package/src/tool-result-guard.ts +7 -8
  298. package/src/tool-result-history.ts +124 -20
  299. package/src/tune-out/coordinator.ts +259 -65
  300. package/src/types/agent.ts +17 -7
  301. package/src/types/events.ts +17 -0
  302. package/src/types/framework.ts +21 -5
  303. package/src/types/inference-log.ts +1 -1
  304. package/src/types/module.ts +24 -4
  305. package/src/types/trace.ts +101 -6
  306. package/src/usage/usage-tracker.ts +32 -8
  307. package/dist/test/activation-request-sanitize.test.d.ts +0 -2
  308. package/dist/test/activation-request-sanitize.test.d.ts.map +0 -1
  309. package/dist/test/activation-request-sanitize.test.js +0 -89
  310. package/dist/test/activation-request-sanitize.test.js.map +0 -1
  311. package/dist/test/agent-cache-ttl.test.d.ts +0 -2
  312. package/dist/test/agent-cache-ttl.test.d.ts.map +0 -1
  313. package/dist/test/agent-cache-ttl.test.js +0 -41
  314. package/dist/test/agent-cache-ttl.test.js.map +0 -1
  315. package/dist/test/agent-runtime-settings.test.d.ts +0 -2
  316. package/dist/test/agent-runtime-settings.test.d.ts.map +0 -1
  317. package/dist/test/agent-runtime-settings.test.js +0 -1598
  318. package/dist/test/agent-runtime-settings.test.js.map +0 -1
  319. package/dist/test/api-admin-gate.test.d.ts +0 -2
  320. package/dist/test/api-admin-gate.test.d.ts.map +0 -1
  321. package/dist/test/api-admin-gate.test.js +0 -116
  322. package/dist/test/api-admin-gate.test.js.map +0 -1
  323. package/dist/test/assistant-persist-refusal.test.d.ts +0 -2
  324. package/dist/test/assistant-persist-refusal.test.d.ts.map +0 -1
  325. package/dist/test/assistant-persist-refusal.test.js +0 -63
  326. package/dist/test/assistant-persist-refusal.test.js.map +0 -1
  327. package/dist/test/batched-wake-locus.test.d.ts +0 -2
  328. package/dist/test/batched-wake-locus.test.d.ts.map +0 -1
  329. package/dist/test/batched-wake-locus.test.js +0 -166
  330. package/dist/test/batched-wake-locus.test.js.map +0 -1
  331. package/dist/test/busy-agent-scheduler.test.d.ts +0 -2
  332. package/dist/test/busy-agent-scheduler.test.d.ts.map +0 -1
  333. package/dist/test/busy-agent-scheduler.test.js +0 -92
  334. package/dist/test/busy-agent-scheduler.test.js.map +0 -1
  335. package/dist/test/channel-incoming-targeting.test.d.ts +0 -2
  336. package/dist/test/channel-incoming-targeting.test.d.ts.map +0 -1
  337. package/dist/test/channel-incoming-targeting.test.js +0 -81
  338. package/dist/test/channel-incoming-targeting.test.js.map +0 -1
  339. package/dist/test/channel-label-history.test.d.ts +0 -2
  340. package/dist/test/channel-label-history.test.d.ts.map +0 -1
  341. package/dist/test/channel-label-history.test.js +0 -424
  342. package/dist/test/channel-label-history.test.js.map +0 -1
  343. package/dist/test/channel-lifecycle-provenance.test.d.ts +0 -2
  344. package/dist/test/channel-lifecycle-provenance.test.d.ts.map +0 -1
  345. package/dist/test/channel-lifecycle-provenance.test.js +0 -47
  346. package/dist/test/channel-lifecycle-provenance.test.js.map +0 -1
  347. package/dist/test/channel-registry-routing.test.d.ts +0 -2
  348. package/dist/test/channel-registry-routing.test.d.ts.map +0 -1
  349. package/dist/test/channel-registry-routing.test.js +0 -446
  350. package/dist/test/channel-registry-routing.test.js.map +0 -1
  351. package/dist/test/channel-registry-typing.test.d.ts +0 -2
  352. package/dist/test/channel-registry-typing.test.d.ts.map +0 -1
  353. package/dist/test/channel-registry-typing.test.js +0 -91
  354. package/dist/test/channel-registry-typing.test.js.map +0 -1
  355. package/dist/test/channels-changed-respond-first.test.d.ts +0 -2
  356. package/dist/test/channels-changed-respond-first.test.d.ts.map +0 -1
  357. package/dist/test/channels-changed-respond-first.test.js +0 -74
  358. package/dist/test/channels-changed-respond-first.test.js.map +0 -1
  359. package/dist/test/checkpoint-attribution.test.d.ts +0 -2
  360. package/dist/test/checkpoint-attribution.test.d.ts.map +0 -1
  361. package/dist/test/checkpoint-attribution.test.js +0 -200
  362. package/dist/test/checkpoint-attribution.test.js.map +0 -1
  363. package/dist/test/code-execution.test.d.ts +0 -11
  364. package/dist/test/code-execution.test.d.ts.map +0 -1
  365. package/dist/test/code-execution.test.js +0 -1272
  366. package/dist/test/code-execution.test.js.map +0 -1
  367. package/dist/test/component-defaults.test.d.ts +0 -2
  368. package/dist/test/component-defaults.test.d.ts.map +0 -1
  369. package/dist/test/component-defaults.test.js +0 -54
  370. package/dist/test/component-defaults.test.js.map +0 -1
  371. package/dist/test/conversation-fork-injection-scoping.test.d.ts +0 -2
  372. package/dist/test/conversation-fork-injection-scoping.test.d.ts.map +0 -1
  373. package/dist/test/conversation-fork-injection-scoping.test.js +0 -200
  374. package/dist/test/conversation-fork-injection-scoping.test.js.map +0 -1
  375. package/dist/test/conversation-router.test.d.ts +0 -2
  376. package/dist/test/conversation-router.test.d.ts.map +0 -1
  377. package/dist/test/conversation-router.test.js +0 -174
  378. package/dist/test/conversation-router.test.js.map +0 -1
  379. package/dist/test/conversation-routing.test.d.ts +0 -7
  380. package/dist/test/conversation-routing.test.d.ts.map +0 -1
  381. package/dist/test/conversation-routing.test.js +0 -621
  382. package/dist/test/conversation-routing.test.js.map +0 -1
  383. package/dist/test/deferred-wake-integrity.test.d.ts +0 -29
  384. package/dist/test/deferred-wake-integrity.test.d.ts.map +0 -1
  385. package/dist/test/deferred-wake-integrity.test.js +0 -320
  386. package/dist/test/deferred-wake-integrity.test.js.map +0 -1
  387. package/dist/test/discord-awareness-outbox.test.d.ts +0 -2
  388. package/dist/test/discord-awareness-outbox.test.d.ts.map +0 -1
  389. package/dist/test/discord-awareness-outbox.test.js +0 -371
  390. package/dist/test/discord-awareness-outbox.test.js.map +0 -1
  391. package/dist/test/discord-history-delete-window.test.d.ts +0 -2
  392. package/dist/test/discord-history-delete-window.test.d.ts.map +0 -1
  393. package/dist/test/discord-history-delete-window.test.js +0 -81
  394. package/dist/test/discord-history-delete-window.test.js.map +0 -1
  395. package/dist/test/discord-history-sync.test.d.ts +0 -2
  396. package/dist/test/discord-history-sync.test.d.ts.map +0 -1
  397. package/dist/test/discord-history-sync.test.js +0 -56
  398. package/dist/test/discord-history-sync.test.js.map +0 -1
  399. package/dist/test/discord-typing-keepalive.test.d.ts +0 -2
  400. package/dist/test/discord-typing-keepalive.test.d.ts.map +0 -1
  401. package/dist/test/discord-typing-keepalive.test.js +0 -77
  402. package/dist/test/discord-typing-keepalive.test.js.map +0 -1
  403. package/dist/test/ephemeral-settle.test.d.ts +0 -2
  404. package/dist/test/ephemeral-settle.test.d.ts.map +0 -1
  405. package/dist/test/ephemeral-settle.test.js +0 -354
  406. package/dist/test/ephemeral-settle.test.js.map +0 -1
  407. package/dist/test/event-gate-passthrough.test.d.ts +0 -15
  408. package/dist/test/event-gate-passthrough.test.d.ts.map +0 -1
  409. package/dist/test/event-gate-passthrough.test.js +0 -289
  410. package/dist/test/event-gate-passthrough.test.js.map +0 -1
  411. package/dist/test/event-gate-policy-mutation.test.d.ts +0 -2
  412. package/dist/test/event-gate-policy-mutation.test.d.ts.map +0 -1
  413. package/dist/test/event-gate-policy-mutation.test.js +0 -137
  414. package/dist/test/event-gate-policy-mutation.test.js.map +0 -1
  415. package/dist/test/event-gate-rate-limit.test.d.ts +0 -2
  416. package/dist/test/event-gate-rate-limit.test.d.ts.map +0 -1
  417. package/dist/test/event-gate-rate-limit.test.js +0 -627
  418. package/dist/test/event-gate-rate-limit.test.js.map +0 -1
  419. package/dist/test/event-gate-script.test.d.ts +0 -2
  420. package/dist/test/event-gate-script.test.d.ts.map +0 -1
  421. package/dist/test/event-gate-script.test.js +0 -95
  422. package/dist/test/event-gate-script.test.js.map +0 -1
  423. package/dist/test/event-gate-selfwake.test.d.ts +0 -15
  424. package/dist/test/event-gate-selfwake.test.d.ts.map +0 -1
  425. package/dist/test/event-gate-selfwake.test.js +0 -125
  426. package/dist/test/event-gate-selfwake.test.js.map +0 -1
  427. package/dist/test/event-gate-tags.test.d.ts +0 -2
  428. package/dist/test/event-gate-tags.test.d.ts.map +0 -1
  429. package/dist/test/event-gate-tags.test.js +0 -76
  430. package/dist/test/event-gate-tags.test.js.map +0 -1
  431. package/dist/test/event-gate.test.d.ts +0 -2
  432. package/dist/test/event-gate.test.d.ts.map +0 -1
  433. package/dist/test/event-gate.test.js +0 -919
  434. package/dist/test/event-gate.test.js.map +0 -1
  435. package/dist/test/explicit-prose-routing.test.d.ts +0 -11
  436. package/dist/test/explicit-prose-routing.test.d.ts.map +0 -1
  437. package/dist/test/explicit-prose-routing.test.js +0 -1715
  438. package/dist/test/explicit-prose-routing.test.js.map +0 -1
  439. package/dist/test/framework.test.d.ts +0 -5
  440. package/dist/test/framework.test.d.ts.map +0 -1
  441. package/dist/test/framework.test.js +0 -1048
  442. package/dist/test/framework.test.js.map +0 -1
  443. package/dist/test/gather-context-timeout.test.d.ts +0 -2
  444. package/dist/test/gather-context-timeout.test.d.ts.map +0 -1
  445. package/dist/test/gather-context-timeout.test.js +0 -120
  446. package/dist/test/gather-context-timeout.test.js.map +0 -1
  447. package/dist/test/health-snapshot.test.d.ts +0 -2
  448. package/dist/test/health-snapshot.test.d.ts.map +0 -1
  449. package/dist/test/health-snapshot.test.js +0 -74
  450. package/dist/test/health-snapshot.test.js.map +0 -1
  451. package/dist/test/helpers/coalescing-fixture.d.ts +0 -74
  452. package/dist/test/helpers/coalescing-fixture.d.ts.map +0 -1
  453. package/dist/test/helpers/coalescing-fixture.js +0 -152
  454. package/dist/test/helpers/coalescing-fixture.js.map +0 -1
  455. package/dist/test/helpers/coalescing-kill-child.d.ts +0 -2
  456. package/dist/test/helpers/coalescing-kill-child.d.ts.map +0 -1
  457. package/dist/test/helpers/coalescing-kill-child.js +0 -24
  458. package/dist/test/helpers/coalescing-kill-child.js.map +0 -1
  459. package/dist/test/helpers/mock-membrane.d.ts +0 -53
  460. package/dist/test/helpers/mock-membrane.d.ts.map +0 -1
  461. package/dist/test/helpers/mock-membrane.js +0 -168
  462. package/dist/test/helpers/mock-membrane.js.map +0 -1
  463. package/dist/test/helpers/pytc-stop-rows.d.ts +0 -11
  464. package/dist/test/helpers/pytc-stop-rows.d.ts.map +0 -1
  465. package/dist/test/helpers/pytc-stop-rows.js +0 -143
  466. package/dist/test/helpers/pytc-stop-rows.js.map +0 -1
  467. package/dist/test/helpers/quiesce-crash-child.d.ts +0 -2
  468. package/dist/test/helpers/quiesce-crash-child.d.ts.map +0 -1
  469. package/dist/test/helpers/quiesce-crash-child.js +0 -156
  470. package/dist/test/helpers/quiesce-crash-child.js.map +0 -1
  471. package/dist/test/hide-then-turn.test.d.ts +0 -2
  472. package/dist/test/hide-then-turn.test.d.ts.map +0 -1
  473. package/dist/test/hide-then-turn.test.js +0 -101
  474. package/dist/test/hide-then-turn.test.js.map +0 -1
  475. package/dist/test/history-module-overview.test.d.ts +0 -2
  476. package/dist/test/history-module-overview.test.d.ts.map +0 -1
  477. package/dist/test/history-module-overview.test.js +0 -711
  478. package/dist/test/history-module-overview.test.js.map +0 -1
  479. package/dist/test/history-module-realstore.test.d.ts +0 -2
  480. package/dist/test/history-module-realstore.test.d.ts.map +0 -1
  481. package/dist/test/history-module-realstore.test.js +0 -363
  482. package/dist/test/history-module-realstore.test.js.map +0 -1
  483. package/dist/test/history-module-semantic.test.d.ts +0 -2
  484. package/dist/test/history-module-semantic.test.d.ts.map +0 -1
  485. package/dist/test/history-module-semantic.test.js +0 -213
  486. package/dist/test/history-module-semantic.test.js.map +0 -1
  487. package/dist/test/history-module-ux.test.d.ts +0 -2
  488. package/dist/test/history-module-ux.test.d.ts.map +0 -1
  489. package/dist/test/history-module-ux.test.js +0 -304
  490. package/dist/test/history-module-ux.test.js.map +0 -1
  491. package/dist/test/history-module.test.d.ts +0 -2
  492. package/dist/test/history-module.test.d.ts.map +0 -1
  493. package/dist/test/history-module.test.js +0 -619
  494. package/dist/test/history-module.test.js.map +0 -1
  495. package/dist/test/history-semantic-review-findings.test.d.ts +0 -2
  496. package/dist/test/history-semantic-review-findings.test.d.ts.map +0 -1
  497. package/dist/test/history-semantic-review-findings.test.js +0 -338
  498. package/dist/test/history-semantic-review-findings.test.js.map +0 -1
  499. package/dist/test/history-semantic-sync-converges.test.d.ts +0 -2
  500. package/dist/test/history-semantic-sync-converges.test.d.ts.map +0 -1
  501. package/dist/test/history-semantic-sync-converges.test.js +0 -109
  502. package/dist/test/history-semantic-sync-converges.test.js.map +0 -1
  503. package/dist/test/host-quiesce.test.d.ts +0 -2
  504. package/dist/test/host-quiesce.test.d.ts.map +0 -1
  505. package/dist/test/host-quiesce.test.js +0 -988
  506. package/dist/test/host-quiesce.test.js.map +0 -1
  507. package/dist/test/inference-exhaustion-rewind.test.d.ts +0 -2
  508. package/dist/test/inference-exhaustion-rewind.test.d.ts.map +0 -1
  509. package/dist/test/inference-exhaustion-rewind.test.js +0 -387
  510. package/dist/test/inference-exhaustion-rewind.test.js.map +0 -1
  511. package/dist/test/inference-failure-bounds.test.d.ts +0 -2
  512. package/dist/test/inference-failure-bounds.test.d.ts.map +0 -1
  513. package/dist/test/inference-failure-bounds.test.js +0 -1202
  514. package/dist/test/inference-failure-bounds.test.js.map +0 -1
  515. package/dist/test/inference-failure-observability.test.d.ts +0 -2
  516. package/dist/test/inference-failure-observability.test.d.ts.map +0 -1
  517. package/dist/test/inference-failure-observability.test.js +0 -84
  518. package/dist/test/inference-failure-observability.test.js.map +0 -1
  519. package/dist/test/journal-tool.test.d.ts +0 -2
  520. package/dist/test/journal-tool.test.d.ts.map +0 -1
  521. package/dist/test/journal-tool.test.js +0 -33
  522. package/dist/test/journal-tool.test.js.map +0 -1
  523. package/dist/test/kv-unified-open-flight-retry.test.d.ts +0 -2
  524. package/dist/test/kv-unified-open-flight-retry.test.d.ts.map +0 -1
  525. package/dist/test/kv-unified-open-flight-retry.test.js +0 -189
  526. package/dist/test/kv-unified-open-flight-retry.test.js.map +0 -1
  527. package/dist/test/kv-unified-wiring.test.d.ts +0 -2
  528. package/dist/test/kv-unified-wiring.test.d.ts.map +0 -1
  529. package/dist/test/kv-unified-wiring.test.js +0 -95
  530. package/dist/test/kv-unified-wiring.test.js.map +0 -1
  531. package/dist/test/late-events-after-stop.test.d.ts +0 -2
  532. package/dist/test/late-events-after-stop.test.d.ts.map +0 -1
  533. package/dist/test/late-events-after-stop.test.js +0 -122
  534. package/dist/test/late-events-after-stop.test.js.map +0 -1
  535. package/dist/test/liveness-watchdog.test.d.ts +0 -2
  536. package/dist/test/liveness-watchdog.test.d.ts.map +0 -1
  537. package/dist/test/liveness-watchdog.test.js +0 -94
  538. package/dist/test/liveness-watchdog.test.js.map +0 -1
  539. package/dist/test/machine-close-provenance.test.d.ts +0 -2
  540. package/dist/test/machine-close-provenance.test.d.ts.map +0 -1
  541. package/dist/test/machine-close-provenance.test.js +0 -116
  542. package/dist/test/machine-close-provenance.test.js.map +0 -1
  543. package/dist/test/maintenance-timer.test.d.ts +0 -2
  544. package/dist/test/maintenance-timer.test.d.ts.map +0 -1
  545. package/dist/test/maintenance-timer.test.js +0 -1827
  546. package/dist/test/maintenance-timer.test.js.map +0 -1
  547. package/dist/test/mcp-server-bin.test.d.ts +0 -2
  548. package/dist/test/mcp-server-bin.test.d.ts.map +0 -1
  549. package/dist/test/mcp-server-bin.test.js +0 -142
  550. package/dist/test/mcp-server-bin.test.js.map +0 -1
  551. package/dist/test/mcpl-access-provider.test.d.ts +0 -2
  552. package/dist/test/mcpl-access-provider.test.d.ts.map +0 -1
  553. package/dist/test/mcpl-access-provider.test.js +0 -20
  554. package/dist/test/mcpl-access-provider.test.js.map +0 -1
  555. package/dist/test/mcpl-awareness-barrier.test.d.ts +0 -2
  556. package/dist/test/mcpl-awareness-barrier.test.d.ts.map +0 -1
  557. package/dist/test/mcpl-awareness-barrier.test.js +0 -769
  558. package/dist/test/mcpl-awareness-barrier.test.js.map +0 -1
  559. package/dist/test/mcpl-capability-grant.test.d.ts +0 -10
  560. package/dist/test/mcpl-capability-grant.test.d.ts.map +0 -1
  561. package/dist/test/mcpl-capability-grant.test.js +0 -111
  562. package/dist/test/mcpl-capability-grant.test.js.map +0 -1
  563. package/dist/test/mcpl-capability-scoping.test.d.ts +0 -2
  564. package/dist/test/mcpl-capability-scoping.test.d.ts.map +0 -1
  565. package/dist/test/mcpl-capability-scoping.test.js +0 -266
  566. package/dist/test/mcpl-capability-scoping.test.js.map +0 -1
  567. package/dist/test/mcpl-child-env.test.d.ts +0 -2
  568. package/dist/test/mcpl-child-env.test.d.ts.map +0 -1
  569. package/dist/test/mcpl-child-env.test.js +0 -158
  570. package/dist/test/mcpl-child-env.test.js.map +0 -1
  571. package/dist/test/mcpl-coalesced-content-parity.test.d.ts +0 -2
  572. package/dist/test/mcpl-coalesced-content-parity.test.d.ts.map +0 -1
  573. package/dist/test/mcpl-coalesced-content-parity.test.js +0 -532
  574. package/dist/test/mcpl-coalesced-content-parity.test.js.map +0 -1
  575. package/dist/test/mcpl-coalescing.test.d.ts +0 -2
  576. package/dist/test/mcpl-coalescing.test.d.ts.map +0 -1
  577. package/dist/test/mcpl-coalescing.test.js +0 -1125
  578. package/dist/test/mcpl-coalescing.test.js.map +0 -1
  579. package/dist/test/mcpl-config-diagnostics.test.d.ts +0 -2
  580. package/dist/test/mcpl-config-diagnostics.test.d.ts.map +0 -1
  581. package/dist/test/mcpl-config-diagnostics.test.js +0 -452
  582. package/dist/test/mcpl-config-diagnostics.test.js.map +0 -1
  583. package/dist/test/mcpl-empty-content.test.d.ts +0 -2
  584. package/dist/test/mcpl-empty-content.test.d.ts.map +0 -1
  585. package/dist/test/mcpl-empty-content.test.js +0 -368
  586. package/dist/test/mcpl-empty-content.test.js.map +0 -1
  587. package/dist/test/mcpl-gate-roundtrip.test.d.ts +0 -2
  588. package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +0 -1
  589. package/dist/test/mcpl-gate-roundtrip.test.js +0 -285
  590. package/dist/test/mcpl-gate-roundtrip.test.js.map +0 -1
  591. package/dist/test/mcpl-list-status.test.d.ts +0 -2
  592. package/dist/test/mcpl-list-status.test.d.ts.map +0 -1
  593. package/dist/test/mcpl-list-status.test.js +0 -82
  594. package/dist/test/mcpl-list-status.test.js.map +0 -1
  595. package/dist/test/mcpl-manifest-changed.test.d.ts +0 -2
  596. package/dist/test/mcpl-manifest-changed.test.d.ts.map +0 -1
  597. package/dist/test/mcpl-manifest-changed.test.js +0 -178
  598. package/dist/test/mcpl-manifest-changed.test.js.map +0 -1
  599. package/dist/test/mcpl-push-convert.test.d.ts +0 -2
  600. package/dist/test/mcpl-push-convert.test.d.ts.map +0 -1
  601. package/dist/test/mcpl-push-convert.test.js +0 -42
  602. package/dist/test/mcpl-push-convert.test.js.map +0 -1
  603. package/dist/test/mcpl-reconnect-events.test.d.ts +0 -2
  604. package/dist/test/mcpl-reconnect-events.test.d.ts.map +0 -1
  605. package/dist/test/mcpl-reconnect-events.test.js +0 -144
  606. package/dist/test/mcpl-reconnect-events.test.js.map +0 -1
  607. package/dist/test/mcpl-reconnect-reregistration.test.d.ts +0 -2
  608. package/dist/test/mcpl-reconnect-reregistration.test.d.ts.map +0 -1
  609. package/dist/test/mcpl-reconnect-reregistration.test.js +0 -238
  610. package/dist/test/mcpl-reconnect-reregistration.test.js.map +0 -1
  611. package/dist/test/mcpl-reference-fetcher.test.d.ts +0 -2
  612. package/dist/test/mcpl-reference-fetcher.test.d.ts.map +0 -1
  613. package/dist/test/mcpl-reference-fetcher.test.js +0 -427
  614. package/dist/test/mcpl-reference-fetcher.test.js.map +0 -1
  615. package/dist/test/mcpl-reference-fields.test.d.ts +0 -2
  616. package/dist/test/mcpl-reference-fields.test.d.ts.map +0 -1
  617. package/dist/test/mcpl-reference-fields.test.js +0 -149
  618. package/dist/test/mcpl-reference-fields.test.js.map +0 -1
  619. package/dist/test/mcpl-rejection-log-lines.test.d.ts +0 -2
  620. package/dist/test/mcpl-rejection-log-lines.test.d.ts.map +0 -1
  621. package/dist/test/mcpl-rejection-log-lines.test.js +0 -349
  622. package/dist/test/mcpl-rejection-log-lines.test.js.map +0 -1
  623. package/dist/test/mcpl-request-timeout.test.d.ts +0 -2
  624. package/dist/test/mcpl-request-timeout.test.d.ts.map +0 -1
  625. package/dist/test/mcpl-request-timeout.test.js +0 -138
  626. package/dist/test/mcpl-request-timeout.test.js.map +0 -1
  627. package/dist/test/mcpl-runtime-lifecycle.test.d.ts +0 -7
  628. package/dist/test/mcpl-runtime-lifecycle.test.d.ts.map +0 -1
  629. package/dist/test/mcpl-runtime-lifecycle.test.js +0 -142
  630. package/dist/test/mcpl-runtime-lifecycle.test.js.map +0 -1
  631. package/dist/test/mcpl-stderr-tail.test.d.ts +0 -2
  632. package/dist/test/mcpl-stderr-tail.test.d.ts.map +0 -1
  633. package/dist/test/mcpl-stderr-tail.test.js +0 -210
  634. package/dist/test/mcpl-stderr-tail.test.js.map +0 -1
  635. package/dist/test/mcpl-tool-class-listing.test.d.ts +0 -2
  636. package/dist/test/mcpl-tool-class-listing.test.d.ts.map +0 -1
  637. package/dist/test/mcpl-tool-class-listing.test.js +0 -147
  638. package/dist/test/mcpl-tool-class-listing.test.js.map +0 -1
  639. package/dist/test/mcpl-tool-classes.test.d.ts +0 -7
  640. package/dist/test/mcpl-tool-classes.test.d.ts.map +0 -1
  641. package/dist/test/mcpl-tool-classes.test.js +0 -80
  642. package/dist/test/mcpl-tool-classes.test.js.map +0 -1
  643. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +0 -2
  644. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +0 -1
  645. package/dist/test/mcpl-tool-lifecycle-e2e.test.js +0 -237
  646. package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +0 -1
  647. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +0 -11
  648. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +0 -1
  649. package/dist/test/mcpl-tool-lifecycle-emitter.test.js +0 -412
  650. package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +0 -1
  651. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts +0 -2
  652. package/dist/test/mcpl-tool-lifecycle-script.test.d.ts.map +0 -1
  653. package/dist/test/mcpl-tool-lifecycle-script.test.js +0 -288
  654. package/dist/test/mcpl-tool-lifecycle-script.test.js.map +0 -1
  655. package/dist/test/mcpl-tool-lifecycle.test.d.ts +0 -11
  656. package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +0 -1
  657. package/dist/test/mcpl-tool-lifecycle.test.js +0 -270
  658. package/dist/test/mcpl-tool-lifecycle.test.js.map +0 -1
  659. package/dist/test/mcpl-transport-close.test.d.ts +0 -2
  660. package/dist/test/mcpl-transport-close.test.d.ts.map +0 -1
  661. package/dist/test/mcpl-transport-close.test.js +0 -373
  662. package/dist/test/mcpl-transport-close.test.js.map +0 -1
  663. package/dist/test/mcpl-transport-spawn.test.d.ts +0 -2
  664. package/dist/test/mcpl-transport-spawn.test.d.ts.map +0 -1
  665. package/dist/test/mcpl-transport-spawn.test.js +0 -58
  666. package/dist/test/mcpl-transport-spawn.test.js.map +0 -1
  667. package/dist/test/mcpl-ws-transport.test.d.ts +0 -2
  668. package/dist/test/mcpl-ws-transport.test.d.ts.map +0 -1
  669. package/dist/test/mcpl-ws-transport.test.js +0 -259
  670. package/dist/test/mcpl-ws-transport.test.js.map +0 -1
  671. package/dist/test/module-context-integration.test.d.ts +0 -18
  672. package/dist/test/module-context-integration.test.d.ts.map +0 -1
  673. package/dist/test/module-context-integration.test.js +0 -181
  674. package/dist/test/module-context-integration.test.js.map +0 -1
  675. package/dist/test/offline-recovery-branch.test.d.ts +0 -2
  676. package/dist/test/offline-recovery-branch.test.d.ts.map +0 -1
  677. package/dist/test/offline-recovery-branch.test.js +0 -570
  678. package/dist/test/offline-recovery-branch.test.js.map +0 -1
  679. package/dist/test/operator-surgery.test.d.ts +0 -2
  680. package/dist/test/operator-surgery.test.d.ts.map +0 -1
  681. package/dist/test/operator-surgery.test.js +0 -595
  682. package/dist/test/operator-surgery.test.js.map +0 -1
  683. package/dist/test/ops-alert.test.d.ts +0 -2
  684. package/dist/test/ops-alert.test.d.ts.map +0 -1
  685. package/dist/test/ops-alert.test.js +0 -153
  686. package/dist/test/ops-alert.test.js.map +0 -1
  687. package/dist/test/overbudget-drain-breaker.test.d.ts +0 -2
  688. package/dist/test/overbudget-drain-breaker.test.d.ts.map +0 -1
  689. package/dist/test/overbudget-drain-breaker.test.js +0 -198
  690. package/dist/test/overbudget-drain-breaker.test.js.map +0 -1
  691. package/dist/test/pack-installs-alone.test.d.ts +0 -2
  692. package/dist/test/pack-installs-alone.test.d.ts.map +0 -1
  693. package/dist/test/pack-installs-alone.test.js +0 -284
  694. package/dist/test/pack-installs-alone.test.js.map +0 -1
  695. package/dist/test/per-agent-delivery.test.d.ts +0 -2
  696. package/dist/test/per-agent-delivery.test.d.ts.map +0 -1
  697. package/dist/test/per-agent-delivery.test.js +0 -108
  698. package/dist/test/per-agent-delivery.test.js.map +0 -1
  699. package/dist/test/physical-window-restart.test.d.ts +0 -16
  700. package/dist/test/physical-window-restart.test.d.ts.map +0 -1
  701. package/dist/test/physical-window-restart.test.js +0 -487
  702. package/dist/test/physical-window-restart.test.js.map +0 -1
  703. package/dist/test/placed-reaction-baseline.test.d.ts +0 -2
  704. package/dist/test/placed-reaction-baseline.test.d.ts.map +0 -1
  705. package/dist/test/placed-reaction-baseline.test.js +0 -312
  706. package/dist/test/placed-reaction-baseline.test.js.map +0 -1
  707. package/dist/test/present-while-acting.test.d.ts +0 -19
  708. package/dist/test/present-while-acting.test.d.ts.map +0 -1
  709. package/dist/test/present-while-acting.test.js +0 -1649
  710. package/dist/test/present-while-acting.test.js.map +0 -1
  711. package/dist/test/prose-segments.test.d.ts +0 -2
  712. package/dist/test/prose-segments.test.d.ts.map +0 -1
  713. package/dist/test/prose-segments.test.js +0 -52
  714. package/dist/test/prose-segments.test.js.map +0 -1
  715. package/dist/test/prose-stream-router.test.d.ts +0 -2
  716. package/dist/test/prose-stream-router.test.d.ts.map +0 -1
  717. package/dist/test/prose-stream-router.test.js +0 -171
  718. package/dist/test/prose-stream-router.test.js.map +0 -1
  719. package/dist/test/provider-acceleration-cooldown.test.d.ts +0 -2
  720. package/dist/test/provider-acceleration-cooldown.test.d.ts.map +0 -1
  721. package/dist/test/provider-acceleration-cooldown.test.js +0 -435
  722. package/dist/test/provider-acceleration-cooldown.test.js.map +0 -1
  723. package/dist/test/provider-waits.test.d.ts +0 -2
  724. package/dist/test/provider-waits.test.d.ts.map +0 -1
  725. package/dist/test/provider-waits.test.js +0 -2259
  726. package/dist/test/provider-waits.test.js.map +0 -1
  727. package/dist/test/puppet-tool-call.test.d.ts +0 -2
  728. package/dist/test/puppet-tool-call.test.d.ts.map +0 -1
  729. package/dist/test/puppet-tool-call.test.js +0 -226
  730. package/dist/test/puppet-tool-call.test.js.map +0 -1
  731. package/dist/test/puppet-turn-reservation.test.d.ts +0 -2
  732. package/dist/test/puppet-turn-reservation.test.d.ts.map +0 -1
  733. package/dist/test/puppet-turn-reservation.test.js +0 -139
  734. package/dist/test/puppet-turn-reservation.test.js.map +0 -1
  735. package/dist/test/reaction-baseline-platform.test.d.ts +0 -2
  736. package/dist/test/reaction-baseline-platform.test.d.ts.map +0 -1
  737. package/dist/test/reaction-baseline-platform.test.js +0 -124
  738. package/dist/test/reaction-baseline-platform.test.js.map +0 -1
  739. package/dist/test/record-journal.test.d.ts +0 -6
  740. package/dist/test/record-journal.test.d.ts.map +0 -1
  741. package/dist/test/record-journal.test.js +0 -269
  742. package/dist/test/record-journal.test.js.map +0 -1
  743. package/dist/test/refusal-reaction-baseline.test.d.ts +0 -2
  744. package/dist/test/refusal-reaction-baseline.test.d.ts.map +0 -1
  745. package/dist/test/refusal-reaction-baseline.test.js +0 -81
  746. package/dist/test/refusal-reaction-baseline.test.js.map +0 -1
  747. package/dist/test/refusal-rewind.test.d.ts +0 -2
  748. package/dist/test/refusal-rewind.test.d.ts.map +0 -1
  749. package/dist/test/refusal-rewind.test.js +0 -117
  750. package/dist/test/refusal-rewind.test.js.map +0 -1
  751. package/dist/test/refusal-single-call.test.d.ts +0 -2
  752. package/dist/test/refusal-single-call.test.d.ts.map +0 -1
  753. package/dist/test/refusal-single-call.test.js +0 -177
  754. package/dist/test/refusal-single-call.test.js.map +0 -1
  755. package/dist/test/release-bump.test.d.ts +0 -2
  756. package/dist/test/release-bump.test.d.ts.map +0 -1
  757. package/dist/test/release-bump.test.js +0 -248
  758. package/dist/test/release-bump.test.js.map +0 -1
  759. package/dist/test/release-changelog.test.d.ts +0 -2
  760. package/dist/test/release-changelog.test.d.ts.map +0 -1
  761. package/dist/test/release-changelog.test.js +0 -159
  762. package/dist/test/release-changelog.test.js.map +0 -1
  763. package/dist/test/release-holds.test.d.ts +0 -2
  764. package/dist/test/release-holds.test.d.ts.map +0 -1
  765. package/dist/test/release-holds.test.js +0 -456
  766. package/dist/test/release-holds.test.js.map +0 -1
  767. package/dist/test/same-round-think-policy.test.d.ts +0 -2
  768. package/dist/test/same-round-think-policy.test.d.ts.map +0 -1
  769. package/dist/test/same-round-think-policy.test.js +0 -853
  770. package/dist/test/same-round-think-policy.test.js.map +0 -1
  771. package/dist/test/save-recent-image.test.d.ts +0 -26
  772. package/dist/test/save-recent-image.test.d.ts.map +0 -1
  773. package/dist/test/save-recent-image.test.js +0 -974
  774. package/dist/test/save-recent-image.test.js.map +0 -1
  775. package/dist/test/shutdown-errors.test.d.ts +0 -2
  776. package/dist/test/shutdown-errors.test.d.ts.map +0 -1
  777. package/dist/test/shutdown-errors.test.js +0 -662
  778. package/dist/test/shutdown-errors.test.js.map +0 -1
  779. package/dist/test/silent-heartbeat-rows.test.d.ts +0 -2
  780. package/dist/test/silent-heartbeat-rows.test.d.ts.map +0 -1
  781. package/dist/test/silent-heartbeat-rows.test.js +0 -451
  782. package/dist/test/silent-heartbeat-rows.test.js.map +0 -1
  783. package/dist/test/silent-heartbeat.test.d.ts +0 -2
  784. package/dist/test/silent-heartbeat.test.d.ts.map +0 -1
  785. package/dist/test/silent-heartbeat.test.js +0 -165
  786. package/dist/test/silent-heartbeat.test.js.map +0 -1
  787. package/dist/test/state-scaling-e2e.test.d.ts +0 -22
  788. package/dist/test/state-scaling-e2e.test.d.ts.map +0 -1
  789. package/dist/test/state-scaling-e2e.test.js +0 -206
  790. package/dist/test/state-scaling-e2e.test.js.map +0 -1
  791. package/dist/test/state-scaling.test.d.ts +0 -12
  792. package/dist/test/state-scaling.test.d.ts.map +0 -1
  793. package/dist/test/state-scaling.test.js +0 -251
  794. package/dist/test/state-scaling.test.js.map +0 -1
  795. package/dist/test/stop-with-host-operations.test.d.ts +0 -20
  796. package/dist/test/stop-with-host-operations.test.d.ts.map +0 -1
  797. package/dist/test/stop-with-host-operations.test.js +0 -1174
  798. package/dist/test/stop-with-host-operations.test.js.map +0 -1
  799. package/dist/test/stop-with-work-in-flight.test.d.ts +0 -23
  800. package/dist/test/stop-with-work-in-flight.test.d.ts.map +0 -1
  801. package/dist/test/stop-with-work-in-flight.test.js +0 -784
  802. package/dist/test/stop-with-work-in-flight.test.js.map +0 -1
  803. package/dist/test/surgery-marks-receipt.test.d.ts +0 -2
  804. package/dist/test/surgery-marks-receipt.test.d.ts.map +0 -1
  805. package/dist/test/surgery-marks-receipt.test.js +0 -540
  806. package/dist/test/surgery-marks-receipt.test.js.map +0 -1
  807. package/dist/test/thinking-token-stamp.test.d.ts +0 -12
  808. package/dist/test/thinking-token-stamp.test.d.ts.map +0 -1
  809. package/dist/test/thinking-token-stamp.test.js +0 -129
  810. package/dist/test/thinking-token-stamp.test.js.map +0 -1
  811. package/dist/test/timezone.test.d.ts +0 -2
  812. package/dist/test/timezone.test.d.ts.map +0 -1
  813. package/dist/test/timezone.test.js +0 -18
  814. package/dist/test/timezone.test.js.map +0 -1
  815. package/dist/test/tool-batch-hook.test.d.ts +0 -8
  816. package/dist/test/tool-batch-hook.test.d.ts.map +0 -1
  817. package/dist/test/tool-batch-hook.test.js +0 -275
  818. package/dist/test/tool-batch-hook.test.js.map +0 -1
  819. package/dist/test/tool-policy.test.d.ts +0 -2
  820. package/dist/test/tool-policy.test.d.ts.map +0 -1
  821. package/dist/test/tool-policy.test.js +0 -51
  822. package/dist/test/tool-policy.test.js.map +0 -1
  823. package/dist/test/tool-presentation.test.d.ts +0 -2
  824. package/dist/test/tool-presentation.test.d.ts.map +0 -1
  825. package/dist/test/tool-presentation.test.js +0 -268
  826. package/dist/test/tool-presentation.test.js.map +0 -1
  827. package/dist/test/tool-result-content.test.d.ts +0 -2
  828. package/dist/test/tool-result-content.test.d.ts.map +0 -1
  829. package/dist/test/tool-result-content.test.js +0 -37
  830. package/dist/test/tool-result-content.test.js.map +0 -1
  831. package/dist/test/tool-result-guard.test.d.ts +0 -2
  832. package/dist/test/tool-result-guard.test.d.ts.map +0 -1
  833. package/dist/test/tool-result-guard.test.js +0 -3729
  834. package/dist/test/tool-result-guard.test.js.map +0 -1
  835. package/dist/test/tool-result-history.test.d.ts +0 -7
  836. package/dist/test/tool-result-history.test.d.ts.map +0 -1
  837. package/dist/test/tool-result-history.test.js +0 -156
  838. package/dist/test/tool-result-history.test.js.map +0 -1
  839. package/dist/test/tool-result-spill.test.d.ts +0 -13
  840. package/dist/test/tool-result-spill.test.d.ts.map +0 -1
  841. package/dist/test/tool-result-spill.test.js +0 -586
  842. package/dist/test/tool-result-spill.test.js.map +0 -1
  843. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts +0 -2
  844. package/dist/test/tool-wrapper-prose-guard-integration.test.d.ts.map +0 -1
  845. package/dist/test/tool-wrapper-prose-guard-integration.test.js +0 -485
  846. package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +0 -1
  847. package/dist/test/tool-wrapper-prose-guard.test.d.ts +0 -2
  848. package/dist/test/tool-wrapper-prose-guard.test.d.ts.map +0 -1
  849. package/dist/test/tool-wrapper-prose-guard.test.js +0 -34
  850. package/dist/test/tool-wrapper-prose-guard.test.js.map +0 -1
  851. package/dist/test/tools-observe-parser-conformance.test.d.ts +0 -2
  852. package/dist/test/tools-observe-parser-conformance.test.d.ts.map +0 -1
  853. package/dist/test/tools-observe-parser-conformance.test.js +0 -129
  854. package/dist/test/tools-observe-parser-conformance.test.js.map +0 -1
  855. package/dist/test/trunk-channel-routing.test.d.ts +0 -19
  856. package/dist/test/trunk-channel-routing.test.d.ts.map +0 -1
  857. package/dist/test/trunk-channel-routing.test.js +0 -652
  858. package/dist/test/trunk-channel-routing.test.js.map +0 -1
  859. package/dist/test/tune-out-e2e.test.d.ts +0 -2
  860. package/dist/test/tune-out-e2e.test.d.ts.map +0 -1
  861. package/dist/test/tune-out-e2e.test.js +0 -142
  862. package/dist/test/tune-out-e2e.test.js.map +0 -1
  863. package/dist/test/tune-out-gate-composition.test.d.ts +0 -2
  864. package/dist/test/tune-out-gate-composition.test.d.ts.map +0 -1
  865. package/dist/test/tune-out-gate-composition.test.js +0 -221
  866. package/dist/test/tune-out-gate-composition.test.js.map +0 -1
  867. package/dist/test/tune-out-lifecycle.test.d.ts +0 -2
  868. package/dist/test/tune-out-lifecycle.test.d.ts.map +0 -1
  869. package/dist/test/tune-out-lifecycle.test.js +0 -121
  870. package/dist/test/tune-out-lifecycle.test.js.map +0 -1
  871. package/dist/test/turn-trigger-provenance.test.d.ts +0 -2
  872. package/dist/test/turn-trigger-provenance.test.d.ts.map +0 -1
  873. package/dist/test/turn-trigger-provenance.test.js +0 -137
  874. package/dist/test/turn-trigger-provenance.test.js.map +0 -1
  875. package/dist/test/unconvertible-tool-result.test.d.ts +0 -2
  876. package/dist/test/unconvertible-tool-result.test.d.ts.map +0 -1
  877. package/dist/test/unconvertible-tool-result.test.js +0 -358
  878. package/dist/test/unconvertible-tool-result.test.js.map +0 -1
  879. package/dist/test/unsent-compiles.test.d.ts +0 -2
  880. package/dist/test/unsent-compiles.test.d.ts.map +0 -1
  881. package/dist/test/unsent-compiles.test.js +0 -139
  882. package/dist/test/unsent-compiles.test.js.map +0 -1
  883. package/dist/test/usage-accounting.test.d.ts +0 -2
  884. package/dist/test/usage-accounting.test.d.ts.map +0 -1
  885. package/dist/test/usage-accounting.test.js +0 -13
  886. package/dist/test/usage-accounting.test.js.map +0 -1
  887. package/dist/test/usage-tracker.test.d.ts +0 -2
  888. package/dist/test/usage-tracker.test.d.ts.map +0 -1
  889. package/dist/test/usage-tracker.test.js +0 -129
  890. package/dist/test/usage-tracker.test.js.map +0 -1
  891. package/dist/test/utils-surface.test.d.ts +0 -2
  892. package/dist/test/utils-surface.test.d.ts.map +0 -1
  893. package/dist/test/utils-surface.test.js +0 -145
  894. package/dist/test/utils-surface.test.js.map +0 -1
  895. package/dist/test/workspace-branch-continuation.test.d.ts +0 -15
  896. package/dist/test/workspace-branch-continuation.test.d.ts.map +0 -1
  897. package/dist/test/workspace-branch-continuation.test.js +0 -183
  898. package/dist/test/workspace-branch-continuation.test.js.map +0 -1
  899. package/dist/test/workspace-materialize-freshness.test.d.ts +0 -16
  900. package/dist/test/workspace-materialize-freshness.test.d.ts.map +0 -1
  901. package/dist/test/workspace-materialize-freshness.test.js +0 -252
  902. package/dist/test/workspace-materialize-freshness.test.js.map +0 -1
  903. package/dist/test/workspace-path-containment.test.d.ts +0 -19
  904. package/dist/test/workspace-path-containment.test.d.ts.map +0 -1
  905. package/dist/test/workspace-path-containment.test.js +0 -91
  906. package/dist/test/workspace-path-containment.test.js.map +0 -1
  907. package/dist/test/workspace-read-file-from-disk.test.d.ts +0 -17
  908. package/dist/test/workspace-read-file-from-disk.test.d.ts.map +0 -1
  909. package/dist/test/workspace-read-file-from-disk.test.js +0 -174
  910. package/dist/test/workspace-read-file-from-disk.test.js.map +0 -1
  911. package/dist/test/workspace-read-image.test.d.ts +0 -2
  912. package/dist/test/workspace-read-image.test.d.ts.map +0 -1
  913. package/dist/test/workspace-read-image.test.js +0 -597
  914. package/dist/test/workspace-read-image.test.js.map +0 -1
  915. package/dist/test/workspace-read-text.test.d.ts +0 -2
  916. package/dist/test/workspace-read-text.test.d.ts.map +0 -1
  917. package/dist/test/workspace-read-text.test.js +0 -101
  918. package/dist/test/workspace-read-text.test.js.map +0 -1
  919. package/dist/test/workspace-restore-order.test.d.ts +0 -16
  920. package/dist/test/workspace-restore-order.test.d.ts.map +0 -1
  921. package/dist/test/workspace-restore-order.test.js +0 -140
  922. package/dist/test/workspace-restore-order.test.js.map +0 -1
  923. package/dist/test/workspace-three-way.test.d.ts +0 -12
  924. package/dist/test/workspace-three-way.test.d.ts.map +0 -1
  925. package/dist/test/workspace-three-way.test.js +0 -4094
  926. package/dist/test/workspace-three-way.test.js.map +0 -1
  927. package/dist/test/workspace-watcher.test.d.ts +0 -2
  928. package/dist/test/workspace-watcher.test.d.ts.map +0 -1
  929. package/dist/test/workspace-watcher.test.js +0 -281
  930. package/dist/test/workspace-watcher.test.js.map +0 -1
  931. package/dist/test/xml-round-persist.test.d.ts +0 -19
  932. package/dist/test/xml-round-persist.test.d.ts.map +0 -1
  933. package/dist/test/xml-round-persist.test.js +0 -235
  934. package/dist/test/xml-round-persist.test.js.map +0 -1
  935. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,988 +0,0 @@
1
- /**
2
- * Host quiesce/maintenance mode (issue #122) — deterministic state-machine
3
- * coverage. No child processes; the MCPL plane/barrier interplay is covered
4
- * by the awareness-barrier suite.
5
- */
6
- import { test } from 'node:test';
7
- import assert from 'node:assert/strict';
8
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
9
- import { spawnSync } from 'node:child_process';
10
- import { fileURLToPath } from 'node:url';
11
- import { tmpdir } from 'node:os';
12
- import { join } from 'node:path';
13
- import { AutobiographicalStrategy } from '@animalabs/context-manager';
14
- import { AgentFramework, ResumeBlockedError } from '../src/index.js';
15
- import { MockMembrane, createMockResponse } from './helpers/mock-membrane.js';
16
- async function waitFor(description, predicate, timeoutMs = 3_000) {
17
- const deadline = Date.now() + timeoutMs;
18
- while (!predicate()) {
19
- if (Date.now() > deadline)
20
- throw new Error(`Timed out waiting for ${description}`);
21
- await new Promise((resolve) => setTimeout(resolve, 25));
22
- }
23
- }
24
- function autobiographical() {
25
- return new AutobiographicalStrategy({
26
- adaptiveResolution: true,
27
- foldingStrategy: 'kv-stable',
28
- recentWindowTokens: 30_000,
29
- kvStableReachTokens: 8_000,
30
- });
31
- }
32
- function stubPreview(framework, agentName, impl) {
33
- const cm = framework.getAgent(agentName).getContextManager();
34
- cm.previewContext = (budget) => impl(budget);
35
- }
36
- async function withFramework(membrane, fn, agentExtras = {}) {
37
- const dir = mkdtempSync(join(tmpdir(), 'host-quiesce-'));
38
- const framework = await AgentFramework.create({
39
- storePath: join(dir, 'store'),
40
- membrane: membrane.asMembrane(),
41
- agents: [{
42
- name: 'agent',
43
- model: 'test-model',
44
- systemPrompt: 'test',
45
- ...agentExtras,
46
- }],
47
- modules: [],
48
- });
49
- try {
50
- await fn(framework, dir);
51
- }
52
- finally {
53
- await framework.stop();
54
- rmSync(dir, { recursive: true, force: true });
55
- }
56
- }
57
- test('quiesce parks wakes; resume releases them', async () => {
58
- const membrane = new MockMembrane();
59
- await withFramework(membrane, async (framework) => {
60
- framework.start();
61
- const before = await framework.quiesce({ reason: 'test window' });
62
- assert.equal(before.quiesced, true);
63
- assert.equal(before.drained, true);
64
- const nudge = framework.nudgeAgent('agent', 'operator');
65
- assert.equal(nudge.ok, true);
66
- // Give the running loop time to (not) start a turn.
67
- await new Promise((resolve) => setTimeout(resolve, 300));
68
- assert.equal(membrane.calls.length, 0, 'no inference while quiesced');
69
- assert.equal(framework.getAgent('agent').state.status, 'idle');
70
- assert.equal(framework.getHostModeStatus().gatedRequests, 1);
71
- const after = await framework.resume();
72
- assert.equal(after.quiesced, false);
73
- await waitFor('parked wake to fire', () => membrane.calls.length > 0);
74
- });
75
- });
76
- test('parked wakes coalesce per (agent, reason), keeping the set bounded', async () => {
77
- const membrane = new MockMembrane();
78
- await withFramework(membrane, async (framework) => {
79
- framework.start();
80
- await framework.quiesce();
81
- for (let i = 0; i < 5; i++)
82
- framework.nudgeAgent('agent', 'operator');
83
- // The loop's next pass compresses same-reason parked requests to one.
84
- await waitFor('coalescing to a single parked request', () => framework.getHostModeStatus().gatedRequests === 1);
85
- await new Promise((resolve) => setTimeout(resolve, 200));
86
- assert.equal(framework.getHostModeStatus().gatedRequests, 1, 'stays bounded');
87
- assert.equal(membrane.calls.length, 0);
88
- });
89
- });
90
- test('coalescing keeps an ADDRESSED wake alive when an ambient one of the same reason parks later', async () => {
91
- // Every channel wake shares one reason; keying the coalescer on reason
92
- // alone let an ambient message parked later evict a DM/mention parked
93
- // earlier — and the resumed turn then answered into the ambient channel.
94
- const membrane = new MockMembrane();
95
- await withFramework(membrane, async (framework) => {
96
- framework.start();
97
- await framework.quiesce();
98
- // Re-read on every access: the scheduler REASSIGNS pendingRequests
99
- // when it takes a batch, so a captured reference goes stale.
100
- const pending = () => framework.pendingRequests;
101
- const t = Date.now();
102
- pending().push({ agentName: 'agent', reason: 'mcpl:channel-incoming', source: 'framework', timestamp: t, addressed: true, channelId: 'dm' }, { agentName: 'agent', reason: 'mcpl:channel-incoming', source: 'framework', timestamp: t + 1, addressed: false, channelId: 'lounge' }, { agentName: 'agent', reason: 'mcpl:channel-incoming', source: 'framework', timestamp: t + 2, addressed: false, channelId: 'lounge' });
103
- await waitFor('scheduler pass to coalesce', () => framework.getHostModeStatus().gatedRequests === 2);
104
- await new Promise((resolve) => setTimeout(resolve, 200));
105
- const survivors = pending().filter((r) => r.reason === 'mcpl:channel-incoming');
106
- assert.equal(survivors.length, 2, 'one addressed + one ambient survive');
107
- assert.ok(survivors.some((r) => r.addressed === true && r.channelId === 'dm'), 'the addressed wake survived');
108
- assert.ok(survivors.some((r) => r.addressed === false), 'the newest ambient wake survived');
109
- assert.equal(membrane.calls.length, 0);
110
- });
111
- });
112
- test('runUntilIdle returns with gated requests parked', async () => {
113
- const membrane = new MockMembrane();
114
- await withFramework(membrane, async (framework) => {
115
- await framework.quiesce();
116
- framework.nudgeAgent('agent', 'operator');
117
- // Must not hang: parked requests are not progress while quiesced.
118
- await framework.runUntilIdle();
119
- assert.equal(membrane.calls.length, 0);
120
- });
121
- });
122
- test('ephemeral admission is refused while quiesced', async () => {
123
- const membrane = new MockMembrane();
124
- await withFramework(membrane, async (framework) => {
125
- await framework.quiesce({ reason: 'surgery' });
126
- await assert.rejects(
127
- // Refused before the agent/CM are touched — a minimal stand-in suffices.
128
- framework.runEphemeralToCompletion({ name: 'ephemeral' }, {}), /quiesced \(surgery\).*resume\(\) first/);
129
- });
130
- });
131
- /** A stream that never completes until cancelled — models a hung provider. */
132
- class HangingStream {
133
- pendingResolve = null;
134
- aborted = false;
135
- cancel() {
136
- this.aborted = true;
137
- this.pendingResolve?.();
138
- }
139
- waitForCancel() {
140
- if (this.aborted)
141
- return Promise.resolve();
142
- return new Promise((resolve) => { this.pendingResolve = resolve; });
143
- }
144
- provideToolResults() { }
145
- get isWaitingForTools() { return false; }
146
- get pendingToolCallIds() { return []; }
147
- get toolDepth() { return 0; }
148
- async *[Symbol.asyncIterator]() {
149
- await this.waitForCancel();
150
- yield { type: 'aborted', reason: 'user' };
151
- }
152
- }
153
- class HangingMembrane extends MockMembrane {
154
- streamYielding(request) {
155
- this.calls.push(request);
156
- return new HangingStream();
157
- }
158
- }
159
- test('drain waits for an in-flight turn; abandon cancels without failure accounting', async () => {
160
- const membrane = new HangingMembrane();
161
- await withFramework(membrane, async (framework) => {
162
- const traces = [];
163
- framework.onTrace((event) => traces.push(event));
164
- framework.start();
165
- framework.nudgeAgent('agent', 'operator');
166
- await waitFor('turn to start', () => membrane.calls.length === 1);
167
- const status = await framework.quiesce({ timeoutMs: 1_000, abandon: true });
168
- assert.equal(status.quiesced, true);
169
- assert.equal(status.drained, true, 'abandon settles the hung turn');
170
- await waitFor('agent back to idle', () => framework.getAgent('agent').state.status === 'idle');
171
- assert.ok(traces.some((t) => t.type === 'inference:aborted'
172
- && t.reason === 'quiesce_abandoned'), 'abandon is traced as an operator abort');
173
- assert.ok(!traces.some((t) => t.type === 'inference:exhausted'), 'an operator cancel must not feed the failure streak / hard-down accounting');
174
- const quiesceTrace = traces.find((t) => t.type === 'host:quiesce');
175
- assert.equal(quiesceTrace?.abandoned, true);
176
- });
177
- });
178
- test('quiesce persists across restart; resume clears it durably', async () => {
179
- const dir = mkdtempSync(join(tmpdir(), 'host-quiesce-persist-'));
180
- const storePath = join(dir, 'store');
181
- const config = () => ({
182
- storePath,
183
- membrane: new MockMembrane().asMembrane(),
184
- agents: [{ name: 'agent', model: 'test-model', systemPrompt: 'test' }],
185
- modules: [],
186
- });
187
- let framework = await AgentFramework.create(config());
188
- try {
189
- await framework.quiesce({ reason: 'refold in progress' });
190
- await framework.stop();
191
- framework = await AgentFramework.create(config());
192
- const restored = framework.getHostModeStatus();
193
- assert.equal(restored.quiesced, true, 'a restart mid-surgery boots quiesced');
194
- assert.equal(restored.reason, 'refold in progress');
195
- await framework.resume();
196
- await framework.stop();
197
- framework = await AgentFramework.create(config());
198
- assert.equal(framework.getHostModeStatus().quiesced, false);
199
- }
200
- finally {
201
- await framework.stop();
202
- rmSync(dir, { recursive: true, force: true });
203
- }
204
- });
205
- test('resume gates on a fresh feasibility verdict; force overrides', async () => {
206
- const membrane = new MockMembrane();
207
- await withFramework(membrane, async (framework) => {
208
- await framework.quiesce();
209
- stubPreview(framework, 'agent', (budget) => ({
210
- finalTokens: 450_000,
211
- budgetTokens: budget.maxTokens,
212
- fits: false,
213
- exhausted: true,
214
- headTokens: 1,
215
- tailTokens: 2,
216
- middleTokens: 3,
217
- middleChunkCount: 1,
218
- deepestLevel: 3,
219
- resolutions: {},
220
- moves: 0,
221
- producedCount: 0,
222
- }));
223
- await assert.rejects(framework.resume(), (error) => {
224
- assert.ok(error instanceof ResumeBlockedError);
225
- assert.equal(error.verdicts.length, 1);
226
- assert.equal(error.verdicts[0].agentName, 'agent');
227
- assert.match(error.message, /folded floor 450000/);
228
- return true;
229
- });
230
- assert.equal(framework.getHostModeStatus().quiesced, true, 'still quiesced after refusal');
231
- const forced = await framework.resume({ force: true });
232
- assert.equal(forced.quiesced, false);
233
- }, {
234
- strategy: autobiographical(),
235
- contextBudgetTokens: 300_000,
236
- maxTokens: 10_000,
237
- });
238
- });
239
- test('resume proceeds with a warn when the strategy cannot preview', async () => {
240
- const membrane = new MockMembrane();
241
- await withFramework(membrane, async (framework) => {
242
- // Default PassthroughStrategy: no previewContext at all.
243
- await framework.quiesce();
244
- const status = await framework.resume();
245
- assert.equal(status.quiesced, false);
246
- });
247
- });
248
- test('resume proceeds without a verdict for an agent whose context manager refuses, and warns naming it', async (t) => {
249
- const membrane = new MockMembrane();
250
- await withFramework(membrane, async (framework) => {
251
- await framework.quiesce();
252
- // A failed strategy initialization fences the context manager: its
253
- // settings queries throw until a successful switchBranch or setStrategy.
254
- const cm = framework.getAgent('agent').getContextManager();
255
- const failing = {
256
- name: 'refusing-init-test',
257
- async initialize() { throw new Error('strategy initialization failed for the test'); },
258
- checkReadiness: () => ({ ready: true }),
259
- async tick() { },
260
- select: () => [],
261
- };
262
- await assert.rejects(cm.setStrategy(failing), /strategy initialization failed for the test/);
263
- assert.throws(() => cm.getHotContextSettings(), /requires successful strategy initialization/);
264
- // The preview answers rather than throws: no verdict, with what the
265
- // agent's own state still says.
266
- // The agent runs at the default budget of 100,000 tokens, so 50,000 is a paced descent.
267
- const preview = framework.previewAgentRuntimeSettings('agent', { contextBudgetTokens: 50_000 });
268
- assert.equal(preview.available, false);
269
- assert.match(String(preview.reason), /requires successful strategy initialization/);
270
- assert.equal(preview.path, 'paced');
271
- assert.equal(preview.liveBudgetTokens, 100_000);
272
- assert.equal(preview.transition, 'stable');
273
- assert.equal(preview.effective, undefined);
274
- // A patch whose values the agent refuses still throws.
275
- assert.throws(() => framework.previewAgentRuntimeSettings('agent', { contextBudgetTokens: 5 }), /contextBudgetTokens must be/);
276
- assert.throws(() => framework.previewAgentRuntimeSettings('agent', { tailTokens: -1 }), /tailTokens must be/);
277
- // Whether the strategy takes a live tail or pace is the manager's to say,
278
- // so while it refuses, a patch that sets one gets no verdict either.
279
- for (const patch of [{ tailTokens: 2_000 }, { transitionPaceTokens: 1_000 }]) {
280
- const unanswered = framework.previewAgentRuntimeSettings('agent', patch);
281
- assert.equal(unanswered.available, false, JSON.stringify(patch));
282
- assert.match(String(unanswered.reason), /requires successful strategy initialization/);
283
- assert.equal(unanswered.liveBudgetTokens, 100_000);
284
- }
285
- // An update of the budget is refused, by the manager, and the preflight
286
- // doesn't say it's applying one.
287
- const preflight = t.mock.method(console, 'warn', () => { });
288
- try {
289
- assert.throws(() => framework.updateAgentRuntimeSettings('agent', { contextBudgetTokens: 50_000 }), /requires successful strategy initialization/);
290
- assert.ok(!preflight.mock.calls.some((call) => String(call.arguments[0]).includes('applying without preflight')));
291
- }
292
- finally {
293
- preflight.mock.restore();
294
- }
295
- assert.equal(framework.getAgent('agent').runtimeBudgetPath().liveBudgetTokens, 100_000, 'the budget is as it was');
296
- const warn = t.mock.method(console, 'warn', () => { });
297
- let status;
298
- try {
299
- status = await framework.resume();
300
- }
301
- finally {
302
- warn.mock.restore();
303
- }
304
- assert.equal(status.quiesced, false);
305
- assert.ok(warn.mock.calls.some((call) => {
306
- const line = String(call.arguments[0]);
307
- return line.includes('feasibility preview unavailable for agent')
308
- && line.includes('requires successful strategy initialization')
309
- && line.includes('proceeding without a verdict');
310
- }), 'resume warns, naming the agent and the reason');
311
- });
312
- });
313
- test('a preview stopped by a stale branch generation says branch_generation_changed, as the reason documents', async () => {
314
- const membrane = new MockMembrane();
315
- await withFramework(membrane, async (framework) => {
316
- await framework.quiesce();
317
- // As the autobiographical strategy refuses a branch it hasn't reloaded:
318
- // its readiness and its settings both say so.
319
- const stale = 'TestStrategy.getHotContextSettings requires reinitialization for the current branch generation';
320
- const strategy = {
321
- name: 'stale-generation-test',
322
- async initialize() { },
323
- checkReadiness: () => { throw new Error(stale); },
324
- getHotContextSettings: () => { throw new Error(stale); },
325
- updateHotContextSettings: () => { throw new Error(stale); },
326
- async tick() { },
327
- select: () => [],
328
- };
329
- const cm = framework.getAgent('agent').getContextManager();
330
- await cm.setStrategy(strategy);
331
- const preview = framework.previewAgentRuntimeSettings('agent', { contextBudgetTokens: 50_000 });
332
- assert.equal(preview.available, false);
333
- assert.equal(preview.reason, 'branch_generation_changed');
334
- assert.equal(preview.liveBudgetTokens, 100_000);
335
- });
336
- });
337
- test('maintenanceTick runs the real maintenance pass while quiesced', async () => {
338
- class QueuedStrategy {
339
- name = 'queued-test';
340
- ticks = 0;
341
- checkReadiness() {
342
- return { ready: this.ticks >= 2, description: 'test maintenance queued' };
343
- }
344
- async tick(_ctx) {
345
- this.ticks++;
346
- }
347
- select(_store, _log, _budget) {
348
- return [];
349
- }
350
- }
351
- const strategy = new QueuedStrategy();
352
- const membrane = new MockMembrane();
353
- await withFramework(membrane, async (framework) => {
354
- framework.start();
355
- await framework.quiesce({ reason: 'compression window' });
356
- const snapshot = await framework.maintenanceTick();
357
- assert.ok(strategy.ticks >= 2, `maintenance ticked while quiesced (${strategy.ticks})`);
358
- assert.ok(snapshot.agents.some((a) => a.agentName === 'agent'));
359
- }, { strategy });
360
- });
361
- test('maintenanceTick runs no pass while a surgery holds the store, and says so', async (t) => {
362
- class QueuedStrategy {
363
- name = 'queued-test';
364
- ticks = 0;
365
- checkReadiness() {
366
- return { ready: false, description: 'test maintenance queued' };
367
- }
368
- async tick(_ctx) {
369
- this.ticks++;
370
- }
371
- select(_store, _log, _budget) {
372
- return [];
373
- }
374
- }
375
- const strategy = new QueuedStrategy();
376
- const membrane = new MockMembrane();
377
- await withFramework(membrane, async (framework) => {
378
- // Held before start(), whose first pass would otherwise tick at once.
379
- const internals = framework;
380
- internals.surgeryHold = { verb: 'rollback', agentName: 'agent', since: Date.now() };
381
- framework.start();
382
- await framework.quiesce({ reason: 'compression window' });
383
- const warn = t.mock.method(console, 'warn', () => { });
384
- try {
385
- const snapshot = await framework.maintenanceTick();
386
- assert.equal(snapshot.ran, false);
387
- assert.equal(strategy.ticks, 0);
388
- assert.equal(snapshot.history.length, 0);
389
- assert.ok(warn.mock.calls.some((call) => String(call.arguments[0]).includes('a rollback for agent holds the store — no pass executed')));
390
- }
391
- finally {
392
- internals.surgeryHold = null;
393
- warn.mock.restore();
394
- }
395
- }, { strategy });
396
- });
397
- // ---------------------------------------------------------------------------
398
- // End-to-end MCPL leg: data plane held while quiesced, resume deliverable
399
- // over host/command (control plane), funnel reopens and flushes the backlog.
400
- // ---------------------------------------------------------------------------
401
- const QUIESCE_STDIO_SERVER = `
402
- const fs = require('node:fs');
403
- const statusPath = process.env.STATUS_PATH;
404
- const pushPath = process.env.PUSH_PATH;
405
- const resumePath = process.env.RESUME_PATH;
406
- const log = (event, extra) =>
407
- fs.appendFileSync(statusPath, JSON.stringify({ event, ...extra }) + '\\n');
408
- let buf = '';
409
- let pushSent = false;
410
- let resumeSent = false;
411
- process.stdin.on('data', (c) => {
412
- buf += c.toString('utf8');
413
- let i;
414
- while ((i = buf.indexOf('\\n')) >= 0) {
415
- const line = buf.slice(0, i); buf = buf.slice(i + 1);
416
- if (!line.trim()) continue;
417
- let m; try { m = JSON.parse(line); } catch { continue; }
418
- const reply = (result) => process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: m.id, result }) + '\\n');
419
- if (m.method === 'initialize') reply({ capabilities: { experimental: { mcpl: { version: '0.4', pushEvents: true } } } });
420
- else if (m.method === 'tools/list') reply({ tools: [] });
421
- else if (m.id === 900) log('push-response', { error: m.error ?? null });
422
- else if (m.id === 901) log('resume-response', { result: m.result ?? null, error: m.error ?? null });
423
- }
424
- });
425
- setInterval(() => {
426
- if (!pushSent && fs.existsSync(pushPath)) {
427
- pushSent = true;
428
- process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: 900, method: 'push/event', params: {
429
- featureSet: 'chat', eventId: 'quiesce-push', timestamp: new Date().toISOString(),
430
- payload: { content: [{ type: 'text', text: 'held while quiesced' }] },
431
- } }) + '\\n');
432
- log('push-sent');
433
- }
434
- if (!resumeSent && fs.existsSync(resumePath)) {
435
- resumeSent = true;
436
- process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: 901, method: 'host/command', params: {
437
- command: 'resume', requesterName: 'test-operator',
438
- } }) + '\\n');
439
- log('resume-sent');
440
- }
441
- }, 25);
442
- `;
443
- test('MCPL: pushes buffer while quiesced; host/command resume reopens and flushes', async () => {
444
- const { writeFileSync, readFileSync, existsSync } = await import('node:fs');
445
- const dir = mkdtempSync(join(tmpdir(), 'host-quiesce-mcpl-'));
446
- const statusPath = join(dir, 'status.jsonl');
447
- const pushPath = join(dir, 'push');
448
- const resumePath = join(dir, 'resume');
449
- const records = () => existsSync(statusPath)
450
- ? readFileSync(statusPath, 'utf8').trim().split('\n').filter(Boolean).map((l) => JSON.parse(l))
451
- : [];
452
- const membrane = new MockMembrane();
453
- const framework = await AgentFramework.create({
454
- storePath: join(dir, 'store'),
455
- membrane: membrane.asMembrane(),
456
- agents: [{ name: 'assistant', model: 'test-model', systemPrompt: 'test' }],
457
- modules: [],
458
- mcplServers: [{
459
- id: 'pusher',
460
- command: process.execPath,
461
- args: ['-e', QUIESCE_STDIO_SERVER],
462
- allowHostCommands: true,
463
- env: { STATUS_PATH: statusPath, PUSH_PATH: pushPath, RESUME_PATH: resumePath },
464
- }],
465
- });
466
- try {
467
- framework.start();
468
- await framework.quiesce({ reason: 'mcpl leg' });
469
- writeFileSync(pushPath, 'go');
470
- await waitFor('push sent by server', () => records().some((r) => r.event === 'push-sent'));
471
- await new Promise((resolve) => setTimeout(resolve, 400));
472
- assert.ok(!records().some((r) => r.event === 'push-response'), 'push must buffer on the paused data plane — no response while quiesced');
473
- assert.equal(membrane.calls.length, 0, 'no wake while quiesced');
474
- // Resume arrives OVER MCPL: host/command rides the control plane, so it
475
- // is deliverable through the very pause it lifts.
476
- writeFileSync(resumePath, 'go');
477
- await waitFor('resume handled via host/command', () => records().some((r) => r.event === 'resume-response'
478
- && r.result?.ok === true));
479
- assert.equal(framework.getHostModeStatus().quiesced, false);
480
- await waitFor('buffered push flushed after resume', () => records().some((r) => r.event === 'push-response'));
481
- }
482
- finally {
483
- await framework.stop();
484
- rmSync(dir, { recursive: true, force: true });
485
- }
486
- });
487
- // ---------------------------------------------------------------------------
488
- // Review-fix regressions (code review 08-21)
489
- // ---------------------------------------------------------------------------
490
- /** A membrane whose stream sleeps before producing its response — a turn
491
- * that settles on its own after `delayMs`, so a drain window's real length
492
- * becomes observable: a collapsed window returns undrained immediately, a
493
- * sane one waits for the turn. */
494
- class DelayedMembrane extends MockMembrane {
495
- delayMs;
496
- constructor(delayMs) {
497
- super();
498
- this.delayMs = delayMs;
499
- }
500
- streamYielding(request, options) {
501
- const inner = super.streamYielding(request, options);
502
- const delayMs = this.delayMs;
503
- return {
504
- cancel: () => inner.cancel(),
505
- provideToolResults: (...args) => inner.provideToolResults(...args),
506
- get isWaitingForTools() { return inner.isWaitingForTools; },
507
- get pendingToolCallIds() { return inner.pendingToolCallIds; },
508
- get toolDepth() { return inner.toolDepth; },
509
- async *[Symbol.asyncIterator]() {
510
- await new Promise((resolve) => setTimeout(resolve, delayMs));
511
- yield* inner;
512
- },
513
- };
514
- }
515
- }
516
- test('a non-finite timeoutMs falls back to the default drain window, never NaN-collapses', async () => {
517
- // NaN reached quiesce() via Number('12O000') on the HTTP ingress. With the
518
- // old Math.max(1_000, NaN) the deadline was NaN and the drain window
519
- // collapsed to zero. Discriminating observable: a turn that settles after
520
- // 600ms is drained by a sane window and NOT by a collapsed one.
521
- const membrane = new DelayedMembrane(600);
522
- membrane.pushResponse(createMockResponse([{ type: 'text', text: 'late' }]));
523
- await withFramework(membrane, async (framework) => {
524
- framework.start();
525
- framework.nudgeAgent('agent', 'operator');
526
- await waitFor('turn to start', () => membrane.calls.length === 1);
527
- const started = Date.now();
528
- const status = await framework.quiesce({ timeoutMs: Number('12O000') });
529
- assert.equal(status.quiesced, true);
530
- assert.equal(status.drained, true, 'the window waited for the turn');
531
- assert.ok(Date.now() - started >= 400, 'quiesce actually waited');
532
- });
533
- });
534
- test('timeoutMs is clamped inside quiesce() — a sub-second value still drains a short turn', async () => {
535
- const membrane = new DelayedMembrane(600);
536
- membrane.pushResponse(createMockResponse([{ type: 'text', text: 'late' }]));
537
- await withFramework(membrane, async (framework) => {
538
- framework.start();
539
- framework.nudgeAgent('agent', 'operator');
540
- await waitFor('turn to start', () => membrane.calls.length === 1);
541
- // 1ms honoured literally would return undrained; the [1s, 10m] floor
542
- // (now inside quiesce(), shared by WS/HTTP/host-command) waits it out.
543
- const status = await framework.quiesce({ timeoutMs: 1 });
544
- assert.equal(status.drained, true);
545
- assert.equal(AgentFramework.QUIESCE_TIMEOUT_MAX_MS, 600_000);
546
- });
547
- });
548
- test('a concurrent resume() supersedes a draining quiesce: no abandon, no stale trace', async () => {
549
- const membrane = new HangingMembrane();
550
- await withFramework(membrane, async (framework) => {
551
- const traces = [];
552
- framework.onTrace((event) => traces.push(event));
553
- framework.start();
554
- framework.nudgeAgent('agent', 'operator');
555
- await waitFor('turn to start', () => membrane.calls.length === 1);
556
- const pending = framework.quiesce({ timeoutMs: 5_000, abandon: true });
557
- await new Promise((resolve) => setTimeout(resolve, 400));
558
- assert.equal(framework.getHostModeStatus().quiesced, true, 'draining');
559
- await framework.resume();
560
- const status = await pending;
561
- assert.equal(status.quiesced, false, 'the superseded quiesce reports the live mode');
562
- assert.ok(!traces.some((t) => t.type === 'inference:aborted'), 'the turn that outlived the window was NOT abandoned after the resume');
563
- assert.ok(!traces.some((t) => t.type === 'host:quiesce'), 'no stale host:quiesce trace');
564
- // Release the hung turn so teardown is clean.
565
- framework.getAgent('agent').cancelStream();
566
- await waitFor('agent idle', () => framework.getAgent('agent').state.status === 'idle');
567
- });
568
- });
569
- test('abandon reports turns it cannot cancel (token held, no stream)', async () => {
570
- const membrane = new MockMembrane();
571
- await withFramework(membrane, async (framework) => {
572
- const traces = [];
573
- framework.onTrace((event) => traces.push(event));
574
- // A turn between dequeue and stream registration: token held, agent idle.
575
- const tokens = framework.activeTurnTokens;
576
- tokens.set('agent', {});
577
- try {
578
- const status = await framework.quiesce({ timeoutMs: 1_000, abandon: true });
579
- assert.equal(status.drained, false);
580
- assert.deepEqual(status.unabandonable, ['agent']);
581
- const trace = traces.find((t) => t.type === 'host:quiesce');
582
- assert.deepEqual(trace?.unabandonable, ['agent']);
583
- assert.equal(membrane.calls.length, 0, 'nothing was cancelled or started');
584
- }
585
- finally {
586
- tokens.delete('agent');
587
- }
588
- });
589
- });
590
- test('a cancel that surfaces as a stream ERROR still settles as an operator abort', async () => {
591
- // Some stream implementations report cancellation through the error
592
- // branch rather than `aborted`; the quiesce_abandoned contract must hold
593
- // on both: no exhausted accounting, lifecycle 'aborted', agent back idle.
594
- class ErroringHangStream extends HangingStream {
595
- async *[Symbol.asyncIterator]() {
596
- await this.waitForCancel();
597
- yield { type: 'error', error: new Error('stream cancelled') };
598
- }
599
- }
600
- class ErroringMembrane extends MockMembrane {
601
- streamYielding(request) {
602
- this.calls.push(request);
603
- return new ErroringHangStream();
604
- }
605
- }
606
- const membrane = new ErroringMembrane();
607
- await withFramework(membrane, async (framework) => {
608
- const traces = [];
609
- framework.onTrace((event) => traces.push(event));
610
- framework.start();
611
- framework.nudgeAgent('agent', 'operator');
612
- await waitFor('turn to start', () => membrane.calls.length === 1);
613
- const status = await framework.quiesce({ timeoutMs: 1_000, abandon: true });
614
- assert.equal(status.drained, true);
615
- await waitFor('agent back to idle', () => framework.getAgent('agent').state.status === 'idle');
616
- assert.ok(traces.some((t) => t.type === 'inference:aborted'
617
- && t.reason === 'quiesce_abandoned'));
618
- assert.ok(!traces.some((t) => t.type === 'inference:exhausted'));
619
- const lifecycle = traces
620
- .filter((t) => String(t.type).includes('lifecycle'))
621
- .map((t) => t.phase);
622
- if (lifecycle.length > 0)
623
- assert.ok(!lifecycle.includes('completed'), 'an abandoned turn is not "completed"');
624
- });
625
- });
626
- test('abandon can escalate an already-quiesced, undrained host', async () => {
627
- class HangingStream {
628
- pendingResolve = null;
629
- aborted = false;
630
- cancel() { this.aborted = true; this.pendingResolve?.(); }
631
- provideToolResults() { }
632
- get isWaitingForTools() { return false; }
633
- get pendingToolCallIds() { return []; }
634
- get toolDepth() { return 0; }
635
- async *[Symbol.asyncIterator]() {
636
- if (!this.aborted) {
637
- await new Promise((resolve) => { this.pendingResolve = resolve; });
638
- }
639
- yield { type: 'aborted', reason: 'user' };
640
- }
641
- }
642
- class HangingMembrane extends MockMembrane {
643
- streamYielding(request) {
644
- this.calls.push(request);
645
- return new HangingStream();
646
- }
647
- }
648
- const membrane = new HangingMembrane();
649
- await withFramework(membrane, async (framework) => {
650
- framework.start();
651
- framework.nudgeAgent('agent', 'operator');
652
- await waitFor('turn to start', () => membrane.calls.length === 1);
653
- const first = await framework.quiesce({ timeoutMs: 1_000 });
654
- assert.equal(first.drained, false, 'hung turn survives the first window');
655
- // Old behavior: `if (this.quiesced) return status` made this a no-op and
656
- // the only way out was resume()+re-quiesce, reopening planes mid-surgery.
657
- const second = await framework.quiesce({ abandon: true });
658
- assert.equal(second.drained, true, 'second quiesce escalates to abandon');
659
- });
660
- });
661
- test('context writes are deferred while quiesced and flushed by resume', async () => {
662
- const membrane = new MockMembrane();
663
- await withFramework(membrane, async (framework) => {
664
- await framework.quiesce({ reason: 'refold' });
665
- const cm = framework.getAgent('agent').getContextManager();
666
- const before = cm.getAllMessages().length;
667
- // Module events / api message.send route through framework.addMessage
668
- // (private — invoked here the way handleProcessEvent invokes it).
669
- framework.addMessage('user', [{ type: 'text', text: 'mid-surgery message' }]);
670
- assert.equal(cm.getAllMessages().length, before, 'no context append while the window is open');
671
- await framework.resume();
672
- assert.equal(cm.getAllMessages().length, before + 1, 'the deferred write lands at resume');
673
- });
674
- });
675
- test('a batch carrying a budget restart re-parks its sibling wakes instead of consuming them', async () => {
676
- const membrane = new MockMembrane();
677
- // The restart's continuation round needs a response to complete on — an
678
- // empty mock stream yields no `complete` and the agent never leaves
679
- // `streaming`, which reads as a scheduler hang rather than a re-park bug.
680
- membrane.pushResponse(createMockResponse([{ type: 'text', text: 'restart round' }]));
681
- await withFramework(membrane, async (framework) => {
682
- await framework.quiesce();
683
- // A parked wake exists...
684
- framework.nudgeAgent('agent', 'operator');
685
- // ...and a budget restart lands in the same pendingRequests batch.
686
- framework.pendingRequests.push({
687
- agentName: 'agent',
688
- reason: 'context_budget_restart',
689
- source: 'framework',
690
- timestamp: Date.now(),
691
- });
692
- // Drive one scheduler pass: the restart starts its continuation turn, but
693
- // the nudge must survive as a parked request rather than being consumed
694
- // by it — exactly one provider call, and the survivor IS the nudge.
695
- await framework.runUntilIdle();
696
- await waitFor('sibling wake re-parked', () => framework.getHostModeStatus().gatedRequests >= 1);
697
- assert.equal(membrane.calls.length, 1, 'only the restart ran');
698
- const parked = framework.pendingRequests;
699
- assert.ok(parked.some((r) => r.reason.startsWith('admin-nudge')), 'the parked survivor is the nudge');
700
- assert.ok(!parked.some((r) => r.reason === 'context_budget_restart'), 'the restart was consumed');
701
- });
702
- });
703
- test('resume flushes deferred writes per message: one poison write neither drops the rest nor skips the reopen', async () => {
704
- const membrane = new MockMembrane();
705
- await withFramework(membrane, async (framework) => {
706
- const traces = [];
707
- framework.onTrace((event) => traces.push(event));
708
- await framework.quiesce({ reason: 'refold' });
709
- const agent = framework.getAgent('agent');
710
- const cm = agent.getContextManager();
711
- const before = cm.getAllMessages().length;
712
- const add = framework.addMessage.bind(framework);
713
- add('user', [{ type: 'text', text: 'first' }]);
714
- add('user', [{ type: 'text', text: 'poison' }]);
715
- add('user', [{ type: 'text', text: 'third' }]);
716
- assert.equal(framework.getHostModeStatus().deferredWrites, 3);
717
- const realAdd = cm.addMessage.bind(cm);
718
- cm.addMessage = ((participant, content, metadata, causedBy) => {
719
- const text = content[0].text;
720
- if (text === 'poison')
721
- throw new Error('store write failed');
722
- return realAdd(participant, content, metadata, causedBy);
723
- });
724
- const status = await framework.resume();
725
- assert.equal(status.quiesced, false);
726
- assert.equal(status.deferredWrites, 0, 'the queue is drained even though one write failed');
727
- assert.deepEqual(cm.getAllMessages().slice(before).map((m) => m.content[0].text), ['first', 'third'], 'the writes behind the poison one still landed');
728
- assert.ok(traces.some((t) => t.type === 'host:resume'), 'resume completed its follow-through');
729
- });
730
- });
731
- test('context writes deferred while quiesced survive a restart and land at resume', async () => {
732
- const dir = mkdtempSync(join(tmpdir(), 'host-quiesce-deferred-'));
733
- const storePath = join(dir, 'store');
734
- const config = () => ({
735
- storePath,
736
- membrane: new MockMembrane().asMembrane(),
737
- agents: [{ name: 'agent', model: 'test-model', systemPrompt: 'test' }],
738
- modules: [],
739
- });
740
- let framework = await AgentFramework.create(config());
741
- try {
742
- await framework.quiesce({ reason: 'surgery' });
743
- const before = framework.getAgent('agent').getContextManager().getAllMessages().length;
744
- framework
745
- .addMessage('user', [{ type: 'text', text: 'said during surgery' }]);
746
- assert.equal(framework.getHostModeStatus().deferredWrites, 1);
747
- await framework.stop(); // crash-equivalent: the queue was in memory
748
- framework = await AgentFramework.create(config());
749
- assert.equal(framework.getHostModeStatus().quiesced, true);
750
- assert.equal(framework.getHostModeStatus().deferredWrites, 1, 'restored from the store');
751
- await framework.resume();
752
- const cm = framework.getAgent('agent').getContextManager();
753
- const texts = cm.getAllMessages().slice(before).map((m) => m.content[0].text);
754
- assert.deepEqual(texts, ['said during surgery']);
755
- assert.equal(framework.getHostModeStatus().deferredWrites, 0);
756
- await framework.stop();
757
- framework = await AgentFramework.create(config());
758
- assert.equal(framework.getHostModeStatus().deferredWrites, 0, 'slot cleared after the flush');
759
- }
760
- finally {
761
- await framework.stop();
762
- rmSync(dir, { recursive: true, force: true });
763
- }
764
- });
765
- // ---------------------------------------------------------------------------
766
- // Review round 2 (antra-tess): admission bypass, branch-independent
767
- // persistence, crash-safe resume flush.
768
- // ---------------------------------------------------------------------------
769
- test('a wake parked on provider admission does not start after quiesce; it runs at resume', async () => {
770
- const membrane = new MockMembrane();
771
- membrane.pushResponse(createMockResponse([{ type: 'text', text: 'after resume' }]));
772
- await withFramework(membrane, async (framework) => {
773
- framework.start();
774
- const internals = framework;
775
- // Hold an auxiliary (compression-style) provider call in flight.
776
- let releaseAux;
777
- const auxDone = internals.withAuxiliaryAdmission('agent', () => new Promise((resolve) => { releaseAux = resolve; }));
778
- await waitFor('auxiliary in flight', () => true);
779
- // A wake passes the scheduler and parks behind the auxiliary: it owns
780
- // provider admission but no turn token yet.
781
- framework.nudgeAgent('agent', 'operator');
782
- await internals.processInferenceRequests();
783
- assert.equal(internals.providerGates.get('agent')?.primaryDepth, 1, 'admission owned');
784
- assert.equal(internals.activeTurnTokens.size, 0, 'no turn token yet');
785
- // Quiesce with a short window: the parked admission is NOT drained.
786
- const status = await framework.quiesce({ reason: 'surgery', timeoutMs: 1_000 });
787
- assert.equal(status.quiesced, true);
788
- assert.equal(status.parkedAdmissions, 1, 'status reports the parked wake');
789
- assert.equal(status.drained, false, 'a parked admission is not "drained"');
790
- // Release the auxiliary: before the fix this started a turn while quiesced.
791
- releaseAux();
792
- await auxDone;
793
- await waitFor('admission released', () => (internals.providerGates.get('agent')?.primaryDepth ?? 0) === 0);
794
- await new Promise((resolve) => setTimeout(resolve, 100));
795
- assert.equal(membrane.calls.length, 0, 'NO inference while quiesced');
796
- assert.equal(framework.getHostModeStatus().quiesced, true);
797
- assert.ok(framework.getHostModeStatus().gatedRequests >= 1, 'the wake was requeued, not dropped');
798
- assert.equal(framework.getHostModeStatus().drained, true, 'drained once the admission was given back');
799
- await framework.resume();
800
- await waitFor('requeued wake to run after resume', () => membrane.calls.length === 1);
801
- });
802
- });
803
- test('quiesce survives a historical rollback + restart (host mode lives outside branch history)', async () => {
804
- const dir = mkdtempSync(join(tmpdir(), 'host-quiesce-rollback-'));
805
- const storePath = join(dir, 'store');
806
- const config = () => ({
807
- storePath,
808
- membrane: new MockMembrane().asMembrane(),
809
- agents: [{ name: 'agent', model: 'test-model', systemPrompt: 'test' }],
810
- modules: [],
811
- });
812
- let framework = await AgentFramework.create(config());
813
- try {
814
- const cm = framework.getAgent('agent').getContextManager();
815
- const checkpoint = cm.addMessage('user', [{ type: 'text', text: 'checkpoint' }]);
816
- cm.addMessage('user', [{ type: 'text', text: 'later' }]);
817
- await framework.quiesce({ reason: 'refold' });
818
- framework
819
- .addMessage('user', [{ type: 'text', text: 'deferred during surgery' }]);
820
- assert.equal(framework.getHostModeStatus().deferredWrites, 1);
821
- // The surgery itself: time-travel to before the quiesce marker was written.
822
- const branch = cm.branchAt(checkpoint, 'rollback/agent/test');
823
- await cm.switchBranch(branch);
824
- assert.equal(framework.getHostModeStatus().quiesced, true, 'live flag unaffected');
825
- assert.equal(existsSync(join(storePath, 'recovery', 'host-mode.json')), true, 'marker is a recovery file');
826
- await framework.stop();
827
- framework = await AgentFramework.create(config());
828
- const booted = framework.getHostModeStatus();
829
- assert.equal(booted.quiesced, true, 'a restart after a rollback still boots quiesced');
830
- assert.equal(booted.reason, 'refold');
831
- assert.equal(booted.deferredWrites, 1, 'deferred writes were not orphaned by the rollback either');
832
- assert.equal(framework.getAgent('agent').getContextManager().currentBranch().name, 'rollback/agent/test');
833
- await framework.resume();
834
- assert.equal(framework.getHostModeStatus().quiesced, false);
835
- const texts = framework.getAgent('agent').getContextManager().getAllMessages()
836
- .map((m) => m.content[0].text);
837
- assert.deepEqual(texts.slice(-2), ['checkpoint', 'deferred during surgery']);
838
- await framework.stop();
839
- framework = await AgentFramework.create(config());
840
- assert.equal(framework.getHostModeStatus().quiesced, false, 'resume cleared the recovery file durably');
841
- }
842
- finally {
843
- await framework.stop();
844
- rmSync(dir, { recursive: true, force: true });
845
- }
846
- });
847
- test('a failed chronicle sync keeps flushed deferred writes in the durable queue until a sync succeeds', async () => {
848
- const dir = mkdtempSync(join(tmpdir(), 'host-quiesce-syncfail-'));
849
- const storePath = join(dir, 'store');
850
- const config = () => ({
851
- storePath,
852
- membrane: new MockMembrane().asMembrane(),
853
- agents: [{ name: 'agent', model: 'test-model', systemPrompt: 'test' }],
854
- modules: [],
855
- });
856
- let framework = await AgentFramework.create(config());
857
- try {
858
- await framework.quiesce({ reason: 'surgery' });
859
- const before = framework.getAgent('agent').getContextManager().getMessageCount();
860
- const add = framework.addMessage.bind(framework);
861
- add('user', [{ type: 'text', text: 'one' }]);
862
- add('user', [{ type: 'text', text: 'two' }]);
863
- const queuePath = join(storePath, 'recovery', 'deferred-writes.json');
864
- const pending = () => JSON.parse(readFileSync(queuePath, 'utf8')).pending.length;
865
- assert.equal(pending(), 2);
866
- // Every sync during resume fails: the messages are appended in memory
867
- // but must NOT be acknowledged — the durable queue keeps both.
868
- const store = framework.store;
869
- const realSync = store.sync.bind(store);
870
- store.sync = () => { throw new Error('disk full'); };
871
- await framework.resume();
872
- assert.deepEqual(framework.getAgent('agent').getContextManager().getAllMessages().slice(before)
873
- .map((m) => m.content[0].text), ['one', 'two'], 'landed in memory');
874
- assert.equal(framework.getHostModeStatus().deferredWrites, 0, 'nothing left pending in memory');
875
- assert.equal(pending(), 2, 'durable queue still lists both — not acked without a sync');
876
- // Sync works again: stop() acks (sync, then rewrite the queue).
877
- store.sync = realSync;
878
- await framework.stop();
879
- assert.equal(pending(), 0, 'acked once the chronicle state was durable');
880
- framework = await AgentFramework.create(config());
881
- assert.equal(framework.getHostModeStatus().deferredWrites, 0);
882
- assert.deepEqual(framework.getAgent('agent').getContextManager().getAllMessages().slice(before)
883
- .map((m) => m.content[0].text), ['one', 'two'], 'exactly once after reopen');
884
- }
885
- finally {
886
- await framework.stop();
887
- rmSync(dir, { recursive: true, force: true });
888
- }
889
- });
890
- const CRASH_CHILD = fileURLToPath(new URL('./helpers/quiesce-crash-child.js', import.meta.url));
891
- const CRASH_SCENARIOS = [
892
- { mode: 'after-ack', label: 'right after the first ack of the resume flush',
893
- expect: ['ACKED-BUT-NOT-SYNCED', 'STILL-PENDING'], bootQuiesced: true },
894
- { mode: 'before-sync', label: 'before the chronicle sync of the resume flush',
895
- expect: ['ACKED-BUT-NOT-SYNCED', 'STILL-PENDING'], bootQuiesced: true },
896
- { mode: 'turn-start-ack', label: "after an ORDINARY turn-start flush's sync but before its queue rewrite",
897
- expect: ['ONCE-ONLY'], bootQuiesced: false },
898
- { mode: 'redefer', label: "at the first re-deferral write of a two-message batch (abandoned turn's teardown while quiesced)",
899
- expect: ['REDEFER-FIRST', 'REDEFER-SECOND'], bootQuiesced: true },
900
- { mode: 'big-batch', label: 'after a 2,101-message resume batch was synced but before it was acked',
901
- expect: Array.from({ length: 2_101 }, (_, i) => `BIG-${i}`), bootQuiesced: true },
902
- ];
903
- for (const scenario of CRASH_SCENARIOS) {
904
- test(`a REAL process exit ${scenario.label} loses no deferred write and duplicates none`, async () => {
905
- const dir = mkdtempSync(join(tmpdir(), `host-quiesce-crash-${scenario.mode}-`));
906
- const storePath = join(dir, 'store');
907
- const config = () => ({
908
- storePath,
909
- membrane: new MockMembrane().asMembrane(),
910
- agents: [{ name: 'agent', model: 'test-model', systemPrompt: 'test' }],
911
- modules: [],
912
- });
913
- let framework = null;
914
- try {
915
- const child = spawnSync(process.execPath, [CRASH_CHILD, storePath, scenario.mode], {
916
- encoding: 'utf8',
917
- timeout: 60_000,
918
- });
919
- assert.equal(child.status, 0, `child staged the crash (stderr: ${child.stderr.slice(-800)})`);
920
- const wanted = new Set(scenario.expect);
921
- const texts = () => framework.getAgent('agent').getContextManager().getAllMessages()
922
- .map((m) => m.content[0].text)
923
- .filter((t) => wanted.has(t));
924
- framework = await AgentFramework.create(config());
925
- const booted = framework.getHostModeStatus();
926
- assert.equal(booted.quiesced, scenario.bootQuiesced);
927
- if (booted.quiesced)
928
- await framework.resume();
929
- assert.deepEqual(texts(), [...scenario.expect], 'present exactly once, in order');
930
- assert.equal(framework.getHostModeStatus().deferredWrites, 0);
931
- await framework.stop();
932
- framework = await AgentFramework.create(config());
933
- assert.equal(framework.getHostModeStatus().quiesced, false);
934
- assert.equal(framework.getHostModeStatus().deferredWrites, 0);
935
- assert.deepEqual(texts(), [...scenario.expect], 'still exactly once after a second reopen');
936
- }
937
- finally {
938
- await framework?.stop();
939
- rmSync(dir, { recursive: true, force: true });
940
- }
941
- });
942
- }
943
- test('a serving boot recovers a stranded deferred-write queue regardless of the mode flag', async () => {
944
- const dir = mkdtempSync(join(tmpdir(), 'host-quiesce-stranded-'));
945
- const storePath = join(dir, 'store');
946
- const config = () => ({
947
- storePath,
948
- membrane: new MockMembrane().asMembrane(),
949
- agents: [{ name: 'agent', model: 'test-model', systemPrompt: 'test' }],
950
- modules: [],
951
- });
952
- let framework = await AgentFramework.create(config());
953
- let before;
954
- try {
955
- before = framework.getAgent('agent').getContextManager().getMessageCount();
956
- await framework.stop();
957
- // The state an older build could leave behind: flag cleared, queue not.
958
- mkdirSync(join(storePath, 'recovery'), { recursive: true });
959
- writeFileSync(join(storePath, 'recovery', 'host-mode.json'), JSON.stringify({ version: 1, quiesced: false }));
960
- writeFileSync(join(storePath, 'recovery', 'deferred-writes.json'), JSON.stringify({
961
- version: 1,
962
- pending: [{ id: 'stranded-1', participant: 'user', content: [{ type: 'text', text: 'stranded' }] }],
963
- }));
964
- framework = await AgentFramework.create(config());
965
- assert.equal(framework.getHostModeStatus().quiesced, false);
966
- assert.equal(framework.getHostModeStatus().deferredWrites, 0, 'recovered at boot');
967
- const texts = framework.getAgent('agent').getContextManager().getAllMessages().slice(before)
968
- .map((m) => m.content[0].text);
969
- assert.deepEqual(texts, ['stranded']);
970
- const queue = JSON.parse(readFileSync(join(storePath, 'recovery', 'deferred-writes.json'), 'utf8'));
971
- assert.equal(queue.pending.length, 0, 'acked durably');
972
- }
973
- finally {
974
- await framework.stop();
975
- rmSync(dir, { recursive: true, force: true });
976
- }
977
- });
978
- test('nudge while quiesced says so', async () => {
979
- const membrane = new MockMembrane();
980
- await withFramework(membrane, async (framework) => {
981
- await framework.quiesce();
982
- const r = framework.nudgeAgent('agent', 'operator');
983
- assert.equal(r.ok, true);
984
- assert.equal(r.quiesced, true);
985
- assert.equal(framework.getHostModeStatus().gatedRequests, 1);
986
- });
987
- });
988
- //# sourceMappingURL=host-quiesce.test.js.map