@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
@@ -59,19 +59,23 @@ import {
59
59
  getShutdownSignalForQueue,
60
60
  type TurnInterruption,
61
61
  } from "../shared/worker-shutdown.js";
62
+ import { terminalizeNonExecutingDecisions } from "./approval-decisions.js";
63
+ import { captureCandidate, pinCaptureBaseline, type TurnCapture } from "./capture.js";
62
64
  import { PersistChokepoint } from "./persist-chokepoint.js";
63
65
  import { StopController } from "./stop-controller.js";
64
66
  import {
65
67
  applyTerminalArm,
68
+ awaitingApprovalArm,
69
+ awaitingReviewArm,
66
70
  costCapArm,
67
71
  failedArm,
68
72
  fileReviewResolvedArm,
69
73
  infrastructureCancelArm,
70
74
  pauseArm,
71
75
  platformStopArm,
72
- rejectedByUserArm,
73
76
  stallArm,
74
77
  TERMINAL_COPY,
78
+ toolCallLimitArm,
75
79
  unexpectedErrorArm,
76
80
  workerShutdownArm,
77
81
  workspaceLockTimeoutArm,
@@ -161,6 +165,8 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
161
165
  const frame: TurnFrame = { primaryDir: undefined, releaseWorkspaceLock: undefined, writeback: null };
162
166
  const stop = new StopController();
163
167
  let usage: UsageAccumulator | undefined;
168
+ /** The turn's capture once the baseline is pinned (capture mode only); the chokepoint reads its progress at every write. */
169
+ let capture: TurnCapture | undefined;
164
170
  let heartbeatPhase = "setup";
165
171
  let lastActivityDetail: string | undefined;
166
172
  let watchdog: StallWatchdog | undefined;
@@ -175,6 +181,7 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
175
181
  status,
176
182
  offload: artifactStorage ? { artifactStorage, executionId } : undefined,
177
183
  usage: () => usage,
184
+ progress: () => capture?.progress,
178
185
  heartbeat,
179
186
  onPlatformStop: () => stop.stop({ kind: "platform-stop" }),
180
187
  });
@@ -231,9 +238,6 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
231
238
  console.warn(`${activityName} workspace lock timeout: execution=${executionId}`);
232
239
  return outcome;
233
240
  }
234
- case "rejected-by-user":
235
- // A reject of an irreversible action (shell/MCP) fails the execution.
236
- return settleWith(rejectedByUserArm());
237
241
  case "file-review-resolved": {
238
242
  // Push the APPROVED tree — reconcile snapped rejected files back to
239
243
  // baseline, so what finalize commits is exactly what the user kept.
@@ -248,7 +252,10 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
248
252
  `${activityName} file-review resume short-circuit: execution=${executionId}, ` +
249
253
  `failed=${settlement.failed}, discarded=${settlement.discardedPaths.length}`,
250
254
  );
251
- return { kind: "return", value: slimStatus(status) };
255
+ // The execution completes here, so its answer rides the slim as it
256
+ // does from `completeTurn`: the seed carried the transcript and any
257
+ // structured output the paused turn resolved (Q-M4-8).
258
+ return { kind: "return", value: completionSlim(lastAssistantText()) };
252
259
  }
253
260
  default: {
254
261
  const exhaustive: never = settlement;
@@ -312,32 +319,81 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
312
319
  await client.updateSession(turn.session);
313
320
  console.log(`Stored ${harnessStateId} as harness_state_id on session ${turn.sessionId}`);
314
321
  },
322
+ bindCasObservations: (read) => {
323
+ // Outside capture mode there is no capture to feed; the bind is a
324
+ // no-op, as the contract promises a harness that always binds.
325
+ if (capture) capture.casObservations = read;
326
+ },
315
327
  };
316
328
 
329
+ // The capture baseline: the runtime's LAST act before the engine, after
330
+ // every write of its own into the tree (the reconcile, the mounts), so
331
+ // anything on the tree after this point is the turn's change, whoever
332
+ // wrote it (`capture.ts`). Absent outside capture mode.
333
+ capture = await pinCaptureBaseline({
334
+ status,
335
+ executionId,
336
+ workspace: turn.workspace,
337
+ fileReview: adapter.capabilities.fileReview,
338
+ artifactStorage: turn.artifactStorage,
339
+ });
340
+
317
341
  heartbeatPhase = "harness";
