@stigmer/runner 3.15.1 → 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
@@ -56,16 +56,25 @@ import type { TurnInputFixtureOverrides } from "../turn-input-fixture.js";
56
56
  * ends `failed` on the given surface (`engine` unless the scenario says
57
57
  * otherwise — the runtime's three failure copies are its own invariant).
58
58
  * - `cancelled`: the engine ends its own run cancelled with nothing to
59
- * wait for (an SDK-side cancel); the turn ends `cancelled`.
59
+ * wait for (an SDK-side cancel); the turn ends `cancelled`. Not every
60
+ * engine can end itself (a LangGraph run is stopped only by the runtime's
61
+ * signal and settles `interrupted`), so a subject that cannot produce it
62
+ * says so and the runtime arm is reported SKIPPED there.
63
+ * - `limit`: the engine exhausts the tool-round budget the execution set and
64
+ * stops at a step boundary with its work checkpointed; the turn ends
65
+ * `tool_call_limit`. Not every engine has such a budget (Cursor's SDK does
66
+ * not), so a subject that cannot produce it says so and the runtime arm
67
+ * is reported SKIPPED there.
60
68
  */
61
69
  export type ScenarioStep =
62
70
  | { readonly kind: "say"; readonly text: string }
63
- | { readonly kind: "propose"; readonly toolCallId: string; readonly action: ProposedAction }
71
+ | { readonly kind: "propose"; readonly toolCallId: string; readonly action: ProposedAction; readonly flows?: boolean }
64
72
  | { readonly kind: "read"; readonly toolCallId: string; readonly path: string }
65
73
  | { readonly kind: "usage"; readonly delta: UsageDelta }
66
74
  | { readonly kind: "hang" }
67
75
  | { readonly kind: "fail"; readonly message: string; readonly surface: FailureSurface }
68
- | { readonly kind: "cancelled" };
76
+ | { readonly kind: "cancelled" }
77
+ | { readonly kind: "limit" };
69
78
 
70
79
  /** One turn's worth of engine behaviour. */
71
80
  export type TurnScenario = readonly ScenarioStep[];
@@ -78,6 +87,18 @@ export const scenario = {
78
87
  propose(toolCallId: string, action: ProposedAction): ScenarioStep {
79
88
  return { kind: "propose", toolCallId, action };
80
89
  },
90
+ /**
91
+ * A `write` the arm EXPECTS to flow under apply-then-review capture (a git
92
+ * work tree, or artifact storage): the engine performs it at once, the row
93
+ * completes, and the RUNTIME captures it for review after the turn
94
+ * (`harness/capture.ts`). The arm states the posture rather than the
95
+ * subject inferring it, so a subject that gates a flowing write is caught,
96
+ * not accommodated. The bytes written are the engine's own; the arm
97
+ * asserts the captured PATH and the reconcile's effect, never the content.
98
+ */
99
+ flowingWrite(toolCallId: string, path: string): ScenarioStep {
100
+ return { kind: "propose", toolCallId, action: { kind: "write", resource: path }, flows: true };
101
+ },
81
102
  read(toolCallId: string, path: string): ScenarioStep {
82
103
  return { kind: "read", toolCallId, path };
83
104
  },
@@ -93,6 +114,9 @@ export const scenario = {
93
114
  cancelled(): ScenarioStep {
94
115
  return { kind: "cancelled" };
95
116
  },
117
+ limit(): ScenarioStep {
118
+ return { kind: "limit" };
119
+ },
96
120
  } as const;
97
121
 
98
122
  /**
@@ -7,11 +7,15 @@
7
7
  * are the wire contract the control plane's workflow keys on — the phases they
8
8
  * persist, the copy they write, whether they RETURN a slim status or THROW
9
9
  * `CancelledFailure`. Refactoring them safely needs goldens recorded through the
10
- * activity whole, not through its modules one at a time. The native harness
11
- * tests already run their activity hermetically by mocking three modules at the
12
- * boundary (`execute-deep-agent/__tests__/{index,hitl-*,sequential-gate-resume}.test.ts`);
13
- * this module is that convention made reusable, harness-agnostic, and driven by
14
- * the framework's own activity environment instead of a hand-written stand-in.
10
+ * activity whole, not through its modules one at a time. The native harness's
11
+ * earlier activity tests ran their activity hermetically by mocking three
12
+ * modules at the boundary with a hand-written `Context` stand-in and a scripted
13
+ * graph object; this module is that convention made reusable, harness-agnostic,
14
+ * and driven by the framework's own activity environment. Both harnesses now
15
+ * run on it (`execute-cursor/__test-utils__/hermetic-cursor.ts`,
16
+ * `execute-deep-agent/__test-utils__/hermetic-deep-agent.ts`), and the earlier
17
+ * native tests were re-homed onto the native driver (S3 M0), their assertions
18
+ * carried into `execute-deep-agent/__tests__/hermetic/`.
15
19
  *
16
20
  * What is generic here and what is not: everything an activity touches that is
17
21
  * NOT the vendor SDK — the Temporal `Context`, the control-plane client, the
@@ -92,6 +96,7 @@ import {
92
96
  signalWorkerShutdown,
93
97
  unregisterWorkerShutdownSignal,
94
98
  } from "../shared/worker-shutdown.js";
99
+ import { decideCapturedFileChanges, type FileReviewVerdicts } from "./file-review-projection.js";
95
100
  import { mockStigmerClient } from "./mock-client.js";
96
101
 
97
102
  // ---------------------------------------------------------------------------
@@ -221,6 +226,19 @@ export class ExecutionRecord {
221
226
  return waiting.length;
222
227
  }
223
228
 
229
+ /**
230
+ * What the server's `SubmitFileDecision` and its projection do between
231
+ * invocations: every change of every AWAITING_REVIEW set the runner captured
232
+ * gets a per-file verdict, and `status.file_change_sets` is re-folded from
233
+ * the ledger (`file-review-projection.ts` mirrors the server's fold). The
234
+ * runner authors the ledger; the server owns the sets — so this is the ONE
235
+ * place a test writes them. Returns how many decisions were written.
236
+ */
237
+ decideCapturedFileChanges(verdicts: FileReviewVerdicts, decidedAt: string): number {
238
+ if (!this.execution.status) throw new Error("ExecutionRecord: no status to decide file changes on (test bug)");
239
+ return decideCapturedFileChanges(this.execution.status, verdicts, decidedAt);
240
+ }
241
+
224
242
  /**
225
243
  * Apply one `UpdateStatus` write and answer the control signal the server
226
244
  * would. A setup-progress report never carries a signal (the runner ignores
@@ -389,12 +407,30 @@ export function createHermeticEnvironment(): HermeticEnvironment {
389
407
  // ---------------------------------------------------------------------------
390
408
 
391
409
  /**
392
- * A deterministic, TICKING `Date`. Only `Date` is faked; timers stay real (the
393
- * periodic heartbeat, the stall watchdog, `withTimeout` all need them). The
394
- * harness double calls {@link ScriptedClock.tick} once per script step, so
395
- * every `Date.now()`-based decision on the activity path (status timestamps,
396
- * the enricher's persist debounce, cache TTLs) sees the same instants run after
397
- * run and runs the same branches production runs.
410
+ * A deterministic, TICKING clock: `Date` AND `performance` are faked and
411
+ * advance together; timers stay real (the periodic heartbeat, the stall
412
+ * watchdog, `withTimeout` all need them). The harness double calls
413
+ * {@link ScriptedClock.tick} once per script step, so every clock-based
414
+ * decision on the activity path status timestamps, the enricher's persist
415
+ * debounce, cache TTLs (`Date`); the streaming scheduler's persist cadence
416
+ * (`performance.now()`) — sees the same instants run after run and runs the
417
+ * same branches production runs.
418
+ *
419
+ * Why both (S3 M5, Q-M5-7; F-M2a-20): until M5 only `Date` was faked, so the
420
+ * scheduler paced persists on REAL elapsed time and `fileChangeProgress`,
421
+ * which rides persists, could gain or lose a capture under load — a golden
422
+ * flake seen twice across S3. One clock, two faces: `tick` advances through
423
+ * the fake clock's own `tick` (`vi.advanceTimersByTime`), which moves both
424
+ * `Date` and `performance.now()`; `vi.setSystemTime` would move `Date` alone
425
+ * (fake-timers keeps `performance` monotonic across a system-time jump), so
426
+ * only {@link reset} uses it — rewinding `Date` to the epoch for a second
427
+ * scenario while `performance` stays monotonic, which is harmless because
428
+ * every turn constructs its scheduler fresh and measures from its own start.
429
+ *
430
+ * Faking `performance` replaces the whole global (`now`, a `timeOrigin` at
431
+ * the epoch, every other method a no-op); nothing on the activity path reads
432
+ * more than `now`, and a module importing from `node:perf_hooks` would bypass
433
+ * the fake (none under `src/` does).
398
434
  */
399
435
  export class ScriptedClock {
400
436
  /** A fixed epoch: 2026-01-01T00:00:00.000Z. Chosen for readability in goldens. */
@@ -405,15 +441,17 @@ export class ScriptedClock {
405
441
  private nowMs = ScriptedClock.EPOCH_MS;
406
442
 
407
443
  install(): void {
408
- vi.useFakeTimers({ toFake: ["Date"], now: this.nowMs });
444
+ vi.useFakeTimers({ toFake: ["Date", "performance"], now: this.nowMs });
409
445
  }
410
446
 
411
447
  tick(ms: number = ScriptedClock.STEP_MS): void {
412
448
  this.nowMs += ms;
413
- vi.setSystemTime(this.nowMs);
449
+ // Through the fake clock's own tick, so `performance.now()` advances with
450
+ // `Date`; with no timers faked there is nothing for it to fire.
451
+ vi.advanceTimersByTime(ms);
414
452
  }
415
453
 
416
- /** Back to the epoch — for a second scenario in the same file. */
454
+ /** Back to the epoch — for a second scenario in the same file. `Date` rewinds; `performance` stays monotonic (see the header). */
417
455
  reset(): void {
418
456
  this.nowMs = ScriptedClock.EPOCH_MS;
419
457
  vi.setSystemTime(this.nowMs);
@@ -10,19 +10,29 @@
10
10
  * registry document — and to THROW for any other URL, so a new network
11
11
  * dependency on the activity path fails the run instead of leaking.
12
12
  *
13
- * One entry, `composer-2.5`, priced at round numbers so a golden's
14
- * `estimatedCostUsd` is legible (600 000 input tokens = $0.60). The entry is
15
- * a Cursor-harness model because that is what the registry lists; the
16
- * document itself is the control plane's, read by every harness's runtime.
17
- * `parsePricingTable` wants `harness: "cursor"` + `pricing`; `parseRegistry`
18
- * wants `id` + `provider` and reads `capabilities.vision`.
13
+ * One entry per harness, each priced at round numbers so a golden's usage and
14
+ * cost are legible (600 000 input tokens = $0.60). `composer-2.5` is the
15
+ * Cursor harness's pinned model (also in the Cursor double's catalog);
16
+ * `claude-haiku-4.5` is the native harness's, an Anthropic id so the native
17
+ * error arms' provider label (`tryInferProvider`) and the thinking heuristic
18
+ * read as they do in production. The document itself is the control plane's,
19
+ * read by every harness's runtime: `parsePricingTable` keeps every entry with
20
+ * `pricing`; `parseRegistry` wants `id` + `provider` and reads
21
+ * `capabilities.vision`; `getDefaultModel` selects only `harness: "native"`.
22
+ * Every fixture NAMES its model on the execution, so the list's order is
23
+ * never consulted and adding an entry is byte-invisible to the other
24
+ * harness's goldens (verified when the native entry landed: Cursor's
25
+ * seventeen unchanged).
19
26
  */
20
27
 
21
28
  import { vi } from "vitest";
22
29
 
23
- /** The pinned model of every hermetic run; in the registry document AND in the Cursor double's catalog. */
30
+ /** The pinned model of every Cursor hermetic run; in the registry document AND in the Cursor double's catalog. */
24
31
  export const FIXTURE_MODEL = "composer-2.5";
25
32
 
33
+ /** The pinned model of every native (deep-agent) hermetic run. */
34
+ export const FIXTURE_NATIVE_MODEL = "claude-haiku-4.5";
35
+
26
36
  export const REGISTRY_DOCUMENT = {
27
37
  models: [
28
38
  {
@@ -48,6 +58,21 @@ export const REGISTRY_DOCUMENT = {
48
58
  },
49
59
  },
50
60
  },
61
+ {
62
+ id: FIXTURE_NATIVE_MODEL,
63
+ displayName: "Claude Haiku 4.5 (hermetic fixture)",
64
+ provider: "anthropic",
65
+ harness: "native",
66
+ costTier: "standard",
67
+ featured: true,
68
+ capabilities: { vision: true },
69
+ pricing: {
70
+ inputPricePerMillion: 1.0,
71
+ outputPricePerMillion: 5.0,
72
+ cacheWritePricePerMillion: 1.25,
73
+ cacheReadPricePerMillion: 0.1,
74
+ },
75
+ },
51
76
  ],
52
77
  } as const;
53
78
 
@@ -42,6 +42,30 @@ export function moduleSpecifiers(fileName: string, source: string): string[] {
42
42
  return specifiers;
43
43
  }
44
44
 
45
+ /**
46
+ * The module specifiers a file LOADS when it is itself loaded: static
47
+ * imports and re-exports that are not type-only. A `import type` is erased
48
+ * by the compiler and a dynamic `import()` runs only when its call runs, so
49
+ * neither is on the static graph — which is what the SDK-free fences on the
50
+ * adapters' lifecycle modules ask about (`harness-adapters.ts`'s rule: the
51
+ * roots import the table before they boot it, so an adapter loads its SDK
52
+ * inside `boot`, never at the top of its module).
53
+ */
54
+ export function staticRuntimeSpecifiers(fileName: string, source: string): string[] {
55
+ const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, /* setParentNodes */ false);
56
+ const specifiers: string[] = [];
57
+ for (const statement of sourceFile.statements) {
58
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
59
+ if (statement.importClause?.isTypeOnly) continue;
60
+ specifiers.push(statement.moduleSpecifier.text);
61
+ } else if (ts.isExportDeclaration(statement) && statement.moduleSpecifier !== undefined && ts.isStringLiteral(statement.moduleSpecifier)) {
62
+ if (statement.isTypeOnly) continue;
63
+ specifiers.push(statement.moduleSpecifier.text);
64
+ }
65
+ }
66
+ return specifiers;
67
+ }
68
+
45
69
  /**
46
70
  * The relative specifiers in `source` that resolve to a path inside
47
71
  * `forbiddenRoot`. Package specifiers are ignored: no alias maps a package
@@ -58,7 +58,7 @@ export interface TurnInputFixtureOverrides extends Partial<Omit<TurnInput, "exec
58
58
  * The status the default execution carries — what the control plane
59
59
  * persisted at the end of the previous invocation, on a reinvocation. The
60
60
  * runtime seeds the turn's in-progress status from a clone of it
61
- * (`seedTranscriptFromExecution`) and an adapter may read the record's own
61
+ * (`seedFromPersistedStatus`) and an adapter may read the record's own
62
62
  * copy for its facts, so a test standing in for the runtime hands both.
63
63
  */
