@stigmer/runner 3.14.1 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/__test-utils__/execution-record-fixture.d.ts +47 -0
  3. package/dist/__test-utils__/execution-record-fixture.js +68 -0
  4. package/dist/__test-utils__/execution-record-fixture.js.map +1 -0
  5. package/dist/__test-utils__/harness-contract/types.d.ts +166 -0
  6. package/dist/__test-utils__/harness-contract/types.js +49 -0
  7. package/dist/__test-utils__/harness-contract/types.js.map +1 -0
  8. package/dist/__test-utils__/hermetic-activity.d.ts +28 -5
  9. package/dist/__test-utils__/hermetic-activity.js +23 -7
  10. package/dist/__test-utils__/hermetic-activity.js.map +1 -1
  11. package/dist/__test-utils__/mock-workspace.d.ts +15 -0
  12. package/dist/__test-utils__/mock-workspace.js +21 -0
  13. package/dist/__test-utils__/mock-workspace.js.map +1 -0
  14. package/dist/__test-utils__/model-registry-fixture.d.ts +56 -0
  15. package/dist/__test-utils__/model-registry-fixture.js +66 -0
  16. package/dist/__test-utils__/model-registry-fixture.js.map +1 -0
  17. package/dist/__test-utils__/turn-input-fixture.d.ts +60 -0
  18. package/dist/__test-utils__/turn-input-fixture.js +118 -0
  19. package/dist/__test-utils__/turn-input-fixture.js.map +1 -0
  20. package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +107 -0
  21. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +344 -0
  22. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -0
  23. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +20 -0
  24. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +58 -0
  25. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -1
  26. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +2 -32
  27. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
  28. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +38 -62
  29. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +47 -121
  30. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  31. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +17 -1
  32. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +27 -4
  33. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
  34. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +52 -11
  35. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +66 -7
  36. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -1
  37. package/dist/activities/execute-cursor/adapter.d.ts +55 -0
  38. package/dist/activities/execute-cursor/adapter.js +119 -0
  39. package/dist/activities/execute-cursor/adapter.js.map +1 -0
  40. package/dist/activities/execute-cursor/approval-state.d.ts +2 -2
  41. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  42. package/dist/activities/execute-cursor/capture-flow.d.ts +15 -30
  43. package/dist/activities/execute-cursor/capture-flow.js +17 -26
  44. package/dist/activities/execute-cursor/capture-flow.js.map +1 -1
  45. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +23 -0
  46. package/dist/activities/execute-cursor/cursor-capabilities.js +33 -0
  47. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -0
  48. package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +2 -2
  49. package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -1
  50. package/dist/activities/execute-cursor/fetch-interceptor.d.ts +15 -25
  51. package/dist/activities/execute-cursor/fetch-interceptor.js +39 -33
  52. package/dist/activities/execute-cursor/fetch-interceptor.js.map +1 -1
  53. package/dist/activities/execute-cursor/http2-interceptor.d.ts +21 -17
  54. package/dist/activities/execute-cursor/http2-interceptor.js +38 -31
  55. package/dist/activities/execute-cursor/http2-interceptor.js.map +1 -1
  56. package/dist/activities/execute-cursor/message-translator.d.ts +28 -19
  57. package/dist/activities/execute-cursor/message-translator.js +76 -27
  58. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  59. package/dist/activities/execute-cursor/prompt-builder.d.ts +180 -11
  60. package/dist/activities/execute-cursor/prompt-builder.js +171 -0
  61. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  62. package/dist/activities/execute-cursor/rejection-capture.d.ts +3 -6
  63. package/dist/activities/execute-cursor/rejection-capture.js +5 -7
  64. package/dist/activities/execute-cursor/rejection-capture.js.map +1 -1
  65. package/dist/activities/execute-cursor/session-lifecycle.d.ts +1 -4
  66. package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -1
  67. package/dist/activities/execute-cursor/turn-boundary.d.ts +1 -1
  68. package/dist/activities/execute-cursor/turn-settle.d.ts +49 -0
  69. package/dist/activities/execute-cursor/turn-settle.js +507 -0
  70. package/dist/activities/execute-cursor/turn-settle.js.map +1 -0
  71. package/dist/activities/execute-cursor/turn-setup.d.ts +173 -0
  72. package/dist/activities/execute-cursor/turn-setup.js +496 -0
  73. package/dist/activities/execute-cursor/turn-setup.js.map +1 -0
  74. package/dist/activities/execute-cursor/turn-stream.d.ts +41 -71
  75. package/dist/activities/execute-cursor/turn-stream.js +70 -135
  76. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  77. package/dist/activities/execute-cursor/turn.d.ts +43 -0
  78. package/dist/activities/execute-cursor/turn.js +222 -0
  79. package/dist/activities/execute-cursor/turn.js.map +1 -0
  80. package/dist/activities/execute-cursor/usage-pricing.d.ts +38 -0
  81. package/dist/activities/execute-cursor/usage-pricing.js +50 -0
  82. package/dist/activities/execute-cursor/usage-pricing.js.map +1 -0
  83. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +1 -1
  84. package/dist/activities/execute-deep-agent/approval-file-change.js +1 -1
  85. package/dist/activities/execute-deep-agent/environment.js +1 -1
  86. package/dist/activities/execute-deep-agent/environment.js.map +1 -1
  87. package/dist/activities/execute-deep-agent/setup.js +3 -2
  88. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  89. package/dist/activities/hydrate-workflow-execution.js +1 -1
  90. package/dist/activities/hydrate-workflow-execution.js.map +1 -1
  91. package/dist/config.d.ts +15 -0
  92. package/dist/config.js.map +1 -1
  93. package/dist/harness/capabilities.d.ts +16 -0
  94. package/dist/harness/capabilities.js +1 -0
  95. package/dist/harness/capabilities.js.map +1 -1
  96. package/dist/harness/persist-chokepoint.d.ts +74 -0
  97. package/dist/harness/persist-chokepoint.js +88 -0
  98. package/dist/harness/persist-chokepoint.js.map +1 -0
  99. package/dist/harness/registry.d.ts +44 -5
  100. package/dist/harness/registry.js +61 -5
  101. package/dist/harness/registry.js.map +1 -1
  102. package/dist/harness/run-turn.d.ts +53 -0
  103. package/dist/harness/run-turn.js +528 -0
  104. package/dist/harness/run-turn.js.map +1 -0
  105. package/dist/harness/stop-controller.d.ts +50 -0
  106. package/dist/harness/stop-controller.js +62 -0
  107. package/dist/harness/stop-controller.js.map +1 -0
  108. package/dist/harness/terminal-table.d.ts +141 -0
  109. package/dist/harness/terminal-table.js +239 -0
  110. package/dist/harness/terminal-table.js.map +1 -0
  111. package/dist/harness/turn-context.d.ts +523 -0
  112. package/dist/harness/turn-context.js +739 -0
  113. package/dist/harness/turn-context.js.map +1 -0
  114. package/dist/harness/types.d.ts +232 -52
  115. package/dist/harness/types.js +17 -8
  116. package/dist/harness/types.js.map +1 -1
  117. package/dist/harness/usage-accumulator.d.ts +68 -0
  118. package/dist/harness/usage-accumulator.js +101 -0
  119. package/dist/harness/usage-accumulator.js.map +1 -0
  120. package/dist/harness-adapters.d.ts +27 -0
  121. package/dist/harness-adapters.js +28 -0
  122. package/dist/harness-adapters.js.map +1 -0
  123. package/dist/main.js.map +1 -1
  124. package/dist/runner-manager.js +64 -48
  125. package/dist/runner-manager.js.map +1 -1
  126. package/dist/runner.d.ts +5 -4
  127. package/dist/runner.js +65 -64
  128. package/dist/runner.js.map +1 -1
  129. package/dist/shared/approval-policy.d.ts +1 -1
  130. package/dist/shared/approval-policy.js.map +1 -1
  131. package/dist/{activities/execute-cursor → shared}/attachment-resolver.d.ts +2 -2
  132. package/dist/{activities/execute-cursor → shared}/attachment-resolver.js +5 -5
  133. package/dist/shared/attachment-resolver.js.map +1 -0
  134. package/dist/{activities/execute-cursor → shared}/blueprint-resolver.d.ts +7 -5
  135. package/dist/{activities/execute-cursor → shared}/blueprint-resolver.js +3 -63
  136. package/dist/shared/blueprint-resolver.js.map +1 -0
  137. package/dist/shared/channel-attachment.d.ts +1 -1
  138. package/dist/shared/channel-attachment.js.map +1 -1
  139. package/dist/{activities/execute-cursor → shared}/cost-guard.d.ts +5 -1
  140. package/dist/{activities/execute-cursor → shared}/cost-guard.js +5 -1
  141. package/dist/shared/cost-guard.js.map +1 -0
  142. package/dist/{activities/execute-cursor → shared}/env-resolver.d.ts +1 -1
  143. package/dist/shared/env-resolver.js.map +1 -0
  144. package/dist/{activities/execute-cursor → shared}/exact-apply.d.ts +1 -1
  145. package/dist/{activities/execute-cursor → shared}/exact-apply.js +6 -6
  146. package/dist/shared/exact-apply.js.map +1 -0
  147. package/dist/shared/execution-context.d.ts +35 -0
  148. package/dist/shared/execution-context.js +38 -0
  149. package/dist/shared/execution-context.js.map +1 -0
  150. package/dist/{activities/execute-cursor → shared}/extract-structured-output.d.ts +5 -2
  151. package/dist/{activities/execute-cursor → shared}/extract-structured-output.js +9 -6
  152. package/dist/shared/extract-structured-output.js.map +1 -0
  153. package/dist/shared/filereview/capture.d.ts +1 -1
  154. package/dist/shared/filereview/capture.js +1 -1
  155. package/dist/shared/heartbeat.d.ts +13 -11
  156. package/dist/shared/heartbeat.js +14 -29
  157. package/dist/shared/heartbeat.js.map +1 -1
  158. package/dist/{activities/execute-cursor → shared}/persist-decision.d.ts +5 -2
  159. package/dist/{activities/execute-cursor → shared}/persist-decision.js +4 -1
  160. package/dist/shared/persist-decision.js.map +1 -0
  161. package/dist/{activities/execute-cursor → shared}/skill-resolver.d.ts +16 -3
  162. package/dist/{activities/execute-cursor → shared}/skill-resolver.js +12 -4
  163. package/dist/shared/skill-resolver.js.map +1 -0
  164. package/dist/shared/subagent-rows.d.ts +21 -0
  165. package/dist/shared/subagent-rows.js +34 -0
  166. package/dist/shared/subagent-rows.js.map +1 -0
  167. package/dist/shared/worker-shutdown.d.ts +43 -16
  168. package/dist/shared/worker-shutdown.js +28 -13
  169. package/dist/shared/worker-shutdown.js.map +1 -1
  170. package/dist/shared/workspace/platform-dir.d.ts +1 -1
  171. package/dist/shared/workspace/platform-dir.js +1 -1
  172. package/dist/shared/workspace/session-provision.d.ts +54 -0
  173. package/dist/{activities/execute-cursor/workspace-provision.js → shared/workspace/session-provision.js} +15 -12
  174. package/dist/shared/workspace/session-provision.js.map +1 -0
  175. package/package.json +4 -4
  176. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +110 -14
  177. package/src/__test-utils__/execution-record-fixture.ts +104 -0
  178. package/src/__test-utils__/harness-boot-order-child.ts +58 -0
  179. package/src/__test-utils__/harness-contract/contract.ts +128 -83
  180. package/src/__test-utils__/harness-contract/recording-sink.ts +15 -4
  181. package/src/__test-utils__/harness-contract/runtime-contract.ts +666 -0
  182. package/src/__test-utils__/harness-contract/scripted-adapter.ts +92 -32
  183. package/src/__test-utils__/harness-contract/types.ts +85 -9
  184. package/src/__test-utils__/hermetic-activity.ts +33 -8
  185. package/src/__test-utils__/model-registry-fixture.ts +72 -0
  186. package/src/__test-utils__/module-specifiers.ts +82 -0
  187. package/src/__test-utils__/turn-input-fixture.ts +155 -0
  188. package/src/__tests__/harness-boot-order.test.ts +77 -0
  189. package/src/__tests__/harness-contract.test.ts +7 -5
  190. package/src/__tests__/runner-manager.test.ts +18 -0
  191. package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +102 -0
  192. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +396 -0
  193. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +66 -0
  194. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +2 -43
  195. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +65 -145
  196. package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +30 -4
  197. package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +96 -8
  198. package/src/activities/execute-cursor/__tests__/adapter-is-temporal-free.test.ts +45 -0
  199. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +90 -0
  200. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +7 -8
  201. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +28 -1
  202. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +1 -1
  203. package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +64 -6
  204. package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +1 -1
  205. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -1
  206. package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.status.json +53 -0
  207. package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.status.json +1 -6
  208. package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.status.json +56 -0
  209. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-transport-timeout.status.json +48 -0
  210. package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
  211. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-cancelled.status.json +36 -0
  212. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-error-non-retryable.status.json +37 -0
  213. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +38 -0
  214. package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.status.json +59 -0
  215. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +79 -0
  216. package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.status.json +2 -7
  217. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +170 -0
  218. package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +22 -18
  219. package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +1 -1
  220. package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +1 -1
  221. package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +286 -0
  222. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +332 -0
  223. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +193 -0
  224. package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +1 -1
  225. package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +185 -0
  226. package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +151 -0
  227. package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +65 -35
  228. package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -40
  229. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +171 -0
  230. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +118 -243
  231. package/src/activities/execute-cursor/__tests__/usage-pricing.test.ts +84 -0
  232. package/src/activities/execute-cursor/adapter.ts +138 -0
  233. package/src/activities/execute-cursor/approval-state.ts +2 -2
  234. package/src/activities/execute-cursor/capture-flow.ts +18 -41
  235. package/src/activities/execute-cursor/cursor-capabilities.ts +35 -0
  236. package/src/activities/execute-cursor/cursor-mcp-config.ts +2 -2
  237. package/src/activities/execute-cursor/fetch-interceptor.ts +48 -45
  238. package/src/activities/execute-cursor/http2-interceptor.ts +47 -34
  239. package/src/activities/execute-cursor/message-translator.ts +90 -45
  240. package/src/activities/execute-cursor/prompt-builder.ts +327 -12
  241. package/src/activities/execute-cursor/rejection-capture.ts +5 -12
  242. package/src/activities/execute-cursor/session-lifecycle.ts +1 -5
  243. package/src/activities/execute-cursor/turn-boundary.ts +1 -1
  244. package/src/activities/execute-cursor/turn-settle.ts +601 -0
  245. package/src/activities/execute-cursor/turn-setup.ts +645 -0
  246. package/src/activities/execute-cursor/turn-stream.ts +84 -210
  247. package/src/activities/execute-cursor/turn.ts +240 -0
  248. package/src/activities/execute-cursor/usage-pricing.ts +67 -0
  249. package/src/activities/execute-deep-agent/approval-file-change.ts +1 -1
  250. package/src/activities/execute-deep-agent/environment.ts +1 -1
  251. package/src/activities/execute-deep-agent/setup.ts +3 -2
  252. package/src/activities/hydrate-workflow-execution.ts +1 -1
  253. package/src/config.ts +13 -0
  254. package/src/harness/__tests__/import-direction.test.ts +168 -0
  255. package/src/harness/__tests__/persist-chokepoint.test.ts +146 -0
  256. package/src/harness/__tests__/registry.test.ts +1 -0
  257. package/src/harness/__tests__/run-turn.test.ts +165 -0
  258. package/src/harness/__tests__/stop-controller.test.ts +49 -0
  259. package/src/harness/__tests__/turn-context.test.ts +178 -0
  260. package/src/harness/__tests__/usage-accumulator.test.ts +83 -0
  261. package/src/harness/capabilities.ts +17 -0
  262. package/src/harness/persist-chokepoint.ts +112 -0
  263. package/src/harness/registry.ts +79 -5
  264. package/src/harness/run-turn.ts +618 -0
  265. package/src/harness/stop-controller.ts +83 -0
  266. package/src/harness/terminal-table.ts +276 -0
  267. package/src/harness/turn-context.ts +1028 -0
  268. package/src/harness/types.ts +248 -53
  269. package/src/harness/usage-accumulator.ts +122 -0
  270. package/src/harness-adapters.ts +30 -0
  271. package/src/main.ts +1 -1
  272. package/src/runner-manager.ts +68 -61
  273. package/src/runner.ts +67 -78
  274. package/src/shared/__tests__/attachment-naming.test.ts +1 -1
  275. package/src/{activities/execute-cursor → shared}/__tests__/attachment-resolver.test.ts +6 -4
  276. package/src/{activities/execute-cursor → shared}/__tests__/cost-guard.test.ts +2 -1
  277. package/src/{activities/execute-cursor → shared}/__tests__/exact-apply.test.ts +3 -3
  278. package/src/{activities/execute-cursor → shared}/__tests__/extract-structured-output.test.ts +8 -8
  279. package/src/{activities/execute-cursor → shared}/__tests__/persist-decision.test.ts +4 -2
  280. package/src/{activities/execute-cursor → shared}/__tests__/skill-resolver.test.ts +1 -1
  281. package/src/shared/__tests__/subagent-rows.test.ts +34 -0
  282. package/src/shared/__tests__/worker-shutdown.test.ts +44 -39
  283. package/src/shared/approval-policy.ts +1 -1
  284. package/src/{activities/execute-cursor → shared}/attachment-resolver.ts +6 -6
  285. package/src/{activities/execute-cursor → shared}/blueprint-resolver.ts +7 -78
  286. package/src/shared/channel-attachment.ts +1 -1
  287. package/src/{activities/execute-cursor → shared}/cost-guard.ts +5 -1
  288. package/src/{activities/execute-cursor → shared}/env-resolver.ts +1 -1
  289. package/src/{activities/execute-cursor → shared}/exact-apply.ts +7 -7
  290. package/src/shared/execution-context.ts +45 -0
  291. package/src/{activities/execute-cursor → shared}/extract-structured-output.ts +10 -7
  292. package/src/shared/filereview/capture.ts +1 -1
  293. package/src/shared/heartbeat.ts +13 -33
  294. package/src/{activities/execute-cursor → shared}/persist-decision.ts +5 -2
  295. package/src/{activities/execute-cursor → shared}/skill-resolver.ts +20 -6
  296. package/src/shared/subagent-rows.ts +39 -0
  297. package/src/shared/worker-shutdown.ts +55 -25
  298. package/src/{activities/execute-cursor/__tests__/workspace-provision.test.ts → shared/workspace/__tests__/session-provision.test.ts} +25 -28
  299. package/src/shared/workspace/platform-dir.ts +1 -1
  300. package/src/{activities/execute-cursor/workspace-provision.ts → shared/workspace/session-provision.ts} +29 -16
  301. package/dist/activities/execute-cursor/attachment-resolver.js.map +0 -1
  302. package/dist/activities/execute-cursor/blueprint-resolver.js.map +0 -1
  303. package/dist/activities/execute-cursor/cost-guard.js.map +0 -1
  304. package/dist/activities/execute-cursor/env-resolver.js.map +0 -1
  305. package/dist/activities/execute-cursor/exact-apply.js.map +0 -1
  306. package/dist/activities/execute-cursor/extract-structured-output.js.map +0 -1
  307. package/dist/activities/execute-cursor/index.d.ts +0 -209
  308. package/dist/activities/execute-cursor/index.js +0 -2345
  309. package/dist/activities/execute-cursor/index.js.map +0 -1
  310. package/dist/activities/execute-cursor/persist-decision.js.map +0 -1
  311. package/dist/activities/execute-cursor/skill-resolver.js.map +0 -1
  312. package/dist/activities/execute-cursor/usage-accumulator.d.ts +0 -89
  313. package/dist/activities/execute-cursor/usage-accumulator.js +0 -121
  314. package/dist/activities/execute-cursor/usage-accumulator.js.map +0 -1
  315. package/dist/activities/execute-cursor/workspace-provision.d.ts +0 -42
  316. package/dist/activities/execute-cursor/workspace-provision.js.map +0 -1
  317. package/src/activities/execute-cursor/__tests__/usage-accumulator.test.ts +0 -164
  318. package/src/activities/execute-cursor/index.ts +0 -2876
  319. package/src/activities/execute-cursor/usage-accumulator.ts +0 -169
  320. /package/dist/{activities/execute-cursor → shared}/env-resolver.js +0 -0
