@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,53 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "Let me look at the recent changes.",
6
+ "timestamp": "2026-01-01T00:00:02.000Z"
7
+ },
8
+ {
9
+ "type": "MESSAGE_AI",
10
+ "content": "Two files changed since yesterday: notes.md and README.md.",
11
+ "timestamp": "2026-01-01T00:00:06.000Z"
12
+ }
13
+ ],
14
+ "phase": "EXECUTION_COMPLETED",
15
+ "startedAt": "2026-01-01T00:00:00.000Z",
16
+ "completedAt": "2026-01-01T00:00:08.000Z",
17
+ "streamingUsage": {
18
+ "inputTokens": "2800",
19
+ "outputTokens": "55",
20
+ "totalTokens": "2855",
21
+ "turnCount": 1,
22
+ "estimatedCostUsd": 0.00302,
23
+ "model": "composer-2.5",
24
+ "observedAt": "2026-01-01T00:00:07.000Z",
25
+ "requestedServiceTier": "SERVICE_TIER_STANDARD",
26
+ "requestedModelParams": "[{\"id\":\"fast\",\"value\":\"false\"},{\"id\":\"thinking\",\"value\":\"false\"}]",
27
+ "requestedThinkingMode": "THINKING_MODE_DISABLED"
28
+ },
29
+ "fileReviewEventStream": {
30
+ "executionId": "aex_hermetic_0001",
31
+ "events": [
32
+ {
33
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
34
+ "changeSetId": "aex_hermetic_0001:0",
35
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
36
+ "timestamp": "2026-01-01T00:00:00.000Z",
37
+ "actor": "runner",
38
+ "baselineCaptured": {
39
+ "changeSetId": "aex_hermetic_0001:0",
40
+ "turnId": "aex_hermetic_0001:0",
41
+ "harnessId": "cursor",
42
+ "baselineSnapshot": {
43
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
44
+ }
45
+ }
46
+ }
47
+ ]
48
+ },
49
+ "fileChangeProgress": {
50
+ "changeSetId": "aex_hermetic_0001:0",
51
+ "capturedAt": "2026-01-01T00:00:01.000Z"
52
+ }
53
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "There are three open pull requests: #12, #15 and #18.",
6
+ "timestamp": "2026-01-01T00:00:05.000Z"
7
+ }
8
+ ],
9
+ "phase": "EXECUTION_COMPLETED",
10
+ "startedAt": "2026-01-01T00:00:00.000Z",
11
+ "completedAt": "2026-01-01T00:00:07.000Z",
12
+ "streamingUsage": {
13
+ "inputTokens": "2200",
14
+ "outputTokens": "30",
15
+ "totalTokens": "2230",
16
+ "turnCount": 1,
17
+ "estimatedCostUsd": 0.00232,
18
+ "model": "composer-2.5",
19
+ "observedAt": "2026-01-01T00:00:06.000Z",
20
+ "requestedServiceTier": "SERVICE_TIER_STANDARD",
21
+ "requestedModelParams": "[{\"id\":\"fast\",\"value\":\"false\"},{\"id\":\"thinking\",\"value\":\"false\"}]",
22
+ "requestedThinkingMode": "THINKING_MODE_DISABLED"
23
+ },
24
+ "fileReviewEventStream": {
25
+ "executionId": "aex_hermetic_0001",
26
+ "events": [
27
+ {
28
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
29
+ "changeSetId": "aex_hermetic_0001:0",
30
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
31
+ "timestamp": "2026-01-01T00:00:00.000Z",
32
+ "actor": "runner",
33
+ "baselineCaptured": {
34
+ "changeSetId": "aex_hermetic_0001:0",
35
+ "turnId": "aex_hermetic_0001:0",
36
+ "harnessId": "cursor",
37
+ "baselineSnapshot": {
38
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
39
+ }
40
+ }
41
+ }
42
+ ]
43
+ },
44
+ "fileChangeProgress": {
45
+ "changeSetId": "aex_hermetic_0001:0",
46
+ "capturedAt": "2026-01-01T00:00:01.000Z"
47
+ }
48
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_SYSTEM",
5
+ "content": "Internal system error occurred. Please contact support if this issue persists.",
6
+ "timestamp": "2026-01-01T00:00:00.000Z"
7
+ },
8
+ {
9
+ "type": "MESSAGE_SYSTEM",
10
+ "content": "Error details: [Error] hermetic fault injected at getAgent",
11
+ "timestamp": "2026-01-01T00:00:00.000Z"
12
+ }
13
+ ],
14
+ "phase": "EXECUTION_FAILED",
15
+ "error": "Execution failed: [Error] hermetic fault injected at getAgent",
16
+ "startedAt": "2026-01-01T00:00:00.000Z",
17
+ "completedAt": "2026-01-01T00:00:00.000Z"
18
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "Looking at the pull requests.",
6
+ "timestamp": "2026-01-01T00:00:02.000Z"
7
+ }
8
+ ],
9
+ "phase": "EXECUTION_CANCELLED",
10
+ "startedAt": "2026-01-01T00:00:00.000Z",
11
+ "completedAt": "2026-01-01T00:00:03.000Z",
12
+ "fileReviewEventStream": {
13
+ "executionId": "aex_hermetic_0001",
14
+ "events": [
15
+ {
16
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
17
+ "changeSetId": "aex_hermetic_0001:0",
18
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
19
+ "timestamp": "2026-01-01T00:00:00.000Z",
20
+ "actor": "runner",
21
+ "baselineCaptured": {
22
+ "changeSetId": "aex_hermetic_0001:0",
23
+ "turnId": "aex_hermetic_0001:0",
24
+ "harnessId": "cursor",
25
+ "baselineSnapshot": {
26
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
27
+ }
28
+ }
29
+ }
30
+ ]
31
+ },
32
+ "fileChangeProgress": {
33
+ "changeSetId": "aex_hermetic_0001:0",
34
+ "capturedAt": "2026-01-01T00:00:01.000Z"
35
+ }
36
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "Checking the repository.",
6
+ "timestamp": "2026-01-01T00:00:02.000Z"
7
+ }
8
+ ],
9
+ "phase": "EXECUTION_FAILED",
10
+ "error": "UNAUTHENTICATED: invalid api key [category=auth, source=sdk, retryable=false]",
11
+ "startedAt": "2026-01-01T00:00:00.000Z",
12
+ "completedAt": "2026-01-01T00:00:03.000Z",
13
+ "fileReviewEventStream": {
14
+ "executionId": "aex_hermetic_0001",
15
+ "events": [
16
+ {
17
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
18
+ "changeSetId": "aex_hermetic_0001:0",
19
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
20
+ "timestamp": "2026-01-01T00:00:00.000Z",
21
+ "actor": "runner",
22
+ "baselineCaptured": {
23
+ "changeSetId": "aex_hermetic_0001:0",
24
+ "turnId": "aex_hermetic_0001:0",
25
+ "harnessId": "cursor",
26
+ "baselineSnapshot": {
27
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
28
+ }
29
+ }
30
+ }
31
+ ]
32
+ },
33
+ "fileChangeProgress": {
34
+ "changeSetId": "aex_hermetic_0001:0",
35
+ "capturedAt": "2026-01-01T00:00:01.000Z"
36
+ }
37
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_SYSTEM",
5
+ "content": "Internal system error occurred. Please contact support if this issue persists.",
6
+ "timestamp": "2026-01-01T00:00:00.000Z"
7
+ },
8
+ {
9
+ "type": "MESSAGE_SYSTEM",
10
+ "content": "Error details: Cursor API rejected the request: invalid API key [category=auth, source=sdk, retryable=false]",
11
+ "timestamp": "2026-01-01T00:00:00.000Z"
12
+ }
13
+ ],
14
+ "phase": "EXECUTION_FAILED",
15
+ "error": "Cursor API rejected the request: invalid API key [category=auth, source=sdk, retryable=false]",
16
+ "startedAt": "2026-01-01T00:00:00.000Z",
17
+ "completedAt": "2026-01-01T00:00:00.000Z",
18
+ "fileReviewEventStream": {
19
+ "executionId": "aex_hermetic_0001",
20
+ "events": [
21
+ {
22
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
23
+ "changeSetId": "aex_hermetic_0001:0",
24
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
25
+ "timestamp": "2026-01-01T00:00:00.000Z",
26
+ "actor": "runner",
27
+ "baselineCaptured": {
28
+ "changeSetId": "aex_hermetic_0001:0",
29
+ "turnId": "aex_hermetic_0001:0",
30
+ "harnessId": "cursor",
31
+ "baselineSnapshot": {
32
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
33
+ }
34
+ }
35
+ }
36
+ ]
37
+ }
38
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "Running the suite.",
6
+ "timestamp": "2026-01-01T00:00:02.000Z",
7
+ "toolCalls": [
8
+ {
9
+ "id": "call-hermetic-stall-0001",
10
+ "name": "shell",
11
+ "args": {
12
+ "command": "npm test"
13
+ },
14
+ "status": "TOOL_CALL_RUNNING",
15
+ "startedAt": "2026-01-01T00:00:03.000Z",
16
+ "requiresApproval": true,
17
+ "approvalMessage": "Run command: npm test",
18
+ "argsPreview": "{\"command\":\"npm test\"}",
19
+ "toolKind": "TOOL_KIND_SHELL",
20
+ "approvalPolicySource": "APPROVAL_POLICY_SOURCE_BUILTIN_CATEGORY",
21
+ "policyEngineVersion": "phase-7"
22
+ }
23
+ ]
24
+ },
25
+ {
26
+ "type": "MESSAGE_SYSTEM",
27
+ "content": "Execution failed: the agent made no progress for too long and was stopped (Agent stream stalled: no activity for 3s (last tool: shell)). You can retry or resume.",
28
+ "timestamp": "2026-01-01T00:00:06.000Z"
29
+ }
30
+ ],
31
+ "phase": "EXECUTION_FAILED",
32
+ "error": "[StallTimeoutError] Agent stream stalled: no activity for 3s (last tool: shell). Retry or resume.",
33
+ "startedAt": "2026-01-01T00:00:00.000Z",
34
+ "completedAt": "2026-01-01T00:00:06.000Z",
35
+ "fileReviewEventStream": {
36
+ "executionId": "aex_hermetic_0001",
37
+ "events": [
38
+ {
39
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
40
+ "changeSetId": "aex_hermetic_0001:0",
41
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
42
+ "timestamp": "2026-01-01T00:00:00.000Z",
43
+ "actor": "runner",
44
+ "baselineCaptured": {
45
+ "changeSetId": "aex_hermetic_0001:0",
46
+ "turnId": "aex_hermetic_0001:0",
47
+ "harnessId": "cursor",
48
+ "baselineSnapshot": {
49
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
50
+ }
51
+ }
52
+ }
53
+ ]
54
+ },
55
+ "fileChangeProgress": {
56
+ "changeSetId": "aex_hermetic_0001:0",
57
+ "capturedAt": "2026-01-01T00:00:01.000Z"
58
+ }
59
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "Let me read it.",
6
+ "timestamp": "2026-01-01T00:00:02.000Z",
7
+ "toolCalls": [
8
+ {
9
+ "id": "call-hermetic-read-0001",
10
+ "name": "read",
11
+ "args": {
12
+ "path": "README.md"
13
+ },
14
+ "result": "# Hermetic\n\nA fixture readme.\n",
15
+ "status": "TOOL_CALL_COMPLETED",
16
+ "startedAt": "2026-01-01T00:00:03.000Z",
17
+ "completedAt": "2026-01-01T00:00:04.000Z",
18
+ "argsPreview": "{\"path\":\"README.md\"}",
19
+ "toolKind": "TOOL_KIND_FILE_READ"
20
+ }
21
+ ]
22
+ },
23
+ {
24
+ "type": "MESSAGE_AI",
25
+ "content": "README.md holds a one-line fixture description.",
26
+ "timestamp": "2026-01-01T00:00:05.000Z"
27
+ }
28
+ ],
29
+ "phase": "EXECUTION_COMPLETED",
30
+ "startedAt": "2026-01-01T00:00:00.000Z",
31
+ "completedAt": "2026-01-01T00:00:07.000Z",
32
+ "streamingUsage": {
33
+ "inputTokens": "2000",
34
+ "outputTokens": "90",
35
+ "totalTokens": "2090",
36
+ "turnCount": 1,
37
+ "estimatedCostUsd": 0.00236,
38
+ "model": "composer-2.5",
39
+ "observedAt": "2026-01-01T00:00:06.000Z",
40
+ "requestedServiceTier": "SERVICE_TIER_STANDARD",
41
+ "requestedModelParams": "[{\"id\":\"fast\",\"value\":\"false\"},{\"id\":\"thinking\",\"value\":\"false\"}]",
42
+ "requestedThinkingMode": "THINKING_MODE_DISABLED"
43
+ },
44
+ "fileReviewEventStream": {
45
+ "executionId": "aex_hermetic_0001",
46
+ "events": [
47
+ {
48
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
49
+ "changeSetId": "aex_hermetic_0001:0",
50
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
51
+ "timestamp": "2026-01-01T00:00:00.000Z",
52
+ "actor": "runner",
53
+ "baselineCaptured": {
54
+ "changeSetId": "aex_hermetic_0001:0",
55
+ "turnId": "aex_hermetic_0001:0",
56
+ "harnessId": "cursor",
57
+ "baselineSnapshot": {
58
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
59
+ }
60
+ }
61
+ }
62
+ ]
63
+ },
64
+ "fileChangeProgress": {
65
+ "changeSetId": "aex_hermetic_0001:0",
66
+ "capturedAt": "2026-01-01T00:00:01.000Z"
67
+ }
68
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "Removing the build directory.",
6
+ "timestamp": "2026-01-01T00:00:02.000Z",
7
+ "toolCalls": [
8
+ {
9
+ "id": "call-hermetic-hookblock-0001",
10
+ "name": "shell",
11
+ "args": {
12
+ "command": "rm -rf build"
13
+ },
14
+ "result": "blocked by a hook",
15
+ "status": "TOOL_CALL_FAILED",
16
+ "completedAt": "2026-01-01T00:00:03.000Z",
17
+ "error": "blocked by a hook",
18
+ "requiresApproval": true,
19
+ "approvalMessage": "Run command: rm -rf build",
20
+ "approvalRequestedAt": "2026-01-01T00:00:03.000Z",
21
+ "argsPreview": "{\"command\":\"rm -rf build\"}",
22
+ "toolKind": "TOOL_KIND_SHELL",
23
+ "approvalPolicySource": "APPROVAL_POLICY_SOURCE_BUILTIN_CATEGORY",
24
+ "policyEngineVersion": "phase-7"
25
+ }
26
+ ]
27
+ },
28
+ {
29
+ "type": "MESSAGE_AI",
30
+ "content": "I could not clean the build directory: the shell command was blocked.",
31
+ "timestamp": "2026-01-01T00:00:04.000Z"
32
+ },
33
+ {
34
+ "type": "MESSAGE_SYSTEM",
35
+ "content": "Execution failed: A Cursor hook outside Stigmer's approval gate blocked tool(s): shell. The workspace's .cursor/hooks.json registers hook(s) outside Stigmer's control [./scripts/team-policy-hook.sh], which most likely denied it. Stigmer cannot request approval on a foreign hook's behalf — remove or adjust the hook in .cursor/hooks.json and retry.",
36
+ "timestamp": "2026-01-01T00:00:06.000Z"
37
+ }
38
+ ],
39
+ "phase": "EXECUTION_FAILED",
40
+ "error": "A Cursor hook outside Stigmer's approval gate blocked tool(s): shell. The workspace's .cursor/hooks.json registers hook(s) outside Stigmer's control [./scripts/team-policy-hook.sh], which most likely denied it. Stigmer cannot request approval on a foreign hook's behalf — remove or adjust the hook in .cursor/hooks.json and retry.",
41
+ "startedAt": "2026-01-01T00:00:00.000Z",
42
+ "completedAt": "2026-01-01T00:00:06.000Z",
43
+ "streamingUsage": {
44
+ "inputTokens": "1500",
45
+ "outputTokens": "40",
46
+ "totalTokens": "1540",
47
+ "turnCount": 1,
48
+ "estimatedCostUsd": 0.00166,
49
+ "model": "composer-2.5",
50
+ "observedAt": "2026-01-01T00:00:05.000Z",
51
+ "requestedServiceTier": "SERVICE_TIER_STANDARD",
52
+ "requestedModelParams": "[{\"id\":\"fast\",\"value\":\"false\"},{\"id\":\"thinking\",\"value\":\"false\"}]",
53
+ "requestedThinkingMode": "THINKING_MODE_DISABLED"
54
+ },
55
+ "fileReviewEventStream": {
56
+ "executionId": "aex_hermetic_0001",
57
+ "events": [
58
+ {
59
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
60
+ "changeSetId": "aex_hermetic_0001:0",
61
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
62
+ "timestamp": "2026-01-01T00:00:00.000Z",
63
+ "actor": "runner",
64
+ "baselineCaptured": {
65
+ "changeSetId": "aex_hermetic_0001:0",
66
+ "turnId": "aex_hermetic_0001:0",
67
+ "harnessId": "cursor",
68
+ "baselineSnapshot": {
69
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
70
+ }
71
+ }
72
+ }
73
+ ]
74
+ },
75
+ "fileChangeProgress": {
76
+ "changeSetId": "aex_hermetic_0001:0",
77
+ "capturedAt": "2026-01-01T00:00:01.000Z"
78
+ }
79
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "messages": [
3
+ {
4
+ "type": "MESSAGE_AI",
5
+ "content": "Starting on the parser.",
6
+ "timestamp": "2026-01-01T00:00:02.000Z"
7
+ },
8
+ {
9
+ "type": "MESSAGE_SYSTEM",
10
+ "content": "Execution interrupted: the runner worker was shut down while the agent was still running. You can retry or resume.",
11
+ "timestamp": "2026-01-01T00:00:03.000Z"
12
+ }
13
+ ],
14
+ "phase": "EXECUTION_FAILED",
15
+ "error": "Execution interrupted: runner worker was shut down. Retry or resume.",
16
+ "startedAt": "2026-01-01T00:00:00.000Z",
17
+ "completedAt": "2026-01-01T00:00:03.000Z",
18
+ "fileReviewEventStream": {
19
+ "executionId": "aex_hermetic_0001",
20
+ "events": [
21
+ {
22
+ "eventId": "aex_hermetic_0001:0:aex_hermetic_0001:0:FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
23
+ "changeSetId": "aex_hermetic_0001:0",
24
+ "eventType": "FILE_REVIEW_EVENT_TYPE_BASELINE_CAPTURED",
25
+ "timestamp": "2026-01-01T00:00:00.000Z",
26
+ "actor": "runner",
27
+ "baselineCaptured": {
28
+ "changeSetId": "aex_hermetic_0001:0",
29
+ "turnId": "aex_hermetic_0001:0",
30
+ "harnessId": "cursor",
31
+ "baselineSnapshot": {
32
+ "kind": "SNAPSHOT_KIND_CAS_MANIFEST"
33
+ }
34
+ }
35
+ }
36
+ ]
37
+ },
38
+ "fileChangeProgress": {
39
+ "changeSetId": "aex_hermetic_0001:0",
40
+ "capturedAt": "2026-01-01T00:00:01.000Z"
41
+ }
42
+ }
@@ -0,0 +1,170 @@
1
+ /**
2
+ * The harness contract kit, BOTH halves, against the REAL Cursor adapter.
3
+ *
4
+ * The adapter-side half (`__test-utils__/harness-contract/contract.ts`) is the
5
+ * single statement of what every `HarnessAdapter` owes the runtime;
6
+ * `src/__tests__/harness-contract.test.ts` runs it against the scripted fake
7
+ * under both pause primitives. The runtime-side half
8
+ * (`__test-utils__/harness-contract/runtime-contract.ts`) is what the turn
9
+ * runtime owes every harness, through the real activity under
10
+ * `MockActivityEnvironment`; `harness/__tests__/run-turn.test.ts` runs it
11
+ * against the fake. This file runs BOTH against `createCursorAdapter()`
12
+ * through the Cursor subject (`__test-utils__/contract-subject.ts`), which
13
+ * translates the kit's scenarios onto S0's scripted `@cursor/sdk` double and
14
+ * runs the REAL bash preToolUse hook the adapter installs for every gated
15
+ * proposal. Nothing of the adapter is mocked; the SDK and the control-plane
16
+ * client are the two doubles every hermetic golden already substitutes.
17
+ *
18
+ * Every runtime arm here has a golden twin under `goldens/`; the goldens pin
19
+ * the transcript byte for byte, the kit asserts the contract facts in words
20
+ * any harness can satisfy. The `actionable` failure arm is registered
21
+ * SKIPPED: only the unattributed-hook-block path produces that surface on
22
+ * this harness (`unattributed-hook-block.test.ts` pins it), and the kit's
23
+ * vocabulary has no word for it.
24
+ *
25
+ * Beside the kit, the Cursor-only observations the kit's vocabulary cannot
26
+ * express: the agent the SDK minted is CLOSED when the session write behind
27
+ * `bindHarnessState` rejects (S2 M4 finding F5, an M3b regression the kit's
28
+ * rejected-bind leg exposed — before the fix the handle leaked its executor
29
+ * lease and MCP subprocesses; Q-M4-8); the SDK is asked to create one agent
30
+ * per session and never to resume (the parked handle serves every later
31
+ * turn, #215); a DISOBEDIENT re-issue after a SKIP is denied by the hook and
32
+ * never executes (what makes the subject's "obedient model" modelling safe);
33
+ * a later proposal of an identity the user already approved and the agent
34
+ * already ran gets its OWN gate and inherits nothing — the approval bleed the
35
+ * kit's invariant 3 found in this adapter (S2 M4 finding F9;
36
+ * `same-identity-reproposal.test.ts` pins the translator's rule); and the
37
+ * hook agreed with the subject's model of it at every proposal.
38
+ *
39
+ * Needs `bash` (the hook) — skipped where it is unavailable, reported as
40
+ * SKIPPED, never a silent pass. The hermetic environment (temp `HOME` for the
41
+ * gate's per-session artifacts, temp workspace root) is created at module
42
+ * level because the subject's `config` is read at collection time; the forks
43
+ * pool keeps it private to this file. No golden: the kit asserts behaviour,
44
+ * the goldens under `goldens/` pin transcripts.
45
+ */
46
+
47
+ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
48
+ import { ApprovalAction, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
49
+
50
+ vi.mock("@cursor/sdk", async () =>
51
+ (await import("../../__test-utils__/scripted-sdk.js")).scriptedCursorSdkModule(),
52
+ );
53
+ vi.mock("../../../../client/stigmer-client.js", async () =>
54
+ (await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
55
+ );
56
+
57
+ import { approvalDecisionsOf } from "../../../../harness/turn-context.js";
58
+ import { ExecutionDriver, describeHarnessContract } from "../../../../__test-utils__/harness-contract/contract.js";
59
+ import { RecordingTurnSink } from "../../../../__test-utils__/harness-contract/recording-sink.js";
60
+ import { describeHarnessRuntimeContract } from "../../../../__test-utils__/harness-contract/runtime-contract.js";
61
+ import { scenario } from "../../../../__test-utils__/harness-contract/types.js";
62
+ import { ScriptedClock, createHermeticEnvironment } from "../../../../__test-utils__/hermetic-activity.js";
63
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
64
+ import { findToolCallRow } from "../../../../__test-utils__/proto-helpers.js";
65
+ import { createCursorContractSubject } from "../../__test-utils__/contract-subject.js";
66
+ import { hasBash } from "../../__test-utils__/cursor-hook-harness.js";
67
+ import { resetCursorModuleState } from "../../__test-utils__/hermetic-cursor.js";
68
+
69
+ const env = createHermeticEnvironment();
70
+ const clock = new ScriptedClock();
71
+ const subject = createCursorContractSubject(env);
72
+ const WRITE_GAMMA = { kind: "write", resource: "/work/gamma.txt" } as const;
73
+
74
+ describe.skipIf(!hasBash)("ExecuteCursor hermetic — the harness contract kit against the real adapter", () => {
75
+ let registry: ReturnType<typeof stubRegistryFetch>;
76
+
77
+ beforeAll(() => {
78
+ // Once, never between turns: a parked agent must survive turn 1 into
79
+ // turn 2 as it does in a live worker.
80
+ resetCursorModuleState();
81
+ registry = stubRegistryFetch();
82
+ clock.install();
83
+ });
84
+
85
+ afterAll(() => {
86
+ clock.uninstall();
87
+ registry.restore();
88
+ env.dispose();
89
+ });
90
+
91
+ describeHarnessContract(subject);
92
+ describeHarnessRuntimeContract({ subject, env, clock }, { failureSurfaces: ["engine", "internal"] });
93
+
94
+ describe("cursor-only observations", () => {
95
+ beforeAll(async () => {
96
+ await subject.adapter.boot(subject.config);
97
+ });
98
+
99
+ it("closes the agent the SDK minted when the session write behind bindHarnessState rejects (F5)", async () => {
100
+ const driver = new ExecutionDriver(subject, "obs-bind-rejects");
101
+ const rejecting = new RecordingTurnSink({ bindRejectsWith: new Error("session write refused") });
102
+
103
+ const { outcome } = await driver.turn([scenario.say("never sent")], { sink: rejecting });
104
+
105
+ expect(outcome.kind).toBe("failed");
106
+ const agent = subject.agentFor(driver.sessionId);
107
+ expect(agent, "the SDK minted an agent for the session").toBeDefined();
108
+ expect(agent!.sends, "nothing was sent to it").toHaveLength(0);
109
+ expect(agent!.closeCalls, "and it was closed, not leaked: its id was never saved, so no later turn can resume it").toBe(1);
110
+ });
111
+
112
+ it("asks the SDK to create one agent per session and never to resume it (#215: the parked handle serves every later turn)", async () => {
113
+ const driver = new ExecutionDriver(subject, "obs-one-create");
114
+
115
+ const first = await driver.turn([scenario.say("first")]);
116
+ const second = await driver.turn([scenario.say("second")]);
117
+
118
+ expect(first.outcome.kind).toBe("completed");
119
+ expect(second.outcome.kind).toBe("completed");
120
+ const agent = subject.agentFor(driver.sessionId)!;
121
+ const resolutions = subject.sdk.resolutions.filter((r) => r.agentId === agent.agentId);
122
+ expect(resolutions.map((r) => r.kind), "one create, no resume").toEqual(["create"]);
123
+ expect(agent.sends, "both turns went to the same parked agent").toHaveLength(2);
124
+ });
125
+
126
+ it("denies a disobedient re-issue after a SKIP: the action never executes and the turn re-gates", async () => {
127
+ const driver = new ExecutionDriver(subject, "obs-disobedient");
128
+ const id = "obs-disobedient-write";
129
+
130
+ const proposed = await driver.turn([scenario.propose(id, WRITE_GAMMA)]);
131
+ expect(proposed.outcome.kind).toBe("awaiting_approval");
132
+ driver.decide(id, ApprovalAction.SKIP);
133
+
134
+ subject.forceReissue(id);
135
+ const reissued = await driver.turn([scenario.propose(id, WRITE_GAMMA), scenario.say("never reached")]);
136
+
137
+ expect(subject.executionCount(id), "the hook denied the re-issue; nothing ran").toBe(0);
138
+ expect(reissued.outcome.kind, "a fresh gated act pauses the turn again").toBe("awaiting_approval");
139
+ });
140
+
141
+ it("gates a later proposal of an already-approved-and-run identity on its own row; the executed row and its decision stand (F9)", async () => {
142
+ const driver = new ExecutionDriver(subject, "obs-reproposal");
143
+ const first = "obs-reproposal-first";
144
+ const later = "obs-reproposal-later";
145
+
146
+ const proposed = await driver.turn([scenario.propose(first, WRITE_GAMMA)]);
147
+ expect(proposed.outcome.kind).toBe("awaiting_approval");
148
+ driver.decide(first, ApprovalAction.APPROVE);
149
+ const ran = await driver.turn([scenario.propose(first, WRITE_GAMMA), scenario.say("written")]);
150
+ expect(ran.outcome.kind).toBe("completed");
151
+ expect(subject.executionCount(first)).toBe(1);
152
+
153
+ const again = await driver.turn([scenario.say("once more"), scenario.propose(later, WRITE_GAMMA)]);
154
+
155
+ expect(again.outcome.kind, "a new act of the same identity is gated afresh").toBe("awaiting_approval");
156
+ expect(subject.executionCount(later), "and did not run under the earlier approval").toBe(0);
157
+ const firstRow = findToolCallRow(again.sink.status, first)!;
158
+ expect(firstRow.status, "the executed row is never rewritten").toBe(ToolCallStatus.TOOL_CALL_COMPLETED);
159
+ expect(firstRow.approvalAction).toBe(ApprovalAction.APPROVE);
160
+ const laterRow = findToolCallRow(again.sink.status, later);
161
+ expect(laterRow?.status, "the new act has its own WAITING row").toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
162
+ expect(laterRow?.approvalAction, "undecided").toBe(ApprovalAction.UNSPECIFIED);
163
+ expect(approvalDecisionsOf(again.sink.status).size, "the runtime would read no decision for it").toBe(0);
164
+ });
165
+
166
+ it("the hook agreed with the subject's model of it at every proposal", () => {
167
+ expect(subject.hookDisagreements).toEqual([]);
168
+ });
169
+ });
170
+ });