64
64
  readonly persistedStatus?: AgentExecutionStatus;
@@ -137,7 +137,7 @@ export function turnInputFixture(overrides: TurnInputFixtureOverrides = {}): Tur
137
137
  leases: { global: false, categories: new Set(), servers: new Set() },
138
138
  policies: new Map(),
139
139
  },
140
- skills: overrides.skills ?? [],
140
+ skills: overrides.skills ?? { root: [], bySubAgent: new Map() },
141
141
  attachments: overrides.attachments ?? { results: [], visionImages: [], visionNotViewable: [] },
142
142
  appliedToolCallIds: overrides.appliedToolCallIds ?? new Set(),
143
143
  model: overrides.model ?? { requested: "default", serviceTier: ServiceTier.STANDARD, thinkingMode: ThinkingMode.DISABLED },
@@ -20,9 +20,16 @@
20
20
  * `adapter.ts`'s graph, or a static client import on the registry's, fails
21
21
  * the first arm; a `boot` that stopped asserting fails the second.
22
22
  *
23
+ * The table has two rows since S3 M2b (2026-09-13): the child boots the
24
+ * Cursor adapter and then the native deep-agent adapter, whose `boot`
25
+ * registers the deepagents profiles and loads LangChain — after the patch,
26
+ * because it is the second row. A `boot` that reordered the rows, or a
27
+ * native adapter that imported its engine statically, would move that load
28
+ * before the patch; the first arm below is where that would show.
29
+ *
23
30
  * `HOME` points at a temp dir so an SDK import-time side effect cannot touch
