@provos/ironcurtain 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (660) hide show
  1. package/README.md +68 -14
  2. package/dist/auth/oauth-provider.js +1 -4
  3. package/dist/auth/oauth-provider.js.map +1 -1
  4. package/dist/cli-help.d.ts +12 -0
  5. package/dist/cli-help.js +21 -0
  6. package/dist/cli-help.js.map +1 -1
  7. package/dist/cli.js +46 -6
  8. package/dist/cli.js.map +1 -1
  9. package/dist/config/agent-model-guard.d.ts +14 -0
  10. package/dist/config/agent-model-guard.js +24 -0
  11. package/dist/config/agent-model-guard.js.map +1 -0
  12. package/dist/config/config-command.js +277 -7
  13. package/dist/config/config-command.js.map +1 -1
  14. package/dist/config/first-start.js +62 -7
  15. package/dist/config/first-start.js.map +1 -1
  16. package/dist/config/generated/compiled-policy.json +528 -161
  17. package/dist/config/generated/test-scenarios.json +4810 -170
  18. package/dist/config/generated/tool-annotations.json +34 -47
  19. package/dist/config/index.d.ts +58 -0
  20. package/dist/config/index.js +97 -15
  21. package/dist/config/index.js.map +1 -1
  22. package/dist/config/mcp-servers.json +2 -2
  23. package/dist/config/model-provider.d.ts +9 -0
  24. package/dist/config/model-provider.js +13 -0
  25. package/dist/config/model-provider.js.map +1 -1
  26. package/dist/config/paths.d.ts +217 -0
  27. package/dist/config/paths.js +363 -14
  28. package/dist/config/paths.js.map +1 -1
  29. package/dist/config/types.d.ts +7 -1
  30. package/dist/config/user-config.d.ts +101 -6
  31. package/dist/config/user-config.js +145 -31
  32. package/dist/config/user-config.js.map +1 -1
  33. package/dist/config/validate-policy-dir.d.ts +10 -0
  34. package/dist/config/validate-policy-dir.js +59 -0
  35. package/dist/config/validate-policy-dir.js.map +1 -0
  36. package/dist/cron/job-commands.js +22 -2
  37. package/dist/cron/job-commands.js.map +1 -1
  38. package/dist/cron/types.d.ts +16 -2
  39. package/dist/cron/types.js +1 -3
  40. package/dist/cron/types.js.map +1 -1
  41. package/dist/daemon/daemon-command.js +30 -7
  42. package/dist/daemon/daemon-command.js.map +1 -1
  43. package/dist/daemon/ironcurtain-daemon.d.ts +62 -1
  44. package/dist/daemon/ironcurtain-daemon.js +231 -8
  45. package/dist/daemon/ironcurtain-daemon.js.map +1 -1
  46. package/dist/daemon-client/daemon-client.d.ts +123 -0
  47. package/dist/daemon-client/daemon-client.js +324 -0
  48. package/dist/daemon-client/daemon-client.js.map +1 -0
  49. package/dist/docker/adapters/claude-code.js +194 -20
  50. package/dist/docker/adapters/claude-code.js.map +1 -1
  51. package/dist/docker/adapters/codex.d.ts +9 -0
  52. package/dist/docker/adapters/codex.js +297 -0
  53. package/dist/docker/adapters/codex.js.map +1 -0
  54. package/dist/docker/adapters/goose.d.ts +12 -11
  55. package/dist/docker/adapters/goose.js +80 -27
  56. package/dist/docker/adapters/goose.js.map +1 -1
  57. package/dist/docker/agent-adapter.d.ts +183 -5
  58. package/dist/docker/agent-adapter.js +16 -0
  59. package/dist/docker/agent-adapter.js.map +1 -1
  60. package/dist/docker/agent-registry.js +5 -0
  61. package/dist/docker/agent-registry.js.map +1 -1
  62. package/dist/docker/apple-container-manager.d.ts +49 -0
  63. package/dist/docker/apple-container-manager.js +464 -0
  64. package/dist/docker/apple-container-manager.js.map +1 -0
  65. package/dist/docker/code-mode-proxy.d.ts +38 -0
  66. package/dist/docker/code-mode-proxy.js +6 -1
  67. package/dist/docker/code-mode-proxy.js.map +1 -1
  68. package/dist/docker/container-lifecycle.d.ts +2 -2
  69. package/dist/docker/container-lifecycle.js.map +1 -1
  70. package/dist/docker/container-runtime.d.ts +29 -0
  71. package/dist/docker/container-runtime.js +76 -0
  72. package/dist/docker/container-runtime.js.map +1 -0
  73. package/dist/docker/docker-agent-session.d.ts +113 -62
  74. package/dist/docker/docker-agent-session.js +271 -294
  75. package/dist/docker/docker-agent-session.js.map +1 -1
  76. package/dist/docker/docker-infrastructure.d.ts +428 -26
  77. package/dist/docker/docker-infrastructure.js +1005 -70
  78. package/dist/docker/docker-infrastructure.js.map +1 -1
  79. package/dist/docker/docker-manager.d.ts +58 -3
  80. package/dist/docker/docker-manager.js +378 -33
  81. package/dist/docker/docker-manager.js.map +1 -1
  82. package/dist/docker/docker-probe.d.ts +45 -0
  83. package/dist/docker/docker-probe.js +86 -0
  84. package/dist/docker/docker-probe.js.map +1 -0
  85. package/dist/docker/docker-progress-sink.d.ts +43 -0
  86. package/dist/docker/docker-progress-sink.js +299 -0
  87. package/dist/docker/docker-progress-sink.js.map +1 -0
  88. package/dist/docker/mitm-proxy.d.ts +135 -1
  89. package/dist/docker/mitm-proxy.js +611 -25
  90. package/dist/docker/mitm-proxy.js.map +1 -1
  91. package/dist/docker/network-topology.d.ts +81 -0
  92. package/dist/docker/network-topology.js +160 -0
  93. package/dist/docker/network-topology.js.map +1 -0
  94. package/dist/docker/oauth-credentials.d.ts +59 -3
  95. package/dist/docker/oauth-credentials.js +181 -14
  96. package/dist/docker/oauth-credentials.js.map +1 -1
  97. package/dist/docker/oauth-token-manager.js +2 -2
  98. package/dist/docker/oauth-token-manager.js.map +1 -1
  99. package/dist/docker/orientation.d.ts +1 -1
  100. package/dist/docker/package-types.d.ts +1 -1
  101. package/dist/docker/provider-config.d.ts +78 -3
  102. package/dist/docker/provider-config.js +295 -31
  103. package/dist/docker/provider-config.js.map +1 -1
  104. package/dist/docker/provision-lock.d.ts +46 -0
  105. package/dist/docker/provision-lock.js +152 -0
  106. package/dist/docker/provision-lock.js.map +1 -0
  107. package/dist/docker/proxy-tools.d.ts +0 -2
  108. package/dist/docker/proxy-tools.js +2 -7
  109. package/dist/docker/proxy-tools.js.map +1 -1
  110. package/dist/docker/pty-session.d.ts +64 -1
  111. package/dist/docker/pty-session.js +306 -104
  112. package/dist/docker/pty-session.js.map +1 -1
  113. package/dist/docker/pty-types.d.ts +0 -2
  114. package/dist/docker/pty-types.js +0 -2
  115. package/dist/docker/pty-types.js.map +1 -1
  116. package/dist/docker/registry-proxy.d.ts +46 -0
  117. package/dist/docker/registry-proxy.js +255 -1
  118. package/dist/docker/registry-proxy.js.map +1 -1
  119. package/dist/docker/resource-limits.d.ts +134 -0
  120. package/dist/docker/resource-limits.js +203 -0
  121. package/dist/docker/resource-limits.js.map +1 -0
  122. package/dist/docker/spawn-with-idle-timeout.d.ts +39 -0
  123. package/dist/docker/spawn-with-idle-timeout.js +152 -0
  124. package/dist/docker/spawn-with-idle-timeout.js.map +1 -0
  125. package/dist/docker/sse-extractor.d.ts +51 -0
  126. package/dist/docker/sse-extractor.js +303 -0
  127. package/dist/docker/sse-extractor.js.map +1 -0
  128. package/dist/docker/token-stream-bus.d.ts +83 -0
  129. package/dist/docker/token-stream-bus.js +98 -0
  130. package/dist/docker/token-stream-bus.js.map +1 -0
  131. package/dist/docker/token-stream-types.d.ts +71 -0
  132. package/dist/docker/token-stream-types.js +8 -0
  133. package/dist/docker/token-stream-types.js.map +1 -0
  134. package/dist/docker/trajectory-capture.d.ts +79 -0
  135. package/dist/docker/trajectory-capture.js +521 -0
  136. package/dist/docker/trajectory-capture.js.map +1 -0
  137. package/dist/docker/trajectory-reassembler.d.ts +286 -0
  138. package/dist/docker/trajectory-reassembler.js +990 -0
  139. package/dist/docker/trajectory-reassembler.js.map +1 -0
  140. package/dist/docker/trajectory-tap.d.ts +100 -0
  141. package/dist/docker/trajectory-tap.js +410 -0
  142. package/dist/docker/trajectory-tap.js.map +1 -0
  143. package/dist/docker/trajectory-types.d.ts +187 -0
  144. package/dist/docker/trajectory-types.js +43 -0
  145. package/dist/docker/trajectory-types.js.map +1 -0
  146. package/dist/docker/types.d.ts +105 -12
  147. package/dist/doctor/checks.d.ts +171 -0
  148. package/dist/doctor/checks.js +598 -0
  149. package/dist/doctor/checks.js.map +1 -0
  150. package/dist/doctor/doctor-command.d.ts +29 -0
  151. package/dist/doctor/doctor-command.js +190 -0
  152. package/dist/doctor/doctor-command.js.map +1 -0
  153. package/dist/doctor/mcp-liveness.d.ts +28 -0
  154. package/dist/doctor/mcp-liveness.js +92 -0
  155. package/dist/doctor/mcp-liveness.js.map +1 -0
  156. package/dist/doctor/oauth-checks.d.ts +23 -0
  157. package/dist/doctor/oauth-checks.js +157 -0
  158. package/dist/doctor/oauth-checks.js.map +1 -0
  159. package/dist/doctor/output.d.ts +26 -0
  160. package/dist/doctor/output.js +82 -0
  161. package/dist/doctor/output.js.map +1 -0
  162. package/dist/escalation/listener-command.js +0 -3
  163. package/dist/escalation/listener-command.js.map +1 -1
  164. package/dist/event-bus/typed-event-bus.d.ts +26 -0
  165. package/dist/event-bus/typed-event-bus.js +35 -0
  166. package/dist/event-bus/typed-event-bus.js.map +1 -0
  167. package/dist/index.js +54 -21
  168. package/dist/index.js.map +1 -1
  169. package/dist/logger.js +31 -2
  170. package/dist/logger.js.map +1 -1
  171. package/dist/memory/auto-save.d.ts +18 -4
  172. package/dist/memory/auto-save.js +46 -6
  173. package/dist/memory/auto-save.js.map +1 -1
  174. package/dist/memory/memory-policy.d.ts +41 -0
  175. package/dist/memory/memory-policy.js +36 -0
  176. package/dist/memory/memory-policy.js.map +1 -0
  177. package/dist/mux/mux-app.d.ts +2 -0
  178. package/dist/mux/mux-app.js +1 -0
  179. package/dist/mux/mux-app.js.map +1 -1
  180. package/dist/mux/mux-command.d.ts +10 -1
  181. package/dist/mux/mux-command.js +74 -40
  182. package/dist/mux/mux-command.js.map +1 -1
  183. package/dist/mux/mux-renderer.js +2 -12
  184. package/dist/mux/mux-renderer.js.map +1 -1
  185. package/dist/mux/pty-bridge.d.ts +2 -0
  186. package/dist/mux/pty-bridge.js +3 -0
  187. package/dist/mux/pty-bridge.js.map +1 -1
  188. package/dist/mux/session-scanner.js +1 -2
  189. package/dist/mux/session-scanner.js.map +1 -1
  190. package/dist/{pipeline → observability}/llm-logger.d.ts +8 -3
  191. package/dist/{pipeline → observability}/llm-logger.js +8 -3
  192. package/dist/observability/llm-logger.js.map +1 -0
  193. package/dist/observe/observe-command.d.ts +12 -0
  194. package/dist/observe/observe-command.js +285 -0
  195. package/dist/observe/observe-command.js.map +1 -0
  196. package/dist/observe/observe-renderer.d.ts +24 -0
  197. package/dist/observe/observe-renderer.js +87 -0
  198. package/dist/observe/observe-renderer.js.map +1 -0
  199. package/dist/observe/observe-tui-rain.d.ts +42 -0
  200. package/dist/observe/observe-tui-rain.js +531 -0
  201. package/dist/observe/observe-tui-rain.js.map +1 -0
  202. package/dist/observe/observe-tui-text-panel.d.ts +46 -0
  203. package/dist/observe/observe-tui-text-panel.js +525 -0
  204. package/dist/observe/observe-tui-text-panel.js.map +1 -0
  205. package/dist/observe/observe-tui-types.d.ts +270 -0
  206. package/dist/observe/observe-tui-types.js +200 -0
  207. package/dist/observe/observe-tui-types.js.map +1 -0
  208. package/dist/observe/observe-tui-word-scorer.d.ts +143 -0
  209. package/dist/observe/observe-tui-word-scorer.js +572 -0
  210. package/dist/observe/observe-tui-word-scorer.js.map +1 -0
  211. package/dist/observe/observe-tui.d.ts +59 -0
  212. package/dist/observe/observe-tui.js +592 -0
  213. package/dist/observe/observe-tui.js.map +1 -0
  214. package/dist/persona/broad-policy-validator.d.ts +95 -0
  215. package/dist/persona/broad-policy-validator.js +171 -0
  216. package/dist/persona/broad-policy-validator.js.map +1 -0
  217. package/dist/persona/compile-persona-policy.d.ts +54 -2
  218. package/dist/persona/compile-persona-policy.js +29 -4
  219. package/dist/persona/compile-persona-policy.js.map +1 -1
  220. package/dist/persona/event-bus-progress-reporter.d.ts +57 -0
  221. package/dist/persona/event-bus-progress-reporter.js +66 -0
  222. package/dist/persona/event-bus-progress-reporter.js.map +1 -0
  223. package/dist/persona/memory-gate.d.ts +19 -0
  224. package/dist/persona/memory-gate.js +33 -0
  225. package/dist/persona/memory-gate.js.map +1 -0
  226. package/dist/persona/persona-command.js +77 -72
  227. package/dist/persona/persona-command.js.map +1 -1
  228. package/dist/persona/persona-compile-orchestrator.d.ts +101 -0
  229. package/dist/persona/persona-compile-orchestrator.js +504 -0
  230. package/dist/persona/persona-compile-orchestrator.js.map +1 -0
  231. package/dist/persona/persona-service.d.ts +137 -0
  232. package/dist/persona/persona-service.js +263 -0
  233. package/dist/persona/persona-service.js.map +1 -0
  234. package/dist/persona/policy-mutation-audit.d.ts +109 -0
  235. package/dist/persona/policy-mutation-audit.js +179 -0
  236. package/dist/persona/policy-mutation-audit.js.map +1 -0
  237. package/dist/persona/resolve.d.ts +22 -0
  238. package/dist/persona/resolve.js +45 -2
  239. package/dist/persona/resolve.js.map +1 -1
  240. package/dist/persona/rule-delta.d.ts +30 -0
  241. package/dist/persona/rule-delta.js +82 -0
  242. package/dist/persona/rule-delta.js.map +1 -0
  243. package/dist/persona/types.d.ts +28 -0
  244. package/dist/pipeline/annotate.js +10 -2
  245. package/dist/pipeline/annotate.js.map +1 -1
  246. package/dist/pipeline/compile.js +14 -2
  247. package/dist/pipeline/compile.js.map +1 -1
  248. package/dist/pipeline/constitution-compiler.d.ts +25 -14
  249. package/dist/pipeline/constitution-compiler.js +107 -38
  250. package/dist/pipeline/constitution-compiler.js.map +1 -1
  251. package/dist/pipeline/dynamic-list-types.d.ts +3 -6
  252. package/dist/pipeline/dynamic-list-types.js +3 -16
  253. package/dist/pipeline/dynamic-list-types.js.map +1 -1
  254. package/dist/pipeline/pipeline-runner.d.ts +63 -4
  255. package/dist/pipeline/pipeline-runner.js +242 -94
  256. package/dist/pipeline/pipeline-runner.js.map +1 -1
  257. package/dist/pipeline/pipeline-shared.d.ts +33 -4
  258. package/dist/pipeline/pipeline-shared.js +79 -19
  259. package/dist/pipeline/pipeline-shared.js.map +1 -1
  260. package/dist/pipeline/policy-verifier.js +16 -3
  261. package/dist/pipeline/policy-verifier.js.map +1 -1
  262. package/dist/pipeline/proxy-mcp-connections.js +17 -2
  263. package/dist/pipeline/proxy-mcp-connections.js.map +1 -1
  264. package/dist/pipeline/refresh-lists.js +3 -5
  265. package/dist/pipeline/refresh-lists.js.map +1 -1
  266. package/dist/pipeline/scenario-generator.d.ts +4 -8
  267. package/dist/pipeline/scenario-generator.js +13 -46
  268. package/dist/pipeline/scenario-generator.js.map +1 -1
  269. package/dist/sandbox/index.d.ts +29 -0
  270. package/dist/sandbox/index.js +351 -119
  271. package/dist/sandbox/index.js.map +1 -1
  272. package/dist/sandbox/ironcurtain-protocol.d.ts +52 -0
  273. package/dist/sandbox/ironcurtain-protocol.js +185 -0
  274. package/dist/sandbox/ironcurtain-protocol.js.map +1 -0
  275. package/dist/session/agent-session.d.ts +6 -0
  276. package/dist/session/agent-session.js +16 -5
  277. package/dist/session/agent-session.js.map +1 -1
  278. package/dist/session/cli-transport.js +0 -6
  279. package/dist/session/cli-transport.js.map +1 -1
  280. package/dist/session/index.d.ts +35 -14
  281. package/dist/session/index.js +333 -130
  282. package/dist/session/index.js.map +1 -1
  283. package/dist/session/preflight.d.ts +21 -13
  284. package/dist/session/preflight.js +227 -88
  285. package/dist/session/preflight.js.map +1 -1
  286. package/dist/session/prompts.d.ts +2 -5
  287. package/dist/session/prompts.js.map +1 -1
  288. package/dist/session/session-manager.d.ts +61 -6
  289. package/dist/session/session-manager.js +72 -10
  290. package/dist/session/session-manager.js.map +1 -1
  291. package/dist/session/session-metadata.d.ts +21 -5
  292. package/dist/session/session-metadata.js +34 -12
  293. package/dist/session/session-metadata.js.map +1 -1
  294. package/dist/session/types.d.ts +320 -5
  295. package/dist/session/types.js +57 -1
  296. package/dist/session/types.js.map +1 -1
  297. package/dist/signal/bot-command.js +6 -1
  298. package/dist/signal/bot-command.js.map +1 -1
  299. package/dist/signal/setup-signal.js +13 -21
  300. package/dist/signal/setup-signal.js.map +1 -1
  301. package/dist/signal/signal-bot-daemon.d.ts +16 -1
  302. package/dist/signal/signal-bot-daemon.js +39 -27
  303. package/dist/signal/signal-bot-daemon.js.map +1 -1
  304. package/dist/signal/signal-container.d.ts +3 -3
  305. package/dist/signal/signal-container.js +9 -3
  306. package/dist/signal/signal-container.js.map +1 -1
  307. package/dist/skills/discovery.d.ts +77 -0
  308. package/dist/skills/discovery.js +206 -0
  309. package/dist/skills/discovery.js.map +1 -0
  310. package/dist/skills/index.d.ts +4 -0
  311. package/dist/skills/index.js +3 -0
  312. package/dist/skills/index.js.map +1 -0
  313. package/dist/skills/staging.d.ts +28 -0
  314. package/dist/skills/staging.js +68 -0
  315. package/dist/skills/staging.js.map +1 -0
  316. package/dist/skills/types.d.ts +46 -0
  317. package/dist/skills/types.js +2 -0
  318. package/dist/skills/types.js.map +1 -0
  319. package/dist/trusted-process/approval-whitelist.d.ts +0 -2
  320. package/dist/trusted-process/approval-whitelist.js +17 -17
  321. package/dist/trusted-process/approval-whitelist.js.map +1 -1
  322. package/dist/trusted-process/async-mutex.d.ts +32 -0
  323. package/dist/trusted-process/async-mutex.js +50 -0
  324. package/dist/trusted-process/async-mutex.js.map +1 -0
  325. package/dist/trusted-process/audit-log.d.ts +38 -1
  326. package/dist/trusted-process/audit-log.js +82 -13
  327. package/dist/trusted-process/audit-log.js.map +1 -1
  328. package/dist/trusted-process/call-circuit-breaker.d.ts +6 -0
  329. package/dist/trusted-process/call-circuit-breaker.js +23 -3
  330. package/dist/trusted-process/call-circuit-breaker.js.map +1 -1
  331. package/dist/trusted-process/container-command.d.ts +35 -0
  332. package/dist/trusted-process/container-command.js +49 -0
  333. package/dist/trusted-process/container-command.js.map +1 -0
  334. package/dist/trusted-process/control-server.d.ts +101 -0
  335. package/dist/trusted-process/control-server.js +282 -0
  336. package/dist/trusted-process/control-server.js.map +1 -0
  337. package/dist/trusted-process/domain-utils.d.ts +6 -6
  338. package/dist/trusted-process/domain-utils.js +7 -23
  339. package/dist/trusted-process/domain-utils.js.map +1 -1
  340. package/dist/trusted-process/error-prefixes.d.ts +16 -0
  341. package/dist/trusted-process/error-prefixes.js +17 -0
  342. package/dist/trusted-process/error-prefixes.js.map +1 -0
  343. package/dist/trusted-process/index.d.ts +40 -23
  344. package/dist/trusted-process/index.js +131 -225
  345. package/dist/trusted-process/index.js.map +1 -1
  346. package/dist/trusted-process/list-matcher.d.ts +17 -0
  347. package/dist/trusted-process/list-matcher.js +31 -0
  348. package/dist/trusted-process/list-matcher.js.map +1 -0
  349. package/dist/trusted-process/mcp-client-manager.d.ts +35 -6
  350. package/dist/trusted-process/mcp-client-manager.js +40 -45
  351. package/dist/trusted-process/mcp-client-manager.js.map +1 -1
  352. package/dist/trusted-process/mcp-proxy-server.d.ts +31 -120
  353. package/dist/trusted-process/mcp-proxy-server.js +201 -660
  354. package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
  355. package/dist/trusted-process/policy-engine.d.ts +16 -4
  356. package/dist/trusted-process/policy-engine.js +103 -47
  357. package/dist/trusted-process/policy-engine.js.map +1 -1
  358. package/dist/trusted-process/policy-roots.d.ts +6 -0
  359. package/dist/trusted-process/policy-roots.js +20 -0
  360. package/dist/trusted-process/policy-roots.js.map +1 -1
  361. package/dist/trusted-process/sandbox-integration.d.ts +12 -0
  362. package/dist/trusted-process/sandbox-integration.js +18 -0
  363. package/dist/trusted-process/sandbox-integration.js.map +1 -1
  364. package/dist/trusted-process/tcp-server-transport.d.ts +12 -1
  365. package/dist/trusted-process/tcp-server-transport.js +9 -1
  366. package/dist/trusted-process/tcp-server-transport.js.map +1 -1
  367. package/dist/trusted-process/tool-call-coordinator.d.ts +283 -0
  368. package/dist/trusted-process/tool-call-coordinator.js +592 -0
  369. package/dist/trusted-process/tool-call-coordinator.js.map +1 -0
  370. package/dist/trusted-process/tool-call-pipeline.d.ts +213 -0
  371. package/dist/trusted-process/tool-call-pipeline.js +832 -0
  372. package/dist/trusted-process/tool-call-pipeline.js.map +1 -0
  373. package/dist/trusted-process/tool-description-hints.d.ts +1 -1
  374. package/dist/types/argument-roles.d.ts +1 -1
  375. package/dist/types/argument-roles.js +14 -1
  376. package/dist/types/argument-roles.js.map +1 -1
  377. package/dist/types/audit.d.ts +9 -0
  378. package/dist/{session → types}/errors.d.ts +8 -2
  379. package/dist/{session → types}/errors.js +8 -2
  380. package/dist/types/errors.js.map +1 -0
  381. package/dist/types/reserved-servers.d.ts +11 -0
  382. package/dist/types/reserved-servers.js +12 -0
  383. package/dist/types/reserved-servers.js.map +1 -0
  384. package/dist/types/server-listing.d.ts +14 -0
  385. package/dist/types/server-listing.js +2 -0
  386. package/dist/types/server-listing.js.map +1 -0
  387. package/dist/types/slug.d.ts +2 -0
  388. package/dist/types/slug.js +2 -0
  389. package/dist/types/slug.js.map +1 -1
  390. package/dist/types/url-normalize.d.ts +16 -0
  391. package/dist/types/url-normalize.js +33 -0
  392. package/dist/types/url-normalize.js.map +1 -0
  393. package/dist/util/atomic-write.d.ts +31 -0
  394. package/dist/util/atomic-write.js +43 -0
  395. package/dist/util/atomic-write.js.map +1 -0
  396. package/dist/utils/error-message.d.ts +8 -0
  397. package/dist/utils/error-message.js +11 -0
  398. package/dist/utils/error-message.js.map +1 -0
  399. package/dist/utils/exec-error.d.ts +19 -0
  400. package/dist/utils/exec-error.js +16 -0
  401. package/dist/utils/exec-error.js.map +1 -0
  402. package/dist/utils/is-plain-object.d.ts +7 -0
  403. package/dist/utils/is-plain-object.js +12 -0
  404. package/dist/utils/is-plain-object.js.map +1 -0
  405. package/dist/utils/preflight-checks.d.ts +16 -0
  406. package/dist/utils/preflight-checks.js +178 -0
  407. package/dist/utils/preflight-checks.js.map +1 -0
  408. package/dist/web-ui/__tests__/json-rpc-dispatch.test.d.ts +7 -0
  409. package/dist/web-ui/__tests__/json-rpc-dispatch.test.js +725 -0
  410. package/dist/web-ui/__tests__/json-rpc-dispatch.test.js.map +1 -0
  411. package/dist/web-ui/conn-registry.d.ts +14 -0
  412. package/dist/web-ui/conn-registry.js +25 -0
  413. package/dist/web-ui/conn-registry.js.map +1 -0
  414. package/dist/web-ui/dispatch/escalation-dispatch.d.ts +7 -0
  415. package/dist/web-ui/dispatch/escalation-dispatch.js +52 -0
  416. package/dist/web-ui/dispatch/escalation-dispatch.js.map +1 -0
  417. package/dist/web-ui/dispatch/job-dispatch.d.ts +8 -0
  418. package/dist/web-ui/dispatch/job-dispatch.js +83 -0
  419. package/dist/web-ui/dispatch/job-dispatch.js.map +1 -0
  420. package/dist/web-ui/dispatch/persona-dispatch.d.ts +50 -0
  421. package/dist/web-ui/dispatch/persona-dispatch.js +269 -0
  422. package/dist/web-ui/dispatch/persona-dispatch.js.map +1 -0
  423. package/dist/web-ui/dispatch/session-dispatch.d.ts +9 -0
  424. package/dist/web-ui/dispatch/session-dispatch.js +219 -0
  425. package/dist/web-ui/dispatch/session-dispatch.js.map +1 -0
  426. package/dist/web-ui/dispatch/token-stream-dispatch.d.ts +15 -0
  427. package/dist/web-ui/dispatch/token-stream-dispatch.js +55 -0
  428. package/dist/web-ui/dispatch/token-stream-dispatch.js.map +1 -0
  429. package/dist/web-ui/dispatch/types.d.ts +54 -0
  430. package/dist/web-ui/dispatch/types.js +72 -0
  431. package/dist/web-ui/dispatch/types.js.map +1 -0
  432. package/dist/web-ui/dispatch/workflow-dispatch.d.ts +103 -0
  433. package/dist/web-ui/dispatch/workflow-dispatch.js +1036 -0
  434. package/dist/web-ui/dispatch/workflow-dispatch.js.map +1 -0
  435. package/dist/web-ui/json-rpc-dispatch.d.ts +12 -0
  436. package/dist/web-ui/json-rpc-dispatch.js +34 -0
  437. package/dist/web-ui/json-rpc-dispatch.js.map +1 -0
  438. package/dist/web-ui/state-graph.d.ts +13 -0
  439. package/dist/web-ui/state-graph.js +82 -0
  440. package/dist/web-ui/state-graph.js.map +1 -0
  441. package/dist/web-ui/token-stream-bridge.d.ts +76 -0
  442. package/dist/web-ui/token-stream-bridge.js +265 -0
  443. package/dist/web-ui/token-stream-bridge.js.map +1 -0
  444. package/dist/web-ui/web-event-bus.d.ts +176 -0
  445. package/dist/web-ui/web-event-bus.js +19 -0
  446. package/dist/web-ui/web-event-bus.js.map +1 -0
  447. package/dist/web-ui/web-session-transport.d.ts +31 -0
  448. package/dist/web-ui/web-session-transport.js +109 -0
  449. package/dist/web-ui/web-session-transport.js.map +1 -0
  450. package/dist/web-ui/web-ui-server.d.ts +90 -0
  451. package/dist/web-ui/web-ui-server.js +477 -0
  452. package/dist/web-ui/web-ui-server.js.map +1 -0
  453. package/dist/web-ui/web-ui-types.d.ts +418 -0
  454. package/dist/web-ui/web-ui-types.js +32 -0
  455. package/dist/web-ui/web-ui-types.js.map +1 -0
  456. package/dist/web-ui/ws-utils.d.ts +5 -0
  457. package/dist/web-ui/ws-utils.js +12 -0
  458. package/dist/web-ui/ws-utils.js.map +1 -0
  459. package/dist/web-ui-static/assets/index-BD5U6ILh.css +1 -0
  460. package/dist/web-ui-static/assets/index-FMsHWEfK.js +79 -0
  461. package/dist/web-ui-static/assets/orbitron-latin-700-normal-4jsRXGGJ.woff2 +0 -0
  462. package/dist/web-ui-static/assets/orbitron-latin-700-normal-DmYOh-W9.woff +0 -0
  463. package/dist/web-ui-static/index.html +14 -0
  464. package/dist/workflow/artifacts.d.ts +59 -0
  465. package/dist/workflow/artifacts.js +188 -0
  466. package/dist/workflow/artifacts.js.map +1 -0
  467. package/dist/workflow/checkpoint-selection.d.ts +34 -0
  468. package/dist/workflow/checkpoint-selection.js +48 -0
  469. package/dist/workflow/checkpoint-selection.js.map +1 -0
  470. package/dist/workflow/checkpoint.d.ts +35 -0
  471. package/dist/workflow/checkpoint.js +84 -0
  472. package/dist/workflow/checkpoint.js.map +1 -0
  473. package/dist/workflow/cli-shared.d.ts +62 -0
  474. package/dist/workflow/cli-shared.js +117 -0
  475. package/dist/workflow/cli-shared.js.map +1 -0
  476. package/dist/workflow/cli-support.d.ts +92 -0
  477. package/dist/workflow/cli-support.js +421 -0
  478. package/dist/workflow/cli-support.js.map +1 -0
  479. package/dist/workflow/container-snapshots.d.ts +29 -0
  480. package/dist/workflow/container-snapshots.js +137 -0
  481. package/dist/workflow/container-snapshots.js.map +1 -0
  482. package/dist/workflow/daemon-gate-commands.d.ts +21 -0
  483. package/dist/workflow/daemon-gate-commands.js +599 -0
  484. package/dist/workflow/daemon-gate-commands.js.map +1 -0
  485. package/dist/workflow/definition-loader.d.ts +32 -0
  486. package/dist/workflow/definition-loader.js +56 -0
  487. package/dist/workflow/definition-loader.js.map +1 -0
  488. package/dist/workflow/discovery.d.ts +107 -0
  489. package/dist/workflow/discovery.js +263 -0
  490. package/dist/workflow/discovery.js.map +1 -0
  491. package/dist/workflow/errors.d.ts +66 -0
  492. package/dist/workflow/errors.js +49 -0
  493. package/dist/workflow/errors.js.map +1 -0
  494. package/dist/workflow/guards.d.ts +8 -0
  495. package/dist/workflow/guards.js +38 -0
  496. package/dist/workflow/guards.js.map +1 -0
  497. package/dist/workflow/lane-template.d.ts +89 -0
  498. package/dist/workflow/lane-template.js +141 -0
  499. package/dist/workflow/lane-template.js.map +1 -0
  500. package/dist/workflow/lint-integration.d.ts +64 -0
  501. package/dist/workflow/lint-integration.js +56 -0
  502. package/dist/workflow/lint-integration.js.map +1 -0
  503. package/dist/workflow/lint.d.ts +72 -0
  504. package/dist/workflow/lint.js +593 -0
  505. package/dist/workflow/lint.js.map +1 -0
  506. package/dist/workflow/machine-builder.d.ts +178 -0
  507. package/dist/workflow/machine-builder.js +678 -0
  508. package/dist/workflow/machine-builder.js.map +1 -0
  509. package/dist/workflow/message-log.d.ts +99 -0
  510. package/dist/workflow/message-log.js +40 -0
  511. package/dist/workflow/message-log.js.map +1 -0
  512. package/dist/workflow/orchestrator.d.ts +954 -0
  513. package/dist/workflow/orchestrator.js +3594 -0
  514. package/dist/workflow/orchestrator.js.map +1 -0
  515. package/dist/workflow/prompt-builder.d.ts +39 -0
  516. package/dist/workflow/prompt-builder.js +243 -0
  517. package/dist/workflow/prompt-builder.js.map +1 -0
  518. package/dist/workflow/run-state-command.d.ts +9 -0
  519. package/dist/workflow/run-state-command.js +414 -0
  520. package/dist/workflow/run-state-command.js.map +1 -0
  521. package/dist/workflow/run-state-debug-capture.d.ts +40 -0
  522. package/dist/workflow/run-state-debug-capture.js +101 -0
  523. package/dist/workflow/run-state-debug-capture.js.map +1 -0
  524. package/dist/workflow/status-parser.d.ts +68 -0
  525. package/dist/workflow/status-parser.js +274 -0
  526. package/dist/workflow/status-parser.js.map +1 -0
  527. package/dist/workflow/types.d.ts +598 -0
  528. package/dist/workflow/types.js +85 -0
  529. package/dist/workflow/types.js.map +1 -0
  530. package/dist/workflow/validate.d.ts +80 -0
  531. package/dist/workflow/validate.js +788 -0
  532. package/dist/workflow/validate.js.map +1 -0
  533. package/dist/workflow/workflow-command.d.ts +9 -0
  534. package/dist/workflow/workflow-command.js +670 -0
  535. package/dist/workflow/workflow-command.js.map +1 -0
  536. package/dist/workflow/workflow-discovery.d.ts +27 -0
  537. package/dist/workflow/workflow-discovery.js +121 -0
  538. package/dist/workflow/workflow-discovery.js.map +1 -0
  539. package/dist/workflow/workflow-manager.d.ts +156 -0
  540. package/dist/workflow/workflow-manager.js +359 -0
  541. package/dist/workflow/workflow-manager.js.map +1 -0
  542. package/dist/workflow/workflows/design-and-code/README.md +50 -0
  543. package/dist/workflow/workflows/design-and-code/workflow.yaml +169 -0
  544. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
  545. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
  546. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
  547. package/dist/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
  548. package/dist/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
  549. package/dist/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
  550. package/dist/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
  551. package/dist/workflow/workflows/evolve/scripts/LICENSE +201 -0
  552. package/dist/workflow/workflows/evolve/scripts/README.md +314 -0
  553. package/dist/workflow/workflows/evolve/scripts/evolve-brief +16 -0
  554. package/dist/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
  555. package/dist/workflow/workflows/evolve/scripts/evolve-db +16 -0
  556. package/dist/workflow/workflows/evolve/scripts/evolve-eval +16 -0
  557. package/dist/workflow/workflows/evolve/scripts/evolve-files +16 -0
  558. package/dist/workflow/workflows/evolve/scripts/evolve-summary +16 -0
  559. package/dist/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
  560. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
  561. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
  562. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
  563. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
  564. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
  565. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
  566. package/dist/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
  567. package/dist/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
  568. package/dist/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
  569. package/dist/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
  570. package/dist/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
  571. package/dist/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
  572. package/dist/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
  573. package/dist/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
  574. package/dist/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
  575. package/dist/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
  576. package/dist/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
  577. package/dist/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
  578. package/dist/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
  579. package/dist/workflow/workflows/evolve/scripts/requirements.txt +2 -0
  580. package/dist/workflow/workflows/evolve/workflow.yaml +646 -0
  581. package/dist/workflow/workflows/test-email-summary/skills/email-formatting/SKILL.md +55 -0
  582. package/dist/workflow/workflows/test-email-summary/skills/gmail-query-syntax/SKILL.md +63 -0
  583. package/dist/workflow/workflows/test-email-summary/skills/json-schema-emails/SKILL.md +41 -0
  584. package/dist/workflow/workflows/test-email-summary/skills/json-schema-emails/schema.json +34 -0
  585. package/dist/workflow/workflows/test-email-summary/skills/summary-style-guide/SKILL.md +51 -0
  586. package/dist/workflow/workflows/test-email-summary/workflow.yaml +90 -0
  587. package/dist/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +206 -0
  588. package/dist/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +167 -0
  589. package/dist/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +189 -0
  590. package/dist/workflow/workflows/vuln-discovery/workflow.yaml +925 -0
  591. package/dist/workflow/worktree.d.ts +43 -0
  592. package/dist/workflow/worktree.js +106 -0
  593. package/dist/workflow/worktree.js.map +1 -0
  594. package/docker/Dockerfile.base +31 -0
  595. package/docker/Dockerfile.base.arm64 +27 -0
  596. package/docker/Dockerfile.claude-code +3 -1
  597. package/docker/Dockerfile.codex +17 -0
  598. package/docker/Dockerfile.goose +3 -1
  599. package/docker/entrypoint-claude-code.sh +7 -0
  600. package/docker/entrypoint-codex.sh +42 -0
  601. package/docker/entrypoint-goose.sh +6 -0
  602. package/docker/entrypoint-uid-remap.sh +93 -0
  603. package/package.json +27 -11
  604. package/packages/web-ui/README.md +113 -0
  605. package/packages/web-ui/docs/workflow-state-machine.png +0 -0
  606. package/src/config/generated/compiled-policy.json +528 -161
  607. package/src/config/generated/test-scenarios.json +4810 -170
  608. package/src/config/generated/tool-annotations.json +34 -47
  609. package/src/config/mcp-servers.json +2 -2
  610. package/src/workflow/workflows/design-and-code/README.md +50 -0
  611. package/src/workflow/workflows/design-and-code/workflow.yaml +169 -0
  612. package/src/workflow/workflows/deterministic-eval-smoke/scripts/format_report.js +29 -0
  613. package/src/workflow/workflows/deterministic-eval-smoke/scripts/package.json +5 -0
  614. package/src/workflow/workflows/deterministic-eval-smoke/scripts/requirements.txt +1 -0
  615. package/src/workflow/workflows/deterministic-eval-smoke/scripts/run_eval.py +41 -0
  616. package/src/workflow/workflows/deterministic-eval-smoke/workflow.yaml +57 -0
  617. package/src/workflow/workflows/deterministic-verdict-smoke/scripts/classify.py +18 -0
  618. package/src/workflow/workflows/deterministic-verdict-smoke/workflow.yaml +51 -0
  619. package/src/workflow/workflows/evolve/scripts/LICENSE +201 -0
  620. package/src/workflow/workflows/evolve/scripts/README.md +314 -0
  621. package/src/workflow/workflows/evolve/scripts/evolve-brief +16 -0
  622. package/src/workflow/workflows/evolve/scripts/evolve-cognition +16 -0
  623. package/src/workflow/workflows/evolve/scripts/evolve-db +16 -0
  624. package/src/workflow/workflows/evolve/scripts/evolve-eval +16 -0
  625. package/src/workflow/workflows/evolve/scripts/evolve-files +16 -0
  626. package/src/workflow/workflows/evolve/scripts/evolve-summary +16 -0
  627. package/src/workflow/workflows/evolve/scripts/evolve_core/__init__.py +14 -0
  628. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/__init__.py +17 -0
  629. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/base.py +21 -0
  630. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/factory.py +90 -0
  631. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/greedy.py +17 -0
  632. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/island.py +316 -0
  633. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/random.py +18 -0
  634. package/src/workflow/workflows/evolve/scripts/evolve_core/algorithms/ucb1.py +55 -0
  635. package/src/workflow/workflows/evolve/scripts/evolve_core/best_snapshot.py +62 -0
  636. package/src/workflow/workflows/evolve/scripts/evolve_core/cli.py +752 -0
  637. package/src/workflow/workflows/evolve/scripts/evolve_core/cognition.py +127 -0
  638. package/src/workflow/workflows/evolve/scripts/evolve_core/database.py +218 -0
  639. package/src/workflow/workflows/evolve/scripts/evolve_core/diff.py +57 -0
  640. package/src/workflow/workflows/evolve/scripts/evolve_core/embedding.py +84 -0
  641. package/src/workflow/workflows/evolve/scripts/evolve_core/file_lock.py +45 -0
  642. package/src/workflow/workflows/evolve/scripts/evolve_core/run_state.py +343 -0
  643. package/src/workflow/workflows/evolve/scripts/evolve_core/sampling_config.py +173 -0
  644. package/src/workflow/workflows/evolve/scripts/evolve_core/structures.py +93 -0
  645. package/src/workflow/workflows/evolve/scripts/evolve_core/vector_index.py +191 -0
  646. package/src/workflow/workflows/evolve/scripts/evolve_result.py +1503 -0
  647. package/src/workflow/workflows/evolve/scripts/requirements.txt +2 -0
  648. package/src/workflow/workflows/evolve/workflow.yaml +646 -0
  649. package/src/workflow/workflows/test-email-summary/skills/email-formatting/SKILL.md +55 -0
  650. package/src/workflow/workflows/test-email-summary/skills/gmail-query-syntax/SKILL.md +63 -0
  651. package/src/workflow/workflows/test-email-summary/skills/json-schema-emails/SKILL.md +41 -0
  652. package/src/workflow/workflows/test-email-summary/skills/json-schema-emails/schema.json +34 -0
  653. package/src/workflow/workflows/test-email-summary/skills/summary-style-guide/SKILL.md +51 -0
  654. package/src/workflow/workflows/test-email-summary/workflow.yaml +90 -0
  655. package/src/workflow/workflows/vuln-discovery/skills/harness-design-fuzzing/SKILL.md +206 -0
  656. package/src/workflow/workflows/vuln-discovery/skills/memory-safety-c-cpp/SKILL.md +167 -0
  657. package/src/workflow/workflows/vuln-discovery/skills/vulnerability-triage/SKILL.md +189 -0
  658. package/src/workflow/workflows/vuln-discovery/workflow.yaml +925 -0
  659. package/dist/pipeline/llm-logger.js.map +0 -1
  660. package/dist/session/errors.js.map +0 -1
