@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
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Regression test: resuming an execution from a durable LangGraph checkpoint
3
+ * must NOT wipe the message transcript.
4
+ *
5
+ * This models the cloud path deterministically. On the post-approval
6
+ * re-invocation of ExecuteDeepAgent:
7
+ * - the persisted execution already holds the run-1 transcript (an AI message
8
+ * plus the gated tool call in WAITING_APPROVAL, approved by the user);
9
+ * - the durable checkpoint exists (getState reports prior values + a pending
10
+ * interrupt), so streamEvents re-emits ONLY the post-interrupt events
11
+ * (the resumed tool execution + the following assistant turn).
12
+ *
13
+ * The activity must seed its status from the persisted execution so the
14
+ * streamed delta appends onto the existing history, and the resumed tool
15
+ * events must reconcile to the existing gated tool call rather than
16
+ * duplicating it. The persisted status after resume must therefore contain
17
+ * the full transcript with exactly one copy of the gated tool call.
18
+ */
19
+
20
+ import { describe, it, expect, vi, beforeEach } from "vitest";
21
+ import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifact-storage.js";
22
+ import { create, clone } from "@bufbuild/protobuf";
23
+ import {
24
+ AgentExecutionStatusSchema,
25
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
26
+ import type { AgentExecutionStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
27
+ import {
28
+ AgentMessageSchema,
29
+ ToolCallSchema,
30
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
31
+ import {
32
+ ApprovalAction,
33
+ ExecutionPhase,
34
+ MessageType,
35
+ ToolCallStatus,
36
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
37
+ import type { V3ProtocolEvent } from "../v3-event-recorder.js";
38
+ import type { Config } from "../../../config.js";
39
+ import type { SetupResult } from "../setup.js";
40
+
41
+ // The Temporal activity context is unavailable outside a worker.
42
+ vi.mock("@temporalio/activity", () => ({
43
+ Context: {
44
+ current: () => ({
45
+ cancellationSignal: { aborted: false },
46
+ heartbeat: vi.fn(),
47
+ }),
48
+ },
49
+ CancelledFailure: class CancelledFailure extends Error {},
50
+ }));
51
+
52
+ vi.mock("../../../idle-watchdog.js", () => ({
53
+ activityStarted: vi.fn(),
54
+ activityFinished: vi.fn(),
55
+ }));
56
+
57
+ // Capture every persisted status (the gRPC chokepoint) for assertions.
58
+ const { persistedStatuses } = vi.hoisted(() => ({
59
+ persistedStatuses: [] as AgentExecutionStatus[],
60
+ }));
61
+
62
+ vi.mock("../../../client/stigmer-client.js", () => ({
63
+ StigmerClient: vi.fn().mockImplementation(() => ({
64
+ updateStatus: vi.fn(async (_id: string, status: AgentExecutionStatus) => {
65
+ // Snapshot point-in-time: persistStatus mutates the same object in place.
66
+ persistedStatuses.push(clone(AgentExecutionStatusSchema, status));
67
+ return { signal: 0 };
68
+ }),
69
+ getExecution: vi.fn(),
70
+ })),
71
+ }));
72
+
73
+ // performSetup is mocked per-test to return a fake durable-resume SetupResult.
74
+ vi.mock("../setup.js", () => ({ performSetup: vi.fn() }));
75
+
76
+ import { createDeepAgentActivities } from "../index.js";
77
+ import { performSetup } from "../setup.js";
78
+
79
+ const GATED_TOOL_CALL_ID = "toolu_hitl_01";
80
+ const PRE_RESUME_AI_TEXT = "I'll call the echo tool.";
81
+ const POST_RESUME_AI_TEXT = "The echo tool returned the result.";
82
+
83
+ function v3Event(
84
+ seq: number,
85
+ method: string,
86
+ data: unknown,
87
+ namespace: string[] = [],
88
+ ): V3ProtocolEvent {
89
+ return {
90
+ type: "event",
91
+ seq,
92
+ method,
93
+ params: { namespace, timestamp: Date.now(), data },
94
+ };
95
+ }
96
+
97
+ /** The events a durable resume re-emits: tool execution + assistant turn. */
98
+ function resumeEvents(): V3ProtocolEvent[] {
99
+ return [
100
+ v3Event(0, "tools", {
101
+ event: "tool-started",
102
+ tool_call_id: GATED_TOOL_CALL_ID,
103
+ tool_name: "echo",
104
+ input: { input: "hello-hitl" },
105
+ }, [`tools:${GATED_TOOL_CALL_ID}`]),
106
+ v3Event(1, "tools", {
107
+ event: "tool-finished",
108
+ tool_call_id: GATED_TOOL_CALL_ID,
109
+ output: {
110
+ lc: 1,
111
+ type: "constructor",
112
+ id: ["langchain_core", "messages", "ToolMessage"],
113
+ kwargs: { content: "hello-hitl", tool_call_id: GATED_TOOL_CALL_ID },
114
+ },
115
+ }, [`tools:${GATED_TOOL_CALL_ID}`]),
116
+ v3Event(2, "messages", { event: "message-start", run_id: "r2" }),
117
+ v3Event(3, "messages", {
118
+ event: "content-block-delta",
119
+ index: 0,
120
+ delta: { type: "text-delta", text: POST_RESUME_AI_TEXT },
121
+ run_id: "r2",
122
+ }),
123
+ v3Event(4, "messages", { event: "message-finish", run_id: "r2" }),
124
+ ];
125
+ }
126
+
127
+ function mockV3Run(events: V3ProtocolEvent[]) {
128
+ return {
129
+ [Symbol.asyncIterator]: async function* () {
130
+ for (const e of events) yield e;
131
+ },
132
+ output: Promise.resolve({ messages: [] }),
133
+ abort: vi.fn(),
134
+ signal: new AbortController().signal,
135
+ };
136
+ }
137
+
138
+ /** The run-1 transcript already persisted on the execution. */
139
+ function persistedRunOneStatus(): AgentExecutionStatus {
140
+ return create(AgentExecutionStatusSchema, {
141
+ phase: ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL,
142
+ startedAt: "2026-06-15T00:00:00.000Z",
143
+ messages: [
144
+ create(AgentMessageSchema, {
145
+ type: MessageType.MESSAGE_AI,
146
+ content: PRE_RESUME_AI_TEXT,
147
+ timestamp: "2026-06-15T00:00:01.000Z",
148
+ toolCalls: [
149
+ create(ToolCallSchema, {
150
+ id: GATED_TOOL_CALL_ID,
151
+ name: "echo",
152
+ status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
153
+ requiresApproval: true,
154
+ approvalMessage: "Execute echo tool",
155
+ approvalAction: ApprovalAction.APPROVE,
156
+ mcpServerSlug: "test-mcp",
157
+ }),
158
+ ],
159
+ }),
160
+ ],
161
+ });
162
+ }
163
+
164
+ function fakeDurableResumeSetup(): SetupResult {
165
+ let streamed = false;
166
+
167
+ const pendingInterruptState = {
168
+ values: { messages: [{ role: "assistant", content: PRE_RESUME_AI_TEXT }] },
169
+ tasks: [{
170
+ id: "task-1",
171
+ interrupts: [{
172
+ value: {
173
+ tool_call_id: GATED_TOOL_CALL_ID,
174
+ tool_name: "echo",
175
+ mcp_server_slug: "test-mcp",
176
+ message: "Execute echo tool",
177
+ },
178
+ resumeValue: undefined,
179
+ }],
180
+ }],
181
+ };
182
+ const resolvedState = {
183
+ values: { messages: [{ role: "assistant", content: PRE_RESUME_AI_TEXT }] },
184
+ tasks: [],
185
+ };
186
+
187
+ const agentGraph = {
188
+ // Before the resumed stream: a pending interrupt awaits the decision.
189
+ // After the stream: the interrupt is resolved (no pending approvals).
190
+ getState: vi.fn(async () => (streamed ? resolvedState : pendingInterruptState)),
191
+ streamEvents: vi.fn(async () => {
192
+ streamed = true;
193
+ return mockV3Run(resumeEvents());
194
+ }),
195
+ };
196
+
197
+ const approvalPolicies = new Map([
198
+ ["test-mcp/echo", {
199
+ toolName: "echo",
200
+ mcpServerSlug: "test-mcp",
201
+ requiresApproval: true,
202
+ approvalMessage: "Execute echo tool",
203
+ }],
204
+ ]);
205
+
206
+ return {
207
+ agentGraph,
208
+ langgraphConfig: { configurable: { thread_id: "thread-1" } },
209
+ langgraphInput: { messages: [{ role: "user", content: "Call echo" }] },
210
+ execution: {
211
+ spec: { message: "Call echo with 'hello-hitl'." },
212
+ status: persistedRunOneStatus(),
213
+ },
214
+ agent: {},
215
+ session: { spec: { workspaceEntries: [] } },
216
+ workspaceBackend: { rootDir: "/tmp/ws" },
217
+ mcpConnection: null,
218
+ mergedEnvVars: {},
219
+ secretKeys: new Set<string>(),
220
+ modelName: "claude-sonnet",
221
+ gracefulStop: undefined,
222
+ artifactStorage: makeInMemoryArtifactStorage({ urlBase: "https://artifacts.local/" }).storage,
223
+ provisionResults: [],
224
+ approvalPolicies,
225
+ toolServerMap: new Map([["echo", "test-mcp"]]),
226
+ autoApproveAll: false,
227
+ hasStructuredOutput: false,
228
+ streamVersion: "v3",
229
+ } as unknown as SetupResult;
230
+ }
231
+
232
+ const baseConfig: Config = {
233
+ taskQueue: "test-queue",
234
+ temporalAddress: "localhost:7233",
235
+ temporalNamespace: "default",
236
+ stigmerBackendEndpoint: "http://localhost:7234",
237
+ stigmerToken: null,
238
+ cursorApiKey: "",
239
+ workspaceRootDir: "/tmp/test",
240
+ mode: "cloud",
241
+ proxyEndpoint: "http://localhost:7234",
242
+ maxConcurrentActivities: 5,
243
+ idleTimeoutSeconds: null,
244
+ cloudModeEnabled: true,
245
+ checkpointerType: "http",
246
+ checkpointerProxyEndpoint: "http://localhost:7234",
247
+ primaryModel: "claude-sonnet",
248
+ cursorStreamStallTimeoutMs: 180000,
249
+ };
250
+
251
+ describe("ExecuteDeepAgent — durable-checkpoint resume preserves history", () => {
252
+ beforeEach(() => {
253
+ persistedStatuses.length = 0;
254
+ vi.mocked(performSetup).mockResolvedValue(fakeDurableResumeSetup());
255
+ });
256
+
257
+ it("retains the full transcript and resolves the gated tool call in place", async () => {
258
+ const activities = createDeepAgentActivities(baseConfig);
259
+ await activities.ExecuteDeepAgent("exec-1", "thread-1");
260
+
261
+ expect(persistedStatuses.length).toBeGreaterThan(0);
262
+ const finalStatus = persistedStatuses.at(-1)!;
263
+
264
+ // 1. The pre-resume transcript survives the resume.
265
+ const allText = finalStatus.messages.map(m => m.content).join("\n");
266
+ expect(allText).toContain(PRE_RESUME_AI_TEXT);
267
+
268
+ // 2. The post-resume assistant turn is appended.
269
+ expect(allText).toContain(POST_RESUME_AI_TEXT);
270
+
271
+ // 3. Exactly one copy of the gated tool call — no duplicate on resume.
272
+ const gatedToolCalls = finalStatus.messages
273
+ .flatMap(m => m.toolCalls)
274
+ .filter(tc => tc.id === GATED_TOOL_CALL_ID);
275
+ expect(gatedToolCalls).toHaveLength(1);
276
+
277
+ // 4. The gated tool call is resolved with its result, not stuck waiting.
278
+ expect(gatedToolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_COMPLETED);
279
+ expect(gatedToolCalls[0].result).toContain("hello-hitl");
280
+
281
+ // 5. The execution reaches a terminal COMPLETED phase.
282
+ expect(finalStatus.phase).toBe(ExecutionPhase.EXECUTION_COMPLETED);
283
+ });
284
+ });
@@ -1,4 +1,4 @@
1
- import { describe, it, expect, vi } from "vitest";
1
+ import { describe, it, expect } from "vitest";
2
2
  import { Command } from "@langchain/langgraph";
3
3
  import { resolveResumeInput, reconcileToolCallStatuses } from "../hitl.js";
4
4
  import { ApprovalAction, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
@@ -70,19 +70,12 @@ function makeGraphState(
70
70
  };
71
71
  }
72
72
 
73
- function makeAgentGraph(state: GraphStateSnapshot) {
74
- return {
75
- getState: vi.fn().mockResolvedValue(state),
76
- };
77
- }
78
-
79
73
  describe("resolveResumeInput", () => {
80
- it("returns fresh input when no interrupts exist", async () => {
74
+ it("returns fresh input when no interrupts exist", () => {
81
75
  const execution = makeExecution([]);
82
- const graph = makeAgentGraph({ values: {}, tasks: [] });
83
- const config = { configurable: { thread_id: "t1" } };
76
+ const state: GraphStateSnapshot = { values: {}, tasks: [] };
84
77
 
85
- const result = await resolveResumeInput(execution, graph, config, "hello");
78
+ const result = resolveResumeInput(execution, state, "hello");
86
79
 
87
80
  expect(result.isResumeFromApproval).toBe(false);
88
81
  expect(result.hasRejection).toBe(false);
@@ -91,19 +84,16 @@ describe("resolveResumeInput", () => {
91
84
  });
92
85
  });
93
86
 
94
- it("returns fresh input when interrupts exist but no decisions", async () => {
87
+ it("returns fresh input when interrupts exist but no decisions", () => {
95
88
  const execution = makeExecution([]);
96
89
  const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
97
- const graph = makeAgentGraph(state);
98
90
 
99
- const result = await resolveResumeInput(
100
- execution, graph, { configurable: { thread_id: "t1" } }, "hello",
101
- );
91
+ const result = resolveResumeInput(execution, state, "hello");
102
92
 
103
93
  expect(result.isResumeFromApproval).toBe(false);
104
94
  });
105
95
 
106
- it("builds Command(resume) when interrupts match decisions", async () => {
96
+ it("builds Command(resume) when interrupts match decisions", () => {
107
97
  const execution = makeExecution([{
108
98
  id: "call-1",
109
99
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
@@ -111,18 +101,15 @@ describe("resolveResumeInput", () => {
111
101
  }]);
112
102
 
113
103
  const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
114
- const graph = makeAgentGraph(state);
115
104
 
116
- const result = await resolveResumeInput(
117
- execution, graph, { configurable: { thread_id: "t1" } }, "hello",
118
- );
105
+ const result = resolveResumeInput(execution, state, "hello");
119
106
 
120
107
  expect(result.isResumeFromApproval).toBe(true);
121
108
  expect(result.hasRejection).toBe(false);
122
109
  expect(result.graphInput).toBeInstanceOf(Command);
123
110
  });
124
111
 
125
- it("detects rejection when a decision is REJECT", async () => {
112
+ it("detects rejection when a decision is REJECT", () => {
126
113
  const execution = makeExecution([{
127
114
  id: "call-1",
128
115
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
@@ -130,18 +117,15 @@ describe("resolveResumeInput", () => {
130
117
  }]);
131
118
 
132
119
  const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
133
- const graph = makeAgentGraph(state);
134
120
 
135
- const result = await resolveResumeInput(
136
- execution, graph, { configurable: { thread_id: "t1" } }, "hello",
137
- );
121
+ const result = resolveResumeInput(execution, state, "hello");
138
122
 
139
123
  expect(result.isResumeFromApproval).toBe(true);
140
124
  expect(result.hasRejection).toBe(true);
141
125
  expect(result.rejectionReason).toContain("Rejected by user");
142
126
  });
143
127
 
144
- it("handles multiple interrupts with mixed decisions", async () => {
128
+ it("handles multiple interrupts with mixed decisions", () => {
145
129
  const execution = makeExecution([
146
130
  {
147
131
  id: "call-1",
@@ -159,17 +143,14 @@ describe("resolveResumeInput", () => {
159
143
  { taskId: "task-1", toolCallId: "call-1" },
160
144
  { taskId: "task-2", toolCallId: "call-2" },
161
145
  ]);
162
- const graph = makeAgentGraph(state);
163
146
 
164
- const result = await resolveResumeInput(
165
- execution, graph, { configurable: { thread_id: "t1" } }, "hello",
166
- );
147
+ const result = resolveResumeInput(execution, state, "hello");
167
148
 
168
149
  expect(result.isResumeFromApproval).toBe(true);
169
150
  expect(result.hasRejection).toBe(false);
170
151
  });
171
152
 
172
- it("skips already-resumed interrupts", async () => {
153
+ it("skips already-resumed interrupts", () => {
173
154
  const execution = makeExecution([{
174
155
  id: "call-1",
175
156
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
@@ -179,11 +160,8 @@ describe("resolveResumeInput", () => {
179
160
  const state = makeGraphState([
180
161
  { taskId: "task-1", toolCallId: "call-1", hasResume: true },
181
162
  ]);
182
- const graph = makeAgentGraph(state);
183
163
 
184
- const result = await resolveResumeInput(
185
- execution, graph, { configurable: { thread_id: "t1" } }, "hello",
186
- );
164
+ const result = resolveResumeInput(execution, state, "hello");
187
165
 
188
166
  expect(result.isResumeFromApproval).toBe(false);
189
167
  });
@@ -10,6 +10,7 @@ import { InlinePublisher } from "../inline-publisher.js";
10
10
  import { StatusBuilder } from "../status-builder.js";
11
11
  import { LocalWorkspaceBackend } from "../../../shared/workspace/local-backend.js";
12
12
  import type { ArtifactStorage } from "../../../shared/artifact-storage.js";
13
+ import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifact-storage.js";
13
14
  import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
14
15
 
15
16
  function makeStatusBuilder(): StatusBuilder {
@@ -35,19 +36,16 @@ function mockArtifactStorage(): ArtifactStorage & {
35
36
  uploadedKeys: string[];
36
37
  uploadedContent: Map<string, Buffer>;
37
38
  } {
39
+ // Canonical double; `uploadedKeys`/`uploadedContent` mirror the backing store
40
+ // so the existing assertions keep working and `download` reads back uploads.
41
+ const { storage, blobs } = makeInMemoryArtifactStorage({ urlBase: "http://localhost:7235/" });
38
42
  const uploadedKeys: string[] = [];
39
- const uploadedContent = new Map<string, Buffer>();
40
- return {
41
- uploadedKeys,
42
- uploadedContent,
43
- upload: vi.fn(async (key: string, content: Buffer) => {
44
- uploadedKeys.push(key);
45
- uploadedContent.set(key, content);
46
- return key;
47
- }),
48
- getDownloadUrl: vi.fn(async (key: string) => `http://localhost:7235/${key}`),
49
- exists: vi.fn(async () => false),
50
- };
43
+ storage.upload.mockImplementation(async (key: string, content: Buffer) => {
44
+ uploadedKeys.push(key);
45
+ blobs.set(key, Buffer.from(content));
46
+ return key;
47
+ });
48
+ return Object.assign(storage, { uploadedKeys, uploadedContent: blobs });
51
49
  }
52
50
 
53
51
  function sha256(content: string): string {
@@ -83,7 +81,6 @@ describe("InlinePublisher", () => {
83
81
  expect(artifact.sandboxPath).toBe("src/main.ts");
84
82
  expect(artifact.kind).toBe(ExecutionArtifactKind.FILE);
85
83
  expect(artifact.storageKey).toBe("artifacts/exec-123/main.ts");
86
- expect(artifact.downloadUrl).toBe("http://localhost:7235/artifacts/exec-123/main.ts");
87
84
  expect(artifact.contentHash).toBe(sha256("console.log('hello');"));
88
85
  expect(Number(artifact.sizeBytes)).toBeGreaterThan(0);
89
86
  });
@@ -164,6 +161,27 @@ describe("InlinePublisher", () => {
164
161
  expect(sb.currentStatus.artifacts[0].contentHash).toBe(expected);
165
162
  });
166
163
 
164
+ it("never publishes a secret-like file to artifact storage (design doc 12, D4)", async () => {
165
+ // Under the global bypass a secret write is not blocked up front, so it would
166
+ // otherwise be uploaded here. The publisher must withhold it: no read, no
167
+ // upload, no registered artifact — the secret's bytes never reach storage.
168
+ const secretBackend = mockWorkspaceBackend({ ".env": "API_KEY=super-secret-value" });
169
+ const readSpy = secretBackend.readFile as ReturnType<typeof vi.fn>;
170
+ const pub = new InlinePublisher({
171
+ workspaceBackend: secretBackend,
172
+ artifactStorage: storage,
173
+ statusWriter: sb,
174
+ executionId: "exec-secret",
175
+ });
176
+
177
+ await pub.publish(".env");
178
+
179
+ expect(storage.uploadedKeys).toHaveLength(0);
180
+ expect(sb.currentStatus.artifacts).toHaveLength(0);
181
+ expect(readSpy).not.toHaveBeenCalled(); // withheld before the file is even read
182
+ expect(pub.publishedPaths.size).toBe(0);
183
+ });
184
+
167
185
  it("guesses content type for common extensions", async () => {
168
186
  const jsonBackend = mockWorkspaceBackend({ "data.json": '{"key":"val"}' });
169
187
  const pub = new InlinePublisher({