@stigmer/runner 3.0.9-dev.20260616060535 → 3.1.1

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 (328) 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 +10 -0
  74. package/dist/activities/execute-deep-agent/hitl.js +5 -1
  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 +370 -56
  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 +11 -5
  92. package/dist/activities/execute-deep-agent/status-builder.js +6 -2
  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 +6 -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 +2 -5
  243. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +31 -13
  244. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +349 -0
  245. package/src/activities/execute-deep-agent/__tests__/stamp-flowed-rows.test.ts +119 -0
  246. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +12 -11
  247. package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +9 -9
  248. package/src/activities/execute-deep-agent/__tests__/subagent-approval-propagation.test.ts +160 -0
  249. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +213 -0
  250. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +3 -6
  251. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +84 -1
  252. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +4 -1
  253. package/src/activities/execute-deep-agent/approval-file-change.ts +80 -0
  254. package/src/activities/execute-deep-agent/attachment-injector.ts +20 -11
  255. package/src/activities/execute-deep-agent/cas-capture-backend.ts +66 -0
  256. package/src/activities/execute-deep-agent/cas-capture-observer.ts +125 -0
  257. package/src/activities/execute-deep-agent/hitl.ts +15 -1
  258. package/src/activities/execute-deep-agent/index.ts +434 -64
  259. package/src/activities/execute-deep-agent/inline-publisher.ts +27 -4
  260. package/src/activities/execute-deep-agent/setup.ts +223 -125
  261. package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +64 -0
  262. package/src/activities/execute-deep-agent/status-builder-shared.ts +62 -23
  263. package/src/activities/execute-deep-agent/status-builder.ts +19 -7
  264. package/src/activities/execute-deep-agent/streaming-side-effects.ts +2 -16
  265. package/src/activities/execute-deep-agent/streaming.ts +3 -13
  266. package/src/activities/execute-deep-agent/subagent-transformer.ts +53 -13
  267. package/src/activities/execute-deep-agent/subagent-wiring.ts +50 -3
  268. package/src/activities/execute-deep-agent/v3-status-builder.ts +8 -2
  269. package/src/claimcheck/payload-codec.ts +8 -8
  270. package/src/client/stigmer-client.ts +9 -1
  271. package/src/middleware/__tests__/approval-gate.test.ts +488 -4
  272. package/src/middleware/approval-gate.ts +247 -38
  273. package/src/middleware/types.ts +5 -5
  274. package/src/shared/__tests__/activity-input.test.ts +78 -0
  275. package/src/shared/__tests__/approval-canonicalize.test.ts +106 -0
  276. package/src/shared/__tests__/approval-fingerprint.test.ts +115 -0
  277. package/src/shared/__tests__/approval-policy.test.ts +274 -40
  278. package/src/shared/__tests__/args-preview.test.ts +78 -0
  279. package/src/shared/__tests__/artifact-storage-extended.test.ts +62 -10
  280. package/src/shared/__tests__/artifact-storage.test.ts +123 -11
  281. package/src/shared/__tests__/file-change.test.ts +85 -0
  282. package/src/shared/__tests__/file-tools.test.ts +90 -0
  283. package/src/shared/__tests__/fingerprint-secret.test.ts +51 -0
  284. package/src/shared/__tests__/lease-scope-corpus.test.ts +56 -0
  285. package/src/shared/__tests__/model-client.test.ts +162 -0
  286. package/src/shared/__tests__/plan-artifact.test.ts +11 -26
  287. package/src/shared/__tests__/policy-source-corpus.test.ts +58 -0
  288. package/src/shared/__tests__/status-offload.test.ts +573 -16
  289. package/src/shared/__tests__/status.test.ts +4 -5
  290. package/src/shared/__tests__/tool-kind.test.ts +24 -1
  291. package/src/shared/__tests__/tool-row.test.ts +221 -0
  292. package/src/shared/activity-input.ts +57 -0
  293. package/src/shared/approval-canonicalize.ts +159 -0
  294. package/src/shared/approval-fingerprint.ts +148 -0
  295. package/src/shared/approval-policy.ts +303 -27
  296. package/src/shared/args-preview.ts +98 -0
  297. package/src/shared/artifact-storage.ts +62 -11
  298. package/src/shared/checkpointer/__tests__/http-saver.test.ts +1 -2
  299. package/src/shared/file-change.ts +64 -0
  300. package/src/shared/file-tools.ts +169 -0
  301. package/src/shared/filereview/__tests__/capture.test.ts +856 -0
  302. package/src/shared/filereview/__tests__/cas-substrate.test.ts +404 -0
  303. package/src/shared/filereview/__tests__/digest.test.ts +100 -0
  304. package/src/shared/filereview/__tests__/events.test.ts +245 -0
  305. package/src/shared/filereview/__tests__/git-substrate.test.ts +362 -0
  306. package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +286 -0
  307. package/src/shared/filereview/__tests__/secret-paths.test.ts +121 -0
  308. package/src/shared/filereview/capture.ts +727 -0
  309. package/src/shared/filereview/cas-substrate.ts +401 -0
  310. package/src/shared/filereview/digest.ts +83 -0
  311. package/src/shared/filereview/events.ts +449 -0
  312. package/src/shared/filereview/git-substrate.ts +555 -0
  313. package/src/shared/filereview/index.ts +60 -0
  314. package/src/shared/filereview/secret-paths.ts +121 -0
  315. package/src/shared/fingerprint-secret.ts +53 -0
  316. package/src/shared/model-client.ts +122 -0
  317. package/src/shared/plan-artifact.ts +0 -2
  318. package/src/shared/status-offload.ts +433 -77
  319. package/src/shared/status.ts +13 -0
  320. package/src/shared/tool-kind.ts +33 -0
  321. package/src/shared/tool-row.ts +135 -0
  322. package/src/shared/workspace/platform-dir.ts +41 -2
  323. package/src/workflow-engine/__tests__/golden-execution.test.ts +35 -18
  324. package/src/workflow-engine/__tests__/tasks/try.test.ts +1 -1
  325. package/src/workflows/__tests__/connect-mcp-server.test.ts +304 -29
  326. package/src/workflows/call-agent-orchestrator.ts +53 -6
  327. package/src/workflows/connect-mcp-server.ts +179 -24
  328. package/src/workflows/types.ts +8 -0
