@stigmer/runner 3.14.1 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/__test-utils__/execution-record-fixture.d.ts +47 -0
  3. package/dist/__test-utils__/execution-record-fixture.js +68 -0
  4. package/dist/__test-utils__/execution-record-fixture.js.map +1 -0
  5. package/dist/__test-utils__/harness-contract/types.d.ts +166 -0
  6. package/dist/__test-utils__/harness-contract/types.js +49 -0
  7. package/dist/__test-utils__/harness-contract/types.js.map +1 -0
  8. package/dist/__test-utils__/hermetic-activity.d.ts +28 -5
  9. package/dist/__test-utils__/hermetic-activity.js +23 -7
  10. package/dist/__test-utils__/hermetic-activity.js.map +1 -1
  11. package/dist/__test-utils__/mock-workspace.d.ts +15 -0
  12. package/dist/__test-utils__/mock-workspace.js +21 -0
  13. package/dist/__test-utils__/mock-workspace.js.map +1 -0
  14. package/dist/__test-utils__/model-registry-fixture.d.ts +56 -0
  15. package/dist/__test-utils__/model-registry-fixture.js +66 -0
  16. package/dist/__test-utils__/model-registry-fixture.js.map +1 -0
  17. package/dist/__test-utils__/turn-input-fixture.d.ts +60 -0
  18. package/dist/__test-utils__/turn-input-fixture.js +118 -0
  19. package/dist/__test-utils__/turn-input-fixture.js.map +1 -0
  20. package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +107 -0
  21. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +344 -0
  22. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -0
  23. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +20 -0
  24. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +58 -0
  25. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -1
  26. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +2 -32
  27. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -1
  28. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +38 -62
  29. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +47 -121
  30. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  31. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +17 -1
  32. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +27 -4
  33. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -1
  34. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +52 -11
  35. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +66 -7
  36. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -1
  37. package/dist/activities/execute-cursor/adapter.d.ts +55 -0
  38. package/dist/activities/execute-cursor/adapter.js +119 -0
  39. package/dist/activities/execute-cursor/adapter.js.map +1 -0
  40. package/dist/activities/execute-cursor/approval-state.d.ts +2 -2
  41. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  42. package/dist/activities/execute-cursor/capture-flow.d.ts +15 -30
  43. package/dist/activities/execute-cursor/capture-flow.js +17 -26
  44. package/dist/activities/execute-cursor/capture-flow.js.map +1 -1
  45. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +23 -0
  46. package/dist/activities/execute-cursor/cursor-capabilities.js +33 -0
  47. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -0
  48. package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +2 -2
  49. package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -1
  50. package/dist/activities/execute-cursor/fetch-interceptor.d.ts +15 -25
  51. package/dist/activities/execute-cursor/fetch-interceptor.js +39 -33
  52. package/dist/activities/execute-cursor/fetch-interceptor.js.map +1 -1
  53. package/dist/activities/execute-cursor/http2-interceptor.d.ts +21 -17
  54. package/dist/activities/execute-cursor/http2-interceptor.js +38 -31
  55. package/dist/activities/execute-cursor/http2-interceptor.js.map +1 -1
  56. package/dist/activities/execute-cursor/message-translator.d.ts +28 -19
  57. package/dist/activities/execute-cursor/message-translator.js +76 -27
  58. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  59. package/dist/activities/execute-cursor/prompt-builder.d.ts +180 -11
  60. package/dist/activities/execute-cursor/prompt-builder.js +171 -0
  61. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  62. package/dist/activities/execute-cursor/rejection-capture.d.ts +3 -6
  63. package/dist/activities/execute-cursor/rejection-capture.js +5 -7
  64. package/dist/activities/execute-cursor/rejection-capture.js.map +1 -1
  65. package/dist/activities/execute-cursor/session-lifecycle.d.ts +1 -4
  66. package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -1
  67. package/dist/activities/execute-cursor/turn-boundary.d.ts +1 -1
  68. package/dist/activities/execute-cursor/turn-settle.d.ts +49 -0
  69. package/dist/activities/execute-cursor/turn-settle.js +507 -0
  70. package/dist/activities/execute-cursor/turn-settle.js.map +1 -0
  71. package/dist/activities/execute-cursor/turn-setup.d.ts +173 -0
  72. package/dist/activities/execute-cursor/turn-setup.js +496 -0
  73. package/dist/activities/execute-cursor/turn-setup.js.map +1 -0
  74. package/dist/activities/execute-cursor/turn-stream.d.ts +41 -71
  75. package/dist/activities/execute-cursor/turn-stream.js +70 -135
  76. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  77. package/dist/activities/execute-cursor/turn.d.ts +43 -0
  78. package/dist/activities/execute-cursor/turn.js +222 -0
  79. package/dist/activities/execute-cursor/turn.js.map +1 -0
  80. package/dist/activities/execute-cursor/usage-pricing.d.ts +38 -0
  81. package/dist/activities/execute-cursor/usage-pricing.js +50 -0
  82. package/dist/activities/execute-cursor/usage-pricing.js.map +1 -0
  83. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +1 -1
  84. package/dist/activities/execute-deep-agent/approval-file-change.js +1 -1
  85. package/dist/activities/execute-deep-agent/environment.js +1 -1
  86. package/dist/activities/execute-deep-agent/environment.js.map +1 -1
  87. package/dist/activities/execute-deep-agent/setup.js +3 -2
  88. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  89. package/dist/activities/hydrate-workflow-execution.js +1 -1
  90. package/dist/activities/hydrate-workflow-execution.js.map +1 -1
  91. package/dist/config.d.ts +15 -0
  92. package/dist/config.js.map +1 -1
  93. package/dist/harness/capabilities.d.ts +16 -0
  94. package/dist/harness/capabilities.js +1 -0
  95. package/dist/harness/capabilities.js.map +1 -1
  96. package/dist/harness/persist-chokepoint.d.ts +74 -0
  97. package/dist/harness/persist-chokepoint.js +88 -0
  98. package/dist/harness/persist-chokepoint.js.map +1 -0
  99. package/dist/harness/registry.d.ts +44 -5
  100. package/dist/harness/registry.js +61 -5
  101. package/dist/harness/registry.js.map +1 -1
  102. package/dist/harness/run-turn.d.ts +53 -0
  103. package/dist/harness/run-turn.js +528 -0
  104. package/dist/harness/run-turn.js.map +1 -0
  105. package/dist/harness/stop-controller.d.ts +50 -0
  106. package/dist/harness/stop-controller.js +62 -0
  107. package/dist/harness/stop-controller.js.map +1 -0
  108. package/dist/harness/terminal-table.d.ts +141 -0
  109. package/dist/harness/terminal-table.js +239 -0
  110. package/dist/harness/terminal-table.js.map +1 -0
  111. package/dist/harness/turn-context.d.ts +523 -0
  112. package/dist/harness/turn-context.js +739 -0
  113. package/dist/harness/turn-context.js.map +1 -0
  114. package/dist/harness/types.d.ts +232 -52
  115. package/dist/harness/types.js +17 -8
  116. package/dist/harness/types.js.map +1 -1
  117. package/dist/harness/usage-accumulator.d.ts +68 -0
  118. package/dist/harness/usage-accumulator.js +101 -0
  119. package/dist/harness/usage-accumulator.js.map +1 -0
  120. package/dist/harness-adapters.d.ts +27 -0
  121. package/dist/harness-adapters.js +28 -0
  122. package/dist/harness-adapters.js.map +1 -0
  123. package/dist/main.js.map +1 -1
  124. package/dist/runner-manager.js +64 -48
  125. package/dist/runner-manager.js.map +1 -1
  126. package/dist/runner.d.ts +5 -4
  127. package/dist/runner.js +65 -64
  128. package/dist/runner.js.map +1 -1
  129. package/dist/shared/approval-policy.d.ts +1 -1
  130. package/dist/shared/approval-policy.js.map +1 -1
  131. package/dist/{activities/execute-cursor → shared}/attachment-resolver.d.ts +2 -2
  132. package/dist/{activities/execute-cursor → shared}/attachment-resolver.js +5 -5
  133. package/dist/shared/attachment-resolver.js.map +1 -0
  134. package/dist/{activities/execute-cursor → shared}/blueprint-resolver.d.ts +7 -5
  135. package/dist/{activities/execute-cursor → shared}/blueprint-resolver.js +3 -63
  136. package/dist/shared/blueprint-resolver.js.map +1 -0
  137. package/dist/shared/channel-attachment.d.ts +1 -1
  138. package/dist/shared/channel-attachment.js.map +1 -1
  139. package/dist/{activities/execute-cursor → shared}/cost-guard.d.ts +5 -1
  140. package/dist/{activities/execute-cursor → shared}/cost-guard.js +5 -1
  141. package/dist/shared/cost-guard.js.map +1 -0
  142. package/dist/{activities/execute-cursor → shared}/env-resolver.d.ts +1 -1
  143. package/dist/shared/env-resolver.js.map +1 -0
  144. package/dist/{activities/execute-cursor → shared}/exact-apply.d.ts +1 -1
  145. package/dist/{activities/execute-cursor → shared}/exact-apply.js +6 -6
  146. package/dist/shared/exact-apply.js.map +1 -0
  147. package/dist/shared/execution-context.d.ts +35 -0
  148. package/dist/shared/execution-context.js +38 -0
  149. package/dist/shared/execution-context.js.map +1 -0
  150. package/dist/{activities/execute-cursor → shared}/extract-structured-output.d.ts +5 -2
  151. package/dist/{activities/execute-cursor → shared}/extract-structured-output.js +9 -6
  152. package/dist/shared/extract-structured-output.js.map +1 -0
  153. package/dist/shared/filereview/capture.d.ts +1 -1
  154. package/dist/shared/filereview/capture.js +1 -1
  155. package/dist/shared/heartbeat.d.ts +13 -11
  156. package/dist/shared/heartbeat.js +14 -29
  157. package/dist/shared/heartbeat.js.map +1 -1
  158. package/dist/{activities/execute-cursor → shared}/persist-decision.d.ts +5 -2
  159. package/dist/{activities/execute-cursor → shared}/persist-decision.js +4 -1
  160. package/dist/shared/persist-decision.js.map +1 -0
  161. package/dist/{activities/execute-cursor → shared}/skill-resolver.d.ts +16 -3
  162. package/dist/{activities/execute-cursor → shared}/skill-resolver.js +12 -4
  163. package/dist/shared/skill-resolver.js.map +1 -0
  164. package/dist/shared/subagent-rows.d.ts +21 -0
  165. package/dist/shared/subagent-rows.js +34 -0
  166. package/dist/shared/subagent-rows.js.map +1 -0
  167. package/dist/shared/worker-shutdown.d.ts +43 -16
  168. package/dist/shared/worker-shutdown.js +28 -13
  169. package/dist/shared/worker-shutdown.js.map +1 -1
  170. package/dist/shared/workspace/platform-dir.d.ts +1 -1
  171. package/dist/shared/workspace/platform-dir.js +1 -1
  172. package/dist/shared/workspace/session-provision.d.ts +54 -0
  173. package/dist/{activities/execute-cursor/workspace-provision.js → shared/workspace/session-provision.js} +15 -12
  174. package/dist/shared/workspace/session-provision.js.map +1 -0
  175. package/package.json +4 -4
  176. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +110 -14
  177. package/src/__test-utils__/execution-record-fixture.ts +104 -0
  178. package/src/__test-utils__/harness-boot-order-child.ts +58 -0
  179. package/src/__test-utils__/harness-contract/contract.ts +128 -83
  180. package/src/__test-utils__/harness-contract/recording-sink.ts +15 -4
  181. package/src/__test-utils__/harness-contract/runtime-contract.ts +666 -0
  182. package/src/__test-utils__/harness-contract/scripted-adapter.ts +92 -32
  183. package/src/__test-utils__/harness-contract/types.ts +85 -9
  184. package/src/__test-utils__/hermetic-activity.ts +33 -8
  185. package/src/__test-utils__/model-registry-fixture.ts +72 -0
  186. package/src/__test-utils__/module-specifiers.ts +82 -0
  187. package/src/__test-utils__/turn-input-fixture.ts +155 -0
  188. package/src/__tests__/harness-boot-order.test.ts +77 -0
  189. package/src/__tests__/harness-contract.test.ts +7 -5
  190. package/src/__tests__/runner-manager.test.ts +18 -0
  191. package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +102 -0
  192. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +396 -0
  193. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +66 -0
  194. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +2 -43
  195. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +65 -145
  196. package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +30 -4
  197. package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +96 -8
  198. package/src/activities/execute-cursor/__tests__/adapter-is-temporal-free.test.ts +45 -0
  199. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +90 -0
  200. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +7 -8
  201. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +28 -1
  202. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +1 -1
  203. package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +64 -6
  204. package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +1 -1
  205. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -1
  206. package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.status.json +53 -0
  207. package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.status.json +1 -6
  208. package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.status.json +56 -0
  209. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-transport-timeout.status.json +48 -0
  210. package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
  211. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-cancelled.status.json +36 -0
  212. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-error-non-retryable.status.json +37 -0
  213. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +38 -0
  214. package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.status.json +59 -0
  215. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +79 -0
  216. package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.status.json +2 -7
  217. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +170 -0
  218. package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +22 -18
  219. package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +1 -1
  220. package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +1 -1
  221. package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +286 -0
  222. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +332 -0
  223. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +193 -0
  224. package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +1 -1
  225. package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +185 -0
  226. package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +151 -0
  227. package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +65 -35
  228. package/src/activities/execute-cursor/__tests__/message-translator.test.ts +0 -40
  229. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +171 -0
  230. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +118 -243
  231. package/src/activities/execute-cursor/__tests__/usage-pricing.test.ts +84 -0
  232. package/src/activities/execute-cursor/adapter.ts +138 -0
  233. package/src/activities/execute-cursor/approval-state.ts +2 -2
  234. package/src/activities/execute-cursor/capture-flow.ts +18 -41
  235. package/src/activities/execute-cursor/cursor-capabilities.ts +35 -0
  236. package/src/activities/execute-cursor/cursor-mcp-config.ts +2 -2
  237. package/src/activities/execute-cursor/fetch-interceptor.ts +48 -45
  238. package/src/activities/execute-cursor/http2-interceptor.ts +47 -34
  239. package/src/activities/execute-cursor/message-translator.ts +90 -45
  240. package/src/activities/execute-cursor/prompt-builder.ts +327 -12
  241. package/src/activities/execute-cursor/rejection-capture.ts +5 -12
  242. package/src/activities/execute-cursor/session-lifecycle.ts +1 -5
  243. package/src/activities/execute-cursor/turn-boundary.ts +1 -1
  244. package/src/activities/execute-cursor/turn-settle.ts +601 -0
  245. package/src/activities/execute-cursor/turn-setup.ts +645 -0
  246. package/src/activities/execute-cursor/turn-stream.ts +84 -210
  247. package/src/activities/execute-cursor/turn.ts +240 -0
  248. package/src/activities/execute-cursor/usage-pricing.ts +67 -0
  249. package/src/activities/execute-deep-agent/approval-file-change.ts +1 -1
  250. package/src/activities/execute-deep-agent/environment.ts +1 -1
  251. package/src/activities/execute-deep-agent/setup.ts +3 -2
  252. package/src/activities/hydrate-workflow-execution.ts +1 -1
  253. package/src/config.ts +13 -0
  254. package/src/harness/__tests__/import-direction.test.ts +168 -0
  255. package/src/harness/__tests__/persist-chokepoint.test.ts +146 -0
  256. package/src/harness/__tests__/registry.test.ts +1 -0
  257. package/src/harness/__tests__/run-turn.test.ts +165 -0
  258. package/src/harness/__tests__/stop-controller.test.ts +49 -0
  259. package/src/harness/__tests__/turn-context.test.ts +178 -0
  260. package/src/harness/__tests__/usage-accumulator.test.ts +83 -0
  261. package/src/harness/capabilities.ts +17 -0
  262. package/src/harness/persist-chokepoint.ts +112 -0
  263. package/src/harness/registry.ts +79 -5
  264. package/src/harness/run-turn.ts +618 -0
  265. package/src/harness/stop-controller.ts +83 -0
  266. package/src/harness/terminal-table.ts +276 -0
  267. package/src/harness/turn-context.ts +1028 -0
  268. package/src/harness/types.ts +248 -53
  269. package/src/harness/usage-accumulator.ts +122 -0
  270. package/src/harness-adapters.ts +30 -0
  271. package/src/main.ts +1 -1
  272. package/src/runner-manager.ts +68 -61
  273. package/src/runner.ts +67 -78
  274. package/src/shared/__tests__/attachment-naming.test.ts +1 -1
  275. package/src/{activities/execute-cursor → shared}/__tests__/attachment-resolver.test.ts +6 -4
  276. package/src/{activities/execute-cursor → shared}/__tests__/cost-guard.test.ts +2 -1
  277. package/src/{activities/execute-cursor → shared}/__tests__/exact-apply.test.ts +3 -3
  278. package/src/{activities/execute-cursor → shared}/__tests__/extract-structured-output.test.ts +8 -8
  279. package/src/{activities/execute-cursor → shared}/__tests__/persist-decision.test.ts +4 -2
  280. package/src/{activities/execute-cursor → shared}/__tests__/skill-resolver.test.ts +1 -1
  281. package/src/shared/__tests__/subagent-rows.test.ts +34 -0
  282. package/src/shared/__tests__/worker-shutdown.test.ts +44 -39
  283. package/src/shared/approval-policy.ts +1 -1
  284. package/src/{activities/execute-cursor → shared}/attachment-resolver.ts +6 -6
  285. package/src/{activities/execute-cursor → shared}/blueprint-resolver.ts +7 -78
  286. package/src/shared/channel-attachment.ts +1 -1
  287. package/src/{activities/execute-cursor → shared}/cost-guard.ts +5 -1
  288. package/src/{activities/execute-cursor → shared}/env-resolver.ts +1 -1
  289. package/src/{activities/execute-cursor → shared}/exact-apply.ts +7 -7
  290. package/src/shared/execution-context.ts +45 -0
  291. package/src/{activities/execute-cursor → shared}/extract-structured-output.ts +10 -7
  292. package/src/shared/filereview/capture.ts +1 -1
  293. package/src/shared/heartbeat.ts +13 -33
  294. package/src/{activities/execute-cursor → shared}/persist-decision.ts +5 -2
  295. package/src/{activities/execute-cursor → shared}/skill-resolver.ts +20 -6
  296. package/src/shared/subagent-rows.ts +39 -0
  297. package/src/shared/worker-shutdown.ts +55 -25
  298. package/src/{activities/execute-cursor/__tests__/workspace-provision.test.ts → shared/workspace/__tests__/session-provision.test.ts} +25 -28
  299. package/src/shared/workspace/platform-dir.ts +1 -1
  300. package/src/{activities/execute-cursor/workspace-provision.ts → shared/workspace/session-provision.ts} +29 -16
  301. package/dist/activities/execute-cursor/attachment-resolver.js.map +0 -1
  302. package/dist/activities/execute-cursor/blueprint-resolver.js.map +0 -1
  303. package/dist/activities/execute-cursor/cost-guard.js.map +0 -1
  304. package/dist/activities/execute-cursor/env-resolver.js.map +0 -1
  305. package/dist/activities/execute-cursor/exact-apply.js.map +0 -1
  306. package/dist/activities/execute-cursor/extract-structured-output.js.map +0 -1
  307. package/dist/activities/execute-cursor/index.d.ts +0 -209
  308. package/dist/activities/execute-cursor/index.js +0 -2345
  309. package/dist/activities/execute-cursor/index.js.map +0 -1
  310. package/dist/activities/execute-cursor/persist-decision.js.map +0 -1
  311. package/dist/activities/execute-cursor/skill-resolver.js.map +0 -1
  312. package/dist/activities/execute-cursor/usage-accumulator.d.ts +0 -89
  313. package/dist/activities/execute-cursor/usage-accumulator.js +0 -121
  314. package/dist/activities/execute-cursor/usage-accumulator.js.map +0 -1
  315. package/dist/activities/execute-cursor/workspace-provision.d.ts +0 -42
  316. package/dist/activities/execute-cursor/workspace-provision.js.map +0 -1
  317. package/src/activities/execute-cursor/__tests__/usage-accumulator.test.ts +0 -164
  318. package/src/activities/execute-cursor/index.ts +0 -2876
  319. package/src/activities/execute-cursor/usage-accumulator.ts +0 -169
  320. /package/dist/{activities/execute-cursor → shared}/env-resolver.js +0 -0