318
342
  const outcome = await adapter.runTurn(turn, sink);
319
343
  armedWatchdog.stop();
320
344
  heartbeatPhase = "epilogue";
321
345
 
346
+ // The capture boundary, ONCE, over whatever the whole turn left on the
347
+ // tree — unless a stop fired mid-turn (`interrupted`: the tree may be
348
+ // mid-edit and the pause or drain reinvokes this same turn). Before the
349
+ // decisions settle below, so the stamp reads the rows as the engine
350
+ // left them. A pending review is the outcome table's second WAITING
351
+ // cause (`awaitingReviewArm`).
352
+ const reviewPending =
353
+ capture !== undefined && outcome.kind !== "interrupted"
354
+ ? await captureCandidate({
355
+ status,
356
+ executionId,
357
+ workspace: turn.workspace,
358
+ fileReview: adapter.capabilities.fileReview,
359
+ artifactStorage: turn.artifactStorage,
360
+ capture,
361
+ globalBypass: turn.mcp.leases.global,
362
+ })
363
+ : false;
364
+
365
+ // The rows whose decision never runs the tool (SKIP, REJECT) are settled
366
+ // by the runtime, once, now that the adapter has had its look at them and
367
+ // before any persist of the outcome: no engine event flips such a row, so
368
+ // without this it would persist WAITING on a finished execution. Every
369
+ // outcome passes through here (`approval-decisions.ts`).
370
+ terminalizeNonExecutingDecisions(status);
371
+
322
372
  switch (outcome.kind) {
323
373
  case "completed":
324
- return completeTurn(turn, ExecutionPhase.EXECUTION_COMPLETED);
374
+ return reviewPending ? pauseCompletedTurnForReview(turn) : completeTurn(turn, ExecutionPhase.EXECUTION_COMPLETED);
325
375
  case "cancelled":
326
- return completeTurn(turn, ExecutionPhase.EXECUTION_CANCELLED);
327
- case "awaiting_approval": {
328
- // Pause for review exactly like the native harness: the adapter put
329
- // the WAITING rows on the transcript; flip the phase, persist, and
330
- // RETURN to the workflow, which waits for the approval signal and
331
- // reinvokes.
332
- status.phase = ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL;
333
- await chokepoint.write();
334
- return { kind: "return", value: slimStatus(status) };
376
+ return reviewPending ? settleWith(awaitingReviewArm()) : completeTurn(turn, ExecutionPhase.EXECUTION_CANCELLED);
377
+ case "awaiting_approval":
378
+ // The adapter put the WAITING rows on the transcript (and a captured
379
+ // candidate, if any, rides the same write); the arm flips the phase,
380
+ // persists once, and RETURNS to the workflow, which waits for the
381
+ // approval or file-review signal and reinvokes.
382
+ return settleWith(awaitingApprovalArm());
383
+ case "tool_call_limit": {
384
+ // A review wins over the terminal (Q-M4-2): the limit's copy rides
385
+ // the transcript and the reinvocation's reconcile completes the turn.
386
+ const settledLimit = await settleWith(reviewPending ? awaitingReviewArm(toolCallLimitArm()) : toolCallLimitArm());
387
+ console.log(`${activityName} terminated (tool-call limit): execution=${executionId}${reviewPending ? ", review pending" : ""}`);
388
+ return settledLimit;
335
389
  }
336
390
  case "failed": {
337
- const settledFailure = await settleWith(failedArm(outcome.message, outcome.surface));
391
+ const arm = failedArm(outcome.message, outcome.surface);
392
+ const settledFailure = await settleWith(reviewPending ? awaitingReviewArm(arm) : arm);
338
393
  console.error(
339
394
  `${activityName} failed (${outcome.surface}): execution=${executionId}, error=${outcome.message}` +
340
- (outcome.cause instanceof Error ? `, cause=${outcome.cause.message}` : ""),
395
+ (outcome.cause instanceof Error ? `, cause=${outcome.cause.message}` : "") +
396
+ (reviewPending ? " — edits on the tree; review pending" : ""),
341
397
  );
342
398
  return settledFailure;
343
399
  }
@@ -400,6 +456,19 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
400
456
  return settleWith(unexpectedErrorArm("HarnessContractError", `${adapter.name} settled interrupted with no stop`));
401
457
  }
402
458
 
459
+ /**
460
+ * The engine finished AND left a reviewable change: the structured output
461
+ * is resolved now, before the WAITING persist, so the resume that
462
+ * reconciles the review completes with it (Q-M4-8 closes Q-M2a-5); then
463
+ * the review pause. Nothing else of the completion epilogue runs here —
464
+ * the plan artifact and the write-back belong to the settlement that
465
+ * actually completes the execution.
466
+ */
467
+ async function pauseCompletedTurnForReview(turn: TurnInput): Promise<Settled> {
468
+ await resolveStructuredOutput(turn, lastAssistantText());
469
+ return settleWith(awaitingReviewArm());
470
+ }
471
+
403
472
  /**
404
473
  * A turn the engine finished (COMPLETED) or ended cancelled on its own
405
474
  * (CANCELLED): the final text from the last AI row; the structured output
@@ -413,18 +482,11 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
413
482
  status.completedAt = utcTimestamp();
414
483
  status.phase = phase;
415
484
 
416
- let structuredOutput: unknown = status.structuredOutput;
417
485
  let finalText: string | undefined;
418
486
 
419
487
  if (phase === ExecutionPhase.EXECUTION_COMPLETED) {
420
- finalText = [...status.messages].reverse().find((m) => m.type === MessageType.MESSAGE_AI)?.content;
421
-
422
- if (structuredOutput === undefined && turn.structuredOutputSchema && finalText) {
423
- structuredOutput = await extractStructuredOutputFromText(turn, finalText);
424
- if (structuredOutput !== undefined) {
425
- status.structuredOutput = structuredOutput as JsonObject;
426
- }
427
- }
488
+ finalText = lastAssistantText();
489
+ await resolveStructuredOutput(turn, finalText);
428
490
 
429
491
  // Plan mode: publish the final plan message as a plan artifact (named
430
492
  // from the plan's title); the only artifact path a harness without an
@@ -452,14 +514,43 @@ async function runTurn(deps: TurnRuntimeDeps, input: NormalizedActivityInput): P
452
514
  await chokepoint.write();
453
515
  console.log(
454
516
  `${activityName} completed: execution=${executionId}, phase=${ExecutionPhase[status.phase]}, ` +
455
- `hasStructuredOutput=${structuredOutput !== undefined}` +
517
+ `hasStructuredOutput=${status.structuredOutput !== undefined}` +
456
518
  (status.error ? `, error=${status.error}` : ""),
457
519
  );
520
+ return { kind: "return", value: completionSlim(finalText) };
521
+ }
458
522
 
523
+ /** The last assistant text on the transcript: the turn's `final_text`. */
524
+ function lastAssistantText(): string | undefined {
525
+ return [...status.messages].reverse().find((m) => m.type === MessageType.MESSAGE_AI)?.content;
526
+ }
527
+
528
+ /**
529
+ * The structured output the execution asked for, folded onto the status
530
+ * unless the adapter already did (the deep-agent's `structuredResponse`):
531
+ * extracted from the final text through the tiers below. Runs where the
532
+ * engine has FINISHED speaking — a completed turn, and a completed turn
533
+ * the runtime pauses for file review (Q-M4-8: the pure-reconcile
534
+ * COMPLETED then carries it, on every harness).
535
+ */
536
+ async function resolveStructuredOutput(turn: TurnInput, finalText: string | undefined): Promise<void> {
537
+ if (status.structuredOutput !== undefined || !turn.structuredOutputSchema || !finalText) return;
538
+ const extracted = await extractStructuredOutputFromText(turn, finalText);
539
+ if (extracted !== undefined) status.structuredOutput = extracted as JsonObject;
540
+ }
541
+
542
+ /**
543
+ * The slim return of a COMPLETED execution: the status the workflow reads,
544
+ * with `final_text` and `structured` beside it for the callers that consume
545
+ * an agent's answer as a value (`call-agent-orchestrator.ts`). One shape for
546
+ * the two ways an execution completes — the engine's own finish and the
547
+ * pure file-review resume.
548
+ */
549
+ function completionSlim(finalText: string | undefined): Record<string, unknown> {
459
550
  const slim = slimStatus(status) as Record<string, unknown>;
460
551
  if (finalText !== undefined) slim.final_text = finalText;
461
- if (structuredOutput !== undefined) slim.structured = structuredOutput;
462
- return { kind: "return", value: slim };
552
+ if (status.structuredOutput !== undefined) slim.structured = status.structuredOutput;
553
+ return slim;
463
554
  }
464
555
 
465
556
  /**
@@ -8,8 +8,8 @@
8
8
  * contract of the runner (the hermetic goldens pin every string below byte
9
9
  * for byte, `activities/execute-cursor/__tests__/hermetic/`), and a table a
10
10
  * reader can scan is how that contract stays reviewable. The native
11
- * harness's `execute-deep-agent/streaming-terminal.ts` keeps one function
12
- * per arm; S3 aligns the two (P-1's copy alignment) with both in view.
11
+ * harness once kept one function per arm (`streaming-terminal.ts`, retired
12
+ * at S3 M2b); since S3 M2a both harnesses' turns end through this one table.
13
13
  *
14
14
  * The throw-vs-return rule, unchanged from the orchestrator it replaces:
15
15
  * - RETURN when a Temporal retry would only repeat the outcome — a stall
@@ -36,6 +36,7 @@ import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexec
36
36
  import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
37
37
 
38
38
  import { COST_LIMIT_USER_COPY, formatCostLimitError } from "../shared/cost-guard.js";
39
+ import { TOOL_CALL_LIMIT_USER_COPY, formatToolCallLimitError } from "../shared/tool-rounds.js";
39
40
  import { formatStallFailure, type StallTimeoutError } from "../shared/stall-watchdog.js";
40
41
  import { utcTimestamp } from "../shared/status.js";
41
42
  import type { WorkspaceLockTimeoutError } from "../shared/workspace/workspace-lock.js";
@@ -79,10 +80,6 @@ export const TERMINAL_COPY = {
79
80
  platformStop: {
80
81
  row: "Execution stopped by the platform.",
81
82
  },
82
- rejectedByUser: {
83
- error: "Execution rejected by user",
84
- row: "Execution was rejected by the user during tool approval.",
85
- },
86
83
  fileReview: {
87
84
  applyFailedPrefix: "Some approved file changes could not be applied because the file changed after review: ",
88
85
  discardedPrefix: "Some proposed file changes were discarded by the user and were not applied: ",
@@ -110,9 +107,9 @@ export function stallArm(error: StallTimeoutError): TerminalArm {
110
107
  /**
111
108
  * The cost cap stopped the turn. TERMINATED, not FAILED: the platform
112
109
  * deliberately stopped the run, work is checkpointed, and the conversation
113
- * continues on the next message (the recursion-limit precedent in
114
- * `execute-deep-agent/streaming-terminal.ts`). RETURN: a retry would burn
115
- * the same budget again.
110
+ * continues on the next message (the recursion-limit precedent,
111
+ * {@link toolCallLimitArm}). RETURN: a retry would burn the same budget
112
+ * again.
116
113
  */
117
114
  export function costCapArm(maxCostUsd: number, estimatedCostUsd: number): TerminalArm {
118
115
  return {
@@ -124,6 +121,23 @@ export function costCapArm(maxCostUsd: number, estimatedCostUsd: number): Termin
124
121
  };
125
122
  }
126
123
 
124
+ /**
125
+ * The engine exhausted its tool-round budget (`max_tool_rounds`). TERMINATED,
126
+ * not FAILED, for the cost cap's reason: the platform deliberately stopped
127
+ * the run, work is checkpointed, and the conversation continues on the next
128
+ * message. RETURN: a retry would spend the same budget again. The error's
129
+ * prefix is a cross-repo contract (`shared/tool-rounds.ts`).
130
+ */
131
+ export function toolCallLimitArm(): TerminalArm {
132
+ return {
133
+ phase: ExecutionPhase.EXECUTION_TERMINATED,
134
+ error: formatToolCallLimitError(),
135
+ rows: [TOOL_CALL_LIMIT_USER_COPY],
136
+ completes: true,
137
+ disposition: RETURN,
138
+ };
139
+ }
140
+
127
141
  /** The runner is draining. Not a user pause: FAILED with the shutdown copy, thrown as cancelled. */
128
142
  export function workerShutdownArm(): TerminalArm {
129
143
  return {
@@ -156,6 +170,44 @@ export function infrastructureCancelArm(): TerminalArm {
156
170
  };
157
171
  }
158
172
 
173
+ /**
174
+ * The engine proposed at least one gated side effect and stopped: the
175
+ * WAITING_APPROVAL rows are already on the transcript. Not an error, not
176
+ * complete, no copy; RETURN to the workflow, which waits for the approval
177
+ * signal and reinvokes with the decisions. Until S3 M4 this was an inline
178
+ * phase flip in `run-turn.ts`; it is an arm because every way an activity
179
+ * ends belongs in this one table.
180
+ */
181
+ export function awaitingApprovalArm(): TerminalArm {
182
+ return { phase: ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL, rows: [], completes: false, disposition: RETURN };
183
+ }
184
+
185
+ /**
186
+ * The engine's turn left a reviewable change on the tree (the runtime
187
+ * captured a candidate, `harness/capture.ts`): the same WAITING pause as an
188
+ * approval, because a file review is the other thing the workflow waits on
189
+ * and reinvokes for. A review WINS over the terminal the engine reported:
190
+ * edits on the user's disk must reach review whatever else happened, and a
191
+ * FAILED or TERMINATED execution never reinvokes, so the terminal is
192
+ * DEFERRED — its ROWS ride the transcript now (the failure copy, the
193
+ * tool-call-limit copy; an `engine`-surface failure has none), never its
194
+ * phase, its `error` or its completion stamp, and the resume's reconcile
195
+ * settles the execution COMPLETED as every pure file-review resume does
196
+ * (`fileReviewResolvedArm`). Until S3 M4 only the Cursor harness behaved so,
197
+ * and only because its boundary ran before it consulted its engine's
198
+ * result; the deep-agent wrote FAILED with the edits applied and unreviewed.
199
+ * Stated cost: the cloud's `status.error` prefix match for a tool-call limit
200
+ * does not fire when that limit left edits (Q-M4-2).
201
+ */
202
+ export function awaitingReviewArm(deferred?: TerminalArm): TerminalArm {
203
+ return {
204
+ phase: ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL,
205
+ rows: deferred?.rows ?? [],
206
+ completes: false,
207
+ disposition: RETURN,
208
+ };
209
+ }
210
+
159
211
  /** The control plane answered STOP. A clean COMPLETED early exit. */
160
212
  export function platformStopArm(): TerminalArm {
161
213
  return {
@@ -177,17 +229,6 @@ export function workspaceLockTimeoutArm(error: WorkspaceLockTimeoutError): Termi
177
229
  };
178
230
  }
179
231
 
180
- /** An adjudicated irreversible action (shell / MCP) was REJECTed. */
181
- export function rejectedByUserArm(): TerminalArm {
182
- return {
183
- phase: ExecutionPhase.EXECUTION_FAILED,
184
- error: TERMINAL_COPY.rejectedByUser.error,
185
- rows: [TERMINAL_COPY.rejectedByUser.row],
186
- completes: true,
187
- disposition: RETURN,
188
- };
189
- }
190
-
191
232
  /**
192
233
  * A pure file-review resume: the agent already finished its turn during
193
234
  * capture, so keeping or discarding a change never re-prompts it