@stigmer/runner 3.15.3-dev.20260914121148 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (592) hide show
  1. package/README.md +2 -1
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__test-utils__/approval-contract/types.d.ts +1 -1
  4. package/dist/__test-utils__/hermetic-activity.d.ts +61 -7
  5. package/dist/__test-utils__/hermetic-activity.js +100 -9
  6. package/dist/__test-utils__/hermetic-activity.js.map +1 -1
  7. package/dist/__test-utils__/model-registry-fixture.d.ts +22 -3
  8. package/dist/__test-utils__/model-registry-fixture.js +22 -7
  9. package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
  10. package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +2 -2
  11. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +2 -2
  12. package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +61 -0
  13. package/dist/activities/execute-cursor/__test-utils__/fold.js +94 -0
  14. package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -0
  15. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +1 -1
  16. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
  17. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +47 -12
  18. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +41 -10
  19. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  20. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +15 -6
  21. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +17 -4
  22. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
  23. package/dist/activities/execute-cursor/adapter.d.ts +4 -4
  24. package/dist/activities/execute-cursor/adapter.js +4 -4
  25. package/dist/activities/execute-cursor/approval-policy.d.ts +10 -10
  26. package/dist/activities/execute-cursor/approval-policy.js +12 -23
  27. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  28. package/dist/activities/execute-cursor/approval-state.d.ts +35 -1
  29. package/dist/activities/execute-cursor/approval-state.js +65 -0
  30. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  31. package/dist/activities/execute-cursor/{message-translator.d.ts → boundary-rows.d.ts} +45 -341
  32. package/dist/activities/execute-cursor/boundary-rows.js +1018 -0
  33. package/dist/activities/execute-cursor/boundary-rows.js.map +1 -0
  34. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +1 -1
  35. package/dist/activities/execute-cursor/cursor-capabilities.js +1 -1
  36. package/dist/activities/execute-cursor/cursor-event-recorder.d.ts +33 -14
  37. package/dist/activities/execute-cursor/cursor-event-recorder.js +43 -21
  38. package/dist/activities/execute-cursor/cursor-event-recorder.js.map +1 -1
  39. package/dist/activities/execute-cursor/prompt-builder.d.ts +3 -3
  40. package/dist/activities/execute-cursor/prompt-builder.js +4 -4
  41. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  42. package/dist/activities/execute-cursor/service-tier.js +1 -2
  43. package/dist/activities/execute-cursor/service-tier.js.map +1 -1
  44. package/dist/activities/execute-cursor/sub-agent-steps.d.ts +79 -0
  45. package/dist/activities/execute-cursor/sub-agent-steps.js +180 -0
  46. package/dist/activities/execute-cursor/sub-agent-steps.js.map +1 -0
  47. package/dist/activities/execute-cursor/tool-result.d.ts +49 -0
  48. package/dist/activities/execute-cursor/tool-result.js +130 -0
  49. package/dist/activities/execute-cursor/tool-result.js.map +1 -0
  50. package/dist/activities/execute-cursor/translator.d.ts +178 -0
  51. package/dist/activities/execute-cursor/translator.js +485 -0
  52. package/dist/activities/execute-cursor/translator.js.map +1 -0
  53. package/dist/activities/execute-cursor/turn-boundary.d.ts +15 -5
  54. package/dist/activities/execute-cursor/turn-boundary.js +10 -14
  55. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
  56. package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
  57. package/dist/activities/execute-cursor/turn-settle.js +47 -34
  58. package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
  59. package/dist/activities/execute-cursor/turn-setup.d.ts +2 -2
  60. package/dist/activities/execute-cursor/turn-setup.js +5 -5
  61. package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
  62. package/dist/activities/execute-cursor/turn-stream.d.ts +23 -14
  63. package/dist/activities/execute-cursor/turn-stream.js +41 -28
  64. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  65. package/dist/activities/execute-cursor/turn.d.ts +4 -4
  66. package/dist/activities/execute-cursor/turn.js +5 -5
  67. package/dist/activities/execute-cursor/usage-pricing.d.ts +2 -2
  68. package/dist/activities/execute-cursor/usage-pricing.js +2 -2
  69. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +2 -2
  70. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +2 -2
  71. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +16 -11
  72. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +22 -10
  73. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -1
  74. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +1 -1
  75. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -1
  76. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +2 -3
  77. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +2 -3
  78. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -1
  79. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +12 -3
  80. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +18 -4
  81. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
  82. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.d.ts +10 -1
  83. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js +24 -11
  84. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js.map +1 -1
  85. package/dist/activities/execute-deep-agent/adapter.d.ts +1 -1
  86. package/dist/activities/execute-deep-agent/adapter.js +1 -1
  87. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +19 -19
  88. package/dist/activities/execute-deep-agent/approval-file-change.js +16 -15
  89. package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
  90. package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +2 -2
  91. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +2 -2
  92. package/dist/activities/execute-deep-agent/hitl.d.ts +2 -2
  93. package/dist/activities/execute-deep-agent/hitl.js +2 -2
  94. package/dist/activities/execute-deep-agent/inline-publisher.d.ts +13 -3
  95. package/dist/activities/execute-deep-agent/inline-publisher.js +3 -3
  96. package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
  97. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +3 -3
  98. package/dist/activities/execute-deep-agent/prompt-builder.js +6 -7
  99. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  100. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +16 -8
  101. package/dist/activities/execute-deep-agent/streaming-side-effects.js +20 -33
  102. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  103. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +3 -3
  104. package/dist/activities/execute-deep-agent/subagent-transformer.js +1 -1
  105. package/dist/activities/execute-deep-agent/translator.d.ts +134 -0
  106. package/dist/activities/execute-deep-agent/translator.js +418 -0
  107. package/dist/activities/execute-deep-agent/translator.js.map +1 -0
  108. package/dist/activities/execute-deep-agent/turn-settle.d.ts +13 -7
  109. package/dist/activities/execute-deep-agent/turn-settle.js +34 -45
  110. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -1
  111. package/dist/activities/execute-deep-agent/turn-setup.d.ts +8 -8
  112. package/dist/activities/execute-deep-agent/turn-setup.js +7 -7
  113. package/dist/activities/execute-deep-agent/turn-stream.d.ts +13 -10
  114. package/dist/activities/execute-deep-agent/turn-stream.js +44 -41
  115. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -1
  116. package/dist/activities/execute-deep-agent/turn.d.ts +3 -3
  117. package/dist/activities/execute-deep-agent/turn.js +3 -3
  118. package/dist/activities/generate-session-subject.d.ts +25 -4
  119. package/dist/activities/generate-session-subject.js +17 -7
  120. package/dist/activities/generate-session-subject.js.map +1 -1
  121. package/dist/client/stigmer-client.d.ts +17 -6
  122. package/dist/client/stigmer-client.js +47 -14
  123. package/dist/client/stigmer-client.js.map +1 -1
  124. package/dist/config.d.ts +6 -3
  125. package/dist/config.js +4 -1
  126. package/dist/config.js.map +1 -1
  127. package/dist/harness/approval-decisions.d.ts +1 -1
  128. package/dist/harness/approval-decisions.js +1 -1
  129. package/dist/harness/capabilities.d.ts +21 -11
  130. package/dist/harness/capabilities.js +2 -2
  131. package/dist/harness/capture.d.ts +4 -4
  132. package/dist/harness/capture.js +4 -4
  133. package/dist/harness/persist-chokepoint.d.ts +3 -3
  134. package/dist/harness/persist-chokepoint.js +3 -3
  135. package/dist/harness/registry.d.ts +2 -2
  136. package/dist/harness/registry.js +2 -2
  137. package/dist/harness/run-turn.d.ts +6 -4
  138. package/dist/harness/run-turn.js +31 -9
  139. package/dist/harness/run-turn.js.map +1 -1
  140. package/dist/harness/stop-controller.d.ts +1 -1
  141. package/dist/harness/stop-controller.js +1 -1
  142. package/dist/harness/terminal-table.d.ts +7 -7
  143. package/dist/harness/terminal-table.js +7 -7
  144. package/dist/harness/transcript/builder.d.ts +182 -0
  145. package/dist/harness/transcript/builder.js +693 -0
  146. package/dist/harness/transcript/builder.js.map +1 -0
  147. package/dist/harness/transcript/events.d.ts +218 -0
  148. package/dist/harness/transcript/events.js +50 -0
  149. package/dist/harness/transcript/events.js.map +1 -0
  150. package/dist/harness/transcript/state.d.ts +110 -0
  151. package/dist/harness/transcript/state.js +148 -0
  152. package/dist/harness/transcript/state.js.map +1 -0
  153. package/dist/harness/turn-context.d.ts +54 -38
  154. package/dist/harness/turn-context.js +42 -43
  155. package/dist/harness/turn-context.js.map +1 -1
  156. package/dist/harness/types.d.ts +63 -22
  157. package/dist/harness/types.js +12 -11
  158. package/dist/harness/types.js.map +1 -1
  159. package/dist/harness/usage-accumulator.d.ts +2 -2
  160. package/dist/harness/usage-accumulator.js +2 -2
  161. package/dist/harness-adapters.d.ts +5 -4
  162. package/dist/harness-adapters.js +5 -4
  163. package/dist/harness-adapters.js.map +1 -1
  164. package/dist/interceptors/run-credential-activity.d.ts +28 -0
  165. package/dist/interceptors/run-credential-activity.js +56 -0
  166. package/dist/interceptors/run-credential-activity.js.map +1 -0
  167. package/dist/middleware/approval-gate.d.ts +6 -0
  168. package/dist/middleware/approval-gate.js +7 -57
  169. package/dist/middleware/approval-gate.js.map +1 -1
  170. package/dist/middleware/cost-advisory.d.ts +3 -3
  171. package/dist/middleware/cost-advisory.js +3 -3
  172. package/dist/middleware/index.d.ts +1 -1
  173. package/dist/middleware/index.js +1 -1
  174. package/dist/runner-manager.js +10 -4
  175. package/dist/runner-manager.js.map +1 -1
  176. package/dist/shared/activity-input.d.ts +9 -0
  177. package/dist/shared/activity-input.js +17 -0
  178. package/dist/shared/activity-input.js.map +1 -1
  179. package/dist/shared/approval-policy.d.ts +53 -0
  180. package/dist/shared/approval-policy.js +76 -0
  181. package/dist/shared/approval-policy.js.map +1 -1
  182. package/dist/shared/args-preview.d.ts +45 -22
  183. package/dist/shared/args-preview.js +51 -41
  184. package/dist/shared/args-preview.js.map +1 -1
  185. package/dist/shared/attachment-resolver.d.ts +4 -4
  186. package/dist/shared/attachment-resolver.js +4 -4
  187. package/dist/shared/attachment-zip.d.ts +2 -2
  188. package/dist/shared/attachment-zip.js +2 -2
  189. package/dist/shared/channel-attachment.d.ts +8 -5
  190. package/dist/shared/channel-attachment.js +10 -6
  191. package/dist/shared/channel-attachment.js.map +1 -1
  192. package/dist/shared/cost-guard.d.ts +2 -2
  193. package/dist/shared/cost-guard.js +2 -2
  194. package/dist/shared/exact-apply.d.ts +1 -1
  195. package/dist/shared/exact-apply.js +1 -1
  196. package/dist/shared/execution-context.d.ts +2 -2
  197. package/dist/shared/execution-context.js +2 -2
  198. package/dist/shared/extract-structured-output.d.ts +2 -2
  199. package/dist/shared/extract-structured-output.js +2 -2
  200. package/dist/shared/filereview/cas-touched.d.ts +2 -2
  201. package/dist/shared/filereview/cas-touched.js +2 -2
  202. package/dist/shared/filereview/progress.d.ts +13 -0
  203. package/dist/shared/filereview/progress.js +13 -0
  204. package/dist/shared/filereview/progress.js.map +1 -1
  205. package/dist/shared/heartbeat.d.ts +1 -1
  206. package/dist/shared/heartbeat.js +1 -1
  207. package/dist/shared/llm-backend.d.ts +0 -4
  208. package/dist/shared/llm-backend.js +0 -4
  209. package/dist/shared/llm-backend.js.map +1 -1
  210. package/dist/shared/memory-attachment.d.ts +16 -9
  211. package/dist/shared/memory-attachment.js +18 -10
  212. package/dist/shared/memory-attachment.js.map +1 -1
  213. package/dist/shared/model-error.d.ts +1 -2
  214. package/dist/shared/model-error.js +1 -2
  215. package/dist/shared/model-error.js.map +1 -1
  216. package/dist/shared/persist-decision.d.ts +18 -24
  217. package/dist/shared/persist-decision.js +19 -11
  218. package/dist/shared/persist-decision.js.map +1 -1
  219. package/dist/shared/prompt-sections.d.ts +4 -4
  220. package/dist/shared/prompt-sections.js +4 -4
  221. package/dist/shared/run-credential-store.d.ts +32 -0
  222. package/dist/shared/run-credential-store.js +39 -0
  223. package/dist/shared/run-credential-store.js.map +1 -0
  224. package/dist/shared/run-credential.d.ts +61 -0
  225. package/dist/shared/run-credential.js +68 -0
  226. package/dist/shared/run-credential.js.map +1 -0
  227. package/dist/shared/skill-resolver.d.ts +3 -3
  228. package/dist/shared/skill-resolver.js +3 -3
  229. package/dist/shared/status-offload.d.ts +1 -1
  230. package/dist/shared/status-offload.js +2 -2
  231. package/dist/shared/status-offload.js.map +1 -1
  232. package/dist/shared/streaming-scheduler.d.ts +2 -7
  233. package/dist/shared/streaming-scheduler.js +6 -14
  234. package/dist/shared/streaming-scheduler.js.map +1 -1
  235. package/dist/shared/subagent-rows.d.ts +2 -2
  236. package/dist/shared/subagent-rows.js +2 -2
  237. package/dist/shared/synthesized-attachment.d.ts +30 -3
  238. package/dist/shared/synthesized-attachment.js +26 -0
  239. package/dist/shared/synthesized-attachment.js.map +1 -1
  240. package/dist/shared/todos.d.ts +3 -3
  241. package/dist/shared/todos.js +3 -3
  242. package/dist/shared/tool-row.d.ts +19 -1
  243. package/dist/shared/tool-row.js +36 -2
  244. package/dist/shared/tool-row.js.map +1 -1
  245. package/dist/shared/worker-shutdown.d.ts +1 -1
  246. package/dist/shared/worker-shutdown.js +1 -1
  247. package/dist/shared/workspace/session-provision.d.ts +1 -1
  248. package/dist/shared/workspace/session-provision.js +1 -1
  249. package/dist/shared/workspace/sources/empty.d.ts +1 -1
  250. package/dist/shared/workspace/sources/empty.js +1 -2
  251. package/dist/shared/workspace/sources/empty.js.map +1 -1
  252. package/dist/shared/workspace/sources/git.js +4 -4
  253. package/dist/shared/workspace/sources/git.js.map +1 -1
  254. package/dist/shared/workspace/sources/local-path.js +6 -6
  255. package/dist/shared/workspace/sources/local-path.js.map +1 -1
  256. package/dist/shared/workspace/stigmer-link.d.ts +1 -1
  257. package/dist/shared/workspace/stigmer-link.js +1 -1
  258. package/dist/shared/workspace/types.d.ts +2 -5
  259. package/dist/shared/workspace/types.js +0 -6
  260. package/dist/shared/workspace/types.js.map +1 -1
  261. package/dist/shared/workspace/writeback-coordinator.d.ts +17 -4
  262. package/dist/shared/workspace/writeback-coordinator.js +7 -9
  263. package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
  264. package/dist/worker.js +10 -3
  265. package/dist/worker.js.map +1 -1
  266. package/dist/workflow-source.d.ts +10 -0
  267. package/dist/workflow-source.js +12 -0
  268. package/dist/workflow-source.js.map +1 -1
  269. package/dist/workflows/execute-from-execution.d.ts +15 -0
  270. package/dist/workflows/execute-from-execution.js +11 -0
  271. package/dist/workflows/execute-from-execution.js.map +1 -1
  272. package/dist/workflows/index.d.ts +5 -3
  273. package/dist/workflows/index.js +5 -3
  274. package/dist/workflows/index.js.map +1 -1
  275. package/dist/workflows/interceptors/run-credential.d.ts +34 -0
  276. package/dist/workflows/interceptors/run-credential.js +71 -0
  277. package/dist/workflows/interceptors/run-credential.js.map +1 -0
  278. package/package.json +4 -4
  279. package/src/__test-utils__/__tests__/execution-record-barrier.test.ts +70 -0
  280. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +35 -1
  281. package/src/__test-utils__/approval-contract/contract.ts +1 -1
  282. package/src/__test-utils__/approval-contract/types.ts +1 -1
  283. package/src/__test-utils__/harness-boot-order-child.ts +1 -1
  284. package/src/__test-utils__/harness-contract/contract.ts +8 -8
  285. package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
  286. package/src/__test-utils__/harness-contract/runtime-contract.ts +52 -16
  287. package/src/__test-utils__/harness-contract/scripted-adapter.ts +47 -43
  288. package/src/__test-utils__/hermetic-activity.ts +113 -9
  289. package/src/__test-utils__/model-registry-fixture.ts +31 -7
  290. package/src/__test-utils__/module-specifiers.ts +32 -3
  291. package/src/__tests__/harness-boot-order.test.ts +1 -1
  292. package/src/__tests__/harness-contract.test.ts +1 -1
  293. package/src/__tests__/run-credential-e2e.test.ts +233 -0
  294. package/src/__tests__/run-credential-registration.test.ts +80 -0
  295. package/src/__tests__/runner-manager.test.ts +1 -1
  296. package/src/activities/__tests__/generate-session-subject-wire.test.ts +119 -0
  297. package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +1 -1
  298. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +2 -2
  299. package/src/activities/execute-cursor/__test-utils__/fold.ts +116 -0
  300. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +1 -1
  301. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +67 -17
  302. package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +19 -5
  303. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +2 -1
  304. package/src/activities/execute-cursor/__tests__/approval-state.test.ts +14 -21
  305. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +3 -3
  306. package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +2 -1
  307. package/src/activities/execute-cursor/__tests__/cursor-event-recorder.test.ts +142 -0
  308. package/src/activities/execute-cursor/__tests__/cursor-fetch-interceptor-bypass.test.ts +19 -8
  309. package/src/activities/execute-cursor/__tests__/cursor-sdk-auth-smoke.test.ts +10 -8
  310. package/src/activities/execute-cursor/__tests__/cursor-transcript-live.test.ts +298 -0
  311. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +4 -2
  312. package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +1 -1
  313. package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +1 -1
  314. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -1
  315. package/src/activities/execute-cursor/__tests__/hermetic/goldens/mcp-tool-call.status.json +71 -0
  316. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.status.json +73 -0
  317. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +78 -0
  318. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +72 -0
  319. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +72 -0
  320. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.status.json +109 -0
  321. package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.status.json +78 -0
  322. package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.status.json +119 -0
  323. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.status.json +68 -0
  324. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.status.json +67 -0
  325. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +1 -1
  326. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +7 -7
  327. package/src/activities/execute-cursor/__tests__/hermetic/mcp-tool-call.test.ts +146 -0
  328. package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +5 -5
  329. package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +2 -1
  330. package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +2 -1
  331. package/src/activities/execute-cursor/__tests__/hermetic/sdk-task-note.test.ts +122 -0
  332. package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +276 -0
  333. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +8 -8
  334. package/src/activities/execute-cursor/__tests__/hermetic/sub-agent-delegation.test.ts +196 -0
  335. package/src/activities/execute-cursor/__tests__/hermetic/thinking-turn.test.ts +145 -0
  336. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +1 -1
  337. package/src/activities/execute-cursor/__tests__/hermetic/todo-write.test.ts +165 -0
  338. package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +3 -3
  339. package/src/activities/execute-cursor/__tests__/hermetic/tool-error.test.ts +138 -0
  340. package/src/activities/execute-cursor/__tests__/hermetic/tool-only-step.test.ts +130 -0
  341. package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +13 -1
  342. package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +2 -2
  343. package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +43 -60
  344. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +23 -28
  345. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +2 -1
  346. package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +1 -1
  347. package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +5 -5
  348. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +11 -13
  349. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +8 -11
  350. package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +8 -22
  351. package/src/activities/execute-cursor/__tests__/translator.test.ts +594 -0
  352. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +8 -5
  353. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +87 -63
  354. package/src/activities/execute-cursor/adapter.ts +4 -4
  355. package/src/activities/execute-cursor/approval-policy.ts +12 -24
  356. package/src/activities/execute-cursor/approval-state.ts +66 -1
  357. package/src/activities/execute-cursor/boundary-rows.ts +1132 -0
  358. package/src/activities/execute-cursor/cursor-capabilities.ts +1 -1
  359. package/src/activities/execute-cursor/cursor-event-recorder.ts +57 -28
  360. package/src/activities/execute-cursor/fetch-interceptor.ts +1 -1
  361. package/src/activities/execute-cursor/http2-interceptor.ts +1 -1
  362. package/src/activities/execute-cursor/prompt-builder.ts +6 -6
  363. package/src/activities/execute-cursor/service-tier.ts +1 -2
  364. package/src/activities/execute-cursor/sub-agent-steps.ts +188 -0
  365. package/src/activities/execute-cursor/tool-result.ts +128 -0
  366. package/src/activities/execute-cursor/translator.ts +541 -0
  367. package/src/activities/execute-cursor/turn-boundary.ts +21 -14
  368. package/src/activities/execute-cursor/turn-settle.ts +46 -34
  369. package/src/activities/execute-cursor/turn-setup.ts +5 -5
  370. package/src/activities/execute-cursor/turn-stream.ts +49 -46
  371. package/src/activities/execute-cursor/turn.ts +5 -5
  372. package/src/activities/execute-cursor/usage-pricing.ts +2 -2
  373. package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +2 -2
  374. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +23 -11
  375. package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +1 -1
  376. package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +2 -3
  377. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +25 -4
  378. package/src/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.ts +25 -11
  379. package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +1 -1
  380. package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +1 -1
  381. package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +6 -17
  382. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +25 -8
  383. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +2 -7
  384. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +4 -14
  385. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +1 -5
  386. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +4 -7
  387. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +1 -5
  388. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +2 -9
  389. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +2 -9
  390. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +1 -4
  391. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +1 -4
  392. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +1 -4
  393. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +109 -76
  394. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +1 -5
  395. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +2 -10
  396. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +2 -10
  397. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +1 -5
  398. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +3 -6
  399. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +1 -4
  400. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +1 -4
  401. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.status.json +92 -0
  402. package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +3 -3
  403. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +9 -5
  404. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +3 -3
  405. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +3 -3
  406. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +7 -6
  407. package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +10 -11
  408. package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +4 -4
  409. package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +9 -8
  410. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +21 -13
  411. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +2 -2
  412. package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +7 -7
  413. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +28 -12
  414. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +21 -21
  415. package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -5
  416. package/src/activities/execute-deep-agent/__tests__/hermetic/write-todos.test.ts +160 -0
  417. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +35 -30
  418. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +3 -4
  419. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +12 -10
  420. package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +13 -3
  421. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +26 -18
  422. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +1 -1
  423. package/src/activities/execute-deep-agent/__tests__/{subagent-tracker.test.ts → translator-subagents.test.ts} +76 -57
  424. package/src/activities/execute-deep-agent/__tests__/{v3-status-builder.test.ts → translator-through-builder.test.ts} +213 -299
  425. package/src/activities/execute-deep-agent/__tests__/translator.test.ts +505 -0
  426. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +11 -29
  427. package/src/activities/execute-deep-agent/adapter.ts +1 -1
  428. package/src/activities/execute-deep-agent/approval-file-change.ts +20 -22
  429. package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +2 -2
  430. package/src/activities/execute-deep-agent/hitl.ts +2 -2
  431. package/src/activities/execute-deep-agent/inline-publisher.ts +16 -5
  432. package/src/activities/execute-deep-agent/prompt-builder.ts +6 -7
  433. package/src/activities/execute-deep-agent/streaming-side-effects.ts +22 -31
  434. package/src/activities/execute-deep-agent/subagent-transformer.ts +3 -3
  435. package/src/activities/execute-deep-agent/translator.ts +463 -0
  436. package/src/activities/execute-deep-agent/turn-settle.ts +35 -43
  437. package/src/activities/execute-deep-agent/turn-setup.ts +8 -8
  438. package/src/activities/execute-deep-agent/turn-stream.ts +53 -51
  439. package/src/activities/execute-deep-agent/turn.ts +3 -3
  440. package/src/activities/generate-session-subject.ts +29 -4
  441. package/src/client/__tests__/stigmer-client.test.ts +92 -0
  442. package/src/client/stigmer-client.ts +48 -14
  443. package/src/config.ts +6 -3
  444. package/src/harness/README.md +335 -0
  445. package/src/harness/__tests__/approval-decisions.test.ts +2 -2
  446. package/src/harness/__tests__/capture.test.ts +3 -3
  447. package/src/harness/__tests__/import-direction.test.ts +3 -2
  448. package/src/harness/__tests__/mount-skills.test.ts +4 -1
  449. package/src/harness/__tests__/readme-index.test.ts +339 -0
  450. package/src/harness/__tests__/run-turn.test.ts +131 -6
  451. package/src/harness/__tests__/transcript-is-engine-free.test.ts +83 -0
  452. package/src/harness/__tests__/transcript-writers.test.ts +191 -0
  453. package/src/harness/__tests__/turn-attachments-vision.test.ts +5 -2
  454. package/src/harness/__tests__/turn-context.test.ts +5 -5
  455. package/src/harness/approval-decisions.ts +1 -1
  456. package/src/harness/capabilities.ts +21 -11
  457. package/src/harness/capture.ts +4 -4
  458. package/src/harness/persist-chokepoint.ts +3 -3
  459. package/src/harness/registry.ts +2 -2
  460. package/src/harness/run-turn.ts +33 -9
  461. package/src/harness/stop-controller.ts +1 -1
  462. package/src/harness/terminal-table.ts +7 -7
  463. package/src/harness/transcript/__tests__/builder.test.ts +975 -0
  464. package/src/harness/transcript/__tests__/state.test.ts +143 -0
  465. package/src/harness/transcript/builder.ts +755 -0
  466. package/src/harness/transcript/events.ts +262 -0
  467. package/src/harness/transcript/state.ts +167 -0
  468. package/src/harness/turn-context.ts +61 -46
  469. package/src/harness/types.ts +64 -22
  470. package/src/harness/usage-accumulator.ts +2 -2
  471. package/src/harness-adapters.ts +5 -4
  472. package/src/interceptors/__tests__/run-credential-activity.test.ts +133 -0
  473. package/src/interceptors/run-credential-activity.ts +67 -0
  474. package/src/middleware/__tests__/cost-advisory.test.ts +2 -2
  475. package/src/middleware/approval-gate.ts +7 -74
  476. package/src/middleware/cost-advisory.ts +3 -3
  477. package/src/middleware/index.ts +1 -1
  478. package/src/runner-manager.ts +14 -4
  479. package/src/shared/__tests__/approval-policy.test.ts +45 -0
  480. package/src/shared/__tests__/args-preview.test.ts +40 -20
  481. package/src/shared/__tests__/attachment-naming.test.ts +1 -1
  482. package/src/shared/__tests__/attachment-resolver.test.ts +5 -5
  483. package/src/shared/__tests__/attachment-zip.test.ts +1 -1
  484. package/src/shared/__tests__/blueprint-resolver.test.ts +1 -1
  485. package/src/shared/__tests__/channel-attachment.test.ts +12 -0
  486. package/src/shared/__tests__/cost-guard.test.ts +1 -1
  487. package/src/shared/__tests__/exact-apply.test.ts +2 -1
  488. package/src/shared/__tests__/memory-attachment.test.ts +17 -0
  489. package/src/shared/__tests__/persist-decision.test.ts +19 -33
  490. package/src/shared/__tests__/prompt-sections.test.ts +1 -1
  491. package/src/shared/__tests__/run-credential.test.ts +111 -0
  492. package/src/shared/__tests__/stamp-flowed-rows.test.ts +1 -1
  493. package/src/shared/__tests__/status-offload.test.ts +1 -1
  494. package/src/shared/__tests__/streaming-scheduler.test.ts +8 -9
  495. package/src/shared/__tests__/todos.test.ts +1 -1
  496. package/src/shared/__tests__/tool-row.test.ts +1 -1
  497. package/src/shared/activity-input.ts +21 -0
  498. package/src/shared/approval-policy.ts +95 -0
  499. package/src/shared/args-preview.ts +51 -42
  500. package/src/shared/attachment-resolver.ts +4 -4
  501. package/src/shared/attachment-zip.ts +2 -2
  502. package/src/shared/channel-attachment.ts +14 -6
  503. package/src/shared/cost-guard.ts +2 -2
  504. package/src/shared/exact-apply.ts +1 -1
  505. package/src/shared/execution-context.ts +2 -2
  506. package/src/shared/extract-structured-output.ts +2 -2
  507. package/src/shared/filereview/__tests__/capture.test.ts +9 -5
  508. package/src/shared/filereview/__tests__/git-substrate.test.ts +4 -1
  509. package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +3 -3
  510. package/src/shared/filereview/cas-touched.ts +2 -2
  511. package/src/shared/filereview/progress.ts +13 -0
  512. package/src/shared/heartbeat.ts +1 -1
  513. package/src/shared/llm-backend.ts +0 -4
  514. package/src/shared/memory-attachment.ts +22 -10
  515. package/src/shared/model-error.ts +1 -2
  516. package/src/shared/persist-decision.ts +19 -28
  517. package/src/shared/prompt-sections.ts +4 -4
  518. package/src/shared/run-credential-store.ts +45 -0
  519. package/src/shared/run-credential.ts +70 -0
  520. package/src/shared/skill-resolver.ts +3 -3
  521. package/src/shared/status-offload.ts +2 -2
  522. package/src/shared/streaming-scheduler.ts +8 -13
  523. package/src/shared/subagent-rows.ts +2 -2
  524. package/src/shared/synthesized-attachment.ts +38 -3
  525. package/src/shared/todos.ts +3 -3
  526. package/src/shared/tool-row.ts +38 -2
  527. package/src/shared/worker-shutdown.ts +1 -1
  528. package/src/shared/workspace/__tests__/git-source.test.ts +3 -3
  529. package/src/shared/workspace/__tests__/provisioner.test.ts +5 -5
  530. package/src/shared/workspace/__tests__/session-provision.test.ts +2 -2
  531. package/src/shared/workspace/__tests__/writeback-coordinator.integration.test.ts +8 -9
  532. package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +25 -25
  533. package/src/shared/workspace/provisioner.ts +1 -1
  534. package/src/shared/workspace/session-provision.ts +1 -1
  535. package/src/shared/workspace/sources/empty.ts +2 -2
  536. package/src/shared/workspace/sources/git.ts +3 -4
  537. package/src/shared/workspace/sources/local-path.ts +5 -6
  538. package/src/shared/workspace/stigmer-link.ts +1 -1
  539. package/src/shared/workspace/types.ts +2 -5
  540. package/src/shared/workspace/writeback-coordinator.ts +23 -12
  541. package/src/worker.ts +15 -3
  542. package/src/workflow-source.ts +15 -0
  543. package/src/workflows/__tests__/run-credential-interceptor.test.ts +178 -0
  544. package/src/workflows/execute-from-execution.ts +17 -0
  545. package/src/workflows/index.ts +5 -3
  546. package/src/workflows/interceptors/run-credential.ts +101 -0
  547. package/dist/activities/execute-cursor/delta-enricher.d.ts +0 -87
  548. package/dist/activities/execute-cursor/delta-enricher.js +0 -265
  549. package/dist/activities/execute-cursor/delta-enricher.js.map +0 -1
  550. package/dist/activities/execute-cursor/message-translator.js +0 -2040
  551. package/dist/activities/execute-cursor/message-translator.js.map +0 -1
  552. package/dist/activities/execute-cursor/todo-tracker.d.ts +0 -40
  553. package/dist/activities/execute-cursor/todo-tracker.js +0 -80
  554. package/dist/activities/execute-cursor/todo-tracker.js.map +0 -1
  555. package/dist/activities/execute-deep-agent/execution-state.d.ts +0 -54
  556. package/dist/activities/execute-deep-agent/execution-state.js +0 -68
  557. package/dist/activities/execute-deep-agent/execution-state.js.map +0 -1
  558. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +0 -65
  559. package/dist/activities/execute-deep-agent/status-builder-shared.js +0 -90
  560. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +0 -1
  561. package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +0 -113
  562. package/dist/activities/execute-deep-agent/subagent-tracker.js +0 -400
  563. package/dist/activities/execute-deep-agent/subagent-tracker.js.map +0 -1
  564. package/dist/activities/execute-deep-agent/v3-events.d.ts +0 -102
  565. package/dist/activities/execute-deep-agent/v3-events.js +0 -35
  566. package/dist/activities/execute-deep-agent/v3-events.js.map +0 -1
  567. package/dist/activities/execute-deep-agent/v3-protocol-normalizer.d.ts +0 -15
  568. package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js +0 -235
  569. package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js.map +0 -1
  570. package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +0 -111
  571. package/dist/activities/execute-deep-agent/v3-status-builder.js +0 -457
  572. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +0 -1
  573. package/dist/shared/execution-status-writer.d.ts +0 -31
  574. package/dist/shared/execution-status-writer.js +0 -43
  575. package/dist/shared/execution-status-writer.js.map +0 -1
  576. package/src/activities/execute-cursor/__tests__/delta-enricher.test.ts +0 -310
  577. package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -1033
  578. package/src/activities/execute-cursor/__tests__/todo-tracker.test.ts +0 -498
  579. package/src/activities/execute-cursor/delta-enricher.ts +0 -307
  580. package/src/activities/execute-cursor/message-translator.ts +0 -2319
  581. package/src/activities/execute-cursor/todo-tracker.ts +0 -91
  582. package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -148
  583. package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -154
  584. package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +0 -47
  585. package/src/activities/execute-deep-agent/__tests__/v3-protocol-normalizer.test.ts +0 -324
  586. package/src/activities/execute-deep-agent/execution-state.ts +0 -78
  587. package/src/activities/execute-deep-agent/status-builder-shared.ts +0 -142
  588. package/src/activities/execute-deep-agent/subagent-tracker.ts +0 -479
  589. package/src/activities/execute-deep-agent/v3-events.ts +0 -153
  590. package/src/activities/execute-deep-agent/v3-protocol-normalizer.ts +0 -264
  591. package/src/activities/execute-deep-agent/v3-status-builder.ts +0 -565
  592. package/src/shared/execution-status-writer.ts +0 -56
