@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,152 @@
1
+ /**
2
+ * Hermetic scenario: WORKSPACE LOCK TIMEOUT — a turn that cannot acquire its
3
+ * workspace within the configured wait fails with an actionable reason and
4
+ * RETURNS.
5
+ *
6
+ * Invariant pinned: the activity serializes on the workspace root
7
+ * (`shared/workspace/workspace-lock.ts`); while another turn holds the lock it
8
+ * reports a visible waiting state and heartbeats; past
9
+ * `Config.workspaceLockTimeoutMs` it maps `WorkspaceLockTimeoutError` to
10
+ * EXECUTION_FAILED with the lock's own message (which names the directory)
11
+ * and one system row, persists ONCE, and returns — a Temporal retry would only
12
+ * queue behind the same holder.
13
+ *
14
+ * The order, ruled at Q-S3-8 and landed at S3 M2a: the runtime takes the
15
+ * lock right after provisioning the workspace, BEFORE the tool surface, the
16
+ * skills, the attachments and the graph — so a turn that cannot have the
17
+ * tree builds no model and compiles no sub-agent. Until then the
18
+ * orchestrator took the lock AFTER the whole of `performSetup`. The setup
19
+ * labels are the runtime's resolution phases'; the adapter's own labels
20
+ * ("Connecting tools…", "Configuring sub-agents…", "Creating agent…") never
21
+ * appear, because the turn ends before the adapter runs.
22
+ *
23
+ * Why this is the one terminal arm WITHOUT a file golden (owner ruling,
24
+ * 2026-09-11, entry 20260911.03 M0; carried for native): the wire copy embeds
25
+ * the absolute workspace path, a per-run temp directory. The S0 rule is to
26
+ * control a volatile source at its origin or escalate — never redact — so
27
+ * this scenario pins every byte the path does not touch with explicit
28
+ * assertions and builds the expected message with the SAME error class over
29
+ * the real resolved path.
30
+ *
31
+ * Determinism: the lock wait is `waitedMs + pollIntervalMs > timeoutMs`, so a
32
+ * timeout below the 1 s poll interval fails on the FIRST contended attempt with
33
+ * no sleep; `waitedMs` is measured on the scripted clock, so it is 0.
34
+ *
35
+ * Regenerate: nothing to regenerate — no snapshot.
36
+ */
37
+
38
+ import { mkdirSync } from "node:fs";
39
+ import { realpath } from "node:fs/promises";
40
+ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
41
+ import { ExecutionPhase, MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
42
+
43
+ vi.mock("../../../../shared/model-client.js", async () =>
44
+ (await import("../../__test-utils__/scripted-model-module.js")).scriptedModelClientModule(),
45
+ );
46
+ vi.mock("../../../../client/stigmer-client.js", async () =>
47
+ (await import("../../../../__test-utils__/hermetic-activity.js")).hermeticStigmerClientModule(),
48
+ );
49
+
50
+ import {
51
+ ScriptedClock,
52
+ createHermeticEnvironment,
53
+ type HermeticEnvironment,
54
+ } from "../../../../__test-utils__/hermetic-activity.js";
55
+ import { stubRegistryFetch } from "../../../../__test-utils__/model-registry-fixture.js";
56
+ import {
57
+ WorkspaceLockTimeoutError,
58
+ acquireWorkspaceLock,
59
+ type ReleaseWorkspaceLock,
60
+ } from "../../../../shared/workspace/workspace-lock.js";
61
+ import {
62
+ beginDeepAgentScenario,
63
+ deepAgentExecutionRecord,
64
+ runDeepAgentTurn,
65
+ sessionWorkspaceDir,
66
+ } from "../../__test-utils__/hermetic-deep-agent.js";
67
+ import { recordedModelBuilds } from "../../__test-utils__/scripted-model-module.js";
68
+
69
+ /** Below the lock's 1 s poll interval: the first contended attempt times out. */
70
+ const LOCK_TIMEOUT_MS = 250;
71
+
72
+ describe("ExecuteDeepAgent hermetic — workspace lock timeout", () => {
73
+ let env: HermeticEnvironment;
74
+ let registry: ReturnType<typeof stubRegistryFetch>;
75
+ const clock = new ScriptedClock();
76
+
77
+ beforeAll(() => {
78
+ env = createHermeticEnvironment();
79
+ registry = stubRegistryFetch();
80
+ clock.install();
81
+ });
82
+
83
+ afterAll(() => {
84
+ clock.uninstall();
85
+ registry.restore();
86
+ env.dispose();
87
+ });
88
+
89
+ it("fails the turn with the lock's message when another turn holds the workspace", async () => {
90
+ // ── Arrange: another turn already holds this session's workspace ─────────
91
+ const record = deepAgentExecutionRecord({ message: "Never streams." });
92
+ const scenario = beginDeepAgentScenario({
93
+ env,
94
+ clock,
95
+ record,
96
+ script: () => {
97
+ throw new Error("the model must never be asked while the workspace is held");
98
+ },
99
+ config: { workspaceLockTimeoutMs: LOCK_TIMEOUT_MS },
100
+ });
101
+ // Created AFTER the scenario begins (which clears the session workspace)
102
+ // and BEFORE either side locks it, so both resolve the same realpath
103
+ // (macOS's /var -> /private/var) and contend on ONE key.
104
+ const workspaceDir = sessionWorkspaceDir(env);
105
+ mkdirSync(workspaceDir, { recursive: true });
106
+ const resolvedDir = await realpath(workspaceDir);
107
+ let releaseHeldLock: ReleaseWorkspaceLock | undefined = await acquireWorkspaceLock(workspaceDir);
108
+
109
+ try {
110
+ // ── Act ────────────────────────────────────────────────────────────────
111
+ const invocation = await runDeepAgentTurn(scenario);
112
+
113
+ // ── Assert: outcome and phases ─────────────────────────────────────────
114
+ expect(invocation.outcome.kind, "a lock timeout RETURNS — a retry would queue behind the same holder").toBe(
115
+ "returned",
116
+ );
117
+ const slim = (invocation.outcome as { value: Record<string, unknown> }).value;
118
+ expect(slim.phase).toBe("EXECUTION_FAILED");
119
+ expect(record.persistedPhases, "the one and only full persist").toEqual([ExecutionPhase.EXECUTION_FAILED]);
120
+
121
+ // ── Assert: the copy, built with the same class over the real path ─────
122
+ const expectedMessage = new WorkspaceLockTimeoutError(resolvedDir, 0).message;
123
+ const final = record.lastFullStatus!;
124
+ expect(final.error).toBe(expectedMessage);
125
+ expect(final.completedAt).not.toBe("");
126
+ expect(final.messages.filter((m) => m.type === MessageType.MESSAGE_SYSTEM).map((m) => m.content)).toEqual([
127
+ `Execution failed: ${expectedMessage}`,
128
+ ]);
129
+ expect(final.messages, "the system row is the whole transcript").toHaveLength(1);
130
+
131
+ // ── Assert: the order — the lock is tried before the tool surface ─────
132
+ expect(record.setupProgress).toEqual([
133
+ "Fetching execution",
134
+ "Resolving agent blueprint",
135
+ "Resolving environment",
136
+ "Provisioning workspace",
137
+ "Waiting for workspace — in use by another session",
138
+ ]);
139
+ expect(recordedModelBuilds(), "no model is built for a turn that cannot have the tree (Q-S3-8)").toHaveLength(0);
140
+
141
+ // ── Assert: hermeticity ────────────────────────────────────────────────
142
+ expect(registry.urls.every((u) => u.includes("/model-registry"))).toBe(true);
143
+ // The runtime's heartbeat posture (Q-S3-8, parent Q8): every resolution
144
+ // phase pulses on entry and the terminal write pulses once, so a turn
145
+ // that ends at the lock has heartbeated before any stream existed.
146
+ expect(invocation.heartbeats.length, "the runtime heartbeats through resolution").toBeGreaterThan(0);
147
+ } finally {
148
+ await releaseHeldLock?.();
149
+ releaseHeldLock = undefined;
150
+ }
151
+ });
152
+ });
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from "vitest";
2
2
  import { Command } from "@langchain/langgraph";
3
- import { resolveResumeInput, reconcileNonExecutingDecisions, reconcileUnattendedSkips } from "../hitl.js";
3
+ import { detectPendingInterrupts, resolveResumeInput, reconcileUnattendedSkips } from "../hitl.js";
4
4
  import { ApprovalAction, ApprovalPolicySource, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
5
5
  import { create } from "@bufbuild/protobuf";
6
6
  import {
@@ -8,50 +8,19 @@ import {
8
8
  ToolCallSchema,
9
9
  } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
10
10
  import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
11
- import { MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
12
- import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
13
11
  import type { GraphStateSnapshot } from "../hitl.js";
14
12
 
15
- function makeExecution(
16
- toolCalls: Array<{
17
- id: string;
18
- status: ToolCallStatus;
19
- approvalAction: ApprovalAction;
20
- }>,
21
- ): AgentExecution {
22
- const msg = create(AgentMessageSchema, {
23
- type: MessageType.MESSAGE_AI,
24
- content: "test",
25
- toolCalls: toolCalls.map(tc =>
26
- create(ToolCallSchema, {
27
- id: tc.id,
28
- name: "test_tool",
29
- status: tc.status,
30
- approvalAction: tc.approvalAction,
31
- }),
32
- ),
33
- });
34
-
35
- return {
36
- $typeName: "ai.stigmer.agentic.agentexecution.v1.AgentExecution",
37
- $unknown: undefined,
38
- metadata: undefined,
39
- spec: {
40
- $typeName: "ai.stigmer.agentic.agentexecution.v1.AgentExecutionSpec",
41
- $unknown: undefined,
42
- sessionId: "session-1",
43
- agentId: "agent-1",
44
- message: "test message",
45
- executionConfig: undefined,
46
- workspaceFileRefs: [],
47
- callbackToken: new Uint8Array(),
48
- autoApproveAll: false,
49
- parentWorkflowId: "",
50
- },
51
- status: create(AgentExecutionStatusSchema, {
52
- messages: [msg],
53
- }),
54
- } as unknown as AgentExecution;
13
+ /** The runtime's reading of the adjudicated rows (`approvalDecisionsOf`): a decision per WAITING tool-call id. */
14
+ function makeDecisions(
15
+ toolCalls: Array<{ id: string; status: ToolCallStatus; approvalAction: ApprovalAction }>,
16
+ ): ReadonlyMap<string, ApprovalAction> {
17
+ const decisions = new Map<string, ApprovalAction>();
18
+ for (const tc of toolCalls) {
19
+ if (tc.status === ToolCallStatus.TOOL_CALL_WAITING_APPROVAL && tc.approvalAction !== ApprovalAction.UNSPECIFIED) {
20
+ decisions.set(tc.id, tc.approvalAction);
21
+ }
22
+ }
23
+ return decisions;
55
24
  }
56
25
 
57
26
  function makeGraphState(
@@ -70,29 +39,29 @@ function makeGraphState(
70
39
  }
71
40
 
72
41
  describe("resolveResumeInput", () => {
73
- it("reports not-a-resume when no interrupts exist (caller falls back to setup.langgraphInput)", () => {
74
- const execution = makeExecution([]);
42
+ it("reports not-a-resume when no interrupts exist (the caller sends the turn's user message)", () => {
43
+ const decisions = makeDecisions([]);
75
44
  const state: GraphStateSnapshot = { values: {}, tasks: [] };
76
45
 
77
- const result = resolveResumeInput(execution, state);
46
+ const result = resolveResumeInput(decisions, state);
78
47
 
79
48
  expect(result.isResumeFromApproval).toBe(false);
80
49
  // No graphInput on this branch — the turn's user message has exactly ONE
81
- // construction site (setup.langgraphInput), never a second copy here.
50
+ // construction site (the caller's), never a second copy here.
82
51
  expect("graphInput" in result).toBe(false);
83
52
  });
84
53
 
85
54
  it("reports not-a-resume when interrupts exist but no decisions", () => {
86
- const execution = makeExecution([]);
55
+ const decisions = makeDecisions([]);
87
56
  const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
88
57
 
89
- const result = resolveResumeInput(execution, state);
58
+ const result = resolveResumeInput(decisions, state);
90
59
 
91
60
  expect(result.isResumeFromApproval).toBe(false);
92
61
  });
93
62
 
94
63
  it("builds Command(resume) when interrupts match decisions", () => {
95
- const execution = makeExecution([{
64
+ const decisions = makeDecisions([{
96
65
  id: "call-1",
97
66
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
98
67
  approvalAction: ApprovalAction.APPROVE,
@@ -100,14 +69,14 @@ describe("resolveResumeInput", () => {
100
69
 
101
70
  const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
102
71
 
103
- const result = resolveResumeInput(execution, state);
72
+ const result = resolveResumeInput(decisions, state);
104
73
 
105
74
  if (!result.isResumeFromApproval) throw new Error("expected an approval resume");
106
75
  expect(result.graphInput).toBeInstanceOf(Command);
107
76
  });
108
77
 
109
78
  it("builds a resume Command for a REJECT decision (denies the tool, does not fail the run)", () => {
110
- const execution = makeExecution([{
79
+ const decisions = makeDecisions([{
111
80
  id: "call-1",
112
81
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
113
82
  approvalAction: ApprovalAction.REJECT,
@@ -115,7 +84,7 @@ describe("resolveResumeInput", () => {
115
84
 
116
85
  const state = makeGraphState([{ taskId: "task-1", toolCallId: "call-1" }]);
117
86
 
118
- const result = resolveResumeInput(execution, state);
87
+ const result = resolveResumeInput(decisions, state);
119
88
 
120
89
  // REJECT resumes the gate like any other decision — the gate returns a
121
90
  // denial ToolMessage and the run continues. There is no execution-level
@@ -126,7 +95,7 @@ describe("resolveResumeInput", () => {
126
95
  });
127
96
 
128
97
  it("handles multiple interrupts with mixed decisions", () => {
129
- const execution = makeExecution([
98
+ const decisions = makeDecisions([
130
99
  {
131
100
  id: "call-1",
132
101
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
@@ -144,13 +113,13 @@ describe("resolveResumeInput", () => {
144
113
  { taskId: "task-2", toolCallId: "call-2" },
145
114
  ]);
146
115
 
147
- const result = resolveResumeInput(execution, state);
116
+ const result = resolveResumeInput(decisions, state);
148
117
 
149
118
  expect(result.isResumeFromApproval).toBe(true);
150
119
  });
151
120
 
152
121
  it("skips already-resumed interrupts", () => {
153
- const execution = makeExecution([{
122
+ const decisions = makeDecisions([{
154
123
  id: "call-1",
155
124
  status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
156
125
  approvalAction: ApprovalAction.APPROVE,
@@ -160,82 +129,41 @@ describe("resolveResumeInput", () => {
160
129
  { taskId: "task-1", toolCallId: "call-1", hasResume: true },
161
130
  ]);
162
131
 
163
- const result = resolveResumeInput(execution, state);
132
+ const result = resolveResumeInput(decisions, state);
164
133
 
165
134
  expect(result.isResumeFromApproval).toBe(false);
166
135
  });
167
136
  });
168
137
 
169
- describe("reconcileNonExecutingDecisions", () => {
170
- function statusWith(
171
- toolCalls: Array<{ id: string; status: ToolCallStatus; approvalAction: ApprovalAction }>,
172
- ) {
173
- return create(AgentExecutionStatusSchema, {
174
- messages: [
175
- create(AgentMessageSchema, {
176
- toolCalls: toolCalls.map(tc =>
177
- create(ToolCallSchema, {
178
- id: tc.id,
179
- name: "test_tool",
180
- status: tc.status,
181
- approvalAction: tc.approvalAction,
182
- }),
183
- ),
184
- }),
138
+ describe("detectPendingInterrupts", () => {
139
+ it("normalizes each un-resumed interrupt into a pending approval and skips resumed ones", () => {
140
+ const state: GraphStateSnapshot = {
141
+ values: {},
142
+ tasks: [
143
+ {
144
+ id: "task-1",
145
+ interrupts: [{
146
+ value: { tool_call_id: "call-1", tool_name: "shell", mcp_server_slug: "", message: "Run it?", policy_source: "classifier_default" },
147
+ }],
148
+ },
149
+ {
150
+ id: "task-2",
151
+ interrupts: [{ value: { tool_call_id: "call-2", tool_name: "write_file", message: "Write?" }, resumeValue: { action: "approve" } }],
152
+ },
185
153
  ],
186
- });
187
- }
154
+ };
188
155
 
189
- it("terminalizes a REJECT decision to SKIPPED with a reason (does not FAIL)", () => {
190
- const status = statusWith([{
191
- id: "call-reject",
192
- status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
193
- approvalAction: ApprovalAction.REJECT,
194
- }]);
195
-
196
- reconcileNonExecutingDecisions(status);
197
-
198
- const tc = status.messages[0].toolCalls[0];
199
- expect(tc.status).toBe(ToolCallStatus.TOOL_CALL_SKIPPED);
200
- expect(tc.error).toContain("Rejected by user");
201
- // The REJECT decision is preserved so the audit trail stays honest.
202
- expect(tc.approvalAction).toBe(ApprovalAction.REJECT);
203
- });
204
-
205
- it("terminalizes a SKIP decision to SKIPPED (fixes the stuck-WAITING for skip too)", () => {
206
- const status = statusWith([{
207
- id: "call-skip",
208
- status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
209
- approvalAction: ApprovalAction.SKIP,
210
- }]);
211
-
212
- reconcileNonExecutingDecisions(status);
213
-
214
- expect(status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_SKIPPED);
215
- });
216
-
217
- it("leaves APPROVE / APPROVE_ALL untouched (the tool executes)", () => {
218
- const status = statusWith([
219
- { id: "call-approve", status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL, approvalAction: ApprovalAction.APPROVE },
220
- { id: "call-approve-all", status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL, approvalAction: ApprovalAction.APPROVE_ALL },
156
+ expect(detectPendingInterrupts(state)).toEqual([
157
+ { toolCallId: "call-1", toolName: "shell", mcpServerSlug: "", message: "Run it?", policySource: "classifier_default" },
221
158
  ]);
222
-
223
- reconcileNonExecutingDecisions(status);
224
-
225
- // Still WAITING — real tool events (not this reconciler) terminalize them.
226
- expect(status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
227
- expect(status.messages[0].toolCalls[1].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
228
159
  });
229
160
 
230
- it("is a no-op when there are no decided tool calls", () => {
231
- const status = statusWith([{
232
- id: "call-pending",
233
- status: ToolCallStatus.TOOL_CALL_WAITING_APPROVAL,
234
- approvalAction: ApprovalAction.UNSPECIFIED,
235
- }]);
236
-
237
- expect(() => reconcileNonExecutingDecisions(status)).not.toThrow();
238
- expect(status.messages[0].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
161
+ it("reads an absent policy source as undefined", () => {
162
+ const state: GraphStateSnapshot = {
163
+ values: {},
164
+ tasks: [{ id: "task-1", interrupts: [{ value: { tool_call_id: "call-1", tool_name: "shell", message: "Run it?" } }] }],
165
+ };
166
+ expect(detectPendingInterrupts(state)[0].policySource).toBeUndefined();
239
167
  });
240
168
  });
241
169
 
@@ -7,14 +7,16 @@ import { create } from "@bufbuild/protobuf";
7
7
  import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
8
8
  import { ExecutionArtifactKind } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
9
9
  import { InlinePublisher } from "../inline-publisher.js";
10
- import { StatusBuilder } from "../status-builder.js";
10
+ import { V3StatusBuilder } from "../v3-status-builder.js";
11
11
  import { LocalWorkspaceBackend } from "../../../shared/workspace/local-backend.js";
12
12
  import type { ArtifactStorage } from "../../../shared/artifact-storage.js";
13
13
  import { makeInMemoryArtifactStorage } from "../../../__test-utils__/fake-artifact-storage.js";
14
14
  import type { WorkspaceBackend } from "../../../shared/workspace/types.js";
15
15
 
16
- function makeStatusBuilder(): StatusBuilder {
17
- return new StatusBuilder("exec-test", create(AgentExecutionStatusSchema, {}));
16
+ // The publisher writes artifacts through the transcript builder's
17
+ // `ExecutionStatusWriter` face (`addArtifact`); the one builder since S3 M2b.
18
+ function makeStatusBuilder(): V3StatusBuilder {
19
+ return new V3StatusBuilder("exec-test", create(AgentExecutionStatusSchema, {}));
18
20
  }
19
21
 
20
22
  function mockWorkspaceBackend(files: Record<string, string>): WorkspaceBackend {
@@ -53,7 +55,7 @@ function sha256(content: string): string {
53
55
  }
54
56
 
55
57
  describe("InlinePublisher", () => {
56
- let sb: StatusBuilder;
58
+ let sb: V3StatusBuilder;
57
59
  let storage: ReturnType<typeof mockArtifactStorage>;
58
60
  let backend: WorkspaceBackend;
59
61
  let publisher: InlinePublisher;
@@ -207,7 +209,7 @@ describe("InlinePublisher with LocalWorkspaceBackend (disk-backed)", () => {
207
209
  await mkdir(join(dir, "src"), { recursive: true });
208
210
  await writeFile(join(dir, "src/app.ts"), "export const x = 42;", "utf-8");
209
211
 
210
- const sb = new StatusBuilder("exec-disk", create(AgentExecutionStatusSchema, {}));
212
+ const sb = new V3StatusBuilder("exec-disk", create(AgentExecutionStatusSchema, {}));
211
213
  const storage = mockArtifactStorage();
212
214
  const backend = new LocalWorkspaceBackend(dir);
213
215
 
@@ -235,7 +237,7 @@ describe("InlinePublisher with LocalWorkspaceBackend (disk-backed)", () => {
235
237
  const dir = join(tmpdir(), `stigmer-publisher-test-${Date.now()}`);
236
238
  await mkdir(dir, { recursive: true });
237
239
 
238
- const sb = new StatusBuilder("exec-miss", create(AgentExecutionStatusSchema, {}));
240
+ const sb = new V3StatusBuilder("exec-miss", create(AgentExecutionStatusSchema, {}));
239
241
  const storage = mockArtifactStorage();
240
242
  const backend = new LocalWorkspaceBackend(dir);
241
243
 
@@ -14,7 +14,7 @@
14
14
  * the workspace — an out-of-root name is simply nonexistent, and the
15
15
  * `.stigmer` symlink keeps platform-dir reads addressable in-root.
16
16
  *
17
- * The graph here is composed exactly the way setup.ts composes the parent:
17
+ * The graph here is composed exactly the way turn-setup.ts composes the parent:
18
18
  * the PRODUCTION buildMiddlewareStack (pathNormalization present on every
19
19
  * graph) + the CAS capture backend + the PRODUCTION buildPlanModePermissions
20
20
  * rules. These tests are also the empirical proof that langchain's
@@ -44,7 +44,7 @@ const OUTSIDE_CONTENT = "OUT_OF_ROOT_SECRET_TOKEN: must never cross the boundary
44
44
  const PLATFORM_CONTENT = "PLATFORM_SKILL_TOKEN: reached through the .stigmer symlink";
45
45
 
46
46
  /**
47
- * Build a plan-mode parent graph the way setup.ts does: the production
47
+ * Build a plan-mode parent graph the way turn-setup.ts does: the production
48
48
  * middleware stack with pathNormalization set (derived, like the graph's
49
49
  * permissions, from the plan-mode rules), a filesystem-only CAS capture
50
50
  * backend (no shellEnv — plan mode clears it), and the production