@stigmer/runner 3.15.3-dev.20260914100347 → 3.15.3-dev.20260916211208

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 (549) hide show
  1. package/README.md +1 -0
  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 +14 -11
  12. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
  13. package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +61 -0
  14. package/dist/activities/execute-cursor/__test-utils__/fold.js +94 -0
  15. package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -0
  16. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +1 -1
  17. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
  18. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +52 -14
  19. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +46 -12
  20. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  21. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +21 -28
  22. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +27 -11
  23. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
  24. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +70 -26
  25. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +82 -32
  26. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -1
  27. package/dist/activities/execute-cursor/adapter.d.ts +8 -7
  28. package/dist/activities/execute-cursor/adapter.js +13 -9
  29. package/dist/activities/execute-cursor/adapter.js.map +1 -1
  30. package/dist/activities/execute-cursor/approval-policy.d.ts +10 -10
  31. package/dist/activities/execute-cursor/approval-policy.js +12 -23
  32. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  33. package/dist/activities/execute-cursor/approval-state.d.ts +35 -1
  34. package/dist/activities/execute-cursor/approval-state.js +65 -0
  35. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  36. package/dist/activities/execute-cursor/{message-translator.d.ts → boundary-rows.d.ts} +45 -341
  37. package/dist/activities/execute-cursor/boundary-rows.js +1018 -0
  38. package/dist/activities/execute-cursor/boundary-rows.js.map +1 -0
  39. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +1 -1
  40. package/dist/activities/execute-cursor/cursor-capabilities.js +1 -1
  41. package/dist/activities/execute-cursor/cursor-event-recorder.d.ts +33 -14
  42. package/dist/activities/execute-cursor/cursor-event-recorder.js +43 -21
  43. package/dist/activities/execute-cursor/cursor-event-recorder.js.map +1 -1
  44. package/dist/activities/execute-cursor/prompt-builder.d.ts +3 -3
  45. package/dist/activities/execute-cursor/prompt-builder.js +4 -4
  46. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  47. package/dist/activities/execute-cursor/sdk-warmup.d.ts +15 -6
  48. package/dist/activities/execute-cursor/sdk-warmup.js +15 -6
  49. package/dist/activities/execute-cursor/sdk-warmup.js.map +1 -1
  50. package/dist/activities/execute-cursor/service-tier.js +1 -2
  51. package/dist/activities/execute-cursor/service-tier.js.map +1 -1
  52. package/dist/activities/execute-cursor/session-lifecycle.d.ts +38 -59
  53. package/dist/activities/execute-cursor/session-lifecycle.js +59 -96
  54. package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -1
  55. package/dist/activities/execute-cursor/session-store.d.ts +100 -0
  56. package/dist/activities/execute-cursor/session-store.js +157 -0
  57. package/dist/activities/execute-cursor/session-store.js.map +1 -0
  58. package/dist/activities/execute-cursor/sub-agent-steps.d.ts +79 -0
  59. package/dist/activities/execute-cursor/sub-agent-steps.js +180 -0
  60. package/dist/activities/execute-cursor/sub-agent-steps.js.map +1 -0
  61. package/dist/activities/execute-cursor/tool-result.d.ts +49 -0
  62. package/dist/activities/execute-cursor/tool-result.js +130 -0
  63. package/dist/activities/execute-cursor/tool-result.js.map +1 -0
  64. package/dist/activities/execute-cursor/translator.d.ts +178 -0
  65. package/dist/activities/execute-cursor/translator.js +485 -0
  66. package/dist/activities/execute-cursor/translator.js.map +1 -0
  67. package/dist/activities/execute-cursor/turn-boundary.d.ts +15 -5
  68. package/dist/activities/execute-cursor/turn-boundary.js +10 -14
  69. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
  70. package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
  71. package/dist/activities/execute-cursor/turn-settle.js +47 -34
  72. package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
  73. package/dist/activities/execute-cursor/turn-setup.d.ts +2 -2
  74. package/dist/activities/execute-cursor/turn-setup.js +5 -5
  75. package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
  76. package/dist/activities/execute-cursor/turn-stream.d.ts +23 -14
  77. package/dist/activities/execute-cursor/turn-stream.js +41 -28
  78. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  79. package/dist/activities/execute-cursor/turn.d.ts +4 -4
  80. package/dist/activities/execute-cursor/turn.js +5 -5
  81. package/dist/activities/execute-cursor/usage-pricing.d.ts +2 -2
  82. package/dist/activities/execute-cursor/usage-pricing.js +2 -2
  83. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +2 -2
  84. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +2 -2
  85. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +16 -11
  86. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +22 -10
  87. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -1
  88. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +1 -1
  89. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -1
  90. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +2 -3
  91. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +2 -3
  92. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -1
  93. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +12 -3
  94. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +18 -4
  95. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
  96. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.d.ts +10 -1
  97. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js +24 -11
  98. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js.map +1 -1
  99. package/dist/activities/execute-deep-agent/adapter.d.ts +1 -1
  100. package/dist/activities/execute-deep-agent/adapter.js +1 -1
  101. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +19 -19
  102. package/dist/activities/execute-deep-agent/approval-file-change.js +16 -15
  103. package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
  104. package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +2 -2
  105. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +2 -2
  106. package/dist/activities/execute-deep-agent/hitl.d.ts +2 -2
  107. package/dist/activities/execute-deep-agent/hitl.js +2 -2
  108. package/dist/activities/execute-deep-agent/inline-publisher.d.ts +13 -3
  109. package/dist/activities/execute-deep-agent/inline-publisher.js +3 -3
  110. package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -1
  111. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +3 -3
  112. package/dist/activities/execute-deep-agent/prompt-builder.js +6 -7
  113. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  114. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +16 -8
  115. package/dist/activities/execute-deep-agent/streaming-side-effects.js +20 -33
  116. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  117. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +3 -3
  118. package/dist/activities/execute-deep-agent/subagent-transformer.js +1 -1
  119. package/dist/activities/execute-deep-agent/translator.d.ts +134 -0
  120. package/dist/activities/execute-deep-agent/translator.js +418 -0
  121. package/dist/activities/execute-deep-agent/translator.js.map +1 -0
  122. package/dist/activities/execute-deep-agent/turn-settle.d.ts +13 -7
  123. package/dist/activities/execute-deep-agent/turn-settle.js +34 -45
  124. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -1
  125. package/dist/activities/execute-deep-agent/turn-setup.d.ts +8 -8
  126. package/dist/activities/execute-deep-agent/turn-setup.js +7 -7
  127. package/dist/activities/execute-deep-agent/turn-stream.d.ts +13 -10
  128. package/dist/activities/execute-deep-agent/turn-stream.js +44 -41
  129. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -1
  130. package/dist/activities/execute-deep-agent/turn.d.ts +3 -3
  131. package/dist/activities/execute-deep-agent/turn.js +3 -3
  132. package/dist/config.d.ts +2 -2
  133. package/dist/harness/approval-decisions.d.ts +1 -1
  134. package/dist/harness/approval-decisions.js +1 -1
  135. package/dist/harness/capabilities.d.ts +21 -11
  136. package/dist/harness/capabilities.js +2 -2
  137. package/dist/harness/capture.d.ts +4 -4
  138. package/dist/harness/capture.js +4 -4
  139. package/dist/harness/persist-chokepoint.d.ts +3 -3
  140. package/dist/harness/persist-chokepoint.js +3 -3
  141. package/dist/harness/registry.d.ts +2 -2
  142. package/dist/harness/registry.js +2 -2
  143. package/dist/harness/run-turn.d.ts +6 -4
  144. package/dist/harness/run-turn.js +31 -9
  145. package/dist/harness/run-turn.js.map +1 -1
  146. package/dist/harness/stop-controller.d.ts +1 -1
  147. package/dist/harness/stop-controller.js +1 -1
  148. package/dist/harness/terminal-table.d.ts +7 -7
  149. package/dist/harness/terminal-table.js +7 -7
  150. package/dist/harness/transcript/builder.d.ts +182 -0
  151. package/dist/harness/transcript/builder.js +693 -0
  152. package/dist/harness/transcript/builder.js.map +1 -0
  153. package/dist/harness/transcript/events.d.ts +218 -0
  154. package/dist/harness/transcript/events.js +50 -0
  155. package/dist/harness/transcript/events.js.map +1 -0
  156. package/dist/harness/transcript/state.d.ts +110 -0
  157. package/dist/harness/transcript/state.js +148 -0
  158. package/dist/harness/transcript/state.js.map +1 -0
  159. package/dist/harness/turn-context.d.ts +54 -38
  160. package/dist/harness/turn-context.js +42 -43
  161. package/dist/harness/turn-context.js.map +1 -1
  162. package/dist/harness/types.d.ts +63 -22
  163. package/dist/harness/types.js +12 -11
  164. package/dist/harness/types.js.map +1 -1
  165. package/dist/harness/usage-accumulator.d.ts +2 -2
  166. package/dist/harness/usage-accumulator.js +2 -2
  167. package/dist/harness-adapters.d.ts +5 -4
  168. package/dist/harness-adapters.js +5 -4
  169. package/dist/harness-adapters.js.map +1 -1
  170. package/dist/middleware/approval-gate.d.ts +6 -0
  171. package/dist/middleware/approval-gate.js +7 -57
  172. package/dist/middleware/approval-gate.js.map +1 -1
  173. package/dist/middleware/cost-advisory.d.ts +3 -3
  174. package/dist/middleware/cost-advisory.js +3 -3
  175. package/dist/middleware/index.d.ts +1 -1
  176. package/dist/middleware/index.js +1 -1
  177. package/dist/runner-manager.js +1 -1
  178. package/dist/runner-manager.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-vision.d.ts +2 -1
  188. package/dist/shared/attachment-vision.js.map +1 -1
  189. package/dist/shared/attachment-zip.d.ts +2 -2
  190. package/dist/shared/attachment-zip.js +2 -2
  191. package/dist/shared/cost-guard.d.ts +2 -2
  192. package/dist/shared/cost-guard.js +2 -2
  193. package/dist/shared/exact-apply.d.ts +1 -1
  194. package/dist/shared/exact-apply.js +1 -1
  195. package/dist/shared/execution-context.d.ts +2 -2
  196. package/dist/shared/execution-context.js +2 -2
  197. package/dist/shared/extract-structured-output.d.ts +2 -2
  198. package/dist/shared/extract-structured-output.js +2 -2
  199. package/dist/shared/filereview/cas-touched.d.ts +2 -2
  200. package/dist/shared/filereview/cas-touched.js +2 -2
  201. package/dist/shared/heartbeat.d.ts +1 -1
  202. package/dist/shared/heartbeat.js +1 -1
  203. package/dist/shared/llm-backend.d.ts +0 -4
  204. package/dist/shared/llm-backend.js +0 -4
  205. package/dist/shared/llm-backend.js.map +1 -1
  206. package/dist/shared/model-error.d.ts +1 -2
  207. package/dist/shared/model-error.js +1 -2
  208. package/dist/shared/model-error.js.map +1 -1
  209. package/dist/shared/persist-decision.d.ts +18 -24
  210. package/dist/shared/persist-decision.js +19 -11
  211. package/dist/shared/persist-decision.js.map +1 -1
  212. package/dist/shared/prompt-sections.d.ts +4 -4
  213. package/dist/shared/prompt-sections.js +4 -4
  214. package/dist/shared/skill-resolver.d.ts +3 -3
  215. package/dist/shared/skill-resolver.js +3 -3
  216. package/dist/shared/status-offload.d.ts +1 -1
  217. package/dist/shared/status-offload.js +2 -2
  218. package/dist/shared/status-offload.js.map +1 -1
  219. package/dist/shared/streaming-scheduler.d.ts +2 -7
  220. package/dist/shared/streaming-scheduler.js +6 -14
  221. package/dist/shared/streaming-scheduler.js.map +1 -1
  222. package/dist/shared/subagent-rows.d.ts +2 -2
  223. package/dist/shared/subagent-rows.js +2 -2
  224. package/dist/shared/todos.d.ts +3 -3
  225. package/dist/shared/todos.js +3 -3
  226. package/dist/shared/tool-row.d.ts +19 -1
  227. package/dist/shared/tool-row.js +36 -2
  228. package/dist/shared/tool-row.js.map +1 -1
  229. package/dist/shared/worker-shutdown.d.ts +1 -1
  230. package/dist/shared/worker-shutdown.js +1 -1
  231. package/dist/shared/workspace/session-provision.d.ts +1 -1
  232. package/dist/shared/workspace/session-provision.js +1 -1
  233. package/dist/shared/workspace/sources/empty.d.ts +1 -1
  234. package/dist/shared/workspace/sources/empty.js +1 -2
  235. package/dist/shared/workspace/sources/empty.js.map +1 -1
  236. package/dist/shared/workspace/sources/git.js +4 -4
  237. package/dist/shared/workspace/sources/git.js.map +1 -1
  238. package/dist/shared/workspace/sources/local-path.js +6 -6
  239. package/dist/shared/workspace/sources/local-path.js.map +1 -1
  240. package/dist/shared/workspace/stigmer-link.d.ts +1 -1
  241. package/dist/shared/workspace/stigmer-link.js +1 -1
  242. package/dist/shared/workspace/types.d.ts +2 -5
  243. package/dist/shared/workspace/types.js +0 -6
  244. package/dist/shared/workspace/types.js.map +1 -1
  245. package/dist/shared/workspace/writeback-coordinator.d.ts +17 -4
  246. package/dist/shared/workspace/writeback-coordinator.js +7 -9
  247. package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
  248. package/package.json +5 -5
  249. package/src/__test-utils__/__tests__/execution-record-barrier.test.ts +70 -0
  250. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +35 -1
  251. package/src/__test-utils__/approval-contract/contract.ts +1 -1
  252. package/src/__test-utils__/approval-contract/types.ts +1 -1
  253. package/src/__test-utils__/harness-boot-order-child.ts +1 -1
  254. package/src/__test-utils__/harness-contract/contract.ts +8 -8
  255. package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
  256. package/src/__test-utils__/harness-contract/runtime-contract.ts +52 -16
  257. package/src/__test-utils__/harness-contract/scripted-adapter.ts +47 -43
  258. package/src/__test-utils__/hermetic-activity.ts +113 -9
  259. package/src/__test-utils__/model-registry-fixture.ts +31 -7
  260. package/src/__test-utils__/module-specifiers.ts +32 -3
  261. package/src/__tests__/harness-boot-order.test.ts +1 -1
  262. package/src/__tests__/harness-contract.test.ts +1 -1
  263. package/src/__tests__/runner-manager.test.ts +1 -1
  264. package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +32 -8
  265. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +12 -10
  266. package/src/activities/execute-cursor/__test-utils__/fold.ts +116 -0
  267. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +1 -1
  268. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +72 -19
  269. package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +35 -29
  270. package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +94 -38
  271. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +2 -1
  272. package/src/activities/execute-cursor/__tests__/approval-state.test.ts +14 -21
  273. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +3 -3
  274. package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +2 -1
  275. package/src/activities/execute-cursor/__tests__/cursor-baseurl-routing.test.ts +10 -8
  276. package/src/activities/execute-cursor/__tests__/cursor-event-recorder.test.ts +142 -0
  277. package/src/activities/execute-cursor/__tests__/cursor-fetch-interceptor-bypass.test.ts +24 -12
  278. package/src/activities/execute-cursor/__tests__/cursor-generate-image-live.test.ts +7 -2
  279. package/src/activities/execute-cursor/__tests__/cursor-hook-protocol-live.test.ts +163 -0
  280. package/src/activities/execute-cursor/__tests__/cursor-sdk-auth-smoke.test.ts +23 -20
  281. package/src/activities/execute-cursor/__tests__/cursor-transcript-live.test.ts +298 -0
  282. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +4 -2
  283. package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +1 -1
  284. package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +5 -2
  285. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +5 -2
  286. package/src/activities/execute-cursor/__tests__/hermetic/goldens/mcp-tool-call.status.json +71 -0
  287. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.status.json +73 -0
  288. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +78 -0
  289. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +72 -0
  290. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +72 -0
  291. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.status.json +109 -0
  292. package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.status.json +78 -0
  293. package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.status.json +119 -0
  294. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.status.json +68 -0
  295. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.status.json +67 -0
  296. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +1 -1
  297. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +10 -7
  298. package/src/activities/execute-cursor/__tests__/hermetic/mcp-tool-call.test.ts +146 -0
  299. package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +8 -5
  300. package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +6 -2
  301. package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +4 -1
  302. package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +6 -2
  303. package/src/activities/execute-cursor/__tests__/hermetic/sdk-task-note.test.ts +122 -0
  304. package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +276 -0
  305. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +12 -9
  306. package/src/activities/execute-cursor/__tests__/hermetic/sub-agent-delegation.test.ts +196 -0
  307. package/src/activities/execute-cursor/__tests__/hermetic/thinking-turn.test.ts +145 -0
  308. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +4 -1
  309. package/src/activities/execute-cursor/__tests__/hermetic/todo-write.test.ts +165 -0
  310. package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +7 -4
  311. package/src/activities/execute-cursor/__tests__/hermetic/tool-error.test.ts +138 -0
  312. package/src/activities/execute-cursor/__tests__/hermetic/tool-only-step.test.ts +130 -0
  313. package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +17 -2
  314. package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -2
  315. package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +43 -60
  316. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +23 -28
  317. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +2 -1
  318. package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +1 -1
  319. package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +5 -5
  320. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +11 -13
  321. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +8 -11
  322. package/src/activities/execute-cursor/__tests__/session-lifecycle.test.ts +86 -58
  323. package/src/activities/execute-cursor/__tests__/session-store.test.ts +220 -0
  324. package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +8 -22
  325. package/src/activities/execute-cursor/__tests__/translator.test.ts +594 -0
  326. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +8 -5
  327. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +87 -63
  328. package/src/activities/execute-cursor/adapter.ts +13 -9
  329. package/src/activities/execute-cursor/approval-policy.ts +12 -24
  330. package/src/activities/execute-cursor/approval-state.ts +66 -1
  331. package/src/activities/execute-cursor/boundary-rows.ts +1132 -0
  332. package/src/activities/execute-cursor/cursor-capabilities.ts +1 -1
  333. package/src/activities/execute-cursor/cursor-event-recorder.ts +57 -28
  334. package/src/activities/execute-cursor/fetch-interceptor.ts +1 -1
  335. package/src/activities/execute-cursor/http2-interceptor.ts +1 -1
  336. package/src/activities/execute-cursor/prompt-builder.ts +6 -6
  337. package/src/activities/execute-cursor/sdk-warmup.ts +15 -6
  338. package/src/activities/execute-cursor/service-tier.ts +1 -2
  339. package/src/activities/execute-cursor/session-lifecycle.ts +63 -109
  340. package/src/activities/execute-cursor/session-store.ts +187 -0
  341. package/src/activities/execute-cursor/sub-agent-steps.ts +188 -0
  342. package/src/activities/execute-cursor/tool-result.ts +128 -0
  343. package/src/activities/execute-cursor/translator.ts +541 -0
  344. package/src/activities/execute-cursor/turn-boundary.ts +21 -14
  345. package/src/activities/execute-cursor/turn-settle.ts +46 -34
  346. package/src/activities/execute-cursor/turn-setup.ts +5 -5
  347. package/src/activities/execute-cursor/turn-stream.ts +49 -46
  348. package/src/activities/execute-cursor/turn.ts +5 -5
  349. package/src/activities/execute-cursor/usage-pricing.ts +2 -2
  350. package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +2 -2
  351. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +23 -11
  352. package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +1 -1
  353. package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +2 -3
  354. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +25 -4
  355. package/src/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.ts +25 -11
  356. package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +1 -1
  357. package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +1 -1
  358. package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +6 -17
  359. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +25 -8
  360. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +2 -7
  361. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +4 -14
  362. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +1 -5
  363. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +4 -7
  364. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +1 -5
  365. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +2 -9
  366. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +2 -9
  367. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +1 -4
  368. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +1 -4
  369. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +1 -4
  370. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +109 -76
  371. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +1 -5
  372. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +2 -10
  373. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +2 -10
  374. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +1 -5
  375. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +3 -6
  376. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +1 -4
  377. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +1 -4
  378. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.status.json +92 -0
  379. package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +3 -3
  380. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +9 -5
  381. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +3 -3
  382. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +3 -3
  383. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +7 -6
  384. package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +10 -11
  385. package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +4 -4
  386. package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +9 -8
  387. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +21 -13
  388. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +2 -2
  389. package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +7 -7
  390. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +28 -12
  391. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +21 -21
  392. package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +5 -5
  393. package/src/activities/execute-deep-agent/__tests__/hermetic/write-todos.test.ts +160 -0
  394. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +35 -30
  395. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +3 -4
  396. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +12 -10
  397. package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +13 -3
  398. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +26 -18
  399. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +1 -1
  400. package/src/activities/execute-deep-agent/__tests__/{subagent-tracker.test.ts → translator-subagents.test.ts} +76 -57
  401. package/src/activities/execute-deep-agent/__tests__/{v3-status-builder.test.ts → translator-through-builder.test.ts} +213 -299
  402. package/src/activities/execute-deep-agent/__tests__/translator.test.ts +505 -0
  403. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +11 -29
  404. package/src/activities/execute-deep-agent/adapter.ts +1 -1
  405. package/src/activities/execute-deep-agent/approval-file-change.ts +20 -22
  406. package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +2 -2
  407. package/src/activities/execute-deep-agent/hitl.ts +2 -2
  408. package/src/activities/execute-deep-agent/inline-publisher.ts +16 -5
  409. package/src/activities/execute-deep-agent/prompt-builder.ts +6 -7
  410. package/src/activities/execute-deep-agent/streaming-side-effects.ts +22 -31
  411. package/src/activities/execute-deep-agent/subagent-transformer.ts +3 -3
  412. package/src/activities/execute-deep-agent/translator.ts +463 -0
  413. package/src/activities/execute-deep-agent/turn-settle.ts +35 -43
  414. package/src/activities/execute-deep-agent/turn-setup.ts +8 -8
  415. package/src/activities/execute-deep-agent/turn-stream.ts +53 -51
  416. package/src/activities/execute-deep-agent/turn.ts +3 -3
  417. package/src/config.ts +2 -2
  418. package/src/harness/README.md +335 -0
  419. package/src/harness/__tests__/approval-decisions.test.ts +2 -2
  420. package/src/harness/__tests__/capture.test.ts +3 -3
  421. package/src/harness/__tests__/import-direction.test.ts +3 -2
  422. package/src/harness/__tests__/mount-skills.test.ts +4 -1
  423. package/src/harness/__tests__/readme-index.test.ts +339 -0
  424. package/src/harness/__tests__/run-turn.test.ts +131 -6
  425. package/src/harness/__tests__/transcript-is-engine-free.test.ts +83 -0
  426. package/src/harness/__tests__/transcript-writers.test.ts +191 -0
  427. package/src/harness/__tests__/turn-attachments-vision.test.ts +5 -2
  428. package/src/harness/__tests__/turn-context.test.ts +5 -5
  429. package/src/harness/approval-decisions.ts +1 -1
  430. package/src/harness/capabilities.ts +21 -11
  431. package/src/harness/capture.ts +4 -4
  432. package/src/harness/persist-chokepoint.ts +3 -3
  433. package/src/harness/registry.ts +2 -2
  434. package/src/harness/run-turn.ts +33 -9
  435. package/src/harness/stop-controller.ts +1 -1
  436. package/src/harness/terminal-table.ts +7 -7
  437. package/src/harness/transcript/__tests__/builder.test.ts +975 -0
  438. package/src/harness/transcript/__tests__/state.test.ts +143 -0
  439. package/src/harness/transcript/builder.ts +755 -0
  440. package/src/harness/transcript/events.ts +262 -0
  441. package/src/harness/transcript/state.ts +167 -0
  442. package/src/harness/turn-context.ts +61 -46
  443. package/src/harness/types.ts +64 -22
  444. package/src/harness/usage-accumulator.ts +2 -2
  445. package/src/harness-adapters.ts +5 -4
  446. package/src/middleware/__tests__/cost-advisory.test.ts +2 -2
  447. package/src/middleware/approval-gate.ts +7 -74
  448. package/src/middleware/cost-advisory.ts +3 -3
  449. package/src/middleware/index.ts +1 -1
  450. package/src/runner-manager.ts +1 -1
  451. package/src/shared/__tests__/approval-policy.test.ts +45 -0
  452. package/src/shared/__tests__/args-preview.test.ts +40 -20
  453. package/src/shared/__tests__/attachment-naming.test.ts +1 -1
  454. package/src/shared/__tests__/attachment-resolver.test.ts +5 -5
  455. package/src/shared/__tests__/attachment-zip.test.ts +1 -1
  456. package/src/shared/__tests__/blueprint-resolver.test.ts +1 -1
  457. package/src/shared/__tests__/cost-guard.test.ts +1 -1
  458. package/src/shared/__tests__/exact-apply.test.ts +2 -1
  459. package/src/shared/__tests__/persist-decision.test.ts +19 -33
  460. package/src/shared/__tests__/prompt-sections.test.ts +1 -1
  461. package/src/shared/__tests__/stamp-flowed-rows.test.ts +1 -1
  462. package/src/shared/__tests__/status-offload.test.ts +1 -1
  463. package/src/shared/__tests__/streaming-scheduler.test.ts +8 -9
  464. package/src/shared/__tests__/todos.test.ts +1 -1
  465. package/src/shared/__tests__/tool-row.test.ts +1 -1
  466. package/src/shared/approval-policy.ts +95 -0
  467. package/src/shared/args-preview.ts +51 -42
  468. package/src/shared/attachment-resolver.ts +4 -4
  469. package/src/shared/attachment-vision.ts +2 -1
  470. package/src/shared/attachment-zip.ts +2 -2
  471. package/src/shared/cost-guard.ts +2 -2
  472. package/src/shared/exact-apply.ts +1 -1
  473. package/src/shared/execution-context.ts +2 -2
  474. package/src/shared/extract-structured-output.ts +2 -2
  475. package/src/shared/filereview/__tests__/capture.test.ts +9 -5
  476. package/src/shared/filereview/__tests__/git-substrate.test.ts +4 -1
  477. package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +3 -3
  478. package/src/shared/filereview/cas-touched.ts +2 -2
  479. package/src/shared/heartbeat.ts +1 -1
  480. package/src/shared/llm-backend.ts +0 -4
  481. package/src/shared/model-error.ts +1 -2
  482. package/src/shared/persist-decision.ts +19 -28
  483. package/src/shared/prompt-sections.ts +4 -4
  484. package/src/shared/skill-resolver.ts +3 -3
  485. package/src/shared/status-offload.ts +2 -2
  486. package/src/shared/streaming-scheduler.ts +8 -13
  487. package/src/shared/subagent-rows.ts +2 -2
  488. package/src/shared/todos.ts +3 -3
  489. package/src/shared/tool-row.ts +38 -2
  490. package/src/shared/worker-shutdown.ts +1 -1
  491. package/src/shared/workspace/__tests__/git-source.test.ts +3 -3
  492. package/src/shared/workspace/__tests__/provisioner.test.ts +5 -5
  493. package/src/shared/workspace/__tests__/session-provision.test.ts +2 -2
  494. package/src/shared/workspace/__tests__/writeback-coordinator.integration.test.ts +8 -9
  495. package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +25 -25
  496. package/src/shared/workspace/provisioner.ts +1 -1
  497. package/src/shared/workspace/session-provision.ts +1 -1
  498. package/src/shared/workspace/sources/empty.ts +2 -2
  499. package/src/shared/workspace/sources/git.ts +3 -4
  500. package/src/shared/workspace/sources/local-path.ts +5 -6
  501. package/src/shared/workspace/stigmer-link.ts +1 -1
  502. package/src/shared/workspace/types.ts +2 -5
  503. package/src/shared/workspace/writeback-coordinator.ts +23 -12
  504. package/dist/activities/execute-cursor/delta-enricher.d.ts +0 -87
  505. package/dist/activities/execute-cursor/delta-enricher.js +0 -265
  506. package/dist/activities/execute-cursor/delta-enricher.js.map +0 -1
  507. package/dist/activities/execute-cursor/message-translator.js +0 -2040
  508. package/dist/activities/execute-cursor/message-translator.js.map +0 -1
  509. package/dist/activities/execute-cursor/todo-tracker.d.ts +0 -40
  510. package/dist/activities/execute-cursor/todo-tracker.js +0 -80
  511. package/dist/activities/execute-cursor/todo-tracker.js.map +0 -1
  512. package/dist/activities/execute-deep-agent/execution-state.d.ts +0 -54
  513. package/dist/activities/execute-deep-agent/execution-state.js +0 -68
  514. package/dist/activities/execute-deep-agent/execution-state.js.map +0 -1
  515. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +0 -65
  516. package/dist/activities/execute-deep-agent/status-builder-shared.js +0 -90
  517. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +0 -1
  518. package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +0 -113
  519. package/dist/activities/execute-deep-agent/subagent-tracker.js +0 -400
  520. package/dist/activities/execute-deep-agent/subagent-tracker.js.map +0 -1
  521. package/dist/activities/execute-deep-agent/v3-events.d.ts +0 -102
  522. package/dist/activities/execute-deep-agent/v3-events.js +0 -35
  523. package/dist/activities/execute-deep-agent/v3-events.js.map +0 -1
  524. package/dist/activities/execute-deep-agent/v3-protocol-normalizer.d.ts +0 -15
  525. package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js +0 -235
  526. package/dist/activities/execute-deep-agent/v3-protocol-normalizer.js.map +0 -1
  527. package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +0 -111
  528. package/dist/activities/execute-deep-agent/v3-status-builder.js +0 -457
  529. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +0 -1
  530. package/dist/shared/execution-status-writer.d.ts +0 -31
  531. package/dist/shared/execution-status-writer.js +0 -43
  532. package/dist/shared/execution-status-writer.js.map +0 -1
  533. package/src/activities/execute-cursor/__tests__/delta-enricher.test.ts +0 -310
  534. package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -1033
  535. package/src/activities/execute-cursor/__tests__/todo-tracker.test.ts +0 -498
  536. package/src/activities/execute-cursor/delta-enricher.ts +0 -307
  537. package/src/activities/execute-cursor/message-translator.ts +0 -2319
  538. package/src/activities/execute-cursor/todo-tracker.ts +0 -91
  539. package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -148
  540. package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -154
  541. package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +0 -47
  542. package/src/activities/execute-deep-agent/__tests__/v3-protocol-normalizer.test.ts +0 -324
  543. package/src/activities/execute-deep-agent/execution-state.ts +0 -78
  544. package/src/activities/execute-deep-agent/status-builder-shared.ts +0 -142
  545. package/src/activities/execute-deep-agent/subagent-tracker.ts +0 -479
  546. package/src/activities/execute-deep-agent/v3-events.ts +0 -153
  547. package/src/activities/execute-deep-agent/v3-protocol-normalizer.ts +0 -264
  548. package/src/activities/execute-deep-agent/v3-status-builder.ts +0 -565
  549. package/src/shared/execution-status-writer.ts +0 -56
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * The Cursor harness's settle — from a consumed stream to a `TurnOutcome`.
3
3
  *