@@ -234,9 +234,9 @@ export async function createStigmerRunnerManager(
234
234
  // `tokenRef` holds the control-plane token (the host's durable credential,
235
235
  // e.g. the desktop's Auth0 token) and is shared with activity clients via
236
236
  // config.stigmerTokenRef. The proxy credential (x-stigmer-auth) is managed
237
- // separately by a RunnerTokenCoordinator (created after the interceptors are
238
- // installed) — see that module for the two-writer rationale and the staleness
239
- // history it guards.
237
+ // separately by a RunnerTokenCoordinator (created after the harnesses boot)
238
+ // — see that module for the two-writer rationale and the staleness history
239
+ // it guards.
240
240
  const tokenRef = { current: options.stigmerToken ?? null };
241
241
  // `runnerTokenRef` mirrors the coordinator's proxy credential for gRPC use:
242
242
  // the minted runner token (token_type=embedded_runner) once adopted, tracking
@@ -251,48 +251,33 @@ export async function createStigmerRunnerManager(
251
251
 
252
252
  assertLlmBackendsPreflight(baseConfig.proxyEndpoint);
253
253
 
254
- // Install the Cursor SDK interceptors BEFORE resolving Temporal coordinates.
255
- // Coordinate discovery dials the control plane via StigmerClient, which loads
256
- // @connectrpc/connect-node and snapshots the node:http2 ESM facade on first
257
- // import. The HTTP/2 interceptor patches http2.connect and only propagates to
258
- // that facade if it runs first, so install MUST precede any connect-node load
259
- // (discovery here, and the SDK later). The interceptors depend only on
260
- // proxyEndpoint/stigmerToken (already in baseConfig), not resolved coordinates.
261
-
262
- // Install fetch interceptor before any @cursor/sdk imports
263
- const { installFetchInterceptor, updateInterceptorToken, getExecutionContext } = await import(
264
- "./activities/execute-cursor/fetch-interceptor.js"
265
- );
266
- installFetchInterceptor({
267
- proxyEndpoint: baseConfig.proxyEndpoint ?? undefined,
268
- stigmerToken: baseConfig.stigmerToken ?? undefined,
269
- });
270
-
271
- // HTTP/2 interceptor for Connect RPC auth + execution ID injection (BiDi billing)
272
- const { installHttp2Interceptor, updateHttp2InterceptorToken, assertHttp2ConnectPatched } = await import(
273
- "./activities/execute-cursor/http2-interceptor.js"
274
- );
275
- installHttp2Interceptor({
276
- proxyEndpoint: baseConfig.proxyEndpoint ?? undefined,
277
- stigmerToken: baseConfig.stigmerToken ?? undefined,
278
- });
279
- // Fail loudly at boot if a load-order regression left the node:http2 ESM
280
- // facade unpatched (otherwise BiDi streams would silently 401). No-op when
281
- // the interceptor is unconfigured (no proxy/token).
282
- await assertHttp2ConnectPatched();
283
- markBoot("interceptors_installed");
254
+ // Boot the harnesses BEFORE resolving Temporal coordinates. Coordinate
255
+ // discovery dials the control plane through connect-node, which snapshots
256
+ // the node:http2 ESM facade on first import; the Cursor adapter's boot
257
+ // installs the proxy interceptors (the HTTP/2 one patches http2.connect,
258
+ // which only reaches that facade if it runs first), proves the patch landed,
259
+ // and only then loads its SDK. The interceptors read the proxy credential
260
+ // per request from `runnerTokenRef` (Config.proxyTokenRef, bound by
261
+ // mapManagerOptionsToConfig): the control-plane token until a runner token
262
+ // is minted, the minted token after, exactly the lockstep the coordinator
263
+ // below maintains in that ref. Nothing a boot reads depends on the
264
+ // coordinates, so `baseConfig` carries none yet. The two modules imported
265
+ // here are connect-free by construction (`harness-adapters.ts`,
266
+ // `harness/registry.ts`; `__tests__/harness-boot-order.test.ts`).
267
+ const [{ HARNESS_ADAPTERS }, { adaptersOf, bootHarnesses, releaseHarnessSession, shutdownHarnesses }] =
268
+ await Promise.all([import("./harness-adapters.js"), import("./harness/registry.js")]);
269
+ await bootHarnesses(adaptersOf(HARNESS_ADAPTERS), baseConfig);
270
+ markBoot("harnesses_booted");
284
271
 
285
272
  // The token coordinator owns the proxy credential (x-stigmer-auth) and its
286
- // refresh lifecycle. It writes ONLY its sinks (the interceptors plus the gRPC
287
- // runner-credential ref) and re-mints using the always-fresh control-plane
273
+ // refresh lifecycle. It writes ONE sink, `runnerTokenRef`, which is read per
274
+ // request by both the interceptors (as Config.proxyTokenRef) and the gRPC
275
+ // client (as Config.stigmerRunnerTokenRef), so mint and refresh reach every
276
+ // reader in one write. It re-mints using the always-fresh control-plane
288
277
  // token in `tokenRef` — never the (possibly expired) minted token itself, so
289
278
  // a slept-past-TTL runner recovers without a restart.
290
279
  const tokenCoordinator = createRunnerTokenCoordinator({
291
280
  applyProxyToken: (token) => {
292
- updateInterceptorToken(token);
293
- updateHttp2InterceptorToken(token);
294
- // Third sink: keeps the ExecutionContext-read credential in lockstep with
295
- // the proxy credential across mint and refresh (see runnerTokenRef above).
296
281
  runnerTokenRef.current = token;
297
282
  },
298
283
  reMint: () =>
@@ -302,7 +287,7 @@ export async function createStigmerRunnerManager(
302
287
  }),
303
288
  });
304
289
 
305
- // Resolve the runner bootstrap after the http2 patch is in place (discovery
290
+ // Resolve the runner bootstrap after the harnesses have booted (discovery
306
291
  // dials the control plane through connect-node). An explicit address wins;
307
292
  // otherwise a token triggers control-plane discovery; otherwise localhost.
308
293
  // Must happen before createAllActivities so the activities' Config carries
@@ -341,11 +326,6 @@ export async function createStigmerRunnerManager(
341
326
  );
342
327
  }
