@stigmer/runner 3.15.0 → 3.15.2-dev.20260913223433

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 (518) hide show
  1. package/README.md +2 -4
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__test-utils__/execution-record-fixture.d.ts +14 -0
  4. package/dist/__test-utils__/execution-record-fixture.js +4 -0
  5. package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
  6. package/dist/__test-utils__/file-review-projection.d.ts +40 -0
  7. package/dist/__test-utils__/file-review-projection.js +136 -0
  8. package/dist/__test-utils__/file-review-projection.js.map +1 -0
  9. package/dist/__test-utils__/harness-contract/types.d.ts +23 -1
  10. package/dist/__test-utils__/harness-contract/types.js +15 -0
  11. package/dist/__test-utils__/harness-contract/types.js.map +1 -1
  12. package/dist/__test-utils__/hermetic-activity.d.ts +44 -12
  13. package/dist/__test-utils__/hermetic-activity.js +52 -14
  14. package/dist/__test-utils__/hermetic-activity.js.map +1 -1
  15. package/dist/__test-utils__/model-registry-fixture.d.ts +32 -7
  16. package/dist/__test-utils__/model-registry-fixture.js +31 -7
  17. package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
  18. package/dist/__test-utils__/turn-input-fixture.d.ts +1 -1
  19. package/dist/__test-utils__/turn-input-fixture.js +1 -1
  20. package/dist/__test-utils__/turn-input-fixture.js.map +1 -1
  21. package/dist/activities/call-agent.js +2 -2
  22. package/dist/activities/call-agent.js.map +1 -1
  23. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +45 -3
  24. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
  25. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +0 -9
  26. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +2 -41
  27. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  28. package/dist/activities/execute-cursor/adapter.d.ts +7 -5
  29. package/dist/activities/execute-cursor/adapter.js +7 -5
  30. package/dist/activities/execute-cursor/adapter.js.map +1 -1
  31. package/dist/activities/execute-cursor/approval-policy.d.ts +5 -2
  32. package/dist/activities/execute-cursor/approval-policy.js +5 -2
  33. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  34. package/dist/activities/execute-cursor/approval-state.d.ts +16 -8
  35. package/dist/activities/execute-cursor/approval-state.js +6 -3
  36. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  37. package/dist/activities/execute-cursor/cas-observations.d.ts +14 -2
  38. package/dist/activities/execute-cursor/cas-observations.js +19 -2
  39. package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
  40. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +8 -4
  41. package/dist/activities/execute-cursor/cursor-capabilities.js +21 -4
  42. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -1
  43. package/dist/activities/execute-cursor/message-translator.d.ts +12 -20
  44. package/dist/activities/execute-cursor/message-translator.js +19 -32
  45. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  46. package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -58
  47. package/dist/activities/execute-cursor/prompt-builder.js +76 -95
  48. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  49. package/dist/activities/execute-cursor/turn-boundary.d.ts +27 -55
  50. package/dist/activities/execute-cursor/turn-boundary.js +30 -90
  51. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
  52. package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
  53. package/dist/activities/execute-cursor/turn-settle.js +37 -49
  54. package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
  55. package/dist/activities/execute-cursor/turn-setup.d.ts +16 -24
  56. package/dist/activities/execute-cursor/turn-setup.js +29 -59
  57. package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
  58. package/dist/activities/execute-cursor/turn-stream.d.ts +3 -8
  59. package/dist/activities/execute-cursor/turn-stream.js +9 -22
  60. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  61. package/dist/activities/execute-cursor/turn.js +5 -1
  62. package/dist/activities/execute-cursor/turn.js.map +1 -1
  63. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +93 -0
  64. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +348 -0
  65. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
  66. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +170 -0
  67. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +225 -0
  68. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
  69. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
  70. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
  71. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
  72. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +54 -0
  73. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +72 -0
  74. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
  75. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +187 -23
  76. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +238 -27
  77. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
  78. package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
  79. package/dist/activities/execute-deep-agent/adapter.js +78 -0
  80. package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
  81. package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +8 -0
  82. package/dist/activities/execute-deep-agent/cas-capture-observer.js +9 -0
  83. package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -1
  84. package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +31 -0
  85. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +40 -0
  86. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
  87. package/dist/activities/execute-deep-agent/execution-state.d.ts +4 -11
  88. package/dist/activities/execute-deep-agent/execution-state.js +4 -12
  89. package/dist/activities/execute-deep-agent/execution-state.js.map +1 -1
  90. package/dist/activities/execute-deep-agent/hitl.d.ts +49 -47
  91. package/dist/activities/execute-deep-agent/hitl.js +77 -103
  92. package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
  93. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +51 -23
  94. package/dist/activities/execute-deep-agent/prompt-builder.js +115 -76
  95. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  96. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +18 -32
  97. package/dist/activities/execute-deep-agent/status-builder-shared.js +10 -65
  98. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
  99. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +10 -8
  100. package/dist/activities/execute-deep-agent/streaming-side-effects.js +12 -14
  101. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  102. package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +36 -13
  103. package/dist/activities/execute-deep-agent/subagent-tracker.js +76 -39
  104. package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
  105. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -28
  106. package/dist/activities/execute-deep-agent/subagent-transformer.js +29 -82
  107. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  108. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -2
  109. package/dist/activities/execute-deep-agent/subagent-wiring.js +2 -2
  110. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  111. package/dist/activities/execute-deep-agent/turn-settle.d.ts +42 -0
  112. package/dist/activities/execute-deep-agent/turn-settle.js +146 -0
  113. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
  114. package/dist/activities/execute-deep-agent/turn-setup.d.ts +212 -0
  115. package/dist/activities/execute-deep-agent/turn-setup.js +430 -0
  116. package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
  117. package/dist/activities/execute-deep-agent/turn-stream.d.ts +97 -0
  118. package/dist/activities/execute-deep-agent/turn-stream.js +242 -0
  119. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
  120. package/dist/activities/execute-deep-agent/turn.d.ts +42 -0
  121. package/dist/activities/execute-deep-agent/turn.js +116 -0
  122. package/dist/activities/execute-deep-agent/turn.js.map +1 -0
  123. package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +6 -5
  124. package/dist/activities/execute-deep-agent/v3-event-recorder.js +6 -5
  125. package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -1
  126. package/dist/activities/execute-deep-agent/v3-events.d.ts +1 -1
  127. package/dist/activities/execute-deep-agent/v3-events.js +1 -1
  128. package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +60 -17
  129. package/dist/activities/execute-deep-agent/v3-status-builder.js +72 -57
  130. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
  131. package/dist/harness/approval-decisions.d.ts +61 -0
  132. package/dist/harness/approval-decisions.js +102 -0
  133. package/dist/harness/approval-decisions.js.map +1 -0
  134. package/dist/harness/capabilities.d.ts +16 -5
  135. package/dist/harness/capabilities.js +9 -0
  136. package/dist/harness/capabilities.js.map +1 -1
  137. package/dist/harness/capture.d.ts +144 -0
  138. package/dist/harness/capture.js +219 -0
  139. package/dist/harness/capture.js.map +1 -0
  140. package/dist/harness/persist-chokepoint.d.ts +19 -4
  141. package/dist/harness/persist-chokepoint.js +17 -4
  142. package/dist/harness/persist-chokepoint.js.map +1 -1
  143. package/dist/harness/run-turn.js +115 -29
  144. package/dist/harness/run-turn.js.map +1 -1
  145. package/dist/harness/terminal-table.d.ts +40 -11
  146. package/dist/harness/terminal-table.js +58 -19
  147. package/dist/harness/terminal-table.js.map +1 -1
  148. package/dist/harness/turn-context.d.ts +141 -76
  149. package/dist/harness/turn-context.js +194 -99
  150. package/dist/harness/turn-context.js.map +1 -1
  151. package/dist/harness/types.d.ts +65 -12
  152. package/dist/harness/types.js +8 -2
  153. package/dist/harness/types.js.map +1 -1
  154. package/dist/harness-adapters.d.ts +12 -8
  155. package/dist/harness-adapters.js +17 -9
  156. package/dist/harness-adapters.js.map +1 -1
  157. package/dist/middleware/approval-gate.d.ts +1 -1
  158. package/dist/middleware/approval-gate.js +1 -1
  159. package/dist/middleware/approval-gate.js.map +1 -1
  160. package/dist/middleware/cost-advisory.d.ts +39 -0
  161. package/dist/middleware/{cost-cap.js → cost-advisory.js} +37 -55
  162. package/dist/middleware/cost-advisory.js.map +1 -0
  163. package/dist/middleware/index.d.ts +23 -12
  164. package/dist/middleware/index.js +26 -18
  165. package/dist/middleware/index.js.map +1 -1
  166. package/dist/middleware/types.d.ts +3 -2
  167. package/dist/runner-manager.js +1 -5
  168. package/dist/runner-manager.js.map +1 -1
  169. package/dist/runner.js +1 -5
  170. package/dist/runner.js.map +1 -1
  171. package/dist/shared/attachment-resolver.d.ts +41 -18
  172. package/dist/shared/attachment-resolver.js +178 -46
  173. package/dist/shared/attachment-resolver.js.map +1 -1
  174. package/dist/shared/attachment-zip.d.ts +85 -0
  175. package/dist/shared/attachment-zip.js +185 -0
  176. package/dist/shared/attachment-zip.js.map +1 -0
  177. package/dist/shared/connect-backfill.js +5 -4
  178. package/dist/shared/connect-backfill.js.map +1 -1
  179. package/dist/shared/cost-guard.d.ts +3 -3
  180. package/dist/shared/cost-guard.js +3 -3
  181. package/dist/shared/execution-status-writer.d.ts +5 -5
  182. package/dist/shared/execution-status-writer.js +5 -5
  183. package/dist/shared/extract-structured-output.d.ts +8 -7
  184. package/dist/shared/extract-structured-output.js +8 -7
  185. package/dist/shared/extract-structured-output.js.map +1 -1
  186. package/dist/shared/filereview/cas-progress.d.ts +1 -18
  187. package/dist/shared/filereview/cas-progress.js +4 -0
  188. package/dist/shared/filereview/cas-progress.js.map +1 -1
  189. package/dist/shared/filereview/cas-touched.d.ts +56 -0
  190. package/dist/shared/filereview/cas-touched.js +63 -0
  191. package/dist/shared/filereview/cas-touched.js.map +1 -0
  192. package/dist/shared/filereview/index.d.ts +2 -1
  193. package/dist/shared/filereview/index.js +2 -1
  194. package/dist/shared/filereview/index.js.map +1 -1
  195. package/dist/shared/mcp-resolver.d.ts +4 -5
  196. package/dist/shared/mcp-resolver.js +4 -5
  197. package/dist/shared/mcp-resolver.js.map +1 -1
  198. package/dist/shared/persist-decision.d.ts +3 -4
  199. package/dist/shared/persist-decision.js +3 -4
  200. package/dist/shared/persist-decision.js.map +1 -1
  201. package/dist/shared/plan-mode-permissions.d.ts +2 -2
  202. package/dist/shared/plan-mode-permissions.js +2 -2
  203. package/dist/shared/plan-mode-prompt.d.ts +1 -1
  204. package/dist/shared/plan-mode-prompt.js +1 -1
  205. package/dist/shared/prompt-sections.d.ts +163 -0
  206. package/dist/shared/prompt-sections.js +164 -0
  207. package/dist/shared/prompt-sections.js.map +1 -0
  208. package/dist/shared/skill-resolver.d.ts +4 -2
  209. package/dist/shared/skill-resolver.js +4 -2
  210. package/dist/shared/skill-resolver.js.map +1 -1
  211. package/dist/shared/tool-rounds.d.ts +32 -0
  212. package/dist/shared/tool-rounds.js +43 -0
  213. package/dist/shared/tool-rounds.js.map +1 -1
  214. package/dist/shared/tool-row.d.ts +34 -0
  215. package/dist/shared/tool-row.js +52 -0
  216. package/dist/shared/tool-row.js.map +1 -1
  217. package/dist/shared/workspace/session-provision.d.ts +3 -3
  218. package/dist/shared/workspace/session-provision.js +3 -3
  219. package/dist/shared/workspace/stigmer-link.d.ts +3 -3
  220. package/dist/shared/workspace/stigmer-link.js +3 -3
  221. package/dist/shared/workspace/writeback-coordinator.d.ts +15 -22
  222. package/dist/shared/workspace/writeback-coordinator.js +16 -53
  223. package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
  224. package/dist/tools/index.d.ts +1 -1
  225. package/dist/tools/index.js +1 -1
  226. package/package.json +4 -4
  227. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +1 -0
  228. package/src/__test-utils__/execution-record-fixture.ts +18 -2
  229. package/src/__test-utils__/file-review-projection.ts +156 -0
  230. package/src/__test-utils__/git-workspace-fixture.ts +58 -0
  231. package/src/__test-utils__/harness-boot-order-child.ts +7 -2
  232. package/src/__test-utils__/harness-contract/contract.ts +33 -20
  233. package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
  234. package/src/__test-utils__/harness-contract/runtime-contract.ts +328 -10
  235. package/src/__test-utils__/harness-contract/scripted-adapter.ts +38 -6
  236. package/src/__test-utils__/harness-contract/types.ts +27 -3
  237. package/src/__test-utils__/hermetic-activity.ts +52 -14
  238. package/src/__test-utils__/model-registry-fixture.ts +32 -7
  239. package/src/__test-utils__/module-specifiers.ts +24 -0
  240. package/src/__test-utils__/turn-input-fixture.ts +2 -2
  241. package/src/__tests__/harness-boot-order.test.ts +9 -2
  242. package/src/activities/call-agent.ts +2 -2
  243. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +47 -3
  244. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +2 -48
  245. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +1 -1
  246. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +6 -1
  247. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +52 -27
  248. package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +25 -0
  249. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +166 -0
  250. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +186 -0
  251. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +191 -0
  252. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
  253. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
  254. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
  255. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -2
  256. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +4 -0
  257. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +24 -4
  258. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +6 -5
  259. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +9 -0
  260. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +11 -8
  261. package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +229 -0
  262. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +3 -3
  263. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +2 -2
  264. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +78 -234
  265. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +1 -26
  266. package/src/activities/execute-cursor/adapter.ts +7 -5
  267. package/src/activities/execute-cursor/approval-policy.ts +5 -2
  268. package/src/activities/execute-cursor/approval-state.ts +16 -8
  269. package/src/activities/execute-cursor/cas-observations.ts +20 -2
  270. package/src/activities/execute-cursor/cursor-capabilities.ts +24 -5
  271. package/src/activities/execute-cursor/message-translator.ts +29 -41
  272. package/src/activities/execute-cursor/prompt-builder.ts +99 -157
  273. package/src/activities/execute-cursor/turn-boundary.ts +34 -140
  274. package/src/activities/execute-cursor/turn-settle.ts +37 -51
  275. package/src/activities/execute-cursor/turn-setup.ts +30 -70
  276. package/src/activities/execute-cursor/turn-stream.ts +8 -31
  277. package/src/activities/execute-cursor/turn.ts +5 -1
  278. package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +391 -0
  279. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +313 -0
  280. package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
  281. package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +85 -0
  282. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +383 -36
  283. package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
  284. package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
  285. package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +80 -0
  286. package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +1 -1
  287. package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -2
  288. package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -3
  289. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +172 -0
  290. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +167 -0
  291. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +36 -0
  292. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +178 -0
  293. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +158 -0
  294. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +210 -0
  295. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +74 -0
  296. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +104 -0
  297. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +78 -0
  298. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +138 -0
  299. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +68 -0
  300. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +154 -0
  301. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +116 -0
  302. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +69 -0
  303. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +67 -0
  304. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +47 -0
  305. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +68 -0
  306. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +280 -0
  307. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +77 -0
  308. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
  309. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +99 -0
  310. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +109 -0
  311. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +76 -0
  312. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +51 -0
  313. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +51 -0
  314. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +56 -0
  315. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +90 -0
  316. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +70 -0
  317. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +71 -0
  318. package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
  319. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +184 -0
  320. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +203 -0
  321. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +170 -0
  322. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +175 -0
  323. package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +206 -0
  324. package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +142 -0
  325. package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +126 -0
  326. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +139 -0
  327. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +122 -0
  328. package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +236 -0
  329. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +161 -0
  330. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +157 -0
  331. package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +152 -0
  332. package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +50 -122
  333. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +8 -6
  334. package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +2 -2
  335. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +35 -35
  336. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +247 -0
  337. package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +329 -0
  338. package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +1 -20
  339. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +78 -0
  340. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +1 -1
  341. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +2 -2
  342. package/src/activities/execute-deep-agent/__tests__/subagent-tracker.test.ts +57 -31
  343. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +19 -79
  344. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +15 -15
  345. package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +1 -1
  346. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +391 -0
  347. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +343 -38
  348. package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +5 -5
  349. package/src/activities/execute-deep-agent/adapter.ts +94 -0
  350. package/src/activities/execute-deep-agent/cas-capture-observer.ts +11 -0
  351. package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +43 -0
  352. package/src/activities/execute-deep-agent/execution-state.ts +4 -13
  353. package/src/activities/execute-deep-agent/hitl.ts +100 -123
  354. package/src/activities/execute-deep-agent/prompt-builder.ts +141 -115
  355. package/src/activities/execute-deep-agent/status-builder-shared.ts +21 -84
  356. package/src/activities/execute-deep-agent/streaming-side-effects.ts +13 -19
  357. package/src/activities/execute-deep-agent/subagent-tracker.ts +77 -42
  358. package/src/activities/execute-deep-agent/subagent-transformer.ts +46 -105
  359. package/src/activities/execute-deep-agent/subagent-wiring.ts +5 -4
  360. package/src/activities/execute-deep-agent/turn-settle.ts +164 -0
  361. package/src/activities/execute-deep-agent/turn-setup.ts +541 -0
  362. package/src/activities/execute-deep-agent/turn-stream.ts +313 -0
  363. package/src/activities/execute-deep-agent/turn.ts +131 -0
  364. package/src/activities/execute-deep-agent/v3-event-recorder.ts +6 -5
  365. package/src/activities/execute-deep-agent/v3-events.ts +1 -1
  366. package/src/activities/execute-deep-agent/v3-status-builder.ts +84 -63
  367. package/src/harness/__tests__/approval-decisions.test.ts +116 -0
  368. package/src/harness/__tests__/capture.test.ts +268 -0
  369. package/src/harness/__tests__/mount-skills.test.ts +169 -0
  370. package/src/harness/__tests__/persist-chokepoint.test.ts +38 -2
  371. package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
  372. package/src/harness/__tests__/run-turn.test.ts +39 -23
  373. package/src/harness/__tests__/turn-attachments-vision.test.ts +80 -0
  374. package/src/harness/__tests__/turn-context.test.ts +73 -26
  375. package/src/harness/approval-decisions.ts +104 -0
  376. package/src/harness/capabilities.ts +16 -5
  377. package/src/harness/capture.ts +301 -0
  378. package/src/harness/persist-chokepoint.ts +24 -4
  379. package/src/harness/run-turn.ts +120 -29
  380. package/src/harness/terminal-table.ts +61 -20
  381. package/src/harness/turn-context.ts +208 -111
  382. package/src/harness/types.ts +66 -12
  383. package/src/harness-adapters.ts +17 -9
  384. package/src/middleware/__tests__/approval-gate.test.ts +1 -1
  385. package/src/middleware/__tests__/cost-advisory.test.ts +113 -0
  386. package/src/middleware/approval-gate.ts +2 -2
  387. package/src/middleware/{cost-cap.ts → cost-advisory.ts} +40 -70
  388. package/src/middleware/index.ts +29 -29
  389. package/src/middleware/types.ts +3 -2
  390. package/src/runner-manager.ts +0 -8
  391. package/src/runner.ts +0 -8
  392. package/src/shared/__tests__/attachment-naming.test.ts +6 -19
  393. package/src/shared/__tests__/attachment-resolver.test.ts +158 -8
  394. package/src/shared/__tests__/attachment-zip.test.ts +236 -0
  395. package/src/shared/__tests__/bedrock-adapter.test.ts +1 -1
  396. package/src/shared/__tests__/blueprint-resolver.test.ts +43 -0
  397. package/src/shared/__tests__/cost-guard.test.ts +3 -3
  398. package/src/shared/__tests__/prompt-sections.test.ts +167 -0
  399. package/src/shared/__tests__/secret-leak-scan.test.ts +2 -2
  400. package/src/{activities/execute-deep-agent → shared}/__tests__/stamp-flowed-rows.test.ts +33 -10
  401. package/src/shared/__tests__/vertex-adapter.test.ts +1 -1
  402. package/src/shared/attachment-resolver.ts +218 -55
  403. package/src/shared/attachment-zip.ts +281 -0
  404. package/src/shared/connect-backfill.ts +9 -11
  405. package/src/shared/cost-guard.ts +3 -3
  406. package/src/shared/execution-status-writer.ts +5 -5
  407. package/src/shared/extract-structured-output.ts +8 -7
  408. package/src/shared/filereview/__tests__/capture.test.ts +86 -4
  409. package/src/shared/filereview/__tests__/cas-progress.test.ts +2 -1
  410. package/src/shared/filereview/cas-progress.ts +5 -19
  411. package/src/shared/filereview/cas-touched.ts +89 -0
  412. package/src/shared/filereview/index.ts +4 -2
  413. package/src/shared/mcp-resolver.ts +4 -5
  414. package/src/shared/persist-decision.ts +3 -4
  415. package/src/shared/plan-mode-permissions.ts +2 -2
  416. package/src/shared/plan-mode-prompt.ts +1 -1
  417. package/src/shared/prompt-sections.ts +256 -0
  418. package/src/shared/skill-resolver.ts +4 -2
  419. package/src/shared/tool-rounds.ts +48 -0
  420. package/src/shared/tool-row.ts +61 -0
  421. package/src/shared/workspace/__tests__/stigmer-link.test.ts +7 -22
  422. package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +20 -61
  423. package/src/shared/workspace/session-provision.ts +3 -3
  424. package/src/shared/workspace/stigmer-link.ts +3 -3
  425. package/src/shared/workspace/writeback-coordinator.ts +16 -64
  426. package/src/tools/index.ts +1 -1
  427. package/dist/activities/execute-cursor/capture-flow.d.ts +0 -142
  428. package/dist/activities/execute-cursor/capture-flow.js +0 -285
  429. package/dist/activities/execute-cursor/capture-flow.js.map +0 -1
  430. package/dist/activities/execute-cursor/command-provenance.d.ts +0 -48
  431. package/dist/activities/execute-cursor/command-provenance.js +0 -38
  432. package/dist/activities/execute-cursor/command-provenance.js.map +0 -1
  433. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +0 -134
  434. package/dist/activities/execute-deep-agent/attachment-injector.js +0 -386
  435. package/dist/activities/execute-deep-agent/attachment-injector.js.map +0 -1
  436. package/dist/activities/execute-deep-agent/command-provenance.d.ts +0 -61
  437. package/dist/activities/execute-deep-agent/command-provenance.js +0 -72
  438. package/dist/activities/execute-deep-agent/command-provenance.js.map +0 -1
  439. package/dist/activities/execute-deep-agent/environment.d.ts +0 -24
  440. package/dist/activities/execute-deep-agent/environment.js +0 -58
  441. package/dist/activities/execute-deep-agent/environment.js.map +0 -1
  442. package/dist/activities/execute-deep-agent/event-recorder.d.ts +0 -21
  443. package/dist/activities/execute-deep-agent/event-recorder.js +0 -67
  444. package/dist/activities/execute-deep-agent/event-recorder.js.map +0 -1
  445. package/dist/activities/execute-deep-agent/index.d.ts +0 -15
  446. package/dist/activities/execute-deep-agent/index.js +0 -918
  447. package/dist/activities/execute-deep-agent/index.js.map +0 -1
  448. package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -28
  449. package/dist/activities/execute-deep-agent/mcp-gate.js +0 -22
  450. package/dist/activities/execute-deep-agent/mcp-gate.js.map +0 -1
  451. package/dist/activities/execute-deep-agent/post-stream.d.ts +0 -23
  452. package/dist/activities/execute-deep-agent/post-stream.js +0 -71
  453. package/dist/activities/execute-deep-agent/post-stream.js.map +0 -1
  454. package/dist/activities/execute-deep-agent/setup.d.ts +0 -136
  455. package/dist/activities/execute-deep-agent/setup.js +0 -767
  456. package/dist/activities/execute-deep-agent/setup.js.map +0 -1
  457. package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +0 -36
  458. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +0 -56
  459. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +0 -1
  460. package/dist/activities/execute-deep-agent/status-builder.d.ts +0 -93
  461. package/dist/activities/execute-deep-agent/status-builder.js +0 -365
  462. package/dist/activities/execute-deep-agent/status-builder.js.map +0 -1
  463. package/dist/activities/execute-deep-agent/streaming-terminal.d.ts +0 -21
  464. package/dist/activities/execute-deep-agent/streaming-terminal.js +0 -80
  465. package/dist/activities/execute-deep-agent/streaming-terminal.js.map +0 -1
  466. package/dist/activities/execute-deep-agent/streaming-v3.d.ts +0 -13
  467. package/dist/activities/execute-deep-agent/streaming-v3.js +0 -174
  468. package/dist/activities/execute-deep-agent/streaming-v3.js.map +0 -1
  469. package/dist/activities/execute-deep-agent/streaming.d.ts +0 -81
  470. package/dist/activities/execute-deep-agent/streaming.js +0 -160
  471. package/dist/activities/execute-deep-agent/streaming.js.map +0 -1
  472. package/dist/middleware/cost-cap.d.ts +0 -22
  473. package/dist/middleware/cost-cap.js.map +0 -1
  474. package/dist/middleware/graceful-stop.d.ts +0 -17
  475. package/dist/middleware/graceful-stop.js +0 -63
  476. package/dist/middleware/graceful-stop.js.map +0 -1
  477. package/dist/shared/skill-writer.d.ts +0 -75
  478. package/dist/shared/skill-writer.js +0 -207
  479. package/dist/shared/skill-writer.js.map +0 -1
  480. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +0 -1032
  481. package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +0 -240
  482. package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +0 -169
  483. package/src/activities/execute-cursor/capture-flow.ts +0 -379
  484. package/src/activities/execute-cursor/command-provenance.ts +0 -73
  485. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +0 -1161
  486. package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +0 -252
  487. package/src/activities/execute-deep-agent/__tests__/environment.test.ts +0 -108
  488. package/src/activities/execute-deep-agent/__tests__/event-recorder.test.ts +0 -150
  489. package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +0 -226
  490. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -318
  491. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -351
  492. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -293
  493. package/src/activities/execute-deep-agent/__tests__/index.test.ts +0 -99
  494. package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +0 -44
  495. package/src/activities/execute-deep-agent/__tests__/post-stream.test.ts +0 -112
  496. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -358
  497. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +0 -1933
  498. package/src/activities/execute-deep-agent/__tests__/streaming-terminal.test.ts +0 -40
  499. package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +0 -597
  500. package/src/activities/execute-deep-agent/__tests__/streaming.test.ts +0 -508
  501. package/src/activities/execute-deep-agent/attachment-injector.ts +0 -627
  502. package/src/activities/execute-deep-agent/command-provenance.ts +0 -102
  503. package/src/activities/execute-deep-agent/environment.ts +0 -76
  504. package/src/activities/execute-deep-agent/event-recorder.ts +0 -95
  505. package/src/activities/execute-deep-agent/index.ts +0 -1072
  506. package/src/activities/execute-deep-agent/mcp-gate.ts +0 -37
  507. package/src/activities/execute-deep-agent/post-stream.ts +0 -109
  508. package/src/activities/execute-deep-agent/setup.ts +0 -1081
  509. package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +0 -64
  510. package/src/activities/execute-deep-agent/status-builder.ts +0 -481
  511. package/src/activities/execute-deep-agent/streaming-terminal.ts +0 -106
  512. package/src/activities/execute-deep-agent/streaming-v3.ts +0 -277
  513. package/src/activities/execute-deep-agent/streaming.ts +0 -313
  514. package/src/middleware/__tests__/cost-cap.test.ts +0 -192
  515. package/src/middleware/__tests__/graceful-stop.test.ts +0 -105
  516. package/src/middleware/graceful-stop.ts +0 -86
  517. package/src/shared/__tests__/skill-writer.test.ts +0 -372
  518. package/src/shared/skill-writer.ts +0 -266
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Hermetic golden: the simplest possible turn through the whole
3
+ * `ExecuteDeepAgent` activity — one user message in, one assistant message
4
+ * out, no tools, no gate, no workspace entries.
5
+ *
6
+ * Invariant pinned: the activity resolves the four-resource chain, builds the
7
+ * REAL deepagents graph, streams it through the v3 protocol into
8
+ * `V3StatusBuilder`, persists IN_PROGRESS then COMPLETED, and returns the slim
9
+ * status. The golden (`goldens/plain-turn.status.json`) is the smallest
10
+ * status the native harness produces: one AI message with the scripted text
11
+ * and the scripted usage, `startedAt` / `completedAt` on the scripted clock.
12
+ *
13
+ * This file is also the PROBE the M0 plan named: no earlier test drove the
14
+ * real graph through `streamEvents(..., { version: "v3" })`. The scripted
15
+ * model streams, so the events under this golden are the ones a provider
16
+ * produces (`scripted-model.ts` header).
17
+ *
18
+ * Two shapes of the activity's wire contract ride on the same golden, and
19
+ * matching the SAME file is the assertion that they are invisible to the
20
+ * status: the legacy positional `(executionId, threadId)` form the control
21
+ * planes still may send (`shared/activity-input.ts`), and an empty
22
+ * `thread_id` (carried from `index.test.ts`: "handles empty threadId
23
+ * gracefully").
24
+ *
25
+ * Since S3 M2a the activity is the turn runtime over the native adapter, and
26
+ * `streamingUsage` carries the runtime accountant's fields — `model`,
27
+ * `estimatedCostUsd` priced at the registry's rates, the requested tier and
28
+ * thinking mode (Q-M2a-2: one writer of the summary, the runtime). Nothing
29
+ * else in this golden moved with the flip.
30
+ *
31
+ * Regenerate ONLY after a deliberate behavior change:
32
+ * npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
33
+ */
34
+
35
+ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
36
+ import { toJson } from "@bufbuild/protobuf";
37
+ import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
38
+ import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
39
+
40
+ vi.mock("../../../../shared/model-client.js", async () =>
41
+ (await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
42
+ );
43
+ vi.mock("../../../../client/stigmer-client.js", async () =>
44
+ (await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
45
+ );
46
+
47
+ import {
48
+ ScriptedClock,
49
+ createHermeticEnvironment,
50
+ type HermeticEnvironment,
51
+ } from "../../../../__test-utils__/hermetic-activity.js";
52
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
53
+ import {
54
+ FIXTURE,
55
+ beginDeepAgentScenario,
56
+ deepAgentExecutionRecord,
57
+ runDeepAgentTurn,
58
+ type DeepAgentTurnOptions,
59
+ } from "../../__test-utils__/hermetic-deep-agent.js";
60
+ import { recordedModelBuilds } from "../../__test-utils__/scripted-model-module.js";
61
+
62
+ const USER_MESSAGE = "Say hello.";
63
+ const ASSISTANT_TEXT = "Hello from the hermetic fixture agent.";
64
+ const GOLDEN = "./goldens/plain-turn.status.json";
65
+
66
+ describe("ExecuteDeepAgent hermetic — plain turn", () => {
67
+ let env: HermeticEnvironment;
68
+ let registry: ReturnType<typeof stubRegistryFetch>;
69
+ const clock = new ScriptedClock();
70
+
71
+ beforeAll(() => {
72
+ env = createHermeticEnvironment();
73
+ registry = stubRegistryFetch();
74
+ clock.install();
75
+ });
76
+
77
+ afterAll(() => {
78
+ clock.uninstall();
79
+ registry.restore();
80
+ env.dispose();
81
+ });
82
+
83
+ async function runPlainTurn(turn: DeepAgentTurnOptions = {}) {
84
+ clock.reset();
85
+ const record = deepAgentExecutionRecord({ message: USER_MESSAGE });
86
+ const scenario = beginDeepAgentScenario({
87
+ env,
88
+ clock,
89
+ record,
90
+ script: () => ({ turns: [{ text: ASSISTANT_TEXT, usage: { inputTokens: 1_200, outputTokens: 30 } }] }),
91
+ });
92
+ const invocation = await runDeepAgentTurn(scenario, turn);
93
+ return { record, invocation };
94
+ }
95
+
96
+ it("persists IN_PROGRESS then COMPLETED with one assistant message and returns the slim status", async () => {
97
+ // ── Act ──────────────────────────────────────────────────────────────────
98
+ const { record, invocation } = await runPlainTurn();
99
+
100
+ // ── Assert: outcome and phases ───────────────────────────────────────────
101
+ expect(invocation.outcome.kind).toBe("returned");
102
+ const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
103
+ expect(slim.phase).toBe("EXECUTION_COMPLETED");
104
+ expect(record.persistedPhases).toEqual([
105
+ ExecutionPhase.EXECUTION_IN_PROGRESS,
106
+ ExecutionPhase.EXECUTION_COMPLETED,
107
+ ]);
108
+
109
+ // ── Assert: the transcript ───────────────────────────────────────────────
110
+ const final = record.lastFullStatus!;
111
+ const ai = final.messages.filter((m) => m.type === MessageType.MESSAGE_AI);
112
+ expect(ai, "one assistant message, no tool rows").toHaveLength(1);
113
+ expect(ai[0].content).toBe(ASSISTANT_TEXT);
114
+ expect(ai[0].toolCalls).toHaveLength(0);
115
+ expect(final.streamingUsage?.inputTokens).toBe(1_200n);
116
+ expect(final.streamingUsage?.outputTokens).toBe(30n);
117
+
118
+ // ── Assert: hermeticity and what production asked the model client for ──
119
+ expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
120
+ const primaryBuild = recordedModelBuilds()[0];
121
+ expect(primaryBuild?.modelName, "the execution's model, not the default").toBe(FIXTURE.model);
122
+ expect(primaryBuild?.proxyEndpoint, "the OSS posture has no proxy").toBeUndefined();
123
+
124
+ // ── Assert: the golden ───────────────────────────────────────────────────
125
+ const json = JSON.stringify(toJson(AgentExecutionStatusSchema, final), null, 2) + "\n";
126
+ await expect(json).toMatchFileSnapshot(GOLDEN);
127
+ });
128
+
129
+ it("produces the same status from the legacy positional wire shape", async () => {
130
+ const { record, invocation } = await runPlainTurn({ positional: true });
131
+ expect(invocation.outcome.kind).toBe("returned");
132
+ const json = JSON.stringify(toJson(AgentExecutionStatusSchema, record.lastFullStatus!), null, 2) + "\n";
133
+ await expect(json).toMatchFileSnapshot(GOLDEN);
134
+ });
135
+
136
+ it("produces the same status with an empty thread_id", async () => {
137
+ const { record, invocation } = await runPlainTurn({ threadId: "" });
138
+ expect(invocation.outcome.kind).toBe("returned");
139
+ const json = JSON.stringify(toJson(AgentExecutionStatusSchema, record.lastFullStatus!), null, 2) + "\n";
140
+ await expect(json).toMatchFileSnapshot(GOLDEN);
141
+ });
142
+ });
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Hermetic golden: the PLATFORM STOP — the control plane answers a mid-stream
3
+ * persist with `ExecutionControlSignal.STOP`.
4
+ *
5
+ * What the arm does: the record's `controlSignal` answers STOP on the first
6
+ * full write that carries a tool row (the tool-call boundary forces that
7
+ * persist, `persist-decision.ts` `contentDirty`); the runtime's chokepoint
8
+ * reads the signal off the write and aborts the adapter's `stopSignal`; the
9
+ * adapter's loop, which AWAITED that persist, sees the abort before it pulls
10
+ * the next event, cancels the graph run and settles `interrupted`; the
11
+ * runtime's table maps the stop to COMPLETED with `platformStopArm`'s one
12
+ * row, "Execution stopped by the platform.", no `status.error`, and RETURNS.
13
+ *
14
+ * Ruled at Q-S3-3 (a platform STOP is the platform saying "stop spending
15
+ * now"; the runtime's abort is the one stop) and landed at S3 M2a. Until
16
+ * then the orchestrator answered STOP by activating `graceful-stop.ts`,
17
+ * which handed the model one more tool-free round: the transcript carried
18
+ * the model's wrap-up ("Stopping here as asked.") AND the middleware's own
19
+ * notice rendered as the agent's words (F-M0-7), and the run ended
20
+ * COMPLETED with no row. The graceful-stop middleware was deleted at S3 M2b
21
+ * (Q-M2a-4 sequenced it after the legacy loop that activated it); nothing in
22
+ * the graph answers a STOP any more, so the second scripted turn is never
23
+ * reached — this golden was byte-identical across the deletion.
24
+ *
25
+ * Regenerate ONLY after a deliberate behavior change:
26
+ * npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
27
+ */
28
+
29
+ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
30
+ import { toJson } from "@bufbuild/protobuf";
31
+ import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
32
+ import {
33
+ ExecutionControlSignal,
34
+ ExecutionPhase,
35
+ MessageType,
36
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
37
+
38
+ vi.mock("../../../../shared/model-client.js", async () =>
39
+ (await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
40
+ );
41
+ vi.mock("../../../../client/stigmer-client.js", async () =>
42
+ (await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
43
+ );
44
+
45
+ import {
46
+ ScriptedClock,
47
+ createHermeticEnvironment,
48
+ type HermeticEnvironment,
49
+ } from "../../../../__test-utils__/hermetic-activity.js";
50
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
51
+ import {
52
+ beginDeepAgentScenario,
53
+ deepAgentExecutionRecord,
54
+ runDeepAgentTurn,
55
+ } from "../../__test-utils__/hermetic-deep-agent.js";
56
+
57
+ const READ_CALL = { id: "call-hermetic-read-0001", name: "read_file", args: { file_path: "/notes.md" } };
58
+ const WRAP_UP = "Stopping here as asked.";
59
+
60
+ describe("ExecuteDeepAgent hermetic — platform STOP", () => {
61
+ let env: HermeticEnvironment;
62
+ let registry: ReturnType<typeof stubRegistryFetch>;
63
+ const clock = new ScriptedClock();
64
+
65
+ beforeAll(() => {
66
+ env = createHermeticEnvironment();
67
+ registry = stubRegistryFetch();
68
+ clock.install();
69
+ });
70
+
71
+ afterAll(() => {
72
+ clock.uninstall();
73
+ registry.restore();
74
+ env.dispose();
75
+ });
76
+
77
+ it("stops the run at the STOP and completes with the platform-stop row (Q-S3-3)", async () => {
78
+ // ── Arrange ──────────────────────────────────────────────────────────────
79
+ let stopsAnswered = 0;
80
+ const record = deepAgentExecutionRecord({
81
+ message: "Look at my notes.",
82
+ controlSignal: (status) => {
83
+ if (status.messages.some((m) => m.toolCalls.length > 0)) {
84
+ stopsAnswered += 1;
85
+ return ExecutionControlSignal.STOP;
86
+ }
87
+ return ExecutionControlSignal.UNSPECIFIED;
88
+ },
89
+ });
90
+ const scenario = beginDeepAgentScenario({
91
+ env,
92
+ clock,
93
+ record,
94
+ script: () => ({
95
+ turns: [
96
+ { text: "Let me look.", toolCalls: [READ_CALL], usage: { inputTokens: 1_200, outputTokens: 30 } },
97
+ { text: WRAP_UP, usage: { inputTokens: 1_400, outputTokens: 10 } },
98
+ ],
99
+ }),
100
+ });
101
+
102
+ // ── Act ──────────────────────────────────────────────────────────────────
103
+ const invocation = await runDeepAgentTurn(scenario);
104
+
105
+ // ── Assert: the STOP was delivered, and the run stopped there ────────────
106
+ expect(stopsAnswered, "the platform said STOP at least once").toBeGreaterThan(0);
107
+ expect(invocation.outcome.kind, "a platform stop RETURNS").toBe("returned");
108
+ expect((invocation.outcome as { value: Record<string, unknown> }).value.phase).toBe("EXECUTION_COMPLETED");
109
+ expect(record.persistedPhases).toEqual([ExecutionPhase.EXECUTION_IN_PROGRESS, ExecutionPhase.EXECUTION_COMPLETED]);
110
+ const final = record.lastFullStatus!;
111
+ expect(final.error).toBe("");
112
+ expect(final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content)).toEqual([
113
+ "Execution stopped by the platform.",
114
+ ]);
115
+ const ai = final.messages.filter((m) => m.type === MessageType.MESSAGE_AI).map((m) => m.content);
116
+ expect(ai, "no wrap-up round and no injected notice: the run stopped at the STOP").toEqual(["Let me look.", ""]);
117
+ expect(ai).not.toContain(WRAP_UP);
118
+
119
+ // ── Assert: hermeticity ──────────────────────────────────────────────────
120
+ expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
121
+
122
+ // ── Assert: the golden ───────────────────────────────────────────────────
123
+ const json = JSON.stringify(toJson(AgentExecutionStatusSchema, final), null, 2) + "\n";
124
+ await expect(json).toMatchFileSnapshot("./goldens/platform-stop.status.json");
125
+ });
126
+ });
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Hermetic golden: the TOOL-CALL BUDGET — `max_tool_rounds` exhausted by a
3
+ * model that keeps calling tools.
4
+ *
5
+ * What the arm does: `max_tool_rounds = 10` (the clamp floor,
6
+ * `shared/tool-rounds.ts` MIN_TOOL_ROUNDS) becomes LangGraph's
7
+ * `recursionLimit = 60` (SUPER_STEPS_PER_ROUND); the script proposes a
8
+ * DISTINCT `read_file` every round (distinct ids and paths, so the
9
+ * loop-detection middleware's "repetitive pattern" warning does not end the
10
+ * run first); the graph throws `GraphRecursionError`; the adapter's turn
11
+ * classifies it as the `tool_call_limit` outcome (`shared/tool-rounds.ts`
12
+ * `isGraphRecursionError`), and the runtime's `toolCallLimitArm` writes
13
+ * TERMINATED with the cross-repo prefix `TOOL_CALL_LIMIT_ERROR_PREFIX`
14
+ * (matched with `startsWith` by stigmer-cloud's `reply-extractor.ts`) and
15
+ * its row, PERSISTS it, and returns the slim.
16
+ *
17
+ * Ruled at Q-S3-6 and landed at S3 M2a. Until then the orchestrator RETURNED
18
+ * the TERMINATED status but never PERSISTED it (S3 M0 finding F-M0-4, a
19
+ * production defect): the last status the control plane held was the
20
+ * stream's mid-run IN_PROGRESS with no error, and only the activity's return
21
+ * value carried the truth. The golden
22
+ * (`goldens/recursion-limit.persisted.status.json`) now records the
23
+ * TERMINATED status the control plane holds, which is what that fix changed
24
+ * on purpose.
25
+ *
26
+ * Also visible here, F-M0-1 at scale: every tool row of the run sits on ONE
27
+ * empty AI message, because `ensureAiMessageForToolCall("")` creates it once
28
+ * and `currentAiMessage[""]` then catches every later row.
29
+ *
30
+ * How many rounds fit is the middleware stack's shape, not the knob's
31
+ * (S3 M2b, owner ruling 2026-09-13 on F-M2b-26): LangChain makes every
32
+ * middleware hook its own graph node, and `max_tool_rounds` becomes a
33
+ * super-step budget at the ×6 floor estimate, so a node fewer per round
34
+ * means more rounds within the same 60 steps. When `graceful-stop.ts` (an
35
+ * `afterModel` node) was deleted with Q-S3-3, this golden went from 11 tool
36
+ * calls to 13 before TERMINATED — the only hunk, the copy unchanged. That the
37
+ * knob counts super-steps and not rounds is recorded as an S5 design item
38
+ * (a round counter in the budget middleware would make it mean what it
39
+ * says); this file pins what the stack delivers today.
40
+ *
41
+ * Regenerate ONLY after a deliberate behavior change:
42
+ * npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
43
+ */
44
+
45
+ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
46
+ import { toJson } from "@bufbuild/protobuf";
47
+ import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
48
+ import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
49
+
50
+ vi.mock("../../../../shared/model-client.js", async () =>
51
+ (await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
52
+ );
53
+ vi.mock("../../../../client/stigmer-client.js", async () =>
54
+ (await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
55
+ );
56
+
57
+ import {
58
+ ScriptedClock,
59
+ createHermeticEnvironment,
60
+ type HermeticEnvironment,
61
+ } from "../../../../__test-utils__/hermetic-activity.js";
62
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
63
+ import { MIN_TOOL_ROUNDS } from "../../../../shared/tool-rounds.js";
64
+ import {
65
+ beginDeepAgentScenario,
66
+ deepAgentExecutionRecord,
67
+ runDeepAgentTurn,
68
+ } from "../../__test-utils__/hermetic-deep-agent.js";
69
+ import { TOOL_CALL_LIMIT_ERROR_PREFIX } from "../../../../shared/tool-rounds.js";
70
+
71
+ /** More rounds than the budget allows; the graph stops the script, not the other way round. */
72
+ const SCRIPTED_ROUNDS = 40;
73
+
74
+ describe("ExecuteDeepAgent hermetic — tool-call budget exhausted", () => {
75
+ let env: HermeticEnvironment;
76
+ let registry: ReturnType<typeof stubRegistryFetch>;
77
+ const clock = new ScriptedClock();
78
+
79
+ beforeAll(() => {
80
+ env = createHermeticEnvironment();
81
+ registry = stubRegistryFetch();
82
+ clock.install();
83
+ });
84
+
85
+ afterAll(() => {
86
+ clock.uninstall();
87
+ registry.restore();
88
+ env.dispose();
89
+ });
90
+
91
+ it("returns TERMINATED with the cross-repo prefix, and persists nothing past IN_PROGRESS (F-M0-4)", async () => {
92
+ // ── Arrange ──────────────────────────────────────────────────────────────
93
+ const record = deepAgentExecutionRecord({ message: "Keep reading files.", maxToolRounds: MIN_TOOL_ROUNDS });
94
+ const scenario = beginDeepAgentScenario({
95
+ env,
96
+ clock,
97
+ record,
98
+ script: () => ({
99
+ turns: Array.from({ length: SCRIPTED_ROUNDS }, (_, i) => ({
100
+ text: `Reading file ${i}.`,
101
+ toolCalls: [{ id: `call-hermetic-loop-${String(i).padStart(4, "0")}`, name: "read_file", args: { file_path: `/f${i}.md` } }],
102
+ usage: { inputTokens: 1_000, outputTokens: 20 },
103
+ })),
104
+ }),
105
+ });
106
+
107
+ // ── Act ──────────────────────────────────────────────────────────────────
108
+ const invocation = await runDeepAgentTurn(scenario);
109
+
110
+ // ── Assert: the slim the workflow receives ───────────────────────────────
111
+ expect(invocation.outcome.kind).toBe("returned");
112
+ const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
113
+ expect(slim.phase).toBe("EXECUTION_TERMINATED");
114
+ expect(String(slim.error).startsWith(TOOL_CALL_LIMIT_ERROR_PREFIX), "the cross-repo prefix").toBe(true);
115
+
116
+ // ── Assert: what the control plane holds (F-M0-4 closed) ─────────────────
117
+ expect(record.persistedPhases, "the TERMINATED terminal is persisted").toEqual([
118
+ ExecutionPhase.EXECUTION_IN_PROGRESS,
119
+ ExecutionPhase.EXECUTION_TERMINATED,
120
+ ]);
121
+ const persisted = record.lastFullStatus!;
122
+ expect(String(persisted.error).startsWith(TOOL_CALL_LIMIT_ERROR_PREFIX), "the persisted error carries the prefix").toBe(true);
123
+ expect(persisted.error, "the event count left the copy (Q-S3-6)").not.toMatch(/\d+ events?/);
124
+ expect(persisted.completedAt).not.toBe("");
125
+ const rows = record.toolCalls();
126
+ expect(rows.length, "fewer rounds ran than were scripted: the budget stopped the graph").toBeLessThan(SCRIPTED_ROUNDS);
127
+ expect(rows.length).toBeGreaterThanOrEqual(MIN_TOOL_ROUNDS);
128
+ const rowHosts = persisted.messages.filter((m) => m.type === MessageType.MESSAGE_AI && m.toolCalls.length > 0);
129
+ expect(rowHosts, "F-M0-1: every row on one empty AI message").toHaveLength(1);
130
+ expect(rowHosts[0].content).toBe("");
131
+
132
+ // ── Assert: hermeticity ──────────────────────────────────────────────────
133
+ expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
134
+
135
+ // ── Assert: the golden ───────────────────────────────────────────────────
136
+ const json = JSON.stringify(toJson(AgentExecutionStatusSchema, persisted), null, 2) + "\n";
137
+ await expect(json).toMatchFileSnapshot("./goldens/recursion-limit.persisted.status.json");
138
+ });
139
+ });
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Hermetic golden: a RESOLUTION ERROR — the control plane rejects a read the
3
+ * setup depends on (`client.getAgent`) before any graph exists.
4
+ *
5
+ * Invariant pinned: the runtime's blueprint phase throws, the runtime's
6
+ * catch takes its generic-error arm (`terminal-table.ts` `unexpectedErrorArm`),
7
+ * persists ONE EXECUTION_FAILED status carrying
8
+ * `status.error = "Execution failed: [Error] <message>"` and two system rows
9
+ * — the boilerplate "Internal system error occurred. Please contact support
10
+ * if this issue persists." and `"Error details: [Error] <message>"` — and
11
+ * RETURNS the slim status (the workflow reads the phase; a throw would make
12
+ * Temporal retry a deterministic failure). Nothing streamed, no lock taken
13
+ * (the fault precedes the lock phase), no artifacts.
14
+ *
15
+ * The row shape is one of Q-S3-7's ruled alignments, landed at S3 M2a: the
16
+ * orchestrator wrote one row `"Error: [Error] <message>"`; the runtime's arm
17
+ * writes the boilerplate plus the details row. `status.error` itself did
18
+ * not move (the conformance suite pins it). The setup labels are the
19
+ * runtime's resolution phases' (a stated default of the M2a plan).
20
+ *
21
+ * Carried from `index.test.ts` ("returns EXECUTION_FAILED status when setup
22
+ * fails", "includes error message in failed status", "always returns a
23
+ * serializable result").
24
+ *
25
+ * Regenerate ONLY after a deliberate behavior change:
26
+ * npx vitest run src/activities/execute-deep-agent/__tests__/hermetic -u
27
+ */
28
+
29
+ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
30
+ import { toJson } from "@bufbuild/protobuf";
31
+ import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
32
+ import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
33
+
34
+ vi.mock("../../../../shared/model-client.js", async () =>
35
+ (await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
36
+ );
37
+ vi.mock("../../../../client/stigmer-client.js", async () =>
38
+ (await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
39
+ );
40
+
41
+ import {
42
+ ScriptedClock,
43
+ createHermeticEnvironment,
44
+ type HermeticEnvironment,
45
+ } from "../../../../__test-utils__/hermetic-activity.js";
46
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
47
+ import {
48
+ beginDeepAgentScenario,
49
+ deepAgentExecutionRecord,
50
+ runDeepAgentTurn,
51
+ } from "../../__test-utils__/hermetic-deep-agent.js";
52
+ import { recordedModelBuilds } from "../../__test-utils__/scripted-model-module.js";
53
+
54
+ const CONTROL_PLANE_FAULT = "hermetic fault injected at getAgent";
55
+
56
+ describe("ExecuteDeepAgent hermetic — resolution error", () => {
57
+ let env: HermeticEnvironment;
58
+ let registry: ReturnType<typeof stubRegistryFetch>;
59
+ const clock = new ScriptedClock();
60
+
61
+ beforeAll(() => {
62
+ env = createHermeticEnvironment();
63
+ registry = stubRegistryFetch();
64
+ clock.install();
65
+ });
66
+
67
+ afterAll(() => {
68
+ clock.uninstall();
69
+ registry.restore();
70
+ env.dispose();
71
+ });
72
+
73
+ it("fails with the fault's message in status.error and one system row, and returns", async () => {
74
+ // ── Arrange ──────────────────────────────────────────────────────────────
75
+ const record = deepAgentExecutionRecord({ message: "Never reaches a model." });
76
+ const scenario = beginDeepAgentScenario({
77
+ env,
78
+ clock,
79
+ record,
80
+ script: () => {
81
+ throw new Error("the model must never be asked on a resolution failure");
82
+ },
83
+ clientOverrides: {
84
+ getAgent: vi.fn(async () => {
85
+ throw new Error(CONTROL_PLANE_FAULT);
86
+ }),
87
+ },
88
+ });
89
+
90
+ // ── Act ──────────────────────────────────────────────────────────────────
91
+ const invocation = await runDeepAgentTurn(scenario);
92
+
93
+ // ── Assert: outcome and phases ───────────────────────────────────────────
94
+ expect(invocation.outcome.kind, "a deterministic failure RETURNS; a retry would fail the same way").toBe(
95
+ "returned",
96
+ );
97
+ const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
98
+ expect(slim.phase).toBe("EXECUTION_FAILED");
99
+ expect(() => JSON.stringify(slim), "the return is serializable").not.toThrow();
100
+ expect(record.persistedPhases, "the one and only full persist").toEqual([ExecutionPhase.EXECUTION_FAILED]);
101
+
102
+ // ── Assert: the copy ─────────────────────────────────────────────────────
103
+ const final = record.lastFullStatus!;
104
+ expect(final.error).toBe(`Execution failed: [Error] ${CONTROL_PLANE_FAULT}`);
105
+ expect(final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content)).toEqual([
106
+ "Internal system error occurred. Please contact support if this issue persists.",
107
+ `Error details: [Error] ${CONTROL_PLANE_FAULT}`,
108
+ ]);
109
+ expect(final.messages, "the two system rows are the whole transcript").toHaveLength(2);
110
+
111
+ // ── Assert: nothing past the fault ───────────────────────────────────────
112
+ expect(recordedModelBuilds(), "no model was built").toHaveLength(0);
113
+ expect(record.setupProgress).toEqual(["Fetching execution", "Resolving agent blueprint"]);
114
+
115
+ // ── Assert: hermeticity ──────────────────────────────────────────────────
116
+ expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
117
+
118
+ // ── Assert: the golden ───────────────────────────────────────────────────
119
+ const json = JSON.stringify(toJson(AgentExecutionStatusSchema, final), null, 2) + "\n";
120
+ await expect(json).toMatchFileSnapshot("./goldens/resolution-error.status.json");
121
+ });
122
+ });