@stigmer/runner 3.14.1 → 3.15.1

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
@@ -1,5 +1,7 @@
1
1
  import { describe, expect, it } from "vitest";
2
+ import { CancelledFailure } from "@temporalio/activity";
2
3
  import {
4
+ cancellationReasonOf,
3
5
  classifyTurnInterruption,
4
6
  getShutdownSignalForQueue,
5
7
  registerWorkerShutdownSignal,
@@ -44,58 +46,61 @@ describe("worker-shutdown signal registry", () => {
44
46
  });
45
47
 
46
48
  describe("classifyTurnInterruption", () => {
47
- const none = {
48
- heartbeatCancelled: false,
49
- heartbeatWorkerShutdown: false,
50
- cancellationSignalAborted: false,
51
- shutdownSignalAborted: false,
52
- };
53
-
54
49
  it("an uninterrupted turn is none", () => {
55
- expect(classifyTurnInterruption(none)).toBe("none");
50
+ expect(classifyTurnInterruption({ cancellationReason: undefined, shutdownSignalAborted: false })).toBe("none");
56
51
  });
57
52
 
58
53
  it("GRACE-WINDOW GUARD (#776): an aborted shutdown signal alone stays none — a run that completed inside the drain grace window must not be failed", () => {
59
- expect(
60
- classifyTurnInterruption({ ...none, shutdownSignalAborted: true }),
61
- ).toBe("none");
54
+ expect(classifyTurnInterruption({ cancellationReason: undefined, shutdownSignalAborted: true })).toBe("none");
55
+ });
56
+
57
+ it("a workflow-requested cancellation without a shutdown signal is the orchestrator's pause", () => {
58
+ expect(classifyTurnInterruption({ cancellationReason: "CANCELLED", shutdownSignalAborted: false })).toBe("pause");
59
+ });
60
+
61
+ it("a delivered cancellation WITH the shutdown signal aborted is a worker shutdown, not a pause (the #776 misclassification)", () => {
62
+ expect(classifyTurnInterruption({ cancellationReason: "CANCELLED", shutdownSignalAborted: true })).toBe("worker-shutdown");
62
63
  });
63
64
 
64
- it("heartbeat cancellation without a shutdown signal is the orchestrator's pause", () => {
65
- expect(
66
- classifyTurnInterruption({ ...none, heartbeatCancelled: true }),
67
- ).toBe("pause");
65
+ it("the SDK's own WORKER_SHUTDOWN reason classifies directly, signal or not", () => {
66
+ expect(classifyTurnInterruption({ cancellationReason: "WORKER_SHUTDOWN", shutdownSignalAborted: false })).toBe("worker-shutdown");
68
67
  });
69
68
 
70
- it("heartbeat cancellation WITH the shutdown signal aborted is a worker shutdown, not a pause (the #776 misclassification)", () => {
71
- expect(
72
- classifyTurnInterruption({
73
- ...none,
74
- heartbeatCancelled: true,
75
- shutdownSignalAborted: true,
76
- }),
77
- ).toBe("worker-shutdown");
69
+ it("a heartbeat timeout (TIMED_OUT) is an infrastructure cancel, neither shutdown nor pause", () => {
70
+ expect(classifyTurnInterruption({ cancellationReason: "TIMED_OUT", shutdownSignalAborted: false })).toBe("infrastructure");
78
71
  });
79
72
 
80
- it("the heartbeat's own workerShutdown flag classifies directly", () => {
81
- expect(
82
- classifyTurnInterruption({ ...none, heartbeatWorkerShutdown: true }),
83
- ).toBe("worker-shutdown");
73
+ it("any other reason (a closed run, a conversion failure) is an infrastructure cancel", () => {
74
+ expect(classifyTurnInterruption({ cancellationReason: "NOT_FOUND", shutdownSignalAborted: false })).toBe("infrastructure");
75
+ expect(classifyTurnInterruption({ cancellationReason: "HEARTBEAT_DETAILS_CONVERSION_FAILED", shutdownSignalAborted: false })).toBe("infrastructure");
76
+ });
77
+
78
+ it("the shutdown signal outranks an infrastructure reason: a drain is a drain whatever Temporal says", () => {
79
+ expect(classifyTurnInterruption({ cancellationReason: "TIMED_OUT", shutdownSignalAborted: true })).toBe("worker-shutdown");
80
+ });
81
+ });
82
+
83
+ describe("cancellationReasonOf", () => {
84
+ it("is undefined for a live signal", () => {
85
+ expect(cancellationReasonOf(new AbortController().signal)).toBeUndefined();
84
86
  });
85
87
 
86
- it("a delivered cancellation with the shutdown signal aborted is a worker shutdown (signal races the heartbeat tick)", () => {
87
- expect(
88
- classifyTurnInterruption({
89
- ...none,
90
- cancellationSignalAborted: true,
91
- shutdownSignalAborted: true,
92
- }),
93
- ).toBe("worker-shutdown");
88
+ it("reads the CancelledFailure message the Temporal SDK aborts with", () => {
89
+ const controller = new AbortController();
90
+ controller.abort(new CancelledFailure("TIMED_OUT"));
91
+ expect(cancellationReasonOf(controller.signal)).toBe("TIMED_OUT");
94
92
  });
95
93
 
96
- it("a delivered cancellation alone (heartbeat timeout / infra cancel) is neither shutdown nor pause", () => {
97
- expect(
98
- classifyTurnInterruption({ ...none, cancellationSignalAborted: true }),
99
- ).toBe("none");
94
+ it("reads a string reason as itself and a reasonless abort as CANCELLED", () => {
95
+ const withString = new AbortController();
96
+ withString.abort("WORKER_SHUTDOWN");
97
+ expect(cancellationReasonOf(withString.signal)).toBe("WORKER_SHUTDOWN");
98
+ const bare = new AbortController();
99
+ bare.abort();
100
+ // A bare abort() carries a DOMException (an Error), whose message is the
101
+ // platform's "This operation was aborted": not a Temporal reason, but a
102
+ // delivered cancellation all the same — the classifier files it as
103
+ // infrastructure, never as nothing.
104
+ expect(cancellationReasonOf(bare.signal)).toBeTypeOf("string");
100
105
  });
101
106
  });
@@ -438,7 +438,7 @@ export function mergeApprovalPolicies(
438
438
  export function lookupMcpToolPolicy(
439
439
  toolName: string,
440
440
  mcpServerSlug: string,
441
- policies: Map<string, MergedToolPolicy>,
441
+ policies: ReadonlyMap<string, MergedToolPolicy>,
442
442
  ): MergedToolPolicy | undefined {
443
443
  return policies.get(`${mcpServerSlug}/${toolName}`);
444
444
  }
@@ -39,18 +39,18 @@
39
39
  import { mkdir, copyFile, readFile, stat, writeFile } from "node:fs/promises";
40
40
  import { join, basename } from "node:path";
41
41
  import type { Attachment } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
42
- import type { ArtifactStorage } from "../../shared/artifact-storage.js";
43
- import { mintAttachmentDownloadUrl } from "../../shared/attachment-download-urls.js";
44
- import { allocateUniqueName } from "../../shared/attachment-naming.js";
42
+ import type { ArtifactStorage } from "./artifact-storage.js";
43
+ import { mintAttachmentDownloadUrl } from "./attachment-download-urls.js";
44
+ import { allocateUniqueName } from "./attachment-naming.js";
45
45
  import {
46
46
  isVisionCandidate,
47
47
  type VisionBudget,
48
48
  type VisionDegradedReason,
49
49
  type VisionImage,
50
50
  type VisionOutcome,
51
- } from "../../shared/attachment-vision.js";
52
- import { getPlatformDir } from "../../shared/workspace/platform-dir.js";
53
- import { ensureStigmerSymlink, STIGMER_LOCAL_STATE_DIR } from "../../shared/workspace/stigmer-link.js";
51
+ } from "./attachment-vision.js";
52
+ import { getPlatformDir } from "./workspace/platform-dir.js";
53
+ import { ensureStigmerSymlink, STIGMER_LOCAL_STATE_DIR } from "./workspace/stigmer-link.js";
54
54
 
55
55
  const INPUTS_SUBDIR = "inputs";
56
56
 
@@ -11,31 +11,25 @@
11
11
  * containing runner-internal markers are rejected with a warning.
12
12
  */
13
13
 
14
- import { resolve } from "node:path";
15
- import type { StigmerClient } from "../../client/stigmer-client.js";
14
+ import type { StigmerClient } from "../client/stigmer-client.js";
16
15
  import type { Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
17
16
  import type { AgentSpec, McpServerUsage, SubAgent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
18
17
  import type { Session } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
19
18
  import type { SessionSpec } from "@stigmer/protos/ai/stigmer/agentic/session/v1/spec_pb";
20
19
  import type { WorkspaceEntry } from "@stigmer/protos/ai/stigmer/agentic/session/v1/workspace_pb";
21
20
  import type { ApiResourceReference } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
22
- import type { CloudRepo } from "./session-lifecycle.js";
23
- import { mergeMcpServerUsages } from "../../shared/mcp-resolver.js";
21
+ import { mergeMcpServerUsages } from "./mcp-resolver.js";
24
22
 
25
23
  // Both harnesses must merge agent + session usages identically (session wins
26
24
  // per slug — the usage whose enabled_tools the enforcement honors), so the
27
25
  // merge lives in shared/mcp-resolver.ts. Re-exported here for its historical
28
26
  // home alongside mergeSkillRefs.
29
- export { mergeMcpServerUsages } from "../../shared/mcp-resolver.js";
27
+ export { mergeMcpServerUsages } from "./mcp-resolver.js";
30
28
 
31
- /**
32
- * Path segments that identify runner-internal directories. Any workspace dir
33
- * whose resolved absolute path contains one of these is rejected.
34
- */
35
- const RUNNER_INTERNAL_MARKERS = [
36
- "/runtimes/cursor-runner/",
37
- "/runtimes/agent-runner/",
38
- ] as const;
29
+ export interface CloudRepo {
30
+ url: string;
31
+ startingRef?: string;
32
+ }
39
33
 
40
34
  export interface ResolvedBlueprint {
41
35
  agent: Agent;
@@ -46,7 +40,6 @@ export interface ResolvedBlueprint {
46
40
  subAgents: SubAgent[];
47
41
  mergedMcpServerUsages: McpServerUsage[];
48
42
  mergedSkillRefs: ApiResourceReference[];
49
- workspaceDirs: string[];
50
43
  cloudRepos: CloudRepo[];
51
44
  }
52
45
 
@@ -59,7 +52,6 @@ export interface ResolvedBlueprint {
59
52
  export async function resolveBlueprint(
60
53
  client: StigmerClient,
61
54
  session: Session,
62
- fallbackWorkspaceDir: string,
63
55
  ): Promise<ResolvedBlueprint> {
64
56
  const sessionSpec = session.spec!;
65
57
 
@@ -78,7 +70,6 @@ export async function resolveBlueprint(
78
70
  sessionSpec.skillRefs,
79
71
  );
80
72
 
81
- const workspaceDirs = resolveWorkspaceDirs(sessionSpec, fallbackWorkspaceDir);
82
73
  const cloudRepos = resolveCloudRepos(sessionSpec.workspaceEntries);
83
74
 
84
75
  return {
@@ -90,7 +81,6 @@ export async function resolveBlueprint(
90
81
  subAgents: agentSpec.subAgents,
91
82
  mergedMcpServerUsages,
92
83
  mergedSkillRefs,
93
- workspaceDirs,
94
84
  cloudRepos,
95
85
  };
96
86
  }
@@ -151,64 +141,3 @@ export function mergeSkillRefs(
151
141
 
152
142
  return [...bySlug.values()];
153
143
  }
154
-
155
- // ---------------------------------------------------------------------------
156
- // Local workspace resolution
157
- // ---------------------------------------------------------------------------
158
-
159
- /**
160
- * Resolve workspace directories from session workspace entries.
161
- *
162
- * For local path entries: use the local path directly.
163
- * Falls back to the config's workspaceRootDir when no entries exist.
164
- *
165
- * All resolved paths are validated to ensure they do not overlap with
166
- * the runner's own internal directories. Any path that fails validation
167
- * is replaced with the fallback directory.
168
- */
169
- function resolveWorkspaceDirs(
170
- sessionSpec: SessionSpec,
171
- fallbackDir: string,
172
- ): string[] {
173
- const safeFallback = validateWorkspaceDir(fallbackDir)
174
- ? fallbackDir
175
- : logAndSkipRunnerDir(fallbackDir, "fallback config");
176
-
177
- if (!sessionSpec.workspaceEntries.length) {
178
- return safeFallback ? [safeFallback] : [];
179
- }
180
-
181
- const dirs: string[] = [];
182
- for (const entry of sessionSpec.workspaceEntries) {
183
- if (entry.source?.source.case === "localPath") {
184
- const path = entry.source.source.value.path;
185
- if (validateWorkspaceDir(path)) {
186
- dirs.push(path);
187
- } else {
188
- logAndSkipRunnerDir(path, "session workspace entry");
189
- }
190
- }
191
- }
192
-
193
- if (dirs.length > 0) {
194
- return dirs;
195
- }
196
-
197
- return safeFallback ? [safeFallback] : [];
198
- }
199
-
200
- /**
201
- * Returns true if the directory is safe (not a runner-internal path).
202
- */
203
- function validateWorkspaceDir(dir: string): boolean {
204
- const absolute = resolve(dir);
205
- return !RUNNER_INTERNAL_MARKERS.some((marker) => absolute.includes(marker));
206
- }
207
-
208
- function logAndSkipRunnerDir(dir: string, source: string): undefined {
209
- console.warn(
210
- `Workspace dir from ${source} ("${dir}") is a runner-internal path — ` +
211
- "rejecting to prevent implementation detail leakage.",
212
- );
213
- return undefined;
214
- }
@@ -164,7 +164,7 @@ export function synthesizeChannelAttachment(
164
164
  * aid). Returns "" when nothing survives the filter — the tool alone
165
165
  * still serves text sends inside a 24-hour window.
166
166
  */
167
- export function formatChannelTemplatesSection(channels: ChannelMessagingInfo[]): string {
167
+ export function formatChannelTemplatesSection(channels: readonly ChannelMessagingInfo[]): string {
168
168
  let withheld = 0;
169
169
  let budget = TEMPLATE_SECTION_CAP;
170
170
 
@@ -1,5 +1,9 @@
1
1
  /**
2
- * ExecutionConfig.max_cost_usd enforcement for the Cursor harness.
2
+ * ExecutionConfig.max_cost_usd enforcement as a hard stop on a harness turn.
3
+ *
4
+ * Harness-agnostic: the Cursor activity is today's only caller and the turn
5
+ * runtime takes it over in S2 M3. The rationale below is Cursor's, and it is
6
+ * why the module is shaped as a hard stop rather than a middleware.
3
7
  *
4
8
  * The native harness enforces the cap in middleware (cost-cap.ts): tools are
5
9
  * blocked at the threshold and the model gets one final tool-free round to
@@ -6,7 +6,7 @@
6
6
  * (e.g. API keys for HTTP headers, secrets for stdio subprocesses).
7
7
  */
8
8
 
9
- import type { StigmerClient } from "../../client/stigmer-client.js";
9
+ import type { StigmerClient } from "../client/stigmer-client.js";
10
10
 
11
11
  export interface EnvResult {
12
12
  envVars: Record<string, string>;
@@ -57,11 +57,11 @@ import type {
57
57
  ToolCall,
58
58
  } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
59
59
  import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
60
- import { ELISION_MARKER } from "../../shared/status-offload.js";
61
- import { extractFilePath, extractWriteContent } from "../../shared/file-tools.js";
62
- import { resolveWorkspacePath } from "../../shared/file-change.js";
63
- import type { WorkspaceBackend } from "../../shared/workspace/types.js";
64
- import { utcTimestamp } from "../../shared/status.js";
60
+ import { ELISION_MARKER } from "./status-offload.js";
61
+ import { extractFilePath, extractWriteContent } from "./file-tools.js";
62
+ import { resolveWorkspacePath } from "./file-change.js";
63
+ import type { WorkspaceBackend } from "./workspace/types.js";
64
+ import { utcTimestamp } from "./status.js";
65
65
 
66
66
  /** Options for {@link applyApprovedWholeFileWrites}. */
67
67
  export interface ExactApplyOptions {
@@ -148,7 +148,7 @@ export async function applyApprovedWholeFileWrites(
148
148
  tc.error = "";
149
149
  applied.add(tc.id);
150
150
  console.log(
151
- `ExecuteCursor exact-apply: wrote approved bytes to ${target} ` +
151
+ `[exact-apply] wrote approved bytes to ${target} ` +
152
152
  `(tool=${tc.id}); no resource grant issued, so a further change ` +
153
153
  `re-gates. execution=${opts.executionId}`,
154
154
  );
@@ -247,7 +247,7 @@ function isWithinWorkspace(
247
247
 
248
248
  function logSkip(executionId: string, tc: ToolCall, reason: string): void {
249
249
  console.log(
250
- `ExecuteCursor exact-apply skipped (falling back to grant+reinvocation): ` +
250
+ `[exact-apply] skipped (falling back to grant+reinvocation): ` +
251
251
  `tool=${tc.id} reason="${reason}" execution=${executionId}`,
252
252
  );
253
253
  }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The execution-scoped context — "this async work belongs to execution X" —
3
+ * as an `AsyncLocalStorage` the turn runtime enters once around the WHOLE
4
+ * activity, and the transport layer reads per request.
5
+ *
6
+ * Why it is the runtime's and not a harness's: every proxy-bound request the
7
+ * runner makes carries `x-stigmer-execution-id` from this store (the Cursor
8
+ * fetch and HTTP/2 interceptors stamp it; `rejection-capture.ts` correlates
9
+ * unhandled rejections by it), and a large share of those requests are made
10
+ * OUTSIDE any engine stretch — attachment downloads and status offload
11
+ * through the artifact proxy, the memory selection, the structured-output
12
+ * extraction and the plan-artifact publish in the epilogue, and in a cloud
13
+ * sandbox the control-plane writes themselves. Under `maxConcurrentActivities
14
+ * > 1` the fallback (a module-level id, `fetch-interceptor.ts`
15
+ * `setInterceptorExecutionId`) is whichever turn set it last; this store is
16
+ * what makes concurrent turns not overwrite each other's headers.
17
+ *
18
+ * Moved from `activities/execute-cursor/fetch-interceptor.ts` (S2 M3,
19
+ * Q-M3-12) so `harness/run-turn.ts` can enter it without importing the
20
+ * adapter; the interceptors import it from here. No harness enters it: the
21
+ * contract lists it among the things deliberately NOT on `TurnSink`.
22
+ */
23
+
24
+ import { AsyncLocalStorage } from "node:async_hooks";
25
+
26
+ export interface ExecutionContextStore {
27
+ readonly executionId: string;
28
+ }
29
+
30
+ const executionContext = new AsyncLocalStorage<ExecutionContextStore>();
31
+
32
+ /** The store, for readers that stamp or correlate by execution id. */
33
+ export function getExecutionContext(): AsyncLocalStorage<ExecutionContextStore> {
34
+ return executionContext;
35
+ }
36
+
37
+ /**
38
+ * Run an async function with execution-scoped context. The executionId is
39
+ * propagated through the async call chain via AsyncLocalStorage, ensuring
40
+ * concurrent activities on the same runner process don't overwrite each
41
+ * other's proxy headers.
42
+ */
43
+ export function runWithExecutionContext<T>(executionId: string, fn: () => Promise<T>): Promise<T> {
44
+ return executionContext.run({ executionId }, fn);
45
+ }
@@ -1,5 +1,8 @@
1
1
  /**
2
- * Tier-2 structured-output extraction for the Cursor harness.
2
+ * Tier-2 structured-output extraction for a harness turn.
3
+ *
4
+ * Harness-agnostic: the Cursor activity is today's only caller and the turn
5
+ * runtime takes it over in S2 M3 (the native harness has no tier 2 today).
3
6
  *
4
7
  * When tier-1 text extraction (shared/extract-json.ts) cannot find JSON in
5
8
  * the agent's free-text response, this tier asks an economy-tier LLM to
@@ -13,12 +16,12 @@
13
16
  * bundle-slim's deferred evaluation preserves.
14
17
  */
15
18
 
16
- import type { Config } from "../../config.js";
17
- import { getEconomyModel } from "../../shared/model-registry.js";
18
- import { buildChatModel } from "../../shared/model-client.js";
19
- import { checkDirectCredentials } from "../../shared/llm-backend.js";
20
- import { tryInferProvider } from "../../shared/llm-proxy.js";
21
- import { jsonSchemaToZod } from "../../shared/json-schema-to-zod.js";
19
+ import type { Config } from "../config.js";
20
+ import { getEconomyModel } from "./model-registry.js";
21
+ import { buildChatModel } from "./model-client.js";
22
+ import { checkDirectCredentials } from "./llm-backend.js";
23
+ import { tryInferProvider } from "./llm-proxy.js";
24
+ import { jsonSchemaToZod } from "./json-schema-to-zod.js";
22
25
 
23
26
  /**
24
27
  * Extract structured data from an agent's free-text response using an
@@ -95,7 +95,7 @@ import { isSecretLikePath } from "./secret-paths.js";
95
95
  * no capture substrate and falls back to the deny-gate: the agent still runs, but
96
96
  * file writes gate pre-execution instead of flowing. In the Cursor harness that
97
97
  * fallback is also the ONLY branch that arms the resume-time exact-apply guarantee
98
- * (see execute-cursor/exact-apply.ts); the deep-agent harness re-applies an
98
+ * (see shared/exact-apply.ts); the deep-agent harness re-applies an
99
99
  * approved write via LangGraph checkpoint replay and needs no exact-apply. Keeping
100
100
  * this the single, named, truth-table-tested decision pins exactly when the
101
101
  * no-storage deny-gate engages in either harness.
@@ -3,50 +3,36 @@
3
3
  *
4
4
  * Provides a periodic heartbeat loop that activities can start for
5
5
  * long-running operations. The loop sends heartbeat details at a
6
- * configurable interval and stops when cancelled or when the
7
- * returned abort function is called.
6
+ * configurable interval and stops when the returned handle is stopped.
8
7
  *
9
- * Heartbeats serve two purposes:
10
- * 1. Prevent Temporal from timing out the activity (heartbeatTimeout)
11
- * 2. Detect parent workflow cancellation (CancelledFailure from heartbeat)
8
+ * Heartbeats keep Temporal from timing the activity out
9
+ * (`heartbeatTimeout`) and are how an activity RECEIVES cancellation: the
10
+ * server piggybacks a cancel request on a heartbeat response, and the SDK
11
+ * then aborts `Context.current().cancellationSignal`. `Context.heartbeat()`
12
+ * itself never throws for cancellation (it enqueues to the worker's
13
+ * heartbeat subject — `@temporalio/activity/lib/index.js`
14
+ * `Context.heartbeat`, `@temporalio/worker/lib/worker.js` the heartbeat
15
+ * callback; the SDK's own doc: "Cancellation is not propagated from this
16
+ * function"). Until S2 M3 this handle carried two flags for a throw that
17
+ * cannot happen; a turn reads its interruption from the signal's reason
18
+ * instead (`worker-shutdown.ts` `classifyTurnInterruption`).
12
19
  */
13
20
 
14
21
  import { Context, CancelledFailure } from "@temporalio/activity";
15
22
 
16
23
  export interface HeartbeatHandle {
17
24
  stop(): void;
18
- readonly cancelled: boolean;
19
- readonly workerShutdown: boolean;
20
- }
21
-
22
- export interface HeartbeatOptions {
23
- shutdownSignal?: AbortSignal;
24
25
  }
25
26
 
26
27
  export function startHeartbeat(
27
28
  intervalMs: number,
28
29
  getDetails?: () => Record<string, unknown>,
29
- options?: HeartbeatOptions,
30
30
  ): HeartbeatHandle {
31
31
  let stopped = false;
32
- let wasCancelled = false;
33
- let wasWorkerShutdown = false;
34
32
 
35
33
  const timer = setInterval(() => {
36
34
  if (stopped) return;
37
- try {
38
- Context.current().heartbeat(getDetails?.());
39
- } catch (err) {
40
- if (err instanceof CancelledFailure) {
41
- if (options?.shutdownSignal?.aborted) {
42
- wasWorkerShutdown = true;
43
- } else {
44
- wasCancelled = true;
45
- }
46
- stopped = true;
47
- clearInterval(timer);
48
- }
49
- }
35
+ Context.current().heartbeat(getDetails?.());
50
36
  }, intervalMs);
51
37
 
52
38
  return {
@@ -54,12 +40,6 @@ export function startHeartbeat(
54
40
  stopped = true;
55
41
  clearInterval(timer);
56
42
  },
57
- get cancelled() {
58
- return wasCancelled;
59
- },
60
- get workerShutdown() {
61
- return wasWorkerShutdown;
62
- },
63
43
  };
64
44
  }
65
45
 
@@ -1,5 +1,8 @@
1
1
  /**
2
- * Streaming persist decision for the Cursor harness.
2
+ * Streaming persist decision for a harness turn.
3
+ *
4
+ * Harness-agnostic: the Cursor stream loop is today's only caller, the turn
5
+ * runtime takes it over in S2 M3, and S3 retires the native twin below.
3
6
  *
4
7
  * Mirrors the native deep-agent harness (execute-deep-agent/streaming.ts):
5
8
  * `shouldPersist = forceFlush || scheduler.shouldSendUpdate(eventCount)`.
@@ -10,7 +13,7 @@
10
13
  * exercise the same implementation and cannot drift.
11
14
  */
12
15
 
13
- import type { StreamingUpdateScheduler } from "../../shared/streaming-scheduler.js";
16
+ import type { StreamingUpdateScheduler } from "./streaming-scheduler.js";
14
17
 
15
18
  /**
16
19
  * Force-flush signals — discrete, user-visible state changes that must reach the
@@ -5,9 +5,17 @@
5
5
  * - Mounts each skill via the shared skill-mount mechanics (SKILL.md +
6
6
  * extracted artifact, hash-keyed cache — see shared/skill-mount.ts)
7
7
  * - Uses a platform-managed directory outside the workspace
8
- * - Ensures the workspace `.stigmer` symlink (see stigmer-link.ts)
8
+ * - Ensures the workspace `.stigmer` symlink (see workspace/stigmer-link.ts)
9
9
  * - Returns metadata for prompt injection
10
10
  *
11
+ * A turn-runtime phase (`harness/turn-context.ts` `mountSkills`): it reads
12
+ * the control plane, which only the runtime holds, and writes under the
13
+ * platform dir the runtime owns; the harness renders the returned metadata
14
+ * into its prompt in its own placement. Moved from
15
+ * `activities/execute-cursor/` at S2 M3b; the native harness's twin
16
+ * (`skill-writer.ts` `fetchSkillsByRefs` + `mountSkills`) is what S3
17
+ * reconciles it with.
18
+ *
11
19
  * The mount is cached by the skill's content-addressed version hash
12
20
  * (stigmer/stigmer#672): metadata is fetched on every execution (that keeps
13
21
  * latest-version freshness), but the artifact download and file rewrite are
@@ -19,17 +27,23 @@
19
27
 
20
28
  import { mkdir } from "node:fs/promises";
21
29
  import { join } from "node:path";
22
- import type { StigmerClient } from "../../client/stigmer-client.js";
30
+ import type { StigmerClient } from "../client/stigmer-client.js";
23
31
  import type { ApiResourceReference } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
24
- import type { SkillMetadata } from "./prompt-builder.js";
25
- import { getPlatformDir } from "../../shared/workspace/platform-dir.js";
32
+ import { getPlatformDir } from "./workspace/platform-dir.js";
26
33
  import {
27
34
  SKILLS_SUBDIR,
28
35
  mountIsFresh,
29
36
  downloadArtifact,
30
37
  writeSkillMount,
31
- } from "../../shared/skill-mount.js";
32
- import { ensureStigmerSymlink, STIGMER_LOCAL_STATE_DIR } from "../../shared/workspace/stigmer-link.js";
38
+ } from "./skill-mount.js";
39
+ import { ensureStigmerSymlink, STIGMER_LOCAL_STATE_DIR } from "./workspace/stigmer-link.js";
40
+
41
+ /** One mounted skill as a prompt renders it: its name, its description, and the workspace-relative path of its SKILL.md. */
42
+ export interface SkillMetadata {
43
+ name: string;
44
+ description: string;
45
+ path: string;
46
+ }
33
47
 
34
48
  export interface SkillResolverOptions {
35
49
  sessionId: string;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Terminal transitions on the sub-agent rows of an execution status,
3
+ * operating on the proto array itself.
4
+ *
5
+ * One function today: marking every non-terminal sub-agent CANCELLED when a
6
+ * turn ends without them (a pause, a shutdown, a stall, a cost cap, an
7
+ * infrastructure cancel), so the final snapshot has no permanent IN_PROGRESS
8
+ * "zombie" delegation. Harness-agnostic (a `SubAgentExecution` is the
9
+ * platform's row, not an engine's), read by the turn runtime's terminal
10
+ * table and the Cursor accumulator's own finalize alike.
11
+ *
12
+ * Moved from `activities/execute-cursor/message-translator.ts` at S2 M3 so
13
+ * the runtime's catch can reach it; the body is unchanged.
14
+ */
15
+
16
+ import type { SubAgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/subagent_pb";
17
+ import { SubAgentStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
18
+
19
+ import { utcTimestamp } from "./status.js";
20
+
21
+ /**
22
+ * Transition any non-terminal sub-agent (IN_PROGRESS or PENDING) in the given
23
+ * proto array to CANCELLED with a completion timestamp, in place. Returns
24
+ * true if any sub-agent changed.
25
+ */
26
+ export function cancelInProgressSubAgentProtos(subAgents: SubAgentExecution[]): boolean {
27
+ let changed = false;
28
+ for (const sub of subAgents) {
29
+ if (
30
+ sub.status === SubAgentStatus.SUB_AGENT_IN_PROGRESS ||
31
+ sub.status === SubAgentStatus.SUB_AGENT_PENDING
32
+ ) {
33
+ sub.status = SubAgentStatus.SUB_AGENT_CANCELLED;
34
+ sub.completedAt = utcTimestamp();
35
+ changed = true;
36
+ }
37
+ }
38
+ return changed;
39
+ }