@@ -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,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
+ }
@@ -8,18 +8,13 @@
8
8
  {
9
9
  "type": "MESSAGE_SYSTEM",
10
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:04.000Z"
12
- },
13
- {
14
- "type": "MESSAGE_SYSTEM",
15
- "content": "Execution interrupted: the runner worker was shut down while the agent was still running. You can retry or resume.",
16
- "timestamp": "2026-01-01T00:00:04.000Z"
11
+ "timestamp": "2026-01-01T00:00:03.000Z"
17
12
  }
18
13
  ],
19
14
  "phase": "EXECUTION_FAILED",
20
15
  "error": "Execution interrupted: runner worker was shut down. Retry or resume.",
21
16
  "startedAt": "2026-01-01T00:00:00.000Z",
22
- "completedAt": "2026-01-01T00:00:04.000Z",
17
+ "completedAt": "2026-01-01T00:00:03.000Z",
23
18
  "fileReviewEventStream": {
24
19
  "executionId": "aex_hermetic_0001",
25
20
  "events": [
@@ -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
+ });
@@ -2,8 +2,8 @@
2
2
  * Hermetic goldens: USER PAUSE versus WORKER SHUTDOWN — the two interruptions
3
3
  * that THROW, and the byte-pinned copy that tells them apart.
4
4
  *