343
328
 
344
- const { setExecutionContextRef } = await import(
345
- "./activities/execute-cursor/rejection-capture.js"
346
- );
347
- setExecutionContextRef(getExecutionContext());
348
-
349
329
  const activities = await createAllActivities(config);
350
330
  markBoot("activities_imported");
351
331
  // Surface the resolved artifact store at boot (see runner.ts for rationale):
@@ -538,13 +518,19 @@ export async function createStigmerRunnerManager(
538
518
  await removeManaged(
539
519
  sessions, sessionId, SESSION_QUEUE_PREFIX + sessionId, "session",
540
520
  );
541
- // The session is done on this host — release its parked agent (and
542
- // the executor + MCP subprocesses the lease pins) immediately rather
543
- // than waiting out the idle TTL (#215).
544
- const { evictSessionAgent } = await import(
545
- "./activities/execute-cursor/agent-session-cache.js"
546
- );
547
- evictSessionAgent(sessionId);
521
+ // The session is done on this host — every harness releases what it
522
+ // parked for it (the Cursor harness: the agent, and the executor + MCP
523
+ // subprocesses its lease pins) now rather than after the idle TTL
524
+ // (#215). Logged, never thrown: the session's worker is already gone,
525
+ // and failing this IPC command would tell the desktop a removal that
526
+ // did happen did not.
527
+ try {
528
+ await releaseHarnessSession(adaptersOf(HARNESS_ADAPTERS), sessionId);
529
+ } catch (err) {
530
+ console.error(
531
+ `[runner-manager] Harness release for session ${sessionId} failed (continuing): ${err instanceof Error ? err.message : String(err)}`,
532
+ );
533
+ }
548
534
  },