@@ -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
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,30 +62,30 @@ 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
- // One read of the graph checkpoint drives two decisions below: whether
53
- // this invocation resumes an existing durable checkpoint (so status must
54
- // be seeded from the persisted transcript instead of starting empty),
55
- // and how any pending approval interrupt resolves. Reading once avoids a
56
- // redundant round-trip on the durable (http) saver.
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.
57
75
  const graphState = await setup.agentGraph.getState(setup.langgraphConfig);
58
- // Seed from the persisted transcript when resuming an existing
59
- // checkpoint; otherwise start empty. On a first run and under the
60
- // memory checkpointer (recreated empty per invocation, so the graph
61
- // replays from scratch)there are no prior checkpoint turns, so this
62
- // is a no-op and the original start-from-empty behavior is preserved.
63
- const initialStatus = shouldSeedFromCheckpoint(graphState, setup.execution)
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 alikeand is a no-op on a first run.
80
+ const initialStatus = shouldSeedFromPersistedTranscript(setup.execution)
64
81
  ? seedStatusFromExecution(setup.execution)
65
82
  : create(AgentExecutionStatusSchema, {});
66
83
  const statusBuilder = new StatusBuilder(executionId, initialStatus);
67
84
  statusBuilder.setApprovalProvider({
68
85
  policies: setup.approvalPolicies,
69
86
  toolServerMap: setup.toolServerMap,
70
- autoApproveAll: setup.autoApproveAll,
87
+ leasedCategories: setup.leasedCategories,
88
+ globalBypass: setup.globalBypass,
71
89
  });
72
90
  const resume = resolveResumeInput(setup.execution, graphState, setup.execution.spec.message);
73
91
  if (resume.hasRejection) {
@@ -105,6 +123,112 @@ export function createDeepAgentActivities(config) {
105
123
  workspaceBackend: setup.workspaceBackend,
106
124
  })
107
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
+ }
108
232
  const cancellationSignal = Context.current().cancellationSignal;
109
233
  const result = await streamExecution({
110
234
  agentGraph: setup.agentGraph,
@@ -117,45 +241,98 @@ export function createDeepAgentActivities(config) {
117
241
  offload: statusOffload,
118
242
  gracefulStop: setup.gracefulStop,
119
243
  inlinePublisher,
120
- 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),
121
247
  heartbeatFn: (details) => Context.current().heartbeat(details),
122
248
  isCancelledFn: () => cancellationSignal.aborted,
123
249
  approvalProvider: {
124
250
  policies: setup.approvalPolicies,
125
251
  toolServerMap: setup.toolServerMap,
126
- autoApproveAll: setup.autoApproveAll,
252
+ leasedCategories: setup.leasedCategories,
253
+ globalBypass: setup.globalBypass,
127
254
  },
128
255
  streamVersion: setup.streamVersion,
129
256
  });
