@stigmer/runner 3.14.0 → 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 (331) 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 +268 -0
  9. package/dist/__test-utils__/hermetic-activity.js +385 -0
  10. package/dist/__test-utils__/hermetic-activity.js.map +1 -0
  11. package/dist/__test-utils__/mock-client.d.ts +13 -0
  12. package/dist/__test-utils__/mock-client.js +45 -0
  13. package/dist/__test-utils__/mock-client.js.map +1 -0
  14. package/dist/__test-utils__/mock-workspace.d.ts +15 -0
  15. package/dist/__test-utils__/mock-workspace.js +21 -0
  16. package/dist/__test-utils__/mock-workspace.js.map +1 -0
  17. package/dist/__test-utils__/model-registry-fixture.d.ts +56 -0
  18. package/dist/__test-utils__/model-registry-fixture.js +66 -0
  19. package/dist/__test-utils__/model-registry-fixture.js.map +1 -0
  20. package/dist/__test-utils__/turn-input-fixture.d.ts +60 -0
  21. package/dist/__test-utils__/turn-input-fixture.js +118 -0
  22. package/dist/__test-utils__/turn-input-fixture.js.map +1 -0
  23. package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +107 -0
  24. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +344 -0
  25. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -0
  26. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +20 -0
  27. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +58 -0
  28. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -1
  29. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +2 -32
  30. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
  31. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +148 -0
  32. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +257 -0
  33. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -0
  34. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +183 -0
  35. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +262 -0
  36. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -0
  37. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +138 -0
  38. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +191 -0
  39. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -0
  40. package/dist/activities/execute-cursor/adapter.d.ts +55 -0
  41. package/dist/activities/execute-cursor/adapter.js +119 -0
  42. package/dist/activities/execute-cursor/adapter.js.map +1 -0
  43. package/dist/activities/execute-cursor/approval-state.d.ts +2 -2
  44. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  45. package/dist/activities/execute-cursor/capture-flow.d.ts +15 -30
  46. package/dist/activities/execute-cursor/capture-flow.js +17 -26
  47. package/dist/activities/execute-cursor/capture-flow.js.map +1 -1
  48. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +23 -0
  49. package/dist/activities/execute-cursor/cursor-capabilities.js +33 -0
  50. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -0
  51. package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +2 -2
  52. package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -1
  53. package/dist/activities/execute-cursor/fetch-interceptor.d.ts +15 -25
  54. package/dist/activities/execute-cursor/fetch-interceptor.js +39 -33
  55. package/dist/activities/execute-cursor/fetch-interceptor.js.map +1 -1
  56. package/dist/activities/execute-cursor/http2-interceptor.d.ts +21 -17
  57. package/dist/activities/execute-cursor/http2-interceptor.js +38 -31
  58. package/dist/activities/execute-cursor/http2-interceptor.js.map +1 -1
  59. package/dist/activities/execute-cursor/message-translator.d.ts +28 -19
  60. package/dist/activities/execute-cursor/message-translator.js +76 -27
  61. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  62. package/dist/activities/execute-cursor/prompt-builder.d.ts +180 -11
  63. package/dist/activities/execute-cursor/prompt-builder.js +171 -0
  64. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  65. package/dist/activities/execute-cursor/rejection-capture.d.ts +3 -6
  66. package/dist/activities/execute-cursor/rejection-capture.js +5 -7
  67. package/dist/activities/execute-cursor/rejection-capture.js.map +1 -1
  68. package/dist/activities/execute-cursor/session-lifecycle.d.ts +1 -4
  69. package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -1
  70. package/dist/activities/execute-cursor/turn-boundary.d.ts +1 -1
  71. package/dist/activities/execute-cursor/turn-settle.d.ts +49 -0
  72. package/dist/activities/execute-cursor/turn-settle.js +507 -0
  73. package/dist/activities/execute-cursor/turn-settle.js.map +1 -0
  74. package/dist/activities/execute-cursor/turn-setup.d.ts +173 -0
  75. package/dist/activities/execute-cursor/turn-setup.js +496 -0
  76. package/dist/activities/execute-cursor/turn-setup.js.map +1 -0
  77. package/dist/activities/execute-cursor/turn-stream.d.ts +41 -71
  78. package/dist/activities/execute-cursor/turn-stream.js +70 -135
  79. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  80. package/dist/activities/execute-cursor/turn.d.ts +43 -0
  81. package/dist/activities/execute-cursor/turn.js +222 -0
  82. package/dist/activities/execute-cursor/turn.js.map +1 -0
  83. package/dist/activities/execute-cursor/usage-pricing.d.ts +38 -0
  84. package/dist/activities/execute-cursor/usage-pricing.js +50 -0
  85. package/dist/activities/execute-cursor/usage-pricing.js.map +1 -0
  86. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +1 -1
  87. package/dist/activities/execute-deep-agent/approval-file-change.js +1 -1
  88. package/dist/activities/execute-deep-agent/environment.js +1 -1
  89. package/dist/activities/execute-deep-agent/environment.js.map +1 -1
  90. package/dist/activities/execute-deep-agent/setup.js +3 -2
  91. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  92. package/dist/activities/hydrate-workflow-execution.js +1 -1
  93. package/dist/activities/hydrate-workflow-execution.js.map +1 -1
  94. package/dist/config.d.ts +15 -0
  95. package/dist/config.js.map +1 -1
  96. package/dist/harness/capabilities.d.ts +87 -0
  97. package/dist/harness/capabilities.js +37 -0
  98. package/dist/harness/capabilities.js.map +1 -0
  99. package/dist/harness/persist-chokepoint.d.ts +74 -0
  100. package/dist/harness/persist-chokepoint.js +88 -0
  101. package/dist/harness/persist-chokepoint.js.map +1 -0
  102. package/dist/harness/registry.d.ts +106 -0
  103. package/dist/harness/registry.js +168 -0
  104. package/dist/harness/registry.js.map +1 -0
  105. package/dist/harness/run-turn.d.ts +53 -0
  106. package/dist/harness/run-turn.js +528 -0
  107. package/dist/harness/run-turn.js.map +1 -0
  108. package/dist/harness/stop-controller.d.ts +50 -0
  109. package/dist/harness/stop-controller.js +62 -0
  110. package/dist/harness/stop-controller.js.map +1 -0
  111. package/dist/harness/terminal-table.d.ts +141 -0
  112. package/dist/harness/terminal-table.js +239 -0
  113. package/dist/harness/terminal-table.js.map +1 -0
  114. package/dist/harness/turn-context.d.ts +523 -0
  115. package/dist/harness/turn-context.js +739 -0
  116. package/dist/harness/turn-context.js.map +1 -0
  117. package/dist/harness/types.d.ts +448 -0
  118. package/dist/harness/types.js +64 -0
  119. package/dist/harness/types.js.map +1 -0
  120. package/dist/harness/usage-accumulator.d.ts +68 -0
  121. package/dist/harness/usage-accumulator.js +101 -0
  122. package/dist/harness/usage-accumulator.js.map +1 -0
  123. package/dist/harness-adapters.d.ts +27 -0
  124. package/dist/harness-adapters.js +28 -0
  125. package/dist/harness-adapters.js.map +1 -0
  126. package/dist/main.js.map +1 -1
  127. package/dist/runner-manager.js +64 -48
  128. package/dist/runner-manager.js.map +1 -1
  129. package/dist/runner.d.ts +5 -4
  130. package/dist/runner.js +65 -64
  131. package/dist/runner.js.map +1 -1
  132. package/dist/shared/approval-policy.d.ts +1 -1
  133. package/dist/shared/approval-policy.js.map +1 -1
  134. package/dist/{activities/execute-cursor → shared}/attachment-resolver.d.ts +2 -2
  135. package/dist/{activities/execute-cursor → shared}/attachment-resolver.js +5 -5
  136. package/dist/shared/attachment-resolver.js.map +1 -0
  137. package/dist/{activities/execute-cursor → shared}/blueprint-resolver.d.ts +7 -5
  138. package/dist/{activities/execute-cursor → shared}/blueprint-resolver.js +3 -63
  139. package/dist/shared/blueprint-resolver.js.map +1 -0
  140. package/dist/shared/channel-attachment.d.ts +1 -1
  141. package/dist/shared/channel-attachment.js.map +1 -1
  142. package/dist/{activities/execute-cursor → shared}/cost-guard.d.ts +5 -1
  143. package/dist/{activities/execute-cursor → shared}/cost-guard.js +5 -1
  144. package/dist/shared/cost-guard.js.map +1 -0
  145. package/dist/{activities/execute-cursor → shared}/env-resolver.d.ts +1 -1
  146. package/dist/shared/env-resolver.js.map +1 -0
  147. package/dist/{activities/execute-cursor → shared}/exact-apply.d.ts +1 -1
  148. package/dist/{activities/execute-cursor → shared}/exact-apply.js +6 -6
  149. package/dist/shared/exact-apply.js.map +1 -0
  150. package/dist/shared/execution-context.d.ts +35 -0
  151. package/dist/shared/execution-context.js +38 -0
  152. package/dist/shared/execution-context.js.map +1 -0
  153. package/dist/{activities/execute-cursor → shared}/extract-structured-output.d.ts +5 -2
  154. package/dist/{activities/execute-cursor → shared}/extract-structured-output.js +9 -6
  155. package/dist/shared/extract-structured-output.js.map +1 -0
  156. package/dist/shared/filereview/capture.d.ts +1 -1
  157. package/dist/shared/filereview/capture.js +1 -1
  158. package/dist/shared/heartbeat.d.ts +13 -11
  159. package/dist/shared/heartbeat.js +14 -29
  160. package/dist/shared/heartbeat.js.map +1 -1
  161. package/dist/{activities/execute-cursor → shared}/persist-decision.d.ts +5 -2
  162. package/dist/{activities/execute-cursor → shared}/persist-decision.js +4 -1
  163. package/dist/shared/persist-decision.js.map +1 -0
  164. package/dist/{activities/execute-cursor → shared}/skill-resolver.d.ts +16 -3
  165. package/dist/{activities/execute-cursor → shared}/skill-resolver.js +12 -4
  166. package/dist/shared/skill-resolver.js.map +1 -0
  167. package/dist/shared/subagent-rows.d.ts +21 -0
  168. package/dist/shared/subagent-rows.js +34 -0
  169. package/dist/shared/subagent-rows.js.map +1 -0
  170. package/dist/shared/worker-shutdown.d.ts +43 -16
  171. package/dist/shared/worker-shutdown.js +28 -13
  172. package/dist/shared/worker-shutdown.js.map +1 -1
  173. package/dist/shared/workspace/platform-dir.d.ts +1 -1
  174. package/dist/shared/workspace/platform-dir.js +1 -1
  175. package/dist/shared/workspace/session-provision.d.ts +54 -0
  176. package/dist/{activities/execute-cursor/workspace-provision.js → shared/workspace/session-provision.js} +15 -12
  177. package/dist/shared/workspace/session-provision.js.map +1 -0
  178. package/package.json +4 -4
  179. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +325 -0
  180. package/src/__test-utils__/config-fixture.ts +63 -0
  181. package/src/__test-utils__/execution-record-fixture.ts +104 -0
  182. package/src/__test-utils__/harness-boot-order-child.ts +58 -0
  183. package/src/__test-utils__/harness-contract/contract.ts +581 -0
  184. package/src/__test-utils__/harness-contract/recording-sink.ts +107 -0
  185. package/src/__test-utils__/harness-contract/runtime-contract.ts +666 -0
  186. package/src/__test-utils__/harness-contract/scripted-adapter.ts +349 -0
  187. package/src/__test-utils__/harness-contract/types.ts +176 -0
  188. package/src/__test-utils__/hermetic-activity.ts +502 -0
  189. package/src/__test-utils__/model-registry-fixture.ts +72 -0
  190. package/src/__test-utils__/module-specifiers.ts +82 -0
  191. package/src/__test-utils__/proto-helpers.ts +25 -0
  192. package/src/__test-utils__/turn-input-fixture.ts +155 -0
  193. package/src/__tests__/harness-boot-order.test.ts +77 -0
  194. package/src/__tests__/harness-contract.test.ts +27 -0
  195. package/src/__tests__/runner-manager.test.ts +18 -0
  196. package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +102 -0
  197. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +396 -0
  198. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +66 -0
  199. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +2 -43
  200. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +342 -0
  201. package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +368 -0
  202. package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +254 -0
  203. package/src/activities/execute-cursor/__tests__/adapter-is-temporal-free.test.ts +45 -0
  204. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +90 -0
  205. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +7 -8
  206. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +28 -1
  207. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +1 -1
  208. package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +64 -6
  209. package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +228 -0
  210. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +180 -0
  211. package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.status.json +53 -0
  212. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn1.status.json +55 -0
  213. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn2.status.json +77 -0
  214. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-capture.status.json +126 -0
  215. package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.status.json +40 -0
  216. package/src/activities/execute-cursor/__tests__/hermetic/goldens/plain-turn.status.json +48 -0
  217. package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.status.json +56 -0
  218. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-fresh-agent.status.json +53 -0
  219. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-transport-timeout.status.json +48 -0
  220. package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
  221. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-cancelled.status.json +36 -0
  222. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-error-non-retryable.status.json +37 -0
  223. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +38 -0
  224. package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.status.json +59 -0
  225. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-call.status.json +68 -0
  226. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +79 -0
  227. package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.status.json +42 -0
  228. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +170 -0
  229. package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +205 -0
  230. package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +171 -0
  231. package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +156 -0
  232. package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +286 -0
  233. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +332 -0
  234. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +193 -0
  235. package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +137 -0
  236. package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +185 -0
  237. package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +151 -0
  238. package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +65 -35
  239. package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -40
  240. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +171 -0
  241. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +118 -243
  242. package/src/activities/execute-cursor/__tests__/usage-pricing.test.ts +84 -0
  243. package/src/activities/execute-cursor/adapter.ts +138 -0
  244. package/src/activities/execute-cursor/approval-state.ts +2 -2
  245. package/src/activities/execute-cursor/capture-flow.ts +18 -41
  246. package/src/activities/execute-cursor/cursor-capabilities.ts +35 -0
  247. package/src/activities/execute-cursor/cursor-mcp-config.ts +2 -2
  248. package/src/activities/execute-cursor/fetch-interceptor.ts +48 -45
  249. package/src/activities/execute-cursor/http2-interceptor.ts +47 -34
  250. package/src/activities/execute-cursor/message-translator.ts +90 -45
  251. package/src/activities/execute-cursor/prompt-builder.ts +327 -12
  252. package/src/activities/execute-cursor/rejection-capture.ts +5 -12
  253. package/src/activities/execute-cursor/session-lifecycle.ts +1 -5
  254. package/src/activities/execute-cursor/turn-boundary.ts +1 -1
  255. package/src/activities/execute-cursor/turn-settle.ts +601 -0
  256. package/src/activities/execute-cursor/turn-setup.ts +645 -0
  257. package/src/activities/execute-cursor/turn-stream.ts +84 -210
  258. package/src/activities/execute-cursor/turn.ts +240 -0
  259. package/src/activities/execute-cursor/usage-pricing.ts +67 -0
  260. package/src/activities/execute-deep-agent/approval-file-change.ts +1 -1
  261. package/src/activities/execute-deep-agent/environment.ts +1 -1
  262. package/src/activities/execute-deep-agent/setup.ts +3 -2
  263. package/src/activities/hydrate-workflow-execution.ts +1 -1
  264. package/src/config.ts +13 -0
  265. package/src/harness/__tests__/import-direction.test.ts +168 -0
  266. package/src/harness/__tests__/persist-chokepoint.test.ts +146 -0
  267. package/src/harness/__tests__/registry.test.ts +168 -0
  268. package/src/harness/__tests__/run-turn.test.ts +165 -0
  269. package/src/harness/__tests__/stop-controller.test.ts +49 -0
  270. package/src/harness/__tests__/turn-context.test.ts +178 -0
  271. package/src/harness/__tests__/usage-accumulator.test.ts +83 -0
  272. package/src/harness/capabilities.ts +92 -0
  273. package/src/harness/persist-chokepoint.ts +112 -0
  274. package/src/harness/registry.ts +197 -0
  275. package/src/harness/run-turn.ts +618 -0
  276. package/src/harness/stop-controller.ts +83 -0
  277. package/src/harness/terminal-table.ts +276 -0
  278. package/src/harness/turn-context.ts +1028 -0
  279. package/src/harness/types.ts +473 -0
  280. package/src/harness/usage-accumulator.ts +122 -0
  281. package/src/harness-adapters.ts +30 -0
  282. package/src/main.ts +1 -1
  283. package/src/runner-manager.ts +68 -61
  284. package/src/runner.ts +67 -78
  285. package/src/shared/__tests__/attachment-naming.test.ts +1 -1
  286. package/src/{activities/execute-cursor → shared}/__tests__/attachment-resolver.test.ts +6 -4
  287. package/src/{activities/execute-cursor → shared}/__tests__/cost-guard.test.ts +2 -1
  288. package/src/{activities/execute-cursor → shared}/__tests__/exact-apply.test.ts +3 -3
  289. package/src/{activities/execute-cursor → shared}/__tests__/extract-structured-output.test.ts +8 -8
  290. package/src/{activities/execute-cursor → shared}/__tests__/persist-decision.test.ts +4 -2
  291. package/src/{activities/execute-cursor → shared}/__tests__/skill-resolver.test.ts +1 -1
  292. package/src/shared/__tests__/subagent-rows.test.ts +34 -0
  293. package/src/shared/__tests__/worker-shutdown.test.ts +44 -39
  294. package/src/shared/approval-policy.ts +1 -1
  295. package/src/{activities/execute-cursor → shared}/attachment-resolver.ts +6 -6
  296. package/src/{activities/execute-cursor → shared}/blueprint-resolver.ts +7 -78
  297. package/src/shared/channel-attachment.ts +1 -1
  298. package/src/{activities/execute-cursor → shared}/cost-guard.ts +5 -1
  299. package/src/{activities/execute-cursor → shared}/env-resolver.ts +1 -1
  300. package/src/{activities/execute-cursor → shared}/exact-apply.ts +7 -7
  301. package/src/shared/execution-context.ts +45 -0
  302. package/src/{activities/execute-cursor → shared}/extract-structured-output.ts +10 -7
  303. package/src/shared/filereview/capture.ts +1 -1
  304. package/src/shared/heartbeat.ts +13 -33
  305. package/src/{activities/execute-cursor → shared}/persist-decision.ts +5 -2
  306. package/src/{activities/execute-cursor → shared}/skill-resolver.ts +20 -6
  307. package/src/shared/subagent-rows.ts +39 -0
  308. package/src/shared/worker-shutdown.ts +55 -25
  309. package/src/{activities/execute-cursor/__tests__/workspace-provision.test.ts → shared/workspace/__tests__/session-provision.test.ts} +25 -28
  310. package/src/shared/workspace/platform-dir.ts +1 -1
  311. package/src/{activities/execute-cursor/workspace-provision.ts → shared/workspace/session-provision.ts} +29 -16
  312. package/dist/activities/execute-cursor/attachment-resolver.js.map +0 -1
  313. package/dist/activities/execute-cursor/blueprint-resolver.js.map +0 -1
  314. package/dist/activities/execute-cursor/cost-guard.js.map +0 -1
  315. package/dist/activities/execute-cursor/env-resolver.js.map +0 -1
  316. package/dist/activities/execute-cursor/exact-apply.js.map +0 -1
  317. package/dist/activities/execute-cursor/extract-structured-output.js.map +0 -1
  318. package/dist/activities/execute-cursor/index.d.ts +0 -209
  319. package/dist/activities/execute-cursor/index.js +0 -2345
  320. package/dist/activities/execute-cursor/index.js.map +0 -1
  321. package/dist/activities/execute-cursor/persist-decision.js.map +0 -1
  322. package/dist/activities/execute-cursor/skill-resolver.js.map +0 -1
  323. package/dist/activities/execute-cursor/usage-accumulator.d.ts +0 -89
  324. package/dist/activities/execute-cursor/usage-accumulator.js +0 -121
  325. package/dist/activities/execute-cursor/usage-accumulator.js.map +0 -1
  326. package/dist/activities/execute-cursor/workspace-provision.d.ts +0 -42
  327. package/dist/activities/execute-cursor/workspace-provision.js.map +0 -1
  328. package/src/activities/execute-cursor/__tests__/usage-accumulator.test.ts +0 -164
  329. package/src/activities/execute-cursor/index.ts +0 -2876
  330. package/src/activities/execute-cursor/usage-accumulator.ts +0 -169
  331. /package/dist/{activities/execute-cursor → shared}/env-resolver.js +0 -0
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Harness capability flags — the facts about an engine the runtime branches
3
+ * on, declared once per adapter and read nowhere else.
4
+ *
5
+ * The runtime is written against the flags, not against harness names: a
6
+ * phase that must differ per engine asks "does this harness accept a system
7
+ * prompt?" rather than "is this Cursor?". That is what keeps a new harness a
8
+ * registry row and an SDK slice instead of a new branch in every phase.
9
+ * Every row of the matrix below is either a flag here or internal to one
10
+ * adapter; nothing in it needed a third kind of thing.
11
+ *
12
+ * The matrix the contract was designed against (2026-09; Claude and Codex are
13
+ * the surveyed SDKs, not built harnesses):
14
+ *
15
+ * | Capability | Native (LangGraph) | Cursor (`@cursor/sdk`) | Claude (`@anthropic-ai/claude-agent-sdk`) | Codex (`@openai/codex-sdk`) |
16
+ * |-------------------|-----------------------------|-----------------------------------------|-----------------------------------------------|------------------------------------------------|
17
+ * | `pausePrimitive` | `interrupt` (checkpoint) | `deny-and-retry` (hook, ledger, cancel) | `callback` (`canUseTool`, in-process) | `none` (approvalPolicy only) → capture-only |
18
+ * | `stateIdSource` | `deterministic` (thread id) | `engine-minted` (agent id) | either (caller-supplied or minted) | `engine-minted` (thread id) |
19
+ * | `systemPrompt` | yes | no (rides the first message) | yes | no (`AGENTS.md` or first message) |
20
+ * | `subAgents` | yes (compiled sub-graphs) | yes (`agents` option) | yes (`AgentDefinition`) | no |
21
+ * | `toolRestriction` | yes (tool list) | no (the hook enforces) | yes (`disallowedTools`, `tools`) | per-server config |
22
+ * | `visionProfile` | PNG, JPEG, WebP, GIF | PNG, JPEG (transport re-sniffs) | (surveyed later) | (surveyed later) |
23
+ * | `fileReview` | `deep-agent`, no excludes | `cursor`, `.cursor/hooks.json` excluded | (surveyed later) | (surveyed later) |
24
+ *
25
+ * Adapter-internal, deliberately NOT flags: how MCP servers are bound, how
26
+ * metering is routed, how the cost cap is applied inside the engine, how a
27
+ * run is cancelled. Those differ per engine but the runtime never needs to
28
+ * know.
29
+ *
30
+ * Two flags matter to the contract kit directly: `pausePrimitive` (the kit
31
+ * proves the two real primitives are indistinguishable above the contract
32
+ * line — both end a turn `awaiting_approval` and both take the decisions on
33
+ * reinvocation) and `stateIdSource` (an `engine-minted` adapter must bind its
34
+ * id before its first persist; a `deterministic` one must never bind).
35
+ */
36
+ import type { VisionProfile } from "../shared/attachment-vision.js";
37
+ /**
38
+ * How the engine can be made to stop before a gated side effect.
39
+ *
40
+ * - `interrupt`: the engine checkpoints and stops at the gate (LangGraph
41
+ * `interrupt`); the adapter resumes it with the decisions.
42
+ * - `deny-and-retry`: an out-of-process hook denies the tool, the adapter
43
+ * records the denial, cancels the run, and re-runs with grants on the next
44
+ * invocation.
45
+ * - `callback`: an in-process callback decides per tool; the runtime still
46
+ * returns `awaiting_approval` and reinvokes, so the adapter answers the
47
+ * callback with "deny, stop" and resumes with the decisions.
48
+ * - `none`: the engine offers no gate; the runtime confines it to
49
+ * capture-only work (a read-only sandbox) and gated actions never reach
50
+ * the engine.
51
+ */
52
+ export type PausePrimitive = "interrupt" | "deny-and-retry" | "callback" | "none";
53
+ /**
54
+ * Who mints the engine's state id. `deterministic`: the runtime derives it
55
+ * from the session before the first turn (`EnsureThread`), so it is known
56
+ * before any engine exists. `engine-minted`: the engine issues it on first
57
+ * use and the adapter must hand it to the runtime at once
58
+ * (`TurnSink.bindHarnessState`) so a crash mid-turn still resumes.
59
+ */
60
+ export type StateIdSource = "deterministic" | "engine-minted";
61
+ /**
62
+ * The two facts the runtime's file-review reconcile needs from the harness
63
+ * and cannot know: the id the projection reads from the BASELINE payload
64
+ * (`shared/filereview/capture.ts` `applyCaptureDecisions`), and the
65
+ * workspace-relative paths the harness writes into the repo that a turn's
66
+ * diff must never show (Cursor's transient `.cursor/hooks.json`). Declared
67
+ * once per adapter, read by `turn-context.ts` (ruled Q-M2-6 as an argument,
68
+ * homed here at M3).
69
+ */
70
+ export interface FileReviewIdentity {
71
+ readonly harnessId: string;
72
+ readonly excludePaths: readonly string[];
73
+ }
74
+ export interface HarnessCapabilities {
75
+ readonly pausePrimitive: PausePrimitive;
76
+ readonly stateIdSource: StateIdSource;
77
+ /** The engine accepts a system prompt; otherwise instructions ride the first user message. */
78
+ readonly systemPrompt: boolean;
79
+ /** The engine runs delegated sub-agents from a definition map. */
80
+ readonly subAgents: boolean;
81
+ /** The engine can hide or deny tools by name; otherwise the gate enforces `enabledTools`. */
82
+ readonly toolRestriction: boolean;
83
+ /** Which image types the engine can display inline; the runtime degrades the rest before the turn. */
84
+ readonly visionProfile: VisionProfile;
85
+ /** How the harness's captured file changes are identified and what its own repo writes are excluded from a diff. */
86
+ readonly fileReview: FileReviewIdentity;
87
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Harness capability flags — the facts about an engine the runtime branches
3
+ * on, declared once per adapter and read nowhere else.
4
+ *
5
+ * The runtime is written against the flags, not against harness names: a
6
+ * phase that must differ per engine asks "does this harness accept a system
7
+ * prompt?" rather than "is this Cursor?". That is what keeps a new harness a
8
+ * registry row and an SDK slice instead of a new branch in every phase.
9
+ * Every row of the matrix below is either a flag here or internal to one
10
+ * adapter; nothing in it needed a third kind of thing.
11
+ *
12
+ * The matrix the contract was designed against (2026-09; Claude and Codex are
13
+ * the surveyed SDKs, not built harnesses):
14
+ *
15
+ * | Capability | Native (LangGraph) | Cursor (`@cursor/sdk`) | Claude (`@anthropic-ai/claude-agent-sdk`) | Codex (`@openai/codex-sdk`) |
16
+ * |-------------------|-----------------------------|-----------------------------------------|-----------------------------------------------|------------------------------------------------|
17
+ * | `pausePrimitive` | `interrupt` (checkpoint) | `deny-and-retry` (hook, ledger, cancel) | `callback` (`canUseTool`, in-process) | `none` (approvalPolicy only) → capture-only |
18
+ * | `stateIdSource` | `deterministic` (thread id) | `engine-minted` (agent id) | either (caller-supplied or minted) | `engine-minted` (thread id) |
19
+ * | `systemPrompt` | yes | no (rides the first message) | yes | no (`AGENTS.md` or first message) |
20
+ * | `subAgents` | yes (compiled sub-graphs) | yes (`agents` option) | yes (`AgentDefinition`) | no |
21
+ * | `toolRestriction` | yes (tool list) | no (the hook enforces) | yes (`disallowedTools`, `tools`) | per-server config |
22
+ * | `visionProfile` | PNG, JPEG, WebP, GIF | PNG, JPEG (transport re-sniffs) | (surveyed later) | (surveyed later) |
23
+ * | `fileReview` | `deep-agent`, no excludes | `cursor`, `.cursor/hooks.json` excluded | (surveyed later) | (surveyed later) |
24
+ *
25
+ * Adapter-internal, deliberately NOT flags: how MCP servers are bound, how
26
+ * metering is routed, how the cost cap is applied inside the engine, how a
27
+ * run is cancelled. Those differ per engine but the runtime never needs to
28
+ * know.
29
+ *
30
+ * Two flags matter to the contract kit directly: `pausePrimitive` (the kit
31
+ * proves the two real primitives are indistinguishable above the contract
32
+ * line — both end a turn `awaiting_approval` and both take the decisions on
33
+ * reinvocation) and `stateIdSource` (an `engine-minted` adapter must bind its
34
+ * id before its first persist; a `deterministic` one must never bind).
35
+ */
36
+ export {};
37
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/harness/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The turn runtime's single persist chokepoint: every write of the
3
+ * execution status during a turn — the adapter's streaming requests, the
4
+ * runtime's own terminal writes — goes through here and nowhere else, so
5
+ * the guards that must never be skipped cannot be skipped by a call site
6
+ * that forgot them.
7
+ *
8
+ * What one write does, in order:
9
+ * 1. The never-persist-secret backstop (DD-26 #2): content is withheld from
10
+ * any built-in write row targeting a secret-like path, top-level and
11
+ * sub-agent. The single airtight choke point for a deny-gate harness and
12
+ * the only guarantee under `auto_approve_all`. Idempotent.
13
+ * 2. `streaming_usage` is refreshed from the accumulator when it has turns,
14
+ * so the summary the UI shows is the one the write carries.
15
+ * 3. `persistStatus` (`shared/status.ts`): tool-output offload, the
16
+ * aggregate size cap, transient retry, oversize recovery. Never rejects.
17
+ * 4. A Temporal heartbeat, so a long streaming turn's liveness is proven by
18
+ * the writes it makes (Q-S2-10).
19
+ * 5. The control plane's answer: STOP becomes the runtime's platform-stop
20
+ * cause on the stop controller, which aborts the adapter's signal.
21
+ *
22
+ * Single-flight with coalescing: an adapter's `requestPersist()` while a
23
+ * write is in flight does not start a second concurrent write (two writes of
24
+ * one status racing on the wire is the drift the chokepoint exists to
25
+ * prevent); it schedules ONE follow-up write after the current one lands,
26
+ * and resolves when that follow-up has. The promise it returns therefore
27
+ * always means "the state as of my request is on the control plane", which
28
+ * is what lets the Cursor loop await it and see a STOP before it pulls the
29
+ * next event, exactly as its own inline persist did (Q-M3-2).
30
+ *
31
+ * The runtime's terminal writes use the same path (`write()`), so the
32
+ * secret backstop and the usage summary ride the final status too, as they
33
+ * did when the orchestrator's `persist` closure was the one place to write.
34
+ */
35
+ import type { AgentExecutionStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
36
+ import type { StigmerClient } from "../client/stigmer-client.js";
37
+ import type { ToolOutputOffloadContext } from "../shared/status-offload.js";
38
+ import type { UsageAccumulator } from "./usage-accumulator.js";
39
+ export interface PersistChokepointDeps {
40
+ readonly client: StigmerClient;
41
+ readonly executionId: string;
42
+ readonly status: AgentExecutionStatus;
43
+ /** Present when artifact storage resolved; enables tool-output offload on every write. */
44
+ readonly offload: ToolOutputOffloadContext | undefined;
45
+ /**
46
+ * The accumulator, read at WRITE time: it exists only once the runtime has
47
+ * the turn's model preferences, after resolution, so it arrives as a thunk
48
+ * and is `undefined` for a write made before then (no usage yet anyway).
49
+ */
50
+ readonly usage: () => UsageAccumulator | undefined;
51
+ /** The Temporal heartbeat, pulsed after each write. */
52
+ readonly heartbeat: () => void;
53
+ /** The control plane answered STOP to this write. */
54
+ readonly onPlatformStop: () => void;
55
+ }
56
+ export declare class PersistChokepoint {
57
+ private readonly deps;
58
+ private inFlight;
59
+ private followUp;
60
+ constructor(deps: PersistChokepointDeps);
61
+ /**
62
+ * The adapter's `requestPersist()`: a write now, or one follow-up write
63
+ * after the in-flight one. Resolves when the state as of this call has
64
+ * been written. Never rejects.
65
+ */
66
+ request(): Promise<void>;
67
+ /**
68
+ * One write, now. The runtime's own writes (a settlement, a terminal
69
+ * status) call this directly: they run when no adapter write can be in
70
+ * flight (before `runTurn` or after it settled), so they need no
71
+ * coalescing, and they must not be deferred behind one.
72
+ */
73
+ write(): Promise<void>;
74
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The turn runtime's single persist chokepoint: every write of the
3
+ * execution status during a turn — the adapter's streaming requests, the
4
+ * runtime's own terminal writes — goes through here and nowhere else, so
5
+ * the guards that must never be skipped cannot be skipped by a call site
6
+ * that forgot them.
7
+ *
8
+ * What one write does, in order:
9
+ * 1. The never-persist-secret backstop (DD-26 #2): content is withheld from
10
+ * any built-in write row targeting a secret-like path, top-level and
11
+ * sub-agent. The single airtight choke point for a deny-gate harness and
12
+ * the only guarantee under `auto_approve_all`. Idempotent.
13
+ * 2. `streaming_usage` is refreshed from the accumulator when it has turns,
14
+ * so the summary the UI shows is the one the write carries.
15
+ * 3. `persistStatus` (`shared/status.ts`): tool-output offload, the
16
+ * aggregate size cap, transient retry, oversize recovery. Never rejects.
17
+ * 4. A Temporal heartbeat, so a long streaming turn's liveness is proven by
18
+ * the writes it makes (Q-S2-10).
19
+ * 5. The control plane's answer: STOP becomes the runtime's platform-stop
20
+ * cause on the stop controller, which aborts the adapter's signal.
21
+ *
22
+ * Single-flight with coalescing: an adapter's `requestPersist()` while a
23
+ * write is in flight does not start a second concurrent write (two writes of
24
+ * one status racing on the wire is the drift the chokepoint exists to
25
+ * prevent); it schedules ONE follow-up write after the current one lands,
26
+ * and resolves when that follow-up has. The promise it returns therefore
27
+ * always means "the state as of my request is on the control plane", which
28
+ * is what lets the Cursor loop await it and see a STOP before it pulls the
29
+ * next event, exactly as its own inline persist did (Q-M3-2).
30
+ *
31
+ * The runtime's terminal writes use the same path (`write()`), so the
32
+ * secret backstop and the usage summary ride the final status too, as they
33
+ * did when the orchestrator's `persist` closure was the one place to write.
34
+ */
35
+ import { create } from "@bufbuild/protobuf";
36
+ import { ExecutionControlSignal } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
37
+ import { StreamingUsageSummarySchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/usage_pb";
38
+ import { persistStatus } from "../shared/status.js";
39
+ import { withholdSecretContentFromMessages } from "../shared/tool-row.js";
40
+ export class PersistChokepoint {
41
+ deps;
42
+ inFlight;
43
+ followUp;
44
+ constructor(deps) {
45
+ this.deps = deps;
46
+ }
47
+ /**
48
+ * The adapter's `requestPersist()`: a write now, or one follow-up write
49
+ * after the in-flight one. Resolves when the state as of this call has
50
+ * been written. Never rejects.
51
+ */
52
+ request() {
53
+ if (this.inFlight === undefined) {
54
+ const write = this.write().finally(() => {
55
+ this.inFlight = undefined;
56
+ });
57
+ this.inFlight = write;
58
+ return write;
59
+ }
60
+ if (this.followUp === undefined) {
61
+ this.followUp = this.inFlight.then(() => {
62
+ this.followUp = undefined;
63
+ return this.request();
64
+ });
65
+ }
66
+ return this.followUp;
67
+ }
68
+ /**
69
+ * One write, now. The runtime's own writes (a settlement, a terminal
70
+ * status) call this directly: they run when no adapter write can be in
71
+ * flight (before `runTurn` or after it settled), so they need no
72
+ * coalescing, and they must not be deferred behind one.
73
+ */
74
+ async write() {
75
+ const { client, executionId, status, offload, heartbeat } = this.deps;
76
+ withholdSecretContentFromMessages(status.messages, status.subAgentExecutions);
77
+ const usage = this.deps.usage();
78
+ if (usage?.hasTurns) {
79
+ status.streamingUsage = create(StreamingUsageSummarySchema, usage.snapshot());
80
+ }
81
+ const signal = await persistStatus(client, executionId, status, { offload });
82
+ heartbeat();
83
+ if (signal === ExecutionControlSignal.STOP) {
84
+ this.deps.onPlatformStop();
85
+ }
86
+ }
87
+ }
88
+ //# sourceMappingURL=persist-chokepoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persist-chokepoint.js","sourceRoot":"","sources":["../../src/harness/persist-chokepoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,8DAA8D,CAAC;AACtG,OAAO,EAAE,2BAA2B,EAAE,MAAM,+DAA+D,CAAC;AAG5G,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAqB1E,MAAM,OAAO,iBAAiB;IAIC;IAHrB,QAAQ,CAA4B;IACpC,QAAQ,CAA4B;IAE5C,YAA6B,IAA2B;QAA3B,SAAI,GAAJ,IAAI,CAAuB;IAAG,CAAC;IAE5D;;;;OAIG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;gBACtC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;YAC5B,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;gBACtC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;gBAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;YACxB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;QACtE,iCAAiC,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,KAAK,EAAE,QAAQ,EAAE,CAAC;YACpB,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,2BAA2B,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7E,SAAS,EAAE,CAAC;QACZ,IAAI,MAAM,KAAK,sBAAsB,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The harness registry — the lifecycle fan-out over the adapters a worker
3
+ * runs, and the byte-pinned binding from harness to Temporal activity name.
4
+ *
5
+ * Plain functions over an `adapters` argument, no module state and no DI
6
+ * (the composition roots are staged plain functions; a missing adapter is a
7
+ * compile error or a loud boot throw, never a silent no-op). ORDER IS
8
+ * LOAD-BEARING: `bootHarnesses` runs adapters in declaration order because
9
+ * the Cursor harness's interceptors must patch `node:http2` before anything
10
+ * dials the control plane, and `shutdownHarnesses` runs them in reverse so
11
+ * what was set up last is torn down first.
12
+ *
13
+ * Error posture, ruled at the entry's gate (Q-S1-10):
14
+ * - Boot validates the whole table BEFORE booting anything (a duplicate name
15
+ * is a configuration defect, and a half-booted worker is the worst state to
16
+ * discover it in), then fails fast at the first adapter that rejects. A
17
+ * worker that cannot boot a harness must not start.
18
+ * - Shutdown and session release CONTINUE past a failing adapter and throw
19
+ * one `AggregateError` at the end naming each failure, so one bad teardown
20
+ * never leaks the others' resources.
21
+ *
22
+ * `createHarnessActivities` binds each row to its Temporal activity over the
23
+ * turn runtime (`run-turn.ts`). The table of real rows is NOT here: it lives
24
+ * at the source root (`src/harness-adapters.ts`), because a row imports its
25
+ * adapter from `activities/` and nothing under `src/harness/` may
26
+ * (`__tests__/import-direction.test.ts`; Q-M3-1). The registry knows rows,
27
+ * never which adapters exist.
28
+ *
29
+ * `HarnessName` lives here and not in `types.ts` on purpose: the wire
30
+ * vocabulary is the registry's concern. An adapter never declares the
31
+ * activity it is bound to (its `name` is a diagnostic identity); the registry
32
+ * row does.
33
+ *
34
+ * THIS MODULE'S STATIC GRAPH MUST STAY CONNECT-FREE. Both composition roots
35
+ * import it BEFORE they boot the harnesses, and the Cursor adapter's boot
36
+ * patches `node:http2` (its HTTP/2 auth interceptor); a static import of
37
+ * anything that loads `@connectrpc/connect-node` here would snapshot the
38
+ * `node:http2` ESM facade to the unpatched `connect` before that boot ran,
39
+ * and every BiDi stream would silently 401. So `StigmerClient` is loaded
40
+ * with a dynamic import inside `createHarnessActivities`, the runner's
41
+ * dynamic-import-for-order convention (`bootstrap.ts` documents the same
42
+ * omission for the same reason). `__tests__/harness-boot-order.test.ts`
43
+ * boots a fresh process through this module and fails if the facade froze.
44
+ */
45
+ import type { Config } from "../config.js";
46
+ import { type ExecuteActivityInput } from "../shared/activity-input.js";
47
+ import type { HarnessAdapter } from "./types.js";
48
+ /** The harnesses the control plane can dispatch to, as the registry knows them. */
49
+ export type HarnessName = "cursor" | "deep-agent";
50
+ /**
51
+ * Byte-pinned Temporal activity names, one per harness. The server side of
52
+ * the pin is `stigmer-server/src/temporal/agentexecution/names.ts`
53
+ * (`EXECUTE_CURSOR_ACTIVITY_NAME`, `EXECUTE_DEEP_AGENT_ACTIVITY_NAME`); the
54
+ * two must stay byte-identical or the workflow schedules an activity no
55
+ * worker registers. Never "cleaned up".
56
+ */
57
+ export declare const HARNESS_ACTIVITY_NAMES: {
58
+ readonly cursor: "ExecuteCursor";
59
+ readonly "deep-agent": "ExecuteDeepAgent";
60
+ };
61
+ export type HarnessActivityName = (typeof HARNESS_ACTIVITY_NAMES)[HarnessName];
62
+ /** One harness the worker serves: the wire name it answers to and the adapter that runs its turns. */
63
+ export interface HarnessRow {
64
+ readonly harness: HarnessName;
65
+ readonly adapter: HarnessAdapter;
66
+ }
67
+ /**
68
+ * The legacy positional activity signature, kept as the wire shape both
69
+ * control planes send until they both send the typed object
70
+ * (`shared/activity-input.ts`). Every harness's activity has it.
71
+ */
72
+ export type HarnessActivity = (arg0: ExecuteActivityInput | string, arg1?: string) => Promise<unknown>;
73
+ /** The adapters of a row list, for the lifecycle functions below. */
74
+ export declare function adaptersOf(rows: readonly HarnessRow[]): HarnessAdapter[];
75
+ /**
76
+ * One Temporal activity per row, under the row's byte-pinned name, over ONE
77
+ * `StigmerClient` for all of them (each harness used to build its own). The
78
+ * activity normalizes the wire input, brackets the turn with the idle
79
+ * watchdog, and hands the turn runtime the adapter. The roots spread the
80
+ * result into the worker's activity map beside the activities the runtime
81
+ * does not own.
82
+ *
83
+ * Async because the client is loaded here, not at the top of the module (see
84
+ * the header): the roots call this after the harnesses have booted, when
85
+ * connect-node may load.
86
+ */
87
+ export declare function createHarnessActivities(rows: readonly HarnessRow[], config: Config): Promise<Partial<Record<HarnessActivityName, HarnessActivity>>>;
88
+ /**
89
+ * Boot every adapter in declaration order, one at a time, awaiting each. The
90
+ * table is validated first; the first rejection stops the boot and propagates
91
+ * (adapters after it are never booted; adapters before it stay booted for the
92
+ * caller's shutdown path to release).
93
+ */
94
+ export declare function bootHarnesses(adapters: readonly HarnessAdapter[], config: Config): Promise<void>;
95
+ /**
96
+ * Shut every adapter down in reverse declaration order, continuing past
97
+ * failures. Rejects with one `AggregateError` carrying every failure once all
98
+ * adapters have been given their chance.
99
+ */
100
+ export declare function shutdownHarnesses(adapters: readonly HarnessAdapter[]): Promise<void>;
101
+ /**
102
+ * Tell every adapter the session is done on this host, in declaration order,
103
+ * continuing past failures. An adapter that parks nothing per session
104
+ * resolves as a no-op; the registry does not know which do.
105
+ */
106
+ export declare function releaseHarnessSession(adapters: readonly HarnessAdapter[], sessionId: string): Promise<void>;
@@ -0,0 +1,168 @@
1
+ /**
2
+ * The harness registry — the lifecycle fan-out over the adapters a worker
3
+ * runs, and the byte-pinned binding from harness to Temporal activity name.
4
+ *
5
+ * Plain functions over an `adapters` argument, no module state and no DI
6
+ * (the composition roots are staged plain functions; a missing adapter is a
7
+ * compile error or a loud boot throw, never a silent no-op). ORDER IS
8
+ * LOAD-BEARING: `bootHarnesses` runs adapters in declaration order because
9
+ * the Cursor harness's interceptors must patch `node:http2` before anything
10
+ * dials the control plane, and `shutdownHarnesses` runs them in reverse so
11
+ * what was set up last is torn down first.
12
+ *
13
+ * Error posture, ruled at the entry's gate (Q-S1-10):
14
+ * - Boot validates the whole table BEFORE booting anything (a duplicate name
15
+ * is a configuration defect, and a half-booted worker is the worst state to
16
+ * discover it in), then fails fast at the first adapter that rejects. A
17
+ * worker that cannot boot a harness must not start.
18
+ * - Shutdown and session release CONTINUE past a failing adapter and throw
19
+ * one `AggregateError` at the end naming each failure, so one bad teardown
20
+ * never leaks the others' resources.
21
+ *
22
+ * `createHarnessActivities` binds each row to its Temporal activity over the
23
+ * turn runtime (`run-turn.ts`). The table of real rows is NOT here: it lives
24
+ * at the source root (`src/harness-adapters.ts`), because a row imports its
25
+ * adapter from `activities/` and nothing under `src/harness/` may
26
+ * (`__tests__/import-direction.test.ts`; Q-M3-1). The registry knows rows,
27
+ * never which adapters exist.
28
+ *
29
+ * `HarnessName` lives here and not in `types.ts` on purpose: the wire
30
+ * vocabulary is the registry's concern. An adapter never declares the
31
+ * activity it is bound to (its `name` is a diagnostic identity); the registry
32
+ * row does.
33
+ *
34
+ * THIS MODULE'S STATIC GRAPH MUST STAY CONNECT-FREE. Both composition roots
35
+ * import it BEFORE they boot the harnesses, and the Cursor adapter's boot
36
+ * patches `node:http2` (its HTTP/2 auth interceptor); a static import of
37
+ * anything that loads `@connectrpc/connect-node` here would snapshot the
38
+ * `node:http2` ESM facade to the unpatched `connect` before that boot ran,
39
+ * and every BiDi stream would silently 401. So `StigmerClient` is loaded
40
+ * with a dynamic import inside `createHarnessActivities`, the runner's
41
+ * dynamic-import-for-order convention (`bootstrap.ts` documents the same
42
+ * omission for the same reason). `__tests__/harness-boot-order.test.ts`
43
+ * boots a fresh process through this module and fails if the facade froze.
44
+ */
45
+ import { activityFinished, activityStarted } from "../idle-watchdog.js";
46
+ import { normalizeActivityInput } from "../shared/activity-input.js";
47
+ import { runTurnActivity } from "./run-turn.js";
48
+ /**
49
+ * Byte-pinned Temporal activity names, one per harness. The server side of
50
+ * the pin is `stigmer-server/src/temporal/agentexecution/names.ts`
51
+ * (`EXECUTE_CURSOR_ACTIVITY_NAME`, `EXECUTE_DEEP_AGENT_ACTIVITY_NAME`); the
52
+ * two must stay byte-identical or the workflow schedules an activity no
53
+ * worker registers. Never "cleaned up".
54
+ */
55
+ export const HARNESS_ACTIVITY_NAMES = {
56
+ cursor: "ExecuteCursor",
57
+ "deep-agent": "ExecuteDeepAgent",
58
+ };
59
+ /** The adapters of a row list, for the lifecycle functions below. */
60
+ export function adaptersOf(rows) {
61
+ return rows.map((row) => row.adapter);
62
+ }
63
+ /**
64
+ * One Temporal activity per row, under the row's byte-pinned name, over ONE
65
+ * `StigmerClient` for all of them (each harness used to build its own). The
66
+ * activity normalizes the wire input, brackets the turn with the idle
67
+ * watchdog, and hands the turn runtime the adapter. The roots spread the
68
+ * result into the worker's activity map beside the activities the runtime
69
+ * does not own.
70
+ *
71
+ * Async because the client is loaded here, not at the top of the module (see
72
+ * the header): the roots call this after the harnesses have booted, when
73
+ * connect-node may load.
74
+ */
75
+ export async function createHarnessActivities(rows, config) {
76
+ const { StigmerClient } = await import("../client/stigmer-client.js");
77
+ const client = new StigmerClient({
78
+ endpoint: config.stigmerBackendEndpoint,
79
+ token: config.stigmerToken,
80
+ tokenRef: config.stigmerTokenRef,
81
+ runnerTokenRef: config.stigmerRunnerTokenRef,
82
+ });
83
+ const activities = {};
84
+ for (const row of rows) {
85
+ const activityName = HARNESS_ACTIVITY_NAMES[row.harness];
86
+ const deps = { adapter: row.adapter, activityName, client, config };
87
+ activities[activityName] = async (arg0, arg1) => {
88
+ const input = normalizeActivityInput(arg0, arg1);
89
+ activityStarted();
90
+ try {
91
+ return await runTurnActivity(deps, input);
92
+ }
93
+ finally {
94
+ activityFinished();
95
+ }
96
+ };
97
+ }
98
+ return activities;
99
+ }
100
+ /**
101
+ * Refuse a table two of whose adapters share a name. Names are the registry's
102
+ * identity for diagnostics and for this check; a duplicate means two adapters
103
+ * would be indistinguishable in every log line and kit message.
104
+ */
105
+ function assertUniqueNames(adapters) {
106
+ const seen = new Set();
107
+ for (const adapter of adapters) {
108
+ if (seen.has(adapter.name)) {
109
+ throw new Error(`harness registry: duplicate adapter name '${adapter.name}'; every adapter must have a unique name`);
110
+ }
111
+ seen.add(adapter.name);
112
+ }
113
+ }
114
+ /**
115
+ * Boot every adapter in declaration order, one at a time, awaiting each. The
116
+ * table is validated first; the first rejection stops the boot and propagates
117
+ * (adapters after it are never booted; adapters before it stay booted for the
118
+ * caller's shutdown path to release).
119
+ */
120
+ export async function bootHarnesses(adapters, config) {
121
+ assertUniqueNames(adapters);
122
+ for (const adapter of adapters) {
123
+ await adapter.boot(config);
124
+ }
125
+ }
126
+ /**
127
+ * Shut every adapter down in reverse declaration order, continuing past
128
+ * failures. Rejects with one `AggregateError` carrying every failure once all
129
+ * adapters have been given their chance.
130
+ */
131
+ export async function shutdownHarnesses(adapters) {
132
+ const failures = [];
133
+ for (const adapter of [...adapters].reverse()) {
134
+ try {
135
+ await adapter.shutdown();
136
+ }
137
+ catch (err) {
138
+ failures.push(describeFailure(adapter, "shutdown", err));
139
+ }
140
+ }
141
+ throwIfAny(failures, "harness registry: shutdown failed for one or more adapters");
142
+ }
143
+ /**
144
+ * Tell every adapter the session is done on this host, in declaration order,
145
+ * continuing past failures. An adapter that parks nothing per session
146
+ * resolves as a no-op; the registry does not know which do.
147
+ */
148
+ export async function releaseHarnessSession(adapters, sessionId) {
149
+ const failures = [];
150
+ for (const adapter of adapters) {
151
+ try {
152
+ await adapter.releaseSession(sessionId);
153
+ }
154
+ catch (err) {
155
+ failures.push(describeFailure(adapter, `releaseSession('${sessionId}')`, err));
156
+ }
157
+ }
158
+ throwIfAny(failures, `harness registry: releaseSession('${sessionId}') failed for one or more adapters`);
159
+ }
160
+ function describeFailure(adapter, call, err) {
161
+ const cause = err instanceof Error ? err : new Error(String(err));
162
+ return new Error(`${adapter.name}: ${call} rejected: ${cause.message}`, { cause });
163
+ }
164
+ function throwIfAny(failures, message) {
165
+ if (failures.length > 0)
166
+ throw new AggregateError(failures, `${message}: ${failures.map((f) => f.message).join("; ")}`);
167
+ }
168
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/harness/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The turn runtime — one agent turn as a Temporal activity, written once for
3
+ * every harness, with the engine behind the adapter contract (`types.ts`).
4
+ *
5
+ * What runs here and nowhere else: the activity's identity and its
6
+ * execution-scoped context; the status and the single persist chokepoint;
7
+ * the periodic heartbeat; the stop controller and its four producers (the
8
+ * stall watchdog, the cost cap, the platform STOP, Temporal's cancellation);
9
+ * the resolution phases (`turn-context.ts`) composed into the `TurnInput`;
10
+ * the sink the adapter is handed; the terminal table (`terminal-table.ts`)
11
+ * with its throw-vs-return rule, applied by `settleWith`, the one writer of
12
+ * a terminal; the completion epilogue (final text,
13
+ * structured output, plan artifact, write-back); the finally that releases
14
+ * the workspace lock last. The adapter owns its SDK slice inside `runTurn`
15
+ * and its own teardown inside its own `finally`, which runs BEFORE this
16
+ * module's (the gate is torn down before the lock is released, as it always
17
+ * was).
18
+ *
19
+ * Shape: one activity per registry row (`createHarnessActivities`), each a
20
+ * closure over the adapter, the activity's byte-pinned name and one shared
21
+ * `StigmerClient`; `runTurnActivity` is the body. Every `console` line here
22
+ * names the activity (`ExecuteCursor started: …`) so the log reads as it did
23
+ * before the extraction, and never a harness literal — the harness is a
24
+ * registry row, not a branch.
25
+ *
26
+ * Extracted from `activities/execute-cursor/index.ts` `executeCursorInner`
27
+ * (S2 M3; the milestone log in stigmer-cloud
28
+ * `_projects/2026-09/20260911.03.sp.turn-runtime-extraction/` has every
29
+ * ruling). Its twelve resolution phases came out at M2; what came out here is
30
+ * everything between them and after the engine: the seventeen hermetic
31
+ * goldens under `execute-cursor/__tests__/hermetic/` pin the result byte
32
+ * for byte, and `__tests__/run-turn.test.ts` proves the table against the
33
+ * scripted fake without any engine at all.
34
+ */
35
+ import type { Config } from "../config.js";
36
+ import type { StigmerClient } from "../client/stigmer-client.js";
37
+ import type { NormalizedActivityInput } from "../shared/activity-input.js";
38
+ import type { HarnessAdapter } from "./types.js";
39
+ /** What every activity of the registry shares: the adapter it drives, its wire name, and the one client. */
40
+ export interface TurnRuntimeDeps {
41
+ readonly adapter: HarnessAdapter;
42
+ readonly activityName: string;
43
+ readonly client: StigmerClient;
44
+ readonly config: Config;
45
+ }
46
+ /**
47
+ * Run one turn: the activity body behind every harness's registry row. Sets
48
+ * the execution-scoped context for the WHOLE activity (the interceptors stamp
49
+ * every proxy-bound request from it, and much of that traffic is the
50
+ * runtime's own: offload, attachments, the epilogue's extraction) and runs
51
+ * the turn inside it.
52
+ */
53
+ export declare function runTurnActivity(deps: TurnRuntimeDeps, input: NormalizedActivityInput): Promise<unknown>;