@@ -0,0 +1,678 @@
1
+ import { setup, assign, fromPromise } from 'xstate';
2
+ import { guardImplementations } from './guards.js';
3
+ import { stripStatusBlock } from './status-parser.js';
4
+ import { isAgentInvocationError } from './errors.js';
5
+ import { laneScopeEvolveCurrentPath, templateLaneCommand } from './lane-template.js';
6
+ // ---------------------------------------------------------------------------
7
+ // Extraction helpers (used by guards and actions inside the machine)
8
+ // ---------------------------------------------------------------------------
9
+ /**
10
+ * Extracts the invoke result from an xstate.done.actor.* event.
11
+ * XState wraps the promise resolution in `event.output`.
12
+ */
13
+ function extractInvokeResult(event) {
14
+ const output = event.output;
15
+ if (output && typeof output === 'object' && 'output' in output && 'outputHash' in output) {
16
+ return output;
17
+ }
18
+ return undefined;
19
+ }
20
+ // ---------------------------------------------------------------------------
21
+ // Agent output truncation
22
+ // ---------------------------------------------------------------------------
23
+ const MAX_AGENT_OUTPUT_BYTES = 32_768;
24
+ const TRUNCATION_NOTICE = '\n\n[Output truncated. Read the artifact directories for full details.]';
25
+ /**
26
+ * Sanitizes agent response text for reuse in subsequent prompts: escapes any
27
+ * literal NUL bytes and truncates to stay within the 32KB limit.
28
+ *
29
+ * NUL escaping is load-bearing, not cosmetic. Agent output flows back into
30
+ * later prompts via `previousAgentOutput` / `previousAgentNotes`, which the
31
+ * Docker adapter passes as an argv element to `child_process.spawn`. Node
32
+ * refuses argv strings containing `\0` (`ERR_INVALID_ARG_VALUE`) and throws
33
+ * synchronously before the container even starts — aborting the workflow. A
34
+ * security-research agent describing a binary file format ("APP1 'Exif\\0\\0'")
35
+ * is the natural way this happens. We escape rather than strip so the textual
36
+ * description survives intact for downstream readers.
37
+ *
38
+ * Exported for testing.
39
+ */
40
+ export function truncateAgentOutput(text) {
41
+ const sanitized = text.includes('\0') ? text.replaceAll('\0', '\\x00') : text;
42
+ if (Buffer.byteLength(sanitized, 'utf-8') <= MAX_AGENT_OUTPUT_BYTES) {
43
+ return sanitized;
44
+ }
45
+ const budget = MAX_AGENT_OUTPUT_BYTES - Buffer.byteLength(TRUNCATION_NOTICE, 'utf-8');
46
+ let truncated = sanitized;
47
+ while (Buffer.byteLength(truncated, 'utf-8') > budget) {
48
+ truncated = truncated.slice(0, Math.floor(truncated.length * 0.9));
49
+ }
50
+ return truncated + TRUNCATION_NOTICE;
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Initial context factory
54
+ // ---------------------------------------------------------------------------
55
+ /**
56
+ * Creates the initial WorkflowContext for a given definition.
57
+ * Exported for testing.
58
+ */
59
+ export function createInitialContext(definition) {
60
+ return {
61
+ artifacts: {},
62
+ round: 0,
63
+ maxRounds: definition.settings?.maxRounds ?? 4,
64
+ previousOutputHashes: {},
65
+ previousTestCount: null,
66
+ humanPrompt: null,
67
+ reviewHistory: [],
68
+ totalTokens: 0,
69
+ lastError: null,
70
+ agentConversationsByState: {},
71
+ previousAgentOutput: null,
72
+ previousAgentNotes: null,
73
+ previousStateName: null,
74
+ visitCounts: {},
75
+ };
76
+ }
77
+ // ---------------------------------------------------------------------------
78
+ // State builders
79
+ // ---------------------------------------------------------------------------
80
+ /**
81
+ * Finds an appropriate error target for a state. Looks for a human_gate
82
+ * in the definition's transitions, then falls back to any terminal state.
83
+ */
84
+ function findErrorTarget(stateDef, definition) {
85
+ // Check if any transition leads to a human gate (good for error review)
86
+ for (const t of stateDef.transitions) {
87
+ const targetState = definition.states[t.to];
88
+ if (targetState.type === 'human_gate')
89
+ return t.to;
90
+ }
91
+ // Fall back: prefer terminal states named 'aborted' or 'failed'
92
+ for (const [id, state] of Object.entries(definition.states)) {
93
+ if (state.type === 'terminal' && (id === 'aborted' || id === 'failed'))
94
+ return id;
95
+ }
96
+ // Then any terminal
97
+ for (const [id, state] of Object.entries(definition.states)) {
98
+ if (state.type === 'terminal')
99
+ return id;
100
+ }
101
+ // Last resort: first transition target (machine will at least not crash)
102
+ if (stateDef.transitions.length > 0) {
103
+ return stateDef.transitions[0].to;
104
+ }
105
+ // Should not happen in a validated definition
106
+ throw new Error('No valid error target found');
107
+ }
108
+ /**
109
+ * Collects all transition actions for a given transition definition into
110
+ * XState action entries, preserving order:
111
+ * 1. the default context-update action (caller-provided),
112
+ * 2. each entry from `actions[]` translated to XState form.
113
+ */
114
+ function collectTransitionActions(t, defaultContextAction) {
115
+ const entries = [defaultContextAction];
116
+ for (const action of t.actions ?? []) {
117
+ entries.push(compileAction(action));
118
+ }
119
+ return entries;
120
+ }
121
+ // Adding a new variant to WorkflowTransitionAction will make
122
+ // `action.stateIds` a compile error, forcing a switch here.
123
+ function compileAction(action) {
124
+ return { type: 'resetVisitCounts', params: { stateIds: action.stateIds } };
125
+ }
126
+ // Shared onDone-transition builder for agent and deterministic states: both map a
127
+ // `when:` clause to the __matchesWhen guard, else a bare `guard:`, and run a
128
+ // per-state-type context-update action. Only the update action differs.
129
+ function buildOnDoneTransitions(transitions, updateAction, mapTarget = (transition) => transition.to) {
130
+ return transitions.map((t) => {
131
+ let guard;
132
+ if (t.when) {
133
+ guard = { type: '__matchesWhen', params: { when: t.when } };
134
+ }
135
+ else if (t.guard) {
136
+ guard = t.guard;
137
+ }
138
+ return {
139
+ target: mapTarget(t),
140
+ ...(guard ? { guard } : {}),
141
+ actions: collectTransitionActions(t, updateAction),
142
+ };
143
+ });
144
+ }
145
+ function buildAgentState(stateId, config, definition, options = {}) {
146
+ return {
147
+ entry: [{ type: 'incrementVisitCount', params: { stateId } }],
148
+ invoke: {
149
+ id: stateId,
150
+ src: 'agentService',
151
+ input: ({ context }) => ({
152
+ stateId,
153
+ stateConfig: config,
154
+ context,
155
+ }),
156
+ onDone: buildOnDoneTransitions(config.transitions, 'updateContextFromAgentResult', options.mapTransitionTarget),
157
+ onError: {
158
+ target: options.onErrorTarget ?? findErrorTarget(config, definition),
159
+ actions: ['storeError', 'updateContextFromAgentInvocationError'],
160
+ },
161
+ },
162
+ };
163
+ }
164
+ function buildDeterministicState(stateId, config, definition, options = {}) {
165
+ const onDoneTransitions = buildOnDoneTransitions(config.transitions, 'updateContextFromDeterministicResult', options.mapTransitionTarget);
166
+ return {
167
+ invoke: {
168
+ id: stateId,
169
+ src: 'deterministicService',
170
+ input: ({ context }) => ({
171
+ stateId,
172
+ commands: config.run.map((command) => templateLaneCommand(command, context)),
173
+ context,
174
+ container: config.container ?? false,
175
+ containerScope: config.containerScope,
176
+ timeoutMs: config.timeoutMs,
177
+ resultFile: config.resultFile ? laneScopeEvolveCurrentPath(config.resultFile, context) : undefined,
178
+ }),
179
+ onDone: onDoneTransitions,
180
+ onError: {
181
+ target: options.onErrorTarget ?? findErrorTarget(config, definition),
182
+ actions: ['storeError'],
183
+ },
184
+ },
185
+ };
186
+ }
187
+ /**
188
+ * Builds the parent `workers` state: a single XState invoke of `fanOutService`
189
+ * (the orchestrator's `runFanOutSegment`). From the parent FSM's vantage the
190
+ * whole batch is ONE invoke — the N child round actors live inside the invoke
191
+ * body, not in the parent's state value, so the parent's `snapshot.value` stays
192
+ * the string `"workers"` (single-active-state spine, §6.4). `onDone` runs
193
+ * `updateContextFromFanOutResult` (promote the joined context) then follows the
194
+ * verdict-matched edge; `onError` routes to the definition's error target.
195
+ */
196
+ function buildFanOutState(stateId, config, definition) {
197
+ return {
198
+ invoke: {
199
+ id: stateId,
200
+ src: 'fanOutService',
201
+ input: ({ context }) => ({
202
+ stateId,
203
+ stateConfig: config,
204
+ context,
205
+ }),
206
+ onDone: buildOnDoneTransitions(config.transitions, 'updateContextFromFanOutResult'),
207
+ onError: {
208
+ target: findErrorTarget(config, definition),
209
+ actions: ['storeError'],
210
+ },
211
+ },
212
+ };
213
+ }
214
+ function buildHumanGateState(_stateId, config) {
215
+ const on = {};
216
+ for (const t of config.transitions) {
217
+ const eventName = `HUMAN_${t.event}`;
218
+ // Order: the hardcoded gate actions (storeHumanPrompt, clearError) run
219
+ // first so they set up context (prompt, error state) before any
220
+ // user-declared actions observe or modify it. User-declared actions
221
+ // (e.g., resetVisitCounts) run afterward.
222
+ const actions = ['storeHumanPrompt', 'clearError'];
223
+ for (const action of t.actions ?? []) {
224
+ actions.push(compileAction(action));
225
+ }
226
+ on[eventName] = {
227
+ target: t.to,
228
+ actions,
229
+ };
230
+ }
231
+ return { on };
232
+ }
233
+ /** The three synthetic terminal state names every child round machine carries. */
234
+ const ROUND_CHILD_RECORDED = 'recorded';
235
+ const ROUND_CHILD_BLOCKED = 'blocked';
236
+ const ROUND_CHILD_ERRORED = 'errored';
237
+ /**
238
+ * Factors a fan-out segment (the round sub-chain
239
+ * `sample -> researcher -> evaluate -> analysis_record`) into a standalone
240
+ * child machine definition. Each member is copied verbatim except for two
241
+ * rewrites: its out-of-segment transition targets are remapped to one of
242
+ * three synthetic terminals via {@link mapRoundChildTarget}, and the
243
+ * `fanOut`/`segment` markers are stripped so the recursive
244
+ * `buildWorkflowMachine` does not try to re-factor the member into yet
245
+ * another child.
246
+ *
247
+ * The three synthetic terminals (`recorded`, `blocked`, `errored`) are the
248
+ * lane verdict surface — every lane finishes in exactly one, and the parent
249
+ * barrier reads it to decide the batch verdict (§6.1). `initial: segment[0]`
250
+ * starts the child at the first segment member. `settings` are inherited from
251
+ * the parent so the child's per-lane `maxVisits` guard fires natively from the
252
+ * member's own declared limits (§6.1).
253
+ */
254
+ function buildRoundChildDefinition(definition, fanOutStateId, segment) {
255
+ const segmentSet = new Set(segment);
256
+ const states = {};
257
+ for (const memberId of segment) {
258
+ const member = definition.states[memberId];
259
+ if (member.type !== 'agent' && member.type !== 'deterministic') {
260
+ throw new Error(`fan-out state "${fanOutStateId}" segment member "${memberId}" is not executable`);
261
+ }
262
+ const transitions = member.transitions.map((transition) => ({
263
+ ...transition,
264
+ to: mapRoundChildTarget(definition, transition, segmentSet),
265
+ }));
266
+ // The agent and deterministic arms produce byte-identical state objects
267
+ // (strip the fan-out markers, override transitions); the only difference
268
+ // is the discriminated-union narrowing of `member`, so one block covers
269
+ // both once the `type` guard above has run. `_fanOut`/`_segment` are
270
+ // destructured only to omit them from `rest`; `void` marks them used.
271
+ const { fanOut: _fanOut, segment: _segment, ...rest } = member;
272
+ void _fanOut;
273
+ void _segment;
274
+ states[memberId] = { ...rest, transitions };
275
+ }
276
+ states[ROUND_CHILD_RECORDED] = {
277
+ type: 'terminal',
278
+ description: `Fan-out segment "${fanOutStateId}" recorded successfully.`,
279
+ };
280
+ states[ROUND_CHILD_BLOCKED] = {
281
+ type: 'terminal',
282
+ description: `Fan-out segment "${fanOutStateId}" needs human review.`,
283
+ };
284
+ states[ROUND_CHILD_ERRORED] = {
285
+ type: 'terminal',
286
+ description: `Fan-out segment "${fanOutStateId}" failed.`,
287
+ };
288
+ return {
289
+ name: `${definition.name}-${fanOutStateId}-round`,
290
+ description: `Child round machine for ${definition.name}.${fanOutStateId}`,
291
+ initial: segment[0],
292
+ settings: definition.settings,
293
+ states,
294
+ };
295
+ }
296
+ /**
297
+ * Maps a segment member's transition target onto a child round-machine
298
+ * target. In-segment edges pass through unchanged; everything that would
299
+ * leave the segment is collapsed onto one of the three synthetic terminals.
300
+ *
301
+ * The mapping table:
302
+ * - target is another segment member -> passthrough (the target name)
303
+ * - `when.verdict === 'recorded'` -> `recorded` (round committed a node)
304
+ * - `when.verdict === 'evaluator_blocked'` -> `blocked` (needs human review)
305
+ * - any other named verdict -> `errored` (unexpected verdict)
306
+ * - target is a human_gate state -> `blocked` (escalation edge)
307
+ * - else (bare fallthrough / failed) -> `errored`
308
+ */
309
+ function mapRoundChildTarget(definition, transition, segment) {
310
+ if (segment.has(transition.to))
311
+ return transition.to;
312
+ const verdict = transition.when?.verdict;
313
+ if (verdict === 'recorded')
314
+ return ROUND_CHILD_RECORDED;
315
+ if (verdict === 'evaluator_blocked')
316
+ return ROUND_CHILD_BLOCKED;
317
+ if (typeof verdict === 'string')
318
+ return ROUND_CHILD_ERRORED;
319
+ const targetState = definition.states[transition.to];
320
+ if (targetState.type === 'human_gate')
321
+ return ROUND_CHILD_BLOCKED;
322
+ return ROUND_CHILD_ERRORED;
323
+ }
324
+ /**
325
+ * Builds an XState v5 machine from a validated WorkflowDefinition.
326
+ *
327
+ * The returned machine has placeholder actors (`agentService`,
328
+ * `deterministicService`) that throw if invoked directly. Callers
329
+ * must call `.provide({ actors: { ... } })` to inject real
330
+ * implementations before passing to `createActor()`.
331
+ *
332
+ * Guards are registered with concrete implementations from the guards
333
+ * module. Actions for context updates are defined inline via `assign`.
334
+ */
335
+ export function buildWorkflowMachine(definition, taskDescription, options = {}) {
336
+ const states = {};
337
+ const roundMachinesByState = new Map();
338
+ const gateStateNames = new Set();
339
+ const terminalStateNames = new Set();
340
+ // Per-state maxVisits map, built at machine-construction time and
341
+ // closed over by the `isStateVisitLimitReached` guard below. Only
342
+ // agent states can declare `maxVisits`; states without it are absent
343
+ // from the map and the guard returns false for them.
344
+ const maxVisitsByState = new Map();
345
+ // For child round machines, every executable member's error path is forced
346
+ // to the synthetic `errored` terminal (see `onErrorTarget` doc above); the
347
+ // parent machine leaves it undefined and falls back to `findErrorTarget`.
348
+ const executableOptions = { onErrorTarget: options.onErrorTarget };
349
+ for (const [stateId, stateDef] of Object.entries(definition.states)) {
350
+ switch (stateDef.type) {
351
+ case 'agent':
352
+ states[stateId] =
353
+ stateDef.fanOut !== undefined
354
+ ? buildFanOutState(stateId, stateDef, definition)
355
+ : buildAgentState(stateId, stateDef, definition, executableOptions);
356
+ if (typeof stateDef.maxVisits === 'number') {
357
+ maxVisitsByState.set(stateId, stateDef.maxVisits);
358
+ }
359
+ break;
360
+ case 'deterministic':
361
+ states[stateId] =
362
+ stateDef.fanOut !== undefined
363
+ ? buildFanOutState(stateId, stateDef, definition)
364
+ : buildDeterministicState(stateId, stateDef, definition, executableOptions);
365
+ break;
366
+ case 'human_gate':
367
+ states[stateId] = buildHumanGateState(stateId, stateDef);
368
+ gateStateNames.add(stateId);
369
+ break;
370
+ case 'terminal':
371
+ states[stateId] = { type: 'final' };
372
+ terminalStateNames.add(stateId);
373
+ break;
374
+ }
375
+ }
376
+ if (options.buildRoundMachines !== false) {
377
+ for (const [stateId, stateDef] of Object.entries(definition.states)) {
378
+ if ((stateDef.type !== 'agent' && stateDef.type !== 'deterministic') || stateDef.fanOut === undefined) {
379
+ continue;
380
+ }
381
+ const segment = stateDef.segment ?? [];
382
+ if (segment.length === 0)
383
+ continue;
384
+ const childDefinition = buildRoundChildDefinition(definition, stateId, segment);
385
+ const child = buildWorkflowMachine(childDefinition, taskDescription, {
386
+ contextFromInput: true,
387
+ buildRoundMachines: false,
388
+ // A segment member's service rejection must land in the child's
389
+ // `errored` terminal, not fall through `findErrorTarget` to the
390
+ // first terminal (`recorded`). See `onErrorTarget` above.
391
+ onErrorTarget: ROUND_CHILD_ERRORED,
392
+ });
393
+ roundMachinesByState.set(stateId, child.machine);
394
+ }
395
+ }
396
+ // Build XState guard implementations compatible with XState's guard API.
397
+ // XState v5 guards receive ({ context, event }) but the event type
398
+ // during onDone is the xstate done event, not our WorkflowEvent.
399
+ // We need to adapt our guards to work with the done event's output.
400
+ // The second `params` argument is used by parameterized guards like __matchesWhen.
401
+ const xstateGuards = {};
402
+ for (const [name, guardFn] of Object.entries(guardImplementations)) {
403
+ xstateGuards[name] = ({ context, event }) => {
404
+ // For xstate.done.actor.* events, extract the output and create
405
+ // a synthetic WorkflowEvent for the guard
406
+ const doneEvent = event;
407
+ let workflowEvent;
408
+ if (doneEvent.type.startsWith('xstate.done.actor.')) {
409
+ const result = extractInvokeResult(doneEvent);
410
+ if (result) {
411
+ // Special case: isStalled needs access to outputHash and stateId
412
+ // which are not part of AgentOutput/WorkflowEvent.
413
+ if (name === 'isStalled') {
414
+ const stateId = doneEvent.type.replace('xstate.done.actor.', '');
415
+ const prevHash = context.previousOutputHashes[stateId];
416
+ return !!prevHash && result.outputHash === prevHash;
417
+ }
418
+ // Special case: isStateVisitLimitReached consults the per-state
419
+ // maxVisits map (closed over from the definition) and compares it
420
+ // to the visit count for the state that just completed.
421
+ if (name === 'isStateVisitLimitReached') {
422
+ const stateId = doneEvent.type.replace('xstate.done.actor.', '');
423
+ const cap = maxVisitsByState.get(stateId);
424
+ if (cap === undefined)
425
+ return false;
426
+ const visits = context.visitCounts[stateId] ?? 0;
427
+ return visits >= cap;
428
+ }
429
+ // Agent service result -> AGENT_COMPLETED event
430
+ workflowEvent = { type: 'AGENT_COMPLETED', output: result.output };
431
+ }
432
+ else {
433
+ // Deterministic service result -> map to VALIDATION_PASSED/FAILED
434
+ const detResult = doneEvent.output;
435
+ if (detResult?.passed) {
436
+ workflowEvent = { type: 'VALIDATION_PASSED', testCount: detResult.testCount ?? 0 };
437
+ }
438
+ else {
439
+ workflowEvent = { type: 'VALIDATION_FAILED', errors: detResult?.errors ?? 'unknown' };
440
+ }
441
+ }
442
+ }
443
+ else {
444
+ // For human gate events, pass through directly
445
+ workflowEvent = event;
446
+ }
447
+ return guardFn({ context, event: workflowEvent });
448
+ };
449
+ }
450
+ // Register the __matchesWhen parameterized guard. This intentionally
451
+ // bypasses the guard adapter loop above because it operates on AgentOutput
452
+ // directly (via extractInvokeResult inline) rather than on WorkflowEvent.
453
+ xstateGuards['__matchesWhen'] = ({ event }, params) => {
454
+ const doneEvent = event;
455
+ let matchSource;
456
+ if (doneEvent.type.startsWith('xstate.done.actor.')) {
457
+ const result = extractInvokeResult(doneEvent);
458
+ if (result) {
459
+ matchSource = result.output;
460
+ }
461
+ else {
462
+ const detResult = doneEvent.output;
463
+ if (typeof detResult?.verdict === 'string') {
464
+ matchSource = { verdict: detResult.verdict };
465
+ }
466
+ }
467
+ }
468
+ if (!matchSource)
469
+ return false;
470
+ // Defensive: fail closed if params are missing or when is empty/missing.
471
+ // Validation prevents these cases, but we don't want a silent unconditional
472
+ // match if validation is bypassed.
473
+ if (!params || typeof params !== 'object')
474
+ return false;
475
+ const whenMap = params.when;
476
+ if (!whenMap || typeof whenMap !== 'object' || Object.keys(whenMap).length === 0) {
477
+ return false;
478
+ }
479
+ const when = whenMap;
480
+ for (const [key, expected] of Object.entries(when)) {
481
+ const actual = matchSource[key];
482
+ if (actual !== expected)
483
+ return false;
484
+ }
485
+ return true;
486
+ };
487
+ const machine = setup({
488
+ types: {
489
+ context: {},
490
+ events: {},
491
+ input: {},
492
+ },
493
+ actors: {
494
+ agentService: fromPromise(() => {
495
+ return Promise.reject(new Error('agentService must be provided via machine.provide()'));
496
+ }),
497
+ deterministicService: fromPromise(() => {
498
+ return Promise.reject(new Error('deterministicService must be provided via machine.provide()'));
499
+ }),
500
+ fanOutService: fromPromise(() => {
501
+ return Promise.reject(new Error('fanOutService must be provided via machine.provide()'));
502
+ }),
503
+ },
504
+ guards: xstateGuards,
505
+ actions: {
506
+ updateContextFromAgentResult: assign(({ context, event }) => {
507
+ const doneEvent = event;
508
+ const result = extractInvokeResult(doneEvent);
509
+ if (!result)
510
+ return {};
511
+ const output = result.output;
512
+ // Derive stateId from the event type: xstate.done.actor.<stateId>
513
+ const stateId = event.type.replace('xstate.done.actor.', '');
514
+ return {
515
+ artifacts: { ...context.artifacts, ...result.artifacts },
516
+ previousOutputHashes: {
517
+ ...context.previousOutputHashes,
518
+ [stateId]: result.outputHash,
519
+ },
520
+ round: context.round + 1,
521
+ reviewHistory: output.verdict === 'rejected' ? [...context.reviewHistory, output.notes ?? ''] : context.reviewHistory,
522
+ agentConversationsByState: {
523
+ ...context.agentConversationsByState,
524
+ [stateId]: result.agentConversationId,
525
+ },
526
+ // Sourced from `instance.outputTokens` in the orchestrator,
527
+ // which subscribes to the token-stream bus and accumulates
528
+ // `message_end.outputTokens` across every session this workflow
529
+ // has spawned. The orchestrator always supplies a numeric
530
+ // cumulative value — the field is required on AgentInvokeResult.
531
+ totalTokens: result.totalTokens,
532
+ previousAgentOutput: truncateAgentOutput(stripStatusBlock(result.responseText)),
533
+ previousAgentNotes: output.notes ? truncateAgentOutput(output.notes) : null,
534
+ previousStateName: stateId,
535
+ humanPrompt: null,
536
+ };
537
+ }),
538
+ updateContextFromDeterministicResult: assign(({ context, event }) => {
539
+ const doneEvent = event;
540
+ const result = doneEvent.output;
541
+ if (!result)
542
+ return {};
543
+ // Only attach lastDeterministicResult when the state actually produced a
544
+ // verdict/payload (a result-file state). Guard-only deterministic states
545
+ // leave context byte-identical to the legacy path (the field stays absent).
546
+ const verdictUpdate = result.verdict !== undefined || result.payload !== undefined
547
+ ? {
548
+ lastDeterministicResult: {
549
+ ...(result.verdict !== undefined ? { verdict: result.verdict } : {}),
550
+ ...(result.payload !== undefined ? { payload: result.payload } : {}),
551
+ },
552
+ }
553
+ : {};
554
+ const baseUpdate = {
555
+ previousTestCount: result.testCount ?? context.previousTestCount,
556
+ ...verdictUpdate,
557
+ };
558
+ if (result.passed)
559
+ return baseUpdate;
560
+ // Set previousStateName to the deterministic state's id (not the prior agent)
561
+ // so prompt-builder's cross-state framing (buildScopingSection) renders the
562
+ // failure as "Output from <det-state>" for the next agent.
563
+ const stateId = event.type.replace('xstate.done.actor.', '');
564
+ return {
565
+ ...baseUpdate,
566
+ previousAgentOutput: truncateAgentOutput(result.errors ?? ''),
567
+ previousAgentNotes: null,
568
+ previousStateName: stateId,
569
+ };
570
+ }),
571
+ // Promotes the batch's joined context onto the parent FSM after a
572
+ // fan-out invoke resolves (the parent was frozen at `workers` for the
573
+ // whole batch — see runFanOutSegment). The result already carries the
574
+ // chosen lane's full WorkflowContext, so this replaces context wholesale.
575
+ // `if (!result) return {}` keeps the existing context unchanged when the
576
+ // invoke produced no output — never blanks the parent context on a
577
+ // malformed/empty result.
578
+ updateContextFromFanOutResult: assign(({ event }) => {
579
+ const doneEvent = event;
580
+ const result = doneEvent.output;
581
+ if (!result)
582
+ return {};
583
+ return result.context;
584
+ }),
585
+ storeHumanPrompt: assign(({ event }) => ({
586
+ humanPrompt: event.prompt ?? null,
587
+ })),
588
+ clearError: assign(() => ({
589
+ lastError: null,
590
+ })),
591
+ storeError: assign(({ event }) => {
592
+ const errorEvent = event;
593
+ const err = errorEvent.error;
594
+ let message;
595
+ if (err instanceof Error) {
596
+ message = err.message;
597
+ }
598
+ else if (typeof err === 'object' && err !== null && 'message' in err) {
599
+ message = String(err.message);
600
+ }
601
+ else if (typeof err === 'string') {
602
+ message = err;
603
+ }
604
+ else {
605
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
606
+ message = err != null ? String(err) : 'Unknown error';
607
+ }
608
+ // Write directly to stderr to bypass any console hijacking
609
+ // (logger.setup() redirects console.error to a log file).
610
+ process.stderr.write(`[workflow] storeError action: ${message}\n`);
611
+ return { lastError: message };
612
+ }),
613
+ /**
614
+ * Mirrors `updateContextFromAgentResult` for the error path: when
615
+ * the agent service rejects, recover the `agentConversationId` that
616
+ * was minted for the invocation (wrapped in `AgentInvocationError`)
617
+ * and persist it into `context.agentConversationsByState[stateId]`.
618
+ *
619
+ * Without this, `onError` drops the conversation id on the floor —
620
+ * `onDone` stamps the id into context, but `onError` used to record
621
+ * only `lastError`, which silently broke `freshSession: false`
622
+ * resume on the next visit to an errored state.
623
+ */
624
+ updateContextFromAgentInvocationError: assign(({ context, event }) => {
625
+ const errorEvent = event;
626
+ const err = errorEvent.error;
627
+ if (!isAgentInvocationError(err))
628
+ return {};
629
+ return {
630
+ agentConversationsByState: {
631
+ ...context.agentConversationsByState,
632
+ [err.stateId]: err.agentConversationId,
633
+ },
634
+ };
635
+ }),
636
+ incrementVisitCount: assign(({ context }, params) => ({
637
+ visitCounts: {
638
+ ...context.visitCounts,
639
+ [params.stateId]: (context.visitCounts[params.stateId] ?? 0) + 1,
640
+ },
641
+ })),
642
+ resetVisitCounts: assign(({ context }, params) => {
643
+ // Clear only the named keys; leave all other visit counts intact.
644
+ // Used on transitions that re-enter a bounded loop (e.g., when the
645
+ // orchestrator sends a fresh hypothesis) to reset the cap without
646
+ // losing counts for unrelated states.
647
+ const next = { ...context.visitCounts };
648
+ for (const stateId of params.stateIds) {
649
+ next[stateId] = 0;
650
+ }
651
+ return { visitCounts: next };
652
+ }),
653
+ },
654
+ }).createMachine({
655
+ id: definition.name,
656
+ initial: definition.initial,
657
+ context: ({ input }) => {
658
+ if (options.contextFromInput) {
659
+ if (!input?.context) {
660
+ throw new Error(`machine "${definition.name}" requires input.context`);
661
+ }
662
+ return input.context;
663
+ }
664
+ return {
665
+ ...createInitialContext(definition),
666
+ taskDescription,
667
+ };
668
+ },
669
+ states,
670
+ });
671
+ return {
672
+ machine,
673
+ roundMachinesByState,
674
+ gateStateNames,
675
+ terminalStateNames,
676
+ };
677
+ }
678
+ //# sourceMappingURL=machine-builder.js.map