24
31
  * the developer's home; the proxy endpoint is an inert loopback; nothing is
25
- * dialled. Two spawns, a few seconds: the SDK is imported for real once.
32
+ * dialled. Two spawns, a few seconds: both SDKs are imported for real once.
26
33
  */
27
34
 
28
35
  import { describe, it, expect } from "vitest";
@@ -63,7 +70,7 @@ function lastLine(text: string): string {
63
70
  }
64
71
 
65
72
  describe("harness boot order (fresh process)", () => {
66
- it("booting the harnesses on a proxy-mode config, the way the roots do, installs the interceptors, patches the facade, and loads the SDK", async () => {
73
+ it("booting both harnesses on a proxy-mode config, the way the roots do, installs the interceptors, patches the facade, and loads both engines after it", async () => {
67
74
  const verdict = await runChild("boot");
68
75
  expect(verdict.line, "the child's verdict").toBe("harness-boot-order: ok");
69
76
  expect(verdict.exitCode).toBe(0);
@@ -225,8 +225,8 @@ export async function callAgentAction(
225
225
  // Honest RunConfig → ExecutionConfig mapping (issue #358): every field
226
226
  // the author may set is forwarded to a field the runner enforces.
227
227
  // model_name replaces the agent's default outright; max_cost_usd feeds
228
- // the harness-generic cost guards (cost-cap middleware / cursor
229
- // cost-guard); max_tool_rounds feeds resolveRecursionLimit (native
228
+ // the turn runtime's cost guard (shared/cost-guard.ts, both harnesses);
229
+ // max_tool_rounds feeds resolveRecursionLimit (native
230
230
  // harness only); service_tier and thinking_mode feed the cursor
231
231
  // harness's explicit variant selection (issues #357/#772). Zero/unset
232
232
  // means "no override" and is omitted.
@@ -79,8 +79,8 @@
79
79
  * would show up there AND in `executionCount`, never be papered over.
80
80
  */
81
81
 
82
- import { mkdirSync } from "node:fs";
83
- import { join } from "node:path";
82
+ import { appendFileSync, mkdirSync } from "node:fs";
83
+ import { dirname, join } from "node:path";
84
84
  import { ApprovalAction, ServiceTier, ThinkingMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
85
85
 
86
86
  import type { Config } from "../../../config.js";
@@ -237,7 +237,11 @@ class CursorSubject implements CursorContractSubject {
237
237
  lastSay = s.text;
238
238
  break;
239
239
  case "propose":
240
- script.push(...this.proposeSteps(s.toolCallId, s.action, view, ev));
240
+ script.push(
241
+ ...(s.flows
242
+ ? this.flowingWriteSteps(s.toolCallId, s.action, view, ev)
243
+ : this.proposeSteps(s.toolCallId, s.action, view, ev)),
244
+ );
241
245
  break;
242
246
  case "read":
243
247
  script.push(...this.readSteps(s.toolCallId, s.path, view, ev));
@@ -281,6 +285,8 @@ class CursorSubject implements CursorContractSubject {
281
285
  script.push(step.effect("kit: the SDK cancels its own run", ({ run }) => run.cancel()));
282
286
  ended = true;
283
287
  break;
288
+ case "limit":
289
+ throw new Error(`${this.name}: limit() is not producible by this subject (the Cursor SDK has no tool-round budget; the runtime arm is declared off for it); test bug`);
284
290
  default: {
285
291
  const exhaustive: never = s;
286
292
  throw new Error(`${this.name}: unknown scenario step ${JSON.stringify(exhaustive)}`);
@@ -352,6 +358,44 @@ class CursorSubject implements CursorContractSubject {
352
358
  ];
353
359
  }
354
360
 
361
+ /**
362
+ * A write the arm expects to FLOW under apply-then-review capture: the
363
+ * stream tool call, the REAL hook (which allows a git-capturable write in
364
+ * capture mode — asserted through the disagreement record like every other
365
+ * hook answer), the write itself as the SDK would perform it once allowed
366
+ * (the bytes are this double's own: the tool-call id, one line, appended),
367
+ * and the completion. The runtime captures the change after the turn; the
368
+ * hook's sidecar is what this adapter binds as its CAS observations, so a
369
+ * gitignored path here would reach the review that way.
370
+ */
371
+ private flowingWriteSteps(toolCallId: string, action: ProposedAction, view: EngineView, ev: ReturnType<typeof sdkEvents>): ScriptStep[] {
372
+ if (action.kind !== "write") {
373
+ throw new Error(`${this.name}: only a write flows under capture (got ${action.kind}); test bug`);
374
+ }
375
+ const memory = this.proposals.get(toolCallId) ?? { emitted: 0, allowed: 0 };
376
+ this.proposals.set(toolCallId, memory);
377
+ if (memory.allowed > 0) return [];
378
+ memory.emitted += 1;
379
+ const gated: ProposedAction & { kind: GatedActionKind } = { ...action, kind: "write" };
380
+ const args = streamArgsFor(gated);
381
+ const workspaceRoot = this.workspaceRootOf(view.sessionId);
382
+ const file = join(workspaceRoot, action.resource);
383
+ return [
384
+ step.event(ev.toolCall(toolCallId, STREAM_NAME.write, "running", args)),
385
+ step.effect(`kit: the real hook lets ${action.resource} flow under capture`, () => {
386
+ const { permission } = runWorkspaceHook(workspaceRoot, hookInputFor(gated));
387
+ if (permission !== "allow") {
388
+ this.hookDisagreements.push(`${toolCallId}: expected a flowing write to be allowed, hook answered ${permission}`);
389
+ return;
390
+ }
391
+ memory.allowed += 1;
392
+ mkdirSync(dirname(file), { recursive: true });
393
+ appendFileSync(file, `${toolCallId}\n`);
394
+ }),
395
+ step.event(ev.toolCall(toolCallId, STREAM_NAME.write, "completed", args, ALLOWED_RESULT)),
396
+ ];
397
+ }
398
+
355
399
  /**
356
400
  * An ungated read: the stream tool call, the REAL hook (which allows every
357
401
  * read — the gate's baked-in category set has no arm for it; asserted
@@ -42,16 +42,9 @@
42
42
  */
43
43
 
44
44
  import { execFileSync } from "node:child_process";
45
- import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
46
- import { dirname, join } from "node:path";
47
- import { create } from "@bufbuild/protobuf";
45
+ import { readFileSync } from "node:fs";
46
+ import { join } from "node:path";
48
47
  import type { ModelListItem } from "@cursor/sdk";
49
- import {
50
- LocalPathSourceSchema,
51
- WorkspaceEntrySchema,
52
- WorkspaceSourceSchema,
53
- type WorkspaceEntry,
54
- } from "@stigmer/protos/ai/stigmer/agentic/session/v1/workspace_pb";
55
48
  import type { StigmerClient } from "../../../client/stigmer-client.js";
56
49
  import type { Config } from "../../../config.js";
57
50
  import type { ExecuteActivityInput } from "../../../shared/activity-input.js";
@@ -203,45 +196,6 @@ export function runWorkspaceHook(
203
196
  return { permission, raw };
204
197
  }
205
198
 
206
- /**
207
- * A git work tree with one committed file, for the file-review capture
208
- * scenario. Author, committer and both dates are pinned so the commit AND tree
209
- * object ids are byte-stable — a file-review golden may carry them.
210
- */
211
- export function initGitWorkspace(root: string, files: Record<string, string>): void {
212
- mkdirSync(root, { recursive: true });
213
- const gitEnv = {
214
- ...process.env,
215
- GIT_AUTHOR_NAME: "hermetic",
216
- GIT_AUTHOR_EMAIL: "hermetic@stigmer.test",
217
- GIT_COMMITTER_NAME: "hermetic",
218
- GIT_COMMITTER_EMAIL: "hermetic@stigmer.test",
219
- GIT_AUTHOR_DATE: "2026-01-01T00:00:00Z",
220
- GIT_COMMITTER_DATE: "2026-01-01T00:00:00Z",
221
- };
222
- const git = (args: string[]): void => {
223
- execFileSync("git", args, { cwd: root, env: gitEnv, stdio: "ignore" });
224
- };
225
- git(["init", "-q", "-b", "main"]);
226
- for (const [rel, content] of Object.entries(files)) {
227
- const abs = join(root, rel);
228
- mkdirSync(dirname(abs), { recursive: true });
229
- writeFileSync(abs, content, "utf-8");
230
- }
231
- git(["add", "-A"]);
232
- git(["commit", "-q", "-m", "initial"]);
233
- }
234
-
235
- /** A session workspace entry mounting an absolute local path (local mode only). */
236
- export function localPathEntry(name: string, path: string): WorkspaceEntry {
237
- return create(WorkspaceEntrySchema, {
238
- name,
239
- source: create(WorkspaceSourceSchema, {
240
- source: { case: "localPath", value: create(LocalPathSourceSchema, { path }) },
241
- }),
242
- });
243
- }
244
-
245
199
  // ---------------------------------------------------------------------------
246
200
  // Running a scenario
247
201
  // ---------------------------------------------------------------------------
@@ -20,7 +20,7 @@ import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/a
20
20
  import { AgentMessageSchema, ToolCallSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
21
21
  import { ApprovalAction, MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
22
22
 
23
- import { approvalDecisionsOf } from "../../../harness/turn-context.js";
23
+ import { approvalDecisionsOf } from "../../../harness/approval-decisions.js";
24
24
  import { reconstructAdjudicatedApprovals } from "../approval-state.js";
25
25
 
26
26
  describe("the runtime's approvalDecisionsOf and the adapter's reconstructAdjudicatedApprovals", () => {
@@ -260,15 +260,17 @@ describe("buildApprovalState", () => {
260
260
  });
261
261
 
262
262
  describe("buildReinvocationPrompt", () => {
263
- it("describes approved and skipped actions in human terms, not opaque ids", () => {
263
+ it("describes approved, skipped and rejected actions in human terms, not opaque ids", () => {
264
264
  const prompt = buildReinvocationPrompt(
265
265
  [
266
266
  pending({ toolCallId: "c1", toolName: "edit", message: "Write file: gated.txt" }),
267
267
  pending({ toolCallId: "c2", toolName: "shell", message: "Run command: rm -rf build" }),
268
+ pending({ toolCallId: "c3", toolName: "shell", message: "Run command: git push --force" }),
268
269
  ],
269
270
  new Map([
270
271
  ["c1", ApprovalAction.APPROVE],
271
272
  ["c2", ApprovalAction.SKIP],
273
+ ["c3", ApprovalAction.REJECT],
272
274
  ]),
273
275
  );
274
276
 
@@ -276,8 +278,11 @@ describe("buildReinvocationPrompt", () => {
276
278
  expect(prompt).toContain("Write file: gated.txt");
277
279
  expect(prompt).toContain("SKIPPED");
278
280
  expect(prompt).toContain("Run command: rm -rf build");
281
+ expect(prompt).toContain("REJECTED");
282
+ expect(prompt).toContain("Run command: git push --force");
279
283
  expect(prompt).not.toContain("c1");
280
284
  expect(prompt).not.toContain("c2");
285
+ expect(prompt).not.toContain("c3");
281
286
  });
282
287
 
283
288
  it("falls back to tool name + args preview when no message is set", () => {