@stigmer/runner 0.1.0-dev.20261017020314.g644422724c27

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 (2029) hide show
  1. package/LICENSE +194 -0
  2. package/README.md +310 -0
  3. package/dist/.build-fingerprint +1 -0
  4. package/dist/__test-utils__/approval-contract/hook-commands.d.ts +25 -0
  5. package/dist/__test-utils__/approval-contract/hook-commands.js +87 -0
  6. package/dist/__test-utils__/approval-contract/hook-commands.js.map +1 -0
  7. package/dist/__test-utils__/approval-contract/types.d.ts +326 -0
  8. package/dist/__test-utils__/approval-contract/types.js +24 -0
  9. package/dist/__test-utils__/approval-contract/types.js.map +1 -0
  10. package/dist/__test-utils__/approval-log.d.ts +34 -0
  11. package/dist/__test-utils__/approval-log.js +126 -0
  12. package/dist/__test-utils__/approval-log.js.map +1 -0
  13. package/dist/__test-utils__/execution-record-fixture.d.ts +121 -0
  14. package/dist/__test-utils__/execution-record-fixture.js +134 -0
  15. package/dist/__test-utils__/execution-record-fixture.js.map +1 -0
  16. package/dist/__test-utils__/file-review-projection.d.ts +45 -0
  17. package/dist/__test-utils__/file-review-projection.js +61 -0
  18. package/dist/__test-utils__/file-review-projection.js.map +1 -0
  19. package/dist/__test-utils__/harness-contract/types.d.ts +188 -0
  20. package/dist/__test-utils__/harness-contract/types.js +64 -0
  21. package/dist/__test-utils__/harness-contract/types.js.map +1 -0
  22. package/dist/__test-utils__/hermetic-activity.d.ts +450 -0
  23. package/dist/__test-utils__/hermetic-activity.js +883 -0
  24. package/dist/__test-utils__/hermetic-activity.js.map +1 -0
  25. package/dist/__test-utils__/loopback-host.d.ts +23 -0
  26. package/dist/__test-utils__/loopback-host.js +45 -0
  27. package/dist/__test-utils__/loopback-host.js.map +1 -0
  28. package/dist/__test-utils__/mock-client.d.ts +13 -0
  29. package/dist/__test-utils__/mock-client.js +46 -0
  30. package/dist/__test-utils__/mock-client.js.map +1 -0
  31. package/dist/__test-utils__/mock-workspace.d.ts +15 -0
  32. package/dist/__test-utils__/mock-workspace.js +21 -0
  33. package/dist/__test-utils__/mock-workspace.js.map +1 -0
  34. package/dist/__test-utils__/model-registry-fixture.d.ts +111 -0
  35. package/dist/__test-utils__/model-registry-fixture.js +109 -0
  36. package/dist/__test-utils__/model-registry-fixture.js.map +1 -0
  37. package/dist/__test-utils__/turn-input-fixture.d.ts +60 -0
  38. package/dist/__test-utils__/turn-input-fixture.js +129 -0
  39. package/dist/__test-utils__/turn-input-fixture.js.map +1 -0
  40. package/dist/activities/attach-session.d.ts +34 -0
  41. package/dist/activities/attach-session.js +94 -0
  42. package/dist/activities/attach-session.js.map +1 -0
  43. package/dist/activities/ensure-thread.d.ts +24 -0
  44. package/dist/activities/ensure-thread.js +44 -0
  45. package/dist/activities/ensure-thread.js.map +1 -0
  46. package/dist/activities/execute-cursor/__test-utils__/contract-subject.d.ts +107 -0
  47. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +392 -0
  48. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -0
  49. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.d.ts +251 -0
  50. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js +254 -0
  51. package/dist/activities/execute-cursor/__test-utils__/cursor-hook-harness.js.map +1 -0
  52. package/dist/activities/execute-cursor/__test-utils__/fold.d.ts +62 -0
  53. package/dist/activities/execute-cursor/__test-utils__/fold.js +94 -0
  54. package/dist/activities/execute-cursor/__test-utils__/fold.js.map +1 -0
  55. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.d.ts +34 -0
  56. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js +287 -0
  57. package/dist/activities/execute-cursor/__test-utils__/gateway-substrate.js.map +1 -0
  58. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +202 -0
  59. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +306 -0
  60. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -0
  61. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.d.ts +176 -0
  62. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js +278 -0
  63. package/dist/activities/execute-cursor/__test-utils__/scripted-agent.js.map +1 -0
  64. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.d.ts +182 -0
  65. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js +241 -0
  66. package/dist/activities/execute-cursor/__test-utils__/scripted-sdk.js.map +1 -0
  67. package/dist/activities/execute-cursor/adapter.d.ts +63 -0
  68. package/dist/activities/execute-cursor/adapter.js +141 -0
  69. package/dist/activities/execute-cursor/adapter.js.map +1 -0
  70. package/dist/activities/execute-cursor/agent-session-cache.d.ts +72 -0
  71. package/dist/activities/execute-cursor/agent-session-cache.js +186 -0
  72. package/dist/activities/execute-cursor/agent-session-cache.js.map +1 -0
  73. package/dist/activities/execute-cursor/approval-policy.d.ts +67 -0
  74. package/dist/activities/execute-cursor/approval-policy.js +101 -0
  75. package/dist/activities/execute-cursor/approval-policy.js.map +1 -0
  76. package/dist/activities/execute-cursor/approval-state.d.ts +657 -0
  77. package/dist/activities/execute-cursor/approval-state.js +682 -0
  78. package/dist/activities/execute-cursor/approval-state.js.map +1 -0
  79. package/dist/activities/execute-cursor/boundary-rows.d.ts +455 -0
  80. package/dist/activities/execute-cursor/boundary-rows.js +1268 -0
  81. package/dist/activities/execute-cursor/boundary-rows.js.map +1 -0
  82. package/dist/activities/execute-cursor/cas-observations.d.ts +126 -0
  83. package/dist/activities/execute-cursor/cas-observations.js +240 -0
  84. package/dist/activities/execute-cursor/cas-observations.js.map +1 -0
  85. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +37 -0
  86. package/dist/activities/execute-cursor/cursor-capabilities.js +74 -0
  87. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -0
  88. package/dist/activities/execute-cursor/cursor-event-recorder.d.ts +43 -0
  89. package/dist/activities/execute-cursor/cursor-event-recorder.js +88 -0
  90. package/dist/activities/execute-cursor/cursor-event-recorder.js.map +1 -0
  91. package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +58 -0
  92. package/dist/activities/execute-cursor/cursor-mcp-config.js +86 -0
  93. package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -0
  94. package/dist/activities/execute-cursor/cursor-mode.d.ts +32 -0
  95. package/dist/activities/execute-cursor/cursor-mode.js +36 -0
  96. package/dist/activities/execute-cursor/cursor-mode.js.map +1 -0
  97. package/dist/activities/execute-cursor/error-classifier.d.ts +138 -0
  98. package/dist/activities/execute-cursor/error-classifier.js +330 -0
  99. package/dist/activities/execute-cursor/error-classifier.js.map +1 -0
  100. package/dist/activities/execute-cursor/fetch-interceptor.d.ts +56 -0
  101. package/dist/activities/execute-cursor/fetch-interceptor.js +378 -0
  102. package/dist/activities/execute-cursor/fetch-interceptor.js.map +1 -0
  103. package/dist/activities/execute-cursor/hook-scope.d.ts +143 -0
  104. package/dist/activities/execute-cursor/hook-scope.js +149 -0
  105. package/dist/activities/execute-cursor/hook-scope.js.map +1 -0
  106. package/dist/activities/execute-cursor/hook-script.d.ts +172 -0
  107. package/dist/activities/execute-cursor/hook-script.js +1204 -0
  108. package/dist/activities/execute-cursor/hook-script.js.map +1 -0
  109. package/dist/activities/execute-cursor/hook-server.d.ts +152 -0
  110. package/dist/activities/execute-cursor/hook-server.js +422 -0
  111. package/dist/activities/execute-cursor/hook-server.js.map +1 -0
  112. package/dist/activities/execute-cursor/hook-tool-hiding.d.ts +37 -0
  113. package/dist/activities/execute-cursor/hook-tool-hiding.js +58 -0
  114. package/dist/activities/execute-cursor/hook-tool-hiding.js.map +1 -0
  115. package/dist/activities/execute-cursor/hook-views.d.ts +74 -0
  116. package/dist/activities/execute-cursor/hook-views.js +180 -0
  117. package/dist/activities/execute-cursor/hook-views.js.map +1 -0
  118. package/dist/activities/execute-cursor/http2-interceptor.d.ts +98 -0
  119. package/dist/activities/execute-cursor/http2-interceptor.js +218 -0
  120. package/dist/activities/execute-cursor/http2-interceptor.js.map +1 -0
  121. package/dist/activities/execute-cursor/model-pricing-data.d.ts +39 -0
  122. package/dist/activities/execute-cursor/model-pricing-data.js +109 -0
  123. package/dist/activities/execute-cursor/model-pricing-data.js.map +1 -0
  124. package/dist/activities/execute-cursor/model-pricing.d.ts +51 -0
  125. package/dist/activities/execute-cursor/model-pricing.js +160 -0
  126. package/dist/activities/execute-cursor/model-pricing.js.map +1 -0
  127. package/dist/activities/execute-cursor/prompt-builder.d.ts +437 -0
  128. package/dist/activities/execute-cursor/prompt-builder.js +719 -0
  129. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -0
  130. package/dist/activities/execute-cursor/rejection-capture.d.ts +27 -0
  131. package/dist/activities/execute-cursor/rejection-capture.js +78 -0
  132. package/dist/activities/execute-cursor/rejection-capture.js.map +1 -0
  133. package/dist/activities/execute-cursor/run-telemetry.d.ts +61 -0
  134. package/dist/activities/execute-cursor/run-telemetry.js +149 -0
  135. package/dist/activities/execute-cursor/run-telemetry.js.map +1 -0
  136. package/dist/activities/execute-cursor/sdk-warmup.d.ts +53 -0
  137. package/dist/activities/execute-cursor/sdk-warmup.js +70 -0
  138. package/dist/activities/execute-cursor/sdk-warmup.js.map +1 -0
  139. package/dist/activities/execute-cursor/service-tier.d.ts +68 -0
  140. package/dist/activities/execute-cursor/service-tier.js +200 -0
  141. package/dist/activities/execute-cursor/service-tier.js.map +1 -0
  142. package/dist/activities/execute-cursor/session-lifecycle.d.ts +247 -0
  143. package/dist/activities/execute-cursor/session-lifecycle.js +330 -0
  144. package/dist/activities/execute-cursor/session-lifecycle.js.map +1 -0
  145. package/dist/activities/execute-cursor/session-store.d.ts +99 -0
  146. package/dist/activities/execute-cursor/session-store.js +156 -0
  147. package/dist/activities/execute-cursor/session-store.js.map +1 -0
  148. package/dist/activities/execute-cursor/sub-agent-steps.d.ts +79 -0
  149. package/dist/activities/execute-cursor/sub-agent-steps.js +180 -0
  150. package/dist/activities/execute-cursor/sub-agent-steps.js.map +1 -0
  151. package/dist/activities/execute-cursor/subagent-config.d.ts +61 -0
  152. package/dist/activities/execute-cursor/subagent-config.js +102 -0
  153. package/dist/activities/execute-cursor/subagent-config.js.map +1 -0
  154. package/dist/activities/execute-cursor/tool-result.d.ts +49 -0
  155. package/dist/activities/execute-cursor/tool-result.js +130 -0
  156. package/dist/activities/execute-cursor/tool-result.js.map +1 -0
  157. package/dist/activities/execute-cursor/translator.d.ts +183 -0
  158. package/dist/activities/execute-cursor/translator.js +485 -0
  159. package/dist/activities/execute-cursor/translator.js.map +1 -0
  160. package/dist/activities/execute-cursor/turn-boundary.d.ts +124 -0
  161. package/dist/activities/execute-cursor/turn-boundary.js +210 -0
  162. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -0
  163. package/dist/activities/execute-cursor/turn-recovery.d.ts +62 -0
  164. package/dist/activities/execute-cursor/turn-recovery.js +208 -0
  165. package/dist/activities/execute-cursor/turn-recovery.js.map +1 -0
  166. package/dist/activities/execute-cursor/turn-settle.d.ts +59 -0
  167. package/dist/activities/execute-cursor/turn-settle.js +512 -0
  168. package/dist/activities/execute-cursor/turn-settle.js.map +1 -0
  169. package/dist/activities/execute-cursor/turn-setup.d.ts +281 -0
  170. package/dist/activities/execute-cursor/turn-setup.js +739 -0
  171. package/dist/activities/execute-cursor/turn-setup.js.map +1 -0
  172. package/dist/activities/execute-cursor/turn-stream.d.ts +133 -0
  173. package/dist/activities/execute-cursor/turn-stream.js +239 -0
  174. package/dist/activities/execute-cursor/turn-stream.js.map +1 -0
  175. package/dist/activities/execute-cursor/turn.d.ts +46 -0
  176. package/dist/activities/execute-cursor/turn.js +247 -0
  177. package/dist/activities/execute-cursor/turn.js.map +1 -0
  178. package/dist/activities/execute-cursor/usage-pricing.d.ts +38 -0
  179. package/dist/activities/execute-cursor/usage-pricing.js +50 -0
  180. package/dist/activities/execute-cursor/usage-pricing.js.map +1 -0
  181. package/dist/activities/execute-cursor/workspace-hook-files.d.ts +116 -0
  182. package/dist/activities/execute-cursor/workspace-hook-files.js +390 -0
  183. package/dist/activities/execute-cursor/workspace-hook-files.js.map +1 -0
  184. package/dist/activities/execute-cursor/workspace-setup.d.ts +148 -0
  185. package/dist/activities/execute-cursor/workspace-setup.js +444 -0
  186. package/dist/activities/execute-cursor/workspace-setup.js.map +1 -0
  187. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +102 -0
  188. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +361 -0
  189. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
  190. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.d.ts +33 -0
  191. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js +423 -0
  192. package/dist/activities/execute-deep-agent/__test-utils__/gateway-substrate.js.map +1 -0
  193. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +224 -0
  194. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +307 -0
  195. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
  196. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
  197. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
  198. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
  199. package/dist/activities/execute-deep-agent/__test-utils__/paused-session-fixture.d.ts +76 -0
  200. package/dist/activities/execute-deep-agent/__test-utils__/paused-session-fixture.js +112 -0
  201. package/dist/activities/execute-deep-agent/__test-utils__/paused-session-fixture.js.map +1 -0
  202. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +53 -0
  203. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +71 -0
  204. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
  205. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +305 -0
  206. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +368 -0
  207. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -0
  208. package/dist/activities/execute-deep-agent/__test-utils__/think-bound-session.d.ts +17 -0
  209. package/dist/activities/execute-deep-agent/__test-utils__/think-bound-session.js +23 -0
  210. package/dist/activities/execute-deep-agent/__test-utils__/think-bound-session.js.map +1 -0
  211. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.d.ts +80 -0
  212. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js +195 -0
  213. package/dist/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.js.map +1 -0
  214. package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
  215. package/dist/activities/execute-deep-agent/adapter.js +79 -0
  216. package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
  217. package/dist/activities/execute-deep-agent/approval-file-change.d.ts +54 -0
  218. package/dist/activities/execute-deep-agent/approval-file-change.js +68 -0
  219. package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -0
  220. package/dist/activities/execute-deep-agent/auto-publish.d.ts +17 -0
  221. package/dist/activities/execute-deep-agent/auto-publish.js +71 -0
  222. package/dist/activities/execute-deep-agent/auto-publish.js.map +1 -0
  223. package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +84 -0
  224. package/dist/activities/execute-deep-agent/cas-capture-backend.js +106 -0
  225. package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -0
  226. package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +83 -0
  227. package/dist/activities/execute-deep-agent/cas-capture-observer.js +117 -0
  228. package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -0
  229. package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +32 -0
  230. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +45 -0
  231. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
  232. package/dist/activities/execute-deep-agent/deepagents-profiles.d.ts +30 -0
  233. package/dist/activities/execute-deep-agent/deepagents-profiles.js +46 -0
  234. package/dist/activities/execute-deep-agent/deepagents-profiles.js.map +1 -0
  235. package/dist/activities/execute-deep-agent/engine-tools.d.ts +32 -0
  236. package/dist/activities/execute-deep-agent/engine-tools.js +32 -0
  237. package/dist/activities/execute-deep-agent/engine-tools.js.map +1 -0
  238. package/dist/activities/execute-deep-agent/hitl.d.ts +126 -0
  239. package/dist/activities/execute-deep-agent/hitl.js +194 -0
  240. package/dist/activities/execute-deep-agent/hitl.js.map +1 -0
  241. package/dist/activities/execute-deep-agent/hooks-setup.d.ts +25 -0
  242. package/dist/activities/execute-deep-agent/hooks-setup.js +59 -0
  243. package/dist/activities/execute-deep-agent/hooks-setup.js.map +1 -0
  244. package/dist/activities/execute-deep-agent/inline-publisher.d.ts +83 -0
  245. package/dist/activities/execute-deep-agent/inline-publisher.js +152 -0
  246. package/dist/activities/execute-deep-agent/inline-publisher.js.map +1 -0
  247. package/dist/activities/execute-deep-agent/platform-route.d.ts +145 -0
  248. package/dist/activities/execute-deep-agent/platform-route.js +237 -0
  249. package/dist/activities/execute-deep-agent/platform-route.js.map +1 -0
  250. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +189 -0
  251. package/dist/activities/execute-deep-agent/prompt-builder.js +369 -0
  252. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -0
  253. package/dist/activities/execute-deep-agent/resumed-history.d.ts +25 -0
  254. package/dist/activities/execute-deep-agent/resumed-history.js +47 -0
  255. package/dist/activities/execute-deep-agent/resumed-history.js.map +1 -0
  256. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +49 -0
  257. package/dist/activities/execute-deep-agent/streaming-side-effects.js +73 -0
  258. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -0
  259. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +253 -0
  260. package/dist/activities/execute-deep-agent/subagent-transformer.js +474 -0
  261. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -0
  262. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +99 -0
  263. package/dist/activities/execute-deep-agent/subagent-wiring.js +119 -0
  264. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -0
  265. package/dist/activities/execute-deep-agent/todo-list.d.ts +40 -0
  266. package/dist/activities/execute-deep-agent/todo-list.js +51 -0
  267. package/dist/activities/execute-deep-agent/todo-list.js.map +1 -0
  268. package/dist/activities/execute-deep-agent/translator.d.ts +167 -0
  269. package/dist/activities/execute-deep-agent/translator.js +521 -0
  270. package/dist/activities/execute-deep-agent/translator.js.map +1 -0
  271. package/dist/activities/execute-deep-agent/turn-settle.d.ts +48 -0
  272. package/dist/activities/execute-deep-agent/turn-settle.js +141 -0
  273. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
  274. package/dist/activities/execute-deep-agent/turn-setup.d.ts +281 -0
  275. package/dist/activities/execute-deep-agent/turn-setup.js +687 -0
  276. package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
  277. package/dist/activities/execute-deep-agent/turn-stream.d.ts +105 -0
  278. package/dist/activities/execute-deep-agent/turn-stream.js +236 -0
  279. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
  280. package/dist/activities/execute-deep-agent/turn.d.ts +48 -0
  281. package/dist/activities/execute-deep-agent/turn.js +136 -0
  282. package/dist/activities/execute-deep-agent/turn.js.map +1 -0
  283. package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +32 -0
  284. package/dist/activities/execute-deep-agent/v3-event-recorder.js +72 -0
  285. package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -0
  286. package/dist/activities/generate-session-subject.d.ts +93 -0
  287. package/dist/activities/generate-session-subject.js +285 -0
  288. package/dist/activities/generate-session-subject.js.map +1 -0
  289. package/dist/activities/list-plugin-tools.d.ts +76 -0
  290. package/dist/activities/list-plugin-tools.js +170 -0
  291. package/dist/activities/list-plugin-tools.js.map +1 -0
  292. package/dist/agent-host/channel.d.ts +93 -0
  293. package/dist/agent-host/channel.js +332 -0
  294. package/dist/agent-host/channel.js.map +1 -0
  295. package/dist/agent-host/codec.d.ts +290 -0
  296. package/dist/agent-host/codec.js +437 -0
  297. package/dist/agent-host/codec.js.map +1 -0
  298. package/dist/agent-host/entry.d.ts +56 -0
  299. package/dist/agent-host/entry.js +137 -0
  300. package/dist/agent-host/entry.js.map +1 -0
  301. package/dist/agent-host/environment.d.ts +36 -0
  302. package/dist/agent-host/environment.js +72 -0
  303. package/dist/agent-host/environment.js.map +1 -0
  304. package/dist/agent-host/failed-boot.d.ts +15 -0
  305. package/dist/agent-host/failed-boot.js +26 -0
  306. package/dist/agent-host/failed-boot.js.map +1 -0
  307. package/dist/agent-host/fs-service.d.ts +18 -0
  308. package/dist/agent-host/fs-service.js +133 -0
  309. package/dist/agent-host/fs-service.js.map +1 -0
  310. package/dist/agent-host/host-sink.d.ts +63 -0
  311. package/dist/agent-host/host-sink.js +136 -0
  312. package/dist/agent-host/host-sink.js.map +1 -0
  313. package/dist/agent-host/host.d.ts +48 -0
  314. package/dist/agent-host/host.js +191 -0
  315. package/dist/agent-host/host.js.map +1 -0
  316. package/dist/agent-host/hosting.d.ts +80 -0
  317. package/dist/agent-host/hosting.js +126 -0
  318. package/dist/agent-host/hosting.js.map +1 -0
  319. package/dist/agent-host/protocol.d.ts +478 -0
  320. package/dist/agent-host/protocol.js +77 -0
  321. package/dist/agent-host/protocol.js.map +1 -0
  322. package/dist/agent-host/remote-adapter.d.ts +64 -0
  323. package/dist/agent-host/remote-adapter.js +283 -0
  324. package/dist/agent-host/remote-adapter.js.map +1 -0
  325. package/dist/agent-host/remote-fs.d.ts +19 -0
  326. package/dist/agent-host/remote-fs.js +120 -0
  327. package/dist/agent-host/remote-fs.js.map +1 -0
  328. package/dist/agent-host/supervisor.d.ts +149 -0
  329. package/dist/agent-host/supervisor.js +311 -0
  330. package/dist/agent-host/supervisor.js.map +1 -0
  331. package/dist/agent-proxy/cursor-lane.d.ts +124 -0
  332. package/dist/agent-proxy/cursor-lane.js +507 -0
  333. package/dist/agent-proxy/cursor-lane.js.map +1 -0
  334. package/dist/agent-proxy/lanes.d.ts +63 -0
  335. package/dist/agent-proxy/lanes.js +255 -0
  336. package/dist/agent-proxy/lanes.js.map +1 -0
  337. package/dist/agent-proxy/loopback-certificate.d.ts +27 -0
  338. package/dist/agent-proxy/loopback-certificate.js +115 -0
  339. package/dist/agent-proxy/loopback-certificate.js.map +1 -0
  340. package/dist/agent-proxy/otlp-forward.d.ts +67 -0
  341. package/dist/agent-proxy/otlp-forward.js +170 -0
  342. package/dist/agent-proxy/otlp-forward.js.map +1 -0
  343. package/dist/agent-proxy/relay.d.ts +67 -0
  344. package/dist/agent-proxy/relay.js +164 -0
  345. package/dist/agent-proxy/relay.js.map +1 -0
  346. package/dist/agent-proxy/server.d.ts +84 -0
  347. package/dist/agent-proxy/server.js +258 -0
  348. package/dist/agent-proxy/server.js.map +1 -0
  349. package/dist/attach/entry.d.ts +36 -0
  350. package/dist/attach/entry.js +69 -0
  351. package/dist/attach/entry.js.map +1 -0
  352. package/dist/attach/main.d.ts +14 -0
  353. package/dist/attach/main.js +25 -0
  354. package/dist/attach/main.js.map +1 -0
  355. package/dist/attach/push.d.ts +71 -0
  356. package/dist/attach/push.js +123 -0
  357. package/dist/attach/push.js.map +1 -0
  358. package/dist/attach/waiter.d.ts +108 -0
  359. package/dist/attach/waiter.js +323 -0
  360. package/dist/attach/waiter.js.map +1 -0
  361. package/dist/bootstrap.d.ts +80 -0
  362. package/dist/bootstrap.js +119 -0
  363. package/dist/bootstrap.js.map +1 -0
  364. package/dist/client/server-contracts.d.ts +51 -0
  365. package/dist/client/server-contracts.js +70 -0
  366. package/dist/client/server-contracts.js.map +1 -0
  367. package/dist/client/stigmer-client.d.ts +328 -0
  368. package/dist/client/stigmer-client.js +478 -0
  369. package/dist/client/stigmer-client.js.map +1 -0
  370. package/dist/client/token-claims.d.ts +40 -0
  371. package/dist/client/token-claims.js +88 -0
  372. package/dist/client/token-claims.js.map +1 -0
  373. package/dist/config.d.ts +216 -0
  374. package/dist/config.js +200 -0
  375. package/dist/config.js.map +1 -0
  376. package/dist/exit-backstop.d.ts +64 -0
  377. package/dist/exit-backstop.js +79 -0
  378. package/dist/exit-backstop.js.map +1 -0
  379. package/dist/gen/turn/ai/stigmer/runner/turn/v1/enum_pb.d.ts +1016 -0
  380. package/dist/gen/turn/ai/stigmer/runner/turn/v1/enum_pb.js +1035 -0
  381. package/dist/gen/turn/ai/stigmer/runner/turn/v1/enum_pb.js.map +1 -0
  382. package/dist/gen/turn/ai/stigmer/runner/turn/v1/ledger_pb.d.ts +402 -0
  383. package/dist/gen/turn/ai/stigmer/runner/turn/v1/ledger_pb.js +47 -0
  384. package/dist/gen/turn/ai/stigmer/runner/turn/v1/ledger_pb.js.map +1 -0
  385. package/dist/gen/turn/ai/stigmer/runner/turn/v1/rows_pb.d.ts +826 -0
  386. package/dist/gen/turn/ai/stigmer/runner/turn/v1/rows_pb.js +48 -0
  387. package/dist/gen/turn/ai/stigmer/runner/turn/v1/rows_pb.js.map +1 -0
  388. package/dist/gen-ai-conventions.d.ts +95 -0
  389. package/dist/gen-ai-conventions.js +102 -0
  390. package/dist/gen-ai-conventions.js.map +1 -0
  391. package/dist/harness/approval-answers.d.ts +104 -0
  392. package/dist/harness/approval-answers.js +136 -0
  393. package/dist/harness/approval-answers.js.map +1 -0
  394. package/dist/harness/approval-decisions.d.ts +50 -0
  395. package/dist/harness/approval-decisions.js +80 -0
  396. package/dist/harness/approval-decisions.js.map +1 -0
  397. package/dist/harness/capabilities.d.ts +149 -0
  398. package/dist/harness/capabilities.js +48 -0
  399. package/dist/harness/capabilities.js.map +1 -0
  400. package/dist/harness/capture.d.ts +154 -0
  401. package/dist/harness/capture.js +248 -0
  402. package/dist/harness/capture.js.map +1 -0
  403. package/dist/harness/cost-cap-watch.d.ts +31 -0
  404. package/dist/harness/cost-cap-watch.js +44 -0
  405. package/dist/harness/cost-cap-watch.js.map +1 -0
  406. package/dist/harness/events/emitter.d.ts +220 -0
  407. package/dist/harness/events/emitter.js +726 -0
  408. package/dist/harness/events/emitter.js.map +1 -0
  409. package/dist/harness/events/ids.d.ts +88 -0
  410. package/dist/harness/events/ids.js +136 -0
  411. package/dist/harness/events/ids.js.map +1 -0
  412. package/dist/harness/loaded-versions.d.ts +20 -0
  413. package/dist/harness/loaded-versions.js +70 -0
  414. package/dist/harness/loaded-versions.js.map +1 -0
  415. package/dist/harness/owed-undos.d.ts +119 -0
  416. package/dist/harness/owed-undos.js +200 -0
  417. package/dist/harness/owed-undos.js.map +1 -0
  418. package/dist/harness/persist-chokepoint.d.ts +113 -0
  419. package/dist/harness/persist-chokepoint.js +126 -0
  420. package/dist/harness/persist-chokepoint.js.map +1 -0
  421. package/dist/harness/registry.d.ts +108 -0
  422. package/dist/harness/registry.js +174 -0
  423. package/dist/harness/registry.js.map +1 -0
  424. package/dist/harness/run-span.d.ts +78 -0
  425. package/dist/harness/run-span.js +139 -0
  426. package/dist/harness/run-span.js.map +1 -0
  427. package/dist/harness/run-turn.d.ts +59 -0
  428. package/dist/harness/run-turn.js +749 -0
  429. package/dist/harness/run-turn.js.map +1 -0
  430. package/dist/harness/stop-controller.d.ts +65 -0
  431. package/dist/harness/stop-controller.js +70 -0
  432. package/dist/harness/stop-controller.js.map +1 -0
  433. package/dist/harness/terminal-table.d.ts +212 -0
  434. package/dist/harness/terminal-table.js +329 -0
  435. package/dist/harness/terminal-table.js.map +1 -0
  436. package/dist/harness/transcript/builder.d.ts +269 -0
  437. package/dist/harness/transcript/builder.js +842 -0
  438. package/dist/harness/transcript/builder.js.map +1 -0
  439. package/dist/harness/transcript/events.d.ts +236 -0
  440. package/dist/harness/transcript/events.js +55 -0
  441. package/dist/harness/transcript/events.js.map +1 -0
  442. package/dist/harness/transcript/resume-seed.d.ts +67 -0
  443. package/dist/harness/transcript/resume-seed.js +228 -0
  444. package/dist/harness/transcript/resume-seed.js.map +1 -0
  445. package/dist/harness/transcript/state.d.ts +111 -0
  446. package/dist/harness/transcript/state.js +147 -0
  447. package/dist/harness/transcript/state.js.map +1 -0
  448. package/dist/harness/turn-context.d.ts +923 -0
  449. package/dist/harness/turn-context.js +1448 -0
  450. package/dist/harness/turn-context.js.map +1 -0
  451. package/dist/harness/turn-timeline.d.ts +132 -0
  452. package/dist/harness/turn-timeline.js +213 -0
  453. package/dist/harness/turn-timeline.js.map +1 -0
  454. package/dist/harness/types.d.ts +700 -0
  455. package/dist/harness/types.js +72 -0
  456. package/dist/harness/types.js.map +1 -0
  457. package/dist/harness/usage-accumulator.d.ts +76 -0
  458. package/dist/harness/usage-accumulator.js +112 -0
  459. package/dist/harness/usage-accumulator.js.map +1 -0
  460. package/dist/harness-adapters.d.ts +40 -0
  461. package/dist/harness-adapters.js +45 -0
  462. package/dist/harness-adapters.js.map +1 -0
  463. package/dist/idle-watchdog.d.ts +11 -0
  464. package/dist/idle-watchdog.js +24 -0
  465. package/dist/idle-watchdog.js.map +1 -0
  466. package/dist/in-flight.d.ts +35 -0
  467. package/dist/in-flight.js +61 -0
  468. package/dist/in-flight.js.map +1 -0
  469. package/dist/index.d.ts +43 -0
  470. package/dist/index.js +42 -0
  471. package/dist/index.js.map +1 -0
  472. package/dist/interceptors/run-credential-activity.d.ts +24 -0
  473. package/dist/interceptors/run-credential-activity.js +36 -0
  474. package/dist/interceptors/run-credential-activity.js.map +1 -0
  475. package/dist/ipc-protocol-fixtures.d.ts +28 -0
  476. package/dist/ipc-protocol-fixtures.js +50 -0
  477. package/dist/ipc-protocol-fixtures.js.map +1 -0
  478. package/dist/ipc-protocol.d.ts +43 -0
  479. package/dist/ipc-protocol.js +20 -0
  480. package/dist/ipc-protocol.js.map +1 -0
  481. package/dist/main.d.ts +26 -0
  482. package/dist/main.js +451 -0
  483. package/dist/main.js.map +1 -0
  484. package/dist/middleware/advisory-message.d.ts +52 -0
  485. package/dist/middleware/advisory-message.js +58 -0
  486. package/dist/middleware/advisory-message.js.map +1 -0
  487. package/dist/middleware/approval-gate.d.ts +255 -0
  488. package/dist/middleware/approval-gate.js +502 -0
  489. package/dist/middleware/approval-gate.js.map +1 -0
  490. package/dist/middleware/cost-advisory.d.ts +65 -0
  491. package/dist/middleware/cost-advisory.js +185 -0
  492. package/dist/middleware/cost-advisory.js.map +1 -0
  493. package/dist/middleware/error-hints.d.ts +27 -0
  494. package/dist/middleware/error-hints.js +116 -0
  495. package/dist/middleware/error-hints.js.map +1 -0
  496. package/dist/middleware/execution-budget.d.ts +38 -0
  497. package/dist/middleware/execution-budget.js +168 -0
  498. package/dist/middleware/execution-budget.js.map +1 -0
  499. package/dist/middleware/index.d.ts +55 -0
  500. package/dist/middleware/index.js +80 -0
  501. package/dist/middleware/index.js.map +1 -0
  502. package/dist/middleware/loop-detection.d.ts +22 -0
  503. package/dist/middleware/loop-detection.js +161 -0
  504. package/dist/middleware/loop-detection.js.map +1 -0
  505. package/dist/middleware/otel-spans.d.ts +43 -0
  506. package/dist/middleware/otel-spans.js +281 -0
  507. package/dist/middleware/otel-spans.js.map +1 -0
  508. package/dist/middleware/path-normalization.d.ts +84 -0
  509. package/dist/middleware/path-normalization.js +161 -0
  510. package/dist/middleware/path-normalization.js.map +1 -0
  511. package/dist/middleware/tool-intent.d.ts +57 -0
  512. package/dist/middleware/tool-intent.js +152 -0
  513. package/dist/middleware/tool-intent.js.map +1 -0
  514. package/dist/middleware/tool-scope.d.ts +119 -0
  515. package/dist/middleware/tool-scope.js +159 -0
  516. package/dist/middleware/tool-scope.js.map +1 -0
  517. package/dist/middleware/tool-truncation.d.ts +16 -0
  518. package/dist/middleware/tool-truncation.js +67 -0
  519. package/dist/middleware/tool-truncation.js.map +1 -0
  520. package/dist/middleware/types.d.ts +119 -0
  521. package/dist/middleware/types.js +10 -0
  522. package/dist/middleware/types.js.map +1 -0
  523. package/dist/otel-export.d.ts +142 -0
  524. package/dist/otel-export.js +269 -0
  525. package/dist/otel-export.js.map +1 -0
  526. package/dist/otel-metrics.d.ts +22 -0
  527. package/dist/otel-metrics.js +47 -0
  528. package/dist/otel-metrics.js.map +1 -0
  529. package/dist/otel.d.ts +49 -0
  530. package/dist/otel.js +125 -0
  531. package/dist/otel.js.map +1 -0
  532. package/dist/payload-codecs.d.ts +17 -0
  533. package/dist/payload-codecs.js +45 -0
  534. package/dist/payload-codecs.js.map +1 -0
  535. package/dist/pipe-safety.d.ts +55 -0
  536. package/dist/pipe-safety.js +103 -0
  537. package/dist/pipe-safety.js.map +1 -0
  538. package/dist/pool-member.d.ts +61 -0
  539. package/dist/pool-member.js +51 -0
  540. package/dist/pool-member.js.map +1 -0
  541. package/dist/preflight.d.ts +77 -0
  542. package/dist/preflight.js +98 -0
  543. package/dist/preflight.js.map +1 -0
  544. package/dist/run-trace-id.d.ts +34 -0
  545. package/dist/run-trace-id.js +44 -0
  546. package/dist/run-trace-id.js.map +1 -0
  547. package/dist/runner-entry.d.ts +15 -0
  548. package/dist/runner-entry.js +17 -0
  549. package/dist/runner-entry.js.map +1 -0
  550. package/dist/runner-manager.d.ts +160 -0
  551. package/dist/runner-manager.js +590 -0
  552. package/dist/runner-manager.js.map +1 -0
  553. package/dist/runner-token-coordinator.d.ts +61 -0
  554. package/dist/runner-token-coordinator.js +89 -0
  555. package/dist/runner-token-coordinator.js.map +1 -0
  556. package/dist/runner.d.ts +155 -0
  557. package/dist/runner.js +392 -0
  558. package/dist/runner.js.map +1 -0
  559. package/dist/sandbox-token-renewal.d.ts +64 -0
  560. package/dist/sandbox-token-renewal.js +168 -0
  561. package/dist/sandbox-token-renewal.js.map +1 -0
  562. package/dist/shared/activity-input.d.ts +52 -0
  563. package/dist/shared/activity-input.js +34 -0
  564. package/dist/shared/activity-input.js.map +1 -0
  565. package/dist/shared/agent-fs.d.ts +144 -0
  566. package/dist/shared/agent-fs.js +171 -0
  567. package/dist/shared/agent-fs.js.map +1 -0
  568. package/dist/shared/agent-handover.d.ts +42 -0
  569. package/dist/shared/agent-handover.js +156 -0
  570. package/dist/shared/agent-handover.js.map +1 -0
  571. package/dist/shared/agent-identity.d.ts +96 -0
  572. package/dist/shared/agent-identity.js +153 -0
  573. package/dist/shared/agent-identity.js.map +1 -0
  574. package/dist/shared/agent-servers.d.ts +4 -0
  575. package/dist/shared/agent-servers.js +46 -0
  576. package/dist/shared/agent-servers.js.map +1 -0
  577. package/dist/shared/approval-canonicalize.d.ts +19 -0
  578. package/dist/shared/approval-canonicalize.js +119 -0
  579. package/dist/shared/approval-canonicalize.js.map +1 -0
  580. package/dist/shared/approval-fingerprint.d.ts +103 -0
  581. package/dist/shared/approval-fingerprint.js +110 -0
  582. package/dist/shared/approval-fingerprint.js.map +1 -0
  583. package/dist/shared/approval-policy.d.ts +323 -0
  584. package/dist/shared/approval-policy.js +375 -0
  585. package/dist/shared/approval-policy.js.map +1 -0
  586. package/dist/shared/archive-mount.d.ts +68 -0
  587. package/dist/shared/archive-mount.js +108 -0
  588. package/dist/shared/archive-mount.js.map +1 -0
  589. package/dist/shared/args-preview.d.ts +90 -0
  590. package/dist/shared/args-preview.js +121 -0
  591. package/dist/shared/args-preview.js.map +1 -0
  592. package/dist/shared/artifact-storage.d.ts +155 -0
  593. package/dist/shared/artifact-storage.js +373 -0
  594. package/dist/shared/artifact-storage.js.map +1 -0
  595. package/dist/shared/attachment-download-urls.d.ts +53 -0
  596. package/dist/shared/attachment-download-urls.js +68 -0
  597. package/dist/shared/attachment-download-urls.js.map +1 -0
  598. package/dist/shared/attachment-naming.d.ts +53 -0
  599. package/dist/shared/attachment-naming.js +59 -0
  600. package/dist/shared/attachment-naming.js.map +1 -0
  601. package/dist/shared/attachment-resolver.d.ts +124 -0
  602. package/dist/shared/attachment-resolver.js +322 -0
  603. package/dist/shared/attachment-resolver.js.map +1 -0
  604. package/dist/shared/attachment-vision.d.ts +245 -0
  605. package/dist/shared/attachment-vision.js +339 -0
  606. package/dist/shared/attachment-vision.js.map +1 -0
  607. package/dist/shared/attachment-zip.d.ts +85 -0
  608. package/dist/shared/attachment-zip.js +185 -0
  609. package/dist/shared/attachment-zip.js.map +1 -0
  610. package/dist/shared/blueprint-resolver.d.ts +175 -0
  611. package/dist/shared/blueprint-resolver.js +305 -0
  612. package/dist/shared/blueprint-resolver.js.map +1 -0
  613. package/dist/shared/builtin-assistant-prompt.d.ts +30 -0
  614. package/dist/shared/builtin-assistant-prompt.js +36 -0
  615. package/dist/shared/builtin-assistant-prompt.js.map +1 -0
  616. package/dist/shared/builtin-judge.d.ts +9 -0
  617. package/dist/shared/builtin-judge.js +53 -0
  618. package/dist/shared/builtin-judge.js.map +1 -0
  619. package/dist/shared/caller-identity.d.ts +112 -0
  620. package/dist/shared/caller-identity.js +150 -0
  621. package/dist/shared/caller-identity.js.map +1 -0
  622. package/dist/shared/channel-attachment.d.ts +90 -0
  623. package/dist/shared/channel-attachment.js +209 -0
  624. package/dist/shared/channel-attachment.js.map +1 -0
  625. package/dist/shared/checkpointer/factory.d.ts +32 -0
  626. package/dist/shared/checkpointer/factory.js +72 -0
  627. package/dist/shared/checkpointer/factory.js.map +1 -0
  628. package/dist/shared/checkpointer/http-saver.d.ts +70 -0
  629. package/dist/shared/checkpointer/http-saver.js +335 -0
  630. package/dist/shared/checkpointer/http-saver.js.map +1 -0
  631. package/dist/shared/checkpointer/sqlite-saver.d.ts +54 -0
  632. package/dist/shared/checkpointer/sqlite-saver.js +272 -0
  633. package/dist/shared/checkpointer/sqlite-saver.js.map +1 -0
  634. package/dist/shared/checkpointer/types.d.ts +25 -0
  635. package/dist/shared/checkpointer/types.js +18 -0
  636. package/dist/shared/checkpointer/types.js.map +1 -0
  637. package/dist/shared/cold-start-timing.d.ts +124 -0
  638. package/dist/shared/cold-start-timing.js +220 -0
  639. package/dist/shared/cold-start-timing.js.map +1 -0
  640. package/dist/shared/context-bridge.d.ts +30 -0
  641. package/dist/shared/context-bridge.js +45 -0
  642. package/dist/shared/context-bridge.js.map +1 -0
  643. package/dist/shared/conversation-attachment.d.ts +103 -0
  644. package/dist/shared/conversation-attachment.js +128 -0
  645. package/dist/shared/conversation-attachment.js.map +1 -0
  646. package/dist/shared/conversation-catchup.d.ts +40 -0
  647. package/dist/shared/conversation-catchup.js +86 -0
  648. package/dist/shared/conversation-catchup.js.map +1 -0
  649. package/dist/shared/cost-guard.d.ts +51 -0
  650. package/dist/shared/cost-guard.js +58 -0
  651. package/dist/shared/cost-guard.js.map +1 -0
  652. package/dist/shared/declared-preferences.d.ts +47 -0
  653. package/dist/shared/declared-preferences.js +64 -0
  654. package/dist/shared/declared-preferences.js.map +1 -0
  655. package/dist/shared/eval-case/agent-mock.d.ts +61 -0
  656. package/dist/shared/eval-case/agent-mock.js +88 -0
  657. package/dist/shared/eval-case/agent-mock.js.map +1 -0
  658. package/dist/shared/eval-case/case-archive.d.ts +51 -0
  659. package/dist/shared/eval-case/case-archive.js +119 -0
  660. package/dist/shared/eval-case/case-archive.js.map +1 -0
  661. package/dist/shared/eval-case/mock-endpoint.d.ts +68 -0
  662. package/dist/shared/eval-case/mock-endpoint.js +209 -0
  663. package/dist/shared/eval-case/mock-endpoint.js.map +1 -0
  664. package/dist/shared/eval-case/prepare-case.d.ts +78 -0
  665. package/dist/shared/eval-case/prepare-case.js +193 -0
  666. package/dist/shared/eval-case/prepare-case.js.map +1 -0
  667. package/dist/shared/eval-case/read-files.d.ts +26 -0
  668. package/dist/shared/eval-case/read-files.js +88 -0
  669. package/dist/shared/eval-case/read-files.js.map +1 -0
  670. package/dist/shared/exact-apply.d.ts +109 -0
  671. package/dist/shared/exact-apply.js +205 -0
  672. package/dist/shared/exact-apply.js.map +1 -0
  673. package/dist/shared/execution-context.d.ts +47 -0
  674. package/dist/shared/execution-context.js +51 -0
  675. package/dist/shared/execution-context.js.map +1 -0
  676. package/dist/shared/execution-target.d.ts +13 -0
  677. package/dist/shared/execution-target.js +15 -0
  678. package/dist/shared/execution-target.js.map +1 -0
  679. package/dist/shared/extract-json.d.ts +26 -0
  680. package/dist/shared/extract-json.js +140 -0
  681. package/dist/shared/extract-json.js.map +1 -0
  682. package/dist/shared/extract-structured-output.d.ts +38 -0
  683. package/dist/shared/extract-structured-output.js +68 -0
  684. package/dist/shared/extract-structured-output.js.map +1 -0
  685. package/dist/shared/file-change.d.ts +42 -0
  686. package/dist/shared/file-change.js +55 -0
  687. package/dist/shared/file-change.js.map +1 -0
  688. package/dist/shared/file-tools.d.ts +105 -0
  689. package/dist/shared/file-tools.js +166 -0
  690. package/dist/shared/file-tools.js.map +1 -0
  691. package/dist/shared/filereview/capture.d.ts +238 -0
  692. package/dist/shared/filereview/capture.js +559 -0
  693. package/dist/shared/filereview/capture.js.map +1 -0
  694. package/dist/shared/filereview/cas-progress.d.ts +45 -0
  695. package/dist/shared/filereview/cas-progress.js +131 -0
  696. package/dist/shared/filereview/cas-progress.js.map +1 -0
  697. package/dist/shared/filereview/cas-substrate.d.ts +226 -0
  698. package/dist/shared/filereview/cas-substrate.js +315 -0
  699. package/dist/shared/filereview/cas-substrate.js.map +1 -0
  700. package/dist/shared/filereview/cas-touched.d.ts +56 -0
  701. package/dist/shared/filereview/cas-touched.js +63 -0
  702. package/dist/shared/filereview/cas-touched.js.map +1 -0
  703. package/dist/shared/filereview/command-provenance.d.ts +95 -0
  704. package/dist/shared/filereview/command-provenance.js +134 -0
  705. package/dist/shared/filereview/command-provenance.js.map +1 -0
  706. package/dist/shared/filereview/digest.d.ts +40 -0
  707. package/dist/shared/filereview/digest.js +66 -0
  708. package/dist/shared/filereview/digest.js.map +1 -0
  709. package/dist/shared/filereview/events.d.ts +199 -0
  710. package/dist/shared/filereview/events.js +348 -0
  711. package/dist/shared/filereview/events.js.map +1 -0
  712. package/dist/shared/filereview/git-substrate.d.ts +233 -0
  713. package/dist/shared/filereview/git-substrate.js +528 -0
  714. package/dist/shared/filereview/git-substrate.js.map +1 -0
  715. package/dist/shared/filereview/index.d.ts +15 -0
  716. package/dist/shared/filereview/index.js +16 -0
  717. package/dist/shared/filereview/index.js.map +1 -0
  718. package/dist/shared/filereview/line-counts.d.ts +48 -0
  719. package/dist/shared/filereview/line-counts.js +72 -0
  720. package/dist/shared/filereview/line-counts.js.map +1 -0
  721. package/dist/shared/filereview/progress.d.ts +200 -0
  722. package/dist/shared/filereview/progress.js +245 -0
  723. package/dist/shared/filereview/progress.js.map +1 -0
  724. package/dist/shared/filereview/record.d.ts +53 -0
  725. package/dist/shared/filereview/record.js +104 -0
  726. package/dist/shared/filereview/record.js.map +1 -0
  727. package/dist/shared/filereview/secret-paths.d.ts +61 -0
  728. package/dist/shared/filereview/secret-paths.js +103 -0
  729. package/dist/shared/filereview/secret-paths.js.map +1 -0
  730. package/dist/shared/fingerprint-secret.d.ts +35 -0
  731. package/dist/shared/fingerprint-secret.js +68 -0
  732. package/dist/shared/fingerprint-secret.js.map +1 -0
  733. package/dist/shared/grpc-retry.d.ts +28 -0
  734. package/dist/shared/grpc-retry.js +39 -0
  735. package/dist/shared/grpc-retry.js.map +1 -0
  736. package/dist/shared/heartbeat.d.ts +24 -0
  737. package/dist/shared/heartbeat.js +40 -0
  738. package/dist/shared/heartbeat.js.map +1 -0
  739. package/dist/shared/hooks/answer.d.ts +49 -0
  740. package/dist/shared/hooks/answer.js +152 -0
  741. package/dist/shared/hooks/answer.js.map +1 -0
  742. package/dist/shared/hooks/condition.d.ts +71 -0
  743. package/dist/shared/hooks/condition.js +341 -0
  744. package/dist/shared/hooks/condition.js.map +1 -0
  745. package/dist/shared/hooks/evaluate.d.ts +125 -0
  746. package/dist/shared/hooks/evaluate.js +253 -0
  747. package/dist/shared/hooks/evaluate.js.map +1 -0
  748. package/dist/shared/hooks/formats/claude-code.d.ts +43 -0
  749. package/dist/shared/hooks/formats/claude-code.js +90 -0
  750. package/dist/shared/hooks/formats/claude-code.js.map +1 -0
  751. package/dist/shared/hooks/formats/common.d.ts +30 -0
  752. package/dist/shared/hooks/formats/common.js +7 -0
  753. package/dist/shared/hooks/formats/common.js.map +1 -0
  754. package/dist/shared/hooks/formats/cursor.d.ts +72 -0
  755. package/dist/shared/hooks/formats/cursor.js +238 -0
  756. package/dist/shared/hooks/formats/cursor.js.map +1 -0
  757. package/dist/shared/hooks/hook-set.d.ts +84 -0
  758. package/dist/shared/hooks/hook-set.js +80 -0
  759. package/dist/shared/hooks/hook-set.js.map +1 -0
  760. package/dist/shared/hooks/matcher.d.ts +14 -0
  761. package/dist/shared/hooks/matcher.js +32 -0
  762. package/dist/shared/hooks/matcher.js.map +1 -0
  763. package/dist/shared/hooks/messages.d.ts +19 -0
  764. package/dist/shared/hooks/messages.js +34 -0
  765. package/dist/shared/hooks/messages.js.map +1 -0
  766. package/dist/shared/hooks/run.d.ts +89 -0
  767. package/dist/shared/hooks/run.js +146 -0
  768. package/dist/shared/hooks/run.js.map +1 -0
  769. package/dist/shared/hooks/setup.d.ts +73 -0
  770. package/dist/shared/hooks/setup.js +166 -0
  771. package/dist/shared/hooks/setup.js.map +1 -0
  772. package/dist/shared/hooks/shell-commands.d.ts +39 -0
  773. package/dist/shared/hooks/shell-commands.js +326 -0
  774. package/dist/shared/hooks/shell-commands.js.map +1 -0
  775. package/dist/shared/hooks/tool-view.d.ts +164 -0
  776. package/dist/shared/hooks/tool-view.js +310 -0
  777. package/dist/shared/hooks/tool-view.js.map +1 -0
  778. package/dist/shared/http-retry.d.ts +85 -0
  779. package/dist/shared/http-retry.js +101 -0
  780. package/dist/shared/http-retry.js.map +1 -0
  781. package/dist/shared/implement-plan-prompt.d.ts +44 -0
  782. package/dist/shared/implement-plan-prompt.js +98 -0
  783. package/dist/shared/implement-plan-prompt.js.map +1 -0
  784. package/dist/shared/json-schema-to-zod.d.ts +13 -0
  785. package/dist/shared/json-schema-to-zod.js +49 -0
  786. package/dist/shared/json-schema-to-zod.js.map +1 -0
  787. package/dist/shared/llm-backend.d.ts +303 -0
  788. package/dist/shared/llm-backend.js +491 -0
  789. package/dist/shared/llm-backend.js.map +1 -0
  790. package/dist/shared/llm-proxy.d.ts +64 -0
  791. package/dist/shared/llm-proxy.js +131 -0
  792. package/dist/shared/llm-proxy.js.map +1 -0
  793. package/dist/shared/mcp-manager.d.ts +61 -0
  794. package/dist/shared/mcp-manager.js +131 -0
  795. package/dist/shared/mcp-manager.js.map +1 -0
  796. package/dist/shared/mcp-oauth-detect.d.ts +23 -0
  797. package/dist/shared/mcp-oauth-detect.js +72 -0
  798. package/dist/shared/mcp-oauth-detect.js.map +1 -0
  799. package/dist/shared/mcp-resolver.d.ts +145 -0
  800. package/dist/shared/mcp-resolver.js +238 -0
  801. package/dist/shared/mcp-resolver.js.map +1 -0
  802. package/dist/shared/mcp-schema-sanitizer.d.ts +68 -0
  803. package/dist/shared/mcp-schema-sanitizer.js +195 -0
  804. package/dist/shared/mcp-schema-sanitizer.js.map +1 -0
  805. package/dist/shared/mcp-tool-listing.d.ts +80 -0
  806. package/dist/shared/mcp-tool-listing.js +166 -0
  807. package/dist/shared/mcp-tool-listing.js.map +1 -0
  808. package/dist/shared/mcp-transport-guard.d.ts +53 -0
  809. package/dist/shared/mcp-transport-guard.js +70 -0
  810. package/dist/shared/mcp-transport-guard.js.map +1 -0
  811. package/dist/shared/memory-attachment.d.ts +103 -0
  812. package/dist/shared/memory-attachment.js +142 -0
  813. package/dist/shared/memory-attachment.js.map +1 -0
  814. package/dist/shared/memory-retrieval.d.ts +126 -0
  815. package/dist/shared/memory-retrieval.js +293 -0
  816. package/dist/shared/memory-retrieval.js.map +1 -0
  817. package/dist/shared/model-client.d.ts +111 -0
  818. package/dist/shared/model-client.js +328 -0
  819. package/dist/shared/model-client.js.map +1 -0
  820. package/dist/shared/model-error.d.ts +94 -0
  821. package/dist/shared/model-error.js +475 -0
  822. package/dist/shared/model-error.js.map +1 -0
  823. package/dist/shared/model-facts.d.ts +21 -0
  824. package/dist/shared/model-facts.js +22 -0
  825. package/dist/shared/model-facts.js.map +1 -0
  826. package/dist/shared/model-lanes.d.ts +48 -0
  827. package/dist/shared/model-lanes.js +52 -0
  828. package/dist/shared/model-lanes.js.map +1 -0
  829. package/dist/shared/model-pricing-data.d.ts +20 -0
  830. package/dist/shared/model-pricing-data.js +82 -0
  831. package/dist/shared/model-pricing-data.js.map +1 -0
  832. package/dist/shared/model-pricing.d.ts +16 -0
  833. package/dist/shared/model-pricing.js +46 -0
  834. package/dist/shared/model-pricing.js.map +1 -0
  835. package/dist/shared/model-registry.d.ts +113 -0
  836. package/dist/shared/model-registry.js +250 -0
  837. package/dist/shared/model-registry.js.map +1 -0
  838. package/dist/shared/persist-decision.d.ts +38 -0
  839. package/dist/shared/persist-decision.js +40 -0
  840. package/dist/shared/persist-decision.js.map +1 -0
  841. package/dist/shared/placeholder-resolver.d.ts +39 -0
  842. package/dist/shared/placeholder-resolver.js +86 -0
  843. package/dist/shared/placeholder-resolver.js.map +1 -0
  844. package/dist/shared/plan-artifact.d.ts +105 -0
  845. package/dist/shared/plan-artifact.js +225 -0
  846. package/dist/shared/plan-artifact.js.map +1 -0
  847. package/dist/shared/plan-mode-permissions.d.ts +49 -0
  848. package/dist/shared/plan-mode-permissions.js +51 -0
  849. package/dist/shared/plan-mode-permissions.js.map +1 -0
  850. package/dist/shared/plan-mode-prompt.d.ts +41 -0
  851. package/dist/shared/plan-mode-prompt.js +74 -0
  852. package/dist/shared/plan-mode-prompt.js.map +1 -0
  853. package/dist/shared/platform-server-address.d.ts +72 -0
  854. package/dist/shared/platform-server-address.js +103 -0
  855. package/dist/shared/platform-server-address.js.map +1 -0
  856. package/dist/shared/plugin-mount.d.ts +165 -0
  857. package/dist/shared/plugin-mount.js +428 -0
  858. package/dist/shared/plugin-mount.js.map +1 -0
  859. package/dist/shared/plugin-servers.d.ts +16 -0
  860. package/dist/shared/plugin-servers.js +22 -0
  861. package/dist/shared/plugin-servers.js.map +1 -0
  862. package/dist/shared/prompt-sections.d.ts +140 -0
  863. package/dist/shared/prompt-sections.js +135 -0
  864. package/dist/shared/prompt-sections.js.map +1 -0
  865. package/dist/shared/recalled-memories.d.ts +55 -0
  866. package/dist/shared/recalled-memories.js +70 -0
  867. package/dist/shared/recalled-memories.js.map +1 -0
  868. package/dist/shared/registry-endpoint.d.ts +60 -0
  869. package/dist/shared/registry-endpoint.js +99 -0
  870. package/dist/shared/registry-endpoint.js.map +1 -0
  871. package/dist/shared/run-credential-store.d.ts +32 -0
  872. package/dist/shared/run-credential-store.js +39 -0
  873. package/dist/shared/run-credential-store.js.map +1 -0
  874. package/dist/shared/run-credential.d.ts +40 -0
  875. package/dist/shared/run-credential.js +47 -0
  876. package/dist/shared/run-credential.js.map +1 -0
  877. package/dist/shared/run-values.d.ts +88 -0
  878. package/dist/shared/run-values.js +101 -0
  879. package/dist/shared/run-values.js.map +1 -0
  880. package/dist/shared/runner-credential-keys.d.ts +20 -0
  881. package/dist/shared/runner-credential-keys.js +101 -0
  882. package/dist/shared/runner-credential-keys.js.map +1 -0
  883. package/dist/shared/runner-credential-store.d.ts +77 -0
  884. package/dist/shared/runner-credential-store.js +111 -0
  885. package/dist/shared/runner-credential-store.js.map +1 -0
  886. package/dist/shared/sender-identity.d.ts +50 -0
  887. package/dist/shared/sender-identity.js +69 -0
  888. package/dist/shared/sender-identity.js.map +1 -0
  889. package/dist/shared/service-tier.d.ts +55 -0
  890. package/dist/shared/service-tier.js +67 -0
  891. package/dist/shared/service-tier.js.map +1 -0
  892. package/dist/shared/session-context.d.ts +35 -0
  893. package/dist/shared/session-context.js +52 -0
  894. package/dist/shared/session-context.js.map +1 -0
  895. package/dist/shared/shell-env.d.ts +42 -0
  896. package/dist/shared/shell-env.js +65 -0
  897. package/dist/shared/shell-env.js.map +1 -0
  898. package/dist/shared/skill-mount.d.ts +135 -0
  899. package/dist/shared/skill-mount.js +178 -0
  900. package/dist/shared/skill-mount.js.map +1 -0
  901. package/dist/shared/skill-resolver.d.ts +57 -0
  902. package/dist/shared/skill-resolver.js +113 -0
  903. package/dist/shared/skill-resolver.js.map +1 -0
  904. package/dist/shared/stall-watchdog.d.ts +68 -0
  905. package/dist/shared/stall-watchdog.js +102 -0
  906. package/dist/shared/stall-watchdog.js.map +1 -0
  907. package/dist/shared/status-offload.d.ts +196 -0
  908. package/dist/shared/status-offload.js +655 -0
  909. package/dist/shared/status-offload.js.map +1 -0
  910. package/dist/shared/status.d.ts +100 -0
  911. package/dist/shared/status.js +191 -0
  912. package/dist/shared/status.js.map +1 -0
  913. package/dist/shared/streaming-scheduler.d.ts +59 -0
  914. package/dist/shared/streaming-scheduler.js +110 -0
  915. package/dist/shared/streaming-scheduler.js.map +1 -0
  916. package/dist/shared/subagent-gate.d.ts +47 -0
  917. package/dist/shared/subagent-gate.js +98 -0
  918. package/dist/shared/subagent-gate.js.map +1 -0
  919. package/dist/shared/subagent-rows.d.ts +21 -0
  920. package/dist/shared/subagent-rows.js +34 -0
  921. package/dist/shared/subagent-rows.js.map +1 -0
  922. package/dist/shared/subagents.d.ts +49 -0
  923. package/dist/shared/subagents.js +51 -0
  924. package/dist/shared/subagents.js.map +1 -0
  925. package/dist/shared/synthesized-attachment.d.ts +73 -0
  926. package/dist/shared/synthesized-attachment.js +59 -0
  927. package/dist/shared/synthesized-attachment.js.map +1 -0
  928. package/dist/shared/telemetry-content.d.ts +132 -0
  929. package/dist/shared/telemetry-content.js +239 -0
  930. package/dist/shared/telemetry-content.js.map +1 -0
  931. package/dist/shared/thinking-mode.d.ts +82 -0
  932. package/dist/shared/thinking-mode.js +105 -0
  933. package/dist/shared/thinking-mode.js.map +1 -0
  934. package/dist/shared/todos.d.ts +30 -0
  935. package/dist/shared/todos.js +58 -0
  936. package/dist/shared/todos.js.map +1 -0
  937. package/dist/shared/tool-kind.d.ts +41 -0
  938. package/dist/shared/tool-kind.js +107 -0
  939. package/dist/shared/tool-kind.js.map +1 -0
  940. package/dist/shared/tool-lists.d.ts +283 -0
  941. package/dist/shared/tool-lists.js +518 -0
  942. package/dist/shared/tool-lists.js.map +1 -0
  943. package/dist/shared/tool-rounds.d.ts +91 -0
  944. package/dist/shared/tool-rounds.js +136 -0
  945. package/dist/shared/tool-rounds.js.map +1 -0
  946. package/dist/shared/tool-row.d.ts +195 -0
  947. package/dist/shared/tool-row.js +320 -0
  948. package/dist/shared/tool-row.js.map +1 -0
  949. package/dist/shared/trace-context.d.ts +20 -0
  950. package/dist/shared/trace-context.js +36 -0
  951. package/dist/shared/trace-context.js.map +1 -0
  952. package/dist/shared/with-timeout.d.ts +27 -0
  953. package/dist/shared/with-timeout.js +47 -0
  954. package/dist/shared/with-timeout.js.map +1 -0
  955. package/dist/shared/worker-shutdown.d.ts +99 -0
  956. package/dist/shared/worker-shutdown.js +94 -0
  957. package/dist/shared/worker-shutdown.js.map +1 -0
  958. package/dist/shared/workspace/file-tree.d.ts +13 -0
  959. package/dist/shared/workspace/file-tree.js +101 -0
  960. package/dist/shared/workspace/file-tree.js.map +1 -0
  961. package/dist/shared/workspace/git-credential.d.ts +91 -0
  962. package/dist/shared/workspace/git-credential.js +222 -0
  963. package/dist/shared/workspace/git-credential.js.map +1 -0
  964. package/dist/shared/workspace/git-identity.d.ts +36 -0
  965. package/dist/shared/workspace/git-identity.js +39 -0
  966. package/dist/shared/workspace/git-identity.js.map +1 -0
  967. package/dist/shared/workspace/local-backend.d.ts +44 -0
  968. package/dist/shared/workspace/local-backend.js +110 -0
  969. package/dist/shared/workspace/local-backend.js.map +1 -0
  970. package/dist/shared/workspace/platform-dir.d.ts +106 -0
  971. package/dist/shared/workspace/platform-dir.js +151 -0
  972. package/dist/shared/workspace/platform-dir.js.map +1 -0
  973. package/dist/shared/workspace/platform-mount.d.ts +95 -0
  974. package/dist/shared/workspace/platform-mount.js +157 -0
  975. package/dist/shared/workspace/platform-mount.js.map +1 -0
  976. package/dist/shared/workspace/provisioner.d.ts +52 -0
  977. package/dist/shared/workspace/provisioner.js +70 -0
  978. package/dist/shared/workspace/provisioner.js.map +1 -0
  979. package/dist/shared/workspace/session-provision.d.ts +56 -0
  980. package/dist/shared/workspace/session-provision.js +54 -0
  981. package/dist/shared/workspace/session-provision.js.map +1 -0
  982. package/dist/shared/workspace/session-root.d.ts +35 -0
  983. package/dist/shared/workspace/session-root.js +53 -0
  984. package/dist/shared/workspace/session-root.js.map +1 -0
  985. package/dist/shared/workspace/sources/empty.d.ts +8 -0
  986. package/dist/shared/workspace/sources/empty.js +16 -0
  987. package/dist/shared/workspace/sources/empty.js.map +1 -0
  988. package/dist/shared/workspace/sources/git.d.ts +30 -0
  989. package/dist/shared/workspace/sources/git.js +224 -0
  990. package/dist/shared/workspace/sources/git.js.map +1 -0
  991. package/dist/shared/workspace/sources/local-path.d.ts +17 -0
  992. package/dist/shared/workspace/sources/local-path.js +61 -0
  993. package/dist/shared/workspace/sources/local-path.js.map +1 -0
  994. package/dist/shared/workspace/stigmer-link.d.ts +73 -0
  995. package/dist/shared/workspace/stigmer-link.js +173 -0
  996. package/dist/shared/workspace/stigmer-link.js.map +1 -0
  997. package/dist/shared/workspace/types.d.ts +71 -0
  998. package/dist/shared/workspace/types.js +19 -0
  999. package/dist/shared/workspace/types.js.map +1 -0
  1000. package/dist/shared/workspace/workspace-lock.d.ts +86 -0
  1001. package/dist/shared/workspace/workspace-lock.js +190 -0
  1002. package/dist/shared/workspace/workspace-lock.js.map +1 -0
  1003. package/dist/shared/workspace/writeback-coordinator.d.ts +119 -0
  1004. package/dist/shared/workspace/writeback-coordinator.js +361 -0
  1005. package/dist/shared/workspace/writeback-coordinator.js.map +1 -0
  1006. package/dist/shared/zip-extract.d.ts +55 -0
  1007. package/dist/shared/zip-extract.js +98 -0
  1008. package/dist/shared/zip-extract.js.map +1 -0
  1009. package/dist/tools/index.d.ts +26 -0
  1010. package/dist/tools/index.js +26 -0
  1011. package/dist/tools/index.js.map +1 -0
  1012. package/dist/tools/url-guard.d.ts +77 -0
  1013. package/dist/tools/url-guard.js +119 -0
  1014. package/dist/tools/url-guard.js.map +1 -0
  1015. package/dist/tools/web-fetch-tool.d.ts +55 -0
  1016. package/dist/tools/web-fetch-tool.js +218 -0
  1017. package/dist/tools/web-fetch-tool.js.map +1 -0
  1018. package/dist/worker.d.ts +35 -0
  1019. package/dist/worker.js +71 -0
  1020. package/dist/worker.js.map +1 -0
  1021. package/dist/workflow-source.d.ts +38 -0
  1022. package/dist/workflow-source.js +53 -0
  1023. package/dist/workflow-source.js.map +1 -0
  1024. package/dist/workflows/index.d.ts +32 -0
  1025. package/dist/workflows/index.js +33 -0
  1026. package/dist/workflows/index.js.map +1 -0
  1027. package/dist/workflows/list-plugin-tools.d.ts +23 -0
  1028. package/dist/workflows/list-plugin-tools.js +56 -0
  1029. package/dist/workflows/list-plugin-tools.js.map +1 -0
  1030. package/dist/workflows/types.d.ts +43 -0
  1031. package/dist/workflows/types.js +18 -0
  1032. package/dist/workflows/types.js.map +1 -0
  1033. package/package.json +161 -0
  1034. package/src/__test-utils__/__tests__/execution-record-barrier.test.ts +75 -0
  1035. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +361 -0
  1036. package/src/__test-utils__/__tests__/live-gate.test.ts +100 -0
  1037. package/src/__test-utils__/__tests__/real-model-registry.test.ts +53 -0
  1038. package/src/__test-utils__/__tests__/vitest-global-setup.test.ts +37 -0
  1039. package/src/__test-utils__/agent-host-probe-child.ts +77 -0
  1040. package/src/__test-utils__/approval-contract/contract.ts +613 -0
  1041. package/src/__test-utils__/approval-contract/hook-commands.ts +100 -0
  1042. package/src/__test-utils__/approval-contract/types.ts +323 -0
  1043. package/src/__test-utils__/approval-log.ts +142 -0
  1044. package/src/__test-utils__/config-fixture.ts +65 -0
  1045. package/src/__test-utils__/cursor-sdk-wire-child.ts +47 -0
  1046. package/src/__test-utils__/execution-record-fixture.ts +229 -0
  1047. package/src/__test-utils__/fake-artifact-storage.ts +83 -0
  1048. package/src/__test-utils__/fake-upstream.ts +67 -0
  1049. package/src/__test-utils__/file-review-projection.ts +77 -0
  1050. package/src/__test-utils__/git-workspace-fixture.ts +58 -0
  1051. package/src/__test-utils__/harness-boot-order-child.ts +78 -0
  1052. package/src/__test-utils__/harness-contract/contract.ts +652 -0
  1053. package/src/__test-utils__/harness-contract/recording-sink.ts +138 -0
  1054. package/src/__test-utils__/harness-contract/runtime-contract.ts +1136 -0
  1055. package/src/__test-utils__/harness-contract/scripted-adapter.ts +404 -0
  1056. package/src/__test-utils__/harness-contract/types.ts +200 -0
  1057. package/src/__test-utils__/hermetic-activity.ts +1061 -0
  1058. package/src/__test-utils__/import-http2-first.ts +11 -0
  1059. package/src/__test-utils__/live-gate.ts +106 -0
  1060. package/src/__test-utils__/loopback-host.ts +48 -0
  1061. package/src/__test-utils__/mock-client.ts +52 -0
  1062. package/src/__test-utils__/mock-workspace.ts +28 -0
  1063. package/src/__test-utils__/model-registry-fixture.ts +133 -0
  1064. package/src/__test-utils__/module-specifiers.ts +177 -0
  1065. package/src/__test-utils__/proto-helpers.ts +70 -0
  1066. package/src/__test-utils__/real-model-registry.ts +85 -0
  1067. package/src/__test-utils__/refuse-engine-sdks.ts +18 -0
  1068. package/src/__test-utils__/timing-lines.ts +43 -0
  1069. package/src/__test-utils__/turn-input-fixture.ts +166 -0
  1070. package/src/__test-utils__/vitest-global-setup.ts +50 -0
  1071. package/src/__tests__/agent-separation.container.test.ts +157 -0
  1072. package/src/__tests__/approval-gateway-contract.test.ts +29 -0
  1073. package/src/__tests__/bootstrap.test.ts +264 -0
  1074. package/src/__tests__/config-boundary.test.ts +135 -0
  1075. package/src/__tests__/config.test.ts +165 -0
  1076. package/src/__tests__/exit-backstop.test.ts +91 -0
  1077. package/src/__tests__/harness-boot-order.test.ts +87 -0
  1078. package/src/__tests__/harness-contract.test.ts +27 -0
  1079. package/src/__tests__/in-flight.test.ts +84 -0
  1080. package/src/__tests__/ipc-protocol-fixtures.test.ts +61 -0
  1081. package/src/__tests__/ipc-protocol.test.ts +33 -0
  1082. package/src/__tests__/otel-export.test.ts +266 -0
  1083. package/src/__tests__/otel-init.test.ts +111 -0
  1084. package/src/__tests__/otel-metrics.test.ts +37 -0
  1085. package/src/__tests__/pipe-safety.test.ts +119 -0
  1086. package/src/__tests__/pool-member.test.ts +77 -0
  1087. package/src/__tests__/preflight.test.ts +104 -0
  1088. package/src/__tests__/readme-environment.test.ts +678 -0
  1089. package/src/__tests__/run-credential-registration.test.ts +53 -0
  1090. package/src/__tests__/run-trace-id.test.ts +53 -0
  1091. package/src/__tests__/runner-hosting.test.ts +134 -0
  1092. package/src/__tests__/runner-manager-interceptors.test.ts +67 -0
  1093. package/src/__tests__/runner-manager-shutdown.test.ts +199 -0
  1094. package/src/__tests__/runner-manager.test.ts +95 -0
  1095. package/src/__tests__/runner-token-coordinator.test.ts +166 -0
  1096. package/src/__tests__/runner.test.ts +284 -0
  1097. package/src/__tests__/sandbox-token-renewal.test.ts +175 -0
  1098. package/src/__tests__/worker.test.ts +107 -0
  1099. package/src/activities/__tests__/attach-session.test.ts +133 -0
  1100. package/src/activities/__tests__/ensure-thread.test.ts +96 -0
  1101. package/src/activities/__tests__/error-classifier.test.ts +464 -0
  1102. package/src/activities/__tests__/generate-session-subject-wire.test.ts +119 -0
  1103. package/src/activities/__tests__/generate-session-subject.test.ts +356 -0
  1104. package/src/activities/__tests__/list-plugin-tools.test.ts +392 -0
  1105. package/src/activities/attach-session.ts +111 -0
  1106. package/src/activities/ensure-thread.ts +45 -0
  1107. package/src/activities/execute-cursor/__test-utils__/__tests__/scripted-double.test.ts +126 -0
  1108. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +445 -0
  1109. package/src/activities/execute-cursor/__test-utils__/cursor-hook-harness.ts +407 -0
  1110. package/src/activities/execute-cursor/__test-utils__/fold.ts +118 -0
  1111. package/src/activities/execute-cursor/__test-utils__/gateway-substrate.ts +316 -0
  1112. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +428 -0
  1113. package/src/activities/execute-cursor/__test-utils__/scripted-agent.ts +374 -0
  1114. package/src/activities/execute-cursor/__test-utils__/scripted-sdk.ts +310 -0
  1115. package/src/activities/execute-cursor/__tests__/adapter-is-temporal-free.test.ts +45 -0
  1116. package/src/activities/execute-cursor/__tests__/agent-session-cache.test.ts +220 -0
  1117. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +141 -0
  1118. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +335 -0
  1119. package/src/activities/execute-cursor/__tests__/approval-state.test.ts +288 -0
  1120. package/src/activities/execute-cursor/__tests__/boundary-seal.test.ts +125 -0
  1121. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +1045 -0
  1122. package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +267 -0
  1123. package/src/activities/execute-cursor/__tests__/check-tool-scope.test.ts +290 -0
  1124. package/src/activities/execute-cursor/__tests__/coarse-fingerprint.test.ts +98 -0
  1125. package/src/activities/execute-cursor/__tests__/cursor-baseurl-routing.live.test.ts +94 -0
  1126. package/src/activities/execute-cursor/__tests__/cursor-event-recorder.test.ts +142 -0
  1127. package/src/activities/execute-cursor/__tests__/cursor-fetch-interceptor-bypass.live.test.ts +76 -0
  1128. package/src/activities/execute-cursor/__tests__/cursor-generate-image.live.test.ts +154 -0
  1129. package/src/activities/execute-cursor/__tests__/cursor-hook-protocol.live.test.ts +479 -0
  1130. package/src/activities/execute-cursor/__tests__/cursor-hooks-gate.live.test.ts +295 -0
  1131. package/src/activities/execute-cursor/__tests__/cursor-mcp-config.test.ts +128 -0
  1132. package/src/activities/execute-cursor/__tests__/cursor-mode.test.ts +95 -0
  1133. package/src/activities/execute-cursor/__tests__/cursor-sdk-auth.live.test.ts +97 -0
  1134. package/src/activities/execute-cursor/__tests__/cursor-transcript.live.test.ts +289 -0
  1135. package/src/activities/execute-cursor/__tests__/deny-gate-exact-apply.test.ts +200 -0
  1136. package/src/activities/execute-cursor/__tests__/error-classifier-billing.test.ts +178 -0
  1137. package/src/activities/execute-cursor/__tests__/error-classifier-extraction.test.ts +208 -0
  1138. package/src/activities/execute-cursor/__tests__/error-classifier-introspection.test.ts +156 -0
  1139. package/src/activities/execute-cursor/__tests__/fetch-interceptor.test.ts +389 -0
  1140. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.append.prompt.md +147 -0
  1141. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +164 -0
  1142. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.no-instructions.prompt.md +142 -0
  1143. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +184 -0
  1144. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +189 -0
  1145. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
  1146. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
  1147. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.append.prompt.md +5 -0
  1148. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
  1149. package/src/activities/execute-cursor/__tests__/hermetic/answers.test.ts +279 -0
  1150. package/src/activities/execute-cursor/__tests__/hermetic/built-in-assistant.test.ts +127 -0
  1151. package/src/activities/execute-cursor/__tests__/hermetic/bypassed-tool-call.test.ts +120 -0
  1152. package/src/activities/execute-cursor/__tests__/hermetic/deny-and-retry.test.ts +233 -0
  1153. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +262 -0
  1154. package/src/activities/execute-cursor/__tests__/hermetic/goldens/approve-all.turn2.events.json +94 -0
  1155. package/src/activities/execute-cursor/__tests__/hermetic/goldens/approve-all.turn2.rows.json +47 -0
  1156. package/src/activities/execute-cursor/__tests__/hermetic/goldens/approve-all.turn2.status.json +17 -0
  1157. package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.events.json +14 -0
  1158. package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.rows.json +14 -0
  1159. package/src/activities/execute-cursor/__tests__/hermetic/goldens/cost-cap.status.json +18 -0
  1160. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn1.events.json +37 -0
  1161. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn1.rows.json +29 -0
  1162. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn1.status.json +4 -0
  1163. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn2.events.json +71 -0
  1164. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn2.rows.json +32 -0
  1165. package/src/activities/execute-cursor/__tests__/hermetic/goldens/deny-and-retry.turn2.status.json +17 -0
  1166. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-capture.events.json +68 -0
  1167. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-capture.rows.json +96 -0
  1168. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-capture.status.json +74 -0
  1169. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-off.events.json +50 -0
  1170. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-off.rows.json +32 -0
  1171. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-off.status.json +17 -0
  1172. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-reconcile.events.json +91 -0
  1173. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-reconcile.rows.json +9 -0
  1174. package/src/activities/execute-cursor/__tests__/hermetic/goldens/file-review-reconcile.status.json +6 -0
  1175. package/src/activities/execute-cursor/__tests__/hermetic/goldens/hooks.turn1.events.json +110 -0
  1176. package/src/activities/execute-cursor/__tests__/hermetic/goldens/hooks.turn1.rows.json +77 -0
  1177. package/src/activities/execute-cursor/__tests__/hermetic/goldens/hooks.turn1.status.json +14 -0
  1178. package/src/activities/execute-cursor/__tests__/hermetic/goldens/hooks.turn2.events.json +144 -0
  1179. package/src/activities/execute-cursor/__tests__/hermetic/goldens/hooks.turn2.rows.json +34 -0
  1180. package/src/activities/execute-cursor/__tests__/hermetic/goldens/hooks.turn2.status.json +27 -0
  1181. package/src/activities/execute-cursor/__tests__/hermetic/goldens/mcp-tool-call.events.json +50 -0
  1182. package/src/activities/execute-cursor/__tests__/hermetic/goldens/mcp-tool-call.rows.json +30 -0
  1183. package/src/activities/execute-cursor/__tests__/hermetic/goldens/mcp-tool-call.status.json +17 -0
  1184. package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.events.json +14 -0
  1185. package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.rows.json +9 -0
  1186. package/src/activities/execute-cursor/__tests__/hermetic/goldens/pause.status.json +4 -0
  1187. package/src/activities/execute-cursor/__tests__/hermetic/goldens/plain-turn.events.json +14 -0
  1188. package/src/activities/execute-cursor/__tests__/hermetic/goldens/plain-turn.rows.json +9 -0
  1189. package/src/activities/execute-cursor/__tests__/hermetic/goldens/plain-turn.status.json +17 -0
  1190. package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.events.json +37 -0
  1191. package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.rows.json +29 -0
  1192. package/src/activities/execute-cursor/__tests__/hermetic/goldens/platform-stop.status.json +6 -0
  1193. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-fresh-agent.events.json +26 -0
  1194. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-fresh-agent.rows.json +14 -0
  1195. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-fresh-agent.status.json +17 -0
  1196. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-transport-timeout.events.json +14 -0
  1197. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-transport-timeout.rows.json +9 -0
  1198. package/src/activities/execute-cursor/__tests__/hermetic/goldens/recovery-transport-timeout.status.json +17 -0
  1199. package/src/activities/execute-cursor/__tests__/hermetic/goldens/reject.turn2.events.json +61 -0
  1200. package/src/activities/execute-cursor/__tests__/hermetic/goldens/reject.turn2.rows.json +31 -0
  1201. package/src/activities/execute-cursor/__tests__/hermetic/goldens/reject.turn2.status.json +17 -0
  1202. package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.events.json +1 -0
  1203. package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.rows.json +14 -0
  1204. package/src/activities/execute-cursor/__tests__/hermetic/goldens/resolution-error.status.json +7 -0
  1205. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-cancelled.events.json +14 -0
  1206. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-cancelled.rows.json +9 -0
  1207. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-cancelled.status.json +5 -0
  1208. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-error-non-retryable.events.json +14 -0
  1209. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-error-non-retryable.rows.json +9 -0
  1210. package/src/activities/execute-cursor/__tests__/hermetic/goldens/run-error-non-retryable.status.json +7 -0
  1211. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.events.json +1 -0
  1212. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.rows.json +14 -0
  1213. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +7 -0
  1214. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.events.json +56 -0
  1215. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.rows.json +34 -0
  1216. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-task-note.status.json +17 -0
  1217. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.events.json +64 -0
  1218. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.rows.json +36 -0
  1219. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.error-delta.status.json +17 -0
  1220. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.events.json +49 -0
  1221. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.events.json +49 -0
  1222. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.rows.json +31 -0
  1223. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.output-first.status.json +17 -0
  1224. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.rows.json +31 -0
  1225. package/src/activities/execute-cursor/__tests__/hermetic/goldens/shell-output-delta.status.json +17 -0
  1226. package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.events.json +24 -0
  1227. package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.rows.json +29 -0
  1228. package/src/activities/execute-cursor/__tests__/hermetic/goldens/stall.status.json +7 -0
  1229. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.events.json +158 -0
  1230. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.rows.json +70 -0
  1231. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sub-agent-delegation.status.json +17 -0
  1232. package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.events.json +77 -0
  1233. package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.rows.json +39 -0
  1234. package/src/activities/execute-cursor/__tests__/hermetic/goldens/thinking-turn.status.json +17 -0
  1235. package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.events.json +99 -0
  1236. package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.rows.json +80 -0
  1237. package/src/activities/execute-cursor/__tests__/hermetic/goldens/todo-write.status.json +17 -0
  1238. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-call.events.json +49 -0
  1239. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-call.rows.json +29 -0
  1240. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-call.status.json +17 -0
  1241. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.events.json +50 -0
  1242. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.rows.json +29 -0
  1243. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-error.status.json +17 -0
  1244. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.events.json +37 -0
  1245. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.rows.json +28 -0
  1246. package/src/activities/execute-cursor/__tests__/hermetic/goldens/tool-only-step.status.json +17 -0
  1247. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattended-skip.events.json +51 -0
  1248. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattended-skip.rows.json +31 -0
  1249. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattended-skip.status.json +17 -0
  1250. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.events.json +50 -0
  1251. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.rows.json +36 -0
  1252. package/src/activities/execute-cursor/__tests__/hermetic/goldens/unattributed-hook-block.status.json +19 -0
  1253. package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.events.json +14 -0
  1254. package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.rows.json +14 -0
  1255. package/src/activities/execute-cursor/__tests__/hermetic/goldens/worker-shutdown.status.json +7 -0
  1256. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +198 -0
  1257. package/src/activities/execute-cursor/__tests__/hermetic/hooks.test.ts +569 -0
  1258. package/src/activities/execute-cursor/__tests__/hermetic/mcp-tool-call.test.ts +149 -0
  1259. package/src/activities/execute-cursor/__tests__/hermetic/pause-vs-shutdown.test.ts +222 -0
  1260. package/src/activities/execute-cursor/__tests__/hermetic/plain-turn.test.ts +178 -0
  1261. package/src/activities/execute-cursor/__tests__/hermetic/recovery-fresh-agent.test.ts +162 -0
  1262. package/src/activities/execute-cursor/__tests__/hermetic/run-wait-arms.test.ts +296 -0
  1263. package/src/activities/execute-cursor/__tests__/hermetic/sdk-task-note.test.ts +125 -0
  1264. package/src/activities/execute-cursor/__tests__/hermetic/shell-output-delta.test.ts +283 -0
  1265. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +342 -0
  1266. package/src/activities/execute-cursor/__tests__/hermetic/sub-agent-delegation.test.ts +197 -0
  1267. package/src/activities/execute-cursor/__tests__/hermetic/thinking-turn.test.ts +149 -0
  1268. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +214 -0
  1269. package/src/activities/execute-cursor/__tests__/hermetic/todo-write.test.ts +169 -0
  1270. package/src/activities/execute-cursor/__tests__/hermetic/tool-call.test.ts +143 -0
  1271. package/src/activities/execute-cursor/__tests__/hermetic/tool-error.test.ts +141 -0
  1272. package/src/activities/execute-cursor/__tests__/hermetic/tool-lists.test.ts +391 -0
  1273. package/src/activities/execute-cursor/__tests__/hermetic/tool-only-step.test.ts +134 -0
  1274. package/src/activities/execute-cursor/__tests__/hermetic/turn-phases.test.ts +136 -0
  1275. package/src/activities/execute-cursor/__tests__/hermetic/unattended-skip.test.ts +157 -0
  1276. package/src/activities/execute-cursor/__tests__/hermetic/unattributed-hook-block.test.ts +200 -0
  1277. package/src/activities/execute-cursor/__tests__/hermetic/workspace-lock-timeout.test.ts +156 -0
  1278. package/src/activities/execute-cursor/__tests__/hitl-ledger.test.ts +2109 -0
  1279. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +431 -0
  1280. package/src/activities/execute-cursor/__tests__/hook-refusal-rows.test.ts +95 -0
  1281. package/src/activities/execute-cursor/__tests__/hook-scope.test.ts +175 -0
  1282. package/src/activities/execute-cursor/__tests__/hook-script.test.ts +1408 -0
  1283. package/src/activities/execute-cursor/__tests__/hook-server.test.ts +465 -0
  1284. package/src/activities/execute-cursor/__tests__/hook-views.test.ts +171 -0
  1285. package/src/activities/execute-cursor/__tests__/http2-interceptor.test.ts +408 -0
  1286. package/src/activities/execute-cursor/__tests__/model-pricing.test.ts +173 -0
  1287. package/src/activities/execute-cursor/__tests__/prepare-hooks.test.ts +97 -0
  1288. package/src/activities/execute-cursor/__tests__/prompt-builder-delegation.test.ts +85 -0
  1289. package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +270 -0
  1290. package/src/activities/execute-cursor/__tests__/resolve-timeout-message.test.ts +24 -0
  1291. package/src/activities/execute-cursor/__tests__/run-telemetry.test.ts +177 -0
  1292. package/src/activities/execute-cursor/__tests__/runner-error-regressions.test.ts +103 -0
  1293. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +174 -0
  1294. package/src/activities/execute-cursor/__tests__/scope-refusal-rows.test.ts +269 -0
  1295. package/src/activities/execute-cursor/__tests__/sdk-warmup.test.ts +45 -0
  1296. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +182 -0
  1297. package/src/activities/execute-cursor/__tests__/service-tier.test.ts +230 -0
  1298. package/src/activities/execute-cursor/__tests__/session-lifecycle.test.ts +336 -0
  1299. package/src/activities/execute-cursor/__tests__/session-store.test.ts +220 -0
  1300. package/src/activities/execute-cursor/__tests__/subagent-config.test.ts +181 -0
  1301. package/src/activities/execute-cursor/__tests__/tool-result-image.test.ts +250 -0
  1302. package/src/activities/execute-cursor/__tests__/translator.test.ts +651 -0
  1303. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +415 -0
  1304. package/src/activities/execute-cursor/__tests__/turn-recovery.test.ts +186 -0
  1305. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +354 -0
  1306. package/src/activities/execute-cursor/__tests__/usage-pricing.test.ts +84 -0
  1307. package/src/activities/execute-cursor/__tests__/workspace-setup.test.ts +814 -0
  1308. package/src/activities/execute-cursor/adapter.ts +161 -0
  1309. package/src/activities/execute-cursor/agent-session-cache.ts +229 -0
  1310. package/src/activities/execute-cursor/approval-policy.ts +129 -0
  1311. package/src/activities/execute-cursor/approval-state.ts +1097 -0
  1312. package/src/activities/execute-cursor/boundary-rows.ts +1419 -0
  1313. package/src/activities/execute-cursor/cas-observations.ts +263 -0
  1314. package/src/activities/execute-cursor/cursor-capabilities.ts +80 -0
  1315. package/src/activities/execute-cursor/cursor-event-recorder.ts +112 -0
  1316. package/src/activities/execute-cursor/cursor-mcp-config.ts +124 -0
  1317. package/src/activities/execute-cursor/cursor-mode.ts +42 -0
  1318. package/src/activities/execute-cursor/error-classifier.ts +416 -0
  1319. package/src/activities/execute-cursor/fetch-interceptor.ts +454 -0
  1320. package/src/activities/execute-cursor/hook-scope.ts +216 -0
  1321. package/src/activities/execute-cursor/hook-script.ts +1232 -0
  1322. package/src/activities/execute-cursor/hook-server.ts +473 -0
  1323. package/src/activities/execute-cursor/hook-tool-hiding.ts +76 -0
  1324. package/src/activities/execute-cursor/hook-views.ts +195 -0
  1325. package/src/activities/execute-cursor/http2-interceptor.ts +267 -0
  1326. package/src/activities/execute-cursor/model-pricing-data.ts +170 -0
  1327. package/src/activities/execute-cursor/model-pricing.ts +190 -0
  1328. package/src/activities/execute-cursor/prompt-builder.ts +1081 -0
  1329. package/src/activities/execute-cursor/rejection-capture.ts +93 -0
  1330. package/src/activities/execute-cursor/run-telemetry.ts +189 -0
  1331. package/src/activities/execute-cursor/sdk-warmup.ts +77 -0
  1332. package/src/activities/execute-cursor/service-tier.ts +251 -0
  1333. package/src/activities/execute-cursor/session-lifecycle.ts +543 -0
  1334. package/src/activities/execute-cursor/session-store.ts +186 -0
  1335. package/src/activities/execute-cursor/sub-agent-steps.ts +188 -0
  1336. package/src/activities/execute-cursor/subagent-config.ts +124 -0
  1337. package/src/activities/execute-cursor/tool-result.ts +128 -0
  1338. package/src/activities/execute-cursor/translator.ts +544 -0
  1339. package/src/activities/execute-cursor/turn-boundary.ts +373 -0
  1340. package/src/activities/execute-cursor/turn-recovery.ts +223 -0
  1341. package/src/activities/execute-cursor/turn-settle.ts +605 -0
  1342. package/src/activities/execute-cursor/turn-setup.ts +964 -0
  1343. package/src/activities/execute-cursor/turn-stream.ts +354 -0
  1344. package/src/activities/execute-cursor/turn.ts +271 -0
  1345. package/src/activities/execute-cursor/usage-pricing.ts +67 -0
  1346. package/src/activities/execute-cursor/workspace-hook-files.ts +424 -0
  1347. package/src/activities/execute-cursor/workspace-setup.ts +549 -0
  1348. package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +404 -0
  1349. package/src/activities/execute-deep-agent/__test-utils__/gateway-substrate.ts +519 -0
  1350. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +430 -0
  1351. package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
  1352. package/src/activities/execute-deep-agent/__test-utils__/paused-session-fixture.ts +172 -0
  1353. package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +84 -0
  1354. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +585 -0
  1355. package/src/activities/execute-deep-agent/__test-utils__/think-bound-session.ts +29 -0
  1356. package/src/activities/execute-deep-agent/__test-utils__/v3-event-fixtures.ts +295 -0
  1357. package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
  1358. package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
  1359. package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +83 -0
  1360. package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +88 -0
  1361. package/src/activities/execute-deep-agent/__tests__/auto-publish.test.ts +144 -0
  1362. package/src/activities/execute-deep-agent/__tests__/builtin-tool-surface.test.ts +108 -0
  1363. package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +286 -0
  1364. package/src/activities/execute-deep-agent/__tests__/cas-capture-observer.test.ts +163 -0
  1365. package/src/activities/execute-deep-agent/__tests__/engine-tools.test.ts +97 -0
  1366. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +133 -0
  1367. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +151 -0
  1368. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.judge.prompt.md +26 -0
  1369. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.append.prompt.md +28 -0
  1370. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +25 -0
  1371. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +140 -0
  1372. package/src/activities/execute-deep-agent/__tests__/goldens/user-message.everything.md +36 -0
  1373. package/src/activities/execute-deep-agent/__tests__/hermetic/answers.test.ts +114 -0
  1374. package/src/activities/execute-deep-agent/__tests__/hermetic/built-in-assistant.test.ts +103 -0
  1375. package/src/activities/execute-deep-agent/__tests__/hermetic/cost-advisory.test.ts +239 -0
  1376. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +306 -0
  1377. package/src/activities/execute-deep-agent/__tests__/hermetic/fixtures/paused-session.deepagents-1.10.2.json +592 -0
  1378. package/src/activities/execute-deep-agent/__tests__/hermetic/fixtures/paused-session.think-bound.json +498 -0
  1379. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.events.json +49 -0
  1380. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.rows.json +32 -0
  1381. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +15 -0
  1382. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.events.json +118 -0
  1383. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.rows.json +45 -0
  1384. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +16 -0
  1385. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.events.json +69 -0
  1386. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.rows.json +30 -0
  1387. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +16 -0
  1388. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.events.json +69 -0
  1389. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.rows.json +97 -0
  1390. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +84 -0
  1391. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-off.events.json +51 -0
  1392. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-off.rows.json +33 -0
  1393. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-off.status.json +27 -0
  1394. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-reconcile.events.json +92 -0
  1395. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-reconcile.rows.json +9 -0
  1396. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-reconcile.status.json +6 -0
  1397. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.events.json +35 -0
  1398. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.rows.json +27 -0
  1399. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +15 -0
  1400. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/hooks.turn1.events.json +107 -0
  1401. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/hooks.turn1.rows.json +74 -0
  1402. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/hooks.turn1.status.json +25 -0
  1403. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/hooks.turn2.events.json +141 -0
  1404. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/hooks.turn2.rows.json +31 -0
  1405. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/hooks.turn2.status.json +26 -0
  1406. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.events.json +71 -0
  1407. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.rows.json +50 -0
  1408. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +26 -0
  1409. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.events.json +105 -0
  1410. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.rows.json +30 -0
  1411. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +27 -0
  1412. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.events.json +37 -0
  1413. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.rows.json +24 -0
  1414. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +15 -0
  1415. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.events.json +24 -0
  1416. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.rows.json +22 -0
  1417. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +15 -0
  1418. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.events.json +14 -0
  1419. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.rows.json +9 -0
  1420. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +16 -0
  1421. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.events.json +24 -0
  1422. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.rows.json +27 -0
  1423. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +17 -0
  1424. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.events.json +352 -0
  1425. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.rows.json +209 -0
  1426. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +18 -0
  1427. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.events.json +71 -0
  1428. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.rows.json +29 -0
  1429. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +16 -0
  1430. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.events.json +1 -0
  1431. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.rows.json +14 -0
  1432. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +7 -0
  1433. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.events.json +90 -0
  1434. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.rows.json +48 -0
  1435. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +15 -0
  1436. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.events.json +124 -0
  1437. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.rows.json +30 -0
  1438. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +16 -0
  1439. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.events.json +70 -0
  1440. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.rows.json +29 -0
  1441. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +16 -0
  1442. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.events.json +24 -0
  1443. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.rows.json +13 -0
  1444. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +16 -0
  1445. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.events.json +24 -0
  1446. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.rows.json +13 -0
  1447. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +16 -0
  1448. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.events.json +36 -0
  1449. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.rows.json +18 -0
  1450. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +16 -0
  1451. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.events.json +118 -0
  1452. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.rows.json +49 -0
  1453. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +16 -0
  1454. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.events.json +49 -0
  1455. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.rows.json +29 -0
  1456. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +16 -0
  1457. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/unattended-skip.events.json +51 -0
  1458. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/unattended-skip.rows.json +31 -0
  1459. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/unattended-skip.status.json +16 -0
  1460. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.events.json +37 -0
  1461. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.rows.json +29 -0
  1462. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +18 -0
  1463. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.events.json +58 -0
  1464. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.rows.json +54 -0
  1465. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/write-todos.status.json +16 -0
  1466. package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
  1467. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +194 -0
  1468. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-parallel-gates.test.ts +131 -0
  1469. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +224 -0
  1470. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +180 -0
  1471. package/src/activities/execute-deep-agent/__tests__/hermetic/hooks.test.ts +556 -0
  1472. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +188 -0
  1473. package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +217 -0
  1474. package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +162 -0
  1475. package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +130 -0
  1476. package/src/activities/execute-deep-agent/__tests__/hermetic/recorded-agent-version.test.ts +148 -0
  1477. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +212 -0
  1478. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +130 -0
  1479. package/src/activities/execute-deep-agent/__tests__/hermetic/resume-across-engine-upgrade.test.ts +268 -0
  1480. package/src/activities/execute-deep-agent/__tests__/hermetic/resume-across-think-retirement.test.ts +181 -0
  1481. package/src/activities/execute-deep-agent/__tests__/hermetic/run-finished-while-waiting.test.ts +110 -0
  1482. package/src/activities/execute-deep-agent/__tests__/hermetic/run-values-refused.test.ts +106 -0
  1483. package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +242 -0
  1484. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-concurrent-invocations.test.ts +312 -0
  1485. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +211 -0
  1486. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-own-context.test.ts +192 -0
  1487. package/src/activities/execute-deep-agent/__tests__/hermetic/thrown-turn-drains-publishes.test.ts +154 -0
  1488. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +167 -0
  1489. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-lists.test.ts +291 -0
  1490. package/src/activities/execute-deep-agent/__tests__/hermetic/turn-phases.test.ts +118 -0
  1491. package/src/activities/execute-deep-agent/__tests__/hermetic/unattended-skip.test.ts +130 -0
  1492. package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +154 -0
  1493. package/src/activities/execute-deep-agent/__tests__/hermetic/write-todos.test.ts +160 -0
  1494. package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +355 -0
  1495. package/src/activities/execute-deep-agent/__tests__/hooks-setup.test.ts +333 -0
  1496. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +350 -0
  1497. package/src/activities/execute-deep-agent/__tests__/loaded-tool-marks.test.ts +95 -0
  1498. package/src/activities/execute-deep-agent/__tests__/plain-turn.live.test.ts +103 -0
  1499. package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +404 -0
  1500. package/src/activities/execute-deep-agent/__tests__/platform-route.test.ts +185 -0
  1501. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +577 -0
  1502. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +293 -0
  1503. package/src/activities/execute-deep-agent/__tests__/resume-across-think-retirement.live.test.ts +98 -0
  1504. package/src/activities/execute-deep-agent/__tests__/resumed-history.test.ts +48 -0
  1505. package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +408 -0
  1506. package/src/activities/execute-deep-agent/__tests__/shell-execute-gate.test.ts +293 -0
  1507. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +120 -0
  1508. package/src/activities/execute-deep-agent/__tests__/subagent-approval-propagation.test.ts +160 -0
  1509. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +214 -0
  1510. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +213 -0
  1511. package/src/activities/execute-deep-agent/__tests__/subagent-spans.test.ts +110 -0
  1512. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +662 -0
  1513. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +197 -0
  1514. package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +330 -0
  1515. package/src/activities/execute-deep-agent/__tests__/tool-call.live.test.ts +80 -0
  1516. package/src/activities/execute-deep-agent/__tests__/tool-scope.test.ts +519 -0
  1517. package/src/activities/execute-deep-agent/__tests__/translator-subagents.test.ts +519 -0
  1518. package/src/activities/execute-deep-agent/__tests__/translator-through-builder.test.ts +830 -0
  1519. package/src/activities/execute-deep-agent/__tests__/translator.test.ts +641 -0
  1520. package/src/activities/execute-deep-agent/__tests__/turn-setup-connect.test.ts +89 -0
  1521. package/src/activities/execute-deep-agent/__tests__/turn-setup-tool-lists.test.ts +192 -0
  1522. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +381 -0
  1523. package/src/activities/execute-deep-agent/__tests__/v3-event-recorder.test.ts +186 -0
  1524. package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +152 -0
  1525. package/src/activities/execute-deep-agent/adapter.ts +95 -0
  1526. package/src/activities/execute-deep-agent/approval-file-change.ts +86 -0
  1527. package/src/activities/execute-deep-agent/auto-publish.ts +80 -0
  1528. package/src/activities/execute-deep-agent/cas-capture-backend.ts +154 -0
  1529. package/src/activities/execute-deep-agent/cas-capture-observer.ts +132 -0
  1530. package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +49 -0
  1531. package/src/activities/execute-deep-agent/deepagents-profiles.ts +51 -0
  1532. package/src/activities/execute-deep-agent/engine-tools.ts +33 -0
  1533. package/src/activities/execute-deep-agent/hitl.ts +274 -0
  1534. package/src/activities/execute-deep-agent/hooks-setup.ts +75 -0
  1535. package/src/activities/execute-deep-agent/inline-publisher.ts +208 -0
  1536. package/src/activities/execute-deep-agent/platform-route.ts +284 -0
  1537. package/src/activities/execute-deep-agent/prompt-builder.ts +547 -0
  1538. package/src/activities/execute-deep-agent/resumed-history.ts +52 -0
  1539. package/src/activities/execute-deep-agent/streaming-side-effects.ts +83 -0
  1540. package/src/activities/execute-deep-agent/subagent-transformer.ts +732 -0
  1541. package/src/activities/execute-deep-agent/subagent-wiring.ts +180 -0
  1542. package/src/activities/execute-deep-agent/todo-list.ts +56 -0
  1543. package/src/activities/execute-deep-agent/translator.ts +564 -0
  1544. package/src/activities/execute-deep-agent/turn-settle.ts +162 -0
  1545. package/src/activities/execute-deep-agent/turn-setup.ts +842 -0
  1546. package/src/activities/execute-deep-agent/turn-stream.ts +309 -0
  1547. package/src/activities/execute-deep-agent/turn.ts +151 -0
  1548. package/src/activities/execute-deep-agent/v3-event-recorder.ts +112 -0
  1549. package/src/activities/generate-session-subject.ts +376 -0
  1550. package/src/activities/list-plugin-tools.ts +251 -0
  1551. package/src/agent-host/__tests__/channel.test.ts +271 -0
  1552. package/src/agent-host/__tests__/codec.test.ts +435 -0
  1553. package/src/agent-host/__tests__/entry-telemetry.test.ts +159 -0
  1554. package/src/agent-host/__tests__/entry.test.ts +223 -0
  1555. package/src/agent-host/__tests__/environment.test.ts +73 -0
  1556. package/src/agent-host/__tests__/failed-boot.test.ts +58 -0
  1557. package/src/agent-host/__tests__/host-sink.test.ts +118 -0
  1558. package/src/agent-host/__tests__/host.test.ts +162 -0
  1559. package/src/agent-host/__tests__/hostile-host.test.ts +440 -0
  1560. package/src/agent-host/__tests__/offload-through-host.test.ts +124 -0
  1561. package/src/agent-host/__tests__/remote-fs.test.ts +177 -0
  1562. package/src/agent-host/__tests__/spawned-host.test.ts +174 -0
  1563. package/src/agent-host/__tests__/supervisor.test.ts +488 -0
  1564. package/src/agent-host/channel.ts +334 -0
  1565. package/src/agent-host/codec.ts +631 -0
  1566. package/src/agent-host/entry.ts +153 -0
  1567. package/src/agent-host/environment.ts +76 -0
  1568. package/src/agent-host/failed-boot.ts +29 -0
  1569. package/src/agent-host/fs-service.ts +133 -0
  1570. package/src/agent-host/host-sink.ts +153 -0
  1571. package/src/agent-host/host.ts +228 -0
  1572. package/src/agent-host/hosting.ts +162 -0
  1573. package/src/agent-host/protocol.ts +380 -0
  1574. package/src/agent-host/remote-adapter.ts +320 -0
  1575. package/src/agent-host/remote-fs.ts +128 -0
  1576. package/src/agent-host/supervisor.ts +382 -0
  1577. package/src/agent-proxy/__tests__/cursor-lane.test.ts +635 -0
  1578. package/src/agent-proxy/__tests__/cursor-sdk-key-required.test.ts +119 -0
  1579. package/src/agent-proxy/__tests__/cursor-sdk-wire.test.ts +175 -0
  1580. package/src/agent-proxy/__tests__/lanes.test.ts +258 -0
  1581. package/src/agent-proxy/__tests__/loopback-certificate.test.ts +100 -0
  1582. package/src/agent-proxy/__tests__/otlp-forward-rebuild.test.ts +66 -0
  1583. package/src/agent-proxy/__tests__/otlp-forward.test.ts +295 -0
  1584. package/src/agent-proxy/__tests__/relay.test.ts +115 -0
  1585. package/src/agent-proxy/__tests__/server.test.ts +436 -0
  1586. package/src/agent-proxy/cursor-lane.ts +528 -0
  1587. package/src/agent-proxy/lanes.ts +285 -0
  1588. package/src/agent-proxy/loopback-certificate.ts +143 -0
  1589. package/src/agent-proxy/otlp-forward.ts +190 -0
  1590. package/src/agent-proxy/relay.ts +188 -0
  1591. package/src/agent-proxy/server.ts +266 -0
  1592. package/src/attach/__tests__/entry.test.ts +123 -0
  1593. package/src/attach/__tests__/import-graph.test.ts +66 -0
  1594. package/src/attach/__tests__/push.test.ts +162 -0
  1595. package/src/attach/__tests__/waiter.test.ts +416 -0
  1596. package/src/attach/entry.ts +92 -0
  1597. package/src/attach/main.ts +26 -0
  1598. package/src/attach/push.ts +165 -0
  1599. package/src/attach/waiter.ts +370 -0
  1600. package/src/bootstrap.ts +178 -0
  1601. package/src/client/__tests__/agent-version-read.test.ts +39 -0
  1602. package/src/client/__tests__/eval-read.test.ts +43 -0
  1603. package/src/client/__tests__/plugin-read.test.ts +57 -0
  1604. package/src/client/__tests__/run-calls.test.ts +65 -0
  1605. package/src/client/__tests__/server-contracts.test.ts +157 -0
  1606. package/src/client/__tests__/session-events-calls.test.ts +139 -0
  1607. package/src/client/__tests__/stigmer-client.test.ts +577 -0
  1608. package/src/client/__tests__/token-claims.test.ts +102 -0
  1609. package/src/client/server-contracts.ts +124 -0
  1610. package/src/client/stigmer-client.ts +686 -0
  1611. package/src/client/token-claims.ts +103 -0
  1612. package/src/config.ts +378 -0
  1613. package/src/exit-backstop.ts +97 -0
  1614. package/src/gen/turn/ai/stigmer/runner/turn/v1/enum_pb.ts +1142 -0
  1615. package/src/gen/turn/ai/stigmer/runner/turn/v1/ledger_pb.ts +458 -0
  1616. package/src/gen/turn/ai/stigmer/runner/turn/v1/rows_pb.ts +920 -0
  1617. package/src/gen-ai-conventions.ts +121 -0
  1618. package/src/harness/README.md +372 -0
  1619. package/src/harness/__tests__/approval-answers.test.ts +202 -0
  1620. package/src/harness/__tests__/approval-decisions.test.ts +114 -0
  1621. package/src/harness/__tests__/attachment-credential.test.ts +115 -0
  1622. package/src/harness/__tests__/capture.test.ts +285 -0
  1623. package/src/harness/__tests__/import-direction.test.ts +169 -0
  1624. package/src/harness/__tests__/loaded-versions.test.ts +76 -0
  1625. package/src/harness/__tests__/mount-skills.test.ts +305 -0
  1626. package/src/harness/__tests__/owed-undos.test.ts +305 -0
  1627. package/src/harness/__tests__/persist-chokepoint.test.ts +344 -0
  1628. package/src/harness/__tests__/readme-index.test.ts +339 -0
  1629. package/src/harness/__tests__/reconcile-turn.test.ts +111 -0
  1630. package/src/harness/__tests__/registry.test.ts +178 -0
  1631. package/src/harness/__tests__/reinvocation-carry.test.ts +65 -0
  1632. package/src/harness/__tests__/resolve-hooks.test.ts +241 -0
  1633. package/src/harness/__tests__/resolve-subagents.test.ts +477 -0
  1634. package/src/harness/__tests__/run-span.test.ts +255 -0
  1635. package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
  1636. package/src/harness/__tests__/run-turn-eval-case.test.ts +211 -0
  1637. package/src/harness/__tests__/run-turn.test.ts +435 -0
  1638. package/src/harness/__tests__/runtime-touches-no-agent-path.test.ts +109 -0
  1639. package/src/harness/__tests__/stop-controller.test.ts +93 -0
  1640. package/src/harness/__tests__/terminal-table.test.ts +81 -0
  1641. package/src/harness/__tests__/transcript-is-engine-free.test.ts +83 -0
  1642. package/src/harness/__tests__/transcript-writers.test.ts +193 -0
  1643. package/src/harness/__tests__/turn-attachments-vision.test.ts +105 -0
  1644. package/src/harness/__tests__/turn-context.test.ts +213 -0
  1645. package/src/harness/__tests__/turn-mcp.test.ts +554 -0
  1646. package/src/harness/__tests__/turn-timeline.test.ts +290 -0
  1647. package/src/harness/__tests__/usage-accumulator.test.ts +106 -0
  1648. package/src/harness/approval-answers.ts +174 -0
  1649. package/src/harness/approval-decisions.ts +82 -0
  1650. package/src/harness/capabilities.ts +155 -0
  1651. package/src/harness/capture.ts +337 -0
  1652. package/src/harness/cost-cap-watch.ts +52 -0
  1653. package/src/harness/events/__tests__/emitter.test.ts +715 -0
  1654. package/src/harness/events/__tests__/ids-corpus.test.ts +86 -0
  1655. package/src/harness/events/emitter.ts +805 -0
  1656. package/src/harness/events/ids.ts +156 -0
  1657. package/src/harness/loaded-versions.ts +78 -0
  1658. package/src/harness/owed-undos.ts +258 -0
  1659. package/src/harness/persist-chokepoint.ts +163 -0
  1660. package/src/harness/registry.ts +203 -0
  1661. package/src/harness/run-span.ts +184 -0
  1662. package/src/harness/run-turn.ts +862 -0
  1663. package/src/harness/stop-controller.ts +101 -0
  1664. package/src/harness/terminal-table.ts +390 -0
  1665. package/src/harness/transcript/__tests__/builder.test.ts +1246 -0
  1666. package/src/harness/transcript/__tests__/resume-seed.test.ts +148 -0
  1667. package/src/harness/transcript/__tests__/state.test.ts +144 -0
  1668. package/src/harness/transcript/builder.ts +925 -0
  1669. package/src/harness/transcript/events.ts +281 -0
  1670. package/src/harness/transcript/resume-seed.ts +280 -0
  1671. package/src/harness/transcript/state.ts +167 -0
  1672. package/src/harness/turn-context.ts +1982 -0
  1673. package/src/harness/turn-timeline.ts +248 -0
  1674. package/src/harness/types.ts +725 -0
  1675. package/src/harness/usage-accumulator.ts +134 -0
  1676. package/src/harness-adapters.ts +48 -0
  1677. package/src/idle-watchdog.ts +28 -0
  1678. package/src/in-flight.ts +71 -0
  1679. package/src/index.ts +48 -0
  1680. package/src/interceptors/__tests__/run-credential-activity.test.ts +86 -0
  1681. package/src/interceptors/run-credential-activity.ts +40 -0
  1682. package/src/ipc-protocol-fixtures.ts +90 -0
  1683. package/src/ipc-protocol.ts +89 -0
  1684. package/src/main.ts +506 -0
  1685. package/src/middleware/__tests__/advisory-message.test.ts +59 -0
  1686. package/src/middleware/__tests__/approval-gate-hooks.test.ts +269 -0
  1687. package/src/middleware/__tests__/approval-gate.test.ts +1072 -0
  1688. package/src/middleware/__tests__/cost-advisory.test.ts +272 -0
  1689. package/src/middleware/__tests__/error-hints.test.ts +90 -0
  1690. package/src/middleware/__tests__/execution-budget.test.ts +239 -0
  1691. package/src/middleware/__tests__/loop-detection.test.ts +194 -0
  1692. package/src/middleware/__tests__/otel-spans.test.ts +460 -0
  1693. package/src/middleware/__tests__/path-normalization.test.ts +198 -0
  1694. package/src/middleware/__tests__/tool-intent.test.ts +266 -0
  1695. package/src/middleware/__tests__/tool-truncation.test.ts +112 -0
  1696. package/src/middleware/advisory-message.ts +62 -0
  1697. package/src/middleware/approval-gate.ts +741 -0
  1698. package/src/middleware/cost-advisory.ts +224 -0
  1699. package/src/middleware/error-hints.ts +136 -0
  1700. package/src/middleware/execution-budget.ts +197 -0
  1701. package/src/middleware/index.ts +100 -0
  1702. package/src/middleware/loop-detection.ts +197 -0
  1703. package/src/middleware/otel-spans.ts +345 -0
  1704. package/src/middleware/path-normalization.ts +178 -0
  1705. package/src/middleware/tool-intent.ts +174 -0
  1706. package/src/middleware/tool-scope.ts +201 -0
  1707. package/src/middleware/tool-truncation.ts +94 -0
  1708. package/src/middleware/types.ts +141 -0
  1709. package/src/otel-export.ts +325 -0
  1710. package/src/otel-metrics.ts +61 -0
  1711. package/src/otel.ts +173 -0
  1712. package/src/payload-codecs.ts +66 -0
  1713. package/src/pipe-safety.ts +117 -0
  1714. package/src/pool-member.ts +99 -0
  1715. package/src/preflight.ts +104 -0
  1716. package/src/run-trace-id.ts +50 -0
  1717. package/src/runner-entry.ts +18 -0
  1718. package/src/runner-manager.ts +882 -0
  1719. package/src/runner-token-coordinator.ts +140 -0
  1720. package/src/runner.ts +588 -0
  1721. package/src/sandbox-token-renewal.ts +211 -0
  1722. package/src/shared/__tests__/activity-input.test.ts +78 -0
  1723. package/src/shared/__tests__/advisory-anthropic-payload.test.ts +194 -0
  1724. package/src/shared/__tests__/agent-handover.test.ts +186 -0
  1725. package/src/shared/__tests__/agent-identity.test.ts +144 -0
  1726. package/src/shared/__tests__/agent-servers.test.ts +55 -0
  1727. package/src/shared/__tests__/approval-canonicalize.test.ts +106 -0
  1728. package/src/shared/__tests__/approval-fingerprint.test.ts +115 -0
  1729. package/src/shared/__tests__/approval-policy.test.ts +466 -0
  1730. package/src/shared/__tests__/args-preview.test.ts +147 -0
  1731. package/src/shared/__tests__/artifact-storage-extended.test.ts +243 -0
  1732. package/src/shared/__tests__/artifact-storage.test.ts +844 -0
  1733. package/src/shared/__tests__/attachment-download-urls.test.ts +72 -0
  1734. package/src/shared/__tests__/attachment-naming.test.ts +146 -0
  1735. package/src/shared/__tests__/attachment-resolver.test.ts +644 -0
  1736. package/src/shared/__tests__/attachment-vision.test.ts +424 -0
  1737. package/src/shared/__tests__/attachment-zip.test.ts +236 -0
  1738. package/src/shared/__tests__/bedrock-adapter.test.ts +213 -0
  1739. package/src/shared/__tests__/bedrock-seam.test.ts +390 -0
  1740. package/src/shared/__tests__/blueprint-resolver.test.ts +629 -0
  1741. package/src/shared/__tests__/builtin-judge.test.ts +57 -0
  1742. package/src/shared/__tests__/caller-identity.test.ts +172 -0
  1743. package/src/shared/__tests__/channel-attachment.test.ts +285 -0
  1744. package/src/shared/__tests__/cold-start-timing.test.ts +333 -0
  1745. package/src/shared/__tests__/context-bridge.test.ts +51 -0
  1746. package/src/shared/__tests__/conversation-attachment.test.ts +152 -0
  1747. package/src/shared/__tests__/conversation-catchup.test.ts +94 -0
  1748. package/src/shared/__tests__/cost-guard.test.ts +68 -0
  1749. package/src/shared/__tests__/declared-preferences.test.ts +109 -0
  1750. package/src/shared/__tests__/default-model-agrees-with-server.test.ts +74 -0
  1751. package/src/shared/__tests__/exact-apply.test.ts +370 -0
  1752. package/src/shared/__tests__/execution-target.test.ts +33 -0
  1753. package/src/shared/__tests__/extract-json.test.ts +153 -0
  1754. package/src/shared/__tests__/extract-structured-output.test.ts +149 -0
  1755. package/src/shared/__tests__/file-change.test.ts +85 -0
  1756. package/src/shared/__tests__/file-tools.test.ts +90 -0
  1757. package/src/shared/__tests__/fingerprint-secret.test.ts +51 -0
  1758. package/src/shared/__tests__/foundry-adapter.test.ts +276 -0
  1759. package/src/shared/__tests__/foundry-seam.test.ts +482 -0
  1760. package/src/shared/__tests__/grpc-retry-extended.test.ts +38 -0
  1761. package/src/shared/__tests__/grpc-retry.test.ts +43 -0
  1762. package/src/shared/__tests__/http-retry.test.ts +68 -0
  1763. package/src/shared/__tests__/implement-plan-prompt.test.ts +86 -0
  1764. package/src/shared/__tests__/json-schema-to-zod.test.ts +227 -0
  1765. package/src/shared/__tests__/lease-scope-corpus.test.ts +78 -0
  1766. package/src/shared/__tests__/llm-backend.test.ts +676 -0
  1767. package/src/shared/__tests__/llm-proxy.test.ts +179 -0
  1768. package/src/shared/__tests__/mcp-manager.test.ts +272 -0
  1769. package/src/shared/__tests__/mcp-oauth-detect.test.ts +167 -0
  1770. package/src/shared/__tests__/mcp-resolver.test.ts +454 -0
  1771. package/src/shared/__tests__/mcp-schema-sanitizer.test.ts +267 -0
  1772. package/src/shared/__tests__/mcp-tool-listing.hang.test.ts +82 -0
  1773. package/src/shared/__tests__/mcp-tool-listing.test.ts +257 -0
  1774. package/src/shared/__tests__/mcp-transport-guard.test.ts +71 -0
  1775. package/src/shared/__tests__/memory-attachment.test.ts +183 -0
  1776. package/src/shared/__tests__/memory-retrieval.test.ts +310 -0
  1777. package/src/shared/__tests__/model-client-sampling.test.ts +110 -0
  1778. package/src/shared/__tests__/model-client.test.ts +623 -0
  1779. package/src/shared/__tests__/model-error.test.ts +579 -0
  1780. package/src/shared/__tests__/model-lanes.test.ts +225 -0
  1781. package/src/shared/__tests__/model-pricing.test.ts +131 -0
  1782. package/src/shared/__tests__/model-registry-at-provider.live.test.ts +63 -0
  1783. package/src/shared/__tests__/model-registry.test.ts +460 -0
  1784. package/src/shared/__tests__/persist-decision.test.ts +87 -0
  1785. package/src/shared/__tests__/placeholder-resolver.test.ts +210 -0
  1786. package/src/shared/__tests__/plan-artifact.test.ts +260 -0
  1787. package/src/shared/__tests__/plan-mode-permissions.test.ts +29 -0
  1788. package/src/shared/__tests__/platform-server-address.test.ts +125 -0
  1789. package/src/shared/__tests__/plugin-mount-faults.test.ts +71 -0
  1790. package/src/shared/__tests__/plugin-mount.test.ts +407 -0
  1791. package/src/shared/__tests__/plugin-servers.test.ts +53 -0
  1792. package/src/shared/__tests__/policy-source-corpus.test.ts +69 -0
  1793. package/src/shared/__tests__/prompt-sections.test.ts +113 -0
  1794. package/src/shared/__tests__/recalled-memories.test.ts +88 -0
  1795. package/src/shared/__tests__/registry-endpoint.test.ts +96 -0
  1796. package/src/shared/__tests__/run-credential.test.ts +109 -0
  1797. package/src/shared/__tests__/run-values.test.ts +125 -0
  1798. package/src/shared/__tests__/runner-credential-store.test.ts +175 -0
  1799. package/src/shared/__tests__/secret-leak-scan.test.ts +100 -0
  1800. package/src/shared/__tests__/sender-identity.test.ts +92 -0
  1801. package/src/shared/__tests__/session-context.test.ts +67 -0
  1802. package/src/shared/__tests__/shell-env.test.ts +118 -0
  1803. package/src/shared/__tests__/skill-mount.test.ts +353 -0
  1804. package/src/shared/__tests__/skill-resolver.test.ts +401 -0
  1805. package/src/shared/__tests__/stall-watchdog.test.ts +193 -0
  1806. package/src/shared/__tests__/stamp-flowed-rows.test.ts +142 -0
  1807. package/src/shared/__tests__/status-offload.test.ts +778 -0
  1808. package/src/shared/__tests__/status.test.ts +350 -0
  1809. package/src/shared/__tests__/streaming-scheduler.test.ts +198 -0
  1810. package/src/shared/__tests__/subagent-gate.test.ts +112 -0
  1811. package/src/shared/__tests__/subagent-rows.test.ts +34 -0
  1812. package/src/shared/__tests__/subagents.test.ts +135 -0
  1813. package/src/shared/__tests__/synthesized-attachment.test.ts +96 -0
  1814. package/src/shared/__tests__/telemetry-content.test.ts +220 -0
  1815. package/src/shared/__tests__/thinking-mode.test.ts +69 -0
  1816. package/src/shared/__tests__/todos.test.ts +216 -0
  1817. package/src/shared/__tests__/tool-kind.test.ts +81 -0
  1818. package/src/shared/__tests__/tool-lists.test.ts +463 -0
  1819. package/src/shared/__tests__/tool-rounds.test.ts +107 -0
  1820. package/src/shared/__tests__/tool-row.test.ts +390 -0
  1821. package/src/shared/__tests__/trace-context.test.ts +68 -0
  1822. package/src/shared/__tests__/vertex-adapter.test.ts +196 -0
  1823. package/src/shared/__tests__/vertex-seam.test.ts +296 -0
  1824. package/src/shared/__tests__/with-timeout.test.ts +60 -0
  1825. package/src/shared/__tests__/worker-shutdown.test.ts +106 -0
  1826. package/src/shared/__tests__/zip-extract.test.ts +256 -0
  1827. package/src/shared/activity-input.ts +78 -0
  1828. package/src/shared/agent-fs.ts +264 -0
  1829. package/src/shared/agent-handover.ts +171 -0
  1830. package/src/shared/agent-identity.ts +185 -0
  1831. package/src/shared/agent-servers.ts +51 -0
  1832. package/src/shared/approval-canonicalize.ts +159 -0
  1833. package/src/shared/approval-fingerprint.ts +145 -0
  1834. package/src/shared/approval-policy.ts +536 -0
  1835. package/src/shared/archive-mount.ts +140 -0
  1836. package/src/shared/args-preview.ts +128 -0
  1837. package/src/shared/artifact-storage.ts +496 -0
  1838. package/src/shared/attachment-download-urls.ts +76 -0
  1839. package/src/shared/attachment-naming.ts +78 -0
  1840. package/src/shared/attachment-resolver.ts +468 -0
  1841. package/src/shared/attachment-vision.ts +466 -0
  1842. package/src/shared/attachment-zip.ts +281 -0
  1843. package/src/shared/blueprint-resolver.ts +420 -0
  1844. package/src/shared/builtin-assistant-prompt.ts +38 -0
  1845. package/src/shared/builtin-judge.ts +62 -0
  1846. package/src/shared/caller-identity.ts +186 -0
  1847. package/src/shared/channel-attachment.ts +246 -0
  1848. package/src/shared/checkpointer/__tests__/factory.test.ts +88 -0
  1849. package/src/shared/checkpointer/__tests__/http-saver.test.ts +393 -0
  1850. package/src/shared/checkpointer/__tests__/sqlite-saver.test.ts +212 -0
  1851. package/src/shared/checkpointer/factory.ts +94 -0
  1852. package/src/shared/checkpointer/http-saver.ts +429 -0
  1853. package/src/shared/checkpointer/sqlite-saver.ts +384 -0
  1854. package/src/shared/checkpointer/types.ts +27 -0
  1855. package/src/shared/cold-start-timing.ts +260 -0
  1856. package/src/shared/context-bridge.ts +51 -0
  1857. package/src/shared/conversation-attachment.ts +141 -0
  1858. package/src/shared/conversation-catchup.ts +93 -0
  1859. package/src/shared/cost-guard.ts +63 -0
  1860. package/src/shared/declared-preferences.ts +84 -0
  1861. package/src/shared/eval-case/__tests__/agent-mock.test.ts +126 -0
  1862. package/src/shared/eval-case/__tests__/case-archive.test.ts +159 -0
  1863. package/src/shared/eval-case/__tests__/mock-endpoint-failure.test.ts +65 -0
  1864. package/src/shared/eval-case/__tests__/mock-endpoint.test.ts +269 -0
  1865. package/src/shared/eval-case/__tests__/prepare-case.test.ts +228 -0
  1866. package/src/shared/eval-case/__tests__/read-files.test.ts +90 -0
  1867. package/src/shared/eval-case/agent-mock.ts +131 -0
  1868. package/src/shared/eval-case/case-archive.ts +135 -0
  1869. package/src/shared/eval-case/mock-endpoint.ts +282 -0
  1870. package/src/shared/eval-case/prepare-case.ts +227 -0
  1871. package/src/shared/eval-case/read-files.ts +94 -0
  1872. package/src/shared/exact-apply.ts +247 -0
  1873. package/src/shared/execution-context.ts +62 -0
  1874. package/src/shared/execution-target.ts +17 -0
  1875. package/src/shared/extract-json.ts +153 -0
  1876. package/src/shared/extract-structured-output.ts +83 -0
  1877. package/src/shared/file-change.ts +62 -0
  1878. package/src/shared/file-tools.ts +167 -0
  1879. package/src/shared/filereview/__tests__/capture.test.ts +1178 -0
  1880. package/src/shared/filereview/__tests__/cas-progress.test.ts +229 -0
  1881. package/src/shared/filereview/__tests__/cas-substrate.test.ts +504 -0
  1882. package/src/shared/filereview/__tests__/command-provenance.test.ts +249 -0
  1883. package/src/shared/filereview/__tests__/digest.test.ts +100 -0
  1884. package/src/shared/filereview/__tests__/events.test.ts +350 -0
  1885. package/src/shared/filereview/__tests__/git-substrate.test.ts +365 -0
  1886. package/src/shared/filereview/__tests__/line-counts.test.ts +73 -0
  1887. package/src/shared/filereview/__tests__/progress.test.ts +480 -0
  1888. package/src/shared/filereview/__tests__/proxy-reconcile.test.ts +265 -0
  1889. package/src/shared/filereview/__tests__/record.test.ts +126 -0
  1890. package/src/shared/filereview/__tests__/secret-paths.test.ts +121 -0
  1891. package/src/shared/filereview/capture.ts +783 -0
  1892. package/src/shared/filereview/cas-progress.ts +155 -0
  1893. package/src/shared/filereview/cas-substrate.ts +460 -0
  1894. package/src/shared/filereview/cas-touched.ts +89 -0
  1895. package/src/shared/filereview/command-provenance.ts +182 -0
  1896. package/src/shared/filereview/digest.ts +83 -0
  1897. package/src/shared/filereview/events.ts +515 -0
  1898. package/src/shared/filereview/git-substrate.ts +680 -0
  1899. package/src/shared/filereview/index.ts +99 -0
  1900. package/src/shared/filereview/line-counts.ts +83 -0
  1901. package/src/shared/filereview/progress.ts +361 -0
  1902. package/src/shared/filereview/record.ts +107 -0
  1903. package/src/shared/filereview/secret-paths.ts +119 -0
  1904. package/src/shared/fingerprint-secret.ts +77 -0
  1905. package/src/shared/grpc-retry.ts +54 -0
  1906. package/src/shared/heartbeat.ts +50 -0
  1907. package/src/shared/hooks/__tests__/answer.test.ts +179 -0
  1908. package/src/shared/hooks/__tests__/condition.test.ts +389 -0
  1909. package/src/shared/hooks/__tests__/cursor-format.test.ts +209 -0
  1910. package/src/shared/hooks/__tests__/evaluate.test.ts +473 -0
  1911. package/src/shared/hooks/__tests__/run.test.ts +159 -0
  1912. package/src/shared/hooks/__tests__/stall.test.ts +75 -0
  1913. package/src/shared/hooks/__tests__/tool-view.test.ts +235 -0
  1914. package/src/shared/hooks/answer.ts +180 -0
  1915. package/src/shared/hooks/condition.ts +341 -0
  1916. package/src/shared/hooks/evaluate.ts +381 -0
  1917. package/src/shared/hooks/formats/claude-code.ts +106 -0
  1918. package/src/shared/hooks/formats/common.ts +31 -0
  1919. package/src/shared/hooks/formats/cursor.ts +261 -0
  1920. package/src/shared/hooks/hook-set.ts +134 -0
  1921. package/src/shared/hooks/matcher.ts +31 -0
  1922. package/src/shared/hooks/messages.ts +38 -0
  1923. package/src/shared/hooks/run.ts +190 -0
  1924. package/src/shared/hooks/setup.ts +209 -0
  1925. package/src/shared/hooks/shell-commands.ts +326 -0
  1926. package/src/shared/hooks/tool-view.ts +406 -0
  1927. package/src/shared/http-retry.ts +139 -0
  1928. package/src/shared/implement-plan-prompt.ts +104 -0
  1929. package/src/shared/json-schema-to-zod.ts +53 -0
  1930. package/src/shared/llm-backend.ts +623 -0
  1931. package/src/shared/llm-proxy.ts +154 -0
  1932. package/src/shared/mcp-manager.ts +161 -0
  1933. package/src/shared/mcp-oauth-detect.ts +80 -0
  1934. package/src/shared/mcp-resolver.ts +338 -0
  1935. package/src/shared/mcp-schema-sanitizer.ts +222 -0
  1936. package/src/shared/mcp-tool-listing.ts +203 -0
  1937. package/src/shared/mcp-transport-guard.ts +81 -0
  1938. package/src/shared/memory-attachment.ts +177 -0
  1939. package/src/shared/memory-retrieval.ts +380 -0
  1940. package/src/shared/model-client.ts +465 -0
  1941. package/src/shared/model-error.ts +551 -0
  1942. package/src/shared/model-facts.ts +30 -0
  1943. package/src/shared/model-lanes.ts +66 -0
  1944. package/src/shared/model-pricing-data.ts +123 -0
  1945. package/src/shared/model-pricing.ts +64 -0
  1946. package/src/shared/model-registry.ts +352 -0
  1947. package/src/shared/persist-decision.ts +47 -0
  1948. package/src/shared/placeholder-resolver.ts +113 -0
  1949. package/src/shared/plan-artifact.ts +255 -0
  1950. package/src/shared/plan-mode-permissions.ts +53 -0
  1951. package/src/shared/plan-mode-prompt.ts +74 -0
  1952. package/src/shared/platform-server-address.ts +124 -0
  1953. package/src/shared/plugin-mount.ts +495 -0
  1954. package/src/shared/plugin-servers.ts +23 -0
  1955. package/src/shared/prompt-sections.ts +205 -0
  1956. package/src/shared/recalled-memories.ts +90 -0
  1957. package/src/shared/registry-endpoint.ts +108 -0
  1958. package/src/shared/run-credential-store.ts +45 -0
  1959. package/src/shared/run-credential.ts +48 -0
  1960. package/src/shared/run-values.ts +154 -0
  1961. package/src/shared/runner-credential-keys.ts +106 -0
  1962. package/src/shared/runner-credential-store.ts +115 -0
  1963. package/src/shared/sender-identity.ts +85 -0
  1964. package/src/shared/service-tier.ts +78 -0
  1965. package/src/shared/session-context.ts +58 -0
  1966. package/src/shared/shell-env.ts +75 -0
  1967. package/src/shared/skill-mount.ts +214 -0
  1968. package/src/shared/skill-resolver.ts +167 -0
  1969. package/src/shared/stall-watchdog.ts +122 -0
  1970. package/src/shared/status-offload.ts +742 -0
  1971. package/src/shared/status.ts +268 -0
  1972. package/src/shared/streaming-scheduler.ts +158 -0
  1973. package/src/shared/subagent-gate.ts +122 -0
  1974. package/src/shared/subagent-rows.ts +39 -0
  1975. package/src/shared/subagents.ts +75 -0
  1976. package/src/shared/synthesized-attachment.ts +100 -0
  1977. package/src/shared/telemetry-content.ts +301 -0
  1978. package/src/shared/thinking-mode.ts +125 -0
  1979. package/src/shared/todos.ts +68 -0
  1980. package/src/shared/tool-kind.ts +140 -0
  1981. package/src/shared/tool-lists.ts +617 -0
  1982. package/src/shared/tool-rounds.ts +151 -0
  1983. package/src/shared/tool-row.ts +346 -0
  1984. package/src/shared/trace-context.ts +35 -0
  1985. package/src/shared/with-timeout.ts +53 -0
  1986. package/src/shared/worker-shutdown.ts +134 -0
  1987. package/src/shared/workspace/__tests__/file-tree.test.ts +210 -0
  1988. package/src/shared/workspace/__tests__/git-credential.test.ts +470 -0
  1989. package/src/shared/workspace/__tests__/git-identity.test.ts +124 -0
  1990. package/src/shared/workspace/__tests__/git-source.test.ts +476 -0
  1991. package/src/shared/workspace/__tests__/local-backend-platform.test.ts +259 -0
  1992. package/src/shared/workspace/__tests__/local-backend.test.ts +160 -0
  1993. package/src/shared/workspace/__tests__/platform-mount.test.ts +378 -0
  1994. package/src/shared/workspace/__tests__/provisioner.test.ts +194 -0
  1995. package/src/shared/workspace/__tests__/session-provision.test.ts +322 -0
  1996. package/src/shared/workspace/__tests__/session-root.test.ts +42 -0
  1997. package/src/shared/workspace/__tests__/stigmer-link.test.ts +278 -0
  1998. package/src/shared/workspace/__tests__/workspace-lock.test.ts +207 -0
  1999. package/src/shared/workspace/__tests__/writeback-coordinator-git.test.ts +244 -0
  2000. package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +495 -0
  2001. package/src/shared/workspace/file-tree.ts +116 -0
  2002. package/src/shared/workspace/git-credential.ts +247 -0
  2003. package/src/shared/workspace/git-identity.ts +41 -0
  2004. package/src/shared/workspace/local-backend.ts +132 -0
  2005. package/src/shared/workspace/platform-dir.ts +163 -0
  2006. package/src/shared/workspace/platform-mount.ts +190 -0
  2007. package/src/shared/workspace/provisioner.ts +119 -0
  2008. package/src/shared/workspace/session-provision.ts +104 -0
  2009. package/src/shared/workspace/session-root.ts +60 -0
  2010. package/src/shared/workspace/sources/empty.ts +19 -0
  2011. package/src/shared/workspace/sources/git.ts +292 -0
  2012. package/src/shared/workspace/sources/local-path.ts +92 -0
  2013. package/src/shared/workspace/stigmer-link.ts +185 -0
  2014. package/src/shared/workspace/types.ts +85 -0
  2015. package/src/shared/workspace/workspace-lock.ts +245 -0
  2016. package/src/shared/workspace/writeback-coordinator.ts +522 -0
  2017. package/src/shared/zip-extract.ts +118 -0
  2018. package/src/tools/__tests__/url-guard.test.ts +155 -0
  2019. package/src/tools/__tests__/web-fetch-tool.test.ts +193 -0
  2020. package/src/tools/index.ts +27 -0
  2021. package/src/tools/url-guard.ts +140 -0
  2022. package/src/tools/web-fetch-tool.ts +278 -0
  2023. package/src/worker.ts +112 -0
  2024. package/src/workflow-source.ts +72 -0
  2025. package/src/workflows/__tests__/barrel.test.ts +21 -0
  2026. package/src/workflows/__tests__/list-plugin-tools.test.ts +82 -0
  2027. package/src/workflows/index.ts +36 -0
  2028. package/src/workflows/list-plugin-tools.ts +70 -0
  2029. package/src/workflows/types.ts +46 -0