4
- * In order: the post-stream finalize (transcript, enrichments, sub-agents,
5
- * the usage snapshot's carrier, the recorder flush, one persist so the UI
6
- * sees settled rows); the runtime's stop, if it fired, settled as
4
+ * In order: the post-stream finalize (the last queued deltas drained, the
5
+ * transcript's streaming flags closed, a stopped turn's sub-agents cancelled,
6
+ * the recorder flush, one persist so the UI sees settled rows); the runtime's
7
+ * stop, if it fired, settled as
7
8
  * `interrupted` with nothing further; the turn boundary (`turn-boundary.ts`)
8
9
  * that overlays the hook's denials as WAITING rows, ending `awaiting_approval`
9
10
  * when a denial pauses or failing on an unattributed hook block (#205);
@@ -18,12 +19,15 @@
18
19
  * `terminal-table.ts`); capture the turn's file changes or decide whether a
19
20
  * review is pending — the runtime's too (`harness/capture.ts`, once over the
20
21
  * whole turn after this settle returns, so a recovery's edits reach review
21
- * without the boundary being re-entered for them; S3 M4). The outcome carries
22
+ * without the boundary being re-entered for them; since #1096). The outcome carries
22
23
  * what the runtime cannot read from the status (`failed`'s message and
23
- * surface, `cancelled`). It does mutate `sink.status`'s transcript rows,
24
- * which are this harness's to write.
24
+ * surface, `cancelled`). The transcript's rows are CREATED through the shared
25
+ * `TranscriptBuilder` (#1097: this harness's translator emits, the builder
26
+ * folds; until then the accumulator, the enricher and the todo tracker wrote
27
+ * them here); the boundary AMENDS rows it owns by identity and proposes its
28
+ * gate through the same builder.
25
29
  *