5
- * Invariant pinned (the throw-vs-return table the runtime will own in S2; parent
6
- * §5c): both interruptions end the activity with a thrown Temporal
5
+ * Invariant pinned (the throw-vs-return table the runtime owns,
6
+ * `harness/terminal-table.ts`; parent §5c): both interruptions end the activity with a thrown Temporal
7
7
  * `CancelledFailure` (never a return), but they persist DIFFERENT terminal
8
8
  * states the control plane keys on:
9
9
  *
@@ -22,17 +22,25 @@
22
22
  * stream loop sees `isCancelled()` on its next iteration and never processes
23
23
  * the event that follows.
24
24
  *
25
- * What the goldens ALSO pin, on purpose: both paths append their system message
26
- * TWICE once in `resolvePreBoundaryTerminal` before the throw, once again in
27
- * the outer `catch (CancelledFailure)`, which re-stamps and re-persists. That is
28
- * today's production behavior on the wire. S2 must reproduce it byte for byte;
29
- * whether it is later collapsed to one message is a separate, deliberate change
30
- * (recorded in the entry's execution log for the owner).
25
+ * What the goldens ALSO pin: each path appends its system message exactly
26
+ * ONCE. The orchestrator this net was recorded on appended it twice — once in
27
+ * `resolvePreBoundaryTerminal` before the throw, once again in the outer
28
+ * `catch (CancelledFailure)`, which re-stamped and re-persisted and the
29
+ * goldens pinned that double on purpose so S2 could reproduce the wire byte
30
+ * for byte (stigmer#1054, Q-S2-4). The runtime's `settleWith` is now the one
31
+ * writer of a terminal arm, so a second row has no code path to come from.
31
32
  *
32
- * Parent phase rows exercised: the stream loop's cancellation check; the
33
- * post-stream `classifyTurnInterruption`; `resolvePreBoundaryTerminal`'s
34
- * pause and worker-shutdown arms; the outer `CancelledFailure` catch; the
35
- * `finally` teardown under a thrown exit.
33
+ * Runtime phases exercised: the adapter's stop-signal cancel; the runtime's
34
+ * `classifyTurnInterruption`; the terminal table's pause and worker-shutdown
35
+ * arms through `settleWith`; the `finally` teardown under a thrown exit.
36
+ *
37
+ * Regeneration history:
38
+ * - S2 M3b (entry 20260911.03): timestamp-only diff — every terminal stamp
39
+ * one scripted second earlier: the adapter cancels the SDK run the instant
40
+ * the runtime's stop signal aborts (Q-M3-4), before the SDK double pulls,
41
+ * and the clock ticks on, one more step. Transcript unchanged.
42
+ * - 2026-09-12 (stigmer#1054, the PR after S2): one removed system row per
43
+ * golden, nothing else. The transcript now carries each terminal row once.
36
44
  *
37
45
  * Regenerate ONLY after a deliberate behavior change:
38
46
  * npx vitest run src/activities/execute-cursor/__tests__/hermetic -u
@@ -63,8 +71,8 @@ import {
63
71
  beginCursorScenario,
64
72
  cursorExecutionRecord,
65
73
  runCursorTurn,
66
- stubRegistryFetch,
67
74
  } from "../../__test-utils__/hermetic-cursor.js";
75
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
68
76
 
69
77
  const USER_MESSAGE = "Refactor the parser module.";
70
78
  const NEVER_SEEN = "This text must never reach the transcript.";
@@ -144,10 +152,7 @@ describe("ExecuteCursor hermetic — user pause vs worker shutdown", () => {
144
152
  expect(final.completedAt, "a paused turn is not complete").toBe("");
145
153
  expect(
146
154
  final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content),
147
- ).toEqual([
148
- "Execution paused by user. Use resume to continue.",
149
- "Execution paused by user. Use resume to continue.",
150
- ]);
155
+ ).toEqual(["Execution paused by user. Use resume to continue."]);
151
156
  expect(final.messages.some((m) => m.content === NEVER_SEEN), "nothing after the cancel is processed").toBe(false);
152
157
 
153
158
  const json = JSON.stringify(toJson(AgentExecutionStatusSchema, final), null, 2) + "\n";
@@ -191,7 +196,6 @@ describe("ExecuteCursor hermetic — user pause vs worker shutdown", () => {
191
196
  final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content),
192
197
  ).toEqual([
193
198
  "Execution interrupted: the runner worker was shut down while the agent was still running. You can retry or resume.",
194
- "Execution interrupted: the runner worker was shut down while the agent was still running. You can retry or resume.",
195
199
  ]);
196
200
  expect(final.messages.some((m) => m.content === NEVER_SEEN)).toBe(false);
197
201
 
@@ -53,8 +53,8 @@ import {
53
53
  beginCursorScenario,
54
54
  cursorExecutionRecord,
55
55
  runCursorTurn,
56
- stubRegistryFetch,
57
56
  } from "../../__test-utils__/hermetic-cursor.js";
57
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
58
58
 
59
59
  const AGENT_ID = "agent-hermetic-plain-0001";
60
60
  const RUN_ID = "run-hermetic-plain-0001";
@@ -49,8 +49,8 @@ import {
49
49
  beginCursorScenario,
50
50
  cursorExecutionRecord,
51
51
  runCursorTurn,
52
- stubRegistryFetch,
53
52
  } from "../../__test-utils__/hermetic-cursor.js";
53
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
54
54
 
55
55
  const STALE_AGENT_ID = "agent-hermetic-stale-0001";
56
56
  const FRESH_AGENT_ID = "agent-hermetic-fresh-0002";