@@ -0,0 +1,1408 @@
1
+ /**
2
+ * @regression file-hitl-gate — pins that decisions bind to the active turn's
3
+ * denial ledger, never a stale one, and that a resume respects its order.
4
+ *
5
+ * Behavior tests for the generated preToolUse bash hook.
6
+ *
7
+ * These run the ACTUAL bash script the runner writes into the workspace, feeding
8
+ * it the REAL hook-input shape captured from @cursor/sdk (PascalCase
9
+ * `tool_name`; `file_path`/`command` in `tool_input`). They are the strongest
10
+ * guard against the regression this work fixes: a gated built-in must be denied,
11
+ * its denial must be recorded with a token byte-identical to the runner's
12
+ * grantToken, and an exact-resource grant must allow only that resource.
13
+ *
14
+ * Skipped automatically where bash is unavailable.
15
+ */
16
+
17
+ import { describe, it, expect, onTestFinished } from "vitest";
18
+ import { execFileSync } from "node:child_process";
19
+ import { existsSync, mkdtempSync, mkdirSync, writeFileSync, rmSync, readFileSync, symlinkSync } from "node:fs";
20
+ import { tmpdir } from "node:os";
21
+ import { join } from "node:path";
22
+
23
+ import { buildHookClientScript, generateHookScript } from "../hook-script.js";
24
+ import { create as createMessage } from "@bufbuild/protobuf";
25
+ import { HookGroupSchema, HookHandlerSchema } from "@stigmer/apis/ai/stigmer/agentic/plugin/v1/hooks_pb";
26
+ import { HookEvaluator } from "../../../shared/hooks/evaluate.js";
27
+ import { HookSet } from "../../../shared/hooks/hook-set.js";
28
+ import { buildShellEnv } from "../../../shared/shell-env.js";
29
+ import { startHookServer } from "../hook-server.js";
30
+ import { CursorEngineToolViews } from "../hook-views.js";
31
+ import { buildApprovalState, grantToken, hookAskDigest, primaryToken, scopeRefusalToken, toolIdentity } from "../approval-state.js";
32
+ import { AGENT_SCOPE_KEY, READ_SCOPE_KEY, compileHookToolScope, scopeKey } from "../hook-scope.js";
33
+ import { CURSOR_SDK_TOOL_COVERS } from "@stigmer/tool-vocabulary";
34
+ import { ToolScope } from "../../../shared/tool-lists.js";
35
+ import { mcpToolKey } from "../../../shared/approval-policy.js";
36
+ import { contentDigest } from "../../../shared/file-tools.js";
37
+ import {
38
+ setupCursorHookHarness as setup,
39
+ hasBash,
40
+ hookWrite,
41
+ hookEdit,
42
+ hookShell,
43
+ hookDelete,
44
+ hookRead,
45
+ hookMcp,
46
+ hookMcpPreToolUse,
47
+ hookSubagentStart,
48
+ hookBuiltin,
49
+ NO_MCP_DEFAULT,
50
+ } from "../__test-utils__/cursor-hook-harness.js";
51
+
52
+ /** Decode the base64(JSON(tool_input)) the hook records on a denial. */
53
+ function decodeInput(b64: string | undefined): Record<string, unknown> {
54
+ if (!b64) throw new Error("ledger entry carried no input");
55
+ return JSON.parse(Buffer.from(b64, "base64").toString("utf-8")) as Record<string, unknown>;
56
+ }
57
+
58
+ const d = hasBash ? describe : describe.skip;
59
+
60
+ d("generated approval hook (preToolUse + beforeMCPExecution)", () => {
61
+ it("denies gated built-ins and records the PRIMARY token (content-exact for a write, coarse for shell/delete)", () => {
62
+ const h = setup({});
63
+
64
+ for (const [input, category, salient, args] of [
65
+ // hookWrite defaults content "x"; the hook records the content-exact token.
66
+ [hookWrite("/x/a.txt"), "write", "/x/a.txt", { content: "x" }],
67
+ [hookShell("rm -rf build"), "shell", "rm -rf build", {}],
68
+ [hookDelete("/x/b.txt"), "delete", "/x/b.txt", {}],
69
+ ] as const) {
70
+ h.resetLedger();
71
+ expect(h.decide(input).permission).toBe("deny");
72
+ const ledger = h.ledger();
73
+ expect(ledger).toHaveLength(1);
74
+ // Byte-identical to the runner's primaryToken: content-exact when the hook
75
+ // can compute an edit digest (the write), else the coarse grantToken.
76
+ expect(ledger[0].token).toBe(primaryToken(category, salient, contentDigest(args)));
77
+ // The normal gate is the APPROVAL kind — the only kind that pauses.
78
+ expect(ledger[0].kind).toBe("approval");
79
+ }
80
+ });
81
+
82
+ it("allows read-only built-ins", () => {
83
+ const h = setup({});
84
+ expect(h.decide(hookRead("/x/a.txt")).permission).toBe("allow");
85
+ expect(h.ledger()).toEqual([]);
86
+ });
87
+
88
+ it("auto-approve-all allows even gated built-ins", () => {
89
+ const h = setup({ autoApproveAll: true });
90
+ expect(h.decide(hookWrite("/x/a.txt")).permission).toBe("allow");
91
+ });
92
+
93
+ it("a run-lifetime category lease allows that category and ONLY that category", () => {
94
+ // "Approve all shell commands" must let later shell calls through while still
95
+ // gating a write — the scoped successor to the old global auto-approve-all.
96
+ const h = setup({ leasedCategories: ["shell"] });
97
+ expect(h.decide(hookShell("rm -rf build")).permission).toBe("allow");
98
+ const writeDecision = h.decide(hookWrite("/x/a.txt"));
99
+ expect(writeDecision.permission).toBe("deny");
100
+ // The denied, non-leased write is still recorded for the runner.
101
+ expect(h.ledger().map((e) => e.toolName)).toContain("Write");
102
+ });
103
+
104
+ // Exact-resource lease isolation ("no name-only over-grant") moved to the
105
+ // gateway Contract Test Kit's invariant 10, where the SAME bash hook is driven
106
+ // through the Cursor substrate adapter alongside the deep-agent substrate. See
107
+ // src/__tests__/approval-gateway-contract.test.ts.
108
+
109
+ it("fails closed (deny) when the state file is missing, recorded as kind fail-closed", () => {
110
+ const h = setup({ noStateFile: true });
111
+ expect(h.decide(hookWrite("/x/a.txt")).permission).toBe("deny");
112
+ // The broken-gate deny is ATTRIBUTABLE (issue #205): recorded under the
113
+ // primary token with kind "fail-closed" and — like every non-approval
114
+ // kind — content-free (no input field: secret content is never persisted).
115
+ const ledger = h.ledger();
116
+ expect(ledger).toHaveLength(1);
117
+ expect(ledger[0].kind).toBe("fail-closed");
118
+ expect(ledger[0].token).toBe(primaryToken("write", "/x/a.txt", contentDigest({ content: "x" })));
119
+ expect(ledger[0]).not.toHaveProperty("input");
120
+ });
121
+
122
+ // Unattended approval mode: same gate, different RESOLUTION — the
123
+ // approval-deny arms record the non-pausing "unattended" kind with an
124
+ // adapt-and-explain message. What is gated must be byte-identical to
125
+ // interactive mode; only the kind and the agent message differ.
126
+ describe("unattended approval mode", () => {
127
+ it("denies a gated built-in with kind 'unattended' and the adapt message (no resume promise)", () => {
128
+ const h = setup({ unattendedSkip: true });
129
+ const res = h.decide(hookShell("rm -rf build"));
130
+ expect(res.permission).toBe("deny");
131
+ expect(res.raw).toContain("skipped automatically");
132
+ expect(res.raw).not.toContain("resume you");
133
+ const ledger = h.ledger();
134
+ expect(ledger).toHaveLength(1);
135
+ expect(ledger[0].kind).toBe("unattended");
136
+ // Same identity space as interactive mode — the stamping correlates on it.
137
+ expect(ledger[0].token).toBe(primaryToken("shell", "rm -rf build", ""));
138
+ // Non-approval kinds are content-free (no approval card needs a preview).
139
+ expect(ledger[0]).not.toHaveProperty("input");
140
+ });
141
+
142
+ it("denies a require-approval MCP tool with kind 'unattended'", () => {
143
+ const h = setup({
144
+ unattendedSkip: true,
145
+ destructiveMcpTools: ["drop_table"],
146
+ });
147
+ const res = h.decide(hookMcp("drop_table", { table: "users" }));
148
+ expect(res.permission).toBe("deny");
149
+ expect(res.raw).toContain("skipped automatically");
150
+ const ledger = h.ledger();
151
+ expect(ledger).toHaveLength(1);
152
+ expect(ledger[0].kind).toBe("unattended");
153
+ expect(ledger[0].token).toBe(grantToken("srv/drop_table", ""));
154
+ });
155
+
156
+ it("still allows auto-approved MCP tools and read-only built-ins (gating is unchanged)", () => {
157
+ const h = setup({
158
+ unattendedSkip: true,
159
+ destructiveMcpTools: ["drop_table"],
160
+ });
161
+ expect(h.decide(hookMcp("list_tables")).permission).toBe("allow");
162
+ expect(h.decide(hookRead("/x/a.txt")).permission).toBe("allow");
163
+ expect(h.ledger()).toEqual([]);
164
+ });
165
+
166
+ it("the secret hard-block stays kind 'secret' (mode-independent)", () => {
167
+ const h = setup({ unattendedSkip: true });
168
+ const res = h.decide(hookWrite("/x/.env", "API_KEY=abc"));
169
+ expect(res.permission).toBe("deny");
170
+ const ledger = h.ledger();
171
+ expect(ledger).toHaveLength(1);
172
+ expect(ledger[0].kind).toBe("secret");
173
+ });
174
+ });
175
+
176
+ // File review off (stigmer#1471): a built-in write or delete flows
177
+ // unreviewed and unasked; the secret-like write block stays, keyed on the
178
+ // git substrate; shell and destructive MCP still ask.
179
+ describe("file review off", () => {
180
+ it("allows a write and a delete with no ledger entry, in a git workspace and in a non-git one", () => {
181
+ for (const gitWorkspace of [true, false]) {
182
+ const h = setup({ fileReview: false, gitWorkspace });
183
+ expect(h.decide(hookWrite(join(h.root, "notes.md"))).permission).toBe("allow");
184
+ expect(h.decide(hookDelete(join(h.root, "old.md"))).permission).toBe("allow");
185
+ expect(h.ledger()).toEqual([]);
186
+ }
187
+ });
188
+
189
+ it("allows a write on an unattended surface: it is applied, not skipped", () => {
190
+ const h = setup({ fileReview: false, unattendedSkip: true });
191
+ expect(h.decide(hookWrite(join(h.root, "reply.md"))).permission).toBe("allow");
192
+ expect(h.ledger()).toEqual([]);
193
+ });
194
+
195
+ it("shell and a destructive MCP tool still ask", () => {
196
+ const h = setup({ fileReview: false, destructiveMcpTools: ["drop_table"] });
197
+ expect(h.decide(hookShell("rm -rf build")).permission).toBe("deny");
198
+ expect(h.decide(hookMcp("drop_table", { table: "users" })).permission).toBe("deny");
199
+ expect(h.ledger().map((e) => e.kind)).toEqual(["approval", "approval"]);
200
+ });
201
+
202
+ it("a tracked .env.example in a git workspace flows: the secret rule is keyed on the substrate", () => {
203
+ const h = setup({ fileReview: false, gitignored: [] });
204
+ expect(h.decide(hookWrite(join(h.root, "config/.env.example"), "KEY=")).permission).toBe("allow");
205
+ expect(h.ledger()).toEqual([]);
206
+ });
207
+
208
+ it("a gitignored or non-git secret-like write is still refused, kind 'secret'", () => {
209
+ const ignored = setup({ fileReview: false, gitignored: [".env"] });
210
+ expect(ignored.decide(hookWrite(join(ignored.root, ".env"), "API_KEY=abc")).permission).toBe("deny");
211
+ expect(ignored.ledger().map((e) => e.kind)).toEqual(["secret"]);
212
+
213
+ const nonGit = setup({ fileReview: false, gitWorkspace: false });
214
+ expect(nonGit.decide(hookWrite(join(nonGit.root, ".env"), "API_KEY=abc")).permission).toBe("deny");
215
+ expect(nonGit.ledger().map((e) => e.kind)).toEqual(["secret"]);
216
+ });
217
+
218
+ it("review on with no substrate still asks before a write (the deny-gate)", () => {
219
+ const h = setup({ fileReview: true, captureMode: false, gitWorkspace: false });
220
+ expect(h.decide(hookWrite(join(h.root, "notes.md"))).permission).toBe("deny");
221
+ expect(h.ledger().map((e) => e.kind)).toEqual(["approval"]);
222
+ });
223
+ });
224
+
225
+ // MCP gating runs ONLY on the beforeMCPExecution event (preToolUse does not
226
+ // enforce MCP), so a denial is recorded in exactly one place. The identity is
227
+ // server and tool (base64("<server>/<tool>\n")): both are identical on the
228
+ // hook input and the runner's stream event, and a grant for one server's
229
+ // tool never covers an equal tool name on another.
230
+ describe("MCP tools (beforeMCPExecution event)", () => {
231
+ it("denies a destructive MCP tool and surfaces its approval message", () => {
232
+ const h = setup({ destructiveMcpTools: ["click"] });
233
+ const res = h.decide(hookMcp("click", { app: "Slack", element_index: "59" }));
234
+ expect(res.permission).toBe("deny");
235
+ expect(res.raw).toContain("Execute click");
236
+ expect(h.ledger()).toHaveLength(1);
237
+ expect(h.ledger()[0].token).toBe(grantToken("srv/click", ""));
238
+ expect(h.ledger()[0].kind).toBe("approval");
239
+ });
240
+
241
+ it("denial agent_message frames approval as automatic and never trains ask-in-prose", () => {
242
+ const h = setup({ destructiveMcpTools: ["click"] });
243
+ const res = h.decide(hookMcp("click"));
244
+ // The agent_message must tell the model approval is handled automatically
245
+ // and that it should continue, NOT stop and wait or ask for permission.
246
+ expect(res.raw).toContain("submitted to the user for approval automatically");
247
+ expect(res.raw).toContain("continue with the rest of the task");
248
+ // It must reframe the deny as the approval gate working as intended and
249
+ // forbid the "fix your Cursor settings" narration that the leaky MCP deny
250
+ // path otherwise provokes.
251
+ expect(res.raw.toLowerCase()).toContain("not an error");
252
+ expect(res.raw.toLowerCase()).toContain("cursor settings");
253
+ // The old propose-then-wait framing and internal sentinel must be gone.
254
+ expect(res.raw).not.toContain("STIGMER_APPROVAL_REQUIRED");
255
+ expect(res.raw).not.toContain("Stop and wait");
256
+ });
257
+
258
+ it("allows a require-approval MCP tool once it has been granted (reinvocation)", () => {
259
+ const h = setup({
260
+ destructiveMcpTools: ["click"],
261
+ grants: [{ toolName: "click", mcpServerSlug: "srv", key: "srv/click", salient: "", contentDigest: "", sourceToolCallId: "consent-1" }],
262
+ });
263
+ expect(h.decide(hookMcp("click")).permission).toBe("allow");
264
+ expect(h.ledger()).toEqual([]);
265
+ });
266
+
267
+ it("a grant for one server's tool does not let an equal tool name through on another server", () => {
268
+ const h = setup({
269
+ destructiveMcpTools: ["click"],
270
+ grants: [{ toolName: "click", mcpServerSlug: "other", key: "other/click", salient: "", contentDigest: "", sourceToolCallId: "consent-1" }],
271
+ });
272
+ expect(h.decide(hookMcp("click")).permission).toBe("deny");
273
+ expect(h.ledger()[0]!.token).toBe(grantToken("srv/click", ""));
274
+ });
275
+
276
+ it("keys an MCP grant on server and tool in the bash fallback too, when the Node binary is unavailable", () => {
277
+ const grant = (slug: string) => [{ toolName: "click", mcpServerSlug: slug, key: `${slug}/click`, salient: "", contentDigest: "", sourceToolCallId: "consent-1" }];
278
+ const withoutNode = (h: ReturnType<typeof setup>) => {
279
+ const scriptPath = join(h.hitlDir, "hook.sh");
280
+ writeFileSync(scriptPath, readFileSync(scriptPath, "utf-8").replace(`NODE_BIN="${process.execPath}"`, 'NODE_BIN="/nonexistent/node"'), "utf-8");
281
+ return h;
282
+ };
283
+ const granted = withoutNode(setup({ destructiveMcpTools: ["click"], grants: grant("srv") }));
284
+ expect(granted.decide(hookMcp("click")).permission).toBe("allow");
285
+ const elsewhere = withoutNode(setup({ destructiveMcpTools: ["click"], grants: grant("other") }));
286
+ expect(elsewhere.decide(hookMcp("click")).permission).toBe("deny");
287
+ expect(elsewhere.ledger()[0]!.token, "the token the stream row's identity recomputes").toBe(grantToken("srv/click", ""));
288
+ });
289
+
290
+ it("allows an MCP tool its server does not mark destructive", () => {
291
+ const h = setup({ destructiveMcpTools: ["click"] });
292
+ expect(h.decide(hookMcp("list_apps")).permission).toBe("allow");
293
+ expect(h.ledger()).toEqual([]);
294
+ });
295
+
296
+ it("asks before every tool of a server whose tools could not be listed this turn, on that server only", () => {
297
+ // The turn start's listing failed for "srv", so whether any of its
298
+ // tools changes anything is unknown: the approval default asks for
299
+ // every one of them (shared/approval-policy.ts `unlisted`), and the
300
+ // hook is the Cursor engine's only MCP gate.
301
+ const h = setup({ unlistedMcpServers: ["srv"] });
302
+ const res = h.decide(hookMcp("anything"));
303
+ expect(res.permission).toBe("deny");
304
+ expect(h.ledger().map((entry) => [entry.kind, entry.token])).toEqual([["approval", grantToken("srv/anything", "")]]);
305
+ expect(h.decide(hookMcp("anything", {}, "other")).permission, "another server's tool").toBe("allow");
306
+ });
307
+
308
+ it("a lease clears a server whose tools could not be listed", () => {
309
+ const h = setup({ unlistedMcpServers: ["srv"], leasedMcpServers: ["srv"] });
310
+ expect(h.decide(hookMcp("anything")).permission).toBe("allow");
311
+ });
312
+
313
+ it("auto-approve-all allows a require-approval MCP tool", () => {
314
+ const h = setup({ autoApproveAll: true, destructiveMcpTools: ["click"] });
315
+ expect(h.decide(hookMcp("click")).permission).toBe("allow");
316
+ });
317
+
318
+ it("fails closed (deny) when the state file is missing, recorded as kind fail-closed", () => {
319
+ const h = setup({ noStateFile: true });
320
+ expect(h.decide(hookMcp("click")).permission).toBe("deny");
321
+ // Attributable under the MCP name-token (the identity the stream row
322
+ // computes for an MCP call), content-free like every non-approval kind.
323
+ const ledger = h.ledger();
324
+ expect(ledger).toHaveLength(1);
325
+ expect(ledger[0].kind).toBe("fail-closed");
326
+ expect(ledger[0].token).toBe(grantToken("srv/click", ""));
327
+ expect(ledger[0]).not.toHaveProperty("input");
328
+ });
329
+
330
+ it("does NOT gate the same MCP tool delivered on preToolUse (no double-gating)", () => {
331
+ const h = setup({ destructiveMcpTools: ["click"] });
332
+ // preToolUse must fall through to allow for MCP — gating belongs to
333
+ // beforeMCPExecution alone, so the denial is never recorded twice.
334
+ expect(h.decide(hookMcpPreToolUse("click")).permission).toBe("allow");
335
+ expect(h.decide({ tool_name: "click", tool_input: "{}", hook_event_name: "preToolUse" }).permission).toBe("allow");
336
+ expect(h.ledger()).toEqual([]);
337
+ });
338
+
339
+ it("keys the destructive set by server: the same tool name on another server passes", () => {
340
+ const h = setup({ destructiveMcpTools: ["click"] });
341
+ expect(h.decide(hookMcp("click", {}, "other")).permission).toBe("allow");
342
+ expect(h.ledger()).toEqual([]);
343
+ });
344
+
345
+ it("a leased server's destructive tool passes", () => {
346
+ const h = setup({ destructiveMcpTools: ["click"], leasedMcpServers: ["srv"] });
347
+ expect(h.decide(hookMcp("click")).permission).toBe("allow");
348
+ expect(h.ledger()).toEqual([]);
349
+ });
350
+
351
+ it("scope guard: a foreign MCP invocation is allowed and never recorded", () => {
352
+ const h = setup({
353
+ destructiveMcpTools: ["click"],
354
+ runnerPid: 2_147_483_600,
355
+ });
356
+ expect(h.decide(hookMcp("click")).permission).toBe("allow");
357
+ expect(h.ledger()).toEqual([]);
358
+ });
359
+ });
360
+
361
+ // The agent's tool lists (scope arm 1a): compiled by the runner
362
+ // (hook-scope.ts) and only looked up here. A refusal is kind "disabled":
363
+ // non-pausing, permanent, and placed BEFORE the capture arms,
364
+ // autoApproveAll and every grant, because a list is not an approval gate.
365
+ describe("tool lists (scope arm)", () => {
366
+ const READ_ONLY = { tools: ["Read", "Grep", "mcp__srv"], disallowedTools: [] };
367
+
368
+ it("refuses a built-in outside an allow-list with the lists' message, recorded under the tool's scope token", () => {
369
+ const h = setup({ lists: READ_ONLY });
370
+ const res = h.decide(hookShell("ls"));
371
+ expect(res.permission).toBe("deny");
372
+ expect(res.raw).toContain("Shell is not available to this agent");
373
+ expect(res.raw).toContain('tools [Read, Grep, mcp__srv]');
374
+ expect(res.raw).not.toContain("submitted to the user for approval");
375
+ const ledger = h.ledger();
376
+ expect(ledger).toHaveLength(1);
377
+ expect(ledger[0].kind).toBe("disabled");
378
+ expect(ledger[0].token).toBe(scopeRefusalToken(scopeKey("shell", CURSOR_SDK_TOOL_COVERS)));
379
+ expect(ledger[0]).not.toHaveProperty("input");
380
+ // The refusal text rides the ledger (base64) for the boundary to stamp on the row.
381
+ expect(Buffer.from(String(ledger[0].message), "base64").toString("utf-8")).toBe(JSON.parse(res.raw).agent_message);
382
+ });
383
+
384
+ it("refuses a built-in a deny-list names and leaves the rest to the approval gate", () => {
385
+ const h = setup({ lists: { tools: [], disallowedTools: ["Bash(git push *)"] } });
386
+ expect(h.decide(hookShell("git status")).permission).toBe("deny");
387
+ expect(h.ledger()[0].kind).toBe("disabled");
388
+ h.resetLedger();
389
+ // Write is not denied by the list, so it reaches the ordinary approval gate.
390
+ expect(h.decide(hookWrite("/x/a.txt")).permission).toBe("deny");
391
+ expect(h.ledger()[0].kind).toBe("approval");
392
+ });
393
+
394
+ it("a hook tool covering a denied Claude tool is refused: never Write refuses Delete and the hook's Write, not StrReplace", () => {
395
+ const h = setup({ lists: { tools: [], disallowedTools: ["Write"] } });
396
+ expect(h.decide(hookDelete("/x/a.txt")).permission).toBe("deny");
397
+ expect(h.decide(hookWrite("/x/b.txt")).permission).toBe("deny");
398
+ // StrReplace covers Edit alone, so it reaches the ordinary approval gate.
399
+ expect(h.decide(hookEdit("/x/a.txt")).permission).toBe("deny");
400
+ expect(h.ledger().map((e) => e.kind)).toEqual(["disabled", "disabled", "approval"]);
401
+ });
402
+
403
+ it("an engine extra is refused only under an allow-list", () => {
404
+ const allow = setup({ lists: READ_ONLY });
405
+ expect(allow.decide(hookBuiltin("GenerateImage", { prompt: "a cat" })).permission).toBe("deny");
406
+ const deny = setup({ lists: { tools: [], disallowedTools: ["Bash"] } });
407
+ expect(deny.decide(hookBuiltin("GenerateImage", { prompt: "a cat" })).permission).toBe("allow");
408
+ });
409
+
410
+ it("binds under autoApproveAll, a category lease and a grant (no approval posture resurrects an excluded tool)", () => {
411
+ const h = setup({
412
+ lists: READ_ONLY,
413
+ autoApproveAll: true,
414
+ leasedCategories: ["shell"],
415
+ grants: [{ toolName: "shell", mcpServerSlug: "", key: "shell", salient: "ls", contentDigest: "", sourceToolCallId: "consent-1" }],
416
+ });
417
+ expect(h.decide(hookShell("ls")).permission).toBe("deny");
418
+ expect(h.ledger()[0].kind).toBe("disabled");
419
+ });
420
+
421
+ it("binds ahead of capture mode: an excluded write is refused, not staged", () => {
422
+ const h = setup({ lists: READ_ONLY, captureMode: true, gitignored: [] });
423
+ expect(h.decide(hookWrite(join(h.root, "a.txt"))).permission).toBe("deny");
424
+ expect(h.ledger()[0].kind).toBe("disabled");
425
+ });
426
+
427
+ it("stays kind disabled under unattended mode (mode-independent)", () => {
428
+ const h = setup({ lists: READ_ONLY, unattendedSkip: true });
429
+ expect(h.decide(hookShell("ls")).permission).toBe("deny");
430
+ expect(h.ledger()[0].kind).toBe("disabled");
431
+ });
432
+
433
+ it("Read excluded: a real platform file read through the turn's .stigmer link passes; anything else is refused", () => {
434
+ const h = setup({ lists: { tools: ["Grep"], disallowedTools: [] } });
435
+ mkdirSync(join(h.platformDir, "skills/a"), { recursive: true });
436
+ mkdirSync(join(h.platformDir, "inputs"), { recursive: true });
437
+ writeFileSync(join(h.platformDir, "skills/a/SKILL.md"), "# skill", "utf-8");
438
+ writeFileSync(join(h.platformDir, "inputs/spec.pdf"), "pdf", "utf-8");
439
+ mkdirSync(join(h.root, "src"), { recursive: true });
440
+ writeFileSync(join(h.root, "src/main.ts"), "code", "utf-8");
441
+ writeFileSync(join(h.root, "secrets.txt"), "secret", "utf-8");
442
+ // A link inside platform content pointing out of it, into the workspace.
443
+ symlinkSync(h.root, join(h.platformDir, "inputs/escape"), "dir");
444
+
445
+ expect(h.decide(hookBuiltin("Read", { file_path: join(h.root, ".stigmer/skills/a/SKILL.md") })).permission).toBe("allow");
446
+ expect(h.decide(hookBuiltin("Read", { file_path: ".stigmer/inputs/spec.pdf" }, h.root)).permission).toBe("allow");
447
+ expect(h.ledger(), "an admitted read records nothing").toEqual([]);
448
+
449
+ const refused = [
450
+ join(h.root, "src/main.ts"),
451
+ // ".." is resolved before the real path is taken.
452
+ join(h.root, ".stigmer/../secrets.txt"),
453
+ // Through the platform link, out through a link inside the content.
454
+ join(h.root, ".stigmer/inputs/escape/secrets.txt"),
455
+ // A file that does not exist has no real path to admit.
456
+ join(h.root, ".stigmer/inputs/missing.pdf"),
457
+ ];
458
+ for (const file of refused) expect(h.decide(hookBuiltin("Read", { file_path: file })).permission, file).toBe("deny");
459
+ expect(h.ledger().map((e) => e.kind)).toEqual(["disabled", "disabled", "disabled", "disabled"]);
460
+ // A Read refusal names the call: the path as given.
461
+ expect(h.ledger()[0].token).toBe(scopeRefusalToken(READ_SCOPE_KEY, join(h.root, "src/main.ts")));
462
+ });
463
+
464
+ it("Skill denied: a read of a skill's files is refused even with Read in scope; other platform content still reads", () => {
465
+ const h = setup({ lists: { tools: [], disallowedTools: ["Skill"] } });
466
+ mkdirSync(join(h.platformDir, "skills/a"), { recursive: true });
467
+ mkdirSync(join(h.platformDir, "plugins/abc/skills/b"), { recursive: true });
468
+ mkdirSync(join(h.platformDir, "inputs"), { recursive: true });
469
+ writeFileSync(join(h.platformDir, "skills/a/SKILL.md"), "# skill", "utf-8");
470
+ writeFileSync(join(h.platformDir, "plugins/abc/skills/b/SKILL.md"), "# plugin skill", "utf-8");
471
+ writeFileSync(join(h.platformDir, "inputs/spec.pdf"), "pdf", "utf-8");
472
+ writeFileSync(join(h.root, "notes.md"), "notes", "utf-8");
473
+
474
+ expect(h.decide(hookBuiltin("Read", { file_path: join(h.root, ".stigmer/skills/a/SKILL.md") })).permission).toBe("deny");
475
+ expect(h.decide(hookBuiltin("Read", { file_path: ".stigmer/plugins/abc/skills/b/SKILL.md" }, h.root)).permission).toBe("deny");
476
+ expect(h.decide(hookBuiltin("Read", { file_path: join(h.root, ".stigmer/inputs/spec.pdf") })).permission).toBe("allow");
477
+ expect(h.decide(hookBuiltin("Read", { file_path: join(h.root, "notes.md") })).permission).toBe("allow");
478
+ expect(h.decide(hookBuiltin("Read", { file_path: join(h.root, "missing.md") })).permission, "a missing file is the read's own error").toBe("allow");
479
+ expect(h.ledger().map((e) => e.kind)).toEqual(["disabled", "disabled"]);
480
+ expect(h.ledger()[0].token).toBe(scopeRefusalToken(READ_SCOPE_KEY, join(h.root, ".stigmer/skills/a/SKILL.md")));
481
+ });
482
+
483
+ it("Skill denied: a read anywhere in a mounted plugin's tree, or under a differently cased skills dir, is refused", () => {
484
+ const h = setup({ lists: { tools: [], disallowedTools: ["Skill"] } });
485
+ // A manifest-declared skill directory, and a directory whose name
486
+ // differs from skills/ only in case (as it may on any filesystem).
487
+ mkdirSync(join(h.platformDir, "plugins/abc/my-skills/solo"), { recursive: true });
488
+ mkdirSync(join(h.platformDir, "Skills/a"), { recursive: true });
489
+ writeFileSync(join(h.platformDir, "plugins/abc/my-skills/solo/SKILL.md"), "# declared", "utf-8");
490
+ writeFileSync(join(h.platformDir, "Skills/a/SKILL.md"), "# cased", "utf-8");
491
+
492
+ expect(h.decide(hookBuiltin("Read", { file_path: ".stigmer/plugins/abc/my-skills/solo/SKILL.md" }, h.root)).permission).toBe("deny");
493
+ expect(h.decide(hookBuiltin("Read", { file_path: join(h.root, ".stigmer/Skills/a/SKILL.md") })).permission).toBe("deny");
494
+ expect(h.ledger().map((e) => e.kind)).toEqual(["disabled", "disabled"]);
495
+ });
496
+
497
+ it("Skill denied: a case-folded spelling of skills/ that the filesystem opens is refused", (ctx) => {
498
+ const h = setup({ lists: { tools: [], disallowedTools: ["Skill"] } });
499
+ mkdirSync(join(h.platformDir, "skills/a"), { recursive: true });
500
+ writeFileSync(join(h.platformDir, "skills/a/SKILL.md"), "# skill", "utf-8");
501
+ // U+017F (long s) folds to "s" on a case-insensitive filesystem but
502
+ // not under toLowerCase: only the path on disk names skills/.
503
+ const variant = join(h.root, ".stigmer/\u017Fkills/a/SKILL.md");
504
+ if (!existsSync(variant)) ctx.skip();
505
+
506
+ expect(h.decide(hookBuiltin("Read", { file_path: variant })).permission).toBe("deny");
507
+ expect(h.ledger().map((e) => e.kind)).toEqual(["disabled"]);
508
+ });
509
+
510
+ it("Read excluded on an unlinked turn: a repository's own .stigmer symlink admits nothing", () => {
511
+ const h = setup({ lists: { tools: ["Grep"], disallowedTools: [] }, stigmerLink: "repo" });
512
+ writeFileSync(join(h.root, "repo-state/notes.md"), "repo file", "utf-8");
513
+ expect(h.decide(hookBuiltin("Read", { file_path: join(h.root, ".stigmer/notes.md") })).permission).toBe("deny");
514
+ expect(h.ledger().map((e) => e.kind)).toEqual(["disabled"]);
515
+ });
516
+
517
+ it("refuses an MCP tool by server AND tool, recorded under its server/tool scope token", () => {
518
+ const h = setup({
519
+ lists: { tools: ["mcp__srv__list_apps"], disallowedTools: [] },
520
+ mcpServers: [{ slug: "srv", listedTools: ["list_apps", "click"] }, { slug: "other", listedTools: ["list_apps"] }],
521
+ });
522
+ expect(h.decide(hookMcp("list_apps")).permission).toBe("allow");
523
+ const res = h.decide(hookMcp("click", { app: "Slack" }));
524
+ expect(res.permission).toBe("deny");
525
+ expect(res.raw).toContain("click is not available to this agent");
526
+ // The same tool name on another server is a different tool.
527
+ expect(h.decide(hookMcp("list_apps", {}, "other")).permission).toBe("deny");
528
+ const ledger = h.ledger();
529
+ expect(ledger.map((e) => e.kind)).toEqual(["disabled", "disabled"]);
530
+ expect(ledger[0].token).toBe(scopeRefusalToken(mcpToolKey("srv", "click")));
531
+ expect(ledger[1].token).toBe(scopeRefusalToken(mcpToolKey("other", "list_apps")));
532
+ });
533
+
534
+ it("answers an MCP tool of a server the turn start could not list by its server's family entry", () => {
535
+ const h = setup({
536
+ lists: { tools: ["mcp__srv"], disallowedTools: ["mcp__srv__drop_all"] },
537
+ mcpServers: [{ slug: "srv", listedTools: null }],
538
+ });
539
+ expect(h.decide(hookMcp("brand_new")).permission).toBe("allow");
540
+ expect(h.decide(hookMcp("drop_all")).permission).toBe("deny");
541
+ expect(h.decide(hookMcp("anything", {}, "unknown_server")).permission).toBe("deny");
542
+ });
543
+
544
+ it("keeps the platform's attachment servers in scope under any allow-list", () => {
545
+ const h = setup({ lists: READ_ONLY, platformServerSlugs: ["stigmer-memory"], mcpServers: [{ slug: "stigmer-memory", listedTools: null }] });
546
+ expect(h.decide(hookMcp("remember", {}, "stigmer-memory")).permission).toBe("allow");
547
+ });
548
+
549
+ it("an excluded MCP tool is refused under autoApproveAll and ahead of its grant", () => {
550
+ const h = setup({
551
+ lists: { tools: [], disallowedTools: ["mcp__srv__click"] },
552
+ autoApproveAll: true,
553
+ grants: [{ toolName: "click", mcpServerSlug: "srv", key: "click", salient: "", contentDigest: "", sourceToolCallId: "consent-1" }],
554
+ });
555
+ expect(h.decide(hookMcp("click")).permission).toBe("deny");
556
+ expect(h.ledger()[0].kind).toBe("disabled");
557
+ });
558
+
559
+ it("an in-scope destructive MCP tool still reaches the approval gate (lists and approvals compose)", () => {
560
+ const h = setup({ lists: { tools: ["mcp__srv"], disallowedTools: [] }, destructiveMcpTools: ["click"] });
561
+ const res = h.decide(hookMcp("click"));
562
+ expect(res.permission).toBe("deny");
563
+ expect(h.ledger()[0].kind).toBe("approval");
564
+ });
565
+
566
+ it("subagentStart: refuses a type outside Agent(type, …), Cursor's built-in types included, and allows a listed one", () => {
567
+ const h = setup({ lists: { tools: ["Read", "Agent(researcher, Explore)"], disallowedTools: [] }, subAgentTypes: ["researcher", "writer"] });
568
+ expect(h.decide(hookSubagentStart("researcher")).permission).toBe("allow");
569
+ expect(h.decide(hookSubagentStart("explore")).permission).toBe("allow");
570
+ const writer = h.decide(hookSubagentStart("writer"));
571
+ expect(writer.permission).toBe("deny");
572
+ expect(writer.raw).toContain("Agent(writer) is not available to this agent");
573
+ expect(h.decide(hookSubagentStart("generalPurpose")).permission).toBe("deny");
574
+ const ledger = h.ledger();
575
+ expect(ledger.map((e) => e.kind)).toEqual(["disabled", "disabled"]);
576
+ // A sub-agent start's refusal names the call: the normalized type.
577
+ expect(ledger[0].token).toBe(scopeRefusalToken(AGENT_SCOPE_KEY, "writer"));
578
+ });
579
+
580
+ it("subagentStart: Cursor's generalPurpose is the general-purpose type a list names", () => {
581
+ const gp = setup({ lists: { tools: ["Read", "Agent(general-purpose)"], disallowedTools: [] } });
582
+ expect(gp.decide(hookSubagentStart("generalPurpose")).permission).toBe("allow");
583
+ const explore = setup({ lists: { tools: ["Read", "Agent(explore)"], disallowedTools: [] } });
584
+ expect(explore.decide(hookSubagentStart("generalPurpose")).permission).toBe("deny");
585
+ expect(explore.decide(hookSubagentStart("Explore")).permission).toBe("allow");
586
+ expect(explore.ledger().map((e) => e.kind)).toEqual(["disabled"]);
587
+ });
588
+
589
+ it("preToolUse Task: a subagent_type outside Agent(type, …) is refused at the call, recorded with its type", () => {
590
+ const h = setup({ lists: { tools: ["Read", "Agent(explore)"], disallowedTools: [] } });
591
+ const res = h.decide(hookBuiltin("Task", { subagent_type: "generalPurpose", description: "Do", prompt: "Do it." }));
592
+ expect(res.permission).toBe("deny");
593
+ expect(res.raw).toContain("Agent(generalPurpose) is not available to this agent");
594
+ expect(h.decide(hookBuiltin("Task", { subagent_type: "Explore", prompt: "Look." })).permission).toBe("allow");
595
+ // A Task naming no type keeps the subagentStart path.
596
+ expect(h.decide(hookBuiltin("Task", { prompt: "Something." })).permission).toBe("allow");
597
+ const ledger = h.ledger();
598
+ expect(ledger.map((e) => e.kind)).toEqual(["disabled"]);
599
+ expect(ledger[0].token).toBe(scopeRefusalToken(AGENT_SCOPE_KEY, "generalpurpose"));
600
+ });
601
+
602
+ it("subagentStart: allowed with no lists, and refused when the lists exclude Agent", () => {
603
+ expect(setup({}).decide(hookSubagentStart("explore")).permission).toBe("allow");
604
+ const h = setup({ lists: { tools: [], disallowedTools: ["Agent"] } });
605
+ expect(h.decide(hookSubagentStart("explore")).permission).toBe("deny");
606
+ });
607
+
608
+ it("an agent with no lists is never refused by the scope arm", () => {
609
+ const h = setup({ autoApproveAll: true });
610
+ expect(h.decide(hookBuiltin("GenerateImage", {})).permission).toBe("allow");
611
+ expect(h.decide(hookMcp("anything", {}, "any")).permission).toBe("allow");
612
+ expect(h.ledger()).toEqual([]);
613
+ });
614
+
615
+ it("an MCP tool named like a state flag cannot switch the flag on (the scope rides the state opaque)", () => {
616
+ // A deny-list leaves these tools in scope, so the compiled table holds
617
+ // `"autoApproveAll":true` and `"captureMode":true` as answers. In scope,
618
+ // a write must still reach the approval gate and be held there.
619
+ const h = setup({
620
+ lists: { tools: [], disallowedTools: ["Bash"] },
621
+ mcpServers: [{ slug: "srv", listedTools: ["autoApproveAll", "captureMode", "unattendedSkip"] }],
622
+ });
623
+ expect(h.decide(hookWrite("/x/a.txt")).permission).toBe("deny");
624
+ expect(h.ledger().map((e) => e.kind)).toEqual(["approval"]);
625
+ });
626
+
627
+ it("scope guard: a foreign invocation is allowed and never recorded, lists or not", () => {
628
+ const h = setup({ lists: READ_ONLY, runnerPid: 2_147_483_600 });
629
+ expect(h.decide(hookShell("ls")).permission).toBe("allow");
630
+ expect(h.ledger()).toEqual([]);
631
+ });
632
+ });
633
+
634
+ // The hook captures the COMPLETE tool_input on every denial (base64(JSON)),
635
+ // so the runner can overlay the proposed change onto the gated tool call for
636
+ // the approval preview — the cursor analog of the native harness reading args
637
+ // from graph state at the interrupt. These pin the capture across taxonomies
638
+ // (built-in object tool_input vs. MCP JSON-string tool_input).
639
+ describe("captures tool_input on the denial ledger", () => {
640
+ it("records the full built-in write input (object tool_input)", () => {
641
+ const h = setup({});
642
+ expect(h.decide(hookWrite("/x/a.txt", "export const x = 1;\n")).permission).toBe("deny");
643
+ const ledger = h.ledger();
644
+ expect(ledger).toHaveLength(1);
645
+ expect(decodeInput(ledger[0].input)).toEqual({
646
+ file_path: "/x/a.txt",
647
+ content: "export const x = 1;\n",
648
+ });
649
+ });
650
+
651
+ it("records an edit's old/new replacement strings", () => {
652
+ const h = setup({});
653
+ expect(h.decide(hookEdit("/x/a.txt", "alpha", "beta")).permission).toBe("deny");
654
+ expect(decodeInput(h.ledger()[0].input)).toEqual({
655
+ file_path: "/x/a.txt",
656
+ old_string: "alpha",
657
+ new_string: "beta",
658
+ });
659
+ });
660
+
661
+ it("parses and records the MCP JSON-STRING tool_input", () => {
662
+ // Cursor delivers MCP tool_input as a JSON string, not an object — the
663
+ // extractor must parse it so the captured input is the same object shape.
664
+ const h = setup({ destructiveMcpTools: ["click"] });
665
+ expect(h.decide(hookMcp("click", { app: "Slack", element_index: "59" })).permission).toBe("deny");
666
+ expect(decodeInput(h.ledger()[0].input)).toEqual({ app: "Slack", element_index: "59" });
667
+ });
668
+
669
+ it("captures large multi-line content intact (printf, not echo/argv)", () => {
670
+ const content = "line\n".repeat(20_000); // ~100 KB, exercises the printf write
671
+ const h = setup({});
672
+ expect(h.decide(hookWrite("/x/big.ts", content)).permission).toBe("deny");
673
+ expect(decodeInput(h.ledger()[0].input).content).toBe(content);
674
+ });
675
+ });
676
+
677
+ // Regression: the original grep-based extraction truncated string values at
678
+ // the first JSON-escaped character, so a shell command containing double
679
+ // quotes (e.g. `printf '%s' 'x' > "file"`) produced a ledger token that never
680
+ // matched the runner's grantToken — the denied call stayed COMPLETED in the
681
+ // persisted messages and a grant for it was re-denied on reinvocation.
682
+ // (Observed live in TestCursorHarness_HITL_ResumedTurn_StillGated.)
683
+ it("records a byte-identical token for commands with quotes, escapes, and newlines", () => {
684
+ const commands = [
685
+ 'printf \'%s\' \'hello\' > "/tmp/a dir/resumed-gate.txt"',
686
+ 'echo "double \\"nested\\" quotes" && echo done',
687
+ "line1\nline2\twith\ttabs",
688
+ 'unicode: caf\u00e9 \u2014 emoji \u{1F600}',
689
+ ];
690
+ for (const command of commands) {
691
+ const h = setup({});
692
+ expect(h.decide(hookShell(command)).permission).toBe("deny");
693
+ const ledger = h.ledger();
694
+ expect(ledger).toHaveLength(1);
695
+ expect(ledger[0].token).toBe(grantToken("shell", command));
696
+ }
697
+ });
698
+
699
+ it("allows the exact granted shell command even when it contains quotes", () => {
700
+ const command = 'printf \'%s\' \'hello-resume\' > "/x/resumed-gate.txt"';
701
+ const id = toolIdentity("shell", "", { command });
702
+ const h = setup({ grants: [{ toolName: "shell", mcpServerSlug: "", key: id.key, salient: id.salient, contentDigest: "", sourceToolCallId: "consent-1" }] });
703
+
704
+ expect(h.decide(hookShell(command)).permission).toBe("allow");
705
+ // A different command is NOT covered by the grant -> still gated.
706
+ expect(h.decide(hookShell('rm -rf "/x"')).permission).toBe("deny");
707
+ });
708
+
709
+ // The full runner<->hook closure, per gated category and for the bytes most
710
+ // likely to drift: the token the RUNNER writes into approval-state.json (via
711
+ // buildApprovalState, exactly as index.ts does on resume) is byte-identical to
712
+ // the token the HOOK records when it denies the same action, and the hook's
713
+ // grep -qF membership check then ALLOWS the re-issued call. This is the precise
714
+ // production safety property — "approve once, allowed on the resumed turn" —
715
+ // closed end to end rather than asserted on either half alone.
716
+ describe("runner grant <-> hook allow closure (tricky args, every gated category)", () => {
717
+ const cases: Array<{
718
+ label: string;
719
+ streamName: string;
720
+ streamArgs: Record<string, unknown>;
721
+ hookInput: object;
722
+ otherHookInput: object;
723
+ }> = [
724
+ {
725
+ label: "write — path with spaces, quotes, and unicode",
726
+ streamName: "edit",
727
+ // Content matches hookWrite's default ("x") so the runner-side grant
728
+ // digest equals the hook-side content digest (content-exact closure).
729
+ streamArgs: { path: '/work/a dir/"café" notes.md', content: "x" },
730
+ hookInput: hookWrite('/work/a dir/"café" notes.md'),
731
+ otherHookInput: hookWrite("/work/other.md"),
732
+ },
733
+ {
734
+ label: "shell — multi-line heredoc with quotes and unicode",
735
+ streamName: "shell",
736
+ streamArgs: { command: "cat > notes.md << 'EOF'\n# Notes — \"x\" café\nEOF" },
737
+ hookInput: hookShell("cat > notes.md << 'EOF'\n# Notes — \"x\" café\nEOF"),
738
+ otherHookInput: hookShell("rm -rf build"),
739
+ },
740
+ {
741
+ label: "delete — path with quotes",
742
+ streamName: "delete",
743
+ streamArgs: { path: '/work/"old" file.tmp' },
744
+ hookInput: hookDelete('/work/"old" file.tmp'),
745
+ otherHookInput: hookDelete("/work/keep.tmp"),
746
+ },
747
+ ];
748
+
749
+ for (const { label, streamName, streamArgs, hookInput, otherHookInput } of cases) {
750
+ it(`${label}: the state-file token the runner writes is the token the hook denies and then allows`, () => {
751
+ // 1. The hook denies the un-granted call and records its identity token.
752
+ const denyHarness = setup({});
753
+ expect(denyHarness.decide(hookInput).permission).toBe("deny");
754
+ const denialLedger = denyHarness.ledger();
755
+ expect(denialLedger).toHaveLength(1);
756
+ const hookDenialToken = denialLedger[0].token;
757
+
758
+ // 2. The runner mints the grant from the STREAM-side identity (the only
759
+ // side it sees) and writes it into the real state file via
760
+ // buildApprovalState — the exact path index.ts takes on resume.
761
+ const id = toolIdentity(streamName, "", streamArgs);
762
+ const state = buildApprovalState(NO_MCP_DEFAULT, false, new Set(), [
763
+ { toolName: streamName, mcpServerSlug: "", key: id.key, salient: id.salient, contentDigest: contentDigest(streamArgs), sourceToolCallId: "consent-1" },
764
+ ]);
765
+
766
+ // 3. The state file carries the byte-exact token the hook recomputed —
767
+ // the grep -qF membership the bash hook performs (string equality).
768
+ expect(state.approvedGrantTokens).toContain(hookDenialToken);
769
+
770
+ // 4. With that state file, the hook ALLOWS the re-issued (fresh-id) call
771
+ // and re-gates a DIFFERENT resource of the same category.
772
+ const grantHarness = setup({ grants: state.approvedGrants });
773
+ expect(grantHarness.decide(hookInput).permission).toBe("allow");
774
+ expect(grantHarness.decide(otherHookInput).permission).toBe("deny");
775
+ });
776
+ }
777
+ });
778
+
779
+ it("sibling isolation: approving one edit does NOT allow a DIFFERENT edit to the same file", () => {
780
+ // The exact reported bug, closed end-to-end through the real hook: approving
781
+ // the rename must re-gate the later `## TODO` edit to the SAME file.
782
+ const path = "/work/notes.md";
783
+ const renameArgs = { path, content: "Planton" };
784
+ const id = toolIdentity("edit", "", renameArgs);
785
+ const state = buildApprovalState(NO_MCP_DEFAULT, false, new Set(), [
786
+ { toolName: "edit", mcpServerSlug: "", key: id.key, salient: id.salient, contentDigest: contentDigest(renameArgs), sourceToolCallId: "consent-1" },
787
+ ]);
788
+ const h = setup({ grants: state.approvedGrants });
789
+
790
+ // The approved edit, re-issued with the SAME content, is allowed.
791
+ expect(h.decide(hookWrite(path, "Planton")).permission).toBe("allow");
792
+ // A DIFFERENT edit to the SAME file is re-gated — the sibling hole is closed.
793
+ expect(h.decide(hookWrite(path, "## TODO")).permission).toBe("deny");
794
+ });
795
+
796
+ // Issue #173: the hook ships on the workspace's shared .cursor/hooks.json, so
797
+ // the user's own Cursor IDE (a DIFFERENT process tree) would load and run it
798
+ // too. The scope guard must allow any invocation that does not descend from
799
+ // the runner process — without gating it and without writing the denial ledger
800
+ // (a foreign denial would surface as a phantom approval card in the session).
801
+ describe("scope guard (issue #173): foreign invocations are not gated", () => {
802
+ // A PID that cannot be an ancestor of the test's bash child. macOS pid_max is
803
+ // 99998; this is comfortably above it and above a freshly-booted Linux
804
+ // pid range, so get_ppid yields nothing and the walk reports "not own".
805
+ const FOREIGN_PID = 2_147_483_600;
806
+
807
+ it("allows a gated built-in when the invocation is not the runner's own agent", () => {
808
+ const h = setup({ runnerPid: FOREIGN_PID });
809
+ // The IDE would have this DENIED if the gate applied — it must be allowed.
810
+ expect(h.decide(hookWrite("/x/a.txt")).permission).toBe("allow");
811
+ expect(h.decide(hookShell("rm -rf build")).permission).toBe("allow");
812
+ });
813
+
814
+ it("never writes the denial ledger for a foreign invocation (no phantom approvals)", () => {
815
+ const h = setup({ runnerPid: FOREIGN_PID });
816
+ h.resetLedger();
817
+ h.decide(hookWrite("/x/a.txt"));
818
+ h.decide(hookShell("gh issue view 173"));
819
+ // The IDE's tool calls must NOT leak into the ledger the runner reads back.
820
+ expect(h.ledger()).toEqual([]);
821
+ });
822
+
823
+ it("allows a foreign invocation even when the state file is missing", () => {
824
+ // Fail-closed is for the runner's OWN agent; a foreign client must never be
825
+ // blocked by a missing state file (that was the multi-root exit-127 lockup).
826
+ const h = setup({ runnerPid: FOREIGN_PID, noStateFile: true });
827
+ expect(h.decide(hookWrite("/x/a.txt")).permission).toBe("allow");
828
+ expect(h.ledger()).toEqual([]);
829
+ });
830
+
831
+ it("still gates the runner's own agent (control: gate applies in-process)", () => {
832
+ // Same inputs, but runnerPid defaults to this process (an ancestor of the
833
+ // bash child) — the gate must apply, proving the guard discriminates.
834
+ const h = setup({});
835
+ expect(h.decide(hookWrite("/x/a.txt")).permission).toBe("deny");
836
+ expect(h.ledger()).toHaveLength(1);
837
+ });
838
+ });
839
+
840
+ // Capture mode (git workspaces): file mutations flow during the turn (the
841
+ // runner captures the whole change set with git and gates it per-file at the
842
+ // turn boundary), while shell/MCP and gitignored writes stay on the deny-gate.
843
+ describe("capture mode (git workspaces)", () => {
844
+ it("allows write/edit/delete to flow and records no denial", () => {
845
+ const h = setup({ captureMode: true });
846
+ expect(h.decide(hookWrite("normal.txt")).permission).toBe("allow");
847
+ expect(h.decide(hookEdit("normal.txt")).permission).toBe("allow");
848
+ expect(h.decide(hookDelete("normal.txt")).permission).toBe("allow");
849
+ expect(h.ledger()).toEqual([]);
850
+ });
851
+
852
+ it("still gates shell (it is not git-reversible)", () => {
853
+ const h = setup({ captureMode: true });
854
+ expect(h.decide(hookShell("rm -rf build")).permission).toBe("deny");
855
+ expect(h.ledger().map((e) => e.toolName)).toContain("Shell");
856
+ });
857
+
858
+ it("still gates require-approval MCP tools", () => {
859
+ const h = setup({ captureMode: true, destructiveMcpTools: ["click"] });
860
+ expect(h.decide(hookMcp("click")).permission).toBe("deny");
861
+ });
862
+
863
+ it("keeps gating a write to a GITIGNORED path (the snapshot cannot revert it)", () => {
864
+ // A NON-secret gitignored path is invisible to the git snapshot, so capture
865
+ // mode must still gate it for explicit approval. (A secret-like gitignored
866
+ // write is hard-blocked instead — see the deny-gate secret cases below.)
867
+ const h = setup({ captureMode: true, gitignored: ["ignored.txt"] });
868
+ expect(h.decide(hookWrite("ignored.txt")).permission).toBe("deny");
869
+ expect(h.ledger().map((e) => e.toolName)).toContain("Write");
870
+ // A non-ignored sibling still flows.
871
+ expect(h.decide(hookWrite("normal.txt")).permission).toBe("allow");
872
+ });
873
+
874
+ it("keeps gating a DELETE of a gitignored path", () => {
875
+ const h = setup({ captureMode: true, gitignored: ["secret.txt"] });
876
+ expect(h.decide(hookDelete("secret.txt")).permission).toBe("deny");
877
+ });
878
+ });
879
+
880
+ // Deny-gate secret hard-block: with no capture substrate for a write
881
+ // (capture off — the classic deny-gate — or captureIgnored off in a git-no-
882
+ // storage workspace) a secret-like WRITE must NOT surface its content for
883
+ // approval. The hook hard-blocks it with the security message and records a
884
+ // kind:"secret" ledger entry — ATTRIBUTABLE (issue #205: the runner must know
885
+ // this block was ours) but non-pausing (approvalDenials filters it out, so it
886
+ // never becomes an approvable WAITING row) and content-free (only the
887
+ // identity token, never the proposed bytes). A non-secret write still
888
+ // deny-gates as kind:"approval", and a delete (content-less) stays gated.
889
+ describe("deny-gate secret hard-block", () => {
890
+ it("hard-blocks a secret-like write; records an attributable, content-free secret entry", () => {
891
+ const h = setup({}); // captureMode off — the classic deny-gate
892
+ const dec = h.decide(hookWrite(".env", "API_KEY=abc"));
893
+ expect(dec.permission).toBe("deny");
894
+ expect(dec.raw).toContain("blocked for security");
895
+ // SECRET_BLOCKED, not APPROVAL_REQUIRED: the model is told to move on.
896
+ expect(dec.raw.toLowerCase()).toContain("nothing was written");
897
+ expect(dec.raw).not.toContain("submitted to the user for approval");
898
+ const ledger = h.ledger();
899
+ expect(ledger).toHaveLength(1);
900
+ expect(ledger[0].kind).toBe("secret");
901
+ // Content-free on the raw ledger bytes: no input field, no trace of the content.
902
+ expect(ledger[0]).not.toHaveProperty("input");
903
+ expect(JSON.stringify(ledger[0])).not.toContain("API_KEY");
904
+ });
905
+
906
+ it("hard-blocks a secret-like edit (path-fragment match)", () => {
907
+ const h = setup({});
908
+ const dec = h.decide(hookEdit(".ssh/id_rsa"));
909
+ expect(dec.permission).toBe("deny");
910
+ expect(dec.raw).toContain("blocked for security");
911
+ expect(h.ledger().map((e) => e.kind)).toEqual(["secret"]);
912
+ });
913
+
914
+ it("still deny-gates a NON-secret write and records its content for approval", () => {
915
+ const h = setup({});
916
+ const dec = h.decide(hookWrite("notes.md", "hello"));
917
+ expect(dec.permission).toBe("deny");
918
+ expect(dec.raw).toContain("submitted to the user for approval"); // APPROVAL_REQUIRED
919
+ expect(h.ledger().map((e) => e.toolName)).toContain("Write");
920
+ expect(h.ledger().map((e) => e.kind)).toEqual(["approval"]);
921
+ });
922
+
923
+ it("a write-category lease does NOT bypass the secret block", () => {
924
+ const h = setup({ leasedCategories: ["write"] });
925
+ expect(h.decide(hookWrite("notes.md", "x")).permission).toBe("allow"); // non-secret rides the lease
926
+ const dec = h.decide(hookWrite(".env", "SECRET")); // secret is still hard-blocked
927
+ expect(dec.permission).toBe("deny");
928
+ expect(dec.raw).toContain("blocked for security");
929
+ expect(h.ledger().map((e) => e.kind)).toEqual(["secret"]);
930
+ expect(JSON.stringify(h.ledger())).not.toContain("SECRET");
931
+ });
932
+
933
+ it("hard-blocks a secret write in a git workspace with captureIgnored off (no storage)", () => {
934
+ const h = setup({ captureMode: true, captureIgnored: false, gitignored: [".env"] });
935
+ const dec = h.decide(hookWrite(".env", "API_KEY=abc"));
936
+ expect(dec.permission).toBe("deny");
937
+ expect(dec.raw).toContain("blocked for security");
938
+ expect(h.ledger().map((e) => e.kind)).toEqual(["secret"]);
939
+ });
940
+
941
+ it("does NOT hard-block a secret DELETE (no content; stays deny-gated)", () => {
942
+ const h = setup({});
943
+ expect(h.decide(hookDelete(".env")).permission).toBe("deny");
944
+ expect(h.ledger().map((e) => e.toolName)).toContain("Delete");
945
+ });
946
+ });
947
+
948
+ // CAS parity: with captureIgnored on, a non-secret gitignored write no
949
+ // longer stays on the deny-gate — the hook stages its pre-turn bytes into the
950
+ // cas-observations sidecar and ALLOWS it (apply-then-review), while a secret-
951
+ // like gitignored write is hard-blocked and recorded as unreviewable. The
952
+ // sidecar is read back through the real reader.
953
+ describe("capture mode + captureIgnored (gitignored CAS capture)", () => {
954
+ it("stages a non-secret gitignored ADD and allows it (before=null)", async () => {
955
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: ["*.log"] });
956
+ expect(h.decide(hookWrite("app.log", "hello")).permission).toBe("allow");
957
+ // Flowed, not denied — it must not become a WAITING_APPROVAL row.
958
+ expect(h.ledger()).toEqual([]);
959
+ const obs = await h.observations();
960
+ expect(obs.secretPaths).toEqual([]);
961
+ expect(obs.captured).toHaveLength(1);
962
+ expect(obs.captured[0].path).toBe("app.log");
963
+ expect(obs.captured[0].before).toBeNull();
964
+ });
965
+
966
+ it("stages a non-secret gitignored MODIFY with the true pre-turn before-bytes", async () => {
967
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: ["*.log"] });
968
+ writeFileSync(join(h.root, "app.log"), "ORIGINAL", "utf-8");
969
+ expect(h.decide(hookWrite("app.log", "NEW")).permission).toBe("allow");
970
+ const obs = await h.observations();
971
+ expect(obs.captured).toHaveLength(1);
972
+ expect(obs.captured[0].before).not.toBeNull();
973
+ expect(Buffer.from(obs.captured[0].before!).toString("utf8")).toBe("ORIGINAL");
974
+ });
975
+
976
+ it("first-touch-wins: two edits to one gitignored path keep the original before", async () => {
977
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: ["*.log"] });
978
+ writeFileSync(join(h.root, "app.log"), "ORIGINAL", "utf-8");
979
+ expect(h.decide(hookWrite("app.log", "FIRST")).permission).toBe("allow");
980
+ // Simulate the first write having applied, then a second edit this turn.
981
+ writeFileSync(join(h.root, "app.log"), "FIRST", "utf-8");
982
+ expect(h.decide(hookEdit("app.log")).permission).toBe("allow");
983
+ const obs = await h.observations();
984
+ expect(obs.captured).toHaveLength(1);
985
+ expect(Buffer.from(obs.captured[0].before!).toString("utf8")).toBe("ORIGINAL");
986
+ });
987
+
988
+ it("hard-blocks a secret-like gitignored write; records a non-pausing secret entry", async () => {
989
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: [".env"] });
990
+ const d = h.decide(hookWrite(".env", "API_KEY=abc"));
991
+ expect(d.permission).toBe("deny");
992
+ expect(d.raw).toContain("blocked for security");
993
+ // A secret is NOT approvable: its kind:"secret" entry attributes the block
994
+ // to our own gate (issue #205) but is filtered out of the pause path — it
995
+ // surfaces as DIFF_UNREVIEWABLE instead, and carries no content.
996
+ const ledger = h.ledger();
997
+ expect(ledger.map((e) => e.kind)).toEqual(["secret"]);
998
+ expect(ledger[0]).not.toHaveProperty("input");
999
+ expect(JSON.stringify(ledger[0])).not.toContain("API_KEY");
1000
+ const obs = await h.observations();
1001
+ expect(obs.captured).toEqual([]);
1002
+ expect(obs.secretPaths).toEqual([".env"]);
1003
+ });
1004
+
1005
+ it("a CAS staging error fails closed and records a content-free capture-error entry", async () => {
1006
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: ["*.log"] });
1007
+ // Force the staging script's "error" result: the sidecar dir path is
1008
+ // occupied by a regular FILE, so mkdir fails and the blob write throws.
1009
+ // (The harness keeps state/ledger/sidecar in .cursor/hooks — its hitlDir
1010
+ // analog; see setupCursorHookHarness.)
1011
+ writeFileSync(join(h.root, ".cursor", "hooks", "cas-observations"), "not a dir", "utf-8");
1012
+ const d = h.decide(hookWrite("app.log", "payload"));
1013
+ expect(d.permission).toBe("deny");
1014
+ // Denied with the approval message (fail-closed, today's deny-gate text)
1015
+ // but recorded as kind "capture-error": attributable, NON-pausing (there
1016
+ // is no approval that could make the write reviewable), and content-free
1017
+ // (the staging error means secret classification may never have run).
1018
+ expect(d.raw).toContain("submitted to the user for approval");
1019
+ const ledger = h.ledger();
1020
+ expect(ledger.map((e) => e.kind)).toEqual(["capture-error"]);
1021
+ expect(ledger[0]).not.toHaveProperty("input");
1022
+ expect(JSON.stringify(ledger[0])).not.toContain("payload");
1023
+ });
1024
+
1025
+ it("captures under auto_approve_all too (capture is a turn property, not authorization)", async () => {
1026
+ const h = setup({
1027
+ captureMode: true,
1028
+ captureIgnored: true,
1029
+ autoApproveAll: true,
1030
+ gitignored: ["*.log", ".env"],
1031
+ });
1032
+ // Non-secret gitignored write is staged + allowed even under the bypass...
1033
+ expect(h.decide(hookWrite("app.log", "x")).permission).toBe("allow");
1034
+ // ...and a secret-like one is STILL hard-blocked under the bypass.
1035
+ expect(h.decide(hookWrite(".env", "SECRET")).permission).toBe("deny");
1036
+ const obs = await h.observations();
1037
+ expect(obs.captured.map((c) => c.path)).toEqual(["app.log"]);
1038
+ expect(obs.secretPaths).toEqual([".env"]);
1039
+ });
1040
+
1041
+ it("does not stage a git-tracked write (git captures it) — flows, no observation", async () => {
1042
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: ["*.log"] });
1043
+ expect(h.decide(hookWrite("tracked.ts", "x")).permission).toBe("allow");
1044
+ const obs = await h.observations();
1045
+ expect(obs.captured).toEqual([]);
1046
+ expect(obs.secretPaths).toEqual([]);
1047
+ });
1048
+
1049
+ it("stages a non-secret gitignored DELETE and allows it (issue #303)", async () => {
1050
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: ["*.log"] });
1051
+ writeFileSync(join(h.root, "app.log"), "DOOMED", "utf-8");
1052
+ expect(h.decide(hookDelete("app.log")).permission).toBe("allow");
1053
+ // Flowed, not denied — reviewed post-hoc as a DELETE entry, not a pause.
1054
+ expect(h.ledger()).toEqual([]);
1055
+ const obs = await h.observations();
1056
+ expect(obs.secretPaths).toEqual([]);
1057
+ expect(obs.captured).toHaveLength(1);
1058
+ expect(obs.captured[0].path).toBe("app.log");
1059
+ // The pre-delete bytes are staged — the restorable "before" side.
1060
+ expect(Buffer.from(obs.captured[0].before!).toString("utf8")).toBe("DOOMED");
1061
+ });
1062
+
1063
+ it("first-touch-wins across write-then-delete: the true pre-turn before survives", async () => {
1064
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: ["*.log"] });
1065
+ writeFileSync(join(h.root, "app.log"), "ORIGINAL", "utf-8");
1066
+ expect(h.decide(hookWrite("app.log", "REWRITTEN")).permission).toBe("allow");
1067
+ // Simulate the write having applied, then a delete later this turn.
1068
+ writeFileSync(join(h.root, "app.log"), "REWRITTEN", "utf-8");
1069
+ expect(h.decide(hookDelete("app.log")).permission).toBe("allow");
1070
+ const obs = await h.observations();
1071
+ expect(obs.captured).toHaveLength(1);
1072
+ expect(Buffer.from(obs.captured[0].before!).toString("utf8")).toBe("ORIGINAL");
1073
+ });
1074
+
1075
+ it("keeps a SECRET-LIKE gitignored delete on the deny-gate: approvable, never staged (issue #303)", async () => {
1076
+ // Unlike a secret write (hard-blocked — its content must never surface), a
1077
+ // delete's args expose no secret content, so a human may approve it. Its
1078
+ // before-bytes must never enter the sidecar though: staging would both
1079
+ // persist the secret bytes and mark the path "secret", making the boundary
1080
+ // author a blocking DIFF_UNREVIEWABLE for a merely-gated delete.
1081
+ const h = setup({ captureMode: true, captureIgnored: true, gitignored: [".env"] });
1082
+ writeFileSync(join(h.root, ".env"), "API_KEY=abc", "utf-8");
1083
+ const d = h.decide(hookDelete(".env"));
1084
+ expect(d.permission).toBe("deny");
1085
+ expect(d.raw).toContain("submitted to the user for approval"); // gated, not blocked
1086
+ expect(h.ledger().map((e) => e.kind)).toEqual(["approval"]);
1087
+ const obs = await h.observations();
1088
+ expect(obs.captured).toEqual([]);
1089
+ expect(obs.secretPaths).toEqual([]); // no secret marker for a gated delete
1090
+ });
1091
+
1092
+ it("with captureIgnored OFF, a gitignored write stays denied and stages nothing", async () => {
1093
+ const h = setup({ captureMode: true, captureIgnored: false, gitignored: ["*.log"] });
1094
+ expect(h.decide(hookWrite("app.log", "x")).permission).toBe("deny");
1095
+ const obs = await h.observations();
1096
+ expect(obs.captured).toEqual([]);
1097
+ });
1098
+ });
1099
+
1100
+ // A NON-git workspace has no git snapshot, so EVERY file write and
1101
+ // (issue #303) every non-secret delete is CAS-staged and flowed for review —
1102
+ // not only gitignored ones — while shell/MCP gate as always. The workspace is
1103
+ // deliberately NOT git-initialized.
1104
+ describe("non-git workspace CAS capture", () => {
1105
+ it("stages EVERY write (not just gitignored) and allows it, no denial", async () => {
1106
+ const h = setup({ captureMode: true, captureIgnored: true, gitWorkspace: false });
1107
+ writeFileSync(join(h.root, "notes.md"), "ORIGINAL", "utf-8");
1108
+ expect(h.decide(hookWrite("notes.md", "NEW")).permission).toBe("allow");
1109
+ expect(h.ledger()).toEqual([]);
1110
+ const obs = await h.observations();
1111
+ expect(obs.secretPaths).toEqual([]);
1112
+ expect(obs.captured).toHaveLength(1);
1113
+ expect(obs.captured[0].path).toBe("notes.md");
1114
+ expect(Buffer.from(obs.captured[0].before!).toString("utf8")).toBe("ORIGINAL");
1115
+ });
1116
+
1117
+ it("stages an ADD (before=null) and allows it", async () => {
1118
+ const h = setup({ captureMode: true, captureIgnored: true, gitWorkspace: false });
1119
+ expect(h.decide(hookWrite("created.ts", "x")).permission).toBe("allow");
1120
+ const obs = await h.observations();
1121
+ expect(obs.captured).toHaveLength(1);
1122
+ expect(obs.captured[0].before).toBeNull();
1123
+ });
1124
+
1125
+ it("hard-blocks a secret-like write; records a non-pausing, content-free secret entry", async () => {
1126
+ const h = setup({ captureMode: true, captureIgnored: true, gitWorkspace: false });
1127
+ const dcn = h.decide(hookWrite(".env", "API_KEY=abc"));
1128
+ expect(dcn.permission).toBe("deny");
1129
+ expect(dcn.raw).toContain("blocked for security");
1130
+ const ledger = h.ledger();
1131
+ expect(ledger.map((e) => e.kind)).toEqual(["secret"]);
1132
+ expect(JSON.stringify(ledger[0])).not.toContain("API_KEY");
1133
+ const obs = await h.observations();
1134
+ expect(obs.captured).toEqual([]);
1135
+ expect(obs.secretPaths).toEqual([".env"]);
1136
+ });
1137
+
1138
+ it("stages a DELETE with its pre-delete bytes and allows it (issue #303)", async () => {
1139
+ const h = setup({ captureMode: true, captureIgnored: true, gitWorkspace: false });
1140
+ writeFileSync(join(h.root, "notes.md"), "KEEP ME", "utf-8");
1141
+ expect(h.decide(hookDelete("notes.md")).permission).toBe("allow");
1142
+ expect(h.ledger()).toEqual([]);
1143
+ const obs = await h.observations();
1144
+ expect(obs.captured).toHaveLength(1);
1145
+ expect(obs.captured[0].path).toBe("notes.md");
1146
+ expect(Buffer.from(obs.captured[0].before!).toString("utf8")).toBe("KEEP ME");
1147
+ });
1148
+
1149
+ it("keeps a secret-like DELETE gated (approvable) and stages nothing", async () => {
1150
+ const h = setup({ captureMode: true, captureIgnored: true, gitWorkspace: false });
1151
+ writeFileSync(join(h.root, ".env"), "API_KEY=abc", "utf-8");
1152
+ const d = h.decide(hookDelete(".env"));
1153
+ expect(d.permission).toBe("deny");
1154
+ expect(d.raw).toContain("submitted to the user for approval");
1155
+ expect(h.ledger().map((e) => e.kind)).toEqual(["approval"]);
1156
+ const obs = await h.observations();
1157
+ expect(obs.captured).toEqual([]);
1158
+ expect(obs.secretPaths).toEqual([]);
1159
+ });
1160
+
1161
+ it("still gates shell (never git-reversible, never CAS-captured)", async () => {
1162
+ const h = setup({ captureMode: true, captureIgnored: true, gitWorkspace: false });
1163
+ expect(h.decide(hookShell("rm -rf /")).permission).toBe("deny");
1164
+ });
1165
+
1166
+ it("still gates a require-approval MCP tool", async () => {
1167
+ const h = setup({
1168
+ captureMode: true,
1169
+ captureIgnored: true,
1170
+ gitWorkspace: false,
1171
+ destructiveMcpTools: ["click"],
1172
+ });
1173
+ expect(h.decide(hookMcp("click")).permission).toBe("deny");
1174
+ });
1175
+ });
1176
+
1177
+ it("still denies gated tools via the bash fallback when the Node binary is unavailable", () => {
1178
+ const ws = mkdtempSync(join(tmpdir(), "hook-script-fallback-"));
1179
+ onTestFinished(() => rmSync(ws, { recursive: true, force: true }));
1180
+ const dir = join(ws, ".cursor", "hooks");
1181
+ mkdirSync(dir, { recursive: true });
1182
+ const statePath = join(dir, "state.json");
1183
+ const ledgerPath = join(dir, "denials.jsonl");
1184
+ const pointerPath = join(dir, "active.json");
1185
+ const scriptPath = join(dir, "hook.sh");
1186
+ // Break the baked Node path to force the grep/cut fallback for BOTH the
1187
+ // active-turn pointer parse and the tool identity extraction.
1188
+ const script = generateHookScript(pointerPath)
1189
+ .replace(`NODE_BIN="${process.execPath}"`, 'NODE_BIN="/nonexistent/node"');
1190
+ writeFileSync(scriptPath, script, "utf-8");
1191
+ writeFileSync(
1192
+ pointerPath,
1193
+ JSON.stringify({ stateFile: statePath, ledgerFile: ledgerPath, runnerPid: process.pid }),
1194
+ "utf-8",
1195
+ );
1196
+ writeFileSync(statePath, JSON.stringify(buildApprovalState(NO_MCP_DEFAULT, false, new Set())), "utf-8");
1197
+
1198
+ const raw = execFileSync("bash", [scriptPath], {
1199
+ input: JSON.stringify(hookWrite("/x/a.txt")),
1200
+ }).toString();
1201
+ expect(raw).toContain('"permission":"deny"');
1202
+ const ledger = readFileSync(ledgerPath, "utf-8").split("\n").filter(Boolean).map((l) => JSON.parse(l));
1203
+ expect(ledger).toHaveLength(1);
1204
+ expect(ledger[0].token).toBe(grantToken("write", "/x/a.txt"));
1205
+ // record_denial is pure bash, so the kind tag survives the Node outage too.
1206
+ expect(ledger[0].kind).toBe("approval");
1207
+ });
1208
+
1209
+ it("refuses every call when the agent has tool lists the hook cannot evaluate (Node unavailable)", () => {
1210
+ const ws = mkdtempSync(join(tmpdir(), "hook-script-fallback-"));
1211
+ onTestFinished(() => rmSync(ws, { recursive: true, force: true }));
1212
+ const dir = join(ws, ".cursor", "hooks");
1213
+ mkdirSync(dir, { recursive: true });
1214
+ const statePath = join(dir, "state.json");
1215
+ const ledgerPath = join(dir, "denials.jsonl");
1216
+ const pointerPath = join(dir, "active.json");
1217
+ const scriptPath = join(dir, "hook.sh");
1218
+ const script = generateHookScript(pointerPath)
1219
+ .replace(`NODE_BIN="${process.execPath}"`, 'NODE_BIN="/nonexistent/node"');
1220
+ writeFileSync(scriptPath, script, "utf-8");
1221
+ writeFileSync(
1222
+ pointerPath,
1223
+ JSON.stringify({ stateFile: statePath, ledgerFile: ledgerPath, runnerPid: process.pid }),
1224
+ "utf-8",
1225
+ );
1226
+ const toolScope = compileHookToolScope({
1227
+ scope: ToolScope.of('Agent "a"', { tools: ["Read"], disallowedTools: [] }),
1228
+ servers: [],
1229
+ listing: undefined,
1230
+ platformServerSlugs: new Set(),
1231
+ readRoot: "",
1232
+ subAgentTypes: [],
1233
+ });
1234
+ writeFileSync(
1235
+ statePath,
1236
+ JSON.stringify(buildApprovalState(NO_MCP_DEFAULT, true, new Set(), undefined, false, false, true, false, toolScope)),
1237
+ "utf-8",
1238
+ );
1239
+
1240
+ // Even a read, in scope, is refused: the hook cannot tell, and a list it
1241
+ // cannot read must not widen to every tool. autoApproveAll does not help.
1242
+ const raw = execFileSync("bash", [scriptPath], { input: JSON.stringify(hookRead("/x/a.txt")) }).toString();
1243
+ expect(raw).toContain('"permission":"deny"');
1244
+ const ledger = readFileSync(ledgerPath, "utf-8").split("\n").filter(Boolean).map((l) => JSON.parse(l));
1245
+ expect(ledger.map((e: { kind: string }) => e.kind)).toEqual(["fail-closed"]);
1246
+ });
1247
+ });
1248
+
1249
+ // The agent's hooks arm (1h) and the post arm (0b), reached through the
1250
+ // runner's hook server: a server that does not answer refuses the call (a
1251
+ // hook that cannot be asked is never skipped), a call after it ran adds
1252
+ // nothing then, and an MCP call's preToolUse firing passes on to its
1253
+ // beforeMCPExecution. The arms against a real server are the gateway
1254
+ // contract's hooks section on this substrate.
1255
+ d("generated approval hook: the agent's hooks", () => {
1256
+ const unreachable = { socketPath: join(tmpdir(), "stigmer-no-such-hooks.sock"), token: "t" };
1257
+
1258
+ it("refuses a call, recorded hook-unavailable, when the hook server does not answer", () => {
1259
+ const h = setup({ hookServer: unreachable });
1260
+ const res = h.decide({ ...hookShell("ls"), hook_event_name: "preToolUse" });
1261
+ expect(res.permission).toBe("deny");
1262
+ expect(res.raw).toContain("could not run this agent hooks");
1263
+ expect(h.ledger().map((e) => e.kind), "the gate worked; the hooks could not be asked").toEqual(["hook-unavailable"]);
1264
+ });
1265
+
1266
+ it("answers a call after it ran with nothing, at once, on a turn with no hook server", () => {
1267
+ const h = setup({});
1268
+ const after = { hook_event_name: "postToolUse", tool_name: "Shell", tool_input: { command: "ls" }, tool_output: "{}" };
1269
+ expect(h.decide(after).raw.trim()).toBe("{}");
1270
+ expect(h.ledger()).toEqual([]);
1271
+ rmSync(join(h.hitlDir, "active.json"), { force: true });
1272
+ expect(h.decide(after).raw.trim(), "with no turn at all, too").toBe("{}");
1273
+ });
1274
+
1275
+ it("lets an MCP call's preToolUse firing pass to the event that names its server", () => {
1276
+ const h = setup({ hookServer: unreachable });
1277
+ expect(h.decide(hookMcpPreToolUse("search")).permission).toBe("allow");
1278
+ expect(h.ledger()).toEqual([]);
1279
+ });
1280
+
1281
+ it("adds nothing after a call when no hook server answers, or when the agent has none", () => {
1282
+ const post = { hook_event_name: "postToolUse", tool_name: "Shell", tool_input: { command: "ls" } };
1283
+ expect(setup({ hookServer: unreachable }).decide(post).raw.trim()).toBe("{}");
1284
+ expect(setup().decide(post).raw.trim()).toBe("{}");
1285
+ });
1286
+
1287
+ it("generates a client that runs on the runner's Node and answers error or {} with no server", () => {
1288
+ const client = buildHookClientScript();
1289
+ expect(client).not.toContain("'");
1290
+ const run = (mode: string) =>
1291
+ execFileSync(process.execPath, ["-e", client, unreachable.socketPath, "t", mode, "", ""], { input: "{}" }).toString();
1292
+ expect(run("pre")).toBe("error");
1293
+ expect(run("post")).toBe("{}");
1294
+ });
1295
+ });
1296
+
1297
+ // A hook's answer meets capture and the secret block as the deny-gate's own
1298
+ // answers do: an ask that trust or a grant satisfies still has a CAS-owned
1299
+ // write staged for review; a secret-like write a hook asks on is blocked,
1300
+ // never shown on a card; a hook's allow of a git-tracked write in capture
1301
+ // mode flows to the turn's review; a staged write keeps the hook's context.
1302
+ d("generated approval hook: a hook's answer under capture and the secret block", () => {
1303
+ async function withHook(answer: object, opts: Parameters<typeof setup>[0], run: (h: ReturnType<typeof setup>) => Promise<void>): Promise<void> {
1304
+ const evaluator = new HookEvaluator({
1305
+ set: HookSet.of([{
1306
+ source: { plugin: "guard", root: "", data: "", options: new Map() },
1307
+ groups: [createMessage(HookGroupSchema, { event: "PreToolUse", matcher: "", handlers: [createMessage(HookHandlerSchema, { command: `printf '%s' '${JSON.stringify(answer)}'` })] })],
1308
+ }]),
1309
+ views: new CursorEngineToolViews({ workspaceRoot: "/", serverNames: new Map(), platformServerSlugs: new Set() }),
1310
+ sessionId: "s",
1311
+ workspaceRoot: tmpdir(),
1312
+ permissionMode: "default",
1313
+ baseEnv: buildShellEnv({}),
1314
+ homeDir: tmpdir(),
1315
+ leases: new Set(),
1316
+ });
1317
+ const server = await startHookServer({ evaluator, refusals: new Map(), captureMode: opts?.captureMode ?? false, globalBypass: opts?.autoApproveAll ?? false });
1318
+ try {
1319
+ await run(setup({ ...opts, hookServer: { socketPath: server.socketPath, token: server.token } }));
1320
+ } finally {
1321
+ await server.close();
1322
+ }
1323
+ }
1324
+ const ask = { hookSpecificOutput: { permissionDecision: "ask" } };
1325
+ const allowWithContext = { hookSpecificOutput: { permissionDecision: "allow", additionalContext: "logged" } };
1326
+
1327
+ it("stages a gitignored write a hook asked on under trust, as it stages one without hooks", async () => {
1328
+ await withHook(ask, { autoApproveAll: true, captureMode: true, captureIgnored: true, gitignored: ["*.log"] }, async (h) => {
1329
+ const res = await h.decideAsync({ ...hookWrite(join(h.root, "out.log"), "x"), hook_event_name: "preToolUse" });
1330
+ expect(res.permission).toBe("allow");
1331
+ expect((await h.observations()).captured, "staged for review").toHaveLength(1);
1332
+ });
1333
+ });
1334
+
1335
+ it("stages a gitignored write a hook asked on that a grant answers", async () => {
1336
+ await withHook(ask, { captureMode: true, captureIgnored: true, gitignored: ["*.log"] }, async (h) => {
1337
+ const file = join(h.root, "out.log");
1338
+ // The approval's grant, as the resumed turn writes it into the state.
1339
+ const statePath = join(h.hitlDir, "state.json");
1340
+ const state = JSON.parse(readFileSync(statePath, "utf-8")) as { approvedGrantTokens: string[] };
1341
+ state.approvedGrantTokens.push(primaryToken("write", file, contentDigest({ file_path: file, content: "x" })));
1342
+ writeFileSync(statePath, JSON.stringify(state), "utf-8");
1343
+ const res = await h.decideAsync({ ...hookWrite(file, "x"), hook_event_name: "preToolUse" });
1344
+ expect(res.permission).toBe("allow");
1345
+ expect((await h.observations()).captured, "staged for review").toHaveLength(1);
1346
+ });
1347
+ });
1348
+
1349
+ it("refuses a call a hook asks on and rewrites, though a grant holds for the call as written; under trust the rewrite runs", async () => {
1350
+ const root = mkdtempSync(join(tmpdir(), "ask-rewrite-"));
1351
+ onTestFinished(() => rmSync(root, { recursive: true, force: true }));
1352
+ const file = join(root, "a.txt");
1353
+ const askAndMove = { hookSpecificOutput: { permissionDecision: "ask", updatedInput: { file_path: join(root, "b.txt"), content: "x" } } };
1354
+ await withHook(askAndMove, {}, async (h) => {
1355
+ // The approval's grant for the call as the model wrote it.
1356
+ const statePath = join(h.hitlDir, "state.json");
1357
+ const state = JSON.parse(readFileSync(statePath, "utf-8")) as { approvedGrantTokens: string[] };
1358
+ state.approvedGrantTokens.push(primaryToken("write", file, contentDigest({ file_path: file, content: "x" })));
1359
+ writeFileSync(statePath, JSON.stringify(state), "utf-8");
1360
+ const res = await h.decideAsync({ ...hookWrite(file, "x"), hook_event_name: "preToolUse" });
1361
+ expect(res.permission).toBe("deny");
1362
+ expect(h.ledger().map((e) => [e.kind, Buffer.from(String(e.hook), "base64").toString("utf-8")]), "the ledger carries the hook in base64").toEqual([["hook", "guard"]]);
1363
+ });
1364
+ await withHook(askAndMove, { autoApproveAll: true }, async (h) => {
1365
+ const res = await h.decideAsync({ ...hookWrite(file, "x"), hook_event_name: "preToolUse" });
1366
+ expect(JSON.parse(res.raw.trim())).toEqual({ permission: "allow", updated_input: { file_path: join(root, "b.txt"), content: "x" } });
1367
+ });
1368
+ });
1369
+
1370
+ it("lets an approved MCP call a hook asked on through, and no other call to the same tool", async () => {
1371
+ // The grant the runner leaves for the approval of merging PR 1 (`boundary-rows.ts` approvalDigest).
1372
+ const grant = (digest: string) => ({ toolName: "merge", mcpServerSlug: "srv", key: "srv/merge", salient: "", contentDigest: digest, sourceToolCallId: "consent-1" });
1373
+ await withHook(ask, { grants: [grant(hookAskDigest({ pr: 1 }))] }, async (h) => {
1374
+ expect((await h.decideAsync(hookMcp("merge", { pr: 1 }))).permission).toBe("allow");
1375
+ expect((await h.decideAsync(hookMcp("merge", { pr: 2 }))).permission, "merging PR 2 needs its own approval").toBe("deny");
1376
+ expect(h.ledger().map((e) => e.kind)).toEqual(["approval"]);
1377
+ });
1378
+ await withHook(ask, { grants: [grant("")] }, async (h) => {
1379
+ expect((await h.decideAsync(hookMcp("merge", { pr: 1 }))).permission, "a grant for the tool alone answers no hook's ask").toBe("deny");
1380
+ });
1381
+ });
1382
+
1383
+ it("blocks a secret-like write a hook asks on, never showing it on a card", async () => {
1384
+ await withHook(ask, {}, async (h) => {
1385
+ const res = await h.decideAsync({ ...hookWrite(join(h.root, ".env"), "TOKEN=x"), hook_event_name: "preToolUse" });
1386
+ expect(res.permission).toBe("deny");
1387
+ expect(h.ledger().map((e) => e.kind)).toEqual(["secret"]);
1388
+ expect(h.ledger()[0]).not.toHaveProperty("input");
1389
+ });
1390
+ });
1391
+
1392
+ it("lets a git-tracked write a hook allows flow in capture mode, and blocks a secret-like one outside it", async () => {
1393
+ await withHook(allowWithContext, { captureMode: true, gitignored: [] }, async (h) => {
1394
+ expect((await h.decideAsync({ ...hookWrite(join(h.root, ".env"), "TOKEN=x"), hook_event_name: "preToolUse" })).permission).toBe("allow");
1395
+ });
1396
+ await withHook(allowWithContext, {}, async (h) => {
1397
+ expect((await h.decideAsync({ ...hookWrite(join(h.root, ".env"), "TOKEN=x"), hook_event_name: "preToolUse" })).permission).toBe("deny");
1398
+ expect(h.ledger().map((e) => e.kind)).toEqual(["secret"]);
1399
+ });
1400
+ });
1401
+
1402
+ it("keeps a hook's context on a write the capture arm staged", async () => {
1403
+ await withHook(allowWithContext, { captureMode: true, captureIgnored: true, gitignored: ["*.log"] }, async (h) => {
1404
+ const res = await h.decideAsync({ ...hookWrite(join(h.root, "out.log"), "x"), hook_event_name: "preToolUse" });
1405
+ expect(JSON.parse(res.raw.trim())).toEqual({ permission: "allow", additional_context: "Hook feedback:\nlogged" });
1406
+ });
1407
+ });
1408
+ });