@stigmer/runner 3.15.0 → 3.15.2-dev.20260913223433

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 (518) hide show
  1. package/README.md +2 -4
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__test-utils__/execution-record-fixture.d.ts +14 -0
  4. package/dist/__test-utils__/execution-record-fixture.js +4 -0
  5. package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
  6. package/dist/__test-utils__/file-review-projection.d.ts +40 -0
  7. package/dist/__test-utils__/file-review-projection.js +136 -0
  8. package/dist/__test-utils__/file-review-projection.js.map +1 -0
  9. package/dist/__test-utils__/harness-contract/types.d.ts +23 -1
  10. package/dist/__test-utils__/harness-contract/types.js +15 -0
  11. package/dist/__test-utils__/harness-contract/types.js.map +1 -1
  12. package/dist/__test-utils__/hermetic-activity.d.ts +44 -12
  13. package/dist/__test-utils__/hermetic-activity.js +52 -14
  14. package/dist/__test-utils__/hermetic-activity.js.map +1 -1
  15. package/dist/__test-utils__/model-registry-fixture.d.ts +32 -7
  16. package/dist/__test-utils__/model-registry-fixture.js +31 -7
  17. package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
  18. package/dist/__test-utils__/turn-input-fixture.d.ts +1 -1
  19. package/dist/__test-utils__/turn-input-fixture.js +1 -1
  20. package/dist/__test-utils__/turn-input-fixture.js.map +1 -1
  21. package/dist/activities/call-agent.js +2 -2
  22. package/dist/activities/call-agent.js.map +1 -1
  23. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +45 -3
  24. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
  25. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +0 -9
  26. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +2 -41
  27. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  28. package/dist/activities/execute-cursor/adapter.d.ts +7 -5
  29. package/dist/activities/execute-cursor/adapter.js +7 -5
  30. package/dist/activities/execute-cursor/adapter.js.map +1 -1
  31. package/dist/activities/execute-cursor/approval-policy.d.ts +5 -2
  32. package/dist/activities/execute-cursor/approval-policy.js +5 -2
  33. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  34. package/dist/activities/execute-cursor/approval-state.d.ts +16 -8
  35. package/dist/activities/execute-cursor/approval-state.js +6 -3
  36. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  37. package/dist/activities/execute-cursor/cas-observations.d.ts +14 -2
  38. package/dist/activities/execute-cursor/cas-observations.js +19 -2
  39. package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
  40. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +8 -4
  41. package/dist/activities/execute-cursor/cursor-capabilities.js +21 -4
  42. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -1
  43. package/dist/activities/execute-cursor/message-translator.d.ts +12 -20
  44. package/dist/activities/execute-cursor/message-translator.js +19 -32
  45. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  46. package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -58
  47. package/dist/activities/execute-cursor/prompt-builder.js +76 -95
  48. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  49. package/dist/activities/execute-cursor/turn-boundary.d.ts +27 -55
  50. package/dist/activities/execute-cursor/turn-boundary.js +30 -90
  51. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
  52. package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
  53. package/dist/activities/execute-cursor/turn-settle.js +37 -49
  54. package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
  55. package/dist/activities/execute-cursor/turn-setup.d.ts +16 -24
  56. package/dist/activities/execute-cursor/turn-setup.js +29 -59
  57. package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
  58. package/dist/activities/execute-cursor/turn-stream.d.ts +3 -8
  59. package/dist/activities/execute-cursor/turn-stream.js +9 -22
  60. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  61. package/dist/activities/execute-cursor/turn.js +5 -1
  62. package/dist/activities/execute-cursor/turn.js.map +1 -1
  63. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +93 -0
  64. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +348 -0
  65. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
  66. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +170 -0
  67. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +225 -0
  68. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
  69. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
  70. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
  71. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
  72. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +54 -0
  73. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +72 -0
  74. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
  75. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +187 -23
  76. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +238 -27
  77. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
  78. package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
  79. package/dist/activities/execute-deep-agent/adapter.js +78 -0
  80. package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
  81. package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +8 -0
  82. package/dist/activities/execute-deep-agent/cas-capture-observer.js +9 -0
  83. package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -1
  84. package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +31 -0
  85. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +40 -0
  86. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
  87. package/dist/activities/execute-deep-agent/execution-state.d.ts +4 -11
  88. package/dist/activities/execute-deep-agent/execution-state.js +4 -12
  89. package/dist/activities/execute-deep-agent/execution-state.js.map +1 -1
  90. package/dist/activities/execute-deep-agent/hitl.d.ts +49 -47
  91. package/dist/activities/execute-deep-agent/hitl.js +77 -103
  92. package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
  93. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +51 -23
  94. package/dist/activities/execute-deep-agent/prompt-builder.js +115 -76
  95. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  96. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +18 -32
  97. package/dist/activities/execute-deep-agent/status-builder-shared.js +10 -65
  98. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
  99. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +10 -8
  100. package/dist/activities/execute-deep-agent/streaming-side-effects.js +12 -14
  101. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  102. package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +36 -13
  103. package/dist/activities/execute-deep-agent/subagent-tracker.js +76 -39
  104. package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
  105. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -28
  106. package/dist/activities/execute-deep-agent/subagent-transformer.js +29 -82
  107. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  108. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -2
  109. package/dist/activities/execute-deep-agent/subagent-wiring.js +2 -2
  110. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  111. package/dist/activities/execute-deep-agent/turn-settle.d.ts +42 -0
  112. package/dist/activities/execute-deep-agent/turn-settle.js +146 -0
  113. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
  114. package/dist/activities/execute-deep-agent/turn-setup.d.ts +212 -0
  115. package/dist/activities/execute-deep-agent/turn-setup.js +430 -0
  116. package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
  117. package/dist/activities/execute-deep-agent/turn-stream.d.ts +97 -0
  118. package/dist/activities/execute-deep-agent/turn-stream.js +242 -0
  119. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
  120. package/dist/activities/execute-deep-agent/turn.d.ts +42 -0
  121. package/dist/activities/execute-deep-agent/turn.js +116 -0
  122. package/dist/activities/execute-deep-agent/turn.js.map +1 -0
  123. package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +6 -5
  124. package/dist/activities/execute-deep-agent/v3-event-recorder.js +6 -5
  125. package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -1
  126. package/dist/activities/execute-deep-agent/v3-events.d.ts +1 -1
  127. package/dist/activities/execute-deep-agent/v3-events.js +1 -1
  128. package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +60 -17
  129. package/dist/activities/execute-deep-agent/v3-status-builder.js +72 -57
  130. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
  131. package/dist/harness/approval-decisions.d.ts +61 -0
  132. package/dist/harness/approval-decisions.js +102 -0
  133. package/dist/harness/approval-decisions.js.map +1 -0
  134. package/dist/harness/capabilities.d.ts +16 -5
  135. package/dist/harness/capabilities.js +9 -0
  136. package/dist/harness/capabilities.js.map +1 -1
  137. package/dist/harness/capture.d.ts +144 -0
  138. package/dist/harness/capture.js +219 -0
  139. package/dist/harness/capture.js.map +1 -0
  140. package/dist/harness/persist-chokepoint.d.ts +19 -4
  141. package/dist/harness/persist-chokepoint.js +17 -4
  142. package/dist/harness/persist-chokepoint.js.map +1 -1
  143. package/dist/harness/run-turn.js +115 -29
  144. package/dist/harness/run-turn.js.map +1 -1
  145. package/dist/harness/terminal-table.d.ts +40 -11
  146. package/dist/harness/terminal-table.js +58 -19
  147. package/dist/harness/terminal-table.js.map +1 -1
  148. package/dist/harness/turn-context.d.ts +141 -76
  149. package/dist/harness/turn-context.js +194 -99
  150. package/dist/harness/turn-context.js.map +1 -1
  151. package/dist/harness/types.d.ts +65 -12
  152. package/dist/harness/types.js +8 -2
  153. package/dist/harness/types.js.map +1 -1
  154. package/dist/harness-adapters.d.ts +12 -8
  155. package/dist/harness-adapters.js +17 -9
  156. package/dist/harness-adapters.js.map +1 -1
  157. package/dist/middleware/approval-gate.d.ts +1 -1
  158. package/dist/middleware/approval-gate.js +1 -1
  159. package/dist/middleware/approval-gate.js.map +1 -1
  160. package/dist/middleware/cost-advisory.d.ts +39 -0
  161. package/dist/middleware/{cost-cap.js → cost-advisory.js} +37 -55
  162. package/dist/middleware/cost-advisory.js.map +1 -0
  163. package/dist/middleware/index.d.ts +23 -12
  164. package/dist/middleware/index.js +26 -18
  165. package/dist/middleware/index.js.map +1 -1
  166. package/dist/middleware/types.d.ts +3 -2
  167. package/dist/runner-manager.js +1 -5
  168. package/dist/runner-manager.js.map +1 -1
  169. package/dist/runner.js +1 -5
  170. package/dist/runner.js.map +1 -1
  171. package/dist/shared/attachment-resolver.d.ts +41 -18
  172. package/dist/shared/attachment-resolver.js +178 -46
  173. package/dist/shared/attachment-resolver.js.map +1 -1
  174. package/dist/shared/attachment-zip.d.ts +85 -0
  175. package/dist/shared/attachment-zip.js +185 -0
  176. package/dist/shared/attachment-zip.js.map +1 -0
  177. package/dist/shared/connect-backfill.js +5 -4
  178. package/dist/shared/connect-backfill.js.map +1 -1
  179. package/dist/shared/cost-guard.d.ts +3 -3
  180. package/dist/shared/cost-guard.js +3 -3
  181. package/dist/shared/execution-status-writer.d.ts +5 -5
  182. package/dist/shared/execution-status-writer.js +5 -5
  183. package/dist/shared/extract-structured-output.d.ts +8 -7
  184. package/dist/shared/extract-structured-output.js +8 -7
  185. package/dist/shared/extract-structured-output.js.map +1 -1
  186. package/dist/shared/filereview/cas-progress.d.ts +1 -18
  187. package/dist/shared/filereview/cas-progress.js +4 -0
  188. package/dist/shared/filereview/cas-progress.js.map +1 -1
  189. package/dist/shared/filereview/cas-touched.d.ts +56 -0
  190. package/dist/shared/filereview/cas-touched.js +63 -0
  191. package/dist/shared/filereview/cas-touched.js.map +1 -0
  192. package/dist/shared/filereview/index.d.ts +2 -1
  193. package/dist/shared/filereview/index.js +2 -1
  194. package/dist/shared/filereview/index.js.map +1 -1
  195. package/dist/shared/mcp-resolver.d.ts +4 -5
  196. package/dist/shared/mcp-resolver.js +4 -5
  197. package/dist/shared/mcp-resolver.js.map +1 -1
  198. package/dist/shared/persist-decision.d.ts +3 -4
  199. package/dist/shared/persist-decision.js +3 -4
  200. package/dist/shared/persist-decision.js.map +1 -1
  201. package/dist/shared/plan-mode-permissions.d.ts +2 -2
  202. package/dist/shared/plan-mode-permissions.js +2 -2
  203. package/dist/shared/plan-mode-prompt.d.ts +1 -1
  204. package/dist/shared/plan-mode-prompt.js +1 -1
  205. package/dist/shared/prompt-sections.d.ts +163 -0
  206. package/dist/shared/prompt-sections.js +164 -0
  207. package/dist/shared/prompt-sections.js.map +1 -0
  208. package/dist/shared/skill-resolver.d.ts +4 -2
  209. package/dist/shared/skill-resolver.js +4 -2
  210. package/dist/shared/skill-resolver.js.map +1 -1
  211. package/dist/shared/tool-rounds.d.ts +32 -0
  212. package/dist/shared/tool-rounds.js +43 -0
  213. package/dist/shared/tool-rounds.js.map +1 -1
  214. package/dist/shared/tool-row.d.ts +34 -0
  215. package/dist/shared/tool-row.js +52 -0
  216. package/dist/shared/tool-row.js.map +1 -1
  217. package/dist/shared/workspace/session-provision.d.ts +3 -3
  218. package/dist/shared/workspace/session-provision.js +3 -3
  219. package/dist/shared/workspace/stigmer-link.d.ts +3 -3
  220. package/dist/shared/workspace/stigmer-link.js +3 -3
  221. package/dist/shared/workspace/writeback-coordinator.d.ts +15 -22
  222. package/dist/shared/workspace/writeback-coordinator.js +16 -53
  223. package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
  224. package/dist/tools/index.d.ts +1 -1
  225. package/dist/tools/index.js +1 -1
  226. package/package.json +4 -4
  227. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +1 -0
  228. package/src/__test-utils__/execution-record-fixture.ts +18 -2
  229. package/src/__test-utils__/file-review-projection.ts +156 -0
  230. package/src/__test-utils__/git-workspace-fixture.ts +58 -0
  231. package/src/__test-utils__/harness-boot-order-child.ts +7 -2
  232. package/src/__test-utils__/harness-contract/contract.ts +33 -20
  233. package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
  234. package/src/__test-utils__/harness-contract/runtime-contract.ts +328 -10
  235. package/src/__test-utils__/harness-contract/scripted-adapter.ts +38 -6
  236. package/src/__test-utils__/harness-contract/types.ts +27 -3
  237. package/src/__test-utils__/hermetic-activity.ts +52 -14
  238. package/src/__test-utils__/model-registry-fixture.ts +32 -7
  239. package/src/__test-utils__/module-specifiers.ts +24 -0
  240. package/src/__test-utils__/turn-input-fixture.ts +2 -2
  241. package/src/__tests__/harness-boot-order.test.ts +9 -2
  242. package/src/activities/call-agent.ts +2 -2
  243. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +47 -3
  244. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +2 -48
  245. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +1 -1
  246. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +6 -1
  247. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +52 -27
  248. package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +25 -0
  249. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +166 -0
  250. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +186 -0
  251. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +191 -0
  252. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
  253. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
  254. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
  255. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -2
  256. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +4 -0
  257. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +24 -4
  258. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +6 -5
  259. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +9 -0
  260. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +11 -8
  261. package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +229 -0
  262. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +3 -3
  263. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +2 -2
  264. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +78 -234
  265. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +1 -26
  266. package/src/activities/execute-cursor/adapter.ts +7 -5
  267. package/src/activities/execute-cursor/approval-policy.ts +5 -2
  268. package/src/activities/execute-cursor/approval-state.ts +16 -8
  269. package/src/activities/execute-cursor/cas-observations.ts +20 -2
  270. package/src/activities/execute-cursor/cursor-capabilities.ts +24 -5
  271. package/src/activities/execute-cursor/message-translator.ts +29 -41
  272. package/src/activities/execute-cursor/prompt-builder.ts +99 -157
  273. package/src/activities/execute-cursor/turn-boundary.ts +34 -140
  274. package/src/activities/execute-cursor/turn-settle.ts +37 -51
  275. package/src/activities/execute-cursor/turn-setup.ts +30 -70
  276. package/src/activities/execute-cursor/turn-stream.ts +8 -31
  277. package/src/activities/execute-cursor/turn.ts +5 -1
  278. package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +391 -0
  279. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +313 -0
  280. package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
  281. package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +85 -0
  282. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +383 -36
  283. package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
  284. package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
  285. package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +80 -0
  286. package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +1 -1
  287. package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -2
  288. package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -3
  289. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +172 -0
  290. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +167 -0
  291. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +36 -0
  292. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +178 -0
  293. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +158 -0
  294. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +210 -0
  295. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +74 -0
  296. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +104 -0
  297. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +78 -0
  298. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +138 -0
  299. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +68 -0
  300. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +154 -0
  301. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +116 -0
  302. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +69 -0
  303. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +67 -0
  304. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +47 -0
  305. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +68 -0
  306. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +280 -0
  307. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +77 -0
  308. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
  309. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +99 -0
  310. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +109 -0
  311. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +76 -0
  312. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +51 -0
  313. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +51 -0
  314. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +56 -0
  315. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +90 -0
  316. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +70 -0
  317. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +71 -0
  318. package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
  319. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +184 -0
  320. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +203 -0
  321. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +170 -0
  322. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +175 -0
  323. package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +206 -0
  324. package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +142 -0
  325. package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +126 -0
  326. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +139 -0
  327. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +122 -0
  328. package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +236 -0
  329. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +161 -0
  330. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +157 -0
  331. package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +152 -0
  332. package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +50 -122
  333. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +8 -6
  334. package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +2 -2
  335. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +35 -35
  336. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +247 -0
  337. package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +329 -0
  338. package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +1 -20
  339. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +78 -0
  340. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +1 -1
  341. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +2 -2
  342. package/src/activities/execute-deep-agent/__tests__/subagent-tracker.test.ts +57 -31
  343. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +19 -79
  344. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +15 -15
  345. package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +1 -1
  346. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +391 -0
  347. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +343 -38
  348. package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +5 -5
  349. package/src/activities/execute-deep-agent/adapter.ts +94 -0
  350. package/src/activities/execute-deep-agent/cas-capture-observer.ts +11 -0
  351. package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +43 -0
  352. package/src/activities/execute-deep-agent/execution-state.ts +4 -13
  353. package/src/activities/execute-deep-agent/hitl.ts +100 -123
  354. package/src/activities/execute-deep-agent/prompt-builder.ts +141 -115
  355. package/src/activities/execute-deep-agent/status-builder-shared.ts +21 -84
  356. package/src/activities/execute-deep-agent/streaming-side-effects.ts +13 -19
  357. package/src/activities/execute-deep-agent/subagent-tracker.ts +77 -42
  358. package/src/activities/execute-deep-agent/subagent-transformer.ts +46 -105
  359. package/src/activities/execute-deep-agent/subagent-wiring.ts +5 -4
  360. package/src/activities/execute-deep-agent/turn-settle.ts +164 -0
  361. package/src/activities/execute-deep-agent/turn-setup.ts +541 -0
  362. package/src/activities/execute-deep-agent/turn-stream.ts +313 -0
  363. package/src/activities/execute-deep-agent/turn.ts +131 -0
  364. package/src/activities/execute-deep-agent/v3-event-recorder.ts +6 -5
  365. package/src/activities/execute-deep-agent/v3-events.ts +1 -1
  366. package/src/activities/execute-deep-agent/v3-status-builder.ts +84 -63
  367. package/src/harness/__tests__/approval-decisions.test.ts +116 -0
  368. package/src/harness/__tests__/capture.test.ts +268 -0
  369. package/src/harness/__tests__/mount-skills.test.ts +169 -0
  370. package/src/harness/__tests__/persist-chokepoint.test.ts +38 -2
  371. package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
  372. package/src/harness/__tests__/run-turn.test.ts +39 -23
  373. package/src/harness/__tests__/turn-attachments-vision.test.ts +80 -0
  374. package/src/harness/__tests__/turn-context.test.ts +73 -26
  375. package/src/harness/approval-decisions.ts +104 -0
  376. package/src/harness/capabilities.ts +16 -5
  377. package/src/harness/capture.ts +301 -0
  378. package/src/harness/persist-chokepoint.ts +24 -4
  379. package/src/harness/run-turn.ts +120 -29
  380. package/src/harness/terminal-table.ts +61 -20
  381. package/src/harness/turn-context.ts +208 -111
  382. package/src/harness/types.ts +66 -12
  383. package/src/harness-adapters.ts +17 -9
  384. package/src/middleware/__tests__/approval-gate.test.ts +1 -1
  385. package/src/middleware/__tests__/cost-advisory.test.ts +113 -0
  386. package/src/middleware/approval-gate.ts +2 -2
  387. package/src/middleware/{cost-cap.ts → cost-advisory.ts} +40 -70
  388. package/src/middleware/index.ts +29 -29
  389. package/src/middleware/types.ts +3 -2
  390. package/src/runner-manager.ts +0 -8
  391. package/src/runner.ts +0 -8
  392. package/src/shared/__tests__/attachment-naming.test.ts +6 -19
  393. package/src/shared/__tests__/attachment-resolver.test.ts +158 -8
  394. package/src/shared/__tests__/attachment-zip.test.ts +236 -0
  395. package/src/shared/__tests__/bedrock-adapter.test.ts +1 -1
  396. package/src/shared/__tests__/blueprint-resolver.test.ts +43 -0
  397. package/src/shared/__tests__/cost-guard.test.ts +3 -3
  398. package/src/shared/__tests__/prompt-sections.test.ts +167 -0
  399. package/src/shared/__tests__/secret-leak-scan.test.ts +2 -2
  400. package/src/{activities/execute-deep-agent → shared}/__tests__/stamp-flowed-rows.test.ts +33 -10
  401. package/src/shared/__tests__/vertex-adapter.test.ts +1 -1
  402. package/src/shared/attachment-resolver.ts +218 -55
  403. package/src/shared/attachment-zip.ts +281 -0
  404. package/src/shared/connect-backfill.ts +9 -11
  405. package/src/shared/cost-guard.ts +3 -3
  406. package/src/shared/execution-status-writer.ts +5 -5
  407. package/src/shared/extract-structured-output.ts +8 -7
  408. package/src/shared/filereview/__tests__/capture.test.ts +86 -4
  409. package/src/shared/filereview/__tests__/cas-progress.test.ts +2 -1
  410. package/src/shared/filereview/cas-progress.ts +5 -19
  411. package/src/shared/filereview/cas-touched.ts +89 -0
  412. package/src/shared/filereview/index.ts +4 -2
  413. package/src/shared/mcp-resolver.ts +4 -5
  414. package/src/shared/persist-decision.ts +3 -4
  415. package/src/shared/plan-mode-permissions.ts +2 -2
  416. package/src/shared/plan-mode-prompt.ts +1 -1
  417. package/src/shared/prompt-sections.ts +256 -0
  418. package/src/shared/skill-resolver.ts +4 -2
  419. package/src/shared/tool-rounds.ts +48 -0
  420. package/src/shared/tool-row.ts +61 -0
  421. package/src/shared/workspace/__tests__/stigmer-link.test.ts +7 -22
  422. package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +20 -61
  423. package/src/shared/workspace/session-provision.ts +3 -3
  424. package/src/shared/workspace/stigmer-link.ts +3 -3
  425. package/src/shared/workspace/writeback-coordinator.ts +16 -64
  426. package/src/tools/index.ts +1 -1
  427. package/dist/activities/execute-cursor/capture-flow.d.ts +0 -142
  428. package/dist/activities/execute-cursor/capture-flow.js +0 -285
  429. package/dist/activities/execute-cursor/capture-flow.js.map +0 -1
  430. package/dist/activities/execute-cursor/command-provenance.d.ts +0 -48
  431. package/dist/activities/execute-cursor/command-provenance.js +0 -38
  432. package/dist/activities/execute-cursor/command-provenance.js.map +0 -1
  433. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +0 -134
  434. package/dist/activities/execute-deep-agent/attachment-injector.js +0 -386
  435. package/dist/activities/execute-deep-agent/attachment-injector.js.map +0 -1
  436. package/dist/activities/execute-deep-agent/command-provenance.d.ts +0 -61
  437. package/dist/activities/execute-deep-agent/command-provenance.js +0 -72
  438. package/dist/activities/execute-deep-agent/command-provenance.js.map +0 -1
  439. package/dist/activities/execute-deep-agent/environment.d.ts +0 -24
  440. package/dist/activities/execute-deep-agent/environment.js +0 -58
  441. package/dist/activities/execute-deep-agent/environment.js.map +0 -1
  442. package/dist/activities/execute-deep-agent/event-recorder.d.ts +0 -21
  443. package/dist/activities/execute-deep-agent/event-recorder.js +0 -67
  444. package/dist/activities/execute-deep-agent/event-recorder.js.map +0 -1
  445. package/dist/activities/execute-deep-agent/index.d.ts +0 -15
  446. package/dist/activities/execute-deep-agent/index.js +0 -918
  447. package/dist/activities/execute-deep-agent/index.js.map +0 -1
  448. package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -28
  449. package/dist/activities/execute-deep-agent/mcp-gate.js +0 -22
  450. package/dist/activities/execute-deep-agent/mcp-gate.js.map +0 -1
  451. package/dist/activities/execute-deep-agent/post-stream.d.ts +0 -23
  452. package/dist/activities/execute-deep-agent/post-stream.js +0 -71
  453. package/dist/activities/execute-deep-agent/post-stream.js.map +0 -1
  454. package/dist/activities/execute-deep-agent/setup.d.ts +0 -136
  455. package/dist/activities/execute-deep-agent/setup.js +0 -767
  456. package/dist/activities/execute-deep-agent/setup.js.map +0 -1
  457. package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +0 -36
  458. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +0 -56
  459. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +0 -1
  460. package/dist/activities/execute-deep-agent/status-builder.d.ts +0 -93
  461. package/dist/activities/execute-deep-agent/status-builder.js +0 -365
  462. package/dist/activities/execute-deep-agent/status-builder.js.map +0 -1
  463. package/dist/activities/execute-deep-agent/streaming-terminal.d.ts +0 -21
  464. package/dist/activities/execute-deep-agent/streaming-terminal.js +0 -80
  465. package/dist/activities/execute-deep-agent/streaming-terminal.js.map +0 -1
  466. package/dist/activities/execute-deep-agent/streaming-v3.d.ts +0 -13
  467. package/dist/activities/execute-deep-agent/streaming-v3.js +0 -174
  468. package/dist/activities/execute-deep-agent/streaming-v3.js.map +0 -1
  469. package/dist/activities/execute-deep-agent/streaming.d.ts +0 -81
  470. package/dist/activities/execute-deep-agent/streaming.js +0 -160
  471. package/dist/activities/execute-deep-agent/streaming.js.map +0 -1
  472. package/dist/middleware/cost-cap.d.ts +0 -22
  473. package/dist/middleware/cost-cap.js.map +0 -1
  474. package/dist/middleware/graceful-stop.d.ts +0 -17
  475. package/dist/middleware/graceful-stop.js +0 -63
  476. package/dist/middleware/graceful-stop.js.map +0 -1
  477. package/dist/shared/skill-writer.d.ts +0 -75
  478. package/dist/shared/skill-writer.js +0 -207
  479. package/dist/shared/skill-writer.js.map +0 -1
  480. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +0 -1032
  481. package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +0 -240
  482. package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +0 -169
  483. package/src/activities/execute-cursor/capture-flow.ts +0 -379
  484. package/src/activities/execute-cursor/command-provenance.ts +0 -73
  485. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +0 -1161
  486. package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +0 -252
  487. package/src/activities/execute-deep-agent/__tests__/environment.test.ts +0 -108
  488. package/src/activities/execute-deep-agent/__tests__/event-recorder.test.ts +0 -150
  489. package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +0 -226
  490. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -318
  491. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -351
  492. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -293
  493. package/src/activities/execute-deep-agent/__tests__/index.test.ts +0 -99
  494. package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +0 -44
  495. package/src/activities/execute-deep-agent/__tests__/post-stream.test.ts +0 -112
  496. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -358
  497. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +0 -1933
  498. package/src/activities/execute-deep-agent/__tests__/streaming-terminal.test.ts +0 -40
  499. package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +0 -597
  500. package/src/activities/execute-deep-agent/__tests__/streaming.test.ts +0 -508
  501. package/src/activities/execute-deep-agent/attachment-injector.ts +0 -627
  502. package/src/activities/execute-deep-agent/command-provenance.ts +0 -102
  503. package/src/activities/execute-deep-agent/environment.ts +0 -76
  504. package/src/activities/execute-deep-agent/event-recorder.ts +0 -95
  505. package/src/activities/execute-deep-agent/index.ts +0 -1072
  506. package/src/activities/execute-deep-agent/mcp-gate.ts +0 -37
  507. package/src/activities/execute-deep-agent/post-stream.ts +0 -109
  508. package/src/activities/execute-deep-agent/setup.ts +0 -1081
  509. package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +0 -64
  510. package/src/activities/execute-deep-agent/status-builder.ts +0 -481
  511. package/src/activities/execute-deep-agent/streaming-terminal.ts +0 -106
  512. package/src/activities/execute-deep-agent/streaming-v3.ts +0 -277
  513. package/src/activities/execute-deep-agent/streaming.ts +0 -313
  514. package/src/middleware/__tests__/cost-cap.test.ts +0 -192
  515. package/src/middleware/__tests__/graceful-stop.test.ts +0 -105
  516. package/src/middleware/graceful-stop.ts +0 -86
  517. package/src/shared/__tests__/skill-writer.test.ts +0 -372
  518. package/src/shared/skill-writer.ts +0 -266
