@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
@@ -6,7 +6,7 @@
6
6
  * with the engine that will run it: the execution and its session, the
7
7
  * agent blueprint, the environment, the workspace and its lock, what the
8
8
  * previous turn left waiting for approval, the MCP servers and their
9
- * approval policies, the attachments, the standing context. Until S2 M2
9
+ * approval policies, the attachments, the standing context. Until #1070
10
10
  * that sequence lived inline in the Cursor orchestrator
11
11
  * (`activities/execute-cursor/index.ts` `executeCursorInner`, phases 1 to
12
12
  * 9c); the native orchestrator carried a second copy in its `performSetup`.
@@ -16,16 +16,16 @@
16
16
  * sequences them, and the adapter runs its own harness-specific steps after
17
17
  * the whole record exists.
18
18
  *
19
- * Shape, chosen against the native orchestrator's `setup.ts` (deleted at S3
20
- * M2b): a typed record built from small functions (the `SetupResult` mold),
19
+ * Shape, chosen against the native orchestrator's `setup.ts` (deleted in
20
+ * #1096): a typed record built from small functions (the `SetupResult` mold),
21
21
  * never one 775-line `performSetup`. The record is the adapter contract's `TurnInput`
22
22
  * (`types.ts`): every phase returns a named slice of it, and
23
23
  * {@link resolveTurnContext} composes the whole. There is no wider
24
24
  * "runtime-private" record beside it — the lock release and the write-back
25
25
  * coordinator a phase produces are the caller's `TurnFrame` resources, set