549
535
 
550
536
  activeSessions(): string[] {
@@ -659,12 +645,18 @@ export async function createStigmerRunnerManager(
659
645
  }
660
646
 
661
647
  await Promise.all(shutdownPromises);
662
- // Workers are drained — release every parked session agent so their
663
- // executor leases dispose (stdio MCP subprocesses die with them) (#215).
664
- const { closeAllCachedAgents } = await import(
665
- "./activities/execute-cursor/agent-session-cache.js"
666
- );
667
- closeAllCachedAgents();
648
+ // Workers are drained — every harness releases what it still holds
649
+ // (the Cursor harness: its parked session agents, whose executor leases
650
+ // dispose and whose stdio MCP subprocesses die with them, #215). Logged,
651
+ // never thrown: the drain has already happened, and a teardown failure
652
+ // must not mask a clean stop.
653
+ try {
654
+ await shutdownHarnesses(adaptersOf(HARNESS_ADAPTERS));
655
+ } catch (err) {
656
+ console.error(
657
+ `[runner-manager] Harness shutdown failed after the workers drained (continuing): ${err instanceof Error ? err.message : String(err)}`,
658
+ );
659
+ }
668
660
  sessions.clear();
669
661
  workflowExecutions.clear();
670
662
  poolControl = null;
@@ -711,6 +703,11 @@ export function mapManagerOptionsToConfig(
711
703
  mcpBridgeEndpoint: process.env.STIGMER_MCP_BRIDGE_ENDPOINT ?? null,
712
704
  stigmerTokenRef: tokenRef,
713
705
  stigmerRunnerTokenRef: runnerTokenRef,
706
+ // The manager's proxy credential is the minted runner token once adopted
707
+ // (the control-plane token in lockstep before that), so it is this ref and
708
+ // not `tokenRef`: binding `tokenRef` would keep sending the desktop's own
709
+ // Auth0 token as x-stigmer-auth after the mint (Q-S2-7).
710
+ proxyTokenRef: runnerTokenRef,
714
711
  cursorApiKey: proxyActive
715
712
  ? (options.cursorApiKey ?? "proxy-managed")
716
713
  : (options.cursorApiKey ?? ""),
@@ -736,9 +733,18 @@ export function mapManagerOptionsToConfig(
736
733
  };
737
734
  }
738
735
 
736
+ /**
737
+ * Dynamically import all activity factories and merge into a single map,
738
+ * after the harnesses have booted: several of these modules transitively load
739
+ * `@connectrpc/connect-node` and LangChain, and the Cursor adapter's boot must
740
+ * have patched `node:http2` before connect-node is first imported (see
741
+ * createStigmerRunnerManager). The harness rows and the registry were imported
742
+ * by the factory for the boot; the imports here hit the module cache.
743
+ */
739
744
  async function createAllActivities(config: Config): Promise<WorkerActivities> {
740
745
  const [
741
- { createCursorActivities },
746
+ { HARNESS_ADAPTERS },
747
+ { createHarnessActivities },
742
748
  { createDeepAgentActivities },
743
749
  { createEnsureThreadActivities },
744
750
  { createGenerateSessionSubjectActivities },
@@ -757,7 +763,8 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
757
763
  { createPromoteTaskOutputActivities },
758
764
  { createAttachSessionActivities },
759
765
  ] = await Promise.all([
760
- import("./activities/execute-cursor/index.js"),
766
+ import("./harness-adapters.js"),
767
+ import("./harness/registry.js"),
761
768
  import("./activities/execute-deep-agent/index.js"),
762
769
  import("./activities/ensure-thread.js"),
763
770
  import("./activities/generate-session-subject.js"),
@@ -778,7 +785,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
778
785
  ]);
779
786
 
780
787
  return {
781
- ...createCursorActivities(config),
788
+ ...(await createHarnessActivities(HARNESS_ADAPTERS, config)),
782
789
  ...createDeepAgentActivities(config),
783
790
  ...createEnsureThreadActivities(),
784
791
  ...createGenerateSessionSubjectActivities(config),
package/src/runner.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Public factory for the unified Stigmer runner.
3
3
  *
4
- * Encapsulates the full boot sequence: fetch interceptor installation,
5
- * dynamic activity imports, Temporal worker creation. Consumers call
4
+ * Encapsulates the full boot sequence: harness boot (the Cursor adapter
5
+ * installs its proxy interceptors there), bootstrap resolution, dynamic
6
+ * activity imports, Temporal worker creation. Consumers call
6
7
  * {@link createStigmerRunner} with typed options and get back a handle
7
8
  * to start/shutdown the worker.
8
9
  *
@@ -125,13 +126,14 @@ export interface StigmerRunner {
125
126
  /**
126
127
  * Wire up self-renewal for a static cloud sandbox's control-plane credential
127
128
  * (see sandbox-token-renewal.ts for the model). The applied token reaches
128
- * every consumer: activity gRPC clients read {@code tokenRef} per request,
129
- * per-call sites (call-llm, registry-endpoint headers) resolve it through
130
- * the runner credential store (which replaced the process.env.STIGMER_TOKEN
131
- * channel, #508), artifact storage resolves the ref per call, and the two
132
- * Cursor SDK interceptors are updated directly a static runner has no
129
+ * every consumer through the ONE ref: activity gRPC clients read
130
+ * {@code tokenRef} per request, per-call sites (call-llm, registry-endpoint
131
+ * headers) resolve it through the runner credential store (which replaced
132
+ * the process.env.STIGMER_TOKEN channel, #508), artifact storage resolves
133
+ * the ref per call, and the two Cursor SDK interceptors read the same ref per
134
+ * request as {@code Config.proxyTokenRef} — a static runner has no
133
135
  * {@code RunnerTokenCoordinator} minting a separate proxy credential, so its
134
- * x-stigmer-auth IS this token.
136
+ * x-stigmer-auth IS this token and one write here rotates it everywhere.
135
137
  */
136
138
  async function startStaticSandboxTokenRenewal(
137
139
  config: Config,
@@ -148,12 +150,6 @@ async function startStaticSandboxTokenRenewal(
148
150
  }
149
151
 
150
152
  const { StigmerClient } = await import("./client/stigmer-client.js");
151
- const { updateInterceptorToken } = await import(
152
- "./activities/execute-cursor/fetch-interceptor.js"
153
- );
154
- const { updateHttp2InterceptorToken } = await import(
155
- "./activities/execute-cursor/http2-interceptor.js"
156
- );
157
153
  const client = new StigmerClient({
158
154
  endpoint: config.stigmerBackendEndpoint,
159
155
  token: null,
@@ -169,8 +165,6 @@ async function startStaticSandboxTokenRenewal(
169
165
  // Store write replaced the process.env.STIGMER_TOKEN write (#508) —
170
166
  // same per-call readers (call-llm, registry headers), no env exposure.
171
167
  setRunnerSecret("STIGMER_TOKEN", token);
172
- updateInterceptorToken(token);
173
- updateHttp2InterceptorToken(token);
174
168
  },
175
169
  });
176
170
  }
@@ -178,8 +172,8 @@ async function startStaticSandboxTokenRenewal(
178
172
  /**
179
173
  * Create a Stigmer runner ready to poll a Temporal task queue.
180
174
  *
181
- * Handles all internal setup: Cursor SDK fetch interceptor, activity
182
- * registration, and Temporal worker creation. Returns a handle with
175
+ * Handles all internal setup: harness boot, activity registration, and
176
+ * Temporal worker creation. Returns a handle with
183
177
  * `start()` and `shutdown()` methods.
184
178
  *
185
179
  * @example
@@ -216,42 +210,40 @@ export async function createStigmerRunner(
216
210
 
217
211
  assertLlmBackendsPreflight(baseConfig.proxyEndpoint);
218
212
 
219
- // Install the Cursor SDK interceptors BEFORE resolving Temporal coordinates.
220
- // Coordinate discovery dials the control plane via StigmerClient, which loads
221
- // @connectrpc/connect-node and snapshots the node:http2 ESM facade on first
222
- // import. The HTTP/2 interceptor patches http2.connect and only propagates to
223
- // that facade if it runs first, so install MUST precede any connect-node load
224
- // (discovery here, and the SDK later). The interceptors depend only on
225
- // proxyEndpoint/stigmerToken (already in baseConfig), not resolved coordinates.
226
-
227
- // The Cursor SDK captures a reference to global.fetch at import time.
228
- // The fetch interceptor MUST be installed before any @cursor/sdk import.
229
- const { installFetchInterceptor, getExecutionContext } = await import(
230
- "./activities/execute-cursor/fetch-interceptor.js"
231
- );
232
- installFetchInterceptor({
233
- proxyEndpoint: baseConfig.proxyEndpoint ?? undefined,
234
- stigmerToken: baseConfig.stigmerToken ?? undefined,
235
- });
213
+ // The control-plane credential lives in a shared mutable ref (as in manager
214
+ // mode) so the sandbox-token renewal below can rotate it in-process:
215
+ // activity clients read the ref per request instead of pinning the boot
216
+ // token for the pod's whole life. It is ALSO this root's proxy credential
217
+ // (Config.proxyTokenRef): a static host provides the proxy token itself and
218
+ // mints no separate one, so the interceptors read this same ref per request.
219
+ const tokenRef = { current: baseConfig.stigmerToken };
220
+ // The runner-class credential the bootstrap below may mint (see there); the
221
+ // ref exists from here so the boot config can carry it.
222
+ const runnerTokenRef: { current: string | null } = { current: null };
236
223
 
237
- // The Cursor SDK's Connect RPC transport uses native HTTP/2, bypassing
238
- // globalThis.fetch. This interceptor injects x-stigmer-execution-id and
239
- // the Stigmer auth token on HTTP/2 streams so the BiDi proxy can
240
- // authenticate and meter billing.
241
- const { installHttp2Interceptor, assertHttp2ConnectPatched } = await import(
242
- "./activities/execute-cursor/http2-interceptor.js"
243
- );
244
- installHttp2Interceptor({
245
- proxyEndpoint: baseConfig.proxyEndpoint ?? undefined,
246
- stigmerToken: baseConfig.stigmerToken ?? undefined,
247
- });
248
- // Fail loudly at boot if a load-order regression left the node:http2 ESM
249
- // facade unpatched (otherwise BiDi streams would silently 401). No-op when
250
- // the interceptor is unconfigured (no proxy/token).
251
- await assertHttp2ConnectPatched();
252
- markBoot("interceptors_installed");
224
+ // Boot the harnesses BEFORE resolving Temporal coordinates. Coordinate
225
+ // discovery dials the control plane through connect-node, which snapshots
226
+ // the node:http2 ESM facade on first import; the Cursor adapter's boot
227
+ // installs the proxy interceptors (the HTTP/2 one patches http2.connect,
228
+ // which only reaches that facade if it runs first), proves the patch landed,
229
+ // and only then loads its SDK. Nothing a boot reads depends on the
230
+ // coordinates, so `bootConfig` carries none yet. The two modules imported
231
+ // here are connect-free by construction (`harness-adapters.ts`,
232
+ // `harness/registry.ts`; `__tests__/harness-boot-order.test.ts`).
233
+ const bootConfig: Config = {
234
+ ...baseConfig,
235
+ stigmerTokenRef: tokenRef,
236
+ stigmerRunnerTokenRef: runnerTokenRef,
237
+ proxyTokenRef: tokenRef,
238
+ };
239
+ const [{ HARNESS_ADAPTERS }, { adaptersOf, bootHarnesses, shutdownHarnesses }] = await Promise.all([
240
+ import("./harness-adapters.js"),
241
+ import("./harness/registry.js"),
242
+ ]);
243
+ await bootHarnesses(adaptersOf(HARNESS_ADAPTERS), bootConfig);
244
+ markBoot("harnesses_booted");
253
245
 
254
- // Resolve Temporal coordinates after the http2 patch is in place (discovery
246
+ // Resolve Temporal coordinates after the harnesses have booted (discovery
255
247
  // dials the control plane through connect-node). Explicit address wins;
256
248
  // otherwise a token triggers control-plane discovery; otherwise localhost.
257
249
  // Only the worker connection consumes these coordinates — no activity dials
@@ -263,11 +255,6 @@ export async function createStigmerRunner(
263
255
  token: options.stigmerToken,
264
256
  stigmerEndpoint: baseConfig.stigmerBackendEndpoint,
265
257
  });
266
- // The control-plane credential lives in a shared mutable ref (as in manager
267
- // mode) so the sandbox-token renewal below can rotate it in-process:
268
- // activity clients read the ref per request instead of pinning the boot
269
- // token for the pod's whole life.
270
- const tokenRef = { current: baseConfig.stigmerToken };
271
258
 
272
259
  // Adopt the bootstrap-minted embedded_runner credential for gRPC runner-class
273
260
  // calls (stigmer-cloud#507). The static path historically discarded it ("the
@@ -282,7 +269,6 @@ export async function createStigmerRunner(
282
269
  // Servers that mint nothing (explicit-address boots, tokenless OSS, cloud
283
270
  // sandboxes with baked credentials) leave the ref null — byte-identical
284
271
  // behavior to before.
285
- const runnerTokenRef: { current: string | null } = { current: null };
286
272
  const runnerTokenCoordinator = createRunnerTokenCoordinator({
287
273
  applyProxyToken: (token) => {
288
274
  runnerTokenRef.current = token;
@@ -301,11 +287,9 @@ export async function createStigmerRunner(
301
287
  }
302
288
 
303
289
  const config: Config = {
304
- ...baseConfig,
290
+ ...bootConfig,
305
291
  temporalAddress: coordinates.temporalAddress,
306
292
  temporalNamespace: coordinates.temporalNamespace,
307
- stigmerTokenRef: tokenRef,
308
- stigmerRunnerTokenRef: runnerTokenRef,
309
293
  };
310
294
  markBoot("bootstrap_resolved");
311
295
 
@@ -314,11 +298,6 @@ export async function createStigmerRunner(
314
298
  // renewal point is scheduled even if the pod boots with a part-used token.
315
299
  const tokenRenewal = await startStaticSandboxTokenRenewal(config, tokenRef);
316
300
 
317
- const { setExecutionContextRef } = await import(
318
- "./activities/execute-cursor/rejection-capture.js"
319
- );
320
- setExecutionContextRef(getExecutionContext());
321
-
322
301
  const activities = await createAllActivities(config);
323
302
  markBoot("activities_imported");
324
303
 
@@ -382,12 +361,18 @@ export async function createStigmerRunner(
382
361
  emitRunnerBootTiming({ task_queue: config.taskQueue, mode: config.mode });
383
362
  await worker.run();
384
363
  console.log("Worker stopped");
385
- // The worker has drained — release any parked session agent so its
386
- // executor lease disposes with the process (#215).
387
- const { closeAllCachedAgents } = await import(
388
- "./activities/execute-cursor/agent-session-cache.js"
389
- );
390
- closeAllCachedAgents();
364
+ // The worker has drained — every harness releases what it still holds
365
+ // (the Cursor harness: its parked session agents, whose executor leases
366
+ // dispose with the process, #215). Logged, never thrown: the drain has
367
+ // already happened and the process is exiting, so a teardown failure
368
+ // must not mask a clean stop.
369
+ try {
370
+ await shutdownHarnesses(adaptersOf(HARNESS_ADAPTERS));
371
+ } catch (err) {
372
+ console.error(
373
+ `[runner] Harness shutdown failed after the worker drained (continuing): ${err instanceof Error ? err.message : String(err)}`,
374
+ );
375
+ }
391
376
  },
392
377
  shutdown() {
393
378
  tokenRenewal?.stop();
@@ -467,13 +452,16 @@ export function mapOptionsToConfig(options: StigmerRunnerOptions): Config {
467
452
  /**
468
453
  * Dynamically import all activity factories and merge into a single map.
469
454
  *
470
- * Dynamic imports are required because several modules transitively import
471
- * @cursor/sdk, which captures global.fetch at import time. The fetch
472
- * interceptor must be installed before these imports.
455
+ * Dynamic imports, after the harnesses have booted: several of these modules
456
+ * transitively load `@connectrpc/connect-node` and LangChain, and the Cursor
457
+ * adapter's boot must have patched `node:http2` before connect-node is first
458
+ * imported (see createStigmerRunner). The harness rows and the registry were
459
+ * imported by the factory for the boot; the imports here hit the module cache.
473
460
  */
474
461
  async function createAllActivities(config: Config): Promise<WorkerActivities> {
475
462
  const [
476
- { createCursorActivities },
463
+ { HARNESS_ADAPTERS },
464
+ { createHarnessActivities },
477
465
  { createDeepAgentActivities },
478
466
  { createEnsureThreadActivities },
479
467
  { createGenerateSessionSubjectActivities },
@@ -492,7 +480,8 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
492
480
  { createPromoteTaskOutputActivities },
493
481
  { createAttachSessionActivities },
494
482
  ] = await Promise.all([
495
- import("./activities/execute-cursor/index.js"),
483
+ import("./harness-adapters.js"),
484
+ import("./harness/registry.js"),
496
485
  import("./activities/execute-deep-agent/index.js"),
497
486
  import("./activities/ensure-thread.js"),
498
487
  import("./activities/generate-session-subject.js"),
@@ -513,7 +502,7 @@ async function createAllActivities(config: Config): Promise<WorkerActivities> {
513
502
  ]);
514
503
 
515
504
  return {
516
- ...createCursorActivities(config),
505
+ ...(await createHarnessActivities(HARNESS_ADAPTERS, config)),
517
506
  ...createDeepAgentActivities(config),
518
507
  ...createEnsureThreadActivities(),
519
508
  ...createGenerateSessionSubjectActivities(config),
@@ -4,7 +4,7 @@ import { join } from "node:path";
4
4
  import { tmpdir } from "node:os";
5
5
  import { uniquifyFilename, allocateUniqueName } from "../attachment-naming.js";
6
6
  import { injectAttachments } from "../../activities/execute-deep-agent/attachment-injector.js";
7
- import { resolveAttachments } from "../../activities/execute-cursor/attachment-resolver.js";
7
+ import { resolveAttachments } from "../attachment-resolver.js";
8
8
  import { getPlatformDir } from "../workspace/platform-dir.js";
9
9
  import { makeInMemoryArtifactStorage } from "../../__test-utils__/fake-artifact-storage.js";
10
10
  import type { WorkspaceBackend } from "../workspace/types.js";
@@ -1,5 +1,7 @@
1
1
  /**
2
- * Tests for the Cursor harness's attachment resolver.
2
+ * Tests for the attachment resolver, which the Cursor activity calls today
3
+ * and the turn runtime takes over in S2 M3 (S3 retires the native twin,
4
+ * execute-deep-agent/attachment-injector.ts).
3
5
  *
4
6
  * The load-bearing behaviors: storage-key attachments materialize under the
5
7
  * platform inputs dir (the universal path — every server-created attachment
@@ -14,9 +16,9 @@ import { mkdtempSync, writeFileSync, readFileSync, rmSync, lstatSync, readlinkSy
14
16
  import { join } from "node:path";
15
17
  import { tmpdir } from "node:os";
16
18
  import { resolveAttachments, AttachmentResolutionError } from "../attachment-resolver.js";
17
- import { getPlatformDir } from "../../../shared/workspace/platform-dir.js";
18
- import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifact-storage.js";
19
- import { CURSOR_VISION_PROFILE, VisionBudget } from "../../../shared/attachment-vision.js";
19
+ import { getPlatformDir } from "../workspace/platform-dir.js";
20
+ import { makeInMemoryArtifactStorage } from "../../__test-utils__/fake-artifact-storage.js";
21
+ import { CURSOR_VISION_PROFILE, VisionBudget } from "../attachment-vision.js";
20
22
 
21
23
  function makeAttachment(overrides: Partial<{
22
24
  filename: string;
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Unit tests for the Cursor harness's max_cost_usd guard (cost-guard.ts).
2
+ * Unit tests for the max_cost_usd hard-stop guard (cost-guard.ts), which the
3
+ * Cursor activity calls today and the turn runtime takes over in S2 M3.
3
4
  *
4
5
  * The guard is the cursor-side analog of the native cost-cap middleware
5
6
  * (middleware/cost-cap.ts): same proto semantics (0/unset = no cap), same
@@ -45,9 +45,9 @@ import {
45
45
  excludeAppliedFromGrants,
46
46
  resolveApprovedWholeFileContent,
47
47
  } from "../exact-apply.js";
48
- import { ELISION_MARKER } from "../../../shared/status-offload.js";
49
- import { mockWorkspaceBackend } from "../../../__test-utils__/mock-workspace.js";
50
- import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
48
+ import { ELISION_MARKER } from "../status-offload.js";
49
+ import { mockWorkspaceBackend } from "../../__test-utils__/mock-workspace.js";
50
+ import type { WorkspaceBackend } from "../workspace/types.js";
51
51
 
52
52
  const ROOT = "/root";
53
53
 
@@ -1,14 +1,14 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
- import type { Config } from "../../../config.js";
2
+ import type { Config } from "../../config.js";
3
3
 
4
- vi.mock("../../../shared/model-registry.js", () => ({
4
+ vi.mock("../model-registry.js", () => ({
5
5
  getEconomyModel: vi.fn().mockResolvedValue("gpt-4o-mini"),
6
6
  }));
7
7
 
8
8
  const mockInvoke = vi.fn();
9
9
  const mockWithStructuredOutput = vi.fn().mockReturnValue({ invoke: mockInvoke });
10
10
 
11
- vi.mock("../../../shared/model-client.js", () => ({
11
+ vi.mock("../model-client.js", () => ({
12
12
  buildChatModel: vi.fn().mockResolvedValue({
13
13
  model: { withStructuredOutput: (...args: unknown[]) => mockWithStructuredOutput(...args) },
14
14
  provider: "openai",
@@ -46,7 +46,7 @@ describe("extractStructuredOutput", () => {
46
46
 
47
47
  it("direct mode with a key builds a direct-mode model (no endpoint threaded)", async () => {
48
48
  vi.stubEnv("OPENAI_API_KEY", "sk-direct");
49
- const { buildChatModel } = await import("../../../shared/model-client.js");
49
+ const { buildChatModel } = await import("../model-client.js");
50
50
  const { extractStructuredOutput } = await import("../extract-structured-output.js");
51
51
  mockInvoke.mockResolvedValueOnce({ answer: "42" });
52
52
 
@@ -61,7 +61,7 @@ describe("extractStructuredOutput", () => {
61
61
  });
62
62
 
63
63
  it("throws the credential message before any construction when no path exists", async () => {
64
- const { buildChatModel } = await import("../../../shared/model-client.js");
64
+ const { buildChatModel } = await import("../model-client.js");
65
65
  const { extractStructuredOutput } = await import("../extract-structured-output.js");
66
66
 
67
67
  await expect(
@@ -72,7 +72,7 @@ describe("extractStructuredOutput", () => {
72
72
  });
73
73
 
74
74
  it("proxy mode threads the proxy endpoint and token, consulting no keys", async () => {
75
- const { buildChatModel } = await import("../../../shared/model-client.js");
75
+ const { buildChatModel } = await import("../model-client.js");
76
76
  const { extractStructuredOutput } = await import("../extract-structured-output.js");
77
77
  mockInvoke.mockResolvedValueOnce({ answer: "ok" });
78
78
 
@@ -95,9 +95,9 @@ describe("extractStructuredOutput", () => {
95
95
  // The registry-empty fallback returns the primary model verbatim; when
96
96
  // its provider can't be inferred the pre-check must not guess — the
97
97
  // construction path owns the precise message.
98
- const { getEconomyModel } = await import("../../../shared/model-registry.js");
98
+ const { getEconomyModel } = await import("../model-registry.js");
99
99
  vi.mocked(getEconomyModel).mockResolvedValueOnce("mystery-model");
100
- const { buildChatModel } = await import("../../../shared/model-client.js");
100
+ const { buildChatModel } = await import("../model-client.js");
101
101
  const { extractStructuredOutput } = await import("../extract-structured-output.js");
102
102
  mockInvoke.mockResolvedValueOnce({ answer: "ok" });
103
103
 
@@ -1,5 +1,7 @@
1
1
  /**
2
- * Unit tests for the Cursor streaming persist decision (issue #179).
2
+ * Unit tests for the streaming persist decision (issue #179), the shared
3
+ * cadence rule the Cursor stream loop calls today and the turn runtime
4
+ * takes over in S2 M3.
3
5
  *
4
6
  * Validates the converged cadence: discrete force-flush signals persist
5
7
  * immediately, while high-frequency token deltas ride the shared
@@ -11,7 +13,7 @@ import { describe, it, expect } from "vitest";
11
13
  import {
12
14
  StreamingUpdateScheduler,
13
15
  type StreamingConfig,
14
- } from "../../../shared/streaming-scheduler.js";
16
+ } from "../streaming-scheduler.js";
15
17
  import { shouldPersistStreamingStatus } from "../persist-decision.js";
16
18
 
17
19
  const CONFIG: StreamingConfig = {
@@ -75,7 +75,7 @@ describe("resolveSkills — artifact extraction", () => {
75
75
 
76
76
  // We need to clean up the platform dir after the test; capture it
77
77
  // via the getPlatformDir import so we know the actual path.
78
- const { getPlatformDir } = await import("../../../shared/workspace/platform-dir.js");
78
+ const { getPlatformDir } = await import("../workspace/platform-dir.js");
79
79
  const platformDir = getPlatformDir(sessionId);
80
80
 
81
81
  const client = {
@@ -0,0 +1,34 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { create } from "@bufbuild/protobuf";
3
+ import { SubAgentExecutionSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
4
+ import { SubAgentStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
+
6
+ import { cancelInProgressSubAgentProtos } from "../subagent-rows.js";
7
+
8
+ describe("cancelInProgressSubAgentProtos", () => {
9
+ it("cancels IN_PROGRESS/PENDING protos in place and reports whether anything changed", () => {
10
+ const running = create(SubAgentExecutionSchema, { id: "a", status: SubAgentStatus.SUB_AGENT_IN_PROGRESS });
11
+ const pending = create(SubAgentExecutionSchema, { id: "b", status: SubAgentStatus.SUB_AGENT_PENDING });
12
+ const completed = create(SubAgentExecutionSchema, {
13
+ id: "c",
14
+ status: SubAgentStatus.SUB_AGENT_COMPLETED,
15
+ completedAt: "2026-01-01T00:00:00Z",
16
+ });
17
+
18
+ const changed = cancelInProgressSubAgentProtos([running, pending, completed]);
19
+
20
+ expect(changed).toBe(true);
21
+ expect(running.status).toBe(SubAgentStatus.SUB_AGENT_CANCELLED);
22
+ expect(running.completedAt).not.toBe("");
23
+ expect(pending.status).toBe(SubAgentStatus.SUB_AGENT_CANCELLED);
24
+ // Terminal sub-agents are untouched.
25
+ expect(completed.status).toBe(SubAgentStatus.SUB_AGENT_COMPLETED);
26
+ expect(completed.completedAt).toBe("2026-01-01T00:00:00Z");
27
+ });
28
+
29
+ it("returns false when there is nothing to cancel", () => {
30
+ const completed = create(SubAgentExecutionSchema, { id: "c", status: SubAgentStatus.SUB_AGENT_COMPLETED });
31
+ expect(cancelInProgressSubAgentProtos([completed])).toBe(false);
32
+ expect(cancelInProgressSubAgentProtos([])).toBe(false);
33
+ });
34
+ });