@@ -1,1081 +0,0 @@
1
- /**
2
- * Execution setup pipeline for the deep agent activity.
3
- *
4
- * Hydrates the execution from the database, resolves the full resource
5
- * chain (session -> agentInstance -> agent), provisions workspace, loads
6
- * MCP servers / environment, creates the LangGraph agent graph with the
7
- * full middleware stack, and returns a SetupResult containing everything
8
- * the streaming phase needs.
9
- */
10
-
11
- import { createDeepAgent } from "deepagents";
12
- import { InteractionMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
13
- import type { BaseCheckpointSaver } from "@langchain/langgraph-checkpoint";
14
- import { z } from "zod";
15
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- type AgentGraph = any;
17
-
18
- import type { AgentExecution, RecalledMemoriesReport } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
19
- import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
20
- import type { Session } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
21
- import type { DynamicStructuredTool } from "@langchain/core/tools";
22
-
23
- import type { Config } from "../../config.js";
24
- import type { StigmerClient } from "../../client/stigmer-client.js";
25
- import { TimingRecorder, emitTimingLog } from "../../shared/cold-start-timing.js";
26
- import { createCheckpointer } from "../../shared/checkpointer/factory.js";
27
- import { readContextBridge } from "../../shared/context-bridge.js";
28
- import { readConversationCatchup } from "../../shared/conversation-catchup.js";
29
- import { readSenderIdentity } from "../../shared/sender-identity.js";
30
- import {
31
- injectCallerIdentityEnv,
32
- resolveCallerIdentity,
33
- } from "../../shared/caller-identity.js";
34
- import { readSessionContext } from "../../shared/session-context.js";
35
- import { readDeclaredPreferences } from "../../shared/declared-preferences.js";
36
- import { selectRecalledFacts } from "../../shared/memory-retrieval.js";
37
- import { connectMcpServers, type McpConnectionResult } from "../../shared/mcp-manager.js";
38
- import { mergeMcpServerUsages, resolveMcpServers } from "../../shared/mcp-resolver.js";
39
- import { resolveMcpTransportPosture } from "../../shared/mcp-transport-guard.js";
40
- import { backfillMcpServersIfNeeded } from "../../shared/connect-backfill.js";
41
- import {
42
- discoverChannelMessaging,
43
- formatChannelTemplatesSection,
44
- synthesizeChannelAttachment,
45
- } from "../../shared/channel-attachment.js";
46
- import {
47
- readChannelConversationId,
48
- synthesizeConversationAttachment,
49
- } from "../../shared/conversation-attachment.js";
50
- import {
51
- memoryCaptureEnabled,
52
- synthesizeMemoryAttachment,
53
- } from "../../shared/memory-attachment.js";
54
- import { injectSynthesizedAttachment } from "../../shared/synthesized-attachment.js";
55
- import { shouldConnectMcp } from "./mcp-gate.js";
56
- import { WorkspaceProvisioner } from "../../shared/workspace/provisioner.js";
57
- import { LocalWorkspaceBackend } from "../../shared/workspace/local-backend.js";
58
- import type { WorkspaceBackend, ProvisionResult } from "../../shared/workspace/types.js";
59
- import { createCasCaptureBackend } from "./cas-capture-backend.js";
60
- import { buildShellEnv } from "./shell-env.js";
61
- import { buildPlanModePermissions } from "../../shared/plan-mode-permissions.js";
62
- import { CasCaptureObserver } from "./cas-capture-observer.js";
63
- import { isGitWorkTree, isPathCapturable } from "../../shared/filereview/git-substrate.js";
64
- import { deriveCaptureMode } from "../../shared/filereview/capture.js";
65
- import { resolveWorkspacePath } from "../../shared/file-change.js";
66
- import { ensurePlatformDir, ensureCheckpointDbPath } from "../../shared/workspace/platform-dir.js";
67
- import { resolveSessionWorkspaceRoot } from "../../shared/workspace/session-root.js";
68
- import { buildWorkspaceFileTree } from "../../shared/workspace/file-tree.js";
69
- import { reportSetupProgress } from "../../shared/status.js";
70
- import { resolveEnvironment, type EnvironmentResult } from "./environment.js";
71
- import { buildEnhancedSystemPrompt, composeUserMessage } from "./prompt-builder.js";
72
- import { buildMiddlewareStack } from "../../middleware/index.js";
73
- import type { GracefulStopMiddleware } from "../../middleware/index.js";
74
- import { createThinkTool, createWebFetchTool, resolveGuardPosture } from "../../tools/index.js";
75
- import type { ApprovalGateConfig } from "../../middleware/approval-gate.js";
76
- import { deriveExecutionFingerprintKey } from "../../shared/approval-fingerprint.js";
77
- import { getRunnerHitlMasterSecret } from "../../shared/fingerprint-secret.js";
78
- import { getModelPricing, ensureLoaded as ensurePricingLoaded } from "../../shared/model-pricing.js";
79
- import { getDefaultModel, getModelVisionCapability } from "../../shared/model-registry.js";
80
- import { buildChatModel } from "../../shared/model-client.js";
81
- import { resolveEffectiveServiceTier } from "../../shared/service-tier.js";
82
- import {
83
- loadArtifactStorageConfig,
84
- resolveUsableArtifactStorage,
85
- type ArtifactStorage,
86
- } from "../../shared/artifact-storage.js";
87
- import {
88
- mergeApprovalPolicies,
89
- deriveActiveLeases,
90
- isUnattendedApprovalMode,
91
- type MergedToolPolicy,
92
- } from "../../shared/approval-policy.js";
93
- import type { ToolApprovalCategory } from "../../shared/tool-kind.js";
94
- import {
95
- mergeSkillRefs,
96
- fetchSkillsByRefs,
97
- mountSkills,
98
- generatePromptSection,
99
- generateAlsoAvailableSection,
100
- } from "../../shared/skill-writer.js";
101
- import { filterSkills, SKILL_COUNT_THRESHOLD } from "../../shared/skill-relevance.js";
102
- import { injectAttachments } from "./attachment-injector.js";
103
- import {
104
- DEEP_AGENT_VISION_PROFILE,
105
- VisionBudget,
106
- toLangChainImageBlocks,
107
- type NotViewableEntry,
108
- } from "../../shared/attachment-vision.js";
109
- import { transformAndCompileSubagents } from "./subagent-transformer.js";
110
- import {
111
- resolveRecursionLimit,
112
- UNBOUNDED_ADVISORY_RECURSION_LIMIT,
113
- } from "../../shared/tool-rounds.js";
114
-
115
- export interface SetupResult {
116
- readonly agentGraph: AgentGraph;
117
- /**
118
- * The checkpoint saver backing agentGraph. Retained so the activity can close
119
- * it in cleanup — the durable sqlite saver holds an open file handle. Backends
120
- * without a handle (memory/http) are duck-typed for an optional close().
121
- */
122
- readonly checkpointer: BaseCheckpointSaver;
123
- readonly langgraphConfig: Record<string, unknown>;
124
- readonly langgraphInput: Record<string, unknown>;
125
- readonly execution: AgentExecution;
126
- readonly agent: Agent;
127
- readonly session: Session;
128
- readonly workspaceBackend: WorkspaceBackend;
129
- readonly mcpConnection: McpConnectionResult | null;
130
- readonly mergedEnvVars: Record<string, string>;
131
- readonly secretKeys: ReadonlySet<string>;
132
- readonly modelName: string;
133
- readonly gracefulStop: GracefulStopMiddleware;
134
- /**
135
- * Artifact storage for CAS blobs, tool-output offload, and attachment/plan
136
- * artifacts. `undefined` only when it cannot be built (proxy transport with a
137
- * missing token/endpoint — a misconfiguration; local storage never fails). Every
138
- * consumer must tolerate its absence: capture degrades to the deny-gate (see
139
- * `captureMode`), offload is disabled (the aggregate size guard still applies),
140
- * and attachment/plan publishing surface a clear error rather than crashing.
141
- */
142
- readonly artifactStorage: ArtifactStorage | undefined;
143
- readonly provisionResults: readonly ProvisionResult[];
144
- readonly approvalPolicies: ReadonlyMap<string, MergedToolPolicy>;
145
- readonly toolServerMap: ReadonlyMap<string, string>;
146
- /**
147
- * Built-in approval categories with a run-lifetime scoped lease (from an
148
- * interactive APPROVE_ALL). Threaded to the StatusBuilder so a leased built-in
149
- * call is attributed to its lease (approval_lease) rather than the plain
150
- * category gate. Empty under a global pre-arm or when no lease is active.
151
- */
152
- readonly leasedCategories: ReadonlySet<ToolApprovalCategory>;
153
- /**
154
- * Pre-armed spec.auto_approve_all — the one unscoped, whole-run bypass. When
155
- * true the approval gate is not installed at all. Interactive "approve all"
156
- * decisions are NOT folded in here; they become scoped leases applied inside
157
- * the gate (see ActiveLeases / deriveActiveLeases).
158
- */
159
- readonly globalBypass: boolean;
160
- /**
161
- * Unattended approval mode (ExecutionConfig.approval_mode = UNATTENDED,
162
- * stamped by approver-less surfaces — channels, guest shares). The gate
163
- * resolves gated tools as automatic skips instead of interrupting; the
164
- * builders never seed WAITING_APPROVAL. See isUnattendedApprovalMode.
165
- */
166
- readonly unattended: boolean;
167
- /**
168
- * Tool-call ids the gate auto-skipped under {@link unattended} this turn.
169
- * Written ONLY by the approval gate (parent + inherited sub-agent gates
170
- * share this instance); read by reconcileUnattendedSkips after the stream
171
- * to stamp terminal SKIPPED rows. Empty set when not unattended.
172
- */
173
- readonly unattendedSkips: Set<string>;
174
- readonly hasStructuredOutput: boolean;
175
- readonly streamVersion: "v2" | "v3";
176
- /**
177
- * The single owner of this turn's CAS-capture state (design docs 08/11/12):
178
- * the pre-turn bytes of first-touched gitignored paths (recorded
179
- * gate-independently by the CAS-observing backends of the parent AND every
180
- * sub-agent) plus the gitignored paths the gate hard-blocked as secret-like
181
- * (DD-E). The turn boundary reads both to compose the CAS change set. Empty in
182
- * the legacy (non-capture) path, where no CAS-observing backend is installed.
183
- */
184
- readonly casObserver: CasCaptureObserver;
185
- /**
186
- * Apply-then-review capture mode, decided by {@link deriveCaptureMode} (shared
187
- * with the Cursor harness so both degrade identically): file edits flow during
188
- * the turn and are reviewed post-hoc as a captured `FileChangeSet` (the activity
189
- * authors the baseline/candidate ledger events and reconciles on resume). True
190
- * whenever there is a capture substrate — a git work tree (needs no storage) OR
191
- * artifact storage for the non-git CAS path. False for a non-git workspace with
192
- * no artifact storage (proxy misconfig): capture has no substrate, so file writes
193
- * fall back to the deny-gate (gated pre-execution) exactly like Cursor's DD-22
194
- * fallback. When true, the deny-gate covers only shell/MCP/irreversible tools.
195
- */
196
- readonly captureMode: boolean;
197
- /**
198
- * True when the workspace is a git work tree. Selects the capture SUBSTRATE for
199
- * this turn: git-diff (pinned baseline/after trees) when true; content-addressed
200
- * CAS manifest (path-scoped to touched paths) when false. Threaded into the
201
- * baseline/candidate/reconcile seam (`capture.ts`) and the CAS capture-class.
202
- */
203
- readonly gitWorkspace: boolean;
204
- /**
205
- * The semantic retriever's injection outcome (DD-008 D5), produced at
206
- * prompt build (Step 8) — the one place selection runs. The activity
207
- * stamps it onto the turn's status proto before the first persist; the
208
- * server's presence-guarded merge preserves it across report-less
209
- * writes. Undefined when nothing was injected (recall absent, disabled,
210
- * or empty) — absent report = wholesale, true by construction.
211
- */
212
- readonly recalledMemoriesReport: RecalledMemoriesReport | undefined;
213
- }
214
-
215
- export interface SetupDependencies {
216
- config: Config;
217
- client: StigmerClient;
218
- executionId: string;
219
- threadId: string;
220
- }
221
-
222
- /**
223
- * Execute all setup phases and return resources for the streaming phase.
224
- *
225
- * On failure, partial resources (MCP connections, workspace backend) are
226
- * cleaned up internally before re-throwing.
227
- */
228
- export async function performSetup(deps: SetupDependencies): Promise<SetupResult> {
229
- const { config, client, executionId, threadId } = deps;
230
- let mcpConnection: McpConnectionResult | null = null;
231
- // Cold-start timeline of this setup (warm-agent-surfaces Phase 0): one mark
232
- // after each phase, emitted as a single structured log line before return.
233
- const timing = new TimingRecorder();
234
-
235
- try {
236
- // Step 1: Hydrate execution
237
- await reportSetupProgress(client, executionId, "Fetching execution…");
238
- const execution = await client.getExecution(executionId);
239
- console.log(`[setup] Execution fetched: agent_id=${execution.spec?.agentId}`);
240
- timing.mark("fetch_execution");
241
-
242
- // Step 2: Resolve chain — execution → session → agentInstance → agent
243
- await reportSetupProgress(client, executionId, "Resolving agent…");
244
- const sessionId = execution.spec!.sessionId;
245
- if (!sessionId) {
246
- throw new Error(
247
- `Session ID is required for execution ${executionId}. ` +
248
- "Execution must have a valid session_id.",
249
- );
250
- }
251
-
252
- const session = await client.getSession(sessionId);
253
- const agentInstance = await client.getAgentInstance(session.spec!.agentInstanceId);
254
- const agent = await client.getAgent(agentInstance.spec!.agentId);
255
-
256
- const instructions = agent.spec!.instructions || "You are a helpful AI assistant.";
257
- console.log(
258
- `[setup] Chain resolved: session=${sessionId}, ` +
259
- `agent=${agent.metadata!.name}`,
260
- );
261
- timing.mark("resolve_chain");
262
-
263
- // Step 3: Resolve model
264
- const modelName = execution.spec!.executionConfig?.modelName
265
- || await getDefaultModel();
266
-
267
- // Step 4: Create checkpointer. The durable local (sqlite) backend keys its
268
- // file per session — a session has exactly one thread (`thread-{sessionId}`),
269
- // so checkpoint lifetime tracks session lifetime. The saver is closed in the
270
- // activity cleanup (see index.ts), alongside the MCP connection.
271
- const checkpointer = await createCheckpointer({
272
- type: config.checkpointerType,
273
- proxyEndpoint: config.checkpointerProxyEndpoint ?? undefined,
274
- authToken: config.stigmerToken ?? undefined,
275
- sqlitePath: config.checkpointerType === "sqlite"
276
- ? await ensureCheckpointDbPath(sessionId)
277
- : undefined,
278
- });
279
- timing.mark("create_checkpointer");
280
-
281
- // Step 5: Resolve environment
282
- await reportSetupProgress(client, executionId, "Resolving environment…");
283
- const envResult: EnvironmentResult = await resolveEnvironment(client, executionId);
284
- timing.mark("resolve_environment");
285
-
286
- // Step 6: Resolve a usable artifact store (shared with the Cursor harness so
287
- // both degrade identically). Returns `undefined` — never throws — when there
288
- // is no working substrate: a proxy misconfig OR an unwritable local path
289
- // (which `createArtifactStorage` cannot detect, since it just holds a path).
290
- // An absent store flips capture mode off (deny-gate fallback below) and
291
- // disables offload, instead of flowing writes then crashing at the boundary.
292
- const artifactStorage: ArtifactStorage | undefined =
293
- await resolveUsableArtifactStorage(loadArtifactStorageConfig(config), { executionId });
294
- timing.mark("resolve_artifact_storage");
295
-
296
- // Step 7: Provision workspace
297
- await reportSetupProgress(client, executionId, "Initializing workspace…");
298
- const { workspaceBackend, provisionResults } = await provisionWorkspace(
299
- config,
300
- session,
301
- envResult.mergedEnvVars,
302
- sessionId,
303
- );
304
- timing.mark("provision_workspace");
305
-
306
- // Apply-then-review is the file-review model whenever there is a capture
307
- // SUBSTRATE (DD-21 D2, Slice 2b): file edits flow during the turn and are
308
- // reviewed post-hoc as a captured `FileChangeSet` (reconciled byte-exactly on
309
- // resume), never gated before they run. The substrate is selected by
310
- // `gitWorkspace`:
311
- // - a git work tree diffs a pinned baseline -> candidate tree (git-substrate,
312
- // needs no artifact storage), and routes its .gitignored edits into the
313
- // path-scoped CAS observer;
314
- // - a non-git workspace has no git snapshot at all, so EVERY touched path is
315
- // captured into the content-addressed CAS manifest (cas-substrate), which
316
- // needs artifact storage to persist blobs.
317
- // So a non-git workspace with NO artifact storage has no substrate: capture
318
- // degrades to the deny-gate (file writes gated pre-execution), exactly like the
319
- // Cursor harness (DD-22). `deriveCaptureMode` is the shared decision so both
320
- // harnesses degrade identically. When capture is on, the deny-gate survives only
321
- // for shell/MCP/irreversible tools.
322
- const gitWorkspace = await isGitWorkTree(workspaceBackend.rootDir);
323
- const captureMode = deriveCaptureMode(
324
- workspaceBackend.rootDir,
325
- gitWorkspace,
326
- !!artifactStorage,
327
- );
328
-
329
- // Git-tracked capturability, consulted by the gate to route a file write to
330
- // disk-and-git-diff (tracked) vs into CAS (ignored). Only meaningful in a git
331
- // work tree. In a non-git workspace nothing is "git-capturable" (there is no
332
- // snapshot), so this resolves false for every path and the gate routes all
333
- // file writes through its captureIgnored (CAS) arm.
334
- const isCapturablePath = gitWorkspace
335
- ? (rawPath: string): Promise<boolean> =>
336
- isPathCapturable(
337
- workspaceBackend.rootDir,
338
- resolveWorkspacePath(rawPath, workspaceBackend.rootDir, true).path,
339
- )
340
- : (_rawPath: string): Promise<boolean> => Promise.resolve(false);
341
-
342
- // CAS capture (design docs 08/11/12): the content-addressed half of
343
- // apply-then-review. The single per-turn observer owns the before-bytes of
344
- // first-touched CAS-owned paths AND the secret-blocked paths, keyed
345
- // workspace-root-relative so they align with the CAS reconcile's
346
- // `join(workspaceRoot, path)`. It is shared by the parent AND every sub-agent
347
- // CAS backend, giving race-free first-touch-wins across concurrent graphs.
348
- // Its ownership predicate is memoized, so `git check-ignore` runs at most once
349
- // per distinct path.
350
- const casObserver = new CasCaptureObserver({
351
- rootDir: workspaceBackend.rootDir,
352
- // Which touched paths the observer owns (records pre-turn bytes for). In a
353
- // git work tree that is the .gitignored set only — git captures the tracked
354
- // ones. In a non-git workspace there is no git substrate, so the observer
355
- // owns EVERY touched path; the CAS manifest is the sole capture surface.
356
- isIgnored: gitWorkspace
357
- ? async (relPath) => !(await isPathCapturable(workspaceBackend.rootDir, relPath))
358
- : async () => true,
359
- });
360
-
361
- // Step 7: Resolve and connect MCP servers. Session-wins-per-slug merge
362
- // (the Cursor harness's blueprint semantics, shared so a duplicate slug
363
- // resolves identically in both harnesses — one usage per server, whose
364
- // enabled_tools is the one the connect-time filter honors).
365
- const mcpServerUsages = mergeMcpServerUsages(
366
- agent.spec!.mcpServerUsages || [],
367
- session.spec!.mcpServerUsages || [],
368
- );
369
-
370
- // The synthesized attachments' credential story (DD-006 D4): the
371
- // exchanged token authenticates the discovery reads per-call (the
372
- // messaging reach refuses a desktop runner's ambient embedded_runner
373
- // credential; undefined lets the ambient credential apply). The
374
- // attachment header falls back to the ambient credential. Unlike the
375
- // env read (which hard-fails on a broken exchange — secrets are
376
- // load-bearing there), this exchange is opportunistic: every consumer
377
- // below degrades to an empty answer by contract, and the server
378
- // refuses the ambient fallback safely, so a failed exchange must not
379
- // kill the run.
380
- let exchangedRunnerToken: string | undefined;
381
- try {
382
- exchangedRunnerToken =
383
- await client.acquireScopedRunnerToken({ agentExecutionId: executionId });
384
- } catch (err) {
385
- console.warn(
386
- "[execute-deep-agent] Scoped-token exchange failed for attachment/discovery " +
387
- `reads; degrading to the ambient credential: ${err instanceof Error ? err.message : err}`,
388
- );
389
- }
390
- const attachmentCredential = exchangedRunnerToken
391
- ?? config.stigmerTokenRef?.current
392
- ?? config.stigmerToken;
393
-
394
- // The channel discovery read runs BEFORE the MCP gate below: an
395
- // agent whose ONLY tool source is a proactive channel would
396
- // otherwise never enter MCP resolution and never connect the
397
- // attachment (DD-006 D7). Every failure mode degrades to an empty
398
- // answer — no tool, no section, execution unharmed.
399
- const channelMessaging = await discoverChannelMessaging(client, exchangedRunnerToken);
400
-
401
- // The conversation-attachment decision (DD-008 D-c): the channel-id
402
- // session label, stamped server-side on every channel session — a
403
- // free, synchronous read, so no hoisted discovery needed.
404
- const conversationChannelId = readChannelConversationId(session.metadata?.labels);
405
-
406
- // The memory-attachment decision (DD-005 D1): the recall snapshot's
407
- // enabled bit, stamped server-side at execution create — like the
408
- // conversation attachment, a free, synchronous spec read.
409
- const captureMemories = memoryCaptureEnabled(execution.spec?.recalledMemories);
410
-
411
- let resolvedMcpServers: Awaited<ReturnType<typeof resolveMcpServers>> | null = null;
412
- if (shouldConnectMcp({
413
- mcpServerUsageCount: mcpServerUsages.length,
414
- channelMessagingCount: channelMessaging.length,
415
- conversationChannelId,
416
- memoryCaptureEnabled: captureMemories,
417
- })) {
418
- await reportSetupProgress(client, executionId, "Connecting tools…");
419
- const transportPosture = resolveMcpTransportPosture(config.mode);
420
- // The MCP-bound env map (and ONLY it) carries the reserved
421
- // caller-identity keys — mirror of the Cursor harness's Phase 4
422
- // injection; filterEnvToDeclaredKeys keeps undeclared servers blind.
423
- const mcpEnvVars = injectCallerIdentityEnv(
424
- envResult.mergedEnvVars,
425
- resolveCallerIdentity(
426
- session.spec!.metadata,
427
- session.status?.audit?.specAudit?.createdBy,
428
- ),
429
- sessionId,
430
- );
431
- resolvedMcpServers = await resolveMcpServers(
432
- client, mcpServerUsages, mcpEnvVars, transportPosture,
433
- );
434
- timing.mark("resolve_mcp_servers");
435
-
436
- const sessionOrg = session.metadata?.org ?? "";
437
- let backfilledServers = await backfillMcpServersIfNeeded(
438
- client,
439
- resolvedMcpServers.resolvedServers,
440
- mcpServerUsages,
441
- mcpEnvVars,
442
- sessionOrg,
443
- transportPosture,
444
- undefined,
445
- envResult.secretKeys,
446
- );
447
-
448
- // The channel messaging attachment (DD-006 D7/D8) — injected AFTER
449
- // resolve + backfill so the destructiveHint tightener can never gate
450
- // it; empty approval maps keep it approval-free by construction.
451
- if (channelMessaging.length > 0) {
452
- const attachment = synthesizeChannelAttachment(channelMessaging, {
453
- bridgeEndpoint: config.mcpBridgeEndpoint,
454
- credential: attachmentCredential,
455
- backendEndpoint: config.stigmerBackendEndpoint,
456
- });
457
- if (attachment) {
458
- backfilledServers = injectSynthesizedAttachment(
459
- backfilledServers, attachment, "channel messaging",
460
- );
461
- }
462
- }
463
-
464
- // The conversation participation attachment (DD-008 D-c) — the
465
- // channel attachment's sibling, same after-backfill rule. HTTP-only:
466
- // synthesize answers undefined with no bridge endpoint by design (see
467
- // shared/conversation-attachment.ts).
468
- const conversationAttachment = synthesizeConversationAttachment(conversationChannelId, {
469
- bridgeEndpoint: config.mcpBridgeEndpoint,
470
- credential: attachmentCredential,
471
- backendEndpoint: config.stigmerBackendEndpoint,
472
- });
473
- if (conversationAttachment) {
474
- backfilledServers = injectSynthesizedAttachment(
475
- backfilledServers, conversationAttachment, "conversation participation",
476
- );
477
- }
478
-
479
- // The memory capture attachment (DD-005 D1) — same after-backfill
480
- // rule. The capture context is attribution the server verifies or
481
- // trusts per edition (Stage 3 provenance decision); the subject is
482
- // never threaded — it derives from the credential.
483
- if (captureMemories) {
484
- const memoryAttachment = synthesizeMemoryAttachment(
485
- execution.spec?.recalledMemories,
486
- {
487
- org: session.metadata?.org ?? "",
488
- agentId: agent.metadata?.id ?? "",
489
- sessionId,
490
- agentExecutionId: executionId,
491
- },
492
- {
493
- bridgeEndpoint: config.mcpBridgeEndpoint,
494
- credential: attachmentCredential,
495
- backendEndpoint: config.stigmerBackendEndpoint,
496
- },
497
- );
498
- if (memoryAttachment) {
499
- backfilledServers = injectSynthesizedAttachment(
500
- backfilledServers, memoryAttachment, "memory capture",
501
- );
502
- }
503
- }
504
- resolvedMcpServers = { resolvedServers: backfilledServers };
505
- timing.mark("backfill_mcp");
506
-
507
- // connect_mcp covers the whole fan-out: stdio servers spawn npx/uvx
508
- // subprocesses here, so on-demand package installs land in this span.
509
- mcpConnection = await connectMcpServers(resolvedMcpServers.resolvedServers);
510
- timing.mark("connect_mcp");
511
- }
512
-
513
- // Step 7b: Resolve and write skills
514
- const skillRefs = mergeSkillRefs(
515
- agent.spec!.skillRefs || [],
516
- session.spec!.skillRefs || [],
517
- );
518
-
519
- let skillsPromptSection = "";
520
- if (skillRefs.length > 0) {
521
- await reportSetupProgress(client, executionId, "Loading skills…");
522
- const skills = await fetchSkillsByRefs(client, skillRefs);
523
-
524
- if (skills.length > 0) {
525
- // platformDir is an invariant of this path: provisionWorkspace below
526
- // threads ensurePlatformDir into every backend it constructs.
527
- const { paths: skillPaths } = await mountSkills(
528
- client, skills, workspaceBackend.platformDir!,
529
- );
530
-
531
- const userMessage = execution.spec!.message || "";
532
- const skillNames = skills.map(s => s.spec?.name || s.metadata?.slug || "unknown");
533
- const skillDescriptions = skills.map(s => s.spec?.description || "");
534
-
535
- if (skills.length >= SKILL_COUNT_THRESHOLD) {
536
- const filterResult = filterSkills(userMessage, skillNames, skillDescriptions);
537
- if (filterResult.excludedNames.length > 0) {
538
- const includedSkills = filterResult.includedIndices.map(i => skills[i]);
539
- console.log(
540
- `[setup] Skill relevance filter: ${includedSkills.length} included, ` +
541
- `${filterResult.excludedNames.length} excluded: ${filterResult.excludedNames.join(", ")}`,
542
- );
543
- skillsPromptSection =
544
- generatePromptSection(includedSkills, skillPaths) +
545
- generateAlsoAvailableSection(filterResult.excludedNames);
546
- } else {
547
- skillsPromptSection = generatePromptSection(skills, skillPaths);
548
- }
549
- } else {
550
- skillsPromptSection = generatePromptSection(skills, skillPaths);
551
- }
552
-
553
- console.log(
554
- `[setup] Skills loaded: ${skills.length} total, prompt section ${skillsPromptSection.length} chars`,
555
- );
556
- }
557
- timing.mark("resolve_skills");
558
- }
559
-
560
- // Step 7c: Inject attachments. The vision budget rides along so image
561
- // attachments are selected for inline delivery while their bytes are
562
- // already in hand (attachment-vision.ts owns all policy). The budget
563
- // also carries the root model's registry vision capability — the root
564
- // model is the only one that ever receives inline image blocks
565
- // (sub-agents get a fresh task description, summarization reuses this
566
- // same model instance) — so a model flagged `vision: false` degrades
567
- // images honestly instead of shipping a payload its provider rejects.
568
- const attachments = execution.spec!.attachments || [];
569
- const visionBudget = new VisionBudget(DEEP_AGENT_VISION_PROFILE, {
570
- modelVision: await getModelVisionCapability(modelName),
571
- });
572
- const injectedFiles = await injectAttachments({
573
- backend: workspaceBackend,
574
- attachments,
575
- storage: artifactStorage,
576
- isLocalMode: config.mode === "local",
577
- visionBudget,
578
- });
579
- // Vision facts, derived once from the single injection result: the images
580
- // the model will see inline (in attachment order) and the ones that
581
- // degraded to path-only, disclosed in the system prompt's Input Files
582
- // section.
583
- const visionImages = injectedFiles.flatMap((f) => (f.vision ? [f.vision] : []));
584
- const visionNotViewable: NotViewableEntry[] = injectedFiles.flatMap((f) =>
585
- f.visionDegraded ? [{ path: f.path, reason: f.visionDegraded }] : [],
586
- );
587
- const visionPromptInfo = visionImages.length > 0 || visionNotViewable.length > 0
588
- ? {
589
- inlineFilenames: visionImages.map((v) => v.filename),
590
- notViewable: visionNotViewable,
591
- }
592
- : undefined;
593
- if (visionPromptInfo) {
594
- console.log(
595
- `[attachment-vision] execution=${executionId} inline=${visionImages.length} ` +
596
- `(${visionImages.reduce((n, v) => n + v.byteSize, 0)} bytes) ` +
597
- `degraded=${JSON.stringify(visionNotViewable.map((d) => `${d.path}:${d.reason}`))}`,
598
- );
599
- }
600
- timing.mark("inject_attachments");
601
-
602
- // Step 8: Build enhanced system prompt.
603
- //
604
- // Recalled memories go through the semantic retriever (DD-008), not the
605
- // raw snapshot read: above the activation threshold it selects the
606
- // top-k facts for THIS turn's message (one batched embeddings call);
607
- // otherwise — and on any failure — it injects the full candidate set,
608
- // exactly the Phase 2 behavior. A re-invocation of this execution
609
- // (approval resume) replays the outcome recorded on the execution's
610
- // status instead of re-selecting, so the prompt never shifts
611
- // mid-execution. The report returned here is stamped onto the turn's
612
- // status by the activity (index.ts) — setup has no status object yet.
613
- const memorySelection = await selectRecalledFacts(
614
- execution.spec!.recalledMemories,
615
- execution.spec!.message,
616
- {
617
- proxyEndpoint: config.proxyEndpoint,
618
- stigmerToken: config.stigmerToken,
619
- executionId,
620
- priorReport: execution.status?.recalledMemoriesReport,
621
- },
622
- );
623
- const systemPrompt = buildEnhancedSystemPrompt({
624
- instructions,
625
- provisionResults,
626
- containerRoot: workspaceBackend.rootDir,
627
- skillsPromptSection,
628
- // "" (nothing sendable) threads as undefined: the tool alone still
629
- // serves text sends inside a 24-hour window (DD-006 D6).
630
- channelTemplatesPromptSection: channelMessaging.length > 0
631
- ? formatChannelTemplatesSection(channelMessaging) || undefined
632
- : undefined,
633
- workspaceFileRefs: execution.spec!.workspaceFileRefs || [],
634
- workspaceRoot: workspaceBackend.rootDir,
635
- injectedFiles,
636
- vision: visionPromptInfo,
637
- downloadUrlKind: artifactStorage?.downloadUrlKind,
638
- interactionMode: execution.spec!.executionConfig?.interactionMode,
639
- buildFromPlan: execution.spec!.executionConfig?.buildFromPlan,
640
- contextBridge: readContextBridge(session.spec!.metadata),
641
- senderIdentity: readSenderIdentity(session.spec!.metadata),
642
- sessionContext: readSessionContext(session.spec!.metadata),
643
- declaredPreferences: readDeclaredPreferences(
644
- execution.spec!.declaredPreferences,
645
- ),
646
- recalledMemories: memorySelection.content,
647
- });
648
-
649
- // Step 9: Construct the LLM model. Resolution to the provider API id
650
- // happens inside buildChatModel; modelName stays the registry id for
651
- // pricing, the native-thinking heuristic, and sub-agent inheritance.
652
- // The operator's STIGMER_LLM_REQUEST_TIMEOUT_MS bound is applied inside
653
- // buildChatModel (#468) — the sub-agent modelFactory below silently
654
- // dropped it when each caller parsed the env itself.
655
- //
656
- // The service tier resolves ONCE here (UNSPECIFIED → explicit
657
- // STANDARD, shared/service-tier.ts) and rides every model this
658
- // execution constructs — the primary below AND the sub-agent factory —
659
- // so the provider account's default can never pick the price of any
660
- // turn (#361, the native half of #357's contract). Sub-agents inherit
661
- // it because the tier is an attribute of the EXECUTION's bill, and
662
- // sub-agent calls land on the same ledger.
663
- const serviceTier = resolveEffectiveServiceTier(
664
- execution.spec!.executionConfig?.serviceTier);
665
- const { model } = await buildChatModel({
666
- modelName,
667
- proxyEndpoint: config.proxyEndpoint ?? undefined,
668
- stigmerToken: config.stigmerToken ?? undefined,
669
- headerScope: { executionId },
670
- serviceTier,
671
- });
672
- timing.mark("build_model");
673
-
674
- // Step 10: Build middleware stack
675
- await ensurePricingLoaded();
676
- const pricing = getModelPricing(modelName);
677
- const execConfig = execution.spec!.executionConfig;
678
- const isPlanMode = execConfig?.interactionMode === InteractionMode.PLAN;
679
- const shellEnv = isPlanMode ? undefined : buildShellEnv(envResult.mergedEnvVars);
680
- // Plan mode's filesystem permission rules, hoisted once: the parent graph
681
- // and every sub-agent graph carry this single value. The rules are the
682
- // write-deny half of plan mode only — the read boundary is structural
683
- // (virtual-rooted backends, issue #754), and the path-normalization shim
684
- // is no longer tied to the rules: every native graph installs it (see
685
- // buildMiddlewareStack below) so the whole harness speaks one dialect.
686
- const planModePermissions = isPlanMode ? buildPlanModePermissions() : undefined;
687
-
688
- const toolServerMap = new Map<string, string>();
689
- if (mcpConnection) {
690
- for (const [serverName, serverTools] of Object.entries(mcpConnection.serverToolMap)) {
691
- for (const t of serverTools) {
692
- toolServerMap.set(t.name, serverName);
693
- }
694
- }
695
- }
696
-
697
- // Step 10b: Resolve approval policies + leases.
698
- //
699
- // Two distinct bypasses (see ActiveLeases): the pre-armed
700
- // spec.auto_approve_all is the one whole-run global bypass; an interactive
701
- // APPROVE_ALL grants a run-lifetime lease scoped to that action's class (its
702
- // built-in category, or its MCP server). Server leases shape the policy map
703
- // (leased servers dropped); built-in category leases are applied inside the
704
- // gate. Both flow into sub-agents via the shared config below.
705
- const leases = deriveActiveLeases(execution);
706
- const globalBypass = leases.global;
707
- // Layer-3 overrides ride each resolved server from its (session-wins
708
- // merged) usage — see ResolvedMcpServer.toolApprovalOverrides (issue
709
- // #349) — so there is no separate override input to pass here.
710
- const approvalPolicies = mergeApprovalPolicies(
711
- resolvedMcpServers?.resolvedServers ?? [],
712
- leases,
713
- );
714
-
715
- // Unattended approval mode (DD-014): approver-less surfaces (channels,
716
- // guest shares) stamp APPROVAL_MODE_UNATTENDED, and the gate resolves
717
- // gated tools as automatic skips instead of interrupting. The registry is
718
- // the gate→reconciler channel for the skipped tool-call ids; one instance
719
- // is shared with sub-agent gates via the inherited config.
720
- const unattended = isUnattendedApprovalMode(execution);
721
- const unattendedSkips = new Set<string>();
722
-
723
- // The approval gate config is the single source of truth for HITL gating,
724
- // built once and inherited verbatim by sub-agents (so a mutating tool inside
725
- // a sub-agent is gated identically to one in the parent). Null under the
726
- // global pre-arm, where the gate is inert; under scoped leases the gate stays
727
- // active and clears only leased categories. The per-execution fingerprint key
728
- // (runner master secret + execution_id) drives the shadow ExecutionReceipt.
729
- const approvalGateConfig: ApprovalGateConfig | null = !globalBypass
730
- ? {
731
- policies: approvalPolicies,
732
- leasedCategories: leases.categories,
733
- toolServerMap,
734
- fingerprintKey: deriveExecutionFingerprintKey(
735
- getRunnerHitlMasterSecret(),
736
- executionId,
737
- ),
738
- executionId,
739
- // Capture mode: file edits flow and are reviewed post-hoc. In a git work
740
- // tree, git-tracked edits flow to the git diff and .gitignored edits flow
741
- // into CAS (captureIgnored) on THIS parent gate; in a non-git workspace
742
- // isCapturablePath is always false, so ALL file writes take the CAS arm.
743
- // Secret-like paths are hard-blocked (DD-E) and recorded for a
744
- // DIFF_UNREVIEWABLE entry. shell/MCP stay gated. Sub-agents inherit this
745
- // config; buildSubAgentMiddleware sets their captureIgnored explicitly
746
- // from whether a CAS observer backs the sub-agent (Session 26, DD-19),
747
- // so their captured edits flow into the SAME observer.
748
- //
749
- // When captureMode is false (no substrate — non-git + no storage),
750
- // fileCaptureMode is false so file writes take the plain deny-gate. The
751
- // CAS arm additionally requires storage: captureIgnored gates gitignored
752
- // writes onto CAS only when a store exists to persist their blobs (the
753
- // git+no-storage case), matching the Cursor harness's
754
- // `captureMode && !!artifactStorage`.
755
- fileCaptureMode: captureMode,
756
- isCapturablePath,
757
- captureIgnored: captureMode && !!artifactStorage,
758
- recordBlockedSecret: (rawPath: string) => casObserver.recordBlockedSecret(rawPath),
759
- // Pre-delete byte capture (issue #303): deepagents has no backend
760
- // delete method for the CAS backend to observe, so a flowing delete's
761
- // before-bytes are recorded by the gate at authorization time, through
762
- // the SAME shared observer — the turn boundary then reads after=null
763
- // and authors a reviewable, restorable DELETE. recordBefore's own
764
- // ownership predicate (gitignored-only in a git tree, everything in
765
- // non-git) agrees with the gate's not-capturable condition.
766
- captureDeleteBefore: (rawPath: string) => casObserver.recordBefore(rawPath),
767
- unattended,
768
- unattendedSkips,
769
- }
770
- : null;
771
-
772
- const maxCostUsd = execConfig?.maxCostUsd ?? 0;
773
- // max_tool_rounds → recursion limit (proto contract: 0/unset = unlimited,
774
- // set = clamped 10–1000 and enforced). One resolved value feeds BOTH the
775
- // hard stop on the invoke config below and the budget middleware's ~80%
776
- // wrap-up advisory, so the warning and the enforcement can never disagree.
777
- const recursionLimit = resolveRecursionLimit(execConfig?.maxToolRounds);
778
- const { middleware, gracefulStop, costCap: costCapMiddleware } = buildMiddlewareStack({
779
- loopDetection: {
780
- historySize: 20,
781
- consecutiveThreshold: 7,
782
- totalThreshold: 20,
783
- },
784
- executionBudget: {
785
- recursionLimit: recursionLimit ?? UNBOUNDED_ADVISORY_RECURSION_LIMIT,
786
- warningPct: 80,
787
- },
788
- toolTruncation: {
789
- maxChars: execConfig?.maxToolResultChars || 30_000,
790
- },
791
- costCap: maxCostUsd > 0 ? {
792
- maxCostUsd,
793
- inputPricePerMillion: pricing.inputPricePerMillion,
794
- outputPricePerMillion: pricing.outputPricePerMillion,
795
- cacheReadPricePerMillion: pricing.cacheReadPricePerMillion,
796
- warningPct: 80,
797
- } : null,
798
- otelSpans: { toolServerMap },
799
- approvalGate: approvalGateConfig,
800
- // Every graph, every mode (issue #754): the dialect-repair seam that
801
- // keeps model-supplied paths canonical for the virtual-rooted backend
802
- // and every downstream consumer (gate, capture, spans).
803
- pathNormalization: { rootDir: workspaceBackend.rootDir },
804
- });
805
- timing.mark("build_middleware");
806
-
807
- // Step 11: Build tools list (MCP tools + native built-in tools).
808
- //
809
- // web_fetch is always-on for every native run — the same posture as the
810
- // Cursor harness, whose WebFetch is a CLI built-in that no configuration
811
- // removes (issue #214 parity). It is auto-approved by design (see
812
- // toolApprovalCategory in shared/tool-kind.ts), so its URL guard posture
813
- // — strict on managed cloud runners, relaxed on user-owned machines — is
814
- // the entire safety boundary. Derived from config.mode, NOT the
815
- // cloudModeEnabled Cursor feature flag.
816
- const webFetchPosture = resolveGuardPosture(config.mode);
817
- const tools = [
818
- ...(mcpConnection?.tools as DynamicStructuredTool[] ?? []),
819
- createThinkTool(),
820
- createWebFetchTool({ posture: webFetchPosture }),
821
- ];
822
-
823
- // Step 11b: Transform and compile subagents
824
- const subAgentProtos = agent.spec!.subAgents || [];
825
- let compiledSubagents: Awaited<ReturnType<typeof transformAndCompileSubagents>> | undefined;
826
-
827
- if (subAgentProtos.length > 0 || workspaceBackend.rootDir) {
828
- await reportSetupProgress(client, executionId, "Configuring sub-agents…");
829
-
830
- const parentMcpServerToolMap = new Map<string, DynamicStructuredTool[]>();
831
- if (mcpConnection) {
832
- for (const [serverName, serverTools] of Object.entries(mcpConnection.serverToolMap)) {
833
- parentMcpServerToolMap.set(serverName, serverTools as DynamicStructuredTool[]);
834
- }
835
- }
836
-
837
- compiledSubagents = await transformAndCompileSubagents({
838
- subAgents: subAgentProtos,
839
- parentMcpTools: mcpConnection?.tools as DynamicStructuredTool[] ?? [],
840
- parentMcpServerToolMap,
841
- parentMcpUsages: mcpServerUsages,
842
- skillClient: client,
843
- workspaceBackend,
844
- approvalGate: approvalGateConfig,
845
- // Capture is universal (Slice 2b), so every sub-agent gets a CAS-observing
846
- // backend wired to the SAME per-turn observer as the parent — their
847
- // captured writes (.gitignored in a git tree, all touched paths in a
848
- // non-git one) compose into the parent's change set (Session 26, DD-19).
849
- casObserver,
850
- parentModelName: modelName,
851
- parentHasNativeThinking: _modelHasNativeThinking(modelName),
852
- webFetchPosture,
853
- costCap: costCapMiddleware ?? undefined,
854
- modelFactory: async (m: string) =>
855
- (await buildChatModel({
856
- modelName: m,
857
- proxyEndpoint: config.proxyEndpoint ?? undefined,
858
- stigmerToken: config.stigmerToken ?? undefined,
859
- headerScope: { executionId },
860
- // The execution's tier, inherited: sub-agent calls bill to the
861
- // same execution (#361 — see the Step 9 resolution comment).
862
- serviceTier,
863
- })).model,
864
- // Presence of shellEnv is the shell-capability switch for sub-agent
865
- // backends too (undefined in plan mode; see buildShellEnv above).
866
- shellEnv,
867
- // Plan mode's deny-all-writes rule, mirrored onto every sub-agent graph
868
- // (issue #255) — pre-built CompiledSubAgents never inherit the parent's
869
- // permissions, so read-only-by-construction must be baked in here.
870
- // compileSubagents derives each sub-agent's path-normalization shim
871
- // from this same value (issue #429).
872
- ...(planModePermissions ? { permissions: planModePermissions } : {}),
873
- });
874
- timing.mark("compile_subagents");
875
- }
876
-
877
- // Step 12: Create the agent graph with middleware
878
- await reportSetupProgress(client, executionId, "Creating agent…");
879
-
880
- const outputSchema = execution.spec!.executionConfig?.structuredOutputSchema;
881
- let responseFormat: z.ZodType | undefined;
882
- if (outputSchema) {
883
- responseFormat = jsonSchemaToZod(outputSchema as unknown as Record<string, unknown>);
884
- }
885
-
886
- // File capture point. Apply-then-review is universal (Slice 2b), so the
887
- // CAS-observing backend: git-tracked edits flow to disk (the turn-boundary
888
- // git diff is authoritative), and the shared CAS observer records the pre-turn
889
- // bytes of every CAS-owned path — .gitignored paths in a git work tree, all
890
- // touched paths in a non-git one — so the boundary can capture them into CAS.
891
- // It is gate-independent, so it holds even under the global bypass.
892
- const fileBackend = await createCasCaptureBackend({
893
- rootDir: workspaceBackend.rootDir,
894
- observer: casObserver,
895
- shellEnv,
896
- });
897
- const agentGraph = await createDeepAgent({
898
- model,
899
- checkpointer: checkpointer as any,
900
- backend: fileBackend,
901
- systemPrompt,
902
- tools,
903
- middleware: middleware as any,
904
- subagents: compiledSubagents ?? undefined,
905
- ...(responseFormat ? { responseFormat } : {}),
906
- ...(planModePermissions ? { permissions: planModePermissions } : {}),
907
- } as Parameters<typeof createDeepAgent>[0]);
908
-
909
- // Step 11: Prepare invocation input and config. The conversation catchup
910
- // (cloud DD-006) rides the USER MESSAGE, not the system prompt — see
911
- // composeUserMessage for the durability rationale (A27).
912
- let userMessage = composeUserMessage(
913
- execution.spec!.message,
914
- readConversationCatchup(execution.spec!.conversationCatchup),
915
- );
916
- if (outputSchema) {
917
- userMessage += `\n\n---\nIMPORTANT: When your analysis is complete, provide your findings as structured output matching the required schema. The system will capture your structured response automatically.`;
918
- }
919
- // With inline images the user message becomes a multimodal content-block
920
- // array — image blocks (with filename labels) FIRST, the composed text
921
- // last, per Anthropic's images-before-text guidance. Without images the
922
- // content stays a plain string, byte-identical to the pre-vision shape.
923
- // The LangGraph messages reducer coerces either form into a HumanMessage
924
- // untouched (verified against the installed @langchain/langgraph).
925
- const langgraphInput = {
926
- messages: [
927
- {
928
- role: "user",
929
- content: visionImages.length > 0
930
- ? [
931
- ...toLangChainImageBlocks(visionImages),
932
- { type: "text", text: userMessage },
933
- ]
934
- : userMessage,
935
- },
936
- ],
937
- };
938
-
939
- const langgraphConfig: Record<string, unknown> = {
940
- configurable: { thread_id: threadId },
941
- // Hard enforcement of max_tool_rounds (null = unlimited, the default):
942
- // when the graph exhausts this, the streaming loop's GraphRecursionError
943
- // handler terminates gracefully with work saved ("send another message
944
- // to continue"). The middleware's wrap-up advisory fires at ~80% of the
945
- // same value, so a healthy run finishes normally before ever hitting it.
946
- ...(recursionLimit !== null ? { recursionLimit } : {}),
947
- };
948
-
949
- const streamVersion: "v2" | "v3" =
950
- process.env.LANGGRAPH_STREAM_EVENTS_VERSION === "v2" ? "v2" : "v3";
951
-
952
- console.log(
953
- `[setup] Complete: model=${modelName}, ` +
954
- `tools=${tools.length}, middleware=${middleware.length}, ` +
955
- `thread_id=${threadId}, streamVersion=${streamVersion}`,
956
- );
957
- timing.mark("create_agent_graph");
958
- emitTimingLog("execution_setup", {
959
- execution_id: executionId,
960
- session_id: sessionId,
961
- harness: "native",
962
- mcp_server_count: mcpServerUsages.length,
963
- skill_count: skillRefs.length,
964
- workspace_entry_count: session.spec!.workspaceEntries?.length ?? 0,
965
- }, timing);
966
-
967
- return {
968
- agentGraph,
969
- checkpointer,
970
- langgraphConfig,
971
- langgraphInput,
972
- execution,
973
- agent,
974
- session,
975
- workspaceBackend,
976
- mcpConnection,
977
- mergedEnvVars: envResult.mergedEnvVars,
978
- secretKeys: envResult.secretKeys,
979
- modelName,
980
- gracefulStop,
981
- artifactStorage,
982
- provisionResults,
983
- approvalPolicies,
984
- toolServerMap,
985
- leasedCategories: leases.categories,
986
- globalBypass,
987
- unattended,
988
- unattendedSkips,
989
- hasStructuredOutput: !!outputSchema,
990
- streamVersion,
991
- casObserver,
992
- captureMode,
993
- gitWorkspace,
994
- recalledMemoriesReport: memorySelection.report,
995
- };
996
- } catch (err) {
997
- if (mcpConnection) {
998
- try { await mcpConnection.client.close(); } catch { /* swallow */ }
999
- }
1000
- throw err;
1001
- }
1002
- }
1003
-
1004
- /**
1005
- * Provision workspace from session workspace entries.
1006
- *
1007
- * A session with no entries gets its own empty per-session directory (see
1008
- * shared/workspace/session-root.ts) — never the shared root, which would
1009
- * leak other sessions' files into it. Mirrors shared/workspace/
1010
- * session-provision.ts `provisionSessionWorkspace` exactly; S3 of the
1011
- * harness runtime program retires this twin in favor of that one.
1012
- */
1013
- async function provisionWorkspace(
1014
- config: Config,
1015
- session: Session,
1016
- mergedEnvVars: Record<string, string>,
1017
- sessionId: string,
1018
- ): Promise<{ workspaceBackend: WorkspaceBackend; provisionResults: ProvisionResult[] }> {
1019
- const platformDir = await ensurePlatformDir(sessionId);
1020
-
1021
- const workspaceEntries = session.spec!.workspaceEntries || [];
1022
- if (workspaceEntries.length === 0) {
1023
- const sessionRoot = await resolveSessionWorkspaceRoot(
1024
- config.workspaceRootDir, workspaceEntries, sessionId,
1025
- );
1026
- return {
1027
- workspaceBackend: new LocalWorkspaceBackend(sessionRoot, platformDir),
1028
- provisionResults: [],
1029
- };
1030
- }
1031
-
1032
- const workspaceBackend = new LocalWorkspaceBackend(config.workspaceRootDir, platformDir);
1033
- const provisioner = new WorkspaceProvisioner();
1034
- const provisionResults = await provisioner.provisionAll(
1035
- workspaceEntries.map(entry => ({
1036
- name: entry.name,
1037
- source: entry.source,
1038
- })),
1039
- workspaceBackend,
1040
- mergedEnvVars,
1041
- config.mode === "local",
1042
- config.mode !== "local",
1043
- );
1044
-
1045
- // If single entry changed root dir, create a new backend with the same platformDir
1046
- if (
1047
- provisionResults.length === 1 &&
1048
- provisionResults[0].rootDir !== workspaceBackend.rootDir
1049
- ) {
1050
- return {
1051
- workspaceBackend: new LocalWorkspaceBackend(provisionResults[0].rootDir, platformDir),
1052
- provisionResults,
1053
- };
1054
- }
1055
-
1056
- return { workspaceBackend, provisionResults };
1057
- }
1058
-
1059
- // Shared JSON Schema → Zod converter (consolidated from 3 duplicate copies).
1060
- import { jsonSchemaToZod } from "../../shared/json-schema-to-zod.js";
1061
-
1062
- /**
1063
- * Heuristic check for native extended thinking support.
1064
- * Models with thinking support don't need the explicit think tool.
1065
- */
1066
- function _modelHasNativeThinking(modelId: string): boolean {
1067
- const lower = modelId.toLowerCase();
1068
-
1069
- if (lower.includes("haiku")) return false;
1070
- if (lower.includes("gpt-4o-mini")) return false;
1071
-
1072
- if (lower.includes("claude") && (
1073
- lower.includes("sonnet") || lower.includes("opus")
1074
- )) return true;
1075
-
1076
- if (lower.includes("o1") || lower.includes("o3") || lower.includes("o4")) {
1077
- return true;
1078
- }
1079
-
1080
- return false;
1081
- }