@@ -0,0 +1,541 @@
1
+ /**
2
+ * CursorTranslator — the Cursor harness's translator: the `@cursor/sdk`'s two
3
+ * event channels in, the canonical `TranscriptEvent` union out
4
+ * (`harness/transcript/events.ts`).
5
+ *
6
+ * The one module that knows the SDK's wire shape:
7
+ * the shared `TranscriptBuilder` folds what comes out of here and nothing of
8
+ * the engine reaches it otherwise. Until #1097 the Cursor harness folded its
9
+ * own transcript — the message accumulator (the second copy of the folding
10
+ * rule the memo counted), the delta enricher (row writes from the delta
11
+ * channel) and the todo tracker (a third writer of `status.todos`) — and
12
+ * every rule they held
13
+ * is either the builder's now or answered here. The same word, the same
14
+ * `translate(raw)` signature and the same seat in its adapter as
15
+ * `execute-deep-agent/translator.ts`, so a third harness's author finds one
16
+ * shape in both.
17
+ *
18
+ * TWO CHANNELS, ONE DISCIPLINE. The SDK streams `SDKMessage`s from
19
+ * `run.stream()` (the source of truth for messages and rows) and fires
20
+ * `InteractionUpdate`s through `onDelta` between them (tool-call timings, live
21
+ * shell output, a completion's status — facts the stream delivers later or
22
+ * never). A delta lands while the loop may be awaiting a persist, and a row
23
+ * write mid-persist would land on a row the offload is replacing, so this
24
+ * translator never hands a delta's events to anyone
25
+ * directly: {@link observeDelta} QUEUES them and the loop applies
26
+ * {@link drainDeltas} after each stream event, and once more before
27
+ * `finalize()`. A delta for a call the stream has not announced yet (the
28
+ * output that beats the `running` event) is HELD and replayed right after the
29
+ * `tool_started` that announces it. Because the fold is later than
30
+ * the observation, a completion learned from a delta carries `observedAt` —
31
+ * the instant the tool actually finished — and the builder stamps that, not
32
+ * the fold's moment. Rows are CREATED by the stream alone: the
33
+ * delta channel amends (output, completion), never announces.
34
+ *
35
+ * WHAT THIS TRANSLATOR ANSWERS, per event:
36
+ *
37
+ * - The MESSAGE BOUNDARY. Cursor has one `run_id` per `send()`,
38
+ * and its message boundary is a tool call: text after a tool call is a new
39
+ * message. So `runId` here is a minted SEGMENT id, `<run_id>:<n>`, advanced
40
+ * on the first text or thinking after a tool call; a tool call emits
41
+ * `message_finish` for the open segment (closing its text and thinking).
42
+ * - The row's IDENTITY. An MCP call arrives as `name: "mcp"` with the real
43
+ * tool packed in `args` (`{ providerIdentifier, toolName, args }`); the row
44
+ * is the inner tool. A resumed agent re-runs an approved tool under a
45
+ * BRAND-NEW call id; the seeded WAITING row it belongs to is found by the
46
+ * identity token the hook and the grants already share, the
47
+ * `tool_started` is emitted with the SEEDED id so the builder's by-id flip
48
+ * does the rest, and every later event for the new id is aliased onto it.
49
+ * The seeded rows that can match exist only in the seed (nothing created
50
+ * mid-stream is WAITING until the boundary runs), so they are indexed once
51
+ * at construction and consumed on match (a declined row is a
52
+ * closed gate and never matched).
53
+ * - The GATE and the PROVENANCE. `gate` is the POLICY's word —
54
+ * this MCP tool's merged policy, or this built-in's category, requires
55
+ * approval — resolved exactly as the accumulator did, lease- and
56
+ * bypass-blind; it is NOT the hook's verdict (the hook has arms this side
57
+ * cannot evaluate: capture mode, grants, bypass, secret blocks — the
58
+ * lesson behind dropping a parked-at-creation arm that had no producer).
59
+ * A gated call that STARTED runs until the boundary parks
60
+ * it through `approval_proposed`. Provenance is the shared read-side
61
+ * `resolveApprovalProvenance` over the same policies and the run's leases.
62
+ * - The RESULT string (`tool-result.ts`): a failure's text is its `error`
63
+ * alone.
64
+ * - The SUB-AGENT: a `task` tool call opens a sub-agent keyed by
65
+ * the call id (`sub_agent_started` before the row's own `tool_started`);
66
+ * its completion emits the row's `tool_finished`, the child's transcript
67
+ * as scoped events (`sub-agent-steps.ts` — Cursor delivers it whole, at
68
+ * completion), then `sub_agent_finished` with the same output string; an
69
+ * error, `tool_error` then `sub_agent_failed`.
70
+ * - The `task` SDK event → `system_note`; a todo write is an
71
+ * ordinary tool call the builder keys on `ToolKind.TODO` and projects;
72
+ * `system`, `status`, `user`, `request` and `usage` carry no
73
+ * transcript fact (usage is the loop's, priced from the `turn-ended`
74
+ * delta in `turn-stream.ts` — the same division as native's `usageOf`).
75
+ *
76
+ * Stateful, one per turn, shared by the primary stream and the recovery
77
+ * retries exactly as the accumulator was (the segment map is keyed by
78
+ * `run_id`, and a retry's send has its own).
79
+ */
80
+
81
+ import type { InteractionUpdate, SDKMessage } from "@cursor/sdk";
82
+ import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
83
+ import { ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
84
+ import type { GateAnswer, ToolStartedEvent, TranscriptEvent } from "../../harness/transcript/events.js";
85
+ import { resolveApprovalProvenance, type MergedToolPolicy, type PolicySource } from "../../shared/approval-policy.js";
86
+ import { utcTimestamp } from "../../shared/status.js";
87
+ import { isDeclinedRow } from "../../shared/tool-row.js";
88
+ import type { ToolApprovalCategory } from "../../shared/tool-kind.js";
89
+ import { builtInRequiresApproval, getBuiltInApprovalMessage, lookupMcpToolPolicy, resolveApprovalMessage } from "./approval-policy.js";
90
+ import { toolCallIdentityToken, toolIdentity, primaryToken } from "./approval-state.js";
91
+ import { contentDigest } from "../../shared/file-tools.js";
92
+ import { subAgentStepEvents } from "./sub-agent-steps.js";
93
+ import { toResultString } from "./tool-result.js";
94
+
95
+ type ToolCallEvent = Extract<SDKMessage, { type: "tool_call" }>;
96
+
97
+ /** The delegation tool: the one tool name this translator knows, because its start opens a sub-agent. */
98
+ const TASK_TOOL = "task";
99
+
100
+ /** The run's approval posture the translator answers `gate` and `provenance` from. */
101
+ export interface CursorTranslatorOptions {
102
+ /** The merged four-level MCP policy map (`mergeApprovalPolicies`). */
103
+ readonly policies: ReadonlyMap<string, MergedToolPolicy>;
104
+ /** The run-lifetime leases: the pre-armed global bypass and the built-in categories approved for the run. */
105
+ readonly leases: { readonly global: boolean; readonly categories: ReadonlySet<ToolApprovalCategory> };
106
+ /** The transcript as seeded at turn start (`status.messages`): the WAITING rows a resumed agent's re-issued call may belong to. */
107
+ readonly seeded: readonly AgentMessage[];
108
+ }
109
+
110
+ /** The text and thinking of one Cursor run, cut into messages by its tool calls. */
111
+ interface Segment {
112
+ /** How many tool calls have cut this run so far; part of the minted `runId`. */
113
+ n: number;
114
+ /** A `message_start` was emitted for the current segment and no `message_finish` yet. */
115
+ open: boolean;
116
+ /** A tool call closed the current segment; the next text or thinking opens the next one. */
117
+ advance: boolean;
118
+ }
119
+
120
+ // ── The translator ────────────────────────────────────────────────
121
+
122
+ export class CursorTranslator {
123
+ private readonly segments = new Map<string, Segment>();
124
+ /** Row ids the stream has announced (a `tool_started` was emitted for them). */
125
+ private readonly announced = new Set<string>();
126
+ /** A resumed agent's fresh call id → the seeded row it re-runs. */
127
+ private readonly aliases = new Map<string, string>();
128
+ /** Identity token → the seeded WAITING rows with it, in transcript order; consumed on match. */
129
+ private readonly resumable = new Map<string, string[]>();
130
+ /** The `task` rows whose completion closes a sub-agent. */
131
+ private readonly taskCalls = new Set<string>();
132
+ /** Delta-derived events for announced rows, awaiting the loop's drain. */
133
+ private queue: TranscriptEvent[] = [];
134
+ /**
135
+ * Delta-derived events for calls the stream has not announced yet, keyed by
136
+ * the delta's own call id and kept as makers: the row they belong to is
137
+ * known only when the stream announces the call (a resumed agent's re-run
138
+ * is aliased onto a seeded row then), so each is materialized at replay.
139
+ */
140
+ private readonly held = new Map<string, Array<(rowId: string) => TranscriptEvent>>();
141
+ /** The most recent shell call the delta channel started — the home of an output delta that names no call. */
142
+ private lastShellCallId: string | undefined;
143
+
144
+ constructor(private readonly options: CursorTranslatorOptions) {
145
+ for (const message of options.seeded) {
146
+ for (const tc of message.toolCalls) {
147
+ if (tc.status !== ToolCallStatus.TOOL_CALL_WAITING_APPROVAL || isDeclinedRow(tc)) continue;
148
+ const token = toolCallIdentityToken(tc);
149
+ const ids = this.resumable.get(token);
150
+ if (ids) ids.push(tc.id);
151
+ else this.resumable.set(token, [tc.id]);
152
+ }
153
+ }
154
+ }
155
+
156
+ /** One stream event to its canonical events — `translate(raw)` is the one signature every harness's translator shares. */
157
+ translate(event: SDKMessage): TranscriptEvent[] {
158
+ switch (event.type) {
159
+ case "assistant": {
160
+ const text = event.message.content
161
+ .filter((b): b is { type: "text"; text: string } => b.type === "text")
162
+ .map((b) => b.text)
163
+ .join("");
164
+ if (!text) return [];
165
+ const { runId, opened } = this.openSegment(event.run_id);
166
+ return [...opened, { kind: "text_delta", runId, text }];
167
+ }
168
+ case "thinking": {
169
+ if (!event.text) return [];
170
+ const { runId, opened } = this.openSegment(event.run_id);
171
+ return [...opened, { kind: "reasoning_delta", runId, text: event.text }];
172
+ }
173
+ case "tool_call":
174
+ return this.translateToolCall(event);
175
+ case "task":
176
+ return event.text ? [{ kind: "system_note", text: event.text }] : [];
177
+ // Carried by the wire, not by the transcript (see the header).
178
+ case "system":
179
+ case "status":
180
+ case "user":
181
+ case "request":
182
+ case "usage":
183
+ return [];
184
+ default: {
185
+ const exhaustive: never = event;
186
+ throw new Error(`CursorTranslator: unknown SDK message ${String((exhaustive as { type: string }).type)}`);
187
+ }
188
+ }
189
+ }
190
+
191
+ /**
192
+ * One delta, queued — never applied here (see the header). The loop drains
193
+ * the queue after the stream event it is processing.
194
+ */
195
+ observeDelta(update: InteractionUpdate): void {
196
+ switch (update.type) {
197
+ case "tool-call-started":
198
+ // The row's `startedAt` is the stream's (every row has one from its
199
+ // first stream event); the delta only tells us which shell an
200
+ // output delta that names no call belongs to.
201
+ if (update.toolCall.type === "shell") this.lastShellCallId = update.callId;
202
+ return;
203
+ case "shell-output-delta": {
204
+ // Right by the SDK's type and exercised by the scripted double; the
205
+ // live run behind #1097 (SDK 1.0.31) sent no `shell-output-delta` for
206
+ // a 1.2 s or a 4 s command, so until the SDK sends one this arm has
207
+ // no live evidence of its own.
208
+ const text = shellOutputText(update.event);
209
+ const callId = shellOutputCallId(update.event) ?? this.lastShellCallId;
210
+ if (!text || !callId) return;
211
+ this.enqueue(callId, (rowId) => ({ kind: "tool_output_delta", callId: rowId, delta: text }));
212
+ return;
213
+ }
214
+ case "tool-call-completed": {
215
+ // The completion, at the instant it was observed, with the
216
+ // OUTCOME the typed delta carries (since #1097): a `result.status`
217
+ // of `error` is a failure, not a completion — until then the enricher
218
+ // promoted every completion delta to COMPLETED, and a tool that failed
219
+ // ended COMPLETED carrying an `error` when the delta beat the stream's
220
+ // own `error` event. The stream's event follows with the text or the
221
+ // result, and the builder's upsert merges the two; an
222
+ // empty message or result never clears anything.
223
+ const observedAt = utcTimestamp();
224
+ const failed = completionFailed(update.toolCall);
225
+ this.enqueue(update.callId, (rowId) =>
226
+ failed
227
+ ? { kind: "tool_error", callId: rowId, message: "", observedAt }
228
+ : { kind: "tool_finished", callId: rowId, result: "", observedAt },
229
+ );
230
+ return;
231
+ }
232
+ default:
233
+ // `turn-ended` (the loop prices it), `text-delta`/`thinking-delta` (the
234
+ // stream carries the text), `thinking-completed`, the step and summary
235
+ // markers, `partial-tool-call`: no transcript fact.
236
+ return;
237
+ }
238
+ }
239
+
240
+ /** The delta-derived events ready to apply, in arrival order; empties the queue. */
241
+ drainDeltas(): TranscriptEvent[] {
242
+ const out = this.queue;
243
+ this.queue = [];
244
+ return out;
245
+ }
246
+
247
+ // ── Messages ────────────────────────────────────────────────────
248
+
249
+ /** The segment id text or thinking streams into now, and the `message_start` that opens it if none is open. */
250
+ private openSegment(runId: string): { runId: string; opened: TranscriptEvent[] } {
251
+ const segment = this.segmentOf(runId);
252
+ if (segment.advance) {
253
+ segment.n += 1;
254
+ segment.advance = false;
255
+ }
256
+ const id = segmentId(runId, segment.n);
257
+ if (segment.open) return { runId: id, opened: [] };
258
+ segment.open = true;
259
+ return { runId: id, opened: [{ kind: "message_start", runId: id }] };
260
+ }
261
+
262
+ /** A tool call ends the open segment: its text and thinking are finished, and the next text starts a new message. */
263
+ private closeSegment(runId: string): TranscriptEvent[] {
264
+ const segment = this.segmentOf(runId);
265
+ segment.advance = true;
266
+ if (!segment.open) return [];
267
+ segment.open = false;
268
+ return [{ kind: "message_finish", runId: segmentId(runId, segment.n) }];
269
+ }
270
+
271
+ private segmentOf(runId: string): Segment {
272
+ let segment = this.segments.get(runId);
273
+ if (!segment) {
274
+ segment = { n: 0, open: false, advance: false };
275
+ this.segments.set(runId, segment);
276
+ }
277
+ return segment;
278
+ }
279
+
280
+ // ── Tool calls ──────────────────────────────────────────────────
281
+
282
+ private translateToolCall(event: ToolCallEvent): TranscriptEvent[] {
283
+ const out: TranscriptEvent[] = this.closeSegment(event.run_id);
284
+
285
+ const mcp = extractMcpToolDetails(event);
286
+ const name = mcp?.toolName ?? event.name;
287
+ const mcpServerSlug = mcp?.providerIdentifier ?? "";
288
+ const input = mcp?.innerArgs ?? parseArgs(event.args);
289
+
290
+ const rowId = this.resolveRowId(event.call_id, name, mcpServerSlug, input);
291
+ const isTask = event.name === TASK_TOOL;
292
+
293
+ if (!this.announced.has(rowId)) {
294
+ if (isTask) {
295
+ this.taskCalls.add(rowId);
296
+ out.push({
297
+ kind: "sub_agent_started",
298
+ subAgentId: rowId,
299
+ name: extractSubagentName(event.args),
300
+ subject: stringArg(event.args, "description"),
301
+ input: stringArg(event.args, "prompt"),
302
+ });
303
+ }
304
+ this.announced.add(rowId);
305
+ }
306
+ out.push(this.toolStarted(rowId, name, mcp !== undefined, mcpServerSlug, input));
307
+ // Deltas that arrived before the stream announced this call follow its
308
+ // start, targeted at the row it resolved to.
309
+ const heldMakers = this.held.get(event.call_id);
310
+ if (heldMakers) {
311
+ this.held.delete(event.call_id);
312
+ for (const make of heldMakers) this.queue.push(make(rowId));
313
+ }
314
+
315
+ switch (event.status) {
316
+ case "running":
317
+ break;
318
+ case "completed": {
319
+ const result = toResultString(event.result);
320
+ out.push({ kind: "tool_finished", callId: rowId, result });
321
+ if (this.taskCalls.has(rowId)) {
322
+ out.push(...subAgentStepEvents(event.result, rowId));
323
+ out.push({ kind: "sub_agent_finished", subAgentId: rowId, output: result });
324
+ }
325
+ break;
326
+ }
327
+ case "error": {
328
+ const message = typeof event.result === "string" ? event.result : "Tool call failed";
329
+ out.push({ kind: "tool_error", callId: rowId, message });
330
+ if (this.taskCalls.has(rowId)) {
331
+ out.push({ kind: "sub_agent_failed", subAgentId: rowId, error: message });
332
+ }
333
+ break;
334
+ }
335
+ default: {
336
+ const exhaustive: never = event.status;
337
+ throw new Error(`CursorTranslator: unknown tool_call status ${String(exhaustive)}`);
338
+ }
339
+ }
340
+ return out;
341
+ }
342
+
343
+ /**
344
+ * The row a call's events fold into: the id the stream gave it, unless the
345
+ * call is a resumed agent's re-run of a seeded WAITING row (the same
346
+ * identity token), in which case the seeded id — aliased for every
347
+ * later event of this call.
348
+ */
349
+ private resolveRowId(callId: string, name: string, mcpServerSlug: string, input: Record<string, unknown>): string {
350
+ const known = this.aliases.get(callId);
351
+ if (known) return known;
352
+ if (this.announced.has(callId)) return callId;
353
+ const identity = toolIdentity(name, mcpServerSlug, input);
354
+ const token = primaryToken(identity.key, identity.salient, contentDigest(input));
355
+ const candidates = this.resumable.get(token);
356
+ const seededId = candidates?.shift();
357
+ if (seededId === undefined) return callId;
358
+ this.aliases.set(callId, seededId);
359
+ return seededId;
360
+ }
361
+
362
+ private toolStarted(callId: string, name: string, isMcp: boolean, mcpServerSlug: string, input: Record<string, unknown>): ToolStartedEvent {
363
+ const { policies, leases } = this.options;
364
+ const provenance: PolicySource | undefined = resolveApprovalProvenance(
365
+ name,
366
+ mcpServerSlug,
367
+ policies,
368
+ leases.categories,
369
+ leases.global,
370
+ );
371
+ const gate = this.gateOf(name, isMcp, mcpServerSlug, input);
372
+ return {
373
+ kind: "tool_started",
374
+ callId,
375
+ name,
376
+ input,
377
+ mcpServerSlug,
378
+ ...(provenance !== undefined ? { provenance } : {}),
379
+ ...(gate !== undefined ? { gate } : {}),
380
+ };
381
+ }
382
+
383
+ /**
384
+ * The policy's word that this call requires approval, and the card's
385
+ * message — or nothing for an ungated call. An MCP call (the `mcp` envelope,
386
+ * whatever its provider field says) is governed by the merged policy map
387
+ * alone; a built-in by its category.
388
+ */
389
+ private gateOf(name: string, isMcp: boolean, mcpServerSlug: string, input: Record<string, unknown>): GateAnswer | undefined {
390
+ if (isMcp) {
391
+ const policy = lookupMcpToolPolicy(name, mcpServerSlug, this.options.policies);
392
+ return policy ? { message: resolveApprovalMessage(policy.approvalMessage, name, input) } : undefined;
393
+ }
394
+ if (!builtInRequiresApproval(name)) return undefined;
395
+ const template = getBuiltInApprovalMessage(name);
396
+ return template ? { message: resolveApprovalMessage(template, name, input) } : undefined;
397
+ }
398
+
399
+ // ── The delta queue ─────────────────────────────────────────────
400
+
401
+ private rowIdOf(callId: string): string {
402
+ return this.aliases.get(callId) ?? callId;
403
+ }
404
+
405
+ private enqueue(callId: string, make: (rowId: string) => TranscriptEvent): void {
406
+ const rowId = this.rowIdOf(callId);
407
+ if (this.announced.has(rowId)) {
408
+ this.queue.push(make(rowId));
409
+ return;
410
+ }
411
+ const pending = this.held.get(callId);
412
+ if (pending) pending.push(make);
413
+ else this.held.set(callId, [make]);
414
+ }
415
+ }
416
+
417
+ function segmentId(runId: string, n: number): string {
418
+ return `${runId}:${n}`;
419
+ }
420
+
421
+ /**
422
+ * Whether a `tool-call-completed` delta reports a FAILURE. Every tool family in
423
+ * the SDK's discriminated union carries `result?: { status: "success" | "error", … }`
424
+ * for the outcome; read structurally so a family the SDK adds is judged the
425
+ * same way, and an absent result (a tool that reports nothing) is a success.
426
+ */
427
+ function completionFailed(toolCall: Extract<InteractionUpdate, { type: "tool-call-completed" }>["toolCall"]): boolean {
428
+ const result: unknown = (toolCall as { result?: unknown }).result;
429
+ return typeof result === "object" && result !== null && (result as { status?: unknown }).status === "error";
430
+ }
431
+
432
+ // ── The MCP envelope ──────────────────────────────────────────────
433
+
434
+ /**
435
+ * Details extracted from an MCP tool call event's args.
436
+ *
437
+ * When Cursor invokes an MCP tool, the SDK stream reports event.name as
438
+ * "mcp" and packs the real tool identity into event.args:
439
+ * { providerIdentifier: "planton", toolName: "search_services", args: {...} }
440
+ */
441
+ export interface McpToolDetails {
442
+ providerIdentifier: string;
443
+ toolName: string;
444
+ innerArgs: Record<string, unknown>;
445
+ }
446
+
447
+ /** The MCP tool a `tool_call` event names, or undefined for a built-in. */
448
+ export function extractMcpToolDetails(event: ToolCallEvent): McpToolDetails | undefined {
449
+ if (event.name !== "mcp") return undefined;
450
+
451
+ const args = event.args;
452
+ if (args == null || typeof args !== "object") return undefined;
453
+
454
+ const obj = args as Record<string, unknown>;
455
+ const providerIdentifier = typeof obj.providerIdentifier === "string" ? obj.providerIdentifier : "";
456
+ const toolName = typeof obj.toolName === "string" ? obj.toolName : "";
457
+
458
+ if (!toolName) return undefined;
459
+
460
+ const innerArgs = (typeof obj.args === "object" && obj.args !== null)
461
+ ? obj.args as Record<string, unknown>
462
+ : {};
463
+
464
+ return { providerIdentifier, toolName, innerArgs };
465
+ }
466
+
467
+ // ── Args ──────────────────────────────────────────────────────────
468
+
469
+ /**
470
+ * A `tool_call` event's `args` as the row's input: the object as it came, a
471
+ * JSON string parsed when it parses (a truncated one does not — the SDK marks
472
+ * `truncated.args`), anything else nothing.
473
+ */
474
+ function parseArgs(raw: unknown): Record<string, unknown> {
475
+ if (raw != null && typeof raw === "object" && !Array.isArray(raw)) return raw as Record<string, unknown>;
476
+ if (typeof raw === "string") {
477
+ try {
478
+ const parsed = JSON.parse(raw) as unknown;
479
+ if (parsed != null && typeof parsed === "object" && !Array.isArray(parsed)) return parsed as Record<string, unknown>;
480
+ } catch {
481
+ // Not JSON (or cut short by the SDK's truncation): the row has no args.
482
+ }
483
+ }
484
+ return {};
485
+ }
486
+
487
+ /**
488
+ * The sub-agent's name from the task tool's args, in both the legacy string
489
+ * form (`"generalPurpose"`) and the SDK's object form
490
+ * (`{ kind: "generalPurpose", name?: "..." }`); `description` (always set by
491
+ * the SDK) before the generic `"task"`. The `kind` value `"unspecified"` is
492
+ * treated as absent — the SDK's default when the blueprint names no type.
493
+ */
494
+ export function extractSubagentName(args: unknown): string {
495
+ if (args == null || typeof args !== "object") return TASK_TOOL;
496
+ const obj = args as Record<string, unknown>;
497
+
498
+ const subagentType = obj.subagentType ?? obj.subagent_type;
499
+ if (typeof subagentType === "string" && subagentType) return subagentType;
500
+ if (subagentType != null && typeof subagentType === "object") {
501
+ const typed = subagentType as Record<string, unknown>;
502
+ if (typeof typed.name === "string" && typed.name) return typed.name;
503
+ if (typeof typed.kind === "string" && typed.kind && typed.kind !== "unspecified") {
504
+ return typed.kind;
505
+ }
506
+ }
507
+
508
+ if (typeof obj.description === "string" && obj.description) return obj.description;
509
+
510
+ return TASK_TOOL;
511
+ }
512
+
513
+ function stringArg(args: unknown, key: string): string {
514
+ if (args != null && typeof args === "object" && key in args) {
515
+ const val = (args as Record<string, unknown>)[key];
516
+ return typeof val === "string" ? val : "";
517
+ }
518
+ return "";
519
+ }
520
+
521
+ // ── The shell-output delta's payload ──────────────────────────────
522
+
523
+ /**
524
+ * The SDK's `shell-output-delta` carries a generic `Record<string, unknown>`;
525
+ * observed payloads are `{ type: "stdout" | "stderr", data }`, sometimes
526
+ * `{ output }`. Read defensively.
527
+ */
528
+ function shellOutputText(event: Record<string, unknown>): string {
529
+ if (typeof event.data === "string") return event.data;
530
+ if (typeof event.output === "string") return event.output;
531
+ if (typeof event.text === "string") return event.text;
532
+ return "";
533
+ }
534
+
535
+ /** The call an output delta names, when it names one (`{ callId, type, data }` observed). */
536
+ function shellOutputCallId(event: Record<string, unknown>): string | undefined {
537
+ if (typeof event.callId === "string") return event.callId;
538
+ if (typeof event.call_id === "string") return event.call_id;
539
+ if (typeof event.id === "string") return event.id;
540
+ return undefined;
541
+ }
@@ -18,13 +18,13 @@
18
18
  * silently stamped by the server's terminal settle after the fact.
19
19
  *
20
20
  * `waiting` means "a denial pauses": a gated tool call the user must decide.
21
- * The turn's FILE CHANGES are not this boundary's since S3 M4 — the runtime
21
+ * The turn's FILE CHANGES are not this boundary's since #1096 — the runtime
22
22
  * captures them once, over whatever the whole turn left on the tree, after
23
23
  * `runTurn` returns (`harness/capture.ts`), and decides the review pause
24
24
  * itself. Two consequences the boundary used to suppress when it could see
25
25
  * the capture: steps 4 and 5 now run on a turn whose only pause would have
26
26
  * been a file review, so a hung row is disclosed and a foreign-hook block is
27
- * failed BEFORE the review rather than after it (F-M4-P9, F-M4-P10, Q-M4-11).
27
+ * failed BEFORE the review rather than after it.
28
28
  *
29
29
  * Extracted from the activity entry point (index.ts Phase 12) so it is directly
30
30
  * unit-testable AND re-enterable: the poisoned-handle / transport-timeout
@@ -34,11 +34,12 @@
34
34
  * and the reconcile is idempotent over it.
35
35
  *
36
36
  * The caller owns everything around the boundary: the stream epilogue
37
- * (accumulator/enricher finalize), the WAITING_FOR_APPROVAL phase flip +
37
+ * (the transcript's finalize), the WAITING_FOR_APPROVAL phase flip +
38
38
  * persist, and the terminal result mapping.
39
39
  */
40
40
 
41
41
  import type { AgentExecutionStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
42
+ import type { TranscriptBuilder } from "../../harness/transcript/builder.js";
42
43
  import { LocalWorkspaceBackend } from "../../shared/workspace/local-backend.js";
43
44
  import type { MergedToolPolicy } from "../../shared/approval-policy.js";
44
45
  import {
@@ -53,12 +54,8 @@ import {
53
54
  reconcileDeniedToolCalls,
54
55
  settleUnresolvedToolCalls,
55
56
  stampUnattendedSkippedToolCalls,
56
- utcTimestamp,
57
57
  type UnattributedHookBlock,
58
- } from "./message-translator.js";
59
- import { create } from "@bufbuild/protobuf";
60
- import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
61
- import { MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
58
+ } from "./boundary-rows.js";
62
59
 
63
60
  // How long the boundary waits for the first-denial-stop's run.cancel() to
64
61
  // settle before reading the final denial ledger. Long enough for the SDK's
@@ -69,8 +66,17 @@ import { MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v
69
66
  const FIRST_DENIAL_CANCEL_TIMEOUT_MS = 5_000;
70
67
 
71
68
  export interface TurnBoundaryOptions {
72
- /** Mutated in place: gate rows overlaid, narration redacted. */
69
+ /** Read, and AMENDED in place by identity: gate rows overlaid, twins collapsed, narration redacted. */
73
70
  readonly status: AgentExecutionStatus;
71
+ /**
72
+ * The turn's transcript builder over `status`: every row the boundary
73
+ * CREATES — the gate it proposes for a denial no streamed call matched, the
74
+ * #965 disclosure line — goes through it (`approval_proposed`,
75
+ * `system_note`), never onto `status.messages` directly (#1097's
76
+ * rule: rows are created through the builder; a harness amends rows its
77
+ * boundary owns and says which).
78
+ */
79
+ readonly transcript: TranscriptBuilder;
74
80
  readonly executionId: string;
75
81
  /** Session HITL dir holding the denial ledger; undefined → no gate installed. */
76
82
  readonly hitlDir: string | undefined;
@@ -147,6 +153,7 @@ export interface TurnBoundaryResult {
147
153
  export async function runTurnBoundary(opts: TurnBoundaryOptions): Promise<TurnBoundaryResult> {
148
154
  const {
149
155
  status,
156
+ transcript,
150
157
  executionId,
151
158
  hitlDir,
152
159
  primaryWorkspaceDir,
@@ -183,6 +190,7 @@ export async function runTurnBoundary(opts: TurnBoundaryOptions): Promise<TurnBo
183
190
  const gateWorkspaceBackend = new LocalWorkspaceBackend(primaryWorkspaceDir);
184
191
  const deniedToolCalls = await reconcileDeniedToolCalls(
185
192
  status.messages,
193
+ transcript,
186
194
  approvalLedger,
187
195
  mergedPolicies,
188
196
  gateWorkspaceBackend,
@@ -279,14 +287,13 @@ export async function runTurnBoundary(opts: TurnBoundaryOptions): Promise<TurnBo
279
287
  );
280
288
  if (settledUnresolved.length > 0) {
281
289
  const names = [...new Set(settledUnresolved.map((s) => s.toolName))].join(", ");
282
- status.messages.push(create(AgentMessageSchema, {
283
- type: MessageType.MESSAGE_SYSTEM,
284
- content:
290
+ transcript.apply({
291
+ kind: "system_note",
292
+ text:
285
293
  `Note: the following tool call(s) never completed and were not executed: ${names}. ` +
286
294
  `No approval is pending for them — if the agent said otherwise, disregard that. ` +
287
295
  `You can ask the agent to try again.`,
288
- timestamp: utcTimestamp(),
289
- }));
296
+ });
290
297
  console.warn(
291
298
  `ExecuteCursor turn boundary: settled ${settledUnresolved.length} unresolved ` +
292
299
  `tool call(s) to INTERRUPTED with disclosure [${names}] — the harness returned ` +