26
- * the instant they exist so a `finally` sees them on every path (M2 had a
27
- * `TurnContext extends TurnInput` for them; once the groups lifted, nothing
28
- * read the extension after composition, so M3 deleted it).
26
+ * the instant they exist so a `finally` sees them on every path (a first cut
27
+ * had a `TurnContext extends TurnInput` for them; once the groups lifted,
28
+ * nothing read the extension after composition, so #1070 shipped without it).
29
29
  *
30
30
  * Three rules every phase obeys:
31
31
  *
@@ -41,17 +41,17 @@
41
41
  * - Its heartbeat pulse and its cold-start timing marks are its own: the
42
42
  * step name it enters under is the mark name it emits, one vocabulary for
43
43
  * "where in setup are we" in Temporal heartbeat details and the
44
- * `execution_setup` log (Q-S2-10).
44
+ * `execution_setup` log.
45
45
  *
46
46
  * What is deliberately NOT here, and where it is instead:
47
47
  *
48
48
  * - Cursor's catalog validation of the requested model (`resolveModelId`),
49
49
  * the pricing preload and the MCP env pre-flight warning stay in the
50
- * Cursor adapter for S2: each reads a module in the adapter column of the
51
- * entry's disposition table, and the runtime carries the REQUESTED model
52
- * name so every harness validates against its own catalog (S2 M2 gate,
53
- * Q-M2-1). The skill mount was in that list until M3b found it reads the
54
- * control plane, which only the runtime holds; it is {@link mountSkills}.
50
+ * Cursor adapter: each reads a module that is the adapter's own, and the
51
+ * runtime carries the REQUESTED model name so every harness validates
52
+ * against its own catalog. The skill mount was in that list until #1070
53
+ * found it reads the control plane, which only the runtime holds; it is
54
+ * {@link mountSkills}.
55
55
  * - The approval grants, the HITL gate, the capture baseline pin and the
56
56
  * Cursor agent itself (phases 5c, 7, 8a, 9) are the adapter's.
57
57
  * - The memory selection is a memoized thunk, not a value: whether a prompt
@@ -81,7 +81,6 @@ import { resolveBlueprint, type ResolvedBlueprint } from "../shared/blueprint-re
81
81
  import { resolveExecutionEnv } from "../shared/env-resolver.js";
82
82
  import { provisionSessionWorkspace } from "../shared/workspace/session-provision.js";
83
83
  import { WriteBackCoordinator } from "../shared/workspace/writeback-coordinator.js";
84
- import { statusProtoWriter } from "../shared/execution-status-writer.js";
85
84
  import { isGitWorkTree } from "../shared/filereview/git-substrate.js";
86
85
  import { applyCaptureDecisions, deriveCaptureMode } from "../shared/filereview/capture.js";
87
86
  import { casBlobReader } from "../shared/filereview/cas-substrate.js";
@@ -116,6 +115,7 @@ import { readConversationCatchup } from "../shared/conversation-catchup.js";
116
115
  import { selectRecalledFacts } from "../shared/memory-retrieval.js";
117
116
  import type { RecalledMemoriesContent } from "../shared/recalled-memories.js";
118
117
  import type { FileReviewIdentity, HarnessCapabilities, PausePrimitive, StateIdSource } from "./capabilities.js";
118
+ import type { TranscriptBuilder } from "./transcript/builder.js";
119
119
  import type {
120
120
  TurnAttachments,
121
121
  TurnEnvironment,
@@ -135,7 +135,7 @@ import type {
135
135
  * What every phase reads from its caller. The activity's identity and the
136
136
  * runtime's own seams; nothing harness-specific. The four function members
137
137
  * are the caller's, injected so the phase bodies are the same code under
138
- * the Cursor orchestrator today and under `run-turn.ts` in M3 (only the
138
+ * the Cursor orchestrator it left and under `run-turn.ts` (only the
139
139
  * binding changes), and so a test can drive a phase without a Temporal
140
140
  * activity context.
141
141
  */
@@ -151,10 +151,20 @@ export interface ResolutionDeps {
151
151
  readonly config: Config;
152
152
  /**
153
153
  * The one execution status this turn folds into. Phases that carry state
154
- * across invocations write here (the seeded transcript, the file-review
155
- * reconcile's events, the memory-selection report); nothing else does.
154
+ * across invocations write the runtime's OWN fields here (the file-review
155
+ * reconcile's events, the memory-selection report, the seeded singletons);
156
+ * nothing else does.
156
157
  */
157
158
  readonly status: AgentExecutionStatus;
159
+ /**
160
+ * The one transcript builder over `status`, the caller's, born with the
161
+ * status. Two phases hand it on: the seed appends a reinvocation's prior
162
+ * rows through it (so they are indexed as they land), and the workspace
163
+ * phase gives it to the write-back coordinator as the place a write-back
164
+ * record is registered. No phase folds an event into it — no engine has
165
+ * run yet.
166
+ */
167
+ readonly transcript: TranscriptBuilder;
158
168
  /** Resolved once by the caller before any phase; absent when no substrate works. */
159
169
  readonly artifactStorage: ArtifactStorage | undefined;
160
170
  /** The cold-start timeline; each phase marks its own segment(s) exactly as before. */
@@ -199,7 +209,7 @@ export interface TurnReinvocation {
199
209
  * A turn that ended during resolution, before any harness ran. Each arm
200
210
  * names what was decided and carries only the facts the caller's status
201
211
  * writes need; the copy, the phase flip, the persist and the slim return are
202
- * the caller's (the orchestrator today, the runtime's terminal table in M3).
212
+ * the caller's (the runtime's terminal table).
203
213
  *
204
214
  * - `workspace-lock-timeout`: another turn held the primary tree past
205
215
  * `Config.workspaceLockTimeoutMs`. FAILED, returned (a Temporal retry
@@ -238,7 +248,7 @@ export type ReinvocationOutcome =
238
248
  /**
239
249
  * Whether the engine already holds state for this execution, so this
240
250
  * invocation resumes rather than begins. One function keyed on how the
241
- * harness mints its state id (Q-S2-8):
251
+ * harness mints its state id:
242
252
  *
243
253
  * - `engine-minted` (Cursor: the agent id): the runtime knows nothing until
244
254
  * the adapter binds an id, so a non-empty `threadId` IS the evidence.
@@ -260,7 +270,7 @@ export type ReinvocationOutcome =
260
270
  * the exact-apply). An adapter that needs create-vs-resume for its ENGINE
261
271
  * reads `input.threadId` itself — for an engine-minted harness that is the
262
272
  * same bit, for a deterministic one the engine's checkpoint is the adapter's
263
- * to consult — so the contract carries no flag with two meanings (Q-M1-7).
273
+ * to consult — so the contract carries no flag with two meanings.
264
274
  */
265
275
  export function isReinvocation(
266
276
  stateIdSource: StateIdSource,
@@ -299,10 +309,10 @@ export interface ReinvocationFacts {
299
309
  * nothing else is complete, because keeping or discarding a file never
300
310
  * re-prompts the agent (Cursor-like). `undefined` means "run the agent".
301
311
  *
302
- * Until S3 M1 a REJECT failed the turn here with its own FAILED arm, Cursor's
312
+ * Until #1096 a REJECT failed the turn here with its own FAILED arm, Cursor's
303
313
  * legacy; the proto (`APPROVAL_ACTION_REJECT`: "does NOT fail the run"), the
304
314
  * conformance suite and the native harness said otherwise since stigmer#197,
305
- * and the runtime now agrees (S2 M4 finding F1; Q-S3-2).
315
+ * and the runtime now agrees.
306
316
  */
307
317
  export function decideReinvocation(
308
318
  facts: ReinvocationFacts,
@@ -326,14 +336,15 @@ export function decideReinvocation(
326
336
  *
327
337
  * Why the transcript must be seeded: a resumed engine re-issues the
328
338
  * previously gated tool calls with brand-new call ids. Without seeding, the
329
- * harness's accumulator would rebuild the transcript from empty and emit a
339
+ * harness's transcript builder would rebuild the transcript from empty and emit a
330
340
  * status that drops the already-committed tool-call ids. The backend's
331
341
  * append-only-at-identity guard rejects any non-terminal update that drops a
332
342
  * committed tool-call id, so the resumed progress would never persist: the
333
343
  * run stalls in WAITING_FOR_APPROVAL with no pending approvals and the
334
344
  * workflow watchdog fails it. Seeding makes the resume status a strict
335
345
  * superset; the re-runs are then reconciled in place onto these seeded calls
336
- * by canonical identity inside the accumulator.
346
+ * by canonical identity inside the harness's translator (the Cursor translator's
347
+ * seeded-row match; the native builder's by-id flip).
337
348
  *
338
349
  * Why the OTHER collections must be seeded too — the server's merge rule
339
350
  * (`stigmer-server/src/domain/agentexecution/update-status.ts`): every list
@@ -355,28 +366,32 @@ export function decideReinvocation(
355
366
  * `phase`, `startedAt`, `completedAt`, `error` are this turn's fresh
356
367
  * terminal, written by the runtime.
357
368
  *
358
- * Every collection is mutated IN PLACE (pushed into, assigned into), never
359
- * reassigned: the write-back coordinator already wraps this status through
360
- * `statusProtoWriter`, and the harness's accumulator wraps `messages` and
361
- * `subAgentExecutions` by reference after this runs, so a reassigned array
362
- * would leave a wrapper holding the old one. The persisted protos are
363
- * cloned so the input execution stays immutable.
369
+ * The transcript half — messages, sub-agent rows, artifacts, write-backs,
370
+ * todos — goes through the builder's `seed()`, which appends every
371
+ * collection IN PLACE (the status's own arrays, so every wrapper of the
372
+ * status keeps seeing every row) and indexes the rows as it appends, so the
373
+ * upcoming turn's re-issued call reconciles onto its seeded row. The three
374
+ * singletons are the runtime's own and are set here. The persisted protos
375
+ * are cloned so the input execution stays immutable.
364
376
  *
365
377
  * Moved from `execute-cursor/index.ts` `seedCursorTranscriptFromExecution`
366
- * (messages only) and widened at S3 M1 to what native's whole-status clone
378
+ * (messages only) and widened in #1096 to what native's whole-status clone
367
379
  * (`execute-deep-agent/index.ts` `seedStatusFromExecution`, retired with its
368
380
  * orchestrator) always carried, minus the fields above that it carried by
369
- * accident (Q-S3-16).
381
+ * accident. Until #1097 the transcript half was pushed straight
382
+ * onto the status here and the adapters constructed their builders after
383
+ * this ran — an ordering the builder's index depended on and nothing
384
+ * enforced; the seed through the builder makes it a non-question.
370
385
  */
371
- export function seedFromPersistedStatus(status: AgentExecutionStatus, execution: AgentExecution): void {
386
+ export function seedFromPersistedStatus(
387
+ status: AgentExecutionStatus,
388
+ transcript: TranscriptBuilder,
389
+ execution: AgentExecution,
390
+ ): void {
372
391
  const persisted = execution.status;
373
392
  if (!persisted || persisted.messages.length === 0) return;
374
393
  const seed = clone(AgentExecutionStatusSchema, persisted);
375
- status.messages.push(...seed.messages);
376
- status.subAgentExecutions.push(...seed.subAgentExecutions);
377
- status.artifacts.push(...seed.artifacts);
378
- status.workspaceWriteBacks.push(...seed.workspaceWriteBacks);
379
- for (const [id, todo] of Object.entries(seed.todos)) status.todos[id] = todo;
394
+ transcript.seed(seed);
380
395
  if (seed.streamingUsage !== undefined) status.streamingUsage = seed.streamingUsage;
381
396
  if (seed.recalledMemoriesReport !== undefined) status.recalledMemoriesReport = seed.recalledMemoriesReport;
382
397
  if (seed.structuredOutput !== undefined) status.structuredOutput = seed.structuredOutput;
@@ -459,7 +474,7 @@ export async function provisionWorkspace(
459
474
 
460
475
  const writeback = provision.provisionResults.length > 0
461
476
  ? new WriteBackCoordinator({
462
- statusWriter: statusProtoWriter(deps.status),
477
+ writeBacks: deps.transcript,
463
478
  executionId: deps.input.executionId,
464
479
  sessionId: args.sessionId,
465
480
  githubToken: args.envVars.GITHUB_TOKEN ?? "",
@@ -550,7 +565,7 @@ export async function bindTelemetryBaggage(
550
565
  *
551
566
  * On a reinvocation, first seed the in-progress status from the persisted
552
567
  * execution ({@link seedFromPersistedStatus}), BEFORE the harness's
553
- * accumulator wraps `status.messages`. Then the file-review reconcile (the
568
+ * transcript builder wraps `status.messages`. Then the file-review reconcile (the
554
569
  * dual-source half): every change set the server projected as DECIDED is
555
570
  * reconciled from the ledger decisions and the pinned git refs (approved
556
571
  * kept at their "after" bytes, rejected snapped back to baseline, all
@@ -583,7 +598,7 @@ export async function reconcileReinvocation(
583
598
 
584
599
  if (reinvoked) {
585
600
  const existingStatus = args.execution.status;
586
- seedFromPersistedStatus(deps.status, args.execution);
601
+ seedFromPersistedStatus(deps.status, deps.transcript, args.execution);
587
602
 
588
603
  if (args.workspace.captureMode && args.workspace.primaryDir) {
589
604
  const decidedSets = (existingStatus?.fileChangeSets ?? []).filter(
@@ -782,10 +797,10 @@ export async function resolveMcpServersAndPolicies(
782
797
  * its to render. One progress label for the whole phase, as before.
783
798
  *
784
799
  * The `.stigmer` link this and the attachment phase create is removed in
785
- * the runtime's finally, after the harness's own teardown. Until S3 M1 the
800
+ * the runtime's finally, after the harness's own teardown. Until #1096 the
786
801
  * native orchestrator fetched and mounted sub-agent skills itself
787
802
  * (`subagent-transformer.ts` with a client); this phase is where that read
788
- * lives now (Q-S3-5).
803
+ * lives now.
789
804
  */
790
805
  export async function mountSkills(
791
806
  deps: ResolutionDeps,
@@ -824,8 +839,8 @@ export async function mountSkills(
824
839
  * actually see the image. Full model validation is not needed for this. The
825
840
  * Cursor harness with no model named builds its own catalog default instead
826
841
  * (`resolveModelId("default")`), so for it this is an approximation: today
827
- * both answers read as sighted, and the exact per-harness default is S4's
828
- * to declare (S3 M1 finding F-M1-4). The vision profile is the harness's
842
+ * both answers read as sighted, and the exact per-harness default is not yet
843
+ * declared. The vision profile is the harness's
829
844
  * (each engine accepts different image shapes), so it arrives as an
830
845
  * argument.
831
846
  */
@@ -878,9 +893,9 @@ export async function resolveTurnAttachments(
878
893
  * re-attempts the call — both regenerate. An `interrupt` engine checkpoints
879
894
  * AT the call and applies its exact args on `approve`, so a runner-side
880
895
  * write would land the same bytes twice and pre-empt a row the engine is
881
- * about to execute; `none` gates nothing. Until S3 M2a the phase ran for
896
+ * about to execute; `none` gates nothing. Until #1096 the phase ran for
882
897
  * every harness — a deny-and-retry mechanism the native harness would have
883
- * met on its first deny-gated file approval (F-M2a-2, Q-M2a-3).
898
+ * met on its first deny-gated file approval.
884
899
  */
885
900
  export function regeneratesApprovedWrites(pausePrimitive: PausePrimitive): boolean {
886
901
  switch (pausePrimitive) {
@@ -21,9 +21,8 @@
21
21
  * (`execute-cursor/turn-stream.ts` `CursorTurnStreamDeps`) or a fact the
22
22
  * runtime cannot read anywhere else. Nothing here is speculative: where the
23
23
  * program's original sketch and the code disagreed, the code won, and the
24
- * disagreement was ruled at the entry's gate
25
- * (stigmer-cloud `_projects/2026-09/20260911.02.sp.harness-contract-and-kit/`
26
- * for S1; `20260911.03.sp.turn-runtime-extraction/` M3 for the growth below).
24
+ * disagreement was ruled before the code landed (#1064; the growth below in
25
+ * #1070).
27
26
  *
28
27
  * What is deliberately NOT on this contract, and why:
29
28
  *
@@ -31,11 +30,13 @@
31
30
  * (`maxConcurrentActivities`), so a per-turn teardown method on the
32
31
  * adapter is a race. The adapter owns its per-turn teardown in its own
33
32
  * `finally` inside `runTurn` (the Cursor harness parks its agent there).
34
- * - No `isCancelled()`, no `heartbeat(details)`, no `ExecutionStatusWriter`
35
- * base. Each would be a second way of saying something `stopSignal`,
36
- * `recordActivity()` or `requestPersist()` already says, and two writers of
37
- * one fact drift (the native builders' `forceNextUpdate` flag is the same
38
- * fact as a `requestPersist()` call).
33
+ * - No `isCancelled()`, no `heartbeat(details)`, and the sink does not
34
+ * EXTEND a status-writer interface. Each would be a second way of saying
35
+ * something `stopSignal`, `recordActivity()` or `requestPersist()` already
36
+ * says, and two writers of one fact drift. The transcript builder rides
37
+ * the sink as a MEMBER (`transcript`), and the distinction holds: its
38
+ * `dirty` is a fact the adapter's persist decision reads, `requestPersist()`
39
+ * is the act; one fact, one act, no second writer.
39
40
  * - No `reason` on `interrupted`, no payload on `completed`, no `retryable`
40
41
  * on `failed`. Every cause of stopping is the runtime's own evidence; the
41
42
  * final text and structured output are already folded onto the status;
@@ -53,9 +54,9 @@
53
54
  * propagates it.
54
55
  * - No persist cadence. The runtime's chokepoint is single-flight and
55
56
  * unconditional at settle; WHEN a streaming turn asks for a write is the
56
- * adapter's (`shared/persist-decision.ts` over its own dirty flags, since
57
- * what counts as a discrete change is engine knowledge). Revisited with
58
- * both loops in view at S3 M4 and kept (Q-S3-13): the cadence RULE is
57
+ * adapter's (`shared/persist-decision.ts` over the builder's `dirty`
58
+ * flag, since WHEN to ask is engine cadence). Revisited with
59
+ * both loops in view in #1096 and kept: the cadence RULE is
59
60
  * shared, the timing is the engine's.
60
61
  * - No capture. The file-review capture is the runtime's whole
61
62
  * (`harness/capture.ts`): the baseline before `runTurn`, the candidate
@@ -90,6 +91,7 @@ import type { DeclaredPreferencesContent } from "../shared/declared-preferences.
90
91
  import type { RecalledMemoriesContent } from "../shared/recalled-memories.js";
91
92
  import type { CasTouchedReader } from "../shared/filereview/cas-touched.js";
92
93
  import type { HarnessCapabilities } from "./capabilities.js";
94
+ import type { TranscriptBuilder } from "./transcript/builder.js";
93
95
 
94
96
  /**
95
97
  * One harness, as the runtime sees it. ONE adapter object exists per worker
@@ -325,14 +327,36 @@ export interface TurnInput extends NormalizedActivityInput {
325
327
  * one status it folds into. One sink per turn, owned by the runtime; the
326
328
  * adapter never constructs one.
327
329
  *
328
- * Field ownership on `status` before the canonical transcript lands (S4):
329
- * the adapter appends the engine's transcript rows (assistant messages,
330
- * tool-call rows and their approval status, sub-agent rows, todos); the
331
- * runtime writes the phase, the terminal system messages, `streamingUsage`,
332
- * artifacts, write-backs, `fileChangeProgress`, the file-review ledger
333
- * events and the change-set stamp on a flowed edit row (S3 M4,
334
- * `harness/capture.ts`). An adapter never writes a phase or a terminal copy:
335
- * those are Temporal semantics the runtime owns once.
330
+ * Field ownership on `status` (since #1097, the canonical transcript):
331
+ *
332
+ * - Transcript rows — messages, tool-call rows, sub-agent rows, todos — are
333
+ * CREATED through `transcript` and nowhere else: the adapter translates
334
+ * its engine's events and applies them; a reinvocation's prior rows are
335
+ * seeded through it by the runtime. The one exception, the runtime's own
336
+ * terminal system rows (`harness/terminal-table.ts`), is the second name
337
+ * on the writer fence's allow-list (`__tests__/transcript-writers.test.ts`).
338
+ * - Artifacts and write-backs a turn produces register through `transcript`
339
+ * too (the native inline publisher; the runtime's write-back coordinator),
340
+ * each dedupe rule owned once. The one artifact written beside it is the
341
+ * epilogue's plan artifact (`shared/plan-artifact.ts`), the runtime's,
342
+ * which supersedes by the plan's own name rule.
343
+ * - Rows may be AMENDED by identity, never created, by the modules that own
344
+ * a fact the builder cannot know, and this is the whole list: the runtime's
345
+ * `harness/approval-decisions.ts` (a SKIP or REJECT settles its row),
346
+ * `harness/capture.ts` (the change-set stamp on a flowed edit row),
347
+ * `shared/exact-apply.ts` (an approved whole-file write applied by the
348
+ * runtime completes its row), `shared/subagent-rows.ts` (a stopped turn's
349
+ * sub-agents CANCELLED); the Cursor boundary (`execute-cursor/
350
+ * boundary-rows.ts`: the identity-token collapses, #205, #965, the
351
+ * unattended stamp); the native settle (`execute-deep-agent/hitl.ts`: the
352
+ * gate's unattended skips). A harness that amends says so in its settle's
353
+ * header.
354
+ * - The runtime alone writes the phase, `startedAt`, `completedAt`,
355
+ * `error`, the terminal system rows, `streamingUsage`,
356
+ * `fileChangeProgress`, the file-review ledger events and the change-set
357
+ * stamp (`harness/capture.ts`, since #1096), and closes every streaming flag
358
+ * once `runTurn` returns. An adapter never writes a phase or a terminal
359
+ * copy: those are Temporal semantics the runtime owns once.
336
360
  */
337
361
  export interface TurnSink {
338
362
  /**
@@ -342,6 +366,24 @@ export interface TurnSink {
342
366
  */
343
367
  readonly status: AgentExecutionStatus;
344
368
 
369
+ /**
370
+ * The one transcript builder over `status`, constructed by the runtime
371
+ * per turn and already holding a reinvocation's seeded rows. The ONE way
372
+ * a transcript row is created: a harness translates its engine's events
373
+ * into `TranscriptEvent`s and `apply`s them; its post-stream facts (a
374
+ * gate parked by a boundary, a disclosure) go in as events too. Artifacts
375
+ * and write-backs a turn produces register here as well (`addArtifact`,
376
+ * `addWriteBack`, one dedupe rule each). Read `dirty` to decide a
377
+ * streaming persist and call `markPersisted()` as you request it; read
378
+ * `awaitingApproval` to learn a proposal was parked. The runtime calls
379
+ * `finalize()` once `runTurn` returns, on every path, so no streaming flag
380
+ * outlives a turn; a harness may call it earlier when it persists on the
381
+ * settled rows itself. A source-walking fence
382
+ * (`harness/__tests__/transcript-writers.test.ts`) refuses any other
383
+ * creator of a row.
384
+ */
385
+ readonly transcript: TranscriptBuilder;
386
+
345
387
  /**
346
388
  * The ONE way a turn is told to stop, whatever the cause: user pause,
347
389
  * worker shutdown, stall, cost cap, platform STOP. The runtime knows why
@@ -402,7 +444,7 @@ export interface TurnSink {
402
444
  * step only the adapter knows ("Initializing Cursor agent"). The runtime
403
445
  * reports its own resolution labels itself; the adapter reports the labels
404
446
  * of its setup steps exactly as the orchestrator did, so the UI's spinner
405
- * copy is unchanged by the extraction (Q-S2-5). Resolves once the label is
447
+ * copy is unchanged by the extraction. Resolves once the label is
406
448
  * written; the write carries no phase, so it never advances the execution.
407
449
  */
408
450
  reportProgress(label: string): Promise<void>;
@@ -415,7 +457,7 @@ export interface TurnSink {
415
457
  * cleared, the agnostic quirk of `BuildUpdateStateStep`); the adapter may
416
458
  * set its own harness-specific `SessionSpec` fields on that record before
417
459
  * binding, one writer per field (`harnessStateId` the runtime's,
418
- * `cursorMode` the adapter's; Q-S2-11). Called only by adapters whose
460
+ * `cursorMode` the adapter's). Called only by adapters whose
419
461
  * `capabilities.stateIdSource` is `"engine-minted"`, and before their first
420
462
  * `requestPersist`; a `deterministic` harness never calls it. Rejects when
421
463
  * the session write fails; the adapter then ends the turn `failed` with
@@ -448,7 +490,7 @@ export interface TurnSink {
448
490
  * Token counts for one engine turn, priced. The four counts are what the
449
491
  * Cursor loop reads from the SDK's `turn-ended` delta; `estimatedCostUsd` is
450
492
  * the adapter's price for them at its vendor's rates (the runtime cannot
451
- * price without the vendor's table and must not import it; Q-S2-12), and
493
+ * price without the vendor's table and must not import it), and
452
494
  * `model` / `requestedModelParams` name the basis it priced against, which
453
495
  * the runtime records into `streamingUsage` (`model` is the catalog-validated
454
496
  * id, `requestedModelParams` the JSON of the params sent — a string on the
@@ -4,7 +4,7 @@
4
4
  * the persist chokepoint writes before every status write, and the running
5
5
  * cost the `max_cost_usd` cap is enforced against.
6
6
  *
7
- * Who owns what (Q-S2-12): the ADAPTER prices, because only it has its
7
+ * Who owns what: the ADAPTER prices, because only it has its
8
8
  * vendor's rate table and variant semantics (`execute-cursor/usage-pricing.ts`
9
9
  * for Cursor); the RUNTIME accounts and enforces, because the cap and the
10
10
  * summary are the platform's, the same for every engine. A delta therefore
@@ -14,7 +14,7 @@
14
14
  * preferences (`TurnInput.model`), the audit trail that the account default
15
15
  * was never left in control (#357, #772).
16
16
  *
17
- * Moved from `activities/execute-cursor/usage-accumulator.ts` at S2 M3, the
17
+ * Moved from `activities/execute-cursor/usage-accumulator.ts` in #1070, the
18
18
  * pricing call split out; the sums, the snapshot shape and the empty
19
19
  * snapshot are unchanged, so `streamingUsage` is byte-for-byte what the
20
20
  * Cursor orchestrator wrote.
@@ -14,7 +14,7 @@
14
14
  * adapter's interceptors must patch `node:http2` before anything dials the
15
15
  * control plane, so it boots first. The native deep-agent adapter boots
16
16
  * second; its `boot` registers the deepagents harness profiles and loads
17
- * LangChain, both after the patch (S3 M2b, 2026-09-13; until then the roots
17
+ * LangChain, both after the patch (#1096, 2026-09-13; until then the roots
18
18
  * imported the native orchestrator directly beside this table).
19
19
  *
20
20
  * THIS MODULE'S STATIC GRAPH MUST STAY CONNECT- AND SDK-FREE. The roots
@@ -22,9 +22,10 @@
22
22
  * where `node:http2` is patched and `@cursor/sdk` first loaded; an adapter
23
23
  * factory that imported its SDK statically would defeat both. Every adapter
24
24
  * named here loads its vendor SDK inside `boot` (`execute-cursor/adapter.ts`
25
- * and `execute-deep-agent/adapter.ts` show the shape; each has a fence that
26
- * walks its static graph). `__tests__/harness-boot-order.test.ts` boots a
27
- * fresh process through this module — both rows — and fails if the graph
25
+ * and `execute-deep-agent/adapter.ts` show the shape; the native adapter's
26
+ * `__tests__/adapter-graph-is-sdk-free.test.ts` walks its static graph off
27
+ * the syntax tree). `__tests__/harness-boot-order.test.ts` boots a fresh
28
+ * process through this module — both rows — and fails if either graph
28
29
  * regresses.
29
30
  */
30
31
 
@@ -3,9 +3,9 @@
3
3
  * running total the sub-agent views share, and warns the model ONCE at the
4
4
  * configured share of `max_cost_usd`. Nothing here caps: the enforcement is
5
5
  * the turn runtime's (`shared/__tests__/cost-guard.test.ts`,
6
- * `harness/__tests__/run-turn.test.ts`'s cost-cap arm). Until S3 M2b this
6
+ * `harness/__tests__/run-turn.test.ts`'s cost-cap arm). Until #1096 this
7
7
  * file was `cost-cap.test.ts` and also pinned the in-graph tool block and
8
- * the "exceeded" message — retired with that half (Q-S3-3, Q-M2b-9).
8
+ * the "exceeded" message — retired with that half.
9
9
  */
10
10
 
11
11
  import { describe, it, expect } from "vitest";
@@ -24,6 +24,12 @@
24
24
  * unrecognized mutating built-in (e.g. `bash`, `overwrite_file`) is therefore
25
25
  * gated by what it does, not by whether someone remembered to list it.
26
26
  *
27
+ * The decision itself — `resolveToolApproval` — lives in
28
+ * `shared/approval-policy.ts` beside its provenance twin since #1097:
29
+ * the native translator reports the same answer on every
30
+ * `tool_started`, so the transcript row and this gate can never disagree
31
+ * about whether a call waits. This module is where the decision is ACTED on.
32
+ *
27
33
  * Gateway invariant (Phase 2): this middleware IS the in-process execution
28
34
  * gateway for the deep-agent harness — `handler(request)` is the side effect. A
29
35
  * side effect runs only with a backing authorization: either (a) the tool was
@@ -50,7 +56,7 @@ import {
50
56
  type MergedToolPolicy,
51
57
  type PolicySource,
52
58
  POLICY_ENGINE_VERSION,
53
- resolveApprovalMessage,
59
+ resolveToolApproval,
54
60
  unattendedSkipMessage,
55
61
  } from "../shared/approval-policy.js";
56
62
  import { toolApprovalCategory, type ToolApprovalCategory } from "../shared/tool-kind.js";
@@ -164,16 +170,6 @@ interface ApprovalDecision {
164
170
  readonly comment?: string;
165
171
  }
166
172
 
167
- // Approval-message template per mutating category. Keyed by category (not raw
168
- // tool name) so every alias of a mutation renders one message; placeholders
169
- // resolve against the deep-agent stream arg shape (`path`/`command`). Mirrors
170
- // the Cursor side's CATEGORY_APPROVAL_MESSAGE.
171
- const CATEGORY_APPROVAL_MESSAGE: Record<ToolApprovalCategory, string> = {
172
- write: "Write file: {{args.path}}",
173
- delete: "Delete: {{args.path}}",
174
- shell: "Execute command: {{args.command}}",
175
- };
176
-
177
173
  /**
178
174
  * The ToolMessage returned when a secret-like write is hard-blocked (DD-E /
179
175
  * DD-26 #2): the write is NEVER applied and the graph continues (this replaces
@@ -383,69 +379,6 @@ export function createApprovalGateMiddleware(
383
379
  };
384
380
  }
385
381
 
386
- interface ApprovalRequirement {
387
- readonly requiresApproval: boolean;
388
- readonly message: string;
389
- /** Which policy layer determined this verdict — stamped on the shadow receipt. */
390
- readonly source: PolicySource;
391
- }
392
-
393
- function resolveToolApproval(
394
- toolName: string,
395
- serverSlug: string,
396
- args: Record<string, unknown>,
397
- policies: ReadonlyMap<string, MergedToolPolicy>,
398
- leasedCategories: ReadonlySet<ToolApprovalCategory>,
399
- ): ApprovalRequirement {
400
- if (serverSlug) {
401
- // MCP tools stay governed by the connect-flow classifier + four-level policy
402
- // chain. The policy map carries only the tools that REQUIRE approval, so an
403
- // absent entry means the classifier already auto-approved it — fail-OPEN is
404
- // correct here (a fail-closed default would re-gate everything the classifier
405
- // cleared). This is deliberately NOT changed by the built-in fail-closed flip.
406
- //
407
- // A server-scoped lease surfaces here as an absent entry too: the leased
408
- // server's tools are dropped from `policies` upstream (mergeApprovalPolicies),
409
- // so a lease-cleared MCP tool takes this same auto-approve path. (Its shadow
410
- // receipt therefore reads classifier_default rather than approval_lease; a
411
- // faithful per-server lease provenance would need the lease set threaded here
412
- // and is deferred with the rest of the persisted-receipt work.)
413
- const key = `${serverSlug}/${toolName}`;
414
- const policy = policies.get(key);
415
- if (policy) {
416
- return {
417
- requiresApproval: policy.requiresApproval,
418
- message: resolveApprovalMessage(policy.approvalMessage, toolName, args),
419
- source: policy.source,
420
- };
421
- }
422
- // Absent = cleared by the MCP four-level chain (classifier base) or by a
423
- // server-scoped lease (dropped upstream).
424
- return { requiresApproval: false, message: "", source: "classifier_default" };
425
- }
426
-
427
- // Built-in/platform tool: gate exactly the mutating categories via the shared
428
- // classifier. Fail-CLOSED for the mutating set — any built-in classifyTool
429
- // deems write/edit/delete/shell requires approval. Read-only and unclassified
430
- // built-ins are not mutating, so they remain fail-open.
431
- const category = toolApprovalCategory(toolName);
432
- if (category) {
433
- // Run-lifetime category lease: the user chose "approve all <category>"
434
- // earlier in this run, so every built-in of that category is auto-approved
435
- // for the rest of the run (the scoped successor to auto-approve-all).
436
- if (leasedCategories.has(category)) {
437
- return { requiresApproval: false, message: "", source: "approval_lease" };
438
- }
439
- return {
440
- requiresApproval: true,
441
- message: resolveApprovalMessage(CATEGORY_APPROVAL_MESSAGE[category], toolName, args),
442
- source: "builtin_category",
443
- };
444
- }
445
-
446
- return { requiresApproval: false, message: "", source: "builtin_category" };
447
- }
448
-
449
382
  /** Shared empty set so a config without leases allocates nothing per call. */
450
383
  const EMPTY_CATEGORY_SET: ReadonlySet<ToolApprovalCategory> = new Set();
451
384
 
@@ -11,17 +11,17 @@
11
11
  * shape `execution-budget.ts` already has beside LangGraph's `recursionLimit`:
12
12
  * the middleware warns inside the graph, the engine's own limit enforces.
13
13
  *
14
- * Until S3 M2b (Q-S3-3) this module was `cost-cap.ts` and did both: it also
14
+ * Until #1096 this module was `cost-cap.ts` and did both: it also
15
15
  * blocked every tool call once the running cost passed the cap and gave the
16
16
  * model one tool-free round to summarize. That second enforcement lived
17
17
  * inside the graph, where the runtime could not see it, and a platform STOP
18
18
  * had a sibling (`graceful-stop.ts`, deleted with it) that let the run spend
19
19
  * a summary round after the platform said stop. Both went when the runtime
20
- * became the one place a turn is stopped (harness runtime program, S3).
20
+ * became the one place a turn is stopped.
21
21
  *
22
22
  * afterModel — reads `usage_metadata` off the latest AIMessage, prices the
23
23
  * call at the parent's rates (a sub-agent on its own model is priced the
24
- * same way the enforcement prices it; per-sub-agent pricing is an S5 item),
24
+ * same way the enforcement prices it; per-sub-agent pricing is #1121),
25
25
  * accumulates the running total, and injects the warning SystemMessage once
26
26
  * at `warningPct` of the cap.
27
27
  *
@@ -21,7 +21,7 @@
21
21
  * Every middleware here either shapes the graph's tool surface or ADVISES
22
22
  * the model; none of them stops the run. A stop — the platform's, the
23
23
  * cost cap's, a stall's — is the turn runtime's, delivered to the graph
24
- * through its abort signal (harness runtime program, S3 Q-S3-3; until M2b a
24
+ * through its abort signal (since #1096; until then a
25
25
  * graceful-stop middleware and the cost cap's tool block were second stops
26
26
  * inside the graph that the runtime could not see).
27
27
  *
@@ -701,7 +701,7 @@ export function mapManagerOptionsToConfig(
701
701
  // The manager's proxy credential is the minted runner token once adopted
702
702
  // (the control-plane token in lockstep before that), so it is this ref and
703
703
  // not `tokenRef`: binding `tokenRef` would keep sending the desktop's own
704
- // Auth0 token as x-stigmer-auth after the mint (Q-S2-7).
704
+ // Auth0 token as x-stigmer-auth after the mint.
705
705
  proxyTokenRef: runnerTokenRef,
706
706
  cursorApiKey: proxyActive
707
707
  ? (options.cursorApiKey ?? "proxy-managed")