@stigmer/runner 3.0.9-dev.20260615153829 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/__test-utils__/approval-contract/types.d.ts +174 -0
  3. package/dist/__test-utils__/approval-contract/types.js +24 -0
  4. package/dist/__test-utils__/approval-contract/types.js.map +1 -0
  5. package/dist/activities/call-agent-status.d.ts +19 -1
  6. package/dist/activities/call-agent-status.js +64 -5
  7. package/dist/activities/call-agent-status.js.map +1 -1
  8. package/dist/activities/call-llm.js +19 -53
  9. package/dist/activities/call-llm.js.map +1 -1
  10. package/dist/activities/classify-tool-approvals.d.ts +24 -0
  11. package/dist/activities/classify-tool-approvals.js +69 -17
  12. package/dist/activities/classify-tool-approvals.js.map +1 -1
  13. package/dist/activities/discover-mcp-server.d.ts +7 -0
  14. package/dist/activities/discover-mcp-server.js +11 -1
  15. package/dist/activities/discover-mcp-server.js.map +1 -1
  16. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +140 -0
  17. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +130 -0
  18. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -0
  19. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.d.ts +18 -0
  20. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +123 -0
  21. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -0
  22. package/dist/activities/execute-cursor/approval-policy.d.ts +17 -61
  23. package/dist/activities/execute-cursor/approval-policy.js +8 -120
  24. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  25. package/dist/activities/execute-cursor/approval-state.d.ts +219 -9
  26. package/dist/activities/execute-cursor/approval-state.js +233 -17
  27. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  28. package/dist/activities/execute-cursor/capture-flow.d.ts +127 -0
  29. package/dist/activities/execute-cursor/capture-flow.js +234 -0
  30. package/dist/activities/execute-cursor/capture-flow.js.map +1 -0
  31. package/dist/activities/execute-cursor/cas-observations.d.ts +96 -0
  32. package/dist/activities/execute-cursor/cas-observations.js +184 -0
  33. package/dist/activities/execute-cursor/cas-observations.js.map +1 -0
  34. package/dist/activities/execute-cursor/command-provenance.d.ts +62 -0
  35. package/dist/activities/execute-cursor/command-provenance.js +128 -0
  36. package/dist/activities/execute-cursor/command-provenance.js.map +1 -0
  37. package/dist/activities/execute-cursor/exact-apply.d.ts +110 -0
  38. package/dist/activities/execute-cursor/exact-apply.js +204 -0
  39. package/dist/activities/execute-cursor/exact-apply.js.map +1 -0
  40. package/dist/activities/execute-cursor/hook-script.d.ts +53 -24
  41. package/dist/activities/execute-cursor/hook-script.js +310 -47
  42. package/dist/activities/execute-cursor/hook-script.js.map +1 -1
  43. package/dist/activities/execute-cursor/index.d.ts +8 -1
  44. package/dist/activities/execute-cursor/index.js +500 -64
  45. package/dist/activities/execute-cursor/index.js.map +1 -1
  46. package/dist/activities/execute-cursor/message-translator.d.ts +258 -11
  47. package/dist/activities/execute-cursor/message-translator.js +836 -90
  48. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  49. package/dist/activities/execute-cursor/prompt-builder.d.ts +20 -23
  50. package/dist/activities/execute-cursor/prompt-builder.js +74 -15
  51. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  52. package/dist/activities/execute-cursor/workspace-setup.d.ts +17 -0
  53. package/dist/activities/execute-cursor/workspace-setup.js +212 -33
  54. package/dist/activities/execute-cursor/workspace-setup.js.map +1 -1
  55. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.d.ts +19 -0
  56. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js +143 -0
  57. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js.map +1 -0
  58. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +88 -0
  59. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +81 -0
  60. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -0
  61. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +47 -0
  62. package/dist/activities/execute-deep-agent/approval-file-change.js +68 -0
  63. package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -0
  64. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +8 -1
  65. package/dist/activities/execute-deep-agent/attachment-injector.js +7 -7
  66. package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
  67. package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +42 -0
  68. package/dist/activities/execute-deep-agent/cas-capture-backend.js +47 -0
  69. package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -0
  70. package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +79 -0
  71. package/dist/activities/execute-deep-agent/cas-capture-observer.js +112 -0
  72. package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -0
  73. package/dist/activities/execute-deep-agent/hitl.d.ts +16 -3
  74. package/dist/activities/execute-deep-agent/hitl.js +11 -3
  75. package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
  76. package/dist/activities/execute-deep-agent/index.d.ts +2 -1
  77. package/dist/activities/execute-deep-agent/index.js +393 -33
  78. package/dist/activities/execute-deep-agent/index.js.map +1 -1
  79. package/dist/activities/execute-deep-agent/inline-publisher.d.ts +7 -1
  80. package/dist/activities/execute-deep-agent/inline-publisher.js +23 -2
  81. package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
  82. package/dist/activities/execute-deep-agent/setup.d.ts +53 -2
  83. package/dist/activities/execute-deep-agent/setup.js +149 -92
  84. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  85. package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +36 -0
  86. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +56 -0
  87. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +1 -0
  88. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +34 -1
  89. package/dist/activities/execute-deep-agent/status-builder-shared.js +26 -25
  90. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
  91. package/dist/activities/execute-deep-agent/status-builder.d.ts +17 -5
  92. package/dist/activities/execute-deep-agent/status-builder.js +44 -3
  93. package/dist/activities/execute-deep-agent/status-builder.js.map +1 -1
  94. package/dist/activities/execute-deep-agent/streaming-side-effects.js +2 -19
  95. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  96. package/dist/activities/execute-deep-agent/streaming.js +3 -15
  97. package/dist/activities/execute-deep-agent/streaming.js.map +1 -1
  98. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -7
  99. package/dist/activities/execute-deep-agent/subagent-transformer.js +23 -7
  100. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  101. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +30 -3
  102. package/dist/activities/execute-deep-agent/subagent-wiring.js +29 -3
  103. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  104. package/dist/activities/execute-deep-agent/v3-status-builder.js +32 -2
  105. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
  106. package/dist/claimcheck/payload-codec.js +9 -5
  107. package/dist/claimcheck/payload-codec.js.map +1 -1
  108. package/dist/client/stigmer-client.d.ts +2 -0
  109. package/dist/client/stigmer-client.js +2 -0
  110. package/dist/client/stigmer-client.js.map +1 -1
  111. package/dist/middleware/approval-gate.d.ts +85 -4
  112. package/dist/middleware/approval-gate.js +165 -38
  113. package/dist/middleware/approval-gate.js.map +1 -1
  114. package/dist/middleware/types.d.ts +2 -5
  115. package/dist/shared/activity-input.d.ts +43 -0
  116. package/dist/shared/activity-input.js +17 -0
  117. package/dist/shared/activity-input.js.map +1 -0
  118. package/dist/shared/approval-canonicalize.d.ts +19 -0
  119. package/dist/shared/approval-canonicalize.js +119 -0
  120. package/dist/shared/approval-canonicalize.js.map +1 -0
  121. package/dist/shared/approval-fingerprint.d.ts +106 -0
  122. package/dist/shared/approval-fingerprint.js +113 -0
  123. package/dist/shared/approval-fingerprint.js.map +1 -0
  124. package/dist/shared/approval-policy.d.ts +182 -12
  125. package/dist/shared/approval-policy.js +213 -27
  126. package/dist/shared/approval-policy.js.map +1 -1
  127. package/dist/shared/args-preview.d.ts +52 -0
  128. package/dist/shared/args-preview.js +93 -0
  129. package/dist/shared/args-preview.js.map +1 -0
  130. package/dist/shared/artifact-storage.d.ts +19 -1
  131. package/dist/shared/artifact-storage.js +48 -11
  132. package/dist/shared/artifact-storage.js.map +1 -1
  133. package/dist/shared/file-change.d.ts +44 -0
  134. package/dist/shared/file-change.js +57 -0
  135. package/dist/shared/file-change.js.map +1 -0
  136. package/dist/shared/file-tools.d.ts +107 -0
  137. package/dist/shared/file-tools.js +168 -0
  138. package/dist/shared/file-tools.js.map +1 -0
  139. package/dist/shared/filereview/capture.d.ts +202 -0
  140. package/dist/shared/filereview/capture.js +498 -0
  141. package/dist/shared/filereview/capture.js.map +1 -0
  142. package/dist/shared/filereview/cas-substrate.d.ts +190 -0
  143. package/dist/shared/filereview/cas-substrate.js +284 -0
  144. package/dist/shared/filereview/cas-substrate.js.map +1 -0
  145. package/dist/shared/filereview/digest.d.ts +40 -0
  146. package/dist/shared/filereview/digest.js +66 -0
  147. package/dist/shared/filereview/digest.js.map +1 -0
  148. package/dist/shared/filereview/events.d.ts +170 -0
  149. package/dist/shared/filereview/events.js +298 -0
  150. package/dist/shared/filereview/events.js.map +1 -0
  151. package/dist/shared/filereview/git-substrate.d.ts +175 -0
  152. package/dist/shared/filereview/git-substrate.js +439 -0
  153. package/dist/shared/filereview/git-substrate.js.map +1 -0
  154. package/dist/shared/filereview/index.d.ts +11 -0
  155. package/dist/shared/filereview/index.js +12 -0
  156. package/dist/shared/filereview/index.js.map +1 -0
  157. package/dist/shared/filereview/secret-paths.d.ts +63 -0
  158. package/dist/shared/filereview/secret-paths.js +105 -0
  159. package/dist/shared/filereview/secret-paths.js.map +1 -0
  160. package/dist/shared/fingerprint-secret.d.ts +26 -0
  161. package/dist/shared/fingerprint-secret.js +47 -0
  162. package/dist/shared/fingerprint-secret.js.map +1 -0
  163. package/dist/shared/model-client.d.ts +51 -0
  164. package/dist/shared/model-client.js +77 -0
  165. package/dist/shared/model-client.js.map +1 -0
  166. package/dist/shared/plan-artifact.js +0 -2
  167. package/dist/shared/plan-artifact.js.map +1 -1
  168. package/dist/shared/status-offload.d.ts +83 -9
  169. package/dist/shared/status-offload.js +399 -79
  170. package/dist/shared/status-offload.js.map +1 -1
  171. package/dist/shared/status.js +14 -1
  172. package/dist/shared/status.js.map +1 -1
  173. package/dist/shared/tool-kind.d.ts +19 -0
  174. package/dist/shared/tool-kind.js +13 -0
  175. package/dist/shared/tool-kind.js.map +1 -1
  176. package/dist/shared/tool-row.d.ts +88 -0
  177. package/dist/shared/tool-row.js +127 -0
  178. package/dist/shared/tool-row.js.map +1 -0
  179. package/dist/shared/workspace/platform-dir.d.ts +25 -0
  180. package/dist/shared/workspace/platform-dir.js +38 -2
  181. package/dist/shared/workspace/platform-dir.js.map +1 -1
  182. package/dist/workflows/call-agent-orchestrator.js +56 -7
  183. package/dist/workflows/call-agent-orchestrator.js.map +1 -1
  184. package/dist/workflows/connect-mcp-server.d.ts +50 -0
  185. package/dist/workflows/connect-mcp-server.js +136 -15
  186. package/dist/workflows/connect-mcp-server.js.map +1 -1
  187. package/dist/workflows/types.d.ts +8 -0
  188. package/package.json +2 -2
  189. package/src/__test-utils__/approval-contract/contract.ts +224 -0
  190. package/src/__test-utils__/approval-contract/types.ts +179 -0
  191. package/src/__test-utils__/fake-artifact-storage.ts +72 -0
  192. package/src/__tests__/approval-gateway-contract.test.ts +29 -0
  193. package/src/__tests__/claimcheck-codec.test.ts +16 -53
  194. package/src/__tests__/golden-e2e.test.ts +2 -0
  195. package/src/__tests__/runner-token-coordinator.test.ts +3 -3
  196. package/src/activities/__tests__/call-agent-status.test.ts +135 -0
  197. package/src/activities/__tests__/call-llm.test.ts +1 -1
  198. package/src/activities/__tests__/classify-tool-approvals.test.ts +208 -1
  199. package/src/activities/__tests__/discover-mcp-server.test.ts +30 -0
  200. package/src/activities/__tests__/workflow-event-activities.test.ts +2 -1
  201. package/src/activities/call-agent-status.ts +74 -4
  202. package/src/activities/call-llm.ts +18 -63
  203. package/src/activities/classify-tool-approvals.ts +101 -19
  204. package/src/activities/discover-mcp-server.ts +29 -1
  205. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +216 -0
  206. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +148 -0
  207. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +41 -9
  208. package/src/activities/execute-cursor/__tests__/approval-state.test.ts +292 -0
  209. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +68 -1
  210. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +1005 -0
  211. package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +187 -0
  212. package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +97 -0
  213. package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +240 -0
  214. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +203 -0
  215. package/src/activities/execute-cursor/__tests__/exact-apply.test.ts +375 -0
  216. package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +1294 -24
  217. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +446 -0
  218. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +384 -110
  219. package/src/activities/execute-cursor/__tests__/message-translator.test.ts +171 -25
  220. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +189 -0
  221. package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +44 -23
  222. package/src/activities/execute-cursor/__tests__/workspace-setup.test.ts +190 -10
  223. package/src/activities/execute-cursor/approval-policy.ts +28 -159
  224. package/src/activities/execute-cursor/approval-state.ts +366 -18
  225. package/src/activities/execute-cursor/capture-flow.ts +323 -0
  226. package/src/activities/execute-cursor/cas-observations.ts +204 -0
  227. package/src/activities/execute-cursor/command-provenance.ts +168 -0
  228. package/src/activities/execute-cursor/exact-apply.ts +253 -0
  229. package/src/activities/execute-cursor/hook-script.ts +317 -51
  230. package/src/activities/execute-cursor/index.ts +575 -67
  231. package/src/activities/execute-cursor/message-translator.ts +963 -89
  232. package/src/activities/execute-cursor/prompt-builder.ts +80 -14
  233. package/src/activities/execute-cursor/workspace-setup.ts +257 -42
  234. package/src/activities/execute-deep-agent/__test-utils__/gateway-substrate.ts +180 -0
  235. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +134 -0
  236. package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +84 -0
  237. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +11 -24
  238. package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +64 -0
  239. package/src/activities/execute-deep-agent/__tests__/cas-capture-observer.test.ts +163 -0
  240. package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +8 -5
  241. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +342 -0
  242. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +284 -0
  243. package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +14 -36
  244. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +31 -13
  245. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +349 -0
  246. package/src/activities/execute-deep-agent/__tests__/stamp-flowed-rows.test.ts +119 -0
  247. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +91 -10
  248. package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +9 -9
  249. package/src/activities/execute-deep-agent/__tests__/subagent-approval-propagation.test.ts +160 -0
  250. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +213 -0
  251. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +3 -6
  252. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +84 -1
  253. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +4 -1
  254. package/src/activities/execute-deep-agent/approval-file-change.ts +80 -0
  255. package/src/activities/execute-deep-agent/attachment-injector.ts +20 -11
  256. package/src/activities/execute-deep-agent/cas-capture-backend.ts +66 -0
  257. package/src/activities/execute-deep-agent/cas-capture-observer.ts +125 -0
  258. package/src/activities/execute-deep-agent/hitl.ts +23 -7
  259. package/src/activities/execute-deep-agent/index.ts +463 -40
  260. package/src/activities/execute-deep-agent/inline-publisher.ts +27 -4
  261. package/src/activities/execute-deep-agent/setup.ts +223 -125
  262. package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +64 -0
  263. package/src/activities/execute-deep-agent/status-builder-shared.ts +62 -23
  264. package/src/activities/execute-deep-agent/status-builder.ts +63 -8
  265. package/src/activities/execute-deep-agent/streaming-side-effects.ts +2 -16
  266. package/src/activities/execute-deep-agent/streaming.ts +3 -13
  267. package/src/activities/execute-deep-agent/subagent-transformer.ts +53 -13
  268. package/src/activities/execute-deep-agent/subagent-wiring.ts +50 -3
  269. package/src/activities/execute-deep-agent/v3-status-builder.ts +36 -2
  270. package/src/claimcheck/payload-codec.ts +8 -8
  271. package/src/client/stigmer-client.ts +9 -1
  272. package/src/middleware/__tests__/approval-gate.test.ts +488 -4
  273. package/src/middleware/approval-gate.ts +247 -38
  274. package/src/middleware/types.ts +5 -5
  275. package/src/shared/__tests__/activity-input.test.ts +78 -0
  276. package/src/shared/__tests__/approval-canonicalize.test.ts +106 -0
  277. package/src/shared/__tests__/approval-fingerprint.test.ts +115 -0
  278. package/src/shared/__tests__/approval-policy.test.ts +274 -40
  279. package/src/shared/__tests__/args-preview.test.ts +78 -0
  280. package/src/shared/__tests__/artifact-storage-extended.test.ts +62 -10
  281. package/src/shared/__tests__/artifact-storage.test.ts +123 -11
  282. package/src/shared/__tests__/file-change.test.ts +85 -0
  283. package/src/shared/__tests__/file-tools.test.ts +90 -0
  284. package/src/shared/__tests__/fingerprint-secret.test.ts +51 -0
  285. package/src/shared/__tests__/lease-scope-corpus.test.ts +56 -0
  286. package/src/shared/__tests__/model-client.test.ts +162 -0
  287. package/src/shared/__tests__/plan-artifact.test.ts +11 -26
  288. package/src/shared/__tests__/policy-source-corpus.test.ts +58 -0
  289. package/src/shared/__tests__/status-offload.test.ts +573 -16
  290. package/src/shared/__tests__/status.test.ts +4 -5
  291. package/src/shared/__tests__/tool-kind.test.ts +24 -1
  292. package/src/shared/__tests__/tool-row.test.ts +221 -0
  293. package/src/shared/activity-input.ts +57 -0
  294. package/src/shared/approval-canonicalize.ts +159 -0
  295. package/src/shared/approval-fingerprint.ts +148 -0
  296. package/src/shared/approval-policy.ts +303 -27
  297. package/src/shared/args-preview.ts +98 -0
  298. package/src/shared/artifact-storage.ts +62 -11
  299. package/src/shared/checkpointer/__tests__/http-saver.test.ts +1 -2
  300. package/src/shared/file-change.ts +64 -0
  301. package/src/shared/file-tools.ts +169 -0
  302. package/src/shared/filereview/__tests__/capture.test.ts +856 -0
  303. package/src/shared/filereview/__tests__/cas-substrate.test.ts +404 -0
  304. package/src/shared/filereview/__tests__/digest.test.ts +100 -0
  305. package/src/shared/filereview/__tests__/events.test.ts +245 -0
  306. package/src/shared/filereview/__tests__/git-substrate.test.ts +362 -0
  307. package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +286 -0
  308. package/src/shared/filereview/__tests__/secret-paths.test.ts +121 -0
  309. package/src/shared/filereview/capture.ts +727 -0
  310. package/src/shared/filereview/cas-substrate.ts +401 -0
  311. package/src/shared/filereview/digest.ts +83 -0
  312. package/src/shared/filereview/events.ts +449 -0
  313. package/src/shared/filereview/git-substrate.ts +555 -0
  314. package/src/shared/filereview/index.ts +60 -0
  315. package/src/shared/filereview/secret-paths.ts +121 -0
  316. package/src/shared/fingerprint-secret.ts +53 -0
  317. package/src/shared/model-client.ts +122 -0
  318. package/src/shared/plan-artifact.ts +0 -2
  319. package/src/shared/status-offload.ts +433 -77
  320. package/src/shared/status.ts +13 -0
  321. package/src/shared/tool-kind.ts +33 -0
  322. package/src/shared/tool-row.ts +135 -0
  323. package/src/shared/workspace/platform-dir.ts +41 -2
  324. package/src/workflow-engine/__tests__/golden-execution.test.ts +35 -18
  325. package/src/workflow-engine/__tests__/tasks/try.test.ts +1 -1
  326. package/src/workflows/__tests__/connect-mcp-server.test.ts +304 -29
  327. package/src/workflows/call-agent-orchestrator.ts +53 -6
  328. package/src/workflows/connect-mcp-server.ts +179 -24
  329. package/src/workflows/types.ts +8 -0
