@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,10 +1,15 @@
1
1
  /**
2
- * Unit tests for resolvePlatformOptions — the Cursor SDK stateRoot derivation.
2
+ * Unit tests for the local agent's create/resume options and the
3
+ * transport-recovery wrapper (`session-lifecycle.ts`).
3
4
  *
4
- * stateRoot is keyed by sessionId and rooted at the durable workspace volume so
5
- * native Agent.resume() survives restart/snapshot-restore and so sessions that
6
- * share one volume (e.g. a workflow sandbox's child agent executions) never
7
- * collide. These invariants are correctness-critical, hence the explicit tests.
5
+ * The SDK module is a `vi.fn` stub so the assertions read the exact options
6
+ * the adapter hands `Agent.create` / `Agent.resume`. The SDK's sqlite entry is
7
+ * NOT mocked here on purpose: `createAgent` opens the session's REAL
8
+ * `SqliteLocalAgentStore` (`node:sqlite`, no network) under a temp workspace
9
+ * volume, so this file is also where the store the runner ships with is
10
+ * proven to open, be reused, and dispose — the hermetic goldens double it.
11
+ * The store's keying and lifetime rules have their own arms in
12
+ * `session-store.test.ts`.
8
13
  */
9
14
 
10
15
  import { describe, it, expect, afterEach, vi } from "vitest";
@@ -20,13 +25,15 @@ vi.mock("@cursor/sdk", () => ({
20
25
  }));
21
26
 
22
27
  import { Agent } from "@cursor/sdk";
28
+ import type { AgentOptions } from "@cursor/sdk";
29
+ import { SqliteLocalAgentStore } from "@cursor/sdk/sqlite";
23
30
  import {
24
- resolvePlatformOptions,
25
31
  createAgent,
26
32
  resumeAgent,
27
33
  resolveAgentWithTransportRecovery,
28
34
  } from "../session-lifecycle.js";
29
35
  import type { CreateAgentOptions } from "../session-lifecycle.js";
36
+ import { releaseAllSessionStores } from "../session-store.js";
30
37
 
31
38
  const tempRoots: string[] = [];
32
39
 
@@ -36,50 +43,25 @@ function freshWorkspaceRoot(): string {
36
43
  return dir;
37
44
  }
38
45
 