130
257
  await processPostStream({
131
258
  status: initialStatus,
132
259
  inlinePublisher,
133
- 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,
134
264
  pendingPublishPromises: result.pendingPublishPromises,
135
265
  pendingWritebackPromises: result.pendingWritebackPromises,
136
266
  executionId,
137
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
+ }
138
314
  if (result.terminalStatus) {
139
315
  if (initialStatus.phase === ExecutionPhase.EXECUTION_PAUSED) {
140
316
  await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
141
317
  console.log(`[ExecuteDeepAgent] Paused for execution ${executionId}: events=${result.eventsProcessed}`);
142
318
  throw new CancelledFailure("Activity paused by orchestrator");
143
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
+ }
144
329
  return result.terminalStatus;
145
330
  }
146
- if (!setup.autoApproveAll) {
147
- const graphState = await setup.agentGraph.getState(setup.langgraphConfig);
148
- const pendingInterrupts = graphState.tasks?.flatMap((task) => (task.interrupts ?? [])
149
- .filter((intr) => intr.resumeValue === undefined)
150
- .map((intr) => {
151
- const val = intr.value;
152
- return {
153
- toolCallId: val?.tool_call_id ?? "",
154
- toolName: val?.tool_name ?? "",
155
- mcpServerSlug: val?.mcp_server_slug ?? "",
156
- message: val?.message ?? "",
157
- };
158
- })) ?? [];
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);
159
336
  if (pendingInterrupts.length > 0) {
160
337
  console.log(`[ExecuteDeepAgent] Detected ${pendingInterrupts.length} pending interrupt(s) ` +
161
338
  `for execution ${executionId} — setting WAITING_FOR_APPROVAL`);
@@ -167,7 +344,7 @@ export function createDeepAgentActivities(config) {
167
344
  isStreaming: false,
168
345
  });
169
346
  for (const intr of pendingInterrupts) {
170
- aiMsg.toolCalls.push(create(ToolCallSchema, {
347
+ const toolCall = create(ToolCallSchema, {
171
348
  id: intr.toolCallId,
172
349
  name: intr.toolName,
173
350
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
@@ -177,15 +354,37 @@ export function createDeepAgentActivities(config) {
177
354
  mcpServerSlug: intr.mcpServerSlug,
178
355
  startedAt: utcTimestamp(),
179
356
  toolKind: classifyTool(intr.toolName, intr.mcpServerSlug),
180
- }));
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);
181
371
  }
182
372
  initialStatus.messages.push(aiMsg);
183
373
  await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
184
374
  return slimStatus(initialStatus);
185
375
  }
186
376
  }
187
- initialStatus.phase = ExecutionPhase.EXECUTION_COMPLETED;
188
- 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
+ }
189
388
  let structuredOutput;
190
389
  let finalText;
191
390
  const lastAiMsg = [...initialStatus.messages]
@@ -226,8 +425,12 @@ export function createDeepAgentActivities(config) {
226
425
  // first-class plan.md artifact so the UI can render a reviewable Plan
227
426
  // card and a follow-up Implement run can reference it. Read-only mode
228
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).
229
431
  if (setup.execution.spec?.executionConfig?.interactionMode === InteractionMode.PLAN &&
230
- finalText) {
432
+ finalText &&
433
+ setup.artifactStorage) {
231
434
  await publishPlanArtifact({
232
435
  status: initialStatus,
233
436
  executionId,
@@ -235,13 +438,25 @@ export function createDeepAgentActivities(config) {
235
438
  artifactStorage: setup.artifactStorage,
236
439
  });
237
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
+ }
238
446
  await persistStatus(client, executionId, initialStatus, { offload: statusOffload });
239
- console.log(`[ExecuteDeepAgent] Completed for execution ${executionId}: ` +
447
+ console.log(`[ExecuteDeepAgent] ${completeNow ? "Completed" : "Awaiting file review for"} ` +
448
+ `execution ${executionId}: ` +
240
449
  `events=${result.eventsProcessed}, ` +
241
450
  `messages=${initialStatus.messages.length}, ` +
242
451
  `artifacts=${initialStatus.artifacts.length}, ` +
243
452
  `writebacks=${initialStatus.workspaceWriteBacks.length}, ` +
244
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
+ }
245
460
  const slim = slimStatus(initialStatus);
246
461
  if (finalText !== undefined) {
247
462
  slim.final_text = finalText;
@@ -295,25 +510,124 @@ export function createDeepAgentActivities(config) {
295
510
  };
296
511
  }
297
512
  /**
298
- * Whether this invocation resumes an existing durable checkpoint.
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.
299
605
  *
300
606
  * The Temporal workflow re-invokes ExecuteDeepAgent with the same thread_id on
301
- * three triggers — HITL approval, pause/resume, and transient recovery. With a
302
- * durable (http) checkpointer the graph resumes from its checkpoint and
303
- * streamEvents re-emits ONLY post-checkpoint events, so a status rebuilt from
304
- * empty would silently drop the prior transcript.
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.
305
611
  *
306
- * The resume is detected from the checkpoint itself prior message turns are
307
- * present in graph statewhich holds for every resume trigger (not just HITL)
308
- * and is false both on a first run and under the memory checkpointer (recreated
309
- * empty per invocation, so the graph replays). Requiring persisted history too
310
- * guarantees seeding never runs ahead of a transcript to seed from.
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.
311
628
  */
312
- function shouldSeedFromCheckpoint(graphState, execution) {
313
- const checkpointMessages = graphState.values.messages;
314
- const checkpointHasPriorTurns = Array.isArray(checkpointMessages) && checkpointMessages.length > 0;
315
- const persistedHasHistory = (execution.status?.messages.length ?? 0) > 0;
316
- return checkpointHasPriorTurns && persistedHasHistory;
629
+ function shouldSeedFromPersistedTranscript(execution) {
630
+ return (execution.status?.messages.length ?? 0) > 0;
317
631
  }
318
632
  /**
319
633
  * Seed a fresh status from the persisted execution transcript so streamed