@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
@@ -35,7 +35,7 @@ import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/a
35
35
  import { ApprovalAction, MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
36
36
  import type { SDKMessage } from "@cursor/sdk";
37
37
 
38
- import { approvalDecisionsOf } from "../../../harness/turn-context.js";
38
+ import { approvalDecisionsOf } from "../../../harness/approval-decisions.js";
39
39
  import { MessageAccumulator, reconcileDeniedToolCalls, toolCallIdentityToken } from "../message-translator.js";
40
40
  import type { DeniedLedgerEntry } from "../approval-state.js";
41
41
 
@@ -83,7 +83,7 @@ function allToolCalls(messages: AgentMessage[]): ToolCall[] {
83
83
 
84
84
  /** The later turn: the model proposes the same edit under a fresh id, the hook denies it, the turn boundary reconciles. */
85
85
  async function laterTurnProposesSameEdit(seeded: AgentMessage[]): Promise<ToolCall[]> {
86
- const acc = new MessageAccumulator(seeded, { seededSubAgents: [] });
86
+ const acc = new MessageAccumulator(seeded, {});
87
87
  acc.processEvent(toolCallEvent(LATER_ID, "running"));
88
88
  acc.processEvent(toolCallEvent(LATER_ID, "error", "Blocked by hook"));
89
89
  acc.finalize();
@@ -158,7 +158,7 @@ describe("a later same-identity proposal never lands on a decided row (F9)", ()
158
158
  }),
159
159
  ];
160
160
 
161
- const acc = new MessageAccumulator(seeded, { seededSubAgents: [] });
161
+ const acc = new MessageAccumulator(seeded, {});
162
162
  acc.processEvent(toolCallEvent(`${FIRST_ID}_RESUME`, "running"));
163
163
  acc.processEvent(toolCallEvent(`${FIRST_ID}_RESUME`, "completed", RESULT_OF_FIRST));
164
164
  acc.finalize();
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @regression file-hitl-phase0 — pins file-edit HITL fix #2 (see _projects/2026-06/20260630.01.file-change-hitl-redesign/tasks/T01_3_regression-manifest.md)
3
3
  *
4
- * Cursor analog of execute-deep-agent/__tests__/sequential-gate-resume.test.ts:
4
+ * Cursor analog of execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts:
5
5
  * two SEQUENTIAL approval gates across a resume, on the Cursor deny-and-reconcile
6
6
  * harness instead of the native in-process gate.
7
7
  *
@@ -139,7 +139,7 @@ describe("Cursor sequential gates A->B across resume", () => {
139
139
  const committed = approvedGateA();
140
140
  const seeded = committed.map((m) => clone(AgentMessageSchema, m));
141
141
 
142
- const acc = new MessageAccumulator(seeded, { seededSubAgents: [] });
142
+ const acc = new MessageAccumulator(seeded, {});
143
143
  for (const event of resumeIntoGateB()) acc.processEvent(event);
144
144
  acc.finalize();
145
145
 
@@ -1,21 +1,29 @@
1
1
  /**
2
2
  * Tests for the extracted turn boundary (turn-boundary.ts) — the post-run
3
- * pipeline shared by the primary path and the recovery retries.
3
+ * pipeline shared by the primary path and the recovery retries: the hook's
4
+ * denials become WAITING_APPROVAL gates, unattended and secret denials are
5
+ * attributed and settled, a foreign hook's block is reported (#205), and a
6
+ * row that hung inside the harness on a completing turn is settled and
7
+ * disclosed (#965).
4
8
  *
5
- * The load-bearing scenario is the recovery-retry sequence that motivated the
6
- * extraction (production case aex_01kws27q1e2esvkqjpvectttxf): the primary
7
- * boundary runs against an untouched tree (the resumed agent errored before
8
- * doing anything), the retry agent then edits files, and the boundary is
9
- * re-entered the candidate must be authored exactly once and the turn must
10
- * pause for review. Runs against a REAL temp git repo with in-memory
11
- * transcript + status protos, mirroring capture-flow.test.ts.
9
+ * The turn's FILE CHANGES are not the boundary's since S3 M4: the runtime
10
+ * captures them once after `runTurn` returns (`harness/capture.ts`, proven
11
+ * in `harness/__tests__/capture.test.ts` and the kit's runtime arm), so the
12
+ * five capture arms this file carried until then the candidate, the clean
13
+ * turn, the missing baseline, the recovery re-entry authoring exactly once,
14
+ * the full-ledger stamp exclusion live there now, restated for the
15
+ * runtime's status-based rules. One arm changed meaning with the lift and is
16
+ * pinned below: a turn whose only pause would have been a file review is a
17
+ * COMPLETING turn to this boundary, so its hung rows are settled before the
18
+ * runtime's review, not after it (F-M4-P9, Q-M4-11).
19
+ *
20
+ * Runs against a temp workspace dir with in-memory transcript + status
21
+ * protos; the gate reads a denied file's `before` from that dir.
12
22
  */
13
23
 
14
24
  import { mkdtemp, rm, writeFile } from "node:fs/promises";
15
- import { execFile } from "node:child_process";
16
25
  import { tmpdir } from "node:os";
17
26
  import { join } from "node:path";
18
- import { promisify } from "node:util";
19
27
  import { afterEach, beforeEach, describe, expect, it } from "vitest";
20
28
  import { create, type JsonObject } from "@bufbuild/protobuf";
21
29
  import {
@@ -25,26 +33,17 @@ import {
25
33
  import type { AgentMessage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
26
34
  import { AgentExecutionStatusSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
27
35
  import type { AgentExecutionStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
28
- import {
29
- FileReviewEventType,
30
- MessageType,
31
- ToolCallStatus,
32
- } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
33
- import { captureBaselineToLedger } from "../capture-flow.js";
36
+ import { MessageType, ToolCallStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
37
+ import { isToolCallRowHidden } from "../../../shared/tool-row.js";
34
38
  import { denialLedgerPath } from "../approval-state.js";
35
39
  import { toolCallIdentityToken, UNRESOLVED_TOOL_CALL_ERROR } from "../message-translator.js";
36
40
  import { runTurnBoundary, type TurnBoundaryOptions } from "../turn-boundary.js";
37
41
 
38
- const execFileAsync = promisify(execFile);
39
42
  const EXEC_ID = "exec-boundary-1";
40
- const CHANGE_SET_ID = `${EXEC_ID}:0`;
41
43
 
42
44
  let repo: string;
43
45
  let hitlDir: string;
44
46
 
45
- async function git(args: string[]): Promise<void> {
46
- await execFileAsync("git", args, { cwd: repo });
47
- }
48
47
  async function write(rel: string, content: string): Promise<void> {
49
48
  await writeFile(join(repo, rel), content, "utf-8");
50
49
  }
@@ -68,46 +67,39 @@ function streamedEdit(id: string, path: string, content: string): AgentMessage {
68
67
  });
69
68
  }
70
69
 
71
- /** Boundary options for this repo's turn; overrides layer the per-test shape. */
72
- function boundaryOpts(
73
- status: AgentExecutionStatus,
74
- baselineTree: string,
75
- overrides?: Partial<TurnBoundaryOptions>,
76
- ): TurnBoundaryOptions {
70
+ /** Boundary options for this turn; overrides layer the per-test shape. */
71
+ function boundaryOpts(status: AgentExecutionStatus, overrides?: Partial<TurnBoundaryOptions>): TurnBoundaryOptions {
77
72
  return {
78
73
  status,
79
74
  executionId: EXEC_ID,
80
- changeSetId: CHANGE_SET_ID,
81
75
  hitlDir,
82
- captureMode: true,
83
- baselineTree,
84
76
  primaryWorkspaceDir: repo,
85
- gitWorkspace: true,
86
77
  turnStartMessageIndex: 0,
87
- approvalGrants: undefined,
88
- globalBypass: false,
89
- seededSubAgents: [],
90
- artifactStorage: undefined,
91
78
  mergedPolicies: new Map(),
92
79
  ...overrides,
93
80
  };
94
81
  }
95
82
 
96
- function candidateEvents(status: AgentExecutionStatus) {
97
- return (status.fileReviewEventStream?.events ?? []).filter(
98
- (e) => e.eventType === FileReviewEventType.CANDIDATE_CAPTURED,
99
- );
83
+ /** A FAILED tool call carrying Cursor's generic hook-block error text (#205). */
84
+ function hookBlockedCall(id: string, name: string, args: JsonObject) {
85
+ return create(ToolCallSchema, {
86
+ id,
87
+ name,
88
+ status: ToolCallStatus.TOOL_CALL_FAILED,
89
+ error: "Command blocked by a hook.",
90
+ args,
91
+ });
92
+ }
93
+
94
+ /** Append one entry to this turn's denial ledger. */
95
+ async function appendLedgerEntry(entry: Record<string, unknown>): Promise<void> {
96
+ await writeFile(denialLedgerPath(hitlDir), JSON.stringify(entry) + "\n", { flag: "a" });
100
97
  }
101
98
 
102
99
  beforeEach(async () => {
103
100
  repo = await mkdtemp(join(tmpdir(), "stigmer-boundary-repo-"));
104
101
  hitlDir = await mkdtemp(join(tmpdir(), "stigmer-boundary-hitl-"));
105
- await git(["init", "-q"]);
106
- await git(["config", "user.email", "t@t.local"]);
107
- await git(["config", "user.name", "t"]);
108
102
  await write("notes.md", "original notes\n");
109
- await git(["add", "-A"]);
110
- await git(["commit", "-q", "-m", "initial"]);
111
103
  });
112
104
 
113
105
  afterEach(async () => {
@@ -116,98 +108,8 @@ afterEach(async () => {
116
108
  });
117
109
 
118
110
  describe("runTurnBoundary", () => {
119
- it("authors a candidate, stamps the row, and pauses when the turn edited files", async () => {
120
- const status = newStatus();
121
- const baseline = await captureBaselineToLedger({
122
- status,
123
- gitRoot: repo,
124
- executionId: EXEC_ID,
125
- changeSetId: CHANGE_SET_ID,
126
- });
127
-
128
- await write("notes.md", "original notes\n\n## TODO\n- ship\n");
129
- status.messages.push(
130
- streamedEdit("tc-1", "notes.md", "original notes\n\n## TODO\n- ship\n"),
131
- );
132
-
133
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
134
-
135
- expect(result.waiting).toBe(true);
136
- expect(result.capturedChangeCount).toBe(1);
137
- expect(result.deniedToolCallCount).toBe(0);
138
- expect(candidateEvents(status)).toHaveLength(1);
139
- // The streamed row is stamped with the change set id (observational record
140
- // anchoring the decision surface).
141
- expect(status.messages[0].toolCalls[0].fileChangeSetId).toBe(CHANGE_SET_ID);
142
- });
143
-
144
- it("reports a clean turn when nothing changed (no candidate, no pause)", async () => {
145
- const status = newStatus();
146
- const baseline = await captureBaselineToLedger({
147
- status,
148
- gitRoot: repo,
149
- executionId: EXEC_ID,
150
- changeSetId: CHANGE_SET_ID,
151
- });
152
-
153
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
154
-
155
- expect(result.waiting).toBe(false);
156
- expect(result.capturedChangeCount).toBe(0);
157
- expect(result.deniedToolCallCount).toBe(0);
158
- expect(candidateEvents(status)).toHaveLength(0);
159
- });
160
-
161
- it("skips capture when no baseline was authored this turn", async () => {
162
- const status = newStatus();
163
- await write("notes.md", "edited without a baseline\n");
164
-
165
- const result = await runTurnBoundary(
166
- boundaryOpts(status, "", { baselineTree: undefined }),
167
- );
168
-
169
- expect(result.waiting).toBe(false);
170
- expect(result.capturedChangeCount).toBe(0);
171
- expect(candidateEvents(status)).toHaveLength(0);
172
- });
173
-
174
- it("re-entered after a no-op primary call, authors the candidate exactly once (recovery-retry sequence)", async () => {
175
- const status = newStatus();
176
- const baseline = await captureBaselineToLedger({
177
- status,
178
- gitRoot: repo,
179
- executionId: EXEC_ID,
180
- changeSetId: CHANGE_SET_ID,
181
- });
182
-
183
- // Primary boundary: the resumed agent errored before touching anything —
184
- // the tree is at baseline, no candidate is authored, the turn looks clean.
185
- const primary = await runTurnBoundary(boundaryOpts(status, baseline));
186
- expect(primary.waiting).toBe(false);
187
- expect(candidateEvents(status)).toHaveLength(0);
188
-
189
- // Recovery retry: a fresh agent re-ran the prompt and created the file.
190
- await write("notes.md", "original notes\n\nretry made this edit\n");
191
- status.messages.push(
192
- streamedEdit("tc-retry", "notes.md", "original notes\n\nretry made this edit\n"),
193
- );
194
-
195
- // Boundary re-entry: the retry's edit reaches the ledger and arms the gate.
196
- const retry = await runTurnBoundary(boundaryOpts(status, baseline));
197
- expect(retry.waiting).toBe(true);
198
- expect(retry.capturedChangeCount).toBe(1);
199
- expect(candidateEvents(status)).toHaveLength(1);
200
- expect(status.messages[0].toolCalls[0].fileChangeSetId).toBe(CHANGE_SET_ID);
201
- });
202
-
203
111
  it("surfaces a hook denial as a WAITING_APPROVAL gate and pauses", async () => {
204
112
  const status = newStatus();
205
- const baseline = await captureBaselineToLedger({
206
- status,
207
- gitRoot: repo,
208
- executionId: EXEC_ID,
209
- changeSetId: CHANGE_SET_ID,
210
- });
211
113
 
212
114
  // The hook gated a shell command mid-turn; the streamed call is still
213
115
  // RUNNING (Cursor reported the deny to the model, not a completion).
@@ -230,37 +132,17 @@ describe("runTurnBoundary", () => {
230
132
  "utf-8",
231
133
  );
232
134
 
233
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
135
+ const result = await runTurnBoundary(boundaryOpts(status));
234
136
 
235
137
  expect(result.waiting).toBe(true);
236
138
  expect(result.deniedToolCallCount).toBe(1);
237
- expect(result.capturedChangeCount).toBe(0);
238
139
  expect(shellCall.status).toBe(ToolCallStatus.TOOL_CALL_WAITING_APPROVAL);
239
140
  });
240
141
 
241
142
  // ── Issue #205: unattributed hook blocks and the kind split ────────────────
242
143
 
243
- /** A FAILED tool call carrying Cursor's generic hook-block error text. */
244
- function hookBlockedCall(id: string, name: string, args: JsonObject) {
245
- return create(ToolCallSchema, {
246
- id,
247
- name,
248
- status: ToolCallStatus.TOOL_CALL_FAILED,
249
- error: "Command blocked by a hook.",
250
- args,
251
- });
252
- }
253
-
254
- /** Append one entry to this turn's denial ledger. */
255
- async function appendLedgerEntry(entry: Record<string, unknown>): Promise<void> {
256
- await writeFile(denialLedgerPath(hitlDir), JSON.stringify(entry) + "\n", { flag: "a" });
257
- }
258
-
259
144
  it("reports a foreign hook block on a non-pausing turn (the #205 silent-complete shape)", async () => {
260
145
  const status = newStatus();
261
- const baseline = await captureBaselineToLedger({
262
- status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
263
- });
264
146
 
265
147
  // A foreign .cursor/hooks.json hook denied the write: Cursor stamped its
266
148
  // generic error, our ledger stayed empty, the tree is untouched. Before
@@ -272,7 +154,7 @@ describe("runTurnBoundary", () => {
272
154
  );
273
155
 
274
156
  const result = await runTurnBoundary(
275
- boundaryOpts(status, baseline, { foreignGatingHooks: ["./team-policy.sh"] }),
157
+ boundaryOpts(status, { foreignGatingHooks: ["./team-policy.sh"] }),
276
158
  );
277
159
 
278
160
  expect(result.waiting).toBe(false);
@@ -286,9 +168,6 @@ describe("runTurnBoundary", () => {
286
168
 
287
169
  it("attributes a secret hard-block (kind:'secret'): no pause, no false foreign-hook report", async () => {
288
170
  const status = newStatus();
289
- const baseline = await captureBaselineToLedger({
290
- status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
291
- });
292
171
 
293
172
  const secretRow = hookBlockedCall("tc-secret", "edit", { path: ".env" });
294
173
  status.messages.push(
@@ -302,7 +181,7 @@ describe("runTurnBoundary", () => {
302
181
  "utf-8",
303
182
  );
304
183
 
305
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
184
+ const result = await runTurnBoundary(boundaryOpts(status));
306
185
 
307
186
  // Not a pause (the agent was told to move on), not a foreign block (our
308
187
  // own kinded entry attributes it), and never a WAITING_APPROVAL overlay.
@@ -314,9 +193,6 @@ describe("runTurnBoundary", () => {
314
193
 
315
194
  it("mixed turn: pauses on our anchor while still reporting the foreign block", async () => {
316
195
  const status = newStatus();
317
- const baseline = await captureBaselineToLedger({
318
- status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
319
- });
320
196
 
321
197
  const ourGated = create(ToolCallSchema, {
322
198
  id: "tc-ours", name: "shell",
@@ -329,7 +205,7 @@ describe("runTurnBoundary", () => {
329
205
  );
330
206
  await appendLedgerEntry({ toolName: "shell", token: toolCallIdentityToken(ourGated), kind: "approval" });
331
207
 
332
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
208
+ const result = await runTurnBoundary(boundaryOpts(status));
333
209
 
334
210
  // The pause wins (a pausing turn is never silent); the foreign block is
335
211
  // still surfaced so the caller can log it next to the approval.
@@ -338,41 +214,8 @@ describe("runTurnBoundary", () => {
338
214
  expect(result.unattributedHookBlocks.map((b) => b.toolCallId)).toEqual(["tc-theirs"]);
339
215
  });
340
216
 
341
- it("excludes a kinded (secret) deny from the flowed-edit stamp (full-ledger deniedTokens)", async () => {
342
- const status = newStatus();
343
- const baseline = await captureBaselineToLedger({
344
- status, gitRoot: repo, executionId: EXEC_ID, changeSetId: CHANGE_SET_ID,
345
- });
346
-
347
- // One edit genuinely flowed (tree changed + streamed row); one secret-like
348
- // write was hard-blocked (FAILED row + kind:"secret" entry, tree untouched).
349
- await write("notes.md", "original notes\nplus a real edit\n");
350
- status.messages.push(streamedEdit("tc-flowed", "notes.md", "original notes\nplus a real edit\n"));
351
- const secretRow = hookBlockedCall("tc-secret", "edit", { path: ".env" });
352
- status.messages.push(
353
- create(AgentMessageSchema, { type: MessageType.MESSAGE_AI, toolCalls: [secretRow] }),
354
- );
355
- await appendLedgerEntry({ toolName: "Write", token: toolCallIdentityToken(secretRow), kind: "secret" });
356
-
357
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
358
-
359
- // The flowed edit is captured + stamped; the secret-blocked row is NOT
360
- // stamped into a change set that does not contain its file — every ledger
361
- // kind means "this action did not execute", so the stamp uses the FULL set.
362
- expect(result.waiting).toBe(true);
363
- expect(result.capturedChangeCount).toBe(1);
364
- expect(status.messages[0].toolCalls[0].fileChangeSetId).toBe(CHANGE_SET_ID);
365
- expect(secretRow.fileChangeSetId).toBe("");
366
- });
367
-
368
217
  it("waits for the denial-stop cancel to settle before reading the ledger", async () => {
369
218
  const status = newStatus();
370
- const baseline = await captureBaselineToLedger({
371
- status,
372
- gitRoot: repo,
373
- executionId: EXEC_ID,
374
- changeSetId: CHANGE_SET_ID,
375
- });
376
219
 
377
220
  const shellCall = create(ToolCallSchema, {
378
221
  id: "tc-late",
@@ -398,7 +241,7 @@ describe("runTurnBoundary", () => {
398
241
  })();
399
242
 
400
243
  const result = await runTurnBoundary(
401
- boundaryOpts(status, baseline, { denialCancelSettled }),
244
+ boundaryOpts(status, { denialCancelSettled }),
402
245
  );
403
246
 
404
247
  expect(result.deniedToolCallCount).toBe(1);
@@ -431,15 +274,9 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
431
274
 
432
275
  it("settles the incident shape to INTERRUPTED and discloses it (regression: aex_01m1a6ww)", async () => {
433
276
  const status = newStatus();
434
- const baseline = await captureBaselineToLedger({
435
- status,
436
- gitRoot: repo,
437
- executionId: EXEC_ID,
438
- changeSetId: CHANGE_SET_ID,
439
- });
440
277
  status.messages.push(hangingGenerateImage("tc-genimage-1"));
441
278
 
442
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
279
+ const result = await runTurnBoundary(boundaryOpts(status));
443
280
 
444
281
  // The turn completes (no pause) — but not silently.
445
282
  expect(result.waiting).toBe(false);
@@ -461,39 +298,52 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
461
298
  expect(last.content).toContain("No approval is pending");
462
299
  });
463
300
 
464
- it("leaves non-terminal rows to the pause machinery on a PAUSING turn", async () => {
301
+ it("leaves non-terminal rows to the pause machinery on a PAUSING turn (a denial pauses)", async () => {
465
302
  const status = newStatus();
466
- const baseline = await captureBaselineToLedger({
467
- status,
468
- gitRoot: repo,
469
- executionId: EXEC_ID,
470
- changeSetId: CHANGE_SET_ID,
303
+ // Our hook denied a shell — the turn pauses for that approval…
304
+ const ourGated = create(ToolCallSchema, {
305
+ id: "tc-ours", name: "shell",
306
+ status: ToolCallStatus.TOOL_CALL_RUNNING,
307
+ args: { command: "rm -rf build" },
471
308
  });
472
- // A captured file change makes the turn pause…
473
- await write("notes.md", "original notes\npaused-turn edit\n");
474
- status.messages.push(
475
- streamedEdit("tc-edit-1", "notes.md", "original notes\npaused-turn edit\n"),
476
- );
309
+ status.messages.push(create(AgentMessageSchema, { type: MessageType.MESSAGE_AI, toolCalls: [ourGated] }));
310
+ await appendLedgerEntry({ toolName: "shell", token: toolCallIdentityToken(ourGated), kind: "approval" });
477
311
  // …while a hanging row rides the same turn.
478
312
  status.messages.push(hangingGenerateImage("tc-genimage-2"));
479
313
 
480
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
314
+ const result = await runTurnBoundary(boundaryOpts(status));
481
315
 
482
316
  expect(result.waiting).toBe(true);
483
317
  expect(result.settledUnresolvedCount).toBe(0);
484
- // Untouched by THIS sweep (a pausing turn's rows belong to the reconcile /
485
- // collapse machinery, which has its own treatment for orphaned attempts).
486
- expect(status.messages[1].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_RUNNING);
318
+ // Untouched by THIS sweep: a pausing turn's rows belong to the reconcile /
319
+ // collapse machinery, which has its own treatment for an attempt that
320
+ // streamed after the gate (the hidden SKIPPED twin), never #965's
321
+ // INTERRUPTED-with-disclosure.
322
+ const hung = status.messages[1].toolCalls[0];
323
+ expect(hung.status).not.toBe(ToolCallStatus.TOOL_CALL_INTERRUPTED);
324
+ expect(isToolCallRowHidden(hung), "collapsed by the reconcile, not settled by the sweep").toBe(true);
325
+ });
326
+
327
+ it("a turn whose only change is a flowed file edit is COMPLETING here: the hung row is settled before the runtime's review (F-M4-P9)", async () => {
328
+ const status = newStatus();
329
+ // The edit flowed and the tree changed — until S3 M4 that made the turn
330
+ // `waiting` and hid the hung row behind the review; the runtime captures
331
+ // the edit after this boundary, so the boundary now tells the truth
332
+ // about the row first.
333
+ await write("notes.md", "original notes\nflowed edit\n");
334
+ status.messages.push(streamedEdit("tc-edit-1", "notes.md", "original notes\nflowed edit\n"));
335
+ status.messages.push(hangingGenerateImage("tc-genimage-2"));
336
+
337
+ const result = await runTurnBoundary(boundaryOpts(status));
338
+
339
+ expect(result.waiting).toBe(false);
340
+ expect(result.settledUnresolvedCount).toBe(1);
341
+ expect(status.messages[1].toolCalls[0].status).toBe(ToolCallStatus.TOOL_CALL_INTERRUPTED);
342
+ expect(status.messages[0].toolCalls[0].fileChangeSetId, "the stamp is the runtime's, after this boundary").toBe("");
487
343
  });
488
344
 
489
345
  it("never settles a ledger-attributed row — that is the kinded machinery's call", async () => {
490
346
  const status = newStatus();
491
- const baseline = await captureBaselineToLedger({
492
- status,
493
- gitRoot: repo,
494
- executionId: EXEC_ID,
495
- changeSetId: CHANGE_SET_ID,
496
- });
497
347
  const secretWrite = create(ToolCallSchema, {
498
348
  id: "tc-secret-1",
499
349
  name: "edit",
@@ -515,7 +365,7 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
515
365
  "utf-8",
516
366
  );
517
367
 
518
- const result = await runTurnBoundary(boundaryOpts(status, baseline));
368
+ const result = await runTurnBoundary(boundaryOpts(status));
519
369
 
520
370
  expect(result.settledUnresolvedCount).toBe(0);
521
371
  expect(secretWrite.status).toBe(ToolCallStatus.TOOL_CALL_PENDING);
@@ -523,12 +373,6 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
523
373
 
524
374
  it("scopes to THIS turn: seeded prior-turn rows and terminal rows are untouched", async () => {
525
375
  const status = newStatus();
526
- const baseline = await captureBaselineToLedger({
527
- status,
528
- gitRoot: repo,
529
- executionId: EXEC_ID,
530
- changeSetId: CHANGE_SET_ID,
531
- });
532
376
  // Message 0 is seeded prior-turn context (already adjudicated elsewhere).
533
377
  status.messages.push(hangingGenerateImage("tc-prior-turn"));
534
378
  // Message 1 opens this turn: one real terminal row.
@@ -547,7 +391,7 @@ describe("runTurnBoundary — unresolved tool calls on a completing turn (issue
547
391
  );
548
392
 
549
393
  const result = await runTurnBoundary(
550
- boundaryOpts(status, baseline, { turnStartMessageIndex: 1 }),
394
+ boundaryOpts(status, { turnStartMessageIndex: 1 }),
551
395
  );
552
396
 
553
397
  expect(result.settledUnresolvedCount).toBe(0);
@@ -2,8 +2,7 @@
2
2
  * Unit tests for the Cursor harness's shared stream seam (turn-stream.ts).
3
3
  *
4
4
  * These lock the behaviors the old bare retry loops used to DROP — live persist,
5
- * DD-32/DD-33 mid-run progress, sub-agent tracking, the first-denial early stop
6
- * — and the loop's side of the adapter contract: progress reported per event
5
+ * sub-agent tracking, the first-denial early stop — and the loop's side of the adapter contract: progress reported per event
7
6
  * and per delta, usage reported priced, the persist awaited, and the runtime's
8
7
  * stop signal honoured at every event boundary and inside a blocked pull by
9
8
  * cancelling the SDK run. Since S2 M3 the loop no longer decides WHY it
@@ -30,7 +29,6 @@ import {
30
29
  type StreamableRun,
31
30
  type TurnStreamState,
32
31
  } from "../turn-stream.js";
33
- import type { ProgressSubstrate } from "../../../shared/filereview/progress.js";
34
32
 
35
33
  // A stream event is only inspected by the loop for `type`/`name`/`status`/
36
34
  // `message`; the accumulator (stubbed) owns the rest, so a minimal cast is safe.
@@ -109,9 +107,6 @@ function buildDeps(overrides: Partial<CursorTurnStreamDeps> = {}): BuiltDeps {
109
107
  // contentDirty (accumulator.isDirty) forces the persist, so shouldSendUpdate
110
108
  // is never consulted; markUpdateSent must still exist.
111
109
  scheduler: { shouldSendUpdate: () => false, markUpdateSent: vi.fn() },
112
- progressSubstrate: undefined,
113
- progressState: { lastAtMs: 0 },
114
- changeSetId: "exec-test:0",
115
110
  hitlDir: undefined,
116
111
  ...overrides,
117
112
  } as unknown as CursorTurnStreamDeps;
@@ -150,26 +145,6 @@ describe("consumeCursorTurnStream", () => {
150
145
  expect(accumulator.trackSubAgentExecution).toHaveBeenCalledTimes(1);
151
146
  });
152
147
 
153
- it("attaches DD-32/DD-33 mid-run progress when a substrate is present", async () => {
154
- const capture = vi.fn(async () => ({ delta: { entries: [] }, changed: true }));
155
- const progressSubstrate = { capture } as unknown as ProgressSubstrate;
156
- const { deps, sink } = buildDeps({ progressSubstrate });
157
-
158
- await consumeCursorTurnStream(mockRun([ev({ type: "assistant" })]), deps);
159
-
160
- expect(capture).toHaveBeenCalled();
161
- // changed:true → the transient snapshot is attached to status.
162
- expect(sink.status.fileChangeProgress).toBeDefined();
163
- });
164
-
165
- it("does not touch progress when no substrate is configured", async () => {
166
- const { deps, sink } = buildDeps({ progressSubstrate: undefined });
167
-
168
- await consumeCursorTurnStream(mockRun([ev({ type: "assistant" })]), deps);
169
-
170
- expect(sink.status.fileChangeProgress).toBeUndefined();
171
- });
172
-
173
148
  it("captures a stream ERROR status message onto state.streamErrorMessage", async () => {
174
149
  const { deps, state } = buildDeps();
175
150
 
@@ -37,11 +37,13 @@
37
37
  * pins it, which is what lets the contract kit run this adapter outside any
38
38
  * activity context).
39
39
  *
40
- * The file-review boundary (`turn-boundary.ts`) runs whole inside `turn.ts`
41
- * for S2 (Q-S2-1): five of its six steps read the denial ledger, this
42
- * harness's deny-and-retry primitive. S3 lifts the capture into the runtime
43
- * with both harnesses' captures in view; `types.ts`'s "the file-review
44
- * boundary is the runtime's" becomes true then.
40
+ * The turn boundary (`turn-boundary.ts`) runs inside `turn.ts` and reads
41
+ * this harness's deny-and-retry evidence the denial ledger — into WAITING
42
+ * rows and settled rows. The file-review capture is NOT here since S3 M4:
43
+ * the runtime pins the baseline before this adapter runs and captures the
44
+ * whole turn's tree after it returns (`harness/capture.ts`); what this
45
+ * adapter contributes is the hook sidecar it binds as the runtime's CAS
46
+ * observations (`turn-setup.ts` `installGate`).
45
47
  *
46
48
  * Extracted from `index.ts` `createCursorActivities` at S2 M3b; split from
47
49
  * the turn body at S2 M5. The seventeen hermetic goldens under
@@ -105,8 +105,11 @@ export const SALIENT_ARG_FIELDS = ["file_path", "path", "target_notebook", "comm
105
105
  * `edit`/`shell`/`delete` all return true. Only mutating/destructive tools are
106
106
  * gated; everything else (read-only built-ins, and — at the hook layer —
107
107
  * auto-approved MCP tools) is allowed. This "gate the dangerous set, allow the
108
- * rest" model mirrors the native harness's resolveToolApproval. It is
109
- * deliberately fail-OPEN for unknown tools: the merged MCP policy map carries
108
+ * rest" model is the platform's one approval rule, read through the shared
109
+ * `approvalCategory` / `toolApprovalCategory` (`shared/tool-kind.ts`) that the
110
+ * native gate (`middleware/approval-gate.ts` `resolveToolApproval`) also
111
+ * reads — one taxonomy, two enforcement points. It is deliberately fail-OPEN
112
+ * for unknown tools: the merged MCP policy map carries
110
113
  * only the tools that REQUIRE approval, so a fail-closed default would wrongly
111
114
  * deny every auto-approved MCP tool, which the hook cannot distinguish from an
112
115
  * unknown built-in by name.