@stigmer/runner 3.0.9-dev.20260616060535 → 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 (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
@@ -21,6 +21,7 @@ import {
21
21
  import type { StigmerClient } from "../client/stigmer-client.js";
22
22
  import {
23
23
  offloadOversizedToolOutputs,
24
+ offloadCandidateChangesToFit,
24
25
  enforceStatusSizeLimit,
25
26
  STATUS_PAYLOAD_HARD_LIMIT_BYTES,
26
27
  type ToolOutputOffloadContext,
@@ -112,6 +113,18 @@ export async function persistStatus(
112
113
  } catch (err) {
113
114
  console.warn(`[persistStatus] ${executionId}: tool-output offload failed (non-fatal): ${err}`);
114
115
  }
116
+ // File-review ledger: if the status still exceeds the soft cap after per-item
117
+ // offload, offload the largest still-inline captured bodies to retrievable
118
+ // refs so those files stay REVIEWABLE (lazily fetched) instead of being
119
+ // dropped by the backstop below. Guarded on the presence of file-review
120
+ // events so an ordinary (non-review) turn pays nothing. Non-fatal.
121
+ if (status.fileReviewEventStream?.events?.length) {
122
+ try {
123
+ await offloadCandidateChangesToFit(status, offload);
124
+ } catch (err) {
125
+ console.warn(`[persistStatus] ${executionId}: file-review offload-to-fit failed (non-fatal): ${err}`);
126
+ }
127
+ }
115
128
  }
116
129
  if (enforceStatusSizeLimit(status)) {
117
130
  console.warn(
@@ -89,3 +89,36 @@ export function classifyTool(name: string, mcpServerSlug?: string): ToolKind {
89
89
  }
90
90
  return ToolKind.UNSPECIFIED;
91
91
  }
92
+
93
+ /**
94
+ * The coarse, cross-taxonomy approval category of a gated built-in tool, or
95
+ * undefined for tools that are not gated by category (read-only built-ins, MCP
96
+ * tools, and unknown names).
97
+ *
98
+ * FILE_WRITE and FILE_EDIT both collapse to "write" on purpose: the Cursor
99
+ * preToolUse hook reports every file mutation — create or edit — as `Write`,
100
+ * while the SDK stream names them `edit`/`write`. The category is therefore the
101
+ * only tool identity that is stable across the hook and stream taxonomies, which
102
+ * is exactly what the Cursor approval grant (and the Phase-2 coarse approval
103
+ * fingerprint) must match on. Built on {@link classifyTool} so this collapse is
104
+ * defined once.
105
+ *
106
+ * This is the single source of truth for the approval category;
107
+ * execute-cursor/approval-policy.ts re-exports it so the two harnesses cannot
108
+ * drift.
109
+ */
110
+ export type ToolApprovalCategory = "write" | "delete" | "shell";
111
+
112
+ export function toolApprovalCategory(name: string): ToolApprovalCategory | undefined {
113
+ switch (classifyTool(name)) {
114
+ case ToolKind.FILE_WRITE:
115
+ case ToolKind.FILE_EDIT:
116
+ return "write";
117
+ case ToolKind.FILE_DELETE:
118
+ return "delete";
119
+ case ToolKind.SHELL:
120
+ return "shell";
121
+ default:
122
+ return undefined;
123
+ }
124
+ }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Harness-agnostic helpers for a transcript tool-call row's file-review
3
+ * presentation.
4
+ *
5
+ * When file edits are reviewed as a captured `FileChangeSet` (the apply-then-
6
+ * review model), each flowed file-edit row STAYS visible at its transcript
7
+ * position as an observational/audit record — "the agent edited this file,
8
+ * here" — and is stamped with the change set id it contributed to
9
+ * ({@link stampFileEditRow}). The ledger remains the single DECISION surface;
10
+ * the row is never one (the research report's "transcript row references
11
+ * change_set_id" / "tool-call rows are observational/audit-only for file
12
+ * tools"). Both harnesses (Cursor deny-gate + deep-agent middleware) stamp rows
13
+ * the same way, so the operation lives here.
14
+ *
15
+ * {@link hideToolCallRow} / {@link isToolCallRowHidden} remain for the OTHER
16
+ * collapse consumer — a superseded same-turn denial twin — and as the render
17
+ * shape of legacy (pre-stamping) sessions whose flowed edit rows were hidden.
18
+ */
19
+
20
+ import { ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
21
+ import type { ToolCall } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
22
+ import type { SubAgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
23
+ import { extractFilePath } from "./file-tools.js";
24
+ import { isSecretLikePath } from "./filereview/secret-paths.js";
25
+ import { utcTimestamp } from "./status.js";
26
+
27
+ /**
28
+ * Stamp a flowed file-edit row with the change set that captured its turn.
29
+ * PRESENTATION/AUDIT-ONLY (see `ToolCall.file_change_set_id`): clients badge
30
+ * the row with the set's review state and anchor the set's decision surface
31
+ * after the turn's last stamped row. Never a correlation or enforcement key.
32
+ *
33
+ * Additive by design — the row keeps its args/result/status so the per-edit
34
+ * diff the user watched stream stays rendered in place. The captured net diff
35
+ * on the ledger is the only REVIEWED artifact; the row is a historical record.
36
+ *
37
+ * An already-stamped row is left untouched. This is load-bearing, not hygiene:
38
+ * the turn-boundary pass re-walks the whole transcript, which on a resume
39
+ * includes the prior turn's seeded rows — without this guard, turn N would
40
+ * re-stamp turn N-1's rows with its own per-turn change set id (silent
41
+ * mis-attribution).
42
+ *
43
+ * Defensive secret clear (DD-12 D4 belt-and-braces): flowed rows are never
44
+ * secret in practice — the Cursor hook hard-denies secret-like writes before
45
+ * they flow — but a write to a TRACKED secret-like path (e.g. a committed
46
+ * credentials file) is outside the hook's gitignored scope. Such a row keeps
47
+ * its path (a filename is not itself the secret) and is stripped of content
48
+ * (`args` body, `result` diff, `args_preview`). Fail-closed: a file row whose
49
+ * path cannot be determined is stripped rather than trusted.
50
+ */
51
+ export function stampFileEditRow(tc: ToolCall, changeSetId: string): void {
52
+ if (tc.fileChangeSetId) return;
53
+ tc.fileChangeSetId = changeSetId;
54
+
55
+ const path = extractFilePath((tc.args ?? {}) as Record<string, unknown>) ?? "";
56
+ if (isSecretLikePath(path)) {
57
+ tc.args = path ? { path } : undefined;
58
+ tc.result = "";
59
+ tc.argsPreview = "";
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Collapse a tool-call row to the hidden shape the SDK renders as absent: a
65
+ * SKIPPED row with no approval state, result, error, preview, or args.
66
+ * Idempotent (re-running yields the same shape).
67
+ *
68
+ * `args` is cleared, not just `args_preview`. A hidden row is redundant with the
69
+ * `file_change_set` (the single review surface), so its content must not linger
70
+ * anywhere: for a file-mutating tool `args` holds the full write body, which for
71
+ * a secret-like path would otherwise persist into the transcript / Temporal
72
+ * history in violation of the never-persist-secret-contents contract (design
73
+ * doc 12, D4). Dropping it is safe at resume — identity is carried by
74
+ * `approval_content_digest`, deliberately immune to `args` being absent (the
75
+ * size-limit elision already drops `args`); no consumer reads a hidden row's
76
+ * `args`.
77
+ */
78
+ export function hideToolCallRow(tc: ToolCall): void {
79
+ tc.status = ToolCallStatus.TOOL_CALL_SKIPPED;
80
+ tc.requiresApproval = false;
81
+ tc.approvalRequestedAt = "";
82
+ tc.approvalMessage = "";
83
+ tc.error = "";
84
+ tc.result = "";
85
+ tc.argsPreview = "";
86
+ tc.args = undefined;
87
+ if (!tc.completedAt) tc.completedAt = utcTimestamp();
88
+ }
89
+
90
+ /**
91
+ * Whether a tool-call row is already collapsed/hidden (the SDK's absent-row
92
+ * predicate). Used to keep {@link hideToolCallRow} idempotent across re-persists
93
+ * and activity retries.
94
+ */
95
+ export function isToolCallRowHidden(tc: ToolCall): boolean {
96
+ return (
97
+ tc.status === ToolCallStatus.TOOL_CALL_SKIPPED &&
98
+ !tc.requiresApproval &&
99
+ tc.args === undefined &&
100
+ !tc.result &&
101
+ !tc.error
102
+ );
103
+ }
104
+
105
+ /**
106
+ * Collect every tool-call id present in a set of sub-agent executions.
107
+ *
108
+ * Used by both harnesses to snapshot, BEFORE a turn's stream, the sub-agent
109
+ * tool-call ids that already existed — so the turn-boundary stamp can scope
110
+ * itself to rows CREATED this turn (a tool-call id absent from the snapshot).
111
+ *
112
+ * Why tool-call-id novelty is the current-turn signal for sub-agent rows (and
113
+ * not the `{unstamped}` heuristic the top-level pass uses): a top-level flowed
114
+ * edit row is guaranteed to be from this turn because prior turns' rows are
115
+ * either already stamped or hidden. Sub-agent rows have neither shield — before
116
+ * sub-agent stamping existed, ALL of them are unstamped and never hidden — so a
117
+ * naive `{unstamped}` walk would mis-attribute a resumed execution's prior
118
+ * sub-agent rows to the current change set. Keying on tool-call-id novelty is
119
+ * also correct for a sub-agent that spans invocations (an internal tool gate):
120
+ * its id pre-exists on resume, but its continuation edit rows carry fresh ids
121
+ * and stamp with the completing turn's set. It is likewise independent of how
122
+ * each harness seeds prior sub-agents (deep-agent replaces per-turn and holds
123
+ * none; Cursor clones them in) — the snapshot reflects whatever is present.
124
+ */
125
+ export function collectSubAgentToolCallIds(
126
+ subAgents: readonly SubAgentExecution[],
127
+ ): Set<string> {
128
+ const ids = new Set<string>();
129
+ for (const sa of subAgents) {
130
+ for (const msg of sa.messages) {
131
+ for (const tc of msg.toolCalls) ids.add(tc.id);
132
+ }
133
+ }
134
+ return ids;
135
+ }
@@ -18,11 +18,50 @@
18
18
  import { join } from "node:path";
19
19
  import { mkdir } from "node:fs/promises";
20
20
  import { homedir } from "node:os";
21
+ import { createHash } from "node:crypto";
22
+
23
+ /** The runner-owned `~/.stigmer` root (overridable via HOME for tests/sandboxes). */
24
+ function getStigmerHome(): string {
25
+ return process.env.HOME || process.env.USERPROFILE || homedir();
26
+ }
21
27
 
22
28
  /** Root of a session's runner-owned directory tree (outside the workspace). */
23
29
  function getSessionDir(sessionId: string): string {
24
- const home = process.env.HOME || process.env.USERPROFILE || homedir();
25
- return join(home, ".stigmer", "sessions", sessionId);
30
+ return join(getStigmerHome(), ".stigmer", "sessions", sessionId);
31
+ }
32
+
33
+ /**
34
+ * Compute the WORKSPACE-scoped HITL gate directory — the home for the STABLE
35
+ * hook script and the per-turn "active turn" pointer.
36
+ *
37
+ * Why workspace-scoped, not session-scoped: the Cursor SDK loads the workspace's
38
+ * `.cursor/hooks.json` (the hook script PATH) ONCE per runner process and caches
39
+ * it; later per-execution rewrites are ignored. A per-session hook script (with
40
+ * per-session baked state/ledger paths) therefore gets cached at the FIRST
41
+ * execution and reused for every later one — so later executions' denials are
42
+ * recorded to the FIRST session's ledger and the current runner reads its own
43
+ * empty ledger, silently completing instead of pausing for approval.
44
+ *
45
+ * The fix is a single STABLE script per workspace (so the SDK's cached path is
46
+ * always correct) that resolves the CURRENT turn's state/ledger/runner from an
47
+ * atomically-updated pointer the script re-reads on every invocation. This dir
48
+ * holds both. It is keyed by a hash of the absolute workspace path so distinct
49
+ * workspaces never collide, and lives under `~/.stigmer` (never the repo, per
50
+ * issue #173). Pure function — performs no I/O.
51
+ */
52
+ export function getHitlGateDir(workspaceRoot: string): string {
53
+ const key = createHash("sha256").update(workspaceRoot).digest("hex").slice(0, 16);
54
+ return join(getStigmerHome(), ".stigmer", "hitl-gate", key);
55
+ }
56
+
57
+ /**
58
+ * Ensure the workspace-scoped HITL gate directory exists and return its path.
59
+ * Idempotent — safe across executions, HITL reinvocations, and activity retries.
60
+ */
61
+ export async function ensureHitlGateDir(workspaceRoot: string): Promise<string> {
62
+ const dir = getHitlGateDir(workspaceRoot);
63
+ await mkdir(dir, { recursive: true });
64
+ return dir;
26
65
  }
27
66
 
28
67
  /**
@@ -385,7 +385,7 @@ describe("Golden Execution — Tier 1d: Advanced Tasks", () => {
385
385
  const state = createState();
386
386
  state.input = { pr_number: 7, repo: "acme/app", diff: "--- a/main.ts" };
387
387
 
388
- const mockCallAgent = vi.fn(async () => ({
388
+ const mockCallAgent = vi.fn<TaskExecutionContext["callAgent"]>(async () => ({
389
389
  structured: { severity: "low", category: "style", customer_impact: false },
390
390
  final_text: "LGTM",
391
391
  agent_execution_id: "aex-verify",
@@ -434,7 +434,7 @@ describe("Golden Execution — Tier 1d: Advanced Tasks", () => {
434
434
  const model = loadWorkflowFromYaml(crossOrgYaml);
435
435
  const state = createState();
436
436
 
437
- const mockCallAgent = vi.fn(async () => ({
437
+ const mockCallAgent = vi.fn<TaskExecutionContext["callAgent"]>(async () => ({
438
438
  final_text: "done",
439
439
  }));
440
440
  const ctx = makeCtx({ callAgent: mockCallAgent });
@@ -678,9 +678,11 @@ describe("Golden Execution — Structured Output Pipeline", () => {
678
678
  await executeDoTasks(model.do, null, state, model, evaluateExpressionBatch, ctx);
679
679
 
680
680
  expect(mockCallAgent).toHaveBeenCalledOnce();
681
- expect(state.context.analyze.dau).toBe(7175);
682
- expect(state.context.analyze.executive_summary).toBe("DAU stable at 7175");
683
- expect(state.context.analyze.cohorts).toHaveLength(2);
681
+ // `$context` is dynamic (typed `unknown` in production); narrow to the shape this golden produces.
682
+ const context = state.context as { analyze: { dau: number; executive_summary: string; cohorts: unknown[] } };
683
+ expect(context.analyze.dau).toBe(7175);
684
+ expect(context.analyze.executive_summary).toBe("DAU stable at 7175");
685
+ expect(context.analyze.cohorts).toHaveLength(2);
684
686
  expect(state.data.report_dau).toBe(7175);
685
687
  expect(state.data.cohort_count).toBe(2);
686
688
  expect(state.data.first_cohort).toBe("D1 New Players");
@@ -838,8 +840,10 @@ describe("Golden Execution — Structured Output Pipeline", () => {
838
840
 
839
841
  await executeDoTasks(model.do, null, state, model, evaluateExpressionBatch, ctx);
840
842
 
841
- expect(state.context.analyze.dau).toBe(7175);
842
- expect(state.context.analyze.executive_summary).toBe("DAU stable at 7175");
843
+ // `$context` is dynamic (typed `unknown` in production); narrow to the shape this golden produces.
844
+ const context = state.context as { analyze: { dau: number; executive_summary: string } };
845
+ expect(context.analyze.dau).toBe(7175);
846
+ expect(context.analyze.executive_summary).toBe("DAU stable at 7175");
843
847
  expect(state.data.report_dau).toBe(7175);
844
848
  expect(state.data.summary).toBe("DAU stable at 7175");
845
849
  });
@@ -979,9 +983,11 @@ describe("Golden Execution — Structured Output Pipeline", () => {
979
983
 
980
984
  await executeDoTasks(model.do, null, state, model, evaluateExpressionBatch, ctx);
981
985
 
982
- expect(state.context.analyze.dau).toBe(7175);
983
- expect(state.context.analyze.cohorts).toHaveLength(2);
984
- expect(state.context.analyze.anomalies).toHaveLength(1);
986
+ // `$context` is dynamic (typed `unknown` in production); narrow to the shape this golden produces.
987
+ const context = state.context as { analyze: { dau: number; cohorts: unknown[]; anomalies: unknown[] } };
988
+ expect(context.analyze.dau).toBe(7175);
989
+ expect(context.analyze.cohorts).toHaveLength(2);
990
+ expect(context.analyze.anomalies).toHaveLength(1);
985
991
  expect(state.data.summary).toBe("Garden Design Makeover DAU remains stable at 7,175");
986
992
  expect(state.data.anomaly_count).toBe(1);
987
993
  });
@@ -991,7 +997,7 @@ describe("Golden Execution — Structured Output Pipeline", () => {
991
997
  const state = createState();
992
998
  state.env = { NOTIFICATION_DATE: "2026-05-26" };
993
999
 
994
- const mockCallAgent = vi.fn(async () => ({
1000
+ const mockCallAgent = vi.fn<TaskExecutionContext["callAgent"]>(async () => ({
995
1001
  structured: {
996
1002
  executive_summary: "Garden Design Makeover DAU stable at 7,185",
997
1003
  dau: 7185,
@@ -1019,13 +1025,22 @@ describe("Golden Execution — Structured Output Pipeline", () => {
1019
1025
  expect(mockCallAgent).toHaveBeenCalledOnce();
1020
1026
  const [config, env, metadata] = mockCallAgent.mock.calls[0];
1021
1027
 
1022
- // Schema must survive expression resolution
1023
- expect(config.output).toBeDefined();
1028
+ // Schema must survive expression resolution. `output.schema` is an arbitrary
1029
+ // JSON schema (typed `Record<string, unknown>` in production); narrow to the
1030
+ // concrete shape this golden asserts against.
1031
+ if (!config.output) throw new Error("expected an output contract on the agent call");
1032
+ const schema = config.output.schema as {
1033
+ required: string[];
1034
+ properties: {
1035
+ cohorts: { items: { required: string[] } };
1036
+ anomalies: { items: { properties: { severity: { enum: string[] } } } };
1037
+ };
1038
+ };
1024
1039
  expect(config.output.schema).toBeDefined();
1025
- expect(config.output.schema.required).toEqual(["executive_summary", "cohorts", "anomalies"]);
1026
- expect(config.output.schema.properties.cohorts.items.required)
1040
+ expect(schema.required).toEqual(["executive_summary", "cohorts", "anomalies"]);
1041
+ expect(schema.properties.cohorts.items.required)
1027
1042
  .toEqual(["name", "size", "action_needed"]);
1028
- expect(config.output.schema.properties.anomalies.items.properties.severity.enum)
1043
+ expect(schema.properties.anomalies.items.properties.severity.enum)
1029
1044
  .toEqual(["warning", "critical"]);
1030
1045
  expect(config.output.on_invalid).toBe("ON_INVALID_FAIL");
1031
1046
 
@@ -1040,8 +1055,10 @@ describe("Golden Execution — Structured Output Pipeline", () => {
1040
1055
  expect(metadata.taskName).toBe("analyze_player_data");
1041
1056
 
1042
1057
  // Structured output exported to context and consumed downstream
1043
- expect(state.context.analyze_player_data.dau).toBe(7185);
1044
- expect(state.context.analyze_player_data.executive_summary).toContain("7,185");
1058
+ // `$context` is dynamic (typed `unknown` in production); narrow to the shape this golden produces.
1059
+ const context = state.context as { analyze_player_data: { dau: number; executive_summary: string } };
1060
+ expect(context.analyze_player_data.dau).toBe(7185);
1061
+ expect(context.analyze_player_data.executive_summary).toContain("7,185");
1045
1062
  expect(state.data.final_dau).toBe(7185);
1046
1063
  expect(state.data.anomaly_count).toBe(1);
1047
1064
  });
@@ -554,7 +554,7 @@ describe("executeTryTask — retryContext propagation", () => {
554
554
 
555
555
  let capturedRetryContext: unknown = undefined;
556
556
  const spyEmitEvents = vi.fn(async function (this: TaskExecutionContext, events: WorkflowEventDescriptor[]) {
557
- capturedRetryContext = (this as Record<string, unknown>)?.retryContext;
557
+ capturedRetryContext = this.retryContext;
558
558
  });
559
559
 
560
560
  let callCount = 0;