@stigmer/runner 3.15.1 → 3.15.2-dev.20260913223433

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 (518) hide show
  1. package/README.md +2 -4
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__test-utils__/execution-record-fixture.d.ts +14 -0
  4. package/dist/__test-utils__/execution-record-fixture.js +4 -0
  5. package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
  6. package/dist/__test-utils__/file-review-projection.d.ts +40 -0
  7. package/dist/__test-utils__/file-review-projection.js +136 -0
  8. package/dist/__test-utils__/file-review-projection.js.map +1 -0
  9. package/dist/__test-utils__/harness-contract/types.d.ts +23 -1
  10. package/dist/__test-utils__/harness-contract/types.js +15 -0
  11. package/dist/__test-utils__/harness-contract/types.js.map +1 -1
  12. package/dist/__test-utils__/hermetic-activity.d.ts +44 -12
  13. package/dist/__test-utils__/hermetic-activity.js +52 -14
  14. package/dist/__test-utils__/hermetic-activity.js.map +1 -1
  15. package/dist/__test-utils__/model-registry-fixture.d.ts +32 -7
  16. package/dist/__test-utils__/model-registry-fixture.js +31 -7
  17. package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
  18. package/dist/__test-utils__/turn-input-fixture.d.ts +1 -1
  19. package/dist/__test-utils__/turn-input-fixture.js +1 -1
  20. package/dist/__test-utils__/turn-input-fixture.js.map +1 -1
  21. package/dist/activities/call-agent.js +2 -2
  22. package/dist/activities/call-agent.js.map +1 -1
  23. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +45 -3
  24. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
  25. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +0 -9
  26. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +2 -41
  27. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  28. package/dist/activities/execute-cursor/adapter.d.ts +7 -5
  29. package/dist/activities/execute-cursor/adapter.js +7 -5
  30. package/dist/activities/execute-cursor/adapter.js.map +1 -1
  31. package/dist/activities/execute-cursor/approval-policy.d.ts +5 -2
  32. package/dist/activities/execute-cursor/approval-policy.js +5 -2
  33. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  34. package/dist/activities/execute-cursor/approval-state.d.ts +16 -8
  35. package/dist/activities/execute-cursor/approval-state.js +6 -3
  36. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  37. package/dist/activities/execute-cursor/cas-observations.d.ts +14 -2
  38. package/dist/activities/execute-cursor/cas-observations.js +19 -2
  39. package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
  40. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +8 -4
  41. package/dist/activities/execute-cursor/cursor-capabilities.js +21 -4
  42. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -1
  43. package/dist/activities/execute-cursor/message-translator.d.ts +12 -20
  44. package/dist/activities/execute-cursor/message-translator.js +19 -32
  45. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  46. package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -58
  47. package/dist/activities/execute-cursor/prompt-builder.js +76 -95
  48. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  49. package/dist/activities/execute-cursor/turn-boundary.d.ts +27 -55
  50. package/dist/activities/execute-cursor/turn-boundary.js +30 -90
  51. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
  52. package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
  53. package/dist/activities/execute-cursor/turn-settle.js +37 -49
  54. package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
  55. package/dist/activities/execute-cursor/turn-setup.d.ts +16 -24
  56. package/dist/activities/execute-cursor/turn-setup.js +29 -59
  57. package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
  58. package/dist/activities/execute-cursor/turn-stream.d.ts +3 -8
  59. package/dist/activities/execute-cursor/turn-stream.js +9 -22
  60. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  61. package/dist/activities/execute-cursor/turn.js +5 -1
  62. package/dist/activities/execute-cursor/turn.js.map +1 -1
  63. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +93 -0
  64. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +348 -0
  65. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
  66. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +170 -0
  67. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +225 -0
  68. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
  69. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
  70. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
  71. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
  72. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +54 -0
  73. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +72 -0
  74. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
  75. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +187 -23
  76. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +238 -27
  77. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
  78. package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
  79. package/dist/activities/execute-deep-agent/adapter.js +78 -0
  80. package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
  81. package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +8 -0
  82. package/dist/activities/execute-deep-agent/cas-capture-observer.js +9 -0
  83. package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -1
  84. package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +31 -0
  85. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +40 -0
  86. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
  87. package/dist/activities/execute-deep-agent/execution-state.d.ts +4 -11
  88. package/dist/activities/execute-deep-agent/execution-state.js +4 -12
  89. package/dist/activities/execute-deep-agent/execution-state.js.map +1 -1
  90. package/dist/activities/execute-deep-agent/hitl.d.ts +49 -47
  91. package/dist/activities/execute-deep-agent/hitl.js +77 -103
  92. package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
  93. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +51 -23
  94. package/dist/activities/execute-deep-agent/prompt-builder.js +115 -76
  95. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  96. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +18 -32
  97. package/dist/activities/execute-deep-agent/status-builder-shared.js +10 -65
  98. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
  99. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +10 -8
  100. package/dist/activities/execute-deep-agent/streaming-side-effects.js +12 -14
  101. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  102. package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +36 -13
  103. package/dist/activities/execute-deep-agent/subagent-tracker.js +76 -39
  104. package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
  105. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -28
  106. package/dist/activities/execute-deep-agent/subagent-transformer.js +29 -82
  107. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  108. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -2
  109. package/dist/activities/execute-deep-agent/subagent-wiring.js +2 -2
  110. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  111. package/dist/activities/execute-deep-agent/turn-settle.d.ts +42 -0
  112. package/dist/activities/execute-deep-agent/turn-settle.js +146 -0
  113. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
  114. package/dist/activities/execute-deep-agent/turn-setup.d.ts +212 -0
  115. package/dist/activities/execute-deep-agent/turn-setup.js +430 -0
  116. package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
  117. package/dist/activities/execute-deep-agent/turn-stream.d.ts +97 -0
  118. package/dist/activities/execute-deep-agent/turn-stream.js +242 -0
  119. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
  120. package/dist/activities/execute-deep-agent/turn.d.ts +42 -0
  121. package/dist/activities/execute-deep-agent/turn.js +116 -0
  122. package/dist/activities/execute-deep-agent/turn.js.map +1 -0
  123. package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +6 -5
  124. package/dist/activities/execute-deep-agent/v3-event-recorder.js +6 -5
  125. package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -1
  126. package/dist/activities/execute-deep-agent/v3-events.d.ts +1 -1
  127. package/dist/activities/execute-deep-agent/v3-events.js +1 -1
  128. package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +60 -17
  129. package/dist/activities/execute-deep-agent/v3-status-builder.js +72 -57
  130. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
  131. package/dist/harness/approval-decisions.d.ts +61 -0
  132. package/dist/harness/approval-decisions.js +102 -0
  133. package/dist/harness/approval-decisions.js.map +1 -0
  134. package/dist/harness/capabilities.d.ts +16 -5
  135. package/dist/harness/capabilities.js +9 -0
  136. package/dist/harness/capabilities.js.map +1 -1
  137. package/dist/harness/capture.d.ts +144 -0
  138. package/dist/harness/capture.js +219 -0
  139. package/dist/harness/capture.js.map +1 -0
  140. package/dist/harness/persist-chokepoint.d.ts +19 -4
  141. package/dist/harness/persist-chokepoint.js +17 -4
  142. package/dist/harness/persist-chokepoint.js.map +1 -1
  143. package/dist/harness/run-turn.js +115 -29
  144. package/dist/harness/run-turn.js.map +1 -1
  145. package/dist/harness/terminal-table.d.ts +40 -11
  146. package/dist/harness/terminal-table.js +58 -19
  147. package/dist/harness/terminal-table.js.map +1 -1
  148. package/dist/harness/turn-context.d.ts +141 -76
  149. package/dist/harness/turn-context.js +194 -99
  150. package/dist/harness/turn-context.js.map +1 -1
  151. package/dist/harness/types.d.ts +65 -12
  152. package/dist/harness/types.js +8 -2
  153. package/dist/harness/types.js.map +1 -1
  154. package/dist/harness-adapters.d.ts +12 -8
  155. package/dist/harness-adapters.js +17 -9
  156. package/dist/harness-adapters.js.map +1 -1
  157. package/dist/middleware/approval-gate.d.ts +1 -1
  158. package/dist/middleware/approval-gate.js +1 -1
  159. package/dist/middleware/approval-gate.js.map +1 -1
  160. package/dist/middleware/cost-advisory.d.ts +39 -0
  161. package/dist/middleware/{cost-cap.js → cost-advisory.js} +37 -55
  162. package/dist/middleware/cost-advisory.js.map +1 -0
  163. package/dist/middleware/index.d.ts +23 -12
  164. package/dist/middleware/index.js +26 -18
  165. package/dist/middleware/index.js.map +1 -1
  166. package/dist/middleware/types.d.ts +3 -2
  167. package/dist/runner-manager.js +1 -5
  168. package/dist/runner-manager.js.map +1 -1
  169. package/dist/runner.js +1 -5
  170. package/dist/runner.js.map +1 -1
  171. package/dist/shared/attachment-resolver.d.ts +41 -18
  172. package/dist/shared/attachment-resolver.js +178 -46
  173. package/dist/shared/attachment-resolver.js.map +1 -1
  174. package/dist/shared/attachment-zip.d.ts +85 -0
  175. package/dist/shared/attachment-zip.js +185 -0
  176. package/dist/shared/attachment-zip.js.map +1 -0
  177. package/dist/shared/connect-backfill.js +5 -4
  178. package/dist/shared/connect-backfill.js.map +1 -1
  179. package/dist/shared/cost-guard.d.ts +3 -3
  180. package/dist/shared/cost-guard.js +3 -3
  181. package/dist/shared/execution-status-writer.d.ts +5 -5
  182. package/dist/shared/execution-status-writer.js +5 -5
  183. package/dist/shared/extract-structured-output.d.ts +8 -7
  184. package/dist/shared/extract-structured-output.js +8 -7
  185. package/dist/shared/extract-structured-output.js.map +1 -1
  186. package/dist/shared/filereview/cas-progress.d.ts +1 -18
  187. package/dist/shared/filereview/cas-progress.js +4 -0
  188. package/dist/shared/filereview/cas-progress.js.map +1 -1
  189. package/dist/shared/filereview/cas-touched.d.ts +56 -0
  190. package/dist/shared/filereview/cas-touched.js +63 -0
  191. package/dist/shared/filereview/cas-touched.js.map +1 -0
  192. package/dist/shared/filereview/index.d.ts +2 -1
  193. package/dist/shared/filereview/index.js +2 -1
  194. package/dist/shared/filereview/index.js.map +1 -1
  195. package/dist/shared/mcp-resolver.d.ts +4 -5
  196. package/dist/shared/mcp-resolver.js +4 -5
  197. package/dist/shared/mcp-resolver.js.map +1 -1
  198. package/dist/shared/persist-decision.d.ts +3 -4
  199. package/dist/shared/persist-decision.js +3 -4
  200. package/dist/shared/persist-decision.js.map +1 -1
  201. package/dist/shared/plan-mode-permissions.d.ts +2 -2
  202. package/dist/shared/plan-mode-permissions.js +2 -2
  203. package/dist/shared/plan-mode-prompt.d.ts +1 -1
  204. package/dist/shared/plan-mode-prompt.js +1 -1
  205. package/dist/shared/prompt-sections.d.ts +163 -0
  206. package/dist/shared/prompt-sections.js +164 -0
  207. package/dist/shared/prompt-sections.js.map +1 -0
  208. package/dist/shared/skill-resolver.d.ts +4 -2
  209. package/dist/shared/skill-resolver.js +4 -2
  210. package/dist/shared/skill-resolver.js.map +1 -1
  211. package/dist/shared/tool-rounds.d.ts +32 -0
  212. package/dist/shared/tool-rounds.js +43 -0
  213. package/dist/shared/tool-rounds.js.map +1 -1
  214. package/dist/shared/tool-row.d.ts +34 -0
  215. package/dist/shared/tool-row.js +52 -0
  216. package/dist/shared/tool-row.js.map +1 -1
  217. package/dist/shared/workspace/session-provision.d.ts +3 -3
  218. package/dist/shared/workspace/session-provision.js +3 -3
  219. package/dist/shared/workspace/stigmer-link.d.ts +3 -3
  220. package/dist/shared/workspace/stigmer-link.js +3 -3
  221. package/dist/shared/workspace/writeback-coordinator.d.ts +15 -22
  222. package/dist/shared/workspace/writeback-coordinator.js +16 -53
  223. package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
  224. package/dist/tools/index.d.ts +1 -1
  225. package/dist/tools/index.js +1 -1
  226. package/package.json +4 -4
  227. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +1 -0
  228. package/src/__test-utils__/execution-record-fixture.ts +18 -2
  229. package/src/__test-utils__/file-review-projection.ts +156 -0
  230. package/src/__test-utils__/git-workspace-fixture.ts +58 -0
  231. package/src/__test-utils__/harness-boot-order-child.ts +7 -2
  232. package/src/__test-utils__/harness-contract/contract.ts +33 -20
  233. package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
  234. package/src/__test-utils__/harness-contract/runtime-contract.ts +328 -10
  235. package/src/__test-utils__/harness-contract/scripted-adapter.ts +38 -6
  236. package/src/__test-utils__/harness-contract/types.ts +27 -3
  237. package/src/__test-utils__/hermetic-activity.ts +52 -14
  238. package/src/__test-utils__/model-registry-fixture.ts +32 -7
  239. package/src/__test-utils__/module-specifiers.ts +24 -0
  240. package/src/__test-utils__/turn-input-fixture.ts +2 -2
  241. package/src/__tests__/harness-boot-order.test.ts +9 -2
  242. package/src/activities/call-agent.ts +2 -2
  243. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +47 -3
  244. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +2 -48
  245. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +1 -1
  246. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +6 -1
  247. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +52 -27
  248. package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +25 -0
  249. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +166 -0
  250. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +186 -0
  251. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +191 -0
  252. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
  253. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
  254. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
  255. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -2
  256. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +4 -0
  257. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +24 -4
  258. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +6 -5
  259. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +9 -0
  260. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +11 -8
  261. package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +229 -0
  262. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +3 -3
  263. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +2 -2
  264. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +78 -234
  265. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +1 -26
  266. package/src/activities/execute-cursor/adapter.ts +7 -5
  267. package/src/activities/execute-cursor/approval-policy.ts +5 -2
  268. package/src/activities/execute-cursor/approval-state.ts +16 -8
  269. package/src/activities/execute-cursor/cas-observations.ts +20 -2
  270. package/src/activities/execute-cursor/cursor-capabilities.ts +24 -5
  271. package/src/activities/execute-cursor/message-translator.ts +29 -41
  272. package/src/activities/execute-cursor/prompt-builder.ts +99 -157
  273. package/src/activities/execute-cursor/turn-boundary.ts +34 -140
  274. package/src/activities/execute-cursor/turn-settle.ts +37 -51
  275. package/src/activities/execute-cursor/turn-setup.ts +30 -70
  276. package/src/activities/execute-cursor/turn-stream.ts +8 -31
  277. package/src/activities/execute-cursor/turn.ts +5 -1
  278. package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +391 -0
  279. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +313 -0
  280. package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
  281. package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +85 -0
  282. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +383 -36
  283. package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
  284. package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
  285. package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +80 -0
  286. package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +1 -1
  287. package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -2
  288. package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -3
  289. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +172 -0
  290. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +167 -0
  291. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +36 -0
  292. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +178 -0
  293. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +158 -0
  294. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +210 -0
  295. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +74 -0
  296. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +104 -0
  297. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +78 -0
  298. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +138 -0
  299. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +68 -0
  300. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +154 -0
  301. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +116 -0
  302. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +69 -0
  303. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +67 -0
  304. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +47 -0
  305. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +68 -0
  306. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +280 -0
  307. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +77 -0
  308. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
  309. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +99 -0
  310. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +109 -0
  311. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +76 -0
  312. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +51 -0
  313. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +51 -0
  314. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +56 -0
  315. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +90 -0
  316. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +70 -0
  317. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +71 -0
  318. package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
  319. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +184 -0
  320. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +203 -0
  321. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +170 -0
  322. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +175 -0
  323. package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +206 -0
  324. package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +142 -0
  325. package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +126 -0
  326. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +139 -0
  327. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +122 -0
  328. package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +236 -0
  329. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +161 -0
  330. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +157 -0
  331. package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +152 -0
  332. package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +50 -122
  333. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +8 -6
  334. package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +2 -2
  335. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +35 -35
  336. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +247 -0
  337. package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +329 -0
  338. package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +1 -20
  339. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +78 -0
  340. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +1 -1
  341. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +2 -2
  342. package/src/activities/execute-deep-agent/__tests__/subagent-tracker.test.ts +57 -31
  343. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +19 -79
  344. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +15 -15
  345. package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +1 -1
  346. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +391 -0
  347. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +343 -38
  348. package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +5 -5
  349. package/src/activities/execute-deep-agent/adapter.ts +94 -0
  350. package/src/activities/execute-deep-agent/cas-capture-observer.ts +11 -0
  351. package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +43 -0
  352. package/src/activities/execute-deep-agent/execution-state.ts +4 -13
  353. package/src/activities/execute-deep-agent/hitl.ts +100 -123
  354. package/src/activities/execute-deep-agent/prompt-builder.ts +141 -115
  355. package/src/activities/execute-deep-agent/status-builder-shared.ts +21 -84
  356. package/src/activities/execute-deep-agent/streaming-side-effects.ts +13 -19
  357. package/src/activities/execute-deep-agent/subagent-tracker.ts +77 -42
  358. package/src/activities/execute-deep-agent/subagent-transformer.ts +46 -105
  359. package/src/activities/execute-deep-agent/subagent-wiring.ts +5 -4
  360. package/src/activities/execute-deep-agent/turn-settle.ts +164 -0
  361. package/src/activities/execute-deep-agent/turn-setup.ts +541 -0
  362. package/src/activities/execute-deep-agent/turn-stream.ts +313 -0
  363. package/src/activities/execute-deep-agent/turn.ts +131 -0
  364. package/src/activities/execute-deep-agent/v3-event-recorder.ts +6 -5
  365. package/src/activities/execute-deep-agent/v3-events.ts +1 -1
  366. package/src/activities/execute-deep-agent/v3-status-builder.ts +84 -63
  367. package/src/harness/__tests__/approval-decisions.test.ts +116 -0
  368. package/src/harness/__tests__/capture.test.ts +268 -0
  369. package/src/harness/__tests__/mount-skills.test.ts +169 -0
  370. package/src/harness/__tests__/persist-chokepoint.test.ts +38 -2
  371. package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
  372. package/src/harness/__tests__/run-turn.test.ts +39 -23
  373. package/src/harness/__tests__/turn-attachments-vision.test.ts +80 -0
  374. package/src/harness/__tests__/turn-context.test.ts +73 -26
  375. package/src/harness/approval-decisions.ts +104 -0
  376. package/src/harness/capabilities.ts +16 -5
  377. package/src/harness/capture.ts +301 -0
  378. package/src/harness/persist-chokepoint.ts +24 -4
  379. package/src/harness/run-turn.ts +120 -29
  380. package/src/harness/terminal-table.ts +61 -20
  381. package/src/harness/turn-context.ts +208 -111
  382. package/src/harness/types.ts +66 -12
  383. package/src/harness-adapters.ts +17 -9
  384. package/src/middleware/__tests__/approval-gate.test.ts +1 -1
  385. package/src/middleware/__tests__/cost-advisory.test.ts +113 -0
  386. package/src/middleware/approval-gate.ts +2 -2
  387. package/src/middleware/{cost-cap.ts → cost-advisory.ts} +40 -70
  388. package/src/middleware/index.ts +29 -29
  389. package/src/middleware/types.ts +3 -2
  390. package/src/runner-manager.ts +0 -8
  391. package/src/runner.ts +0 -8
  392. package/src/shared/__tests__/attachment-naming.test.ts +6 -19
  393. package/src/shared/__tests__/attachment-resolver.test.ts +158 -8
  394. package/src/shared/__tests__/attachment-zip.test.ts +236 -0
  395. package/src/shared/__tests__/bedrock-adapter.test.ts +1 -1
  396. package/src/shared/__tests__/blueprint-resolver.test.ts +43 -0
  397. package/src/shared/__tests__/cost-guard.test.ts +3 -3
  398. package/src/shared/__tests__/prompt-sections.test.ts +167 -0
  399. package/src/shared/__tests__/secret-leak-scan.test.ts +2 -2
  400. package/src/{activities/execute-deep-agent → shared}/__tests__/stamp-flowed-rows.test.ts +33 -10
  401. package/src/shared/__tests__/vertex-adapter.test.ts +1 -1
  402. package/src/shared/attachment-resolver.ts +218 -55
  403. package/src/shared/attachment-zip.ts +281 -0
  404. package/src/shared/connect-backfill.ts +9 -11
  405. package/src/shared/cost-guard.ts +3 -3
  406. package/src/shared/execution-status-writer.ts +5 -5
  407. package/src/shared/extract-structured-output.ts +8 -7
  408. package/src/shared/filereview/__tests__/capture.test.ts +86 -4
  409. package/src/shared/filereview/__tests__/cas-progress.test.ts +2 -1
  410. package/src/shared/filereview/cas-progress.ts +5 -19
  411. package/src/shared/filereview/cas-touched.ts +89 -0
  412. package/src/shared/filereview/index.ts +4 -2
  413. package/src/shared/mcp-resolver.ts +4 -5
  414. package/src/shared/persist-decision.ts +3 -4
  415. package/src/shared/plan-mode-permissions.ts +2 -2
  416. package/src/shared/plan-mode-prompt.ts +1 -1
  417. package/src/shared/prompt-sections.ts +256 -0
  418. package/src/shared/skill-resolver.ts +4 -2
  419. package/src/shared/tool-rounds.ts +48 -0
  420. package/src/shared/tool-row.ts +61 -0
  421. package/src/shared/workspace/__tests__/stigmer-link.test.ts +7 -22
  422. package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +20 -61
  423. package/src/shared/workspace/session-provision.ts +3 -3
  424. package/src/shared/workspace/stigmer-link.ts +3 -3
  425. package/src/shared/workspace/writeback-coordinator.ts +16 -64
  426. package/src/tools/index.ts +1 -1
  427. package/dist/activities/execute-cursor/capture-flow.d.ts +0 -142
  428. package/dist/activities/execute-cursor/capture-flow.js +0 -285
  429. package/dist/activities/execute-cursor/capture-flow.js.map +0 -1
  430. package/dist/activities/execute-cursor/command-provenance.d.ts +0 -48
  431. package/dist/activities/execute-cursor/command-provenance.js +0 -38
  432. package/dist/activities/execute-cursor/command-provenance.js.map +0 -1
  433. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +0 -134
  434. package/dist/activities/execute-deep-agent/attachment-injector.js +0 -386
  435. package/dist/activities/execute-deep-agent/attachment-injector.js.map +0 -1
  436. package/dist/activities/execute-deep-agent/command-provenance.d.ts +0 -61
  437. package/dist/activities/execute-deep-agent/command-provenance.js +0 -72
  438. package/dist/activities/execute-deep-agent/command-provenance.js.map +0 -1
  439. package/dist/activities/execute-deep-agent/environment.d.ts +0 -24
  440. package/dist/activities/execute-deep-agent/environment.js +0 -58
  441. package/dist/activities/execute-deep-agent/environment.js.map +0 -1
  442. package/dist/activities/execute-deep-agent/event-recorder.d.ts +0 -21
  443. package/dist/activities/execute-deep-agent/event-recorder.js +0 -67
  444. package/dist/activities/execute-deep-agent/event-recorder.js.map +0 -1
  445. package/dist/activities/execute-deep-agent/index.d.ts +0 -15
  446. package/dist/activities/execute-deep-agent/index.js +0 -918
  447. package/dist/activities/execute-deep-agent/index.js.map +0 -1
  448. package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -28
  449. package/dist/activities/execute-deep-agent/mcp-gate.js +0 -22
  450. package/dist/activities/execute-deep-agent/mcp-gate.js.map +0 -1
  451. package/dist/activities/execute-deep-agent/post-stream.d.ts +0 -23
  452. package/dist/activities/execute-deep-agent/post-stream.js +0 -71
  453. package/dist/activities/execute-deep-agent/post-stream.js.map +0 -1
  454. package/dist/activities/execute-deep-agent/setup.d.ts +0 -136
  455. package/dist/activities/execute-deep-agent/setup.js +0 -767
  456. package/dist/activities/execute-deep-agent/setup.js.map +0 -1
  457. package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +0 -36
  458. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +0 -56
  459. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +0 -1
  460. package/dist/activities/execute-deep-agent/status-builder.d.ts +0 -93
  461. package/dist/activities/execute-deep-agent/status-builder.js +0 -365
  462. package/dist/activities/execute-deep-agent/status-builder.js.map +0 -1
  463. package/dist/activities/execute-deep-agent/streaming-terminal.d.ts +0 -21
  464. package/dist/activities/execute-deep-agent/streaming-terminal.js +0 -80
  465. package/dist/activities/execute-deep-agent/streaming-terminal.js.map +0 -1
  466. package/dist/activities/execute-deep-agent/streaming-v3.d.ts +0 -13
  467. package/dist/activities/execute-deep-agent/streaming-v3.js +0 -174
  468. package/dist/activities/execute-deep-agent/streaming-v3.js.map +0 -1
  469. package/dist/activities/execute-deep-agent/streaming.d.ts +0 -81
  470. package/dist/activities/execute-deep-agent/streaming.js +0 -160
  471. package/dist/activities/execute-deep-agent/streaming.js.map +0 -1
  472. package/dist/middleware/cost-cap.d.ts +0 -22
  473. package/dist/middleware/cost-cap.js.map +0 -1
  474. package/dist/middleware/graceful-stop.d.ts +0 -17
  475. package/dist/middleware/graceful-stop.js +0 -63
  476. package/dist/middleware/graceful-stop.js.map +0 -1
  477. package/dist/shared/skill-writer.d.ts +0 -75
  478. package/dist/shared/skill-writer.js +0 -207
  479. package/dist/shared/skill-writer.js.map +0 -1
  480. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +0 -1032
  481. package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +0 -240
  482. package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +0 -169
  483. package/src/activities/execute-cursor/capture-flow.ts +0 -379
  484. package/src/activities/execute-cursor/command-provenance.ts +0 -73
  485. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +0 -1161
  486. package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +0 -252
  487. package/src/activities/execute-deep-agent/__tests__/environment.test.ts +0 -108
  488. package/src/activities/execute-deep-agent/__tests__/event-recorder.test.ts +0 -150
  489. package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +0 -226
  490. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -318
  491. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -351
  492. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -293
  493. package/src/activities/execute-deep-agent/__tests__/index.test.ts +0 -99
  494. package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +0 -44
  495. package/src/activities/execute-deep-agent/__tests__/post-stream.test.ts +0 -112
  496. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -358
  497. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +0 -1933
  498. package/src/activities/execute-deep-agent/__tests__/streaming-terminal.test.ts +0 -40
  499. package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +0 -597
  500. package/src/activities/execute-deep-agent/__tests__/streaming.test.ts +0 -508
  501. package/src/activities/execute-deep-agent/attachment-injector.ts +0 -627
  502. package/src/activities/execute-deep-agent/command-provenance.ts +0 -102
  503. package/src/activities/execute-deep-agent/environment.ts +0 -76
  504. package/src/activities/execute-deep-agent/event-recorder.ts +0 -95
  505. package/src/activities/execute-deep-agent/index.ts +0 -1072
  506. package/src/activities/execute-deep-agent/mcp-gate.ts +0 -37
  507. package/src/activities/execute-deep-agent/post-stream.ts +0 -109
  508. package/src/activities/execute-deep-agent/setup.ts +0 -1081
  509. package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +0 -64
  510. package/src/activities/execute-deep-agent/status-builder.ts +0 -481
  511. package/src/activities/execute-deep-agent/streaming-terminal.ts +0 -106
  512. package/src/activities/execute-deep-agent/streaming-v3.ts +0 -277
  513. package/src/activities/execute-deep-agent/streaming.ts +0 -313
  514. package/src/middleware/__tests__/cost-cap.test.ts +0 -192
  515. package/src/middleware/__tests__/graceful-stop.test.ts +0 -105
  516. package/src/middleware/graceful-stop.ts +0 -86
  517. package/src/shared/__tests__/skill-writer.test.ts +0 -372
  518. package/src/shared/skill-writer.ts +0 -266