39
- afterEach(() => {
46
+ afterEach(async () => {
47
+ // Release every store before its directory goes, so the sqlite handles are
48
+ // closed when the temp roots are removed (and no test inherits a store).
49
+ await releaseAllSessionStores();
40
50
  for (const dir of tempRoots.splice(0)) {
41
51
  rmSync(dir, { recursive: true, force: true });
42
52
  }
43
53
  });
44
54
 
45
- describe("resolvePlatformOptions", () => {
46
- it("derives stateRoot under the workspace volume (not $HOME)", () => {
47
- const workspaceRootDir = freshWorkspaceRoot();
48
- const opts = resolvePlatformOptions("ses-123", workspaceRootDir);
49
-
50
- expect(opts.stateRoot).toBe(
51
- join(workspaceRootDir, ".stigmer", "cursor-sdk-state", "ses-123"),
52
- );
53
- expect(opts.stateRoot.startsWith(workspaceRootDir)).toBe(true);
54
- // Created eagerly to prevent ENOENT on first SDK write.
55
- expect(existsSync(opts.stateRoot!)).toBe(true);
56
- expect(opts.workspaceRef).toBe("stigmer-session:ses-123");
57
- });
58
-
59
- it("isolates two sessions sharing one workspace volume into distinct stores", () => {
60
- const workspaceRootDir = freshWorkspaceRoot();
61
- const a = resolvePlatformOptions("ses-aaa", workspaceRootDir);
62
- const b = resolvePlatformOptions("ses-bbb", workspaceRootDir);
63
-
64
- expect(a.stateRoot).not.toBe(b.stateRoot);
65
- expect(a.workspaceRef).not.toBe(b.workspaceRef);
66
- // Both live under the same shared volume but in session-keyed subdirs.
67
- expect(a.stateRoot!.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
68
- expect(b.stateRoot!.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
69
- });
70
-
71
- it("throws on an empty sessionId (would collide across sessions on a shared volume)", () => {
72
- const workspaceRootDir = freshWorkspaceRoot();
73
- expect(() => resolvePlatformOptions("", workspaceRootDir)).toThrow(/sessionId is required/);
74
- });
55
+ function lastCreateOptions(): AgentOptions {
56
+ return vi.mocked(Agent.create).mock.calls.at(-1)![0];
57
+ }
75
58
 
76
- it("throws on an empty workspaceRootDir (state must live on the durable volume)", () => {
77
- expect(() => resolvePlatformOptions("ses-123", "")).toThrow(/workspaceRootDir is required/);
78
- });
79
- });
59
+ function lastResumeCall(): [string, Partial<AgentOptions> | undefined] {
60
+ return vi.mocked(Agent.resume).mock.calls.at(-1)! as [string, Partial<AgentOptions> | undefined];
61
+ }
80
62
 
81
63
  // ---------------------------------------------------------------------------
82
- // Workspace binding across create/resume
64
+ // The local options across create/resume
83
65
  //
84
66
  // Regression: Agent.resume() does not persist local.cwd. When resumeAgent()
85
67
  // omitted it, the SDK fell back to process.cwd() — re-rooting the resumed
@@ -87,17 +69,33 @@ describe("resolvePlatformOptions", () => {
87
69
  // setting source (the .cursor/hooks.json carrying the HITL approval hook)
88
70
  // from that wrong directory. Result: on every resumed turn, file edits and
89
71
  // shell commands ran unguarded with no approval card (observed in production
90
- // execution aex_01ktr5na07f5xtmn0dz3mfjtdp).
72
+ // execution aex_01ktr5na07f5xtmn0dz3mfjtdp). The same rule now covers the
73
+ // store (#1053): a resume without it would look the agent up in a default
74
+ // store derived from cwd, not the one the session's records are in.
91
75
  // ---------------------------------------------------------------------------
92
76
 
93
- describe("workspace binding on create/resume", () => {
77
+ describe("local options on create/resume", () => {
94
78
  const baseOptions = {
95
79
  apiKey: "key",
96
80
  sessionId: "ses-cwd-test",
97
81
  model: "gpt-test",
98
82
  };
99
83
 
100
- it("createAgent passes the single workspace dir as local.cwd", async () => {
84
+ it("createAgent passes the single workspace dir as local.cwd, with no dirs", async () => {
85
+ const workspaceRootDir = freshWorkspaceRoot();
86
+ await createAgent({
87
+ ...baseOptions,
88
+ workspaceDirs: ["/work/repo-a"],
89
+ workspaceRootDir,
90
+ });
91
+
92
+ const { local } = lastCreateOptions();
93
+ expect(local?.cwd).toBe("/work/repo-a");
94
+ expect(local).not.toHaveProperty("dirs");
95
+ expect(local?.settingSources).toContain("project");
96
+ });
97
+
98
+ it("createAgent opens the session's real SQLite store under the workspace volume and passes it as local.store", async () => {
101
99
  const workspaceRootDir = freshWorkspaceRoot();
102
100
  await createAgent({
103
101
  ...baseOptions,
@@ -105,13 +103,37 @@ describe("workspace binding on create/resume", () => {
105
103
  workspaceRootDir,
106
104
  });
107
105
 
108
- const callOptions = vi.mocked(Agent.create).mock.calls.at(-1)![0] as any;
109
- expect(callOptions.local.cwd).toBe("/work/repo-a");
110
- expect(callOptions.local.settingSources).toContain("project");
106
+ const store = lastCreateOptions().local?.store;
107
+ expect(store).toBeInstanceOf(SqliteLocalAgentStore);
108
+ const sqlite = store as SqliteLocalAgentStore;
109
+ expect(sqlite.workspaceRef).toBe("stigmer-session:ses-cwd-test");
110
+ expect(sqlite.stateRoot).toBe(join(workspaceRootDir, ".stigmer", "cursor-sdk-state", "ses-cwd-test"));
111
+ // The SDK's layout lands where the runner said, not under $HOME.
112
+ expect(existsSync(sqlite.stateRoot)).toBe(true);
111
113
  });
112
114
 
113
- it("resumeAgent re-supplies local.cwd (not persisted by Agent.resume)", async () => {
115
+ it("createAgent pins the SDK's own retries off (the runner is the retry authority)", async () => {
114
116
  const workspaceRootDir = freshWorkspaceRoot();
117
+ await createAgent({
118
+ ...baseOptions,
119
+ workspaceDirs: ["/work/repo-a"],
120
+ workspaceRootDir,
121
+ });
122
+
123
+ // 1.0.31 defaults this to true for headless embedders; an absent field
124
+ // would silently stack the SDK's transport retries under the runner's.
125
+ expect(lastCreateOptions().local?.enableAgentRetries).toBe(false);
126
+ });
127
+
128
+ it("resumeAgent re-supplies cwd, settingSources, store and the retry pin (nothing under local survives Agent.resume)", async () => {
129
+ const workspaceRootDir = freshWorkspaceRoot();
130
+ await createAgent({
131
+ ...baseOptions,
132
+ workspaceDirs: ["/work/repo-a"],
133
+ workspaceRootDir,
134
+ });
135
+ const createdWith = lastCreateOptions().local?.store;
136
+
115
137
  await resumeAgent({
116
138
  ...baseOptions,
117
139
  agentId: "agent-123",
@@ -119,25 +141,31 @@ describe("workspace binding on create/resume", () => {
119
141
  workspaceRootDir,
120
142
  });
121
143
 
122
- const [agentId, callOptions] = vi.mocked(Agent.resume).mock.calls.at(-1)! as [string, any];
144
+ const [agentId, callOptions] = lastResumeCall();
123
145
  expect(agentId).toBe("agent-123");
124
- // The load-bearing assertion: without cwd the SDK re-roots the agent at
125
- // process.cwd() and the project HITL hook never loads on resumed turns.
126
- expect(callOptions.local.cwd).toBe("/work/repo-a");
127
- expect(callOptions.local.settingSources).toContain("project");
146
+ // The load-bearing assertions: without cwd the SDK re-roots the agent at
147
+ // process.cwd() and the project HITL hook never loads on resumed turns;
148
+ // without the SAME store it looks the agent up somewhere else.
149
+ expect(callOptions?.local?.cwd).toBe("/work/repo-a");
150
+ expect(callOptions?.local?.settingSources).toContain("project");
151
+ expect(callOptions?.local?.store).toBe(createdWith);
152
+ expect(callOptions?.local?.enableAgentRetries).toBe(false);
128
153
  });
129
154
 
130
- it("resumeAgent passes multiple workspace dirs as an array cwd", async () => {
155
+ it("passes a multi-root workspace as cwd (the first dir) plus dirs (the rest)", async () => {
131
156
  const workspaceRootDir = freshWorkspaceRoot();
132
157
  await resumeAgent({
133
158
  ...baseOptions,
134
159
  agentId: "agent-456",
135
- workspaceDirs: ["/work/repo-a", "/work/repo-b"],
160
+ workspaceDirs: ["/work/repo-a", "/work/repo-b", "/work/repo-c"],
136
161
  workspaceRootDir,
137
162
  });
138
163
 
139
- const callOptions = vi.mocked(Agent.resume).mock.calls.at(-1)![1] as any;
140
- expect(callOptions.local.cwd).toEqual(["/work/repo-a", "/work/repo-b"]);
164
+ const [, callOptions] = lastResumeCall();
165
+ // The SDK merges cwd-first with duplicates dropped, so this is the array
166
+ // the SDK took whole at 1.0.13, in the same order.
167
+ expect(callOptions?.local?.cwd).toBe("/work/repo-a");
168
+ expect(callOptions?.local?.dirs).toEqual(["/work/repo-b", "/work/repo-c"]);
141
169
  });
142
170
  });
143
171
 
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Unit tests for `session-store.ts`: where a session's Cursor SDK store lives,
3
+ * and the lifetime the runner owns for it (stigmer/stigmer#1053).
4
+ *
5
+ * The location rules are correctness-critical: the state root is keyed by
6
+ * sessionId and rooted at the durable workspace volume so native
7
+ * Agent.resume() survives restart/snapshot-restore and so sessions that share
8
+ * one volume (a workflow sandbox's child agent executions) never collide.
9
+ *
10
+ * The lifetime rules are what a revert of the adapter's release hooks would
11
+ * break: one open per session however many activities ask, the SAME instance
12
+ * on every ask, a release that disposes and forgets so the next ask reopens, a
13
+ * failed open that is not remembered, and a re-acquire under a different root
14
+ * that releases the store it held. `SessionStores` takes the opener, so these
15
+ * run against a recording fake and no SQLite file.
16
+ */
17
+
18
+ import { describe, it, expect, afterEach } from "vitest";
19
+ import { mkdtempSync, rmSync, existsSync } from "node:fs";
20
+ import { tmpdir } from "node:os";
21
+ import { join } from "node:path";
22
+
23
+ import { SessionStores, resolveSessionStoreLocation, type ReleasableStore, type SessionStoreLocation } from "../session-store.js";
24
+
25
+ const tempRoots: string[] = [];
26
+
27
+ function freshWorkspaceRoot(): string {
28
+ const dir = mkdtempSync(join(tmpdir(), "stigmer-session-store-test-"));
29
+ tempRoots.push(dir);
30
+ return dir;
31
+ }
32
+
33
+ afterEach(() => {
34
+ for (const dir of tempRoots.splice(0)) {
35
+ rmSync(dir, { recursive: true, force: true });
36
+ }
37
+ });
38
+
39
+ describe("resolveSessionStoreLocation", () => {
40
+ it("derives the state root under the workspace volume (not $HOME), created eagerly", () => {
41
+ const workspaceRootDir = freshWorkspaceRoot();
42
+ const location = resolveSessionStoreLocation("ses-123", workspaceRootDir);
43
+
44
+ expect(location.stateRoot).toBe(join(workspaceRootDir, ".stigmer", "cursor-sdk-state", "ses-123"));
45
+ expect(location.stateRoot.startsWith(workspaceRootDir)).toBe(true);
46
+ // Created eagerly to prevent ENOENT on the SDK's first write.
47
+ expect(existsSync(location.stateRoot)).toBe(true);
48
+ expect(location.workspaceRef).toBe("stigmer-session:ses-123");
49
+ });
50
+
51
+ it("isolates two sessions sharing one workspace volume into distinct stores", () => {
52
+ const workspaceRootDir = freshWorkspaceRoot();
53
+ const a = resolveSessionStoreLocation("ses-aaa", workspaceRootDir);
54
+ const b = resolveSessionStoreLocation("ses-bbb", workspaceRootDir);
55
+
56
+ expect(a.stateRoot).not.toBe(b.stateRoot);
57
+ expect(a.workspaceRef).not.toBe(b.workspaceRef);
58
+ expect(a.stateRoot.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
59
+ expect(b.stateRoot.startsWith(join(workspaceRootDir, ".stigmer"))).toBe(true);
60
+ });
61
+
62
+ it("throws on an empty sessionId (would collide across sessions on a shared volume)", () => {
63
+ const workspaceRootDir = freshWorkspaceRoot();
64
+ expect(() => resolveSessionStoreLocation("", workspaceRootDir)).toThrow(/sessionId is required/);
65
+ });
66
+
67
+ it("throws on an empty workspaceRootDir (state must live on the durable volume)", () => {
68
+ expect(() => resolveSessionStoreLocation("ses-123", "")).toThrow(/workspaceRootDir is required/);
69
+ });
70
+ });
71
+
72
+ // ---------------------------------------------------------------------------
73
+ // The lifetime
74
+ // ---------------------------------------------------------------------------
75
+
76
+ class FakeStore implements ReleasableStore {
77
+ disposeCalls = 0;
78
+ constructor(readonly location: SessionStoreLocation) {}
79
+ get stateRoot(): string {
80
+ return this.location.stateRoot;
81
+ }
82
+ async dispose(): Promise<void> {
83
+ this.disposeCalls++;
84
+ }
85
+ }
86
+
87
+ /** A recording opener; `failNext` makes the next open reject once. */
88
+ function recordingOpener() {
89
+ const opened: FakeStore[] = [];
90
+ let failNext: Error | undefined;
91
+ const open = async (location: SessionStoreLocation): Promise<FakeStore> => {
92
+ if (failNext) {
93
+ const err = failNext;
94
+ failNext = undefined;
95
+ throw err;
96
+ }
97
+ const store = new FakeStore(location);
98
+ opened.push(store);
99
+ return store;
100
+ };
101
+ return { open, opened, fail: (err: Error) => (failNext = err) };
102
+ }
103
+
104
+ describe("SessionStores", () => {
105
+ it("opens once per session and hands the same instance to every later acquire, concurrent ones included", async () => {
106
+ const workspaceRootDir = freshWorkspaceRoot();
107
+ const { open, opened } = recordingOpener();
108
+ const stores = new SessionStores(open);
109
+
110
+ // Two activities racing on one session (the agent cache's documented race).
111
+ const [a, b] = await Promise.all([
112
+ stores.acquire("ses-1", workspaceRootDir),
113
+ stores.acquire("ses-1", workspaceRootDir),
114
+ ]);
115
+ const c = await stores.acquire("ses-1", workspaceRootDir);
116
+
117
+ expect(opened).toHaveLength(1);
118
+ expect(a).toBe(b);
119
+ expect(b).toBe(c);
120
+ expect(a.location.workspaceRef).toBe("stigmer-session:ses-1");
121
+ expect(stores.size).toBe(1);
122
+ });
123
+
124
+ it("keeps one store per session, not one per process", async () => {
125
+ const workspaceRootDir = freshWorkspaceRoot();
126
+ const { open, opened } = recordingOpener();
127
+ const stores = new SessionStores(open);
128
+
129
+ const a = await stores.acquire("ses-a", workspaceRootDir);
130
+ const b = await stores.acquire("ses-b", workspaceRootDir);
131
+
132
+ expect(opened).toHaveLength(2);
133
+ expect(a).not.toBe(b);
134
+ expect(stores.size).toBe(2);
135
+ });
136
+
137
+ it("release disposes the session's store and forgets it, so a later acquire reopens", async () => {
138
+ const workspaceRootDir = freshWorkspaceRoot();
139
+ const { open, opened } = recordingOpener();
140
+ const stores = new SessionStores(open);
141
+
142
+ const first = await stores.acquire("ses-1", workspaceRootDir);
143
+ await stores.release("ses-1");
144
+
145
+ expect(first.disposeCalls).toBe(1);
146
+ expect(stores.size).toBe(0);
147
+
148
+ const second = await stores.acquire("ses-1", workspaceRootDir);
149
+ expect(second).not.toBe(first);
150
+ expect(opened).toHaveLength(2);
151
+ });
152
+
153
+ it("release of a session with no store is a no-op", async () => {
154
+ const { open, opened } = recordingOpener();
155
+ const stores = new SessionStores(open);
156
+
157
+ await expect(stores.release("ses-unknown")).resolves.toBeUndefined();
158
+ expect(opened).toHaveLength(0);
159
+ });
160
+
161
+ it("releaseAll disposes every held store and empties the map (worker shutdown)", async () => {
162
+ const workspaceRootDir = freshWorkspaceRoot();
163
+ const { open, opened } = recordingOpener();
164
+ const stores = new SessionStores(open);
165
+
166
+ await stores.acquire("ses-a", workspaceRootDir);
167
+ await stores.acquire("ses-b", workspaceRootDir);
168
+ await stores.releaseAll();
169
+
170
+ expect(opened.map((s) => s.disposeCalls)).toEqual([1, 1]);
171
+ expect(stores.size).toBe(0);
172
+ });
173
+
174
+ it("does not remember a failed open: the next acquire retries", async () => {
175
+ const workspaceRootDir = freshWorkspaceRoot();
176
+ const { open, opened, fail } = recordingOpener();
177
+ const stores = new SessionStores(open);
178
+
179
+ fail(new Error("disk full"));
180
+ await expect(stores.acquire("ses-1", workspaceRootDir)).rejects.toThrow("disk full");
181
+ expect(stores.size).toBe(0);
182
+
183
+ const store = await stores.acquire("ses-1", workspaceRootDir);
184
+ expect(opened).toEqual([store]);
185
+ expect(stores.size).toBe(1);
186
+ });
187
+
188
+ it("a re-acquire under a different workspace volume releases the held store and opens the new one", async () => {
189
+ const rootA = freshWorkspaceRoot();
190
+ const rootB = freshWorkspaceRoot();
191
+ const { open, opened } = recordingOpener();
192
+ const stores = new SessionStores(open);
193
+
194
+ const onA = await stores.acquire("ses-1", rootA);
195
+ const onB = await stores.acquire("ses-1", rootB);
196
+
197
+ // The handle for the old binding can never serve the new one (the same
198
+ // rule the agent cache applies to a fingerprint mismatch).
199
+ expect(onB).not.toBe(onA);
200
+ expect(onA.disposeCalls).toBe(1);
201
+ expect(onB.stateRoot.startsWith(rootB)).toBe(true);
202
+ expect(opened).toHaveLength(2);
203
+ expect(stores.size).toBe(1);
204
+ });
205
+
206
+ it("a dispose that throws is swallowed: the store is forgotten either way", async () => {
207
+ const workspaceRootDir = freshWorkspaceRoot();
208
+ const stores = new SessionStores(async (location) => {
209
+ const store = new FakeStore(location);
210
+ store.dispose = async () => {
211
+ throw new Error("handle already closed");
212
+ };
213
+ return store;
214
+ });
215
+
216
+ await stores.acquire("ses-1", workspaceRootDir);
217
+ await expect(stores.release("ses-1")).resolves.toBeUndefined();
218
+ expect(stores.size).toBe(0);
219
+ });
220
+ });
@@ -23,7 +23,7 @@
23
23
  * shape) is guarded in shared/__tests__/status-offload.
24
24
  */
25
25
 
26
- import { describe, it, expect, vi } from "vitest";
26
+ import { describe, it, expect } from "vitest";
27
27
  import { create } from "@bufbuild/protobuf";
28
28
  import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
29
29
  import { AgentMessageSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
@@ -33,13 +33,8 @@ import {
33
33
  offloadOversizedToolOutputs,
34
34
  detectImagePayload,
35
35
  } from "../../../shared/status-offload.js";
36
- import {
37
- toResultString,
38
- canonicalizeImageResult,
39
- buildToolCallProto,
40
- MessageAccumulator,
41
- } from "../message-translator.js";
42
- import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
36
+ import { toResultString, canonicalizeImageResult } from "../tool-result.js";
37
+ import { foldCursorEvents } from "../__test-utils__/fold.js";
43
38
 
44
39
  // PNG signature + a little payload. PNG_BYTES is how the Cursor SDK delivers
45
40
  // image data at runtime (Node Buffer-JSON); PNG_BASE64 is its base64 form, used
@@ -143,7 +138,7 @@ describe("toResultString", () => {
143
138
  });
144
139
  });
145
140
 
146
- describe("buildToolCallProto image normalization", () => {
141
+ describe("stream row image normalization (through the translator and the builder)", () => {
147
142
  it("produces a result the shared offload detector recognizes as an image", () => {
148
143
  const event = {
149
144
  type: "tool_call",
@@ -156,7 +151,7 @@ describe("buildToolCallProto image normalization", () => {
156
151
  result: cursorImageEnvelope(),
157
152
  } as unknown as Extract<SDKMessage, { type: "tool_call" }>;
158
153
 
159
- const tc = buildToolCallProto(event);
154
+ const tc = foldCursorEvents([event]).rows()[0];
160
155
  expect(tc.name).toBe("get_app_state");
161
156
  const img = detectImagePayload(tc.result);
162
157
  expect(img).not.toBeNull();
@@ -188,7 +183,7 @@ describe("cursor image flows through the persist-time offload", () => {
188
183
  result: cursorImageEnvelope(),
189
184
  } as unknown as Extract<SDKMessage, { type: "tool_call" }>;
190
185
 
191
- const tc = buildToolCallProto(event);
186
+ const tc = foldCursorEvents([event]).rows()[0];
192
187
  const status = create(AgentExecutionStatusSchema, {
193
188
  messages: [create(AgentMessageSchema, { toolCalls: [tc] })],
194
189
  });
@@ -207,11 +202,8 @@ describe("cursor image flows through the persist-time offload", () => {
207
202
  });
208
203
  });
209
204
 
210
- describe("sub-agent image normalization (extractConversationSteps)", () => {
205
+ describe("sub-agent image normalization (sub-agent-steps)", () => {
211
206
  it("normalizes a screenshot returned inside a sub-agent toolCall step", () => {
212
- const messages: AgentMessage[] = [];
213
- const acc = new MessageAccumulator(messages);
214
-
215
207
  const running = {
216
208
  type: "tool_call",
217
209
  agent_id: "a1",
@@ -221,9 +213,6 @@ describe("sub-agent image normalization (extractConversationSteps)", () => {
221
213
  status: "running",
222
214
  args: { description: "screenshot", prompt: "capture" },
223
215
  } as unknown as Extract<SDKMessage, { type: "tool_call" }>;
224
- acc.processEvent(running);
225
- acc.trackSubAgentExecution(running);
226
-
227
216
  const completed = {
228
217
  type: "tool_call",
229
218
  agent_id: "a1",
@@ -254,10 +243,7 @@ describe("sub-agent image normalization (extractConversationSteps)", () => {
254
243
  },
255
244
  } as unknown as Extract<SDKMessage, { type: "tool_call" }>;
256
245
 
257
- acc.processEvent(completed);
258
- acc.trackSubAgentExecution(completed);
259
-
260
- const sub = acc.subAgentExecutions[0];
246
+ const sub = foldCursorEvents([running, completed]).status.subAgentExecutions[0];
261
247
  const subToolResult = sub.messages[0].toolCalls[0].result;
262
248
  const img = detectImagePayload(subToolResult);
263
249
  expect(img?.base64).toBe(PNG_BASE64);