@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
@@ -10,8 +10,26 @@
10
10
  * their first segment (e.g. "tools:<pregelUuid>|model_request:<innerUuid>")
11
11
  * - First segment match (before "|") correlates child events to sub-agent
12
12
  *
13
- * The tracker owns the SubAgentExecution proto instances. V3StatusBuilder
14
- * delegates sub-agent-scoped events here instead of the parent message list.
13
+ * The tracker builds INTO the status's own `subAgentExecutions` array, by
14
+ * reference: it pushes new rows and mutates existing ones, never replaces the
15
+ * array, so the caller that seeded the array from the persisted transcript
16
+ * (the turn runtime's `seedFromPersistedStatus`) keeps every prior turn's
17
+ * row and every wrapper of the status sees the same rows. Seeded rows are
18
+ * indexed by id on construction; a re-emitted `task` tool start for a known
19
+ * id binds its routing prefix to the existing row instead of pushing a twin
20
+ * (the memory-checkpointer replay re-drives the whole graph), exactly as the
21
+ * parent builder reconciles re-emitted tool calls through its rebuilt index.
22
+ * Until S3 M2a the tracker owned a private array that `syncSubAgentExecutions`
23
+ * assigned onto the status wholesale, which a resumed turn's first delegation
24
+ * would have used to drop turn 1's rows (S3 M1 deferred debt).
25
+ *
26
+ * V3StatusBuilder delegates sub-agent-scoped events here instead of the
27
+ * parent message list. Marking rows CANCELLED when a turn stops is NOT the
28
+ * tracker's: `shared/subagent-rows.ts` `cancelInProgressSubAgentProtos` is
29
+ * the one home of that transition for every harness (the runtime's thrown
30
+ * arms and both adapters' stops call it); the tracker only clears the
31
+ * streaming flags those rows' messages still carry
32
+ * ({@link SubAgentTracker.finalizeAllStreaming}).
15
33
  */
16
34
 
17
35
  import { create, type JsonObject } from "@bufbuild/protobuf";
@@ -30,7 +48,7 @@ import {
30
48
  import { utcTimestamp } from "../../shared/status.js";
31
49
  import { classifyTool } from "../../shared/tool-kind.js";
32
50
  import { extractToolResultV3 } from "./status-builder-shared.js";
33
- import type { StigmerRunEvent, V3UsagePayload } from "./v3-events.js";
51
+ import type { StigmerRunEvent } from "./v3-events.js";
34
52
 
35
53
  // ── Per-SubAgent State ───────────────────────────────────────────────────────
36
54
 
@@ -51,16 +69,50 @@ interface SubAgentState {
51
69
  toolArgBuffers: Map<string, string>;
52
70
  }
53
71
 
72
+ /** Fresh routing state over a row; `namespacePrefix` is `""` for a seeded row until its `task` start re-announces it. */
73
+ function newSubAgentState(proto: SubAgentExecution, callId: string, namespacePrefix: string): SubAgentState {
74
+ return {
75
+ proto,
76
+ callId,
77
+ namespacePrefix,
78
+ messagesByRun: new Map(),
79
+ currentAiMessage: new Map(),
80
+ lastLlmRunId: new Map(),
81
+ toolCalls: new Map(),
82
+ toolArgBuffers: new Map(),
83
+ };
84
+ }
85
+
54
86
  // ── SubAgentTracker ──────────────────────────────────────────────────────────
55
87
 
56
88
  export class SubAgentTracker {
57
- private readonly executions: SubAgentExecution[] = [];
58
89
  private readonly stateByCallId = new Map<string, SubAgentState>();
59
90
  private readonly stateByPrefix = new Map<string, SubAgentState>();
60
91
 
92
+ /**
93
+ * @param executions - The status's own `subAgentExecutions` array, built
94
+ * into by reference. Rows already on it (the runtime's seed on a
95
+ * reinvocation) are indexed by id, with their tool calls, so a re-driven
96
+ * event reconciles onto them; their routing prefix is unknown until a
97
+ * `task` tool start re-announces it.
98
+ */
99
+ constructor(private readonly executions: SubAgentExecution[]) {
100
+ for (const proto of executions) {
101
+ const state = newSubAgentState(proto, proto.id, "");
102
+ for (const message of proto.messages) {
103
+ for (const tc of message.toolCalls) {
104
+ if (tc.id) state.toolCalls.set(tc.id, tc);
105
+ }
106
+ }
107
+ this.stateByCallId.set(proto.id, state);
108
+ }
109
+ }
110
+
61
111
  /**
62
112
  * Called when a "task" tool_started event is observed at depth 0 or 1.
63
- * Creates a new SubAgentExecution and begins tracking.
113
+ * Creates a new SubAgentExecution and begins tracking — or, for a seeded
114
+ * row re-announced by a replayed graph, binds the routing prefix to the
115
+ * row that already exists.
64
116
  *
65
117
  * @param callId - Provider tool call ID (e.g. "toolu_01HW...")
66
118
  * @param args - Tool input arguments (subagent_type, description)
@@ -70,7 +122,15 @@ export class SubAgentTracker {
70
122
  * caller provides a synthetic prefix like "tools:<callId>".
71
123
  */
72
124
  onTaskToolStarted(callId: string, args: Record<string, unknown>, routingPrefix: string): void {
73
- if (this.stateByCallId.has(callId)) return;
125
+ const existing = this.stateByCallId.get(callId);
126
+ if (existing) {
127
+ if (existing.namespacePrefix === "") {
128
+ const bound = { ...existing, namespacePrefix: routingPrefix };
129
+ this.stateByCallId.set(callId, bound);
130
+ this.stateByPrefix.set(routingPrefix, bound);
131
+ }
132
+ return;
133
+ }
74
134
 
75
135
  const name = safeString(args, "subagent_type") || "task";
76
136
  const description = safeString(args, "description") || "";
@@ -84,16 +144,7 @@ export class SubAgentTracker {
84
144
  startedAt: utcTimestamp(),
85
145
  });
86
146
 
87
- const state: SubAgentState = {
88
- proto,
89
- callId,
90
- namespacePrefix: routingPrefix,
91
- messagesByRun: new Map(),
92
- currentAiMessage: new Map(),
93
- lastLlmRunId: new Map(),
94
- toolCalls: new Map(),
95
- toolArgBuffers: new Map(),
96
- };
147
+ const state = newSubAgentState(proto, callId, routingPrefix);
97
148
 
98
149
  this.executions.push(proto);
99
150
  this.stateByCallId.set(callId, state);
@@ -129,16 +180,14 @@ export class SubAgentTracker {
129
180
  }
130
181
 
131
182
  /**
132
- * Mark all active sub-agents as cancelled (parent execution cancelled).
183
+ * Clear the streaming flag on every tracked sub-agent's in-flight
184
+ * messages. Called when the turn stops before the sub-agents finished;
185
+ * the rows' own CANCELLED transition is the caller's, through the shared
186
+ * `cancelInProgressSubAgentProtos` (see the header).
133
187
  */
134
- cancelAll(): void {
188
+ finalizeAllStreaming(): void {
135
189
  for (const state of this.stateByCallId.values()) {
136
- if (state.proto.status === SubAgentStatus.SUB_AGENT_IN_PROGRESS) {
137
- state.proto.status = SubAgentStatus.SUB_AGENT_CANCELLED;
138
- state.proto.completedAt = utcTimestamp();
139
- state.proto.error = "Cancelled: parent execution was cancelled";
140
- this.finalizeStreamingMessages(state);
141
- }
190
+ this.finalizeStreamingMessages(state);
142
191
  }
143
192
  }
144
193
 
@@ -186,7 +235,7 @@ export class SubAgentTracker {
186
235
  this.handleToolCallArgDelta(state, event.callId, event.argsChunk);
187
236
  break;
188
237
  case "message_finish":
189
- this.handleMessageFinish(state, event.runId, event.usage);
238
+ this.handleMessageFinish(state, event.runId);
190
239
  break;
191
240
  case "tool_started":
192
241
  this.handleToolStarted(state, event.callId, event.name, event.input, localNs);
@@ -207,20 +256,6 @@ export class SubAgentTracker {
207
256
  }
208
257
  }
209
258
 
210
- /**
211
- * Returns the current list of SubAgentExecution protos for persist.
212
- */
213
- getExecutions(): SubAgentExecution[] {
214
- return this.executions;
215
- }
216
-
217
- /**
218
- * Returns true if any sub-agents are being tracked.
219
- */
220
- hasExecutions(): boolean {
221
- return this.executions.length > 0;
222
- }
223
-
224
259
  // ── Message Handlers ─────────────────────────────────────────────────────
225
260
 
226
261
  private handleMessageStart(state: SubAgentState, runId: string, localNs: string): void {
@@ -258,11 +293,11 @@ export class SubAgentTracker {
258
293
  state.messagesByRun.set(thinkingKey, msg);
259
294
  }
260
295
 
261
- private handleMessageFinish(state: SubAgentState, runId: string, usage?: V3UsagePayload): void {
296
+ private handleMessageFinish(state: SubAgentState, runId: string): void {
262
297
  const msg = state.messagesByRun.get(runId);
263
298
  if (msg) msg.isStreaming = false;
264
- // Usage is tracked at parent level via V3StatusBuilder — not duplicated per sub-agent
265
- void usage;
299
+ // The usage on this event was reported by `V3StatusBuilder.processEvent`
300
+ // before it routed here (Q-M2b-1); the tracker owns the transcript only.
266
301
  }
267
302
 
268
303
  // ── Tool Handlers ──────────────────────────────────────────────────────
@@ -14,7 +14,7 @@
14
14
  * - Built-in general-purpose replaces deepagents' auto-injected one (which carries
15
15
  * no approval gate — see deepagents-profiles.ts for the suppression half)
16
16
  * - Sub-agent backends are shell-capable outside plan mode (issue #248), mirroring
17
- * the parent's backend selection in setup.ts
17
+ * the parent's backend selection in turn-setup.ts
18
18
  * - Sub-agent graphs carry the parent's filesystem permissions explicitly
19
19
  * (issue #255): pre-built CompiledSubAgents never inherit them, so plan
20
20
  * mode's deny-all-writes rule is baked into each graph at compile time
@@ -31,20 +31,16 @@ import type { BaseChatModel } from "@langchain/core/language_models/chat_models"
31
31
  import type { SubAgent, McpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
32
32
 
33
33
  import type { WorkspaceBackend } from "../../shared/workspace/types.js";
34
- import type { StigmerClient } from "../../client/stigmer-client.js";
35
34
  import type { ApprovalGateConfig } from "../../middleware/approval-gate.js";
36
35
  import { createCasCaptureBackend } from "./cas-capture-backend.js";
37
36
  import type { CasCaptureObserver } from "./cas-capture-observer.js";
38
- import type { CostCapMiddleware, StigmerMiddleware } from "../../middleware/index.js";
37
+ import type { CostAdvisoryMiddleware, StigmerMiddleware } from "../../middleware/index.js";
39
38
  import { createThinkTool, createWebFetchTool, type GuardPosture } from "../../tools/index.js";
40
39
  import { buildSubAgentMiddleware } from "./subagent-wiring.js";
41
40
  import { SubAgentGate } from "../../shared/subagent-gate.js";
42
41
  import { isModelRegistered } from "../../shared/model-registry.js";
43
- import {
44
- fetchSkillsByRefs,
45
- mountSkills,
46
- generatePromptSection,
47
- } from "../../shared/skill-writer.js";
42
+ import type { SkillMetadata } from "../../shared/skill-resolver.js";
43
+ import { renderSkillsSection } from "./prompt-builder.js";
48
44
 
49
45
  // =========================================================================
50
46
  // Built-in subagent types and prompts
@@ -141,7 +137,14 @@ export interface SubagentTransformOptions {
141
137
  readonly parentMcpTools: readonly StructuredTool[];
142
138
  readonly parentMcpServerToolMap: ReadonlyMap<string, readonly StructuredTool[]>;
143
139
  readonly parentMcpUsages: readonly McpServerUsage[];
144
- readonly skillClient: StigmerClient;
140
+ /**
141
+ * Each sub-agent's mounted skills, keyed by the sub-agent's name — the
142
+ * runtime's `TurnSkills.bySubAgent` (resolved and mounted by its skills
143
+ * phase, S3 M1 Q-S3-5). A sub-agent with no entry renders no skills
144
+ * section. Until S3 M2a this module fetched and mounted them itself with
145
+ * a control-plane client; the compile step is client-free now.
146
+ */
147
+ readonly skills: ReadonlyMap<string, readonly SkillMetadata[]>;
145
148
  readonly workspaceBackend: WorkspaceBackend;
146
149
  /**
147
150
  * The parent's approval-gate config, inherited verbatim so a mutating tool
@@ -162,11 +165,11 @@ export interface SubagentTransformOptions {
162
165
  readonly parentHasNativeThinking: boolean;
163
166
  /**
164
167
  * URL-guard posture for the native `web_fetch` tool, inherited from the
165
- * parent (resolveGuardPosture(config.mode) in setup.ts) so a sub-agent
168
+ * parent (resolveGuardPosture(config.mode) in turn-setup.ts) so a sub-agent
166
169
  * fetch is bounded exactly like a parent fetch.
167
170
  */
168
171
  readonly webFetchPosture: GuardPosture;
169
- readonly costCap?: CostCapMiddleware;
172
+ readonly costAdvisory?: CostAdvisoryMiddleware;
170
173
  /**
171
174
  * Builds a configured chat-model instance for a given model name. When
172
175
  * provided, sub-agents are compiled with the same proxy-aware model client
@@ -184,7 +187,7 @@ export interface SubagentTransformOptions {
184
187
  readonly shellEnv?: Record<string, string>;
185
188
  /**
186
189
  * Filesystem permission rules baked into each compiled sub-agent graph,
187
- * inherited from the parent's rules in setup.ts (plan mode's deny-all-writes
190
+ * inherited from the parent's rules in turn-setup.ts (plan mode's deny-all-writes
188
191
  * today). Required because deepagents' parent-permission inheritance covers
189
192
  * only spec-style sub-agents — pre-built CompiledSubAgents bypass it, so
190
193
  * without this a plan-mode sub-agent could still write (issue #255).
@@ -321,7 +324,7 @@ export async function transformSingleSubagent(
321
324
  }
322
325
 
323
326
  // web_fetch is unconditional — unlike think, it is a capability, not a
324
- // reasoning aid, and the parent always has it (setup.ts Step 11). A
327
+ // reasoning aid, and the parent always has it (turn-setup.ts `buildEngine`). A
325
328
  // sub-agent silently lacking web access the parent has would recreate the
326
329
  // harness-parity gap of issue #214 one level down.
327
330
  tools.push(createWebFetchTool({ posture: opts.webFetchPosture }) as unknown as StructuredTool);
@@ -415,64 +418,38 @@ export function filterMcpToolsForSubagent(
415
418
  // =========================================================================
416
419
 
417
420
  /**
418
- * Collect all unique skill refs across all subagents for batch fetching.
419
- *
420
- * Deduplicates by slug to minimize gRPC calls. Returns an array of refs
421
- * and the mapping from slug to original refs for distribution.
421
+ * The `## Skills` section of one sub-agent's system prompt, from the skills
422
+ * the runtime mounted for it. Empty when it has none.
422
423
  */
423
- export function collectAllSkillRefs(
424
- subAgents: readonly SubAgent[],
425
- ): { slug: string; ref: unknown }[] {
426
- const seen = new Set<string>();
427
- const unique: { slug: string; ref: unknown }[] = [];
428
-
429
- for (const sa of subAgents) {
430
- for (const ref of sa.skillRefs) {
431
- const slug = (ref as { slug?: string }).slug;
432
- if (slug && !seen.has(slug)) {
433
- seen.add(slug);
434
- unique.push({ slug, ref });
435
- }
436
- }
437
- }
438
-
439
- return unique;
424
+ export function resolveSubagentSkillPrompt(
425
+ subAgent: SubAgent,
426
+ skills: ReadonlyMap<string, readonly SkillMetadata[]>,
427
+ ): string {
428
+ return renderSkillsSection(skills.get(subAgent.name) ?? []);
440
429
  }
441
430
 
442
431
  /**
443
- * Resolve skills for a single subagent and return the prompt section.
444
- *
445
- * Looks up each of the subagent's skill_refs in the pre-fetched skills
446
- * collection and generates a prompt section containing activation
447
- * instructions and file paths.
448
- *
449
- * Returns empty string if no skills match or if the subagent has no skill_refs.
432
+ * Heuristic check for native extended thinking support. Models with thinking
433
+ * support don't need the explicit think tool. Read for the parent (does its
434
+ * graph carry `think`?) and inherited by every sub-agent that names no model
435
+ * of its own. Moved from `setup.ts` at S3 M2a: the compile step is where it
436
+ * is consumed, and the adapter's setup reads it from here too.
450
437
  */
451
- export function resolveSubagentSkillPrompt(
452
- subAgent: SubAgent,
453
- skillsBySlug: ReadonlyMap<string, { skill: unknown; path: string }>,
454
- ): string {
455
- if (subAgent.skillRefs.length === 0) return "";
438
+ export function modelHasNativeThinking(modelId: string): boolean {
439
+ const lower = modelId.toLowerCase();
456
440
 
457
- const matchedSkills: unknown[] = [];
458
- const matchedPaths = new Map<string, string>();
441
+ if (lower.includes("haiku")) return false;
442
+ if (lower.includes("gpt-4o-mini")) return false;
459
443
 
460
- for (const ref of subAgent.skillRefs) {
461
- const slug = (ref as { slug?: string }).slug;
462
- if (!slug) continue;
444
+ if (lower.includes("claude") && (
445
+ lower.includes("sonnet") || lower.includes("opus")
446
+ )) return true;
463
447
 
464
- const entry = skillsBySlug.get(slug);
465
- if (entry) {
466
- matchedSkills.push(entry.skill);
467
- const id = (entry.skill as { metadata?: { id?: string } }).metadata?.id;
468
- if (id) matchedPaths.set(id, entry.path);
469
- }
448
+ if (lower.includes("o1") || lower.includes("o3") || lower.includes("o4")) {
449
+ return true;
470
450
  }
471
451
 
472
- if (matchedSkills.length === 0) return "";
473
-
474
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
475
- return generatePromptSection(matchedSkills as any[], matchedPaths);
452
+ return false;
476
453
  }
477
454
 
478
455
  // =========================================================================
@@ -481,7 +458,7 @@ export function resolveSubagentSkillPrompt(
481
458
 
482
459
  /**
483
460
  * Select a sub-agent's deepagents backend, mirroring the parent's selection in
484
- * setup.ts along two independent axes:
461
+ * turn-setup.ts along two independent axes:
485
462
  *
486
463
  * - CAS observation (capture mode): when a shared observer is supplied, the
487
464
  * backend records pre-turn bytes of CAS-owned paths so the sub-agent's
@@ -535,7 +512,7 @@ async function buildSubagentBackend(opts: {
535
512
  export async function compileSubagents(
536
513
  transformed: readonly TransformedSubagent[],
537
514
  opts: {
538
- readonly costCap?: CostCapMiddleware;
515
+ readonly costAdvisory?: CostAdvisoryMiddleware;
539
516
  readonly approvalGate?: ApprovalGateConfig | null;
540
517
  readonly parentModelName: string;
541
518
  readonly workspaceRootDir: string;
@@ -562,7 +539,7 @@ export async function compileSubagents(
562
539
  // (issue #754): every graph speaks the virtual dialect, so every graph
563
540
  // carries the repair seam — matching the parent's composition.
564
541
  const middleware = buildSubAgentMiddleware({
565
- costCap: opts.costCap,
542
+ costAdvisory: opts.costAdvisory,
566
543
  approvalGate: opts.approvalGate,
567
544
  captureIgnored: !!opts.casObserver,
568
545
  pathNormalization: { rootDir: opts.workspaceRootDir },
@@ -623,7 +600,7 @@ export async function compileSubagents(
623
600
  /**
624
601
  * Transform proto SubAgents and compile into CompiledSubAgent instances.
625
602
  *
626
- * This is the main entry point called from setup.ts. It orchestrates:
603
+ * This is the main entry point called from turn-setup.ts. It orchestrates:
627
604
  * 1. Built-in subagent creation (explore, shell, general-purpose)
628
605
  * 2. Per-subagent transformation (proto → TransformedSubagent)
629
606
  * 3. MCP tool filtering per subagent
@@ -640,14 +617,14 @@ export async function transformAndCompileSubagents(
640
617
  parentMcpTools,
641
618
  parentMcpServerToolMap,
642
619
  parentMcpUsages,
643
- skillClient,
620
+ skills,
644
621
  workspaceBackend,
645
622
  approvalGate,
646
623
  casObserver,
647
624
  parentModelName,
648
625
  parentHasNativeThinking,
649
626
  webFetchPosture,
650
- costCap,
627
+ costAdvisory,
651
628
  modelFactory,
652
629
  shellEnv,
653
630
  permissions,
@@ -669,42 +646,6 @@ export async function transformAndCompileSubagents(
669
646
  webFetchPosture,
670
647
  );
671
648
 
672
- // Step 1b: Batch fetch all skills referenced by subagents
673
- const allSkillRefs = collectAllSkillRefs(subAgents);
674
- const skillsBySlug = new Map<string, { skill: unknown; path: string }>();
675
-
676
- if (allSkillRefs.length > 0) {
677
- try {
678
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
679
- const refs = allSkillRefs.map((r) => r.ref) as any[];
680
- const skills = await fetchSkillsByRefs(skillClient, refs);
681
-
682
- if (skills.length > 0) {
683
- // Runs after the parent's setup step 7b mounted its skills, so any
684
- // skill shared by parent and sub-agent is a cache hit here — the
685
- // hash-keyed marker turns the old double download into a no-op.
686
- // platformDir is an invariant: provisionWorkspace threads
687
- // ensurePlatformDir into every backend it constructs.
688
- const { paths: skillPaths } = await mountSkills(
689
- skillClient, skills, workspaceBackend.platformDir!,
690
- );
691
-
692
- for (const skill of skills) {
693
- const slug = (skill as { metadata?: { slug?: string } }).metadata?.slug;
694
- const id = (skill as { metadata?: { id?: string } }).metadata?.id;
695
- if (slug && id) {
696
- skillsBySlug.set(slug, { skill, path: skillPaths.get(id) ?? "" });
697
- }
698
- }
699
- console.log(
700
- `[subagent-transformer] Fetched ${skills.length} skill(s) for subagents`,
701
- );
702
- }
703
- } catch (err) {
704
- console.error(`[subagent-transformer] Failed to fetch skills for subagents: ${err}`);
705
- }
706
- }
707
-
708
649
  // Step 2: Transform proto subagents
709
650
  const transformed: TransformedSubagent[] = [];
710
651
 
@@ -735,7 +676,7 @@ export async function transformAndCompileSubagents(
735
676
  );
736
677
 
737
678
  // Resolve skills prompt section for this subagent
738
- const skillsSection = resolveSubagentSkillPrompt(subAgent, skillsBySlug);
679
+ const skillsSection = resolveSubagentSkillPrompt(subAgent, skills);
739
680
  const enhancedPrompt = skillsSection
740
681
  ? result.systemPrompt.replace(
741
682
  RESPONSE_RULES,
@@ -770,7 +711,7 @@ export async function transformAndCompileSubagents(
770
711
 
771
712
  // Step 4: Compile all subagents
772
713
  const compiled = await compileSubagents(allSpecs, {
773
- costCap,
714
+ costAdvisory,
774
715
  approvalGate,
775
716
  parentModelName,
776
717
  workspaceRootDir: workspaceBackend.rootDir,
@@ -41,7 +41,7 @@ import type {
41
41
  ToolTruncationConfig,
42
42
  PathNormalizationConfig,
43
43
  } from "../../middleware/types.js";
44
- import type { CostCapMiddleware } from "../../middleware/index.js";
44
+ import type { CostAdvisoryMiddleware } from "../../middleware/index.js";
45
45
  import { createPathNormalizationMiddleware } from "../../middleware/path-normalization.js";
46
46
  import { createLoopDetectionMiddleware } from "../../middleware/loop-detection.js";
47
47
  import { createToolTruncationMiddleware } from "../../middleware/tool-truncation.js";
@@ -57,7 +57,8 @@ const SUB_AGENT_ADVISORY_INTERVAL = 30;
57
57
  const SUB_AGENT_MAX_ADVISORIES = 4;
58
58
 
59
59
  export interface SubAgentMiddlewareOptions {
60
- readonly costCap?: CostCapMiddleware;
60
+ /** The parent's cost advisory, whose running total the sub-agent's calls advance. */
61
+ readonly costAdvisory?: CostAdvisoryMiddleware;
61
62
  readonly toolTruncation?: Partial<ToolTruncationConfig>;
62
63
  /**
63
64
  * Approval gate config inherited from the parent. When present, the sub-agent
@@ -142,8 +143,8 @@ export function buildSubAgentMiddleware(
142
143
  ));
143
144
  }
144
145
 
145
- if (options.costCap) {
146
- stack.push(options.costCap.forSubAgent());
146
+ if (options.costAdvisory) {
147
+ stack.push(options.costAdvisory.forSubAgent());
147
148
  }
148
149
 
149
150
  stack.push(createErrorHintsMiddleware());
@@ -0,0 +1,164 @@
1
+ /**
2
+ * The native deep-agent harness's settle — from a consumed stream to a
3
+ * `TurnOutcome`.
4
+ *
5
+ * In order: drain the inline publishes the stream fired and, on a finished
6
+ * turn, run the auto-publish safety net; settle the gate's unattended skips
7
+ * (the one settlement whose evidence exists only inside this harness); on
8
+ * the runtime's stop, mark in-flight sub-agent rows through the shared act
9
+ * and settle `interrupted` with nothing further; the graph's
10
+ * `structuredResponse` folded onto the status; the interrupts a completed
11
+ * stream left pending seeded as WAITING rows; and the outcome.
12
+ *
13
+ * What this module never does: write a phase, a terminal copy or
14
+ * `completedAt` — those are the runtime's (`harness/run-turn.ts`,
15
+ * `terminal-table.ts`); settle SKIP and REJECT rows — the runtime's
16
+ * (`harness/approval-decisions.ts`, after every outcome); withhold secret
17
+ * content — the runtime's chokepoint does it on every write; finalize the
18
+ * write-back — the runtime's epilogue; capture the turn's file changes or
19
+ * decide whether a review is pending — the runtime's (`harness/capture.ts`,
20
+ * once, over whatever the whole turn left on the tree, after this settle
21
+ * returns; S3 M4). It does mutate `sink.status`'s transcript rows, which
22
+ * are this harness's to write.
23
+ *
24
+ * The structured response is folded BEFORE the outcome is decided, so a turn
25
+ * the runtime then pauses for file review persists it and the pure
26
+ * file-review resume completes with it (the runtime's text fallback runs on
27
+ * the review-pending path too, Q-M4-8).
28
+ *
29
+ * Moved from `index.ts` (post-stream through the terminal arms) at S3 M2a;
30
+ * the capture boundary left for the runtime at M4.
31
+ */
32
+
33
+ import { create, type JsonObject } from "@bufbuild/protobuf";
34
+ import { AgentMessageSchema, ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
35
+ import { MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
36
+
37
+ import type { TurnInput, TurnOutcome, TurnSink } from "../../harness/types.js";
38
+ import { POLICY_ENGINE_VERSION, toProtoPolicySource } from "../../shared/approval-policy.js";
39
+ import { utcTimestamp } from "../../shared/status.js";
40
+ import { cancelInProgressSubAgentProtos } from "../../shared/subagent-rows.js";
41
+ import { classifyTool } from "../../shared/tool-kind.js";
42
+ import { captureApprovalArtifacts } from "./approval-file-change.js";
43
+ import { autoPublishWrittenFiles } from "./auto-publish.js";
44
+ import { detectPendingInterrupts, reconcileUnattendedSkips, type GraphStateSnapshot } from "./hitl.js";
45
+ import type { DeepAgentEngine } from "./turn-setup.js";
46
+ import type { DeepAgentStreamResult, DeepAgentTranscript } from "./turn-stream.js";
47
+
48
+ export interface DeepAgentSettleDeps {
49
+ readonly input: TurnInput;
50
+ readonly sink: TurnSink;
51
+ readonly engine: DeepAgentEngine;
52
+ readonly transcript: DeepAgentTranscript;
53
+ readonly stream: DeepAgentStreamResult;
54
+ }
55
+
56
+ export async function settleDeepAgentTurn(deps: DeepAgentSettleDeps): Promise<TurnOutcome> {
57
+ const { input, sink, engine, transcript, stream } = deps;
58
+ const { executionId } = input;
59
+ const { status } = sink;
60
+
61
+ // Drain the publishes the stream fired (fire-and-forget completions); the
62
+ // safety net that scans tool calls for files the stream missed runs only
63
+ // on a finished turn, as it always did.
64
+ if (stream.pendingPublishPromises.length > 0) {
65
+ await Promise.allSettled(stream.pendingPublishPromises);
66
+ }
67
+ if (stream.reason === "completed") {
68
+ try {
69
+ await autoPublishWrittenFiles(status, transcript.publisher);
70
+ } catch (err) {
71
+ console.warn(`[turn-settle] execution=${executionId} — auto-publish safety net error: ${err}`);
72
+ }
73
+ }
74
+ sink.recordActivity();
75
+
76
+ // Terminalize every tool call the gate auto-skipped under UNATTENDED
77
+ // approval mode (DD-014): the skip has no human decision behind it, so the
78
+ // runtime's terminalizer cannot see it; the gate's registry is this
79
+ // harness's evidence.
80
+ reconcileUnattendedSkips(status, engine.gate.unattendedSkips);
81
+
82
+ if (stream.reason === "interrupted") {
83
+ // A stopped turn aborted the graph run, so any sub-agent the parent had
84
+ // delegated is no longer executing: CANCELLED through the one shared act
85
+ // (the runtime marks them itself only on its thrown arms), its messages'
86
+ // streaming flags cleared. There is no review to open.
87
+ cancelInProgressSubAgentProtos(status.subAgentExecutions);
88
+ transcript.builder.finalizeSubAgentStreaming();
89
+ return { kind: "interrupted" };
90
+ }
91
+
92
+ // The graph's structured response, when the run surfaced one: folded now,
93
+ // so a turn the runtime pauses for review persists it and the pure
94
+ // file-review resume completes with it.
95
+ if (engine.hasStructuredOutput) {
96
+ const sr = stream.runOutput?.structuredResponse;
97
+ if (sr != null && typeof sr === "object" && !Array.isArray(sr)) {
98
+ status.structuredOutput = sr as JsonObject;
99
+ } else if (sr !== undefined) {
100
+ console.warn(`[turn-settle] structuredResponse is not a plain object for execution ${executionId}: type=${typeof sr}`);
101
+ }
102
+ }
103
+
104
+ if (stream.reason === "awaiting_approval") {
105
+ return { kind: "awaiting_approval" };
106
+ }
107
+
108
+ // A completed stream can still leave the graph interrupted at a gate whose
109
+ // tool start produced no row (the durable savers resume without a
110
+ // tool_started; the replay path never re-drives it): read the checkpoint
111
+ // once more and seed a WAITING row per pending interrupt. Skipped under
112
+ // the global bypass, where no gate is installed.
113
+ if (!engine.gate.globalBypass && (await seedPendingInterrupts(deps))) {
114
+ return { kind: "awaiting_approval" };
115
+ }
116
+
117
+ return { kind: "completed" };
118
+ }
119
+
120
+ /**
121
+ * Seed one WAITING_APPROVAL row per interrupt the graph left pending, on one
122
+ * AI message, with the sanitized args preview AND the redacted args read
123
+ * from the AI message in graph state (the single source of truth for the
124
+ * proposed call; issue #754: a placeholder without args rendered a pathless
125
+ * header). Returns whether any was seeded.
126
+ */
127
+ async function seedPendingInterrupts(deps: DeepAgentSettleDeps): Promise<boolean> {
128
+ const { input, sink, engine } = deps;
129
+ const graphState: GraphStateSnapshot = await engine.graph.getState(engine.langgraphConfig);
130
+ const pending = detectPendingInterrupts(graphState);
131
+ if (pending.length === 0) return false;
132
+
133
+ const graphMessages = (graphState.values as { messages?: unknown }).messages;
134
+ const aiMessages = Array.isArray(graphMessages) ? graphMessages : [];
135
+ console.log(`[turn-settle] Detected ${pending.length} pending interrupt(s) for execution ${input.executionId} — awaiting approval`);
136
+
137
+ const aiMsg = create(AgentMessageSchema, {
138
+ type: MessageType.MESSAGE_AI,
139
+ content: "",
140
+ timestamp: utcTimestamp(),
141
+ isStreaming: false,
142
+ });
143
+ for (const intr of pending) {
144
+ const toolCall = create(ToolCallSchema, {
145
+ id: intr.toolCallId,
146
+ name: intr.toolName,
147
+ status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
148
+ requiresApproval: true,
149
+ approvalMessage: intr.message,
150
+ approvalRequestedAt: utcTimestamp(),
151
+ mcpServerSlug: intr.mcpServerSlug,
152
+ startedAt: utcTimestamp(),
153
+ toolKind: classifyTool(intr.toolName, intr.mcpServerSlug),
154
+ approvalPolicySource: toProtoPolicySource(intr.policySource),
155
+ policyEngineVersion: intr.policySource ? POLICY_ENGINE_VERSION : "",
156
+ });
157
+ const { argsPreview, args } = captureApprovalArtifacts({ toolCallId: intr.toolCallId, messages: aiMessages });
158
+ if (argsPreview) toolCall.argsPreview = argsPreview;
159
+ if (args) toolCall.args = args as typeof toolCall.args;
160
+ aiMsg.toolCalls.push(toolCall);
161
+ }
162
+ sink.status.messages.push(aiMsg);
163
+ return true;
164
+ }