@@ -0,0 +1,391 @@
1
+ /**
2
+ * The native adapter's stream loop (`turn-stream.ts` `consumeDeepAgentStream`)
3
+ * over a SCRIPTED v3 run and the kit's recording sink — no graph, no model,
4
+ * no runtime. What the hermetic goldens prove end to end, this file pins one
5
+ * rule at a time, where a failure names the rule:
6
+ *
7
+ * - how the graph is invoked (the two-arg v3 `streamEvents` shape, the
8
+ * runtime's `langgraphConfig` carried whole, the loop's own abort signal);
9
+ * - what each event becomes (the normalizer feeds the builder; the sink
10
+ * learns of activity per event, with the tool's name as the detail);
11
+ * - what the sink is told and when (usage priced per `message_finish`;
12
+ * a persist requested on the shared cadence rule, a tool start forcing it);
13
+ * - how the loop ends: `completed` with the run's output, `awaiting_approval`
14
+ * at a gate, `interrupted` when the runtime stops it — taken at the NEXT
15
+ * event, the engine's own step boundary (S3 M2a F-M2a-18), and before the
16
+ * first if the stop came earlier;
17
+ * - what it refuses and what it tolerates: an empty stream throws; the
18
+ * engine's own error propagates; a `run.output` that rejects is logged
19
+ * and the turn completes without a final state;
20
+ * - the recorder exists only under `V3_EVENT_RECORD_DIR`.
21
+ *
22
+ * Carried from the legacy v3 loop's suite (`streaming-v3.test.ts`, retired
23
+ * with the loop at S3 M2b, Q-M2b-5): the arms whose rule the adapter's loop
24
+ * still has, re-stated against the sink. The loop-specific arms it dropped
25
+ * (the in-band heartbeat timer, the 120 s stall, STOP read from the persist,
26
+ * pause as a terminal status) are the turn runtime's now and pinned in
27
+ * `harness/__tests__` and the hermetic goldens.
28
+ */
29
+
30
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
31
+ import { existsSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
32
+ import { tmpdir } from "node:os";
33
+ import { join } from "node:path";
34
+ import { MemorySaver } from "@langchain/langgraph";
35
+ import { MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
36
+
37
+ import { RecordingTurnSink } from "../../../__test-utils__/harness-contract/recording-sink.js";
38
+ import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifact-storage.js";
39
+ import { turnInputFixture } from "../../../__test-utils__/turn-input-fixture.js";
40
+ import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
41
+ import type { ModelPricing } from "../../../shared/model-pricing.js";
42
+ import type { MergedToolPolicy } from "../../../shared/approval-policy.js";
43
+ import { CasCaptureObserver } from "../cas-capture-observer.js";
44
+ import type { DeepAgentEngine, DeepAgentGateState, DeepAgentGraphInput, DeepAgentWorkspace } from "../turn-setup.js";
45
+ import { consumeDeepAgentStream, createDeepAgentTranscript, type StreamableRun } from "../turn-stream.js";
46
+ import type { V3ProtocolEvent } from "../v3-event-recorder.js";
47
+ import {
48
+ makeMessageFinish,
49
+ makeMessageStart,
50
+ makeTextDelta,
51
+ makeToolFinished,
52
+ makeToolStarted,
53
+ resetSeq,
54
+ } from "../__test-utils__/v3-event-fixtures.js";
55
+
56
+ const PRICING: ModelPricing = {
57
+ model: "claude-haiku-4.5",
58
+ displayName: "Haiku (test)",
59
+ costTier: "standard",
60
+ inputPricePerMillion: 1.0,
61
+ outputPricePerMillion: 5.0,
62
+ cacheWritePricePerMillion: 1.25,
63
+ cacheReadPricePerMillion: 0.1,
64
+ };
65
+
66
+ function openGate(overrides: Partial<DeepAgentGateState> = {}): DeepAgentGateState {
67
+ return {
68
+ policies: new Map(),
69
+ toolServerMap: new Map(),
70
+ leasedCategories: new Set(),
71
+ globalBypass: false,
72
+ unattended: false,
73
+ unattendedSkips: new Set(),
74
+ ...overrides,
75
+ };
76
+ }
77
+
78
+ /** A workspace whose files are the given map; the publisher reads through it. */
79
+ function workspaceOver(files: Record<string, string>): DeepAgentWorkspace {
80
+ const backend: WorkspaceBackend = {
81
+ rootDir: "/workspace",
82
+ execute: vi.fn(async () => ""),
83
+ readFile: vi.fn(async (path: string) => {
84
+ const content = files[path];
85
+ if (content === undefined) throw new Error(`File not found: ${path}`);
86
+ return content;
87
+ }),
88
+ writeFile: vi.fn(async () => undefined),
89
+ writeFileBuffer: vi.fn(async () => undefined),
90
+ exists: vi.fn(async (path: string) => path in files),
91
+ };
92
+ return {
93
+ backend,
94
+ casObserver: new CasCaptureObserver({ rootDir: "/workspace", isIgnored: async () => false }),
95
+ isCapturablePath: async () => false,
96
+ };
97
+ }
98
+
99
+ interface ScriptedRunOptions {
100
+ /** The final state `run.output` resolves to; a function so a rejection is created when the run is. */
101
+ readonly output?: () => Promise<unknown>;
102
+ /** Called between events, after the event at this index was yielded and before the next is. */
103
+ readonly between?: (yielded: number) => void;
104
+ /** Thrown from the stream after this many events. */
105
+ readonly failAfter?: number;
106
+ }
107
+
108
+ /** A `StreamableRun` over scripted events; what the graph would hand the loop. */
109
+ function scriptedRun(events: readonly V3ProtocolEvent[], options: ScriptedRunOptions = {}): StreamableRun {
110
+ const output = options.output ? options.output() : Promise.resolve({ messages: [] });
111
+ const iterate = async function* (): AsyncGenerator<V3ProtocolEvent> {
112
+ let yielded = 0;
113
+ for (const event of events) {
114
+ if (options.failAfter !== undefined && yielded === options.failAfter) throw new Error("engine exploded mid-stream");
115
+ yield event;
116
+ yielded++;
117
+ options.between?.(yielded);
118
+ }
119
+ if (options.failAfter !== undefined && yielded === options.failAfter) throw new Error("engine exploded mid-stream");
120
+ };
121
+ return { output, [Symbol.asyncIterator]: iterate };
122
+ }
123
+
124
+ interface Harness {
125
+ readonly sink: RecordingTurnSink;
126
+ readonly engine: DeepAgentEngine;
127
+ readonly streamEvents: ReturnType<typeof vi.fn>;
128
+ readonly blobs: Map<string, Buffer>;
129
+ run(run: StreamableRun): ReturnType<typeof consumeDeepAgentStream>;
130
+ }
131
+
132
+ function harness(options: { gate?: DeepAgentGateState; files?: Record<string, string> } = {}): Harness {
133
+ // Artifact storage is part of the turn's input; the publisher uploads there
134
+ // and registers the artifact on the status, or does nothing at all without it.
135
+ const { storage, blobs } = makeInMemoryArtifactStorage();
136
+ const input = turnInputFixture({ message: "Say hello.", artifactStorage: storage });
137
+ const sink = new RecordingTurnSink();
138
+ const streamEvents = vi.fn();
139
+ const engine: DeepAgentEngine = {
140
+ graph: { streamEvents },
141
+ checkpointer: new MemorySaver(),
142
+ langgraphConfig: { configurable: { thread_id: "thread-fixture" }, recursionLimit: 40 },
143
+ modelName: PRICING.model,
144
+ pricing: PRICING,
145
+ gate: options.gate ?? openGate(),
146
+ hasStructuredOutput: false,
147
+ };
148
+ const workspace = workspaceOver(options.files ?? {});
149
+ const graphInput: DeepAgentGraphInput = { kind: "message", input: { messages: [{ role: "user", content: "Say hello." }] } };
150
+ return {
151
+ sink,
152
+ engine,
153
+ streamEvents,
154
+ blobs,
155
+ run(run) {
156
+ streamEvents.mockResolvedValue(run);
157
+ const transcript = createDeepAgentTranscript(input, sink, engine, workspace);
158
+ return consumeDeepAgentStream({ input, sink, engine, graphInput, transcript });
159
+ },
160
+ };
161
+ }
162
+
163
+ /** One text turn with usage, as the graph streams it. */
164
+ function textTurn(runId: string, text: string, usage = { input_tokens: 100, output_tokens: 20 }): V3ProtocolEvent[] {
165
+ return [makeMessageStart(runId), makeTextDelta(runId, text), makeMessageFinish(runId, { usage })];
166
+ }
167
+
168
+ beforeEach(() => resetSeq());
169
+ afterEach(() => vi.unstubAllEnvs());
170
+
171
+ describe("consumeDeepAgentStream — how the graph is invoked", () => {
172
+ it("calls streamEvents with the graph input and the runtime's config plus version v3 and its own abort signal", async () => {
173
+ const h = harness();
174
+ await h.run(scriptedRun(textTurn("run-1", "Hello.")));
175
+
176
+ expect(h.streamEvents).toHaveBeenCalledTimes(1);
177
+ const [input, config] = h.streamEvents.mock.calls[0] as [unknown, Record<string, unknown>];
178
+ expect(input).toEqual({ messages: [{ role: "user", content: "Say hello." }] });
179
+ expect(config.version).toBe("v3");
180
+ expect(config.configurable, "the runtime's thread id rides the config whole").toEqual({ thread_id: "thread-fixture" });
181
+ expect(config.recursionLimit).toBe(40);
182
+ expect(config.signal).toBeInstanceOf(AbortSignal);
183
+ expect((config.signal as AbortSignal).aborted, "a completed run was never aborted").toBe(false);
184
+ });
185
+ });
186
+
187
+ describe("consumeDeepAgentStream — what each event becomes", () => {
188
+ it("feeds every event through the normalizer into the transcript and completes with the run's output", async () => {
189
+ const h = harness();
190
+ const result = await h.run(
191
+ scriptedRun(
192
+ [...textTurn("run-1", "Reading the file."), makeToolStarted("toolu_1", "read_file", { path: "/x" }), makeToolFinished("toolu_1", "contents")],
193
+ { output: () => Promise.resolve({ messages: [], structuredResponse: { ok: true } }) },
194
+ ),
195
+ );
196
+
197
+ expect(result.reason).toBe("completed");
198
+ expect(result.eventsProcessed).toBe(5);
199
+ expect(result.runOutput?.structuredResponse).toEqual({ ok: true });
200
+ const [message] = h.sink.status.messages;
201
+ expect(message.type).toBe(MessageType.MESSAGE_AI);
202
+ expect(message.content).toBe("Reading the file.");
203
+ expect(message.toolCalls[0].name).toBe("read_file");
204
+ expect(message.toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_COMPLETED);
205
+ });
206
+
207
+ it("tells the sink of activity once per event, naming the tool a tool_started carries", async () => {
208
+ const h = harness();
209
+ await h.run(scriptedRun([...textTurn("run-1", "x"), makeToolStarted("toolu_1", "read_file", { path: "/x" }), makeToolFinished("toolu_1", "ok")]));
210
+
211
+ const details = h.sink.events.flatMap((e) => (e.kind === "activity" ? [e.detail] : []));
212
+ // One mark after the run starts, one per event (5), one after the output resolved.
213
+ expect(details).toHaveLength(7);
214
+ expect(details.filter((d) => d === "read_file"), "the tool's name is the stall watchdog's last detail").toHaveLength(1);
215
+ });
216
+
217
+ it("reports usage per message_finish, priced at the engine's rates for the engine's model", async () => {
218
+ const h = harness();
219
+ await h.run(
220
+ scriptedRun([
221
+ ...textTurn("run-1", "one", { input_tokens: 1_000, output_tokens: 100 }),
222
+ ...textTurn("run-2", "two", { input_tokens: 2_000, output_tokens: 200 }),
223
+ ]),
224
+ );
225
+
226
+ const deltas = h.sink.usageDeltas;
227
+ expect(deltas).toHaveLength(2);
228
+ expect(deltas[0]).toMatchObject({ inputTokens: 1_000, outputTokens: 100, model: PRICING.model });
229
+ // 1,000 in at $1/M + 100 out at $5/M.
230
+ expect(deltas[0].estimatedCostUsd).toBeCloseTo(0.0015, 10);
231
+ expect(deltas[1].estimatedCostUsd).toBeCloseTo(0.003, 10);
232
+ });
233
+
234
+ it("requests a persist on the shared cadence rule — a tool start forces one — and clears the force flag", async () => {
235
+ const h = harness();
236
+ await h.run(scriptedRun([...textTurn("run-1", "x"), makeToolStarted("toolu_1", "read_file", { path: "/x" }), makeToolFinished("toolu_1", "ok")]));
237
+
238
+ expect(h.sink.persistRequests, "the tool start and the tool finish each force a persist").toBeGreaterThanOrEqual(2);
239
+ const order = h.sink.events.map((e) => e.kind);
240
+ expect(order.indexOf("persist"), "the first persist follows the events that forced it, never precedes them").toBeGreaterThan(0);
241
+ });
242
+
243
+ it("publishes a file-modifying tool's target as an artifact on the status when the call finishes", async () => {
244
+ const h = harness({ files: { "src/main.ts": "console.log('hi');" } });
245
+ const result = await h.run(
246
+ scriptedRun([
247
+ ...textTurn("run-1", "Writing."),
248
+ makeToolStarted("toolu_w", "write_file", { file_path: "src/main.ts", content: "console.log('hi');" }),
249
+ makeToolFinished("toolu_w", "written"),
250
+ ]),
251
+ );
252
+
253
+ expect(result.pendingPublishPromises, "one publish fired mid-turn, for the settle to drain").toHaveLength(1);
254
+ await Promise.all(result.pendingPublishPromises);
255
+ expect(h.sink.status.artifacts.map((a) => a.sandboxPath)).toEqual(["src/main.ts"]);
256
+ expect([...h.blobs.keys()], "the bytes were uploaded under the execution's artifact key").toEqual(["artifacts/aex_fixture_0001/main.ts"]);
257
+ });
258
+ });
259
+
260
+ describe("consumeDeepAgentStream — how the loop ends", () => {
261
+ it("ends awaiting_approval when the builder leaves a gated tool WAITING, without awaiting the run's output", async () => {
262
+ const policy: MergedToolPolicy = {
263
+ toolName: "dangerous_tool",
264
+ mcpServerSlug: "my-server",
265
+ requiresApproval: true,
266
+ approvalMessage: "Approve?",
267
+ source: "classifier_default",
268
+ };
269
+ const h = harness({
270
+ gate: openGate({ policies: new Map([["my-server/dangerous_tool", policy]]), toolServerMap: new Map([["dangerous_tool", "my-server"]]) }),
271
+ });
272
+ const neverResolves = new Promise<unknown>(() => undefined);
273
+ const result = await h.run(
274
+ scriptedRun([...textTurn("run-1", "Gated."), makeToolStarted("toolu_g", "dangerous_tool", { target: "prod" })], { output: () => neverResolves }),
275
+ );
276
+
277
+ expect(result.reason).toBe("awaiting_approval");
278
+ expect(result.runOutput).toBeUndefined();
279
+ expect(h.sink.status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
280
+ });
281
+
282
+ it("a stop before the first event settles interrupted without invoking the graph", async () => {
283
+ const h = harness();
284
+ h.sink.abort("stopped before start");
285
+ const result = await h.run(scriptedRun(textTurn("run-1", "never")));
286
+
287
+ expect(result.reason).toBe("interrupted");
288
+ expect(result.eventsProcessed).toBe(0);
289
+ expect(h.streamEvents).not.toHaveBeenCalled();
290
+ });
291
+
292
+ it("a stop mid-stream is taken at the NEXT event: the events before it count, the run's signal is aborted", async () => {
293
+ const h = harness();
294
+ const [start, delta, finish] = textTurn("run-1", "partial");
295
+ const result = await h.run(scriptedRun([start, delta, finish], { between: (yielded) => { if (yielded === 2) h.sink.abort("runtime stop"); } }));
296
+
297
+ expect(result.reason).toBe("interrupted");
298
+ expect(result.eventsProcessed, "start and delta were folded; finish arrived after the stop").toBe(2);
299
+ const [, config] = h.streamEvents.mock.calls[0] as [unknown, { signal: AbortSignal }];
300
+ expect(config.signal.aborted, "the graph run itself is aborted when the stop is taken").toBe(true);
301
+ expect(h.sink.status.messages[0].content, "what streamed before the stop is on the transcript").toBe("partial");
302
+ });
303
+
304
+ it("the engine's own error propagates when the runtime did not stop the turn", async () => {
305
+ const h = harness();
306
+ await expect(h.run(scriptedRun(textTurn("run-1", "x"), { failAfter: 1 }))).rejects.toThrow("engine exploded mid-stream");
307
+ });
308
+
309
+ it("an error thrown after the runtime stopped the turn is the stop, not a failure", async () => {
310
+ const h = harness();
311
+ const result = await h.run(
312
+ scriptedRun(textTurn("run-1", "x"), { between: (yielded) => { if (yielded === 1) h.sink.abort("runtime stop"); }, failAfter: 1 }),
313
+ );
314
+ expect(result.reason).toBe("interrupted");
315
+ });
316
+
317
+ it("refuses a stream that produced no events", async () => {
318
+ const h = harness();
319
+ await expect(h.run(scriptedRun([]))).rejects.toThrow(/Stream completed without processing any events/);
320
+ });
321
+
322
+ it("a run.output that rejects is logged and the turn completes without a final state", async () => {
323
+ const h = harness();
324
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
325
+ try {
326
+ const result = await h.run(scriptedRun(textTurn("run-1", "x"), { output: () => Promise.reject(new Error("state never settled")) }));
327
+ expect(result.reason).toBe("completed");
328
+ expect(result.runOutput).toBeUndefined();
329
+ expect(warn.mock.calls.some((c) => String(c[0]).includes("run.output rejected"))).toBe(true);
330
+ } finally {
331
+ warn.mockRestore();
332
+ }
333
+ });
334
+
335
+ // Regression pins for stigmer#1008 (carried from the orchestrator's
336
+ // `streaming-v3.test.ts`, retired with its module; the fix on that module
337
+ // was stigmer#1092). The run.output bound must not leave its timer armed:
338
+ // a referenced timer holds the runner's event loop open after its worker
339
+ // has stopped, for the full Kubernetes termination grace. Faked timers
340
+ // here so `vi.getTimerCount()` can see what the loop left behind.
341
+ describe("the run.output bound leaves nothing armed", () => {
342
+ beforeEach(() => vi.useFakeTimers());
343
+ afterEach(() => vi.useRealTimers());
344
+
345
+ it("once run.output has resolved", async () => {
346
+ const h = harness();
347
+ const promise = h.run(scriptedRun(textTurn("run-1", "x")));
348
+ // Well short of the 30 s bound: a leaked timer would still be pending here.
349
+ await vi.advanceTimersByTimeAsync(1_000);
350
+ const result = await promise;
351
+ expect(result.runOutput).toBeDefined();
352
+ expect(vi.getTimerCount(), "the loop left a timer armed after completion").toBe(0);
353
+ });
354
+
355
+ it("when run.output never settles: the bound ends the wait, no final state, nothing armed", async () => {
356
+ const h = harness();
357
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
358
+ try {
359
+ const promise = h.run(scriptedRun(textTurn("run-1", "x"), { output: () => new Promise(() => undefined) }));
360
+ await vi.advanceTimersByTimeAsync(30_000);
361
+ const result = await promise;
362
+ expect(result.reason).toBe("completed");
363
+ expect(result.runOutput).toBeUndefined();
364
+ expect(warn.mock.calls.some((c) => String(c[0]).includes("run.output did not resolve within 30000ms"))).toBe(true);
365
+ expect(vi.getTimerCount(), "the bound's own timer is cleared on expiry").toBe(0);
366
+ } finally {
367
+ warn.mockRestore();
368
+ }
369
+ });
370
+ });
371
+ });
372
+
373
+ describe("consumeDeepAgentStream — the event recorder", () => {
374
+ let dir: string;
375
+ beforeEach(() => { dir = mkdtempSync(join(tmpdir(), "v3-events-")); });
376
+ afterEach(() => rmSync(dir, { recursive: true, force: true }));
377
+
378
+ it("records nothing unless V3_EVENT_RECORD_DIR is set", async () => {
379
+ vi.stubEnv("V3_EVENT_RECORD_DIR", "");
380
+ const h = harness();
381
+ await h.run(scriptedRun(textTurn("run-1", "x")));
382
+ expect(readdirSync(dir)).toEqual([]);
383
+ });
384
+
385
+ it("records every raw event to <dir>/<executionId>.v3-events.json and flushes it when the stream ends", async () => {
386
+ vi.stubEnv("V3_EVENT_RECORD_DIR", dir);
387
+ const h = harness();
388
+ await h.run(scriptedRun(textTurn("run-1", "x")));
389
+ expect(existsSync(join(dir, "aex_fixture_0001.v3-events.json"))).toBe(true);
390
+ });
391
+ });