@@ -31,9 +31,13 @@ const ACTION_MAP = new Map([
31
31
  * Returns a `Command(resume=...)` if there are pending interrupts with
32
32
  * matching approval decisions, or a fresh user message input if this is
33
33
  * not a resume scenario.
34
+ *
35
+ * The graph checkpoint snapshot is read once by the caller and passed in: the
36
+ * same snapshot also decides whether status must be seeded from the persisted
37
+ * transcript (see `index.ts`), and on the durable (http) saver an extra
38
+ * `getState` is a network round-trip best avoided.
34
39
  */
35
- export async function resolveResumeInput(execution, agentGraph, langgraphConfig, userMessage) {
36
- const graphState = await agentGraph.getState(langgraphConfig);
40
+ export function resolveResumeInput(execution, graphState, userMessage) {
37
41
  const pendingInterrupts = extractPendingInterrupts(graphState);
38
42
  if (pendingInterrupts.length === 0) {
39
43
  return {
@@ -101,7 +105,11 @@ function extractPendingInterrupts(state) {
101
105
  if (typeof value === "object" && value !== null) {
102
106
  const toolCallId = value.tool_call_id;
103
107
  if (typeof toolCallId === "string" && toolCallId) {
104
- result.push({ interruptId: task.id, toolCallId });
108
+ // Key on the interrupt's own id (falling back to task.id for the
109
+ // parent-level case where they coincide). This is what makes a
110
+ // sub-agent approval resume into the nested interrupt rather than
111
+ // being dropped — see InterruptValue.id.
112
+ result.push({ interruptId: intr.id ?? task.id, toolCallId });
105
113
  }
106
114
  }
107
115
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hitl.js","sourceRoot":"","sources":["../../../src/activities/execute-deep-agent/hitl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hitl.js","sourceRoot":"","sources":["../../../src/activities/execute-deep-agent/hitl.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,8 @@
8
8
  * Phase 3b-iii: full middleware stack + artifact storage, inline publishing,
9
9
  * incremental git writeback, and post-stream safety net.
10
10
  */
11
+ import { type ExecuteActivityInput } from "../../shared/activity-input.js";
11
12
  import type { Config } from "../../config.js";
12
13
  export declare function createDeepAgentActivities(config: Config): {
13
- ExecuteDeepAgent: (executionId: string, threadId: string) => Promise<unknown>;
14
+ ExecuteDeepAgent: (arg0: ExecuteActivityInput | string, arg1?: string) => Promise<unknown>;
14
15
  };
@@ -8,15 +8,19 @@
8
8
  * Phase 3b-iii: full middleware stack + artifact storage, inline publishing,
9
9
  * incremental git writeback, and post-stream safety net.
10
10
  */
11
+ import { readFile } from "node:fs/promises";
12
+ import { join } from "node:path";
11
13
  import { Context, CancelledFailure } from "@temporalio/activity";
12
- import { create } from "@bufbuild/protobuf";
14
+ import { create, clone } from "@bufbuild/protobuf";
13
15
  import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
14
16
  import { AgentMessageSchema, ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
15
- import { ExecutionPhase, InteractionMode, MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
17
+ import { ExecutionPhase, FileCaptureClass, FileChangeSetStatus, InteractionMode, MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
16
18
  import { activityStarted, activityFinished } from "../../idle-watchdog.js";
19
+ import { normalizeActivityInput } from "../../shared/activity-input.js";
17
20
  import { persistStatus, slimStatus, utcTimestamp } from "../../shared/status.js";
18
21
  import { publishPlanArtifact } from "../../shared/plan-artifact.js";
19
22
  import { classifyTool } from "../../shared/tool-kind.js";
23
+ import { POLICY_ENGINE_VERSION, toProtoPolicySource, } from "../../shared/approval-policy.js";
20
24
  import { StigmerClient } from "../../client/stigmer-client.js";
21
25
  import { performSetup } from "./setup.js";
22
26
  import { streamExecution } from "./streaming.js";
@@ -26,6 +30,15 @@ import { InlinePublisher } from "./inline-publisher.js";
26
30
  import { WriteBackCoordinator } from "./writeback-coordinator.js";
27
31
  import { processPostStream } from "./post-stream.js";
28
32
  import { resolveResumeInput } from "./hitl.js";
33
+ import { captureApprovalArtifacts } from "./approval-file-change.js";
34
+ import { applyCaptureDecisions, captureBaselineToLedger, captureCandidateToLedger, } from "../../shared/filereview/capture.js";
35
+ import { hasCandidateCaptured } from "../../shared/filereview/events.js";
36
+ import { casBlobReader } from "../../shared/filereview/cas-substrate.js";
37
+ import { partitionIgnoredPathsBySecret } from "../../shared/filereview/secret-paths.js";
38
+ import { collectSubAgentToolCallIds } from "../../shared/tool-row.js";
39
+ import { stampFlowedFileEditRows, stampFlowedSubAgentFileEditRows } from "./stamp-flowed-rows.js";
40
+ /** The harness id stamped on the deep-agent's file-review ledger events. */
41
+ const DEEP_AGENT_HARNESS_ID = "deep-agent";
29
42
  export function createDeepAgentActivities(config) {
30
43
  const client = new StigmerClient({
31
44
  endpoint: config.stigmerBackendEndpoint,
@@ -34,7 +47,12 @@ export function createDeepAgentActivities(config) {
34
47
  });
35
48
  const streamingConfig = loadStreamingConfig();
36
49
  return {
37
- ExecuteDeepAgent: async (executionId, threadId) => {
50
+ // Accepts the new typed object OR the legacy positional args (transitional
51
+ // dual-shape so the runner can deploy before the control planes — see
52
+ // shared/activity-input.ts). Drop the positional arm once both control
53
+ // planes send the object.
54
+ ExecuteDeepAgent: async (arg0, arg1) => {
55
+ const { executionId, threadId, turnSeq } = normalizeActivityInput(arg0, arg1);
38
56
  activityStarted();
39
57
  let setup = null;
40
58
  try {
@@ -44,19 +62,32 @@ export function createDeepAgentActivities(config) {
44
62
  // oversized tool outputs (e.g. computer-use screenshots) to artifact
45
63
  // storage so the UI can render them, and keep the status under the
46
64
  // gRPC cap. Threaded into the streaming loop and reused for the
47
- // terminal persists below so the guard is never skipped.
48
- const statusOffload = {
49
- artifactStorage: setup.artifactStorage,
50
- executionId,
51
- };
52
- const initialStatus = create(AgentExecutionStatusSchema, {});
65
+ // terminal persists below so the guard is never skipped. Undefined when
66
+ // there is no artifact store (proxy misconfig): offload is then disabled,
67
+ // but persistStatus still enforces the aggregate size cap, so persistence
68
+ // can never silently blow past the gRPC limit.
69
+ const statusOffload = setup.artifactStorage
70
+ ? { artifactStorage: setup.artifactStorage, executionId }
71
+ : undefined;
72
+ // Read the graph checkpoint once, to resolve how a pending approval
73
+ // interrupt continues (Command(resume) vs a fresh replay). Reading once
74
+ // avoids a redundant round-trip on the durable (http) saver.
75
+ const graphState = await setup.agentGraph.getState(setup.langgraphConfig);
76
+ // Seed from the persisted transcript whenever the execution already has
77
+ // committed history, so streamed deltas append onto it instead of
78
+ // replacing it. This holds for every re-invocation — durable resume and
79
+ // memory-checkpointer replay alike — and is a no-op on a first run.
80
+ const initialStatus = shouldSeedFromPersistedTranscript(setup.execution)
81
+ ? seedStatusFromExecution(setup.execution)
82
+ : create(AgentExecutionStatusSchema, {});
53
83
  const statusBuilder = new StatusBuilder(executionId, initialStatus);
54
84
  statusBuilder.setApprovalProvider({
55
85
  policies: setup.approvalPolicies,
56
86
  toolServerMap: setup.toolServerMap,
57
- autoApproveAll: setup.autoApproveAll,
87
+ leasedCategories: setup.leasedCategories,
88
+ globalBypass: setup.globalBypass,
58
89
  });
59
- const resume = await resolveResumeInput(setup.execution, setup.agentGraph, setup.langgraphConfig, setup.execution.spec.message);
90
+ const resume = resolveResumeInput(setup.execution, graphState, setup.execution.spec.message);
60
91
  if (resume.hasRejection) {
61
92
  const failedStatus = create(AgentExecutionStatusSchema, {
62
93
  phase: ExecutionPhase.EXECUTION_FAILED,
@@ -92,6 +123,112 @@ export function createDeepAgentActivities(config) {
92
123
  workspaceBackend: setup.workspaceBackend,
93
124
  })
94
125
  : null;
126
+ // Apply-then-review capture identity + substrate root for this turn.
127
+ const gitRoot = setup.workspaceBackend.rootDir;
128
+ const changeSetId = `${executionId}:${turnSeq}`;
129
+ // (1) Capture-mode resume — reconcile any DECIDED change set FIRST (this
130
+ // drops the per-execution refs), before the next baseline re-pins them
131
+ // (refs are executionId-keyed). Then (2) short-circuit a pure file-review
132
+ // resume — the agent already finished in a prior segment, so finalize with
133
+ // NO model re-invocation. A mixed turn (a tool gate is also pending) falls
134
+ // through to resume the graph for the gated tool.
135
+ if (setup.captureMode) {
136
+ const decidedSets = (setup.execution.status?.fileChangeSets ?? []).filter((cs) => cs.status === FileChangeSetStatus.DECIDED);
137
+ let reconciledAny = false;
138
+ let reconcileFailed = false;
139
+ let reconcileFailureDetail = "";
140
+ // The CAS blob reader reconciles ignored-file decisions from the durable
141
+ // manifest (git-only turns have no manifest, so the CAS branch no-ops).
142
+ // Undefined with no store: this block still runs for a git workspace
143
+ // whose captureMode is true without storage, but such a turn captures no
144
+ // CAS files (captureIgnored is off), so its change set carries no CAS ref
145
+ // and applyCaptureDecisions never needs the reader.
146
+ const casReadBlob = setup.artifactStorage
147
+ ? casBlobReader(setup.artifactStorage)
148
+ : undefined;
149
+ for (const changeSet of decidedSets) {
150
+ const capResult = await applyCaptureDecisions({
151
+ status: initialStatus,
152
+ gitRoot,
153
+ executionId,
154
+ changeSet,
155
+ harnessId: DEEP_AGENT_HARNESS_ID,
156
+ storage: setup.artifactStorage,
157
+ readBlob: casReadBlob,
158
+ gitWorkspace: setup.gitWorkspace,
159
+ });
160
+ if (!capResult.isCaptureTurn)
161
+ continue;
162
+ reconciledAny = true;
163
+ if (capResult.failed) {
164
+ reconcileFailed = true;
165
+ reconcileFailureDetail =
166
+ capResult.failureDetail ?? "file review reconcile failed";
167
+ }
168
+ }
169
+ if (reconciledAny) {
170
+ if (reconcileFailed) {
171
+ // What-you-approve-is-what-applies failed: nothing was applied.
172
+ initialStatus.phase = ExecutionPhase.EXECUTION_FAILED;
173
+ initialStatus.error = `File review reconcile failed: ${reconcileFailureDetail}`;
174
+ initialStatus.completedAt = utcTimestamp();
175
+ await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
176
+ return slimStatus(initialStatus);
177
+ }
178
+ if (!hasPendingToolApprovals(setup.execution)) {
179
+ // Pure file review: the agent's final answer + outputs already rode
180
+ // the prior segment's persisted status (seeded into initialStatus).
181
+ // Complete now and push only the approved tree — NO model re-run.
182
+ //
183
+ // The discriminator is the PERSISTED transcript, not the live graph
184
+ // checkpoint: the memory checkpointer (OSS local / desktop) recreates
185
+ // the checkpoint empty each invocation, so a graphState-based check
186
+ // would wrongly fire for a mixed turn. A mixed turn leaves
187
+ // WAITING_APPROVAL tool rows in the transcript; a pure file-review
188
+ // turn leaves none.
189
+ initialStatus.phase = ExecutionPhase.EXECUTION_COMPLETED;
190
+ initialStatus.completedAt = utcTimestamp();
191
+ if (writebackCoordinator) {
192
+ await processCaptureWriteback(writebackCoordinator, executionId);
193
+ }
194
+ await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
195
+ // Surface the agent's final outputs (computed in the prior segment,
196
+ // carried on the seeded status) the same way a normal completion does.
197
+ const slim = slimStatus(initialStatus);
198
+ const lastAi = [...initialStatus.messages]
199
+ .reverse()
200
+ .find((m) => m.type === MessageType.MESSAGE_AI);
201
+ if (lastAi?.content)
202
+ slim.final_text = lastAi.content;
203
+ if (initialStatus.structuredOutput !== undefined) {
204
+ slim.structured = initialStatus.structuredOutput;
205
+ }
206
+ return slim;
207
+ }
208
+ // else: mixed turn — fall through; the graph resumes for the gated
209
+ // tool and a new baseline is taken below for the continuation segment.
210
+ }
211
+ }
212
+ // Turn start (capture mode): pin the pre-turn tree + author BASELINE. Taken
213
+ // AFTER any reconcile above and AFTER performSetup's workspace writes, so
214
+ // the baseline absorbs the reconciled state and the runner-owned files.
215
+ let captureBaselineTree = "";
216
+ // Snapshot the sub-agent tool-call ids that exist BEFORE this turn's
217
+ // stream, so the turn-boundary stamp scopes itself to sub-agent rows
218
+ // created this turn (empty here by construction — this harness never
219
+ // seeds prior sub-agents — but computed, not assumed, so it stays correct
220
+ // if that ever changes; see collectSubAgentToolCallIds).
221
+ const priorSubAgentToolCallIds = collectSubAgentToolCallIds(initialStatus.subAgentExecutions);
222
+ if (setup.captureMode) {
223
+ captureBaselineTree = await captureBaselineToLedger({
224
+ status: initialStatus,
225
+ gitRoot,
226
+ executionId,
227
+ changeSetId,
228
+ harnessId: DEEP_AGENT_HARNESS_ID,
229
+ gitWorkspace: setup.gitWorkspace,
230
+ });
231
+ }
95
232
  const cancellationSignal = Context.current().cancellationSignal;
96
233
  const result = await streamExecution({
97
234
  agentGraph: setup.agentGraph,
@@ -104,45 +241,98 @@ export function createDeepAgentActivities(config) {
104
241
  offload: statusOffload,
105
242
  gracefulStop: setup.gracefulStop,
106
243
  inlinePublisher,
107
- writebackCoordinator: writebackCoordinator ?? undefined,
244
+ // Capture mode: never push speculative edits during the turn. Writeback
245
+ // is deferred until the approved tree is reconciled (post-decision).
246
+ writebackCoordinator: setup.captureMode ? undefined : (writebackCoordinator ?? undefined),
108
247
  heartbeatFn: (details) => Context.current().heartbeat(details),
109
248
  isCancelledFn: () => cancellationSignal.aborted,
110
249
  approvalProvider: {
111
250
  policies: setup.approvalPolicies,
112
251
  toolServerMap: setup.toolServerMap,
113
- autoApproveAll: setup.autoApproveAll,
252
+ leasedCategories: setup.leasedCategories,
253
+ globalBypass: setup.globalBypass,
114
254
  },
115
255
  streamVersion: setup.streamVersion,
116
256
  });
117
257
  await processPostStream({
118
258
  status: initialStatus,
119
259
  inlinePublisher,
120
- writebackCoordinator,
260
+ // Capture mode: suppress the post-stream writeback finalize — the edits
261
+ // on disk are still speculative until reviewed. Writeback runs only on
262
+ // the approved tree (processCaptureWriteback, after reconcile).
263
+ writebackCoordinator: setup.captureMode ? null : writebackCoordinator,
121
264
  pendingPublishPromises: result.pendingPublishPromises,
122
265
  pendingWritebackPromises: result.pendingWritebackPromises,
123
266
  executionId,
124
267
  });
268
+ // Turn boundary (capture mode): capture the candidate change set from the
269
+ // git diff and author CANDIDATE_CAPTURED, then stamp the flowed file-edit
270
+ // rows with the change set id — they stay visible in place as
271
+ // observational records while file_change_sets remains the single
272
+ // decision surface. Skipped on an abnormal terminal (pause / stop /
273
+ // recursion limit) — there is no review to open. `fileReviewPending`
274
+ // then composes with any tool gate below.
275
+ let fileReviewPending = false;
276
+ const abnormalTerminal = !!result.terminalStatus &&
277
+ initialStatus.phase !== ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL;
278
+ if (setup.captureMode && !abnormalTerminal) {
279
+ // Compose the CAS-captured paths (before-bytes from the observer,
280
+ // after-bytes re-read from disk) and the secret-blocked paths into the
281
+ // change set. The substrate class labels their provenance:
282
+ // GIT_IGNORED_CAPTURED for a git tree's ignored paths, NON_GIT_CAS for a
283
+ // non-git workspace (where these ARE the whole change set). In a git turn
284
+ // they compose with the git-tracked diff into one hybrid set; in a non-git
285
+ // turn they are the entire (CAS-only) set.
286
+ const casCaptureClass = setup.gitWorkspace
287
+ ? FileCaptureClass.GIT_IGNORED_CAPTURED
288
+ : FileCaptureClass.NON_GIT_CAS;
289
+ const { casCaptures, unreviewablePaths } = await buildCasTurnCaptures(setup.casObserver, gitRoot, casCaptureClass);
290
+ await captureCandidateToLedger({
291
+ status: initialStatus,
292
+ gitRoot,
293
+ executionId,
294
+ changeSetId,
295
+ baselineTree: captureBaselineTree,
296
+ harnessId: DEEP_AGENT_HARNESS_ID,
297
+ casCaptures,
298
+ storage: setup.artifactStorage,
299
+ unreviewablePaths,
300
+ unreviewableCaptureClass: casCaptureClass,
301
+ gitWorkspace: setup.gitWorkspace,
302
+ });
303
+ // Review is pending iff a CANDIDATE was actually authored (the seam
304
+ // drops no-op captures), so a turn that only touched-then-unchanged an
305
+ // ignored file does not open an empty review. Stamping is gated on the
306
+ // same signal: a row must never reference a change set that does not
307
+ // exist.
308
+ fileReviewPending = hasCandidateCaptured(initialStatus, changeSetId);
309
+ if (fileReviewPending) {
310
+ stampFlowedFileEditRows(initialStatus.messages, changeSetId);
311
+ stampFlowedSubAgentFileEditRows(initialStatus.subAgentExecutions, changeSetId, priorSubAgentToolCallIds);
312
+ }
313
+ }
125
314
  if (result.terminalStatus) {
126
315
  if (initialStatus.phase === ExecutionPhase.EXECUTION_PAUSED) {
127
316
  await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
128
317
  console.log(`[ExecuteDeepAgent] Paused for execution ${executionId}: events=${result.eventsProcessed}`);
129
318
  throw new CancelledFailure("Activity paused by orchestrator");
130
319
  }
320
+ // Capture mode: a tool gate set WAITING during the stream while file
321
+ // edits also flowed this turn. The CANDIDATE event + stamped file-edit
322
+ // rows post-date the stream's slim, so persist + return the current
323
+ // status (both review surfaces — the file change set and the tool gate —
324
+ // are now pending). `!abnormalTerminal` means the capture block ran.
325
+ if (setup.captureMode && !abnormalTerminal) {
326
+ await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
327
+ return slimStatus(initialStatus);
328
+ }
131
329
  return result.terminalStatus;
132
330
  }
133
- if (!setup.autoApproveAll) {
134
- const graphState = await setup.agentGraph.getState(setup.langgraphConfig);
135
- const pendingInterrupts = graphState.tasks?.flatMap((task) => (task.interrupts ?? [])
136
- .filter((intr) => intr.resumeValue === undefined)
137
- .map((intr) => {
138
- const val = intr.value;
139
- return {
140
- toolCallId: val?.tool_call_id ?? "",
141
- toolName: val?.tool_name ?? "",
142
- mcpServerSlug: val?.mcp_server_slug ?? "",
143
- message: val?.message ?? "",
144
- };
145
- })) ?? [];
331
+ if (!setup.globalBypass) {
332
+ const postStreamGraphState = await setup.agentGraph.getState(setup.langgraphConfig);
333
+ const graphMessages = postStreamGraphState.values.messages;
334
+ const aiMessages = Array.isArray(graphMessages) ? graphMessages : [];
335
+ const pendingInterrupts = detectPendingInterrupts(postStreamGraphState);
146
336
  if (pendingInterrupts.length > 0) {
147
337
  console.log(`[ExecuteDeepAgent] Detected ${pendingInterrupts.length} pending interrupt(s) ` +
148
338
  `for execution ${executionId} — setting WAITING_FOR_APPROVAL`);
@@ -154,7 +344,7 @@ export function createDeepAgentActivities(config) {
154
344
  isStreaming: false,
155
345
  });
156
346
  for (const intr of pendingInterrupts) {
157
- aiMsg.toolCalls.push(create(ToolCallSchema, {
347
+ const toolCall = create(ToolCallSchema, {
158
348
  id: intr.toolCallId,
159
349
  name: intr.toolName,
160
350
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
@@ -164,15 +354,37 @@ export function createDeepAgentActivities(config) {
164
354
  mcpServerSlug: intr.mcpServerSlug,
165
355
  startedAt: utcTimestamp(),
166
356
  toolKind: classifyTool(intr.toolName, intr.mcpServerSlug),
167
- }));
357
+ approvalPolicySource: toProtoPolicySource(intr.policySource),
358
+ policyEngineVersion: intr.policySource ? POLICY_ENGINE_VERSION : "",
359
+ });
360
+ // Capture a sanitized args preview while the graph is paused, so the
361
+ // approval UI renders the proposed change before the tool runs. Args
362
+ // are correlated from the AI-message tool call in graph state (the
363
+ // single source of truth).
364
+ const { argsPreview } = captureApprovalArtifacts({
365
+ toolCallId: intr.toolCallId,
366
+ messages: aiMessages,
367
+ });
368
+ if (argsPreview)
369
+ toolCall.argsPreview = argsPreview;
370
+ aiMsg.toolCalls.push(toolCall);
168
371
  }
169
372
  initialStatus.messages.push(aiMsg);
170
373
  await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
171
374
  return slimStatus(initialStatus);
172
375
  }
173
376
  }
174
- initialStatus.phase = ExecutionPhase.EXECUTION_COMPLETED;
175
- initialStatus.completedAt = utcTimestamp();
377
+ // Capture mode: file edits flowed but no tool gate fired — open file
378
+ // review instead of completing. The agent's final answer + outputs are
379
+ // still computed and persisted below, so the pure-file-review resume can
380
+ // complete from the seeded status with no model re-invocation.
381
+ const completeNow = !fileReviewPending;
382
+ initialStatus.phase = completeNow
383
+ ? ExecutionPhase.EXECUTION_COMPLETED
384
+ : ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL;
385
+ if (completeNow) {
386
+ initialStatus.completedAt = utcTimestamp();
387
+ }
176
388
  let structuredOutput;
177
389
  let finalText;
178
390
  const lastAiMsg = [...initialStatus.messages]
@@ -213,8 +425,12 @@ export function createDeepAgentActivities(config) {
213
425
  // first-class plan.md artifact so the UI can render a reviewable Plan
214
426
  // card and a follow-up Implement run can reference it. Read-only mode
215
427
  // produces no file to auto-publish, so this is the only artifact path.
428
+ // Requires artifact storage; with none (proxy misconfig) the plan text
429
+ // still lives in the final message — only the reviewable artifact is
430
+ // skipped (mirrors Cursor's storage-guarded plan publish).
216
431
  if (setup.execution.spec?.executionConfig?.interactionMode === InteractionMode.PLAN &&
217
- finalText) {
432
+ finalText &&
433
+ setup.artifactStorage) {
218
434
  await publishPlanArtifact({
219
435
  status: initialStatus,
220
436
  executionId,
@@ -222,13 +438,25 @@ export function createDeepAgentActivities(config) {
222
438
  artifactStorage: setup.artifactStorage,
223
439
  });
224
440
  }
441
+ // Capture mode: push the approved tree exactly once, on terminal
442
+ // completion — never the speculative mid-turn edits.
443
+ if (setup.captureMode && completeNow && writebackCoordinator) {
444
+ await processCaptureWriteback(writebackCoordinator, executionId);
445
+ }
225
446
  await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
226
- console.log(`[ExecuteDeepAgent] Completed for execution ${executionId}: ` +
447
+ console.log(`[ExecuteDeepAgent] ${completeNow ? "Completed" : "Awaiting file review for"} ` +
448
+ `execution ${executionId}: ` +
227
449
  `events=${result.eventsProcessed}, ` +
228
450
  `messages=${initialStatus.messages.length}, ` +
229
451
  `artifacts=${initialStatus.artifacts.length}, ` +
230
452
  `writebacks=${initialStatus.workspaceWriteBacks.length}, ` +
231
453
  `hasStructuredOutput=${structuredOutput !== undefined}`);
454
+ // A WAITING (file-review) return carries no final outputs yet — those are
455
+ // surfaced when the pure-file-review resume completes from this persisted
456
+ // status. The COMPLETED return enriches the slim with final text/outputs.
457
+ if (!completeNow) {
458
+ return slimStatus(initialStatus);
459
+ }
232
460
  const slim = slimStatus(initialStatus);
233
461
  if (finalText !== undefined) {
234
462
  slim.final_text = finalText;
@@ -281,6 +509,138 @@ export function createDeepAgentActivities(config) {
281
509
  },
282
510
  };
283
511
  }
512
+ /**
513
+ * Normalize the graph checkpoint's un-resumed interrupts into pending approvals.
514
+ * Used both before streaming (to detect whether a resume is a pure file review)
515
+ * and after (to seed the WAITING_FOR_APPROVAL tool rows).
516
+ */
517
+ function detectPendingInterrupts(graphState) {
518
+ const tasks = graphState.tasks;
519
+ return (tasks?.flatMap((task) => (task.interrupts ?? [])
520
+ .filter((intr) => intr.resumeValue === undefined)
521
+ .map((intr) => {
522
+ const val = intr.value;
523
+ return {
524
+ toolCallId: val?.tool_call_id ?? "",
525
+ toolName: val?.tool_name ?? "",
526
+ mcpServerSlug: val?.mcp_server_slug ?? "",
527
+ message: val?.message ?? "",
528
+ policySource: val?.policy_source || undefined,
529
+ };
530
+ })) ?? []);
531
+ }
532
+ /**
533
+ * Whether the persisted transcript holds any tool call awaiting approval — the
534
+ * checkpointer-independent signal that a resume must drive a tool gate (resume
535
+ * the graph), not just a file review. Scans root + sub-agent messages. A tool
536
+ * keeps `WAITING_APPROVAL` after the user decides (the decision rides
537
+ * `approval_action`) until the runner reconciles it, so this is true for a mixed
538
+ * turn's resume and false for a pure file-review turn.
539
+ */
540
+ function hasPendingToolApprovals(execution) {
541
+ const status = execution.status;
542
+ if (!status)
543
+ return false;
544
+ const anyWaiting = (msgs) => msgs.some((m) => m.toolCalls.some((tc) => tc.status === ToolCallStatus.TOOL_CALL_WAITING_APPROVAL));
545
+ if (anyWaiting(status.messages))
546
+ return true;
547
+ return status.subAgentExecutions.some((sa) => anyWaiting(sa.messages));
548
+ }
549
+ /**
550
+ * Assemble the turn's CAS captures and secret-blocked paths from the shared
551
+ * observer (the pre-turn bytes recorded by the parent AND every sub-agent CAS
552
+ * backend, plus the gate's secret-blocked set).
553
+ *
554
+ * For each observed CAS-owned path the after-bytes are re-read from disk (the
555
+ * authoritative net result of the turn; `null` when the file is gone). A path
556
+ * that is secret-like is diverted to `unreviewablePaths` and its before-bytes are
557
+ * dropped — the fail-closed backstop that holds even under the global bypass,
558
+ * where the gate did not run to block it up front. The result composes into the
559
+ * change set in {@link captureCandidateToLedger}.
560
+ *
561
+ * `captureClass` is the turn's CAS substrate class — GIT_IGNORED_CAPTURED for a
562
+ * git work tree's ignored paths, NON_GIT_CAS for a non-git workspace (where these
563
+ * ARE the whole change set) — so each captured path carries its true provenance.
564
+ */
565
+ async function buildCasTurnCaptures(observer, workspaceRoot, captureClass) {
566
+ // The secret partition (pure, corpus-lockable) decides what may be captured;
567
+ // this shell only performs the IO for the capturable set. The backstop that
568
+ // withholds a secret observed under the global bypass lives in the partition.
569
+ const { capturablePaths, unreviewablePaths } = partitionIgnoredPathsBySecret(observer.before.keys(), observer.blockedSecretPaths);
570
+ const casCaptures = [];
571
+ for (const relPath of capturablePaths) {
572
+ const after = await readFileOrNull(join(workspaceRoot, relPath));
573
+ casCaptures.push({
574
+ path: relPath,
575
+ before: observer.before.get(relPath) ?? null,
576
+ after,
577
+ captureClass,
578
+ });
579
+ }
580
+ return { casCaptures, unreviewablePaths: [...unreviewablePaths] };
581
+ }
582
+ /** Raw bytes of a file, or `null` when it does not exist (a DELETE). */
583
+ async function readFileOrNull(absolutePath) {
584
+ try {
585
+ return await readFile(absolutePath);
586
+ }
587
+ catch {
588
+ return null;
589
+ }
590
+ }
591
+ /**
592
+ * Push the reconciled (approved) tree exactly once, on terminal completion in
593
+ * capture mode. The coordinator's {@link WriteBackCoordinator.finalize} commits +
594
+ * pushes whatever uncommitted changes remain — which, post-reconcile, is exactly
595
+ * the approved content (rejected files were already snapped back to baseline).
596
+ * Speculative mid-turn edits never reach here (writeback is suppressed during the
597
+ * turn). Fire-and-forget by the coordinator's own contract (errors logged).
598
+ */
599
+ async function processCaptureWriteback(writebackCoordinator, executionId) {
600
+ await writebackCoordinator.finalize();
601
+ console.log(`[ExecuteDeepAgent] capture writeback finalized for execution ${executionId}`);
602
+ }
603
+ /**
604
+ * Whether to seed the initial status from the persisted execution transcript.
605
+ *
606
+ * The Temporal workflow re-invokes ExecuteDeepAgent with the same thread_id on
607
+ * every continuation — HITL approval, pause/resume, and transient recovery. The
608
+ * runner owns the transcript and the server enforces it as append-only at
609
+ * identity, so any continuation must build ON the committed history rather than
610
+ * rebuilding from an empty proto and replacing it.
611
+ *
612
+ * The decision is therefore driven solely by whether the server already holds
613
+ * committed history for this execution — NOT by the live graph checkpoint, which
614
+ * the two checkpointers leave in different states for the same continuation:
615
+ * - durable (http): the checkpoint survives, the graph resumes via
616
+ * Command(resume), and streamEvents re-emits only post-checkpoint events;
617
+ * - memory (the OSS local / desktop default): the checkpoint is recreated
618
+ * empty every invocation, so the graph REPLAYS from scratch and the blind
619
+ * FIFO turns advance one gate at a time.
620
+ * Keying on the live checkpoint skipped seeding on that memory-replay path, so a
621
+ * second sequential gate emitted a transcript holding only the new gate, dropped
622
+ * the first gate's committed tool-call id, and tripped the server's append-only
623
+ * guard — the silent sequential-gate skip. Seeding whenever persisted history
624
+ * exists covers both paths; a re-emitted prior turn reconciles in place by
625
+ * tool-call id (StatusBuilder.rebuildToolCallIndex), so seeding never
626
+ * duplicates. False on a first run (no persisted messages), preserving the
627
+ * original start-from-empty behavior.
628
+ */
629
+ function shouldSeedFromPersistedTranscript(execution) {
630
+ return (execution.status?.messages.length ?? 0) > 0;
631
+ }
632
+ /**
633
+ * Seed a fresh status from the persisted execution transcript so streamed
634
+ * deltas append onto existing history rather than replacing it. The clone keeps
635
+ * the persisted proto immutable. Terminal fields are cleared because the resumed
636
+ * run is in progress again; the StatusBuilder constructor re-sets the phase.
637
+ */
638
+ function seedStatusFromExecution(execution) {
639
+ const seeded = clone(AgentExecutionStatusSchema, execution.status);
640
+ seeded.completedAt = "";
641
+ seeded.error = "";
642
+ return seeded;
643
+ }
284
644
  async function cleanup(setup) {
285
645
  if (!setup)
286
646
  return;