26
- * Moved from `index.ts` `executeCursorInner` phases 11 to 13 at S2 M3b; the
30
+ * Moved from `index.ts` `executeCursorInner` phases 11 to 13 in #1070; the
27
31
  * bodies are the orchestrator's, with the runtime's arms taken out.
28
32
  */
29
33
 
@@ -35,8 +39,8 @@ import { StreamingUsageSummarySchema } from "@stigmer/protos/ai/stigmer/agentic/
35
39
  import type { TurnInput, TurnOutcome, TurnSink } from "../../harness/types.js";
36
40
  import { TimingRecorder, emitTimingLog } from "../../shared/cold-start-timing.js";
37
41
  import { StreamingUpdateScheduler, loadStreamingConfig } from "../../shared/streaming-scheduler.js";
42
+ import { cancelInProgressSubAgentProtos } from "../../shared/subagent-rows.js";
38
43
  import { createCursorEventRecorder } from "./cursor-event-recorder.js";
39
- import { DeltaEnricher } from "./delta-enricher.js";
40
44
  import {
41
45
  extractRunErrorSources,
42
46
  formatClassifiedError,
@@ -44,9 +48,9 @@ import {
44
48
  synthesizeError,
45
49
  } from "./error-classifier.js";
46
50
  import { closeProxySessions } from "./http2-interceptor.js";
47
- import { MessageAccumulator, collapseRedundantToolCallTwins } from "./message-translator.js";
51
+ import { collapseRedundantToolCallTwins } from "./boundary-rows.js";
48
52
  import { clearCapturedRejection, getCapturedRejection } from "./rejection-capture.js";
49
- import { TodoTracker } from "./todo-tracker.js";
53
+ import { CursorTranslator } from "./translator.js";
50
54
  import { runTurnBoundary, type TurnBoundaryResult } from "./turn-boundary.js";
51
55
  import {
52
56
  consumeCursorTurnStream,
@@ -80,21 +84,32 @@ export async function streamAndSettle(frame: CursorTurnFrame): Promise<TurnOutco
80
84
  const { executionId, sessionId, blueprint, workspace, mcp } = input;
81
85
  const { status } = sink;
82
86
 
83
- const deltaEnricher = new DeltaEnricher();
84
- const todoTracker = new TodoTracker(status.todos);
85
- const eventRecorder = createCursorEventRecorder(executionId);
87
+ // The runtime's one transcript builder over the turn's status, and this
88
+ // harness's translator over the run's approval posture and the seeded
89
+ // transcript (a resumed agent's re-issued call is matched onto its seeded
90
+ // WAITING row by identity). Both live for the whole turn — the
91
+ // primary stream and both recovery retries fold into them.
92
+ const transcript = sink.transcript;
93
+ const translator = new CursorTranslator({
94
+ policies: mcp.policies,
95
+ leases: { global: mcp.leases.global, categories: mcp.leases.categories },
96
+ seeded: status.messages,
97
+ });
98
+ // The raw recording of both SDK channels, on only when the env names a dir
99
+ // (the recorder reads no process state itself, so its tests need no env).
100
+ const eventRecorder = createCursorEventRecorder(executionId, process.env.CURSOR_EVENT_RECORD_DIR);
86
101
 
87
102
  // The two recovery retries (poisoned-handle / transport-timeout) below run at
88
103
  // most once per turn; this guard is the latch.
89
104
  let alreadyRetriedWithFreshAgent = false;
90
105
 
91
- // The shared onDelta only needs the sink/pricer/enricher/state subset, and
92
- // it is wired at SEND time — before the accumulator exists — so it takes the
93
- // narrow deps. The primary send and both retry sends reuse this object.
106
+ // The shared onDelta needs the sink/pricer/translator/recorder/state subset
107
+ // and is wired at SEND time. The primary send and both retry sends reuse this object.
94
108
  const onDeltaDeps: TurnOnDeltaDeps = {
95
109
  sink,
96
110
  usagePricer: engine.usagePricer,
97
- deltaEnricher,
111
+ translator,
112
+ eventRecorder,
98
113
  promptEstimatedTokens: prompt.promptEstimatedTokens,
99
114
  executionId,
100
115
  state: streamState,
@@ -138,15 +153,9 @@ export async function streamAndSettle(frame: CursorTurnFrame): Promise<TurnOutco
138
153
 
139
154
  // Everything at an index >= this was produced by THIS turn's stream — the
140
155
  // positional scope the boundary's #205 attribution and #965 settle read.
141
- // Snapshotted before the accumulator can append.
156
+ // Snapshotted before the builder can append.
142
157
  const turnStartMessageIndex = status.messages.length;
143
158
 
144
- const accumulator = new MessageAccumulator(status.messages, {
145
- mergedPolicies: mcp.policies,
146
- provenance: { globalBypass: mcp.leases.global, leasedCategories: mcp.leases.categories },
147
- workspaceRoot: workspace.primaryDir,
148
- subAgentExecutions: status.subAgentExecutions,
149
- });
150
159
  // Shared cadence with the native harness: discrete state changes force a
151
160
  // flush; high-frequency token deltas ride this scheduler's time cadence
152
161
  // (env-tunable via STREAMING_* — see loadStreamingConfig).
@@ -156,27 +165,29 @@ export async function streamAndSettle(frame: CursorTurnFrame): Promise<TurnOutco
156
165
  // state. Consumed by the primary stream here and by both recovery retries.
157
166
  const streamDeps: CursorTurnStreamDeps = {
158
167
  ...onDeltaDeps,
159
- accumulator,
160
- todoTracker,
161
- eventRecorder,
162
168
  scheduler,
163
169
  hitlDir: gate.hitlDir,
164
170
  };
165
171
 
166
172
  // Post-stream finalize, shared by the primary turn and both recovery retries:
167
- // finalize the transcript + streaming flags, mark any in-flight sub-agent
168
- // CANCELLED on a stopped turn, keep the usage summary's carrier current,
173
+ // fold the deltas that arrived after the last stream event (a completion
174
+ // the delta channel reported last was lost before #1097), close every
175
+ // streaming flag, mark any in-flight sub-agent CANCELLED on a stopped turn,
169
176
  // flush the recorder, and persist so the UI sees the settled rows.
170
177
  const finalizeStreamPhase = async (): Promise<void> => {
171
- accumulator.finalize();
172
- deltaEnricher.finalize(status.messages);
178
+ for (const fact of translator.drainDeltas()) transcript.apply(fact);
179
+ // The runtime finalizes once `runTurn` returns, on every path; this
180
+ // harness finalizes EARLIER too because it persists on the settled rows
181
+ // right below, before `run.wait()` and the boundary, and the console's
182
+ // spinner must stop before that wait. Idempotent.
183
+ transcript.finalize();
173
184
  // A stopped turn (pause, shutdown, stall, cost cap, platform stop) aborts
174
185
  // the Cursor SDK run, so any sub-agent the parent had delegated is no
175
186
  // longer executing. Mark it CANCELLED rather than leaving a permanent
176
- // IN_PROGRESS "zombie" in the final snapshot (parity with the native
177
- // harness's cancelSubAgents()).
187
+ // IN_PROGRESS "zombie" in the final snapshot, through the one shared act
188
+ // (parity with the native settle).
178
189
  if (sink.stopSignal.aborted) {
179
- accumulator.cancelInProgressSubAgents();
190
+ cancelInProgressSubAgentProtos(status.subAgentExecutions);
180
191
  }
181
192
  await eventRecorder?.flush();
182
193
  console.log(
@@ -196,6 +207,7 @@ export async function streamAndSettle(frame: CursorTurnFrame): Promise<TurnOutco
196
207
  const runBoundary = (denialSettled?: Promise<void>): Promise<TurnBoundaryResult> =>
197
208
  runTurnBoundary({
198
209
  status,
210
+ transcript,
199
211
  executionId,
200
212
  hitlDir: gate.hitlDir,
201
213
  primaryWorkspaceDir: workspace.primaryDir,
@@ -22,7 +22,7 @@
22
22
  * resolved, over the runtime's timeline (`sink.setupTiming`), so the one
23
23
  * timeline reads end to end.
24
24
  *
25
- * Moved from `index.ts` `executeCursorInner` phases 4c to 10c at S2 M3b; the
25
+ * Moved from `index.ts` `executeCursorInner` phases 4c to 10c in #1070; the
26
26
  * step bodies are the orchestrator's, verbatim where nothing changed.
27
27
  */
28
28
 
@@ -286,7 +286,7 @@ export async function installGate(input: TurnInput, sink: TurnSink, rows: Adjudi
286
286
  /**
287
287
  * Resolve the Cursor agent (parked, created, resumed, or created after a
288
288
  * resume failure), emit the cold-start line, and bind a NEW agent's id
289
- * through the sink before anything else runs (Q-S2-11: a rejected bind ends
289
+ * through the sink before anything else runs (a rejected bind ends
290
290
  * the turn `failed`; the sink rejects and the caller's catch names it).
291
291
  *
292
292
  * The requested name and the effective tier and thinking mode are the
@@ -446,7 +446,7 @@ export async function resolveEngine(input: TurnInput, sink: TurnSink, config: Cu
446
446
  // A NEW agent's id is bound at once, before anything else runs, so a crash
447
447
  // mid-turn still resumes on the next invocation. The mode is this
448
448
  // harness's field on the session record, set before the runtime writes it
449
- // (one writer per field, Q-S2-11); the runtime sets harness_state_id and
449
+ // (one writer per field); the runtime sets harness_state_id and
450
450
  // clears the slug.
451
451
  if (resolution.isNew && resolution.agentId) {
452
452
  if (blueprint.sessionSpec.cursorMode === CursorMode.UNSPECIFIED) {
@@ -459,8 +459,8 @@ export async function resolveEngine(input: TurnInput, sink: TurnSink, config: Cu
459
459
  // receives the engine only when this returns) and its id was never
460
460
  // saved, so no later turn can resume it: close it here, or its executor
461
461
  // lease and MCP subprocesses outlive the failed turn with nothing to
462
- // release them (S2 M4, Q-M4-8). Then let the rejection settle the turn
463
- // `failed` as R3 rules.
462
+ // release them (found by the contract kit in #1070). Then let the
463
+ // rejection settle the turn `failed`, as the contract states.
464
464
  try {
465
465
  resolution.agent.close();
466
466
  } catch {
@@ -10,20 +10,29 @@
10
10
  * retry froze the UI and mis-handled a mid-retry pause. One loop removes that
11
11
  * drift by construction.
12
12
  *
13
+ * The transcript (since #1097): every stream event goes through the harness's
14
+ * translator (`translator.ts`) into the shared `TranscriptBuilder`
15
+ * (`harness/transcript/builder.ts`), and the delta channel's facts, which the
16
+ * translator QUEUES as they arrive in `onDelta`, are drained into the builder
17
+ * after each stream event — never during an awaited persist, where a row
18
+ * write would land on a row the offload is replacing.
19
+ * Until #1097 this loop fed three writers of its own (the message accumulator,
20
+ * the delta enricher, the todo tracker), the Cursor copy of the folding rule.
21
+ *
13
22
  * What the loop asks of the runtime, through the sink (`harness/types.ts`):
14
23
  * `recordActivity()` per event (with the tool name) and per delta, so the
15
24
  * runtime's stall watchdog measures the engine; `reportUsage()` per
16
25
  * `turn-ended` delta, priced here at the requested variant's rates
17
26
  * (`usage-pricing.ts`), so the runtime accounts and enforces the cost cap;
18
27
  * `requestPersist()` where a discrete change or the streaming cadence says
19
- * so (`shared/persist-decision.ts` over this loop's own dirty flags), AWAITED,
28
+ * so (`shared/persist-decision.ts` over the builder's dirty flag), AWAITED,
20
29
  * so a platform STOP the runtime reads from that write aborts the signal
21
30
  * before the next event is pulled; and `stopSignal`, checked at every event
22
31
  * boundary and listened to inside the pull, where an abort cancels the SDK
23
32
  * run — the one way a wedged stream is unblocked, and the same act for every
24
33
  * cause of stopping (the runtime knows why; this loop never does).
25
34
  *
26
- * Until S2 M3 this loop armed its own stall watchdog, enforced the cost cap,
35
+ * Until #1070 this loop armed its own stall watchdog, enforced the cost cap,
27
36
  * read STOP from its own persist, and told a pause from the activity's
28
37
  * cancellation signal; every one of those is the runtime's now, and the loop
29
38
  * reports only `completed`, `first-denial` or `interrupted`.
@@ -33,9 +42,7 @@ import type { SDKMessage, InteractionUpdate } from "@cursor/sdk";
33
42
  import type { TurnSink } from "../../harness/types.js";
34
43
  import { shouldPersistStreamingStatus } from "../../shared/persist-decision.js";
35
44
  import { approvalDenials, readDenialLedger } from "./approval-state.js";
36
- import type { MessageAccumulator } from "./message-translator.js";
37
- import type { DeltaEnricher } from "./delta-enricher.js";
38
- import type { TodoTracker } from "./todo-tracker.js";
45
+ import type { CursorTranslator } from "./translator.js";
39
46
  import type { StreamingUpdateScheduler } from "../../shared/streaming-scheduler.js";
40
47
  import type { CursorUsagePricer } from "./usage-pricing.js";
41
48
  import type { createCursorEventRecorder } from "./cursor-event-recorder.js";
@@ -74,7 +81,7 @@ export interface TurnStreamState {
74
81
  denialCancelSettled: Promise<void> | undefined;
75
82
  /** Written by: the loop (a stream ERROR status event) + the retry setup (reset). Read by: error classification. */
76
83
  streamErrorMessage: string | undefined;
77
- /** Written by: the loop. Read by: the event recorder, the persist cadence, and logs. */
84
+ /** Written by: the loop. Read by: the persist cadence and logs. */
78
85
  eventCount: number;
79
86
  /** Written + read by: onDelta (log the first turn's context attribution exactly once). */
80
87
  firstTurnAttributionLogged: boolean;
@@ -92,24 +99,25 @@ export function newTurnStreamState(): TurnStreamState {
92
99
  }
93
100
 
94
101
  /**
95
- * The subset of collaborators the shared onDelta needs. Broken out from
96
- * CursorTurnStreamDeps because the primary send happens BEFORE the accumulator
97
- * exists — onDelta only touches the sink, the pricer, the enricher, and state.
102
+ * The subset of collaborators the shared onDelta needs — the sink, the
103
+ * pricer, the translator (which queues the delta's transcript facts), the
104
+ * recorder (which sequences the delta with the stream events around it) and
105
+ * the state. Broken out from CursorTurnStreamDeps so the send that wires
106
+ * onDelta needs nothing of the stream loop.
98
107
  */
99
108
  export interface TurnOnDeltaDeps {
100
109
  readonly sink: TurnSink;
101
110
  /** This harness's pricing of a `turn-ended` delta at the requested variant's rates. */
102
111
  readonly usagePricer: CursorUsagePricer;
103
- readonly deltaEnricher: DeltaEnricher;
112
+ readonly translator: CursorTranslator;
113
+ /** The raw recording of both channels (`cursor-event-recorder.ts`); undefined when recording is off. */
114
+ readonly eventRecorder: CursorTurnEventRecorder | undefined;
104
115
  readonly promptEstimatedTokens: number;
105
116
  readonly executionId: string;
106
117
  readonly state: TurnStreamState;
107
118
  }
108
119
 
109
120
  export interface CursorTurnStreamDeps extends TurnOnDeltaDeps {
110
- readonly accumulator: MessageAccumulator;
111
- readonly todoTracker: TodoTracker;
112
- readonly eventRecorder: CursorTurnEventRecorder | undefined;
113
121
  readonly scheduler: StreamingUpdateScheduler;
114
122
  /** Session HITL dir holding the denial ledger; undefined → no gate installed → no first-denial stop. */
115
123
  readonly hitlDir: string | undefined;
@@ -119,17 +127,21 @@ export interface CursorTurnStreamDeps extends TurnOnDeltaDeps {
119
127
  * Build the shared onDelta callback. The Cursor SDK's fine-grained delta channel
120
128
  * carries token usage, live shell output, and precise tool-call timings; it also
121
129
  * fires far more often than discrete stream events, so it is where the runtime's
122
- * stall timer is reset during a long model generation.
130
+ * stall timer is reset during a long model generation. Usage is priced here
131
+ * (a loop concern); the transcript facts are the translator's to queue.
123
132
  */
124
133
  export function makeCursorTurnOnDelta(
125
134
  deps: TurnOnDeltaDeps,
126
135
  ): (event: { update: InteractionUpdate }) => void {
127
- const { sink, usagePricer, deltaEnricher, promptEstimatedTokens, executionId, state } = deps;
136
+ const { sink, usagePricer, translator, eventRecorder, promptEstimatedTokens, executionId, state } = deps;
128
137
  return ({ update }) => {
129
138
  // Progress on the delta channel too: a long model generation emits token
130
139
  // deltas but few discrete stream events, and resetting only in the stream
131
140
  // loop would false-positive a stall.
132
141
  sink.recordActivity();
142
+ // Recorded on arrival, before anything reads it, so the file's order is
143
+ // the SDK's order across both channels.
144
+ eventRecorder?.recordDelta(update);
133
145
  if (update.type === "turn-ended" && update.usage) {
134
146
  // The running estimate advances only here; the runtime enforces the cap
135
147
  // and aborts the signal, which the loop reads at the next boundary.
@@ -146,7 +158,7 @@ export function makeCursorTurnOnDelta(
146
158
  );
147
159
  }
148
160
  }
149
- deltaEnricher.processDelta(update);
161
+ translator.observeDelta(update);
150
162
  };
151
163
  }
152
164
 
@@ -164,16 +176,14 @@ export async function consumeCursorTurnStream(
164
176
  ): Promise<TurnStreamReason> {
165
177
  const {
166
178
  sink,
167
- accumulator,
168
- todoTracker,
169
- deltaEnricher,
179
+ translator,
170
180
  eventRecorder,
171
181
  scheduler,
172
182
  hitlDir,
173
183
  executionId,
174
184
  state,
175
185
  } = deps;
176
- const { status, stopSignal } = sink;
186
+ const { stopSignal, transcript } = sink;
177
187
 
178
188
  // The runtime's stop, whatever its cause, ends the run through the SDK's
179
189
  // own cancel: that is what unblocks a wedged `for await` (a stall), and it
@@ -205,14 +215,13 @@ export async function consumeCursorTurnStream(
205
215
  // naming the tool so a stall's copy can say `last tool: shell`.
206
216
  sink.recordActivity(event.type === "tool_call" && typeof event.name === "string" ? event.name : undefined);
207
217
 
208
- eventRecorder?.record(event, state.eventCount);
218
+ eventRecorder?.record(event);
209
219
 
210
- accumulator.processEvent(event);
211
- todoTracker.processEvent(event);
212
-
213
- if (event.type === "tool_call" && event.name === "task") {
214
- accumulator.trackSubAgentExecution(event as Extract<SDKMessage, { type: "tool_call" }>);
215
- }
220
+ // The stream event, then the deltas that arrived since the last one —
221
+ // the enricher's order, kept so a completion the delta channel reported
222
+ // in the same window as the stream's own defers to the stream's instant.
223
+ for (const fact of translator.translate(event)) transcript.apply(fact);
224
+ for (const fact of translator.drainDeltas()) transcript.apply(fact);
216
225
 
217
226
  // First-denial stop (HITL clean pause). In CAPTURE mode this fires only for
218
227
  // an IRREVERSIBLE tool the hook still gates (shell, MCP, or a gitignored
@@ -228,7 +237,7 @@ export async function consumeCursorTurnStream(
228
237
  // post-denial reaction (thinking, narration, a workaround shell) stream and
229
238
  // persist live (production case aex_01kwj07f7g23c3wp9sn8496z5g). The
230
239
  // tool_call-event read stays as the backstop for platforms where fs.watch
231
- // is unreliable; the current event was already accumulated above, so the
240
+ // is unreliable; the current event was already folded above, so the
232
241
  // anchor's own row is always present for the turn-boundary gate overlay.
233
242
  if (!state.firstDenialDetected && hitlDir && (state.denialLedgerDirty || event.type === "tool_call")) {
234
243
  state.denialLedgerDirty = false;
@@ -262,7 +271,6 @@ export async function consumeCursorTurnStream(
262
271
  }
263
272
  }
264
273
 
265
- deltaEnricher.applyEnrichments(status.messages);
266
274
  state.eventCount++;
267
275
 
268
276
  if (event.type === "status") {
@@ -278,27 +286,22 @@ export async function consumeCursorTurnStream(
278
286
  }
279
287
  }
280
288
 
281
- const shouldPersist = shouldPersistStreamingStatus(
282
- {
283
- deltaEnricherDirty: deltaEnricher.isDirty,
284
- todosDirty: todoTracker.isDirty,
285
- contentDirty: accumulator.isDirty,
286
- },
287
- scheduler,
288
- state.eventCount,
289
- );
289
+ // The builder's one flag is the discrete signal, as on native
290
+ // (`shared/persist-decision.ts`).
291
+ const shouldPersist = shouldPersistStreamingStatus(transcript.dirty, scheduler, state.eventCount);
290
292
  if (shouldPersist) {
291
- // The accumulator upserts sub-agent rows into `status.subAgentExecutions`
292
- // in place (wrapped by reference at construction), so every persist
293
- // already carries delegation, IN_PROGRESS included. The runtime attaches
294
- // the mid-run file-change progress on this write (the chokepoint's
295
- // step 2), as it does on every write.
293
+ // Cleared as the write is requested, not after it lands (the same
294
+ // order as the native loop): a change that folds while the write is
295
+ // in flight must dirty the next one.
296
+ transcript.markPersisted();
297
+ // The builder upserts sub-agent rows into `status.subAgentExecutions`
298
+ // in place (the status's own array), so every persist already carries
299
+ // delegation, IN_PROGRESS included. The runtime attaches the mid-run
300
+ // file-change progress on this write (the chokepoint's step 2), as it
301
+ // does on every write.
296
302
  // Awaited: the runtime reads the control plane's answer to this write,
297
303
  // and a STOP must be seen at the next event boundary, not one event late.
298
304
  await sink.requestPersist();
299
- deltaEnricher.markPersisted();
300
- todoTracker.markPersisted();
301
- accumulator.markPersisted();
302
305
  scheduler.markUpdateSent(state.eventCount);
303
306
  }
304
307
  }
@@ -25,17 +25,17 @@
25
25
  * on why `stopSignal` aborted, never writes a phase or a terminal copy, never
26
26
  * imports `@temporalio/*` (`__tests__/adapter-is-temporal-free.test.ts`).
27
27
  *
28
- * Engine disposition, one rule per outcome (Q-S2-6): the agent is PARKED
28
+ * Engine disposition, one rule per outcome: the agent is PARKED
29
29
  * for the session's next turn on every exit but a failure — `completed`,
30
30
  * `cancelled`, `awaiting_approval` and `interrupted` alike (a wedged handle
31
31
  * after a stall is caught by the poisoned-handle recovery on the next turn;
32
- * before S2 a pause, a shutdown and a stall dropped the handle, leaking the
32
+ * before #1070 a pause, a shutdown and a stall dropped the handle, leaking the
33
33
  * executor lease). A `failed` turn keeps the orchestrator's three
34
34
  * dispositions: an engine-reported failure parks (a bad key is not a bad
35
35
  * handle), a user-actionable failure closes, an internal failure drops.
36
36
  *
37
- * Extracted from `index.ts` `executeCursorInner` at S2 M3b and moved out of
38
- * `adapter.ts` at S2 M5; the seventeen hermetic goldens under `__tests__/hermetic/`
37
+ * Extracted from `index.ts` `executeCursorInner` and moved out of
38
+ * `adapter.ts` in #1070; the seventeen hermetic goldens under `__tests__/hermetic/`
39
39
  * pin the result byte for byte.
40
40
  */
41
41
 
@@ -67,7 +67,7 @@ export async function runCursorTurn(input: TurnInput, sink: TurnSink, config: Cu
67
67
  closeProxySessions();
68
68
  // The module-level fallback the interceptors read when no execution
69
69
  // context is entered (the runtime enters one around the whole activity;
70
- // the SDK warm-up in main.ts has none). Deprecated; an S5 footprint item.
70
+ // the SDK warm-up in main.ts has none). Deprecated; its removal is #1132.
71
71
  setInterceptorExecutionId(executionId);
72
72
 
73
73
  if (sink.stopSignal.aborted) return { kind: "interrupted" };
@@ -4,11 +4,11 @@
4
4
  * basis on the priced delta the runtime accumulates.
5
5
  *
6
6
  * The runtime cannot price without the vendor's table and variant semantics,
7
- * and it must not import them (Q-S2-12), so the adapter hands
7
+ * and it must not import them, so the adapter hands
8
8
  * `TurnSink.reportUsage` a delta that already carries `estimatedCostUsd`
9
9
  * and the basis (`model`, the catalog-validated id; `requestedModelParams`,
10
10
  * the JSON of the params sent with every create/resume) the runtime writes
11
- * into `streaming_usage`. Split out of the accumulator at S2 M3
11
+ * into `streaming_usage`. Split out of the accumulator in #1070
12
12
  * (`harness/usage-accumulator.ts` keeps the sums); the arithmetic and the
13
13
  * rounding are unchanged, so the estimate is byte-for-byte the old one.
14
14
  *
@@ -10,7 +10,7 @@
10
10
  * module owns the ENGINE — what the model will do on its next call — and
11
11
  * reports what really happened. The adapter under test is the production
12
12
  * one, untouched; the model client is the one module doubled
13
- * (`scripted-model-module.ts`, S3 M0 ruling Q-M0-1), and the tools the model
13
+ * (`scripted-model-module.ts`), and the tools the model
14
14
  * calls are deepagents' real built-ins over the real gate.
15
15
  *
16
16
  * ── The engine is per execution, and its memory is the conversation ────────
@@ -28,7 +28,7 @@
28
28
  * checkpoint IS the engine's memory, which is why the same plan is right on
29
29
  * a `Command(resume)` (the tool result is in the transcript before the model
30
30
  * is asked) and on a later turn of the same thread (an approved-and-run call
31
- * is not proposed again — Cursor's "obedient model" of Q-M4-4, derived
31
+ * is not proposed again — Cursor's subject's "obedient model", derived
32
32
  * instead of stored).
33
33
  *
34
34
  * ── The translation, one rule per word ──────────────────────────────────────
@@ -41,25 +41,30 @@
41
41
  * network. A scenario picks one; the HITL arms record both.
42
42
  *
43
43
  * The ONE knowledge of production this driver holds is `activityFactory`: how
44
- * to obtain the `ExecuteDeepAgent` function from a `Config`. Since S3 M2a it
44
+ * to obtain the `ExecuteDeepAgent` function from a `Config`. Since #1096 it
45
45
  * is the harness registry's: the native adapter booted and bound to its
46
46
  * byte-pinned activity name through `createHarnessActivities`, exactly the
47
- * way the composition roots bind it since S3 M2b through `harness-adapters.ts`
47
+ * way the composition roots bind it since #1096 through `harness-adapters.ts`
48
48
  * (and the way the Cursor driver binds its own, `hermetic-cursor.ts`). The
49
- * orchestrator this adapter replaced (`index.ts`, `setup.ts`) was deleted at
50
- * M2b; the goldens moved once, with the M2a flip, each hunk quoted with its
51
- * ruling in its test's header (Q-M2a-1), and the switch of the roots moved
52
- * none (Q-M2b-4).
49
+ * orchestrator this adapter replaced (`index.ts`, `setup.ts`) was deleted in
50
+ * #1096; the goldens moved once, with the flip onto the runtime, each hunk
51
+ * quoted with its reason in its test's header, and the switch of the roots
52
+ * moved none.
53
53
  *
54
54
  * `boot` registers the deepagents harness profiles as production does
55
- * (S3 M2a F-M2a-14: the orchestrator-driven runs never did, so deepagents
56
- * auto-injected its ungated `general-purpose` sub-agent into every M0
55
+ * (found in #1096: the orchestrator-driven runs never did, so deepagents
56
+ * auto-injected its ungated `general-purpose` sub-agent into every earlier
57
57
  * scenario; the scripted model never delegated to it).
58
58
  *
59
- * Determinism beyond S0's: the clock ticks once per model turn (the scripted
59
+ * Determinism beyond the Cursor driver's (#1048): the clock ticks once per model turn (the scripted
60
60
  * model's `onTurn`), so status timestamps and the persist cadence land on the
61
61
  * same instants every run; a scenario's interruption (pause, worker shutdown)
62
- * is scheduled on a model turn through the same hook, never on a timer.
62
+ * is scheduled on a model turn through the same hook, never on a timer. And
63
+ * a turn does not begin — the clock does not tick — until the loop has
64
+ * persisted the previous turn's tool results settled
65
+ * (`ExecutionRecord.whenToolCallsSettled`): the ground a real model's latency
66
+ * gives for free, without which the producer runs ahead of a consumer that is
67
+ * awaiting a slow persist and the stamps of one turn straddle the next tick.
63
68
  */
64
69
 
65
70
  import { rmSync } from "node:fs";
@@ -174,7 +179,7 @@ export function sessionWorkspaceDir(env: HermeticEnvironment): string {
174
179
  /** The `ExecuteDeepAgent` function as the runner serves it: the typed object OR the legacy positional pair. */
175
180
  export type ExecuteDeepAgentFn = (arg0: ExecuteActivityInput | string, arg1?: string) => Promise<unknown>;
176
181
 
177
- /** How the driver obtains the activity from a `Config` — the one seam M2 flips. */
182
+ /** How the driver obtains the activity from a `Config` — the one seam the move onto the runtime flipped. */
178
183
  export type ActivityFactory = (config: Config) => Promise<ExecuteDeepAgentFn>;
179
184
 
180
185
  /**
@@ -225,6 +230,13 @@ export class DeepAgentScenario {
225
230
  ) {
226
231
  this.model = new ScriptedModel(script, [], {
227
232
  onTurn: async (info) => {
233
+ // A real model answers long after the loop has folded and persisted
234
+ // the tool results it is answering; a scripted one answers at once and
235
+ // lets the producer run a turn ahead of the consumer. Wait for that
236
+ // ground before ticking, so every stamp of the previous turn precedes
237
+ // this turn's instant, whatever the persist's I/O took (the barrier's
238
+ // own header on `ExecutionRecord` carries the whole reason).
239
+ await this.record.whenToolCallsSettled(info.priorToolCallIds);
228
240
  this.clock.tick();
229
241
  if (onTurn && this.controls) await onTurn(info, this.controls);
230
242
  },
@@ -29,7 +29,7 @@ export const EXECUTE_CALL_B: ScriptedToolCall = {
29
29
 
30
30
  /** The gate's copy for a SHELL built-in (`CATEGORY_APPROVAL_MESSAGE.shell` over the args). */
31
31
  export function executeApprovalMessage(call: ScriptedToolCall): string {
32
- return `Execute command: ${String(call.args.command)}`;
32
+ return `Run command: ${String(call.args.command)}`;
33
33
  }
34
34
 
35
35
  /** Round 0 of every gated arm: one text block and the gated `execute` A. */
@@ -9,8 +9,7 @@
9
9
  * (`shared/extract-structured-output.ts`). None of them takes a model as an
10
10
  * argument, so the one seam a hermetic run has is this module — the native analog of the Cursor
11
11
  * driver's `vi.mock("@cursor/sdk")`: the vendor engine doubled where the
12
- * runner imports it, and nothing else (S3 M0 ruling Q-M0-1, amending
13
- * Q-S3-11).
12
+ * runner imports it, and nothing else.
14
13
  *
15
14
  * `vi.mock` is hoisted and must live in the test file; the factory can
16
15
  * `await import()` this module:
@@ -33,7 +32,7 @@
33
32
  * header), so a test that runs several executions at once — the harness
34
33
  * contract kit's concurrency invariant — routes each build to that
35
34
  * execution's own engine through the id production already sends, and
36
- * through nothing added for the test (S3 M3).
35
+ * through nothing added for the test.
37
36
  */
38
37
 
39
38
  import type { BuildChatModelOptions, BuiltChatModel } from "../../../shared/model-client.js";
@@ -28,7 +28,7 @@
28
28
  * indexing left to the caller — for a consumer whose plan is not "turn k on
29
29
  * round k" but "the first step the conversation does not yet show" (the
30
30
  * harness contract kit's native subject, whose one execution spans many
31
- * kit turns on one sqlite thread, S3 M3).
31
+ * kit turns on one sqlite thread).
32
32
  *
33
33
  * A turn may END the model call instead of finishing the message
34
34
  * ({@link TurnEnding}): `fail` throws after its chunks (a provider error
@@ -46,8 +46,8 @@
46
46
  * and otherwise falls back to a synthesized final-message event sequence
47
47
  * (`@langchain/langgraph` `pregel/messages-v2.js` `emitFinalMessage`). The
48
48
  * fallback spreads a `tool_call` block's `args` OBJECT into the
49
- * `tool_call_chunk` fields the runner's normalizer reads as a JSON STRING
50
- * (`v3-protocol-normalizer.ts` `argsChunk`), which no real provider does.
49
+ * `tool_call_chunk` fields the runner's translator reads as a JSON STRING
50
+ * (`translator.ts` `argsChunk`), which no real provider does.
51
51
  * Streaming keeps the double on the production event path: `@langchain/core`
52
52
  * `language_models/compat.js` `convertChunksToEvents` turns the chunks below
53
53
  * into `message-start`, per-block `content-block-start` / `-delta` /
@@ -181,6 +181,13 @@ export type ScriptSelector = (boundToolNames: string[], context: ScriptRoleConte
181
181
  export interface ScriptedTurnInfo {
182
182
  readonly boundToolNames: readonly string[];
183
183
  readonly round: number;
184
+ /**
185
+ * The ids of the tool calls the transcript's last AI message made — the
186
+ * calls whose results this turn answers. Empty on a role's first turn and
187
+ * after a text-only turn. Read from the transcript the engine hands the
188
+ * model, never from the script, so it is what the engine actually ran.
189
+ */
190
+ readonly priorToolCallIds: readonly string[];
184
191
  }
185
192
 
186
193
  export interface ScriptedModelOptions {
@@ -240,7 +247,11 @@ export class ScriptedModel extends BaseChatModel {
240
247
  /** The turn for this transcript, after the driver hook has run. */
241
248
  private async turnFor(messages: BaseMessage[]): Promise<ScriptedTurn> {
242
249
  const round = completedToolRounds(messages);
243
- await this.options.onTurn?.({ boundToolNames: this.toolNames, round });
250
+ await this.options.onTurn?.({
251
+ boundToolNames: this.toolNames,
252
+ round,
253
+ priorToolCallIds: priorToolCallIds(messages),
254
+ });
244
255
  const context: ScriptRoleContext = { systemPrompt: systemPromptOf(messages) };
245
256
  return resolveTurn(this.select(this.toolNames, context), { round, transcript: messages, toolNames: this.toolNames });
246
257
  }
@@ -347,6 +358,16 @@ export function completedToolRounds(messages: readonly BaseMessage[]): number {
347
358
  return rounds;
348
359
  }
349
360
 
361
+ /** The tool-call ids on the transcript's last AI message; `[]` when there is none or it made no calls. */
362
+ export function priorToolCallIds(messages: readonly BaseMessage[]): string[] {
363
+ for (let i = messages.length - 1; i >= 0; i--) {
364
+ const m = messages[i];
365
+ if (!isAIMessage(m)) continue;
366
+ return (m.tool_calls ?? []).flatMap((call) => (call.id ? [call.id] : []));
367
+ }
368
+ return [];
369
+ }
370
+
350
371
  /** What one model call knows when it picks its turn. */
351
372
  interface TurnRequest {
352
373
  readonly round: number;