@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
@@ -22,10 +22,17 @@ import type { ArtifactStorage } from "../../shared/artifact-storage.js";
22
22
  import type { WorkspaceBackend } from "../../shared/workspace/types.js";
23
23
  import type { ExecutionStatusWriter } from "./execution-status-writer.js";
24
24
  import { utcTimestamp } from "../../shared/status.js";
25
+ import { isSecretLikePath } from "../../shared/filereview/secret-paths.js";
25
26
 
26
27
  export class InlinePublisher {
27
28
  private readonly workspaceBackend: WorkspaceBackend;
28
- private readonly artifactStorage: ArtifactStorage;
29
+ /**
30
+ * `undefined` when the runner has no artifact store (proxy misconfig). Inline
31
+ * publishing is a best-effort real-time UI nicety, so {@link publish} becomes a
32
+ * no-op — the operator was already warned once at setup, and the transcript still
33
+ * persists without the offloaded artifact.
34
+ */
35
+ private readonly artifactStorage: ArtifactStorage | undefined;
29
36
  private readonly statusWriter: ExecutionStatusWriter;
30
37
  private readonly executionId: string;
31
38
 
@@ -34,7 +41,7 @@ export class InlinePublisher {
34
41
 
35
42
  constructor(opts: {
36
43
  workspaceBackend: WorkspaceBackend;
37
- artifactStorage: ArtifactStorage;
44
+ artifactStorage: ArtifactStorage | undefined;
38
45
  statusWriter: ExecutionStatusWriter;
39
46
  executionId: string;
40
47
  }) {
@@ -54,9 +61,27 @@ export class InlinePublisher {
54
61
  * status builder. Fire-and-forget: errors are logged and swallowed.
55
62
  */
56
63
  async publish(path: string): Promise<void> {
64
+ // No artifact store (proxy misconfig): nothing to upload to. Skip silently —
65
+ // this is a best-effort UI publisher and the operator was warned at setup.
66
+ if (!this.artifactStorage) return;
57
67
  try {
58
68
  const sandboxPath = normalizePath(path);
59
69
 
70
+ // Never publish a secret-like file to durable artifact storage (design
71
+ // doc 12, D4). This is the third secret-withholding choke point beside the
72
+ // CAS capture gate and the transcript args scrub: under the global bypass
73
+ // (spec.auto_approve_all) a secret write is not blocked up front, so it
74
+ // would otherwise be uploaded here (keyed by basename) and registered as an
75
+ // ExecutionArtifact. Fail-closed and unconditional — the same name-based
76
+ // gate the capture path uses, so the decision has one source of truth.
77
+ if (isSecretLikePath(sandboxPath)) {
78
+ console.log(
79
+ `[InlinePublisher] execution=${this.executionId} — withheld '${sandboxPath}' ` +
80
+ `(secret-like; never published to artifact storage)`,
81
+ );
82
+ return;
83
+ }
84
+
60
85
  const content = await this.workspaceBackend.readFile(sandboxPath);
61
86
  const contentBuffer = Buffer.from(content, "utf-8");
62
87
  const contentHash = sha256(contentBuffer);
@@ -69,7 +94,6 @@ export class InlinePublisher {
69
94
  const storageKey = `artifacts/${this.executionId}/${fileName}`;
70
95
 
71
96
  await this.artifactStorage.upload(storageKey, contentBuffer, guessContentType(fileName));
72
- const downloadUrl = await this.artifactStorage.getDownloadUrl(storageKey);
73
97
 
74
98
  const artifact = create(ExecutionArtifactSchema, {
75
99
  name: fileName,
@@ -77,7 +101,6 @@ export class InlinePublisher {
77
101
  kind: ExecutionArtifactKind.FILE,
78
102
  sizeBytes: BigInt(contentBuffer.length),
79
103
  storageKey,
80
- downloadUrl,
81
104
  createdAt: utcTimestamp(),
82
105
  contentHash,
83
106
  });
@@ -8,11 +8,8 @@
8
8
  * the streaming phase needs.
9
9
  */
10
10
 
11
- import { createDeepAgent, FilesystemBackend, type FilesystemPermission } from "deepagents";
11
+ import { createDeepAgent, type FilesystemPermission } from "deepagents";
12
12
  import { InteractionMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
13
- import { ChatAnthropic } from "@langchain/anthropic";
14
- import { ChatOpenAI } from "@langchain/openai";
15
- import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
16
13
  import type { BaseCheckpointSaver } from "@langchain/langgraph-checkpoint";
17
14
  import { z } from "zod";
18
15
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -32,6 +29,11 @@ import { backfillMcpServersIfNeeded } from "../../shared/connect-backfill.js";
32
29
  import { WorkspaceProvisioner } from "../../shared/workspace/provisioner.js";
33
30
  import { LocalWorkspaceBackend } from "../../shared/workspace/local-backend.js";
34
31
  import type { WorkspaceBackend, ProvisionResult } from "../../shared/workspace/types.js";
32
+ import { CasCaptureFilesystemBackend } from "./cas-capture-backend.js";
33
+ import { CasCaptureObserver } from "./cas-capture-observer.js";
34
+ import { isGitWorkTree, isPathCapturable } from "../../shared/filereview/git-substrate.js";
35
+ import { deriveCaptureMode } from "../../shared/filereview/capture.js";
36
+ import { resolveWorkspacePath } from "../../shared/file-change.js";
35
37
  import { ensurePlatformDir } from "../../shared/workspace/platform-dir.js";
36
38
  import { buildWorkspaceFileTree } from "../../shared/workspace/file-tree.js";
37
39
  import { reportSetupProgress } from "../../shared/status.js";
@@ -39,8 +41,12 @@ import { resolveEnvironment, type EnvironmentResult } from "./environment.js";
39
41
  import { buildEnhancedSystemPrompt } from "./prompt-builder.js";
40
42
  import { buildMiddlewareStack, createThinkTool } from "../../middleware/index.js";
41
43
  import type { GracefulStopMiddleware } from "../../middleware/index.js";
44
+ import type { ApprovalGateConfig } from "../../middleware/approval-gate.js";
45
+ import { deriveExecutionFingerprintKey } from "../../shared/approval-fingerprint.js";
46
+ import { getRunnerHitlMasterSecret } from "../../shared/fingerprint-secret.js";
42
47
  import { getModelPricing, ensureLoaded as ensurePricingLoaded } from "../../shared/model-pricing.js";
43
48
  import { getDefaultModel } from "../../shared/model-registry.js";
49
+ import { buildChatModel } from "../../shared/model-client.js";
44
50
  import {
45
51
  loadArtifactStorageConfig,
46
52
  createArtifactStorage,
@@ -48,15 +54,10 @@ import {
48
54
  } from "../../shared/artifact-storage.js";
49
55
  import {
50
56
  mergeApprovalPolicies,
51
- hasApproveAllDecision,
57
+ deriveActiveLeases,
52
58
  type MergedToolPolicy,
53
59
  } from "../../shared/approval-policy.js";
54
- import {
55
- inferProvider,
56
- stripProviderPrefix,
57
- resolveProxyBaseUrl,
58
- buildProxyHeaders,
59
- } from "../../shared/llm-proxy.js";
60
+ import type { ToolApprovalCategory } from "../../shared/tool-kind.js";
60
61
  import {
61
62
  mergeSkillRefs,
62
63
  fetchSkillsByRefs,
@@ -84,13 +85,62 @@ export interface SetupResult {
84
85
  readonly secretKeys: ReadonlySet<string>;
85
86
  readonly modelName: string;
86
87
  readonly gracefulStop: GracefulStopMiddleware;
87
- readonly artifactStorage: ArtifactStorage;
88
+ /**
89
+ * Artifact storage for CAS blobs, tool-output offload, and attachment/plan
90
+ * artifacts. `undefined` only when it cannot be built (proxy transport with a
91
+ * missing token/endpoint — a misconfiguration; local storage never fails). Every
92
+ * consumer must tolerate its absence: capture degrades to the deny-gate (see
93
+ * `captureMode`), offload is disabled (the aggregate size guard still applies),
94
+ * and attachment/plan publishing surface a clear error rather than crashing.
95
+ */
96
+ readonly artifactStorage: ArtifactStorage | undefined;
88
97
  readonly provisionResults: readonly ProvisionResult[];
89
98
  readonly approvalPolicies: ReadonlyMap<string, MergedToolPolicy>;
90
99
  readonly toolServerMap: ReadonlyMap<string, string>;
91
- readonly autoApproveAll: boolean;
100
+ /**
101
+ * Built-in approval categories with a run-lifetime scoped lease (from an
102
+ * interactive APPROVE_ALL). Threaded to the StatusBuilder so a leased built-in
103
+ * call is attributed to its lease (approval_lease) rather than the plain
104
+ * category gate. Empty under a global pre-arm or when no lease is active.
105
+ */
106
+ readonly leasedCategories: ReadonlySet<ToolApprovalCategory>;
107
+ /**
108
+ * Pre-armed spec.auto_approve_all — the one unscoped, whole-run bypass. When
109
+ * true the approval gate is not installed at all. Interactive "approve all"
110
+ * decisions are NOT folded in here; they become scoped leases applied inside
111
+ * the gate (see ActiveLeases / deriveActiveLeases).
112
+ */
113
+ readonly globalBypass: boolean;
92
114
  readonly hasStructuredOutput: boolean;
93
115
  readonly streamVersion: "v2" | "v3";
116
+ /**
117
+ * The single owner of this turn's CAS-capture state (design docs 08/11/12):
118
+ * the pre-turn bytes of first-touched gitignored paths (recorded
119
+ * gate-independently by the CAS-observing backends of the parent AND every
120
+ * sub-agent) plus the gitignored paths the gate hard-blocked as secret-like
121
+ * (DD-E). The turn boundary reads both to compose the CAS change set. Empty in
122
+ * the legacy (non-capture) path, where no CAS-observing backend is installed.
123
+ */
124
+ readonly casObserver: CasCaptureObserver;
125
+ /**
126
+ * Apply-then-review capture mode, decided by {@link deriveCaptureMode} (shared
127
+ * with the Cursor harness so both degrade identically): file edits flow during
128
+ * the turn and are reviewed post-hoc as a captured `FileChangeSet` (the activity
129
+ * authors the baseline/candidate ledger events and reconciles on resume). True
130
+ * whenever there is a capture substrate — a git work tree (needs no storage) OR
131
+ * artifact storage for the non-git CAS path. False for a non-git workspace with
132
+ * no artifact storage (proxy misconfig): capture has no substrate, so file writes
133
+ * fall back to the deny-gate (gated pre-execution) exactly like Cursor's DD-22
134
+ * fallback. When true, the deny-gate covers only shell/MCP/irreversible tools.
135
+ */
136
+ readonly captureMode: boolean;
137
+ /**
138
+ * True when the workspace is a git work tree. Selects the capture SUBSTRATE for
139
+ * this turn: git-diff (pinned baseline/after trees) when true; content-addressed
140
+ * CAS manifest (path-scoped to touched paths) when false. Threaded into the
141
+ * baseline/candidate/reconcile seam (`capture.ts`) and the CAS capture-class.
142
+ */
143
+ readonly gitWorkspace: boolean;
94
144
  }
95
145
 
96
146
  export interface SetupDependencies {
@@ -151,9 +201,20 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
151
201
  await reportSetupProgress(client, executionId, "Resolving environment…");
152
202
  const envResult: EnvironmentResult = await resolveEnvironment(client, executionId);
153
203
 
154
- // Step 6: Create artifact storage
155
- const artifactStorageConfig = loadArtifactStorageConfig(config);
156
- const artifactStorage = createArtifactStorage(artifactStorageConfig);
204
+ // Step 6: Create artifact storage. Best-effort, mirroring the Cursor harness:
205
+ // `createArtifactStorage` throws only for proxy transport with a missing
206
+ // token/endpoint (a misconfiguration; local storage never throws). We degrade
207
+ // rather than crash — an absent store flips capture mode off (deny-gate
208
+ // fallback below) and disables offload, instead of failing the whole execution.
209
+ let artifactStorage: ArtifactStorage | undefined;
210
+ try {
211
+ artifactStorage = createArtifactStorage(loadArtifactStorageConfig(config));
212
+ } catch (storageErr) {
213
+ console.warn(
214
+ `[setup] artifact storage unavailable — capture degrades to the deny-gate ` +
215
+ `and tool-output offload is disabled: execution=${executionId}, error=${storageErr}`,
216
+ );
217
+ }
157
218
 
158
219
  // Step 7: Provision workspace
159
220
  await reportSetupProgress(client, executionId, "Initializing workspace…");
@@ -164,6 +225,61 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
164
225
  sessionId,
165
226
  );
166
227
 
228
+ // Apply-then-review is the file-review model whenever there is a capture
229
+ // SUBSTRATE (DD-21 D2, Slice 2b): file edits flow during the turn and are
230
+ // reviewed post-hoc as a captured `FileChangeSet` (reconciled byte-exactly on
231
+ // resume), never gated before they run. The substrate is selected by
232
+ // `gitWorkspace`:
233
+ // - a git work tree diffs a pinned baseline -> candidate tree (git-substrate,
234
+ // needs no artifact storage), and routes its .gitignored edits into the
235
+ // path-scoped CAS observer;
236
+ // - a non-git workspace has no git snapshot at all, so EVERY touched path is
237
+ // captured into the content-addressed CAS manifest (cas-substrate), which
238
+ // needs artifact storage to persist blobs.
239
+ // So a non-git workspace with NO artifact storage has no substrate: capture
240
+ // degrades to the deny-gate (file writes gated pre-execution), exactly like the
241
+ // Cursor harness (DD-22). `deriveCaptureMode` is the shared decision so both
242
+ // harnesses degrade identically. When capture is on, the deny-gate survives only
243
+ // for shell/MCP/irreversible tools.
244
+ const gitWorkspace = await isGitWorkTree(workspaceBackend.rootDir);
245
+ const captureMode = deriveCaptureMode(
246
+ workspaceBackend.rootDir,
247
+ gitWorkspace,
248
+ !!artifactStorage,
249
+ );
250
+
251
+ // Git-tracked capturability, consulted by the gate to route a file write to
252
+ // disk-and-git-diff (tracked) vs into CAS (ignored). Only meaningful in a git
253
+ // work tree. In a non-git workspace nothing is "git-capturable" (there is no
254
+ // snapshot), so this resolves false for every path and the gate routes all
255
+ // file writes through its captureIgnored (CAS) arm.
256
+ const isCapturablePath = gitWorkspace
257
+ ? (rawPath: string): Promise<boolean> =>
258
+ isPathCapturable(
259
+ workspaceBackend.rootDir,
260
+ resolveWorkspacePath(rawPath, workspaceBackend.rootDir, true).path,
261
+ )
262
+ : (_rawPath: string): Promise<boolean> => Promise.resolve(false);
263
+
264
+ // CAS capture (design docs 08/11/12): the content-addressed half of
265
+ // apply-then-review. The single per-turn observer owns the before-bytes of
266
+ // first-touched CAS-owned paths AND the secret-blocked paths, keyed
267
+ // workspace-root-relative so they align with the CAS reconcile's
268
+ // `join(workspaceRoot, path)`. It is shared by the parent AND every sub-agent
269
+ // CAS backend, giving race-free first-touch-wins across concurrent graphs.
270
+ // Its ownership predicate is memoized, so `git check-ignore` runs at most once
271
+ // per distinct path.
272
+ const casObserver = new CasCaptureObserver({
273
+ rootDir: workspaceBackend.rootDir,
274
+ // Which touched paths the observer owns (records pre-turn bytes for). In a
275
+ // git work tree that is the .gitignored set only — git captures the tracked
276
+ // ones. In a non-git workspace there is no git substrate, so the observer
277
+ // owns EVERY touched path; the CAS manifest is the sole capture surface.
278
+ isIgnored: gitWorkspace
279
+ ? async (relPath) => !(await isPathCapturable(workspaceBackend.rootDir, relPath))
280
+ : async () => true,
281
+ });
282
+
167
283
  // Step 7: Resolve and connect MCP servers
168
284
  const mcpServerUsages = [
169
285
  ...(agent.spec!.mcpServerUsages || []),
@@ -258,8 +374,18 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
258
374
  injectedFiles,
259
375
  });
260
376
 
261
- // Step 9: Construct the LLM model
262
- const model = constructModel(modelName, config, executionId);
377
+ // Step 9: Construct the LLM model. Resolution to the provider API id
378
+ // happens inside buildChatModel; modelName stays the registry id for
379
+ // pricing, the native-thinking heuristic, and sub-agent inheritance.
380
+ const requestTimeoutMs =
381
+ parseInt(process.env.STIGMER_LLM_REQUEST_TIMEOUT_MS ?? "0") || undefined;
382
+ const { model } = await buildChatModel({
383
+ modelName,
384
+ proxyEndpoint: config.proxyEndpoint ?? undefined,
385
+ stigmerToken: config.stigmerToken ?? undefined,
386
+ headerScope: { executionId },
387
+ timeoutMs: requestTimeoutMs,
388
+ });
263
389
 
264
390
  // Step 10: Build middleware stack
265
391
  await ensurePricingLoaded();
@@ -275,25 +401,64 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
275
401
  }
276
402
  }
277
403
 
278
- // Step 10b: Resolve approval policies
404
+ // Step 10b: Resolve approval policies + leases.
279
405
  //
280
- // Effective auto-approve is true when EITHER the execution was pre-armed via
281
- // spec.auto_approve_all (CLI --auto-approve, API, CI/CD) OR a user chose
282
- // APPROVE_ALL ("approve and don't ask again") at some gate earlier in this
283
- // run. In both cases the gate is disabled for the rest of the execution, and
284
- // the value propagates to mergeApprovalPolicies and (below) to sub-agents so
285
- // they inherit it. See the ApprovalAction doc in enum.proto.
286
- const autoApproveAll =
287
- (execution.spec!.autoApproveAll ?? false) || hasApproveAllDecision(execution);
406
+ // Two distinct bypasses (see ActiveLeases): the pre-armed
407
+ // spec.auto_approve_all is the one whole-run global bypass; an interactive
408
+ // APPROVE_ALL grants a run-lifetime lease scoped to that action's class (its
409
+ // built-in category, or its MCP server). Server leases shape the policy map
410
+ // (leased servers dropped); built-in category leases are applied inside the
411
+ // gate. Both flow into sub-agents via the shared config below.
412
+ const leases = deriveActiveLeases(execution);
413
+ const globalBypass = leases.global;
288
414
  const agentOverrides = agent.spec!.mcpServerUsages?.flatMap(
289
415
  u => u.toolApprovalOverrides ?? [],
290
416
  ) ?? [];
291
417
  const approvalPolicies = mergeApprovalPolicies(
292
418
  resolvedMcpServers?.resolvedServers ?? [],
293
419
  agentOverrides,
294
- autoApproveAll,
420
+ leases,
295
421
  );
296
422
 
423
+ // The approval gate config is the single source of truth for HITL gating,
424
+ // built once and inherited verbatim by sub-agents (so a mutating tool inside
425
+ // a sub-agent is gated identically to one in the parent). Null under the
426
+ // global pre-arm, where the gate is inert; under scoped leases the gate stays
427
+ // active and clears only leased categories. The per-execution fingerprint key
428
+ // (runner master secret + execution_id) drives the shadow ExecutionReceipt.
429
+ const approvalGateConfig: ApprovalGateConfig | null = !globalBypass
430
+ ? {
431
+ policies: approvalPolicies,
432
+ leasedCategories: leases.categories,
433
+ toolServerMap,
434
+ fingerprintKey: deriveExecutionFingerprintKey(
435
+ getRunnerHitlMasterSecret(),
436
+ executionId,
437
+ ),
438
+ executionId,
439
+ // Capture mode: file edits flow and are reviewed post-hoc. In a git work
440
+ // tree, git-tracked edits flow to the git diff and .gitignored edits flow
441
+ // into CAS (captureIgnored) on THIS parent gate; in a non-git workspace
442
+ // isCapturablePath is always false, so ALL file writes take the CAS arm.
443
+ // Secret-like paths are hard-blocked (DD-E) and recorded for a
444
+ // DIFF_UNREVIEWABLE entry. shell/MCP stay gated. Sub-agents inherit this
445
+ // config; buildSubAgentMiddleware sets their captureIgnored explicitly
446
+ // from whether a CAS observer backs the sub-agent (Session 26, DD-19),
447
+ // so their captured edits flow into the SAME observer.
448
+ //
449
+ // When captureMode is false (no substrate — non-git + no storage),
450
+ // fileCaptureMode is false so file writes take the plain deny-gate. The
451
+ // CAS arm additionally requires storage: captureIgnored gates gitignored
452
+ // writes onto CAS only when a store exists to persist their blobs (the
453
+ // git+no-storage case), matching the Cursor harness's
454
+ // `captureMode && !!artifactStorage`.
455
+ fileCaptureMode: captureMode,
456
+ isCapturablePath,
457
+ captureIgnored: captureMode && !!artifactStorage,
458
+ recordBlockedSecret: (rawPath: string) => casObserver.recordBlockedSecret(rawPath),
459
+ }
460
+ : null;
461
+
297
462
  const maxCostUsd = execConfig?.maxCostUsd ?? 0;
298
463
  const { middleware, gracefulStop, costCap: costCapMiddleware } = buildMiddlewareStack({
299
464
  loopDetection: {
@@ -318,11 +483,7 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
318
483
  warningPct: 80,
319
484
  } : null,
320
485
  otelSpans: { toolServerMap },
321
- approvalGate: !autoApproveAll ? {
322
- policies: approvalPolicies,
323
- autoApproveAll,
324
- toolServerMap,
325
- } : null,
486
+ approvalGate: approvalGateConfig,
326
487
  });
327
488
 
328
489
  // Step 11: Build tools list (MCP tools + think tool)
@@ -352,12 +513,22 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
352
513
  parentMcpUsages: mcpServerUsages,
353
514
  skillClient: client,
354
515
  workspaceBackend,
355
- approvalPolicies,
356
- autoApproveAll,
516
+ approvalGate: approvalGateConfig,
517
+ // Capture is universal (Slice 2b), so every sub-agent gets a CAS-observing
518
+ // backend wired to the SAME per-turn observer as the parent — their
519
+ // captured writes (.gitignored in a git tree, all touched paths in a
520
+ // non-git one) compose into the parent's change set (Session 26, DD-19).
521
+ casObserver,
357
522
  parentModelName: modelName,
358
523
  parentHasNativeThinking: _modelHasNativeThinking(modelName),
359
524
  costCap: costCapMiddleware ?? undefined,
360
- modelFactory: (m: string) => constructModel(m, config, executionId),
525
+ modelFactory: async (m: string) =>
526
+ (await buildChatModel({
527
+ modelName: m,
528
+ proxyEndpoint: config.proxyEndpoint ?? undefined,
529
+ stigmerToken: config.stigmerToken ?? undefined,
530
+ headerScope: { executionId },
531
+ })).model,
361
532
  });
362
533
  }
363
534
 
@@ -381,10 +552,20 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
381
552
  { operations: ["write"], paths: ["/**"], mode: "deny" },
382
553
  ];
383
554
 
555
+ // File capture point. Apply-then-review is universal (Slice 2b), so the
556
+ // CAS-observing backend: git-tracked edits flow to disk (the turn-boundary
557
+ // git diff is authoritative), and the shared CAS observer records the pre-turn
558
+ // bytes of every CAS-owned path — .gitignored paths in a git work tree, all
559
+ // touched paths in a non-git one — so the boundary can capture them into CAS.
560
+ // It is gate-independent, so it holds even under the global bypass.
561
+ const fileBackend = new CasCaptureFilesystemBackend(
562
+ { rootDir: workspaceBackend.rootDir },
563
+ { observer: casObserver },
564
+ );
384
565
  const agentGraph = await createDeepAgent({
385
566
  model,
386
567
  checkpointer: checkpointer as any,
387
- backend: new FilesystemBackend({ rootDir: workspaceBackend.rootDir }),
568
+ backend: fileBackend,
388
569
  systemPrompt,
389
570
  tools,
390
571
  middleware: middleware as any,
@@ -432,9 +613,13 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
432
613
  provisionResults,
433
614
  approvalPolicies,
434
615
  toolServerMap,
435
- autoApproveAll,
616
+ leasedCategories: leases.categories,
617
+ globalBypass,
436
618
  hasStructuredOutput: !!outputSchema,
437
619
  streamVersion,
620
+ casObserver,
621
+ captureMode,
622
+ gitWorkspace,
438
623
  };
439
624
  } catch (err) {
440
625
  if (mcpConnection) {
@@ -444,93 +629,6 @@ export async function performSetup(deps: SetupDependencies): Promise<SetupResult
444
629
  }
445
630
  }
446
631
 
447
- /**
448
- * Construct the appropriate chat model for the given model name.
449
- *
450
- * Provider inference uses name prefix heuristics (claude → Anthropic,
451
- * gpt/o1/o3/o4 → OpenAI). In proxy mode, requests route through the
452
- * stigmer-cloud LlmProxyController at provider-specific paths.
453
- */
454
- function constructModel(
455
- modelName: string,
456
- config: Config,
457
- executionId?: string,
458
- ): BaseChatModel {
459
- const provider = inferProvider(modelName);
460
- const apiModelId = stripProviderPrefix(modelName);
461
-
462
- const baseUrl = config.proxyEndpoint
463
- ? resolveProxyBaseUrl(config.proxyEndpoint, provider)
464
- : undefined;
465
-
466
- const headers = config.proxyEndpoint && config.stigmerToken
467
- ? buildProxyHeaders(config.stigmerToken, { executionId })
468
- : undefined;
469
-
470
- switch (provider) {
471
- case "anthropic":
472
- return buildAnthropicModel(apiModelId, baseUrl, headers, config);
473
- case "openai":
474
- return buildOpenAIModel(apiModelId, baseUrl, headers, config);
475
- }
476
- }
477
-
478
- function buildAnthropicModel(
479
- model: string,
480
- baseUrl: string | undefined,
481
- headers: Record<string, string> | undefined,
482
- config: Config,
483
- ): BaseChatModel {
484
- const apiKey = config.proxyEndpoint
485
- ? (config.stigmerToken ?? "proxy-managed")
486
- : (process.env.ANTHROPIC_API_KEY ?? "");
487
-
488
- const requestTimeoutMs = parseInt(process.env.STIGMER_LLM_REQUEST_TIMEOUT_MS ?? "0") || undefined;
489
-
490
- return new ChatAnthropic({
491
- model,
492
- apiKey,
493
- temperature: 0,
494
- ...(requestTimeoutMs ? { maxRetries: 0, timeout: requestTimeoutMs } : {}),
495
- ...(baseUrl || headers
496
- ? {
497
- clientOptions: {
498
- ...(baseUrl ? { baseURL: baseUrl } : {}),
499
- ...(headers ? { defaultHeaders: headers } : {}),
500
- },
501
- }
502
- : {}),
503
- });
504
- }
505
-
506
- function buildOpenAIModel(
507
- model: string,
508
- baseUrl: string | undefined,
509
- headers: Record<string, string> | undefined,
510
- config: Config,
511
- ): BaseChatModel {
512
- const apiKey = config.proxyEndpoint
513
- ? (config.stigmerToken ?? "proxy-managed")
514
- : (process.env.OPENAI_API_KEY ?? "");
515
-
516
- const requestTimeoutMs = parseInt(process.env.STIGMER_LLM_REQUEST_TIMEOUT_MS ?? "0") || undefined;
517
-
518
- return new ChatOpenAI({
519
- model,
520
- apiKey,
521
- temperature: 0,
522
- ...(requestTimeoutMs ? { maxRetries: 0, timeout: requestTimeoutMs } : {}),
523
- ...(baseUrl || headers
524
- ? {
525
- configuration: {
526
- ...(baseUrl ? { baseURL: baseUrl } : {}),
527
- ...(headers ? { defaultHeaders: headers } : {}),
528
- },
529
- }
530
- : {}),
531
- });
532
- }
533
-
534
632
  /**
535
633
  * Provision workspace from session workspace entries.
536
634
  */
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Deep-agent turn-boundary stamping of flowed file-edit rows — the deep-agent
3
+ * analog of the Cursor adapter's `stampFlowedFileEditRows` (in `capture-flow.ts`),
4
+ * minus deny-token coordination (this harness has no deny gate; every
5
+ * write/delete flowed). Extracted from the activity entry point so it is
6
+ * directly unit-testable, mirroring how `approval-file-change.ts` isolates the
7
+ * capture helpers.
8
+ *
9
+ * Rows stay visible in place as observational records; `file_change_sets`
10
+ * remains the single decision surface (DD-24).
11
+ */
12
+
13
+ import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
14
+ import type { SubAgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
15
+ import { toolApprovalCategory } from "../../shared/tool-kind.js";
16
+ import { isToolCallRowHidden, stampFileEditRow } from "../../shared/tool-row.js";
17
+
18
+ /**
19
+ * Stamp every flowed file-edit row (category write/delete) with this turn's
20
+ * change set id. Skips already-stamped rows (a resume seeds prior turns' rows
21
+ * into this transcript — re-stamping would mis-attribute them) and legacy hidden
22
+ * rows from pre-stamping sessions (they belong to an earlier turn's set).
23
+ *
24
+ * `skipToolCallIds` scopes the pass to rows CREATED this turn: a tool-call id
25
+ * present before this turn's stream is skipped. Top-level callers omit it (a
26
+ * top-level flowed row is this-turn's by the already-stamped/hidden shields);
27
+ * sub-agent callers pass a pre-turn snapshot, since sub-agent rows have neither
28
+ * shield (see `collectSubAgentToolCallIds` in `shared/tool-row.ts`).
29
+ */
30
+ export function stampFlowedFileEditRows(
31
+ messages: readonly AgentMessage[],
32
+ changeSetId: string,
33
+ skipToolCallIds?: ReadonlySet<string>,
34
+ ): void {
35
+ for (const msg of messages) {
36
+ for (const tc of msg.toolCalls) {
37
+ if (tc.fileChangeSetId) continue;
38
+ if (skipToolCallIds?.has(tc.id)) continue;
39
+ if (isToolCallRowHidden(tc)) continue;
40
+ const category = toolApprovalCategory(tc.name);
41
+ if (category !== "write" && category !== "delete") continue;
42
+ stampFileEditRow(tc, changeSetId);
43
+ }
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Stamp the current turn's sub-agent flowed file-edit rows with the parent
49
+ * turn's change set id. Sub-agent writes fold their files into the SAME parent
50
+ * turn set (shared git diff + one shared CasCaptureObserver, DD-19), so they
51
+ * carry the parent change set id and badge against the same set the parent's
52
+ * rows do. They live under `subAgentExecutions` (not the top-level transcript),
53
+ * so they are walked separately and scoped to this turn via `priorToolCallIds`
54
+ * (the sub-agent tool-call ids that existed before this turn's stream).
55
+ */
56
+ export function stampFlowedSubAgentFileEditRows(
57
+ subAgents: readonly SubAgentExecution[],
58
+ changeSetId: string,
59
+ priorToolCallIds: ReadonlySet<string>,
60
+ ): void {
61
+ for (const sa of subAgents) {
62
+ stampFlowedFileEditRows(sa.messages, changeSetId, priorToolCallIds);
